diff --git a/.github/workflows/issue_comment.yml b/.github/workflows/issue_comment.yml new file mode 100644 index 000000000..b57db42a1 --- /dev/null +++ b/.github/workflows/issue_comment.yml @@ -0,0 +1,19 @@ +name: Sync issue comments to JIRA + +# This workflow will be triggered when new issue comment is created (including PR comments) +on: issue_comment + +jobs: + sync_issue_comments_to_jira: + name: Sync Issue Comments to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync issue comments to JIRA + uses: espressif/github-actions/sync_issues_to_jira@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: GIT8266O + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} diff --git a/.github/workflows/new_issues.yml b/.github/workflows/new_issues.yml new file mode 100644 index 000000000..5358cc820 --- /dev/null +++ b/.github/workflows/new_issues.yml @@ -0,0 +1,19 @@ +name: Sync issues to Jira + +# This workflow will be triggered when a new issue is opened +on: issues + +jobs: + sync_issues_to_jira: + name: Sync issues to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync GitHub issues to Jira project + uses: espressif/github-actions/sync_issues_to_jira@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: GIT8266O + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} diff --git a/.github/workflows/new_prs.yml b/.github/workflows/new_prs.yml new file mode 100644 index 000000000..3b540c3ba --- /dev/null +++ b/.github/workflows/new_prs.yml @@ -0,0 +1,24 @@ +name: Sync remain PRs to Jira + +# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project +# Note that, PRs can also get synced when new PR comment is created +on: + schedule: + - cron: "0 * * * *" + +jobs: + sync_prs_to_jira: + name: Sync PRs to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync PRs to Jira project + uses: espressif/github-actions/sync_issues_to_jira@master + with: + cron_job: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: GIT8266O + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} diff --git a/.gitignore b/.gitignore index 86e34e780..ac4dec2e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o +*.pyc # eclipse setting .settings @@ -17,3 +18,27 @@ examples/**/build tools/unit-test-app/sdkconfig tools/unit-test-app/sdkconfig.old tools/unit-test-app/build + +# Doc build artifacts +docs/*/_build/ +docs/*/doxygen-warning-log.txt +docs/*/sphinx-warning-log.txt +docs/*/sphinx-warning-log-sanitized.txt +docs/*/xml/ +docs/*/xml_in/ +docs/*/man/ +docs/doxygen_sqlite3.db + +# emacs +.dir-locals.el + +# emacs temp file suffixes +*~ +.#* +\#*# + +# eclipse setting +.settings + +# MacOS directory files +.DS_Store \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 068dfb7bc..ede03ce8f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,12 @@ variables: IDF_PATH: "$CI_PROJECT_DIR" + # Versioned esp-idf-doc env image to use for all document building jobs + ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v8" + + GIT_SUBMODULE_STRATEGY: recursive + ESPCI_TOKEN: $GITLAB_KEY + # before each job, we need to check if this job is filtered by bot stage/job filter .apply_bot_filter: &apply_bot_filter python $APPLY_BOT_FILTER_SCRIPT || exit 0 @@ -23,12 +29,14 @@ before_script: before_script: &do_nothing_before # apply bot filter in before script - *apply_bot_filter - - echo "Not setting up GitLab key, not fetching submodules" + - echo "Not setting up GitLab key, fetching submodules ..." + - git submodule update --init --recursive + - tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1 - source tools/ci/configure_ci_environment.sh .build_template: &build_template stage: build - image: $CI_DOCKER_REGISTRY/esp8266-ci-env$BOT_DOCKER_IMAGE_TAG + image: $CI_DOCKER_REGISTRY/esp8266-ci-env-new tags: - build @@ -39,10 +47,11 @@ build_ssc: - ./SSC/ssc_bin expire_in: 6 mos script: + - tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1 - git clone $GITLAB_SSH_SERVER/yinling/SSC.git - cd SSC # try checkout same branch - - git checkout "${CI_BUILD_REF_NAME}_8266" || echo "Using default branch..." + - git checkout "release/v3.4_8266" || echo "Using default branch..." - ./gen_misc_rtos.sh push_master_to_github: @@ -73,3 +82,127 @@ push_master_to_github: # (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch # and then pushes that ref to a corresponding github branch - eval $(git for-each-ref --shell bash --format 'if [ $CI_COMMIT_SHA == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS) + +build_docs: + stage: build + image: $ESP_IDF_DOC_ENV_IMAGE + tags: + - build_docs + artifacts: + when: always + paths: + # English version of documentation + - docs/en/doxygen-warning-log.txt + - docs/en/sphinx-warning-log.txt + - docs/en/sphinx-warning-log-sanitized.txt + - docs/en/_build/html + - docs/sphinx-err-* + expire_in: 1 day + only: + variables: + - $BOT_TRIGGER_WITH_LABEL == null + - $BOT_LABEL_BUILD + - $BOT_LABEL_BUILD_DOCS + - $BOT_LABEL_REGULAR_TEST + script: + - source /opt/pyenv/activate && pyenv global 3.6.10 + - /opt/pyenv/pyenv-1.2.16/versions/3.6.10/bin/python -m pip install --user -r $CI_PROJECT_DIR/docs/requirements.txt + - cd docs + - cd en + - make gh-linkcheck + - make html + - ../check_doc_warnings.sh + +.build_examples_make_template: &build_examples_make_template + <<: *build_template + # This is a workaround for a rarely encountered issue with building examples in CI. + # Probably related to building of Kconfig in 'make clean' stage + retry: 1 + artifacts: + when: always + paths: + - $LOG_PATH + - ./build_examples/example_builds/*/build/bootloader/*.bin + - ./build_examples/example_builds/*/build/partition_table/*.bin + - ./build_examples/example_builds/*/build/*.bin + - ./build_examples/example_builds/*/build/*.elf + - ./build_examples/example_builds/*/build/*.map + - ./build_examples/example_builds/*/build/*.config + expire_in: 2 days + variables: + LOG_PATH: "$CI_PROJECT_DIR/log_examples_make" + only: + variables: + - $BOT_TRIGGER_WITH_LABEL == null + - $BOT_LABEL_BUILD + - $BOT_LABEL_EXAMPLE_TEST + - $BOT_LABEL_REGULAR_TEST + before_script: *do_nothing_before + script: + # it's not possible to build 100% out-of-tree and have the "artifacts" + # mechanism work, but this is the next best thing + - rm -rf build_examples + - mkdir build_examples + - cd build_examples + # build some of examples + - mkdir -p ${LOG_PATH} + - ${IDF_PATH}/tools/ci/build_examples.sh "${CI_JOB_NAME}" + +# same as above, but for CMake +.build_examples_cmake_template: &build_examples_cmake_template + <<: *build_template + artifacts: + when: always + paths: + - $LOG_PATH + - ./build_examples_cmake/example_builds/*/build/bootloader/*.bin + - ./build_examples_cmake/example_builds/*/build/partition_table/*.bin + - ./build_examples_cmake/example_builds/*/build/*.bin + - ./build_examples_cmake/example_builds/*/build/*.elf + - ./build_examples_cmake/example_builds/*/build/*.map + - ./build_examples_cmake/example_builds/*/build/*.config + - ./build_examples_cmake/example_builds/*/build/flasher_args.json + - ./build_examples_cmake/example_builds/*/sdkconfig + expire_in: 2 days + variables: + LOG_PATH: "$CI_PROJECT_DIR/log_examples_cmake" + only: + variables: + - $BOT_TRIGGER_WITH_LABEL == null + - $BOT_LABEL_BUILD + - $BOT_LABEL_EXAMPLE_TEST + - $BOT_LABEL_REGULAR_TEST + before_script: *do_nothing_before + script: + # it's not possible to build 100% out-of-tree and have the "artifacts" + # mechanism work, but this is the next best thing + - rm -rf build_examples_cmake + - mkdir build_examples_cmake + - cd build_examples_cmake + # build some of examples + - mkdir -p ${LOG_PATH} + - ${IDF_PATH}/tools/ci/build_examples_cmake.sh "${CI_JOB_NAME}" + +build_examples_make_00: + <<: *build_examples_make_template + +build_examples_make_01: + <<: *build_examples_make_template + +build_examples_make_02: + <<: *build_examples_make_template + +build_examples_make_03: + <<: *build_examples_make_template + +build_examples_cmake_00: + <<: *build_examples_cmake_template + +build_examples_cmake_01: + <<: *build_examples_cmake_template + +build_examples_cmake_02: + <<: *build_examples_cmake_template + +build_examples_cmake_03: + <<: *build_examples_cmake_template diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..5051ce92e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,19 @@ +[submodule "components/json/cJSON"] + path = components/json/cJSON + url = ../../DaveGamble/cJSON.git + +[submodule "components/mbedtls/mbedtls"] + path = components/mbedtls/mbedtls + url = ../../espressif/mbedtls.git + +[submodule "components/lwip/lwip"] + path = components/lwip/lwip + url = ../../espressif/esp-lwip.git + +[submodule "components/mqtt/esp-mqtt"] + path = components/mqtt/esp-mqtt + url = ../../espressif/esp-mqtt.git + +[submodule "components/coap/libcoap"] + path = components/coap/libcoap + url = https://jihulab.com/esp-mirror/obgm/libcoap.git diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..3704e9469 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,27 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: "ubuntu-20.04" + tools: + python: "3.6" + +# Optionally build your docs in additional formats such as PDF and ePub +formats: + - htmlzip + - pdf + +# Optionally set the version of Python and requirements required to build your docs +python: + install: + - requirements: docs/setuptools.requirements.txt + - requirements: docs/requirements.txt + +# Specify the path for conf.py +sphinx: + configuration: docs/en/conf.py diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..1b4810648 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,82 @@ +cmake_minimum_required(VERSION 3.5) +project(esp-idf C CXX ASM) + +unset(compile_options) +unset(c_compile_options) +unset(cxx_compile_options) +unset(compile_definitions) + +# Add the following build specifications here, since these seem to be dependent +# on config values on the root Kconfig. + +if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE) + list(APPEND compile_options "-Os") +else() + list(APPEND compile_options "-Og") +endif() + +if(CONFIG_COMPILER_CXX_EXCEPTIONS) + list(APPEND cxx_compile_options "-fexceptions") +else() + list(APPEND cxx_compile_options "-fno-exceptions") +endif() + +if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS) + list(APPEND compile_options "-Wno-parentheses" + "-Wno-sizeof-pointer-memaccess" + "-Wno-clobbered") + + # doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before + if(GCC_NOT_5_2_0) + list(APPEND compile_options "-Wno-format-overflow" + "-Wno-stringop-truncation" + "-Wno-misleading-indentation" + "-Wno-cast-function-type" + "-Wno-implicit-fallthrough" + "-Wno-unused-const-variable" + "-Wno-switch-unreachable" + "-Wno-format-truncation" + "-Wno-memset-elt-size" + "-Wno-int-in-bool-context") + endif() +endif() + +if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE) + list(APPEND compile_definitions "-DNDEBUG") +endif() + +if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM) + list(APPEND compile_options "-fstack-protector") +elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG) + list(APPEND compile_options "-fstack-protector-strong") +elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL) + list(APPEND compile_options "-fstack-protector-all") +endif() + + +idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) +idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND) +idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND) +idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND) + +idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS) + +# Add each component as a subdirectory, processing each component's CMakeLists.txt +foreach(component_target ${build_component_targets}) + __component_get_property(dir ${component_target} COMPONENT_DIR) + __component_get_property(_name ${component_target} COMPONENT_NAME) + __component_get_property(prefix ${component_target} __PREFIX) + __component_get_property(alias ${component_target} COMPONENT_ALIAS) + set(COMPONENT_NAME ${_name}) + set(COMPONENT_DIR ${dir}) + set(COMPONENT_ALIAS ${alias}) + set(COMPONENT_PATH ${dir}) # for backward compatibility only, COMPONENT_DIR is preferred + idf_build_get_property(build_prefix __PREFIX) + set(__idf_component_context 1) + if(NOT prefix STREQUAL build_prefix) + add_subdirectory(${dir} ${prefix}_${_name}) + else() + add_subdirectory(${dir} ${_name}) + endif() + set(__idf_component_context 0) +endforeach() \ No newline at end of file diff --git a/Kconfig b/Kconfig index 90d710124..1673fa3f5 100644 --- a/Kconfig +++ b/Kconfig @@ -4,164 +4,197 @@ # mainmenu "Espressif IoT Development Framework Configuration" -choice TARGET_PLATFORM - bool "Espressif target platform choose" - default TARGET_PLATFORM_ESP8266 - help - Choose the specific target platform which you will use. - -config TARGET_PLATFORM_ESP32 - bool "esp32" -config TARGET_PLATFORM_ESP8266 - bool "esp8266" -endchoice - -menu "SDK tool configuration" -config TOOLPREFIX - string - default "xtensa-esp32-elf-" if TARGET_PLATFORM_ESP32 - default "xtensa-lx106-elf-" if TARGET_PLATFORM_ESP8266 - help - The prefix/path that is used to call the toolchain. The default setting assumes - a crosstool-ng gcc setup that is in your PATH. - -config PYTHON - string "Python 2 interpreter" - default "python" - help - The executable name/path that is used to run python. On some systems Python 2.x - may need to be invoked as python2. - -config MAKE_WARN_UNDEFINED_VARIABLES - bool "'make' warns on undefined variables" - default "y" - help - Adds --warn-undefined-variables to MAKEFLAGS. This causes make to - print a warning any time an undefined variable is referenced. - - This option helps find places where a variable reference is misspelled - or otherwise missing, but it can be unwanted if you have Makefiles which - depend on undefined variables expanding to an empty string. - -endmenu # SDK tool configuration - -source "$COMPONENT_KCONFIGS_PROJBUILD" - -menu "Compiler options" - -choice OPTIMIZATION_COMPILER - prompt "Optimization Level" - default OPTIMIZATION_LEVEL_DEBUG - help - This option sets compiler optimization level (gcc -O argument). - - - for "Release" setting, -Os flag is added to CFLAGS. - - for "Debug" setting, -Og flag is added to CFLAGS. - - "Release" with -Os produces smaller & faster compiled code but it - may be harder to correlated code addresses to source files when debugging. - - To add custom optimization settings, set CFLAGS and/or CPPFLAGS - in project makefile, before including $(IDF_PATH)/make/project.mk. Note that - custom optimization levels may be unsupported. - -config OPTIMIZATION_LEVEL_DEBUG - bool "Debug (-Og)" -config OPTIMIZATION_LEVEL_RELEASE - bool "Release (-Os)" -endchoice - -choice OPTIMIZATION_ASSERTION_LEVEL - prompt "Assertion level" - default OPTIMIZATION_ASSERTIONS_ENABLED - help - Assertions can be: - - Enabled. Failure will print verbose assertion details. This is the default. - - - Set to "silent" to save code size (failed assertions will abort() but user - needs to use the aborting address to find the line number with the failed assertion.) - - - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added - to CPPFLAGS in this case. - -config OPTIMIZATION_ASSERTIONS_ENABLED - prompt "Enabled" - bool - help - Enable assertions. Assertion content and line number will be printed on failure. - -config OPTIMIZATION_ASSERTIONS_SILENT - prompt "Silent (saves code size)" - bool - help - Enable silent assertions. Failed assertions will abort(), user needs to - use the aborting address to find the line number with the failed assertion. - -config OPTIMIZATION_ASSERTIONS_DISABLED - prompt "Disabled (sets -DNDEBUG)" - bool - help - If assertions are disabled, -DNDEBUG is added to CPPFLAGS. - -endchoice # assertions - -menuconfig CXX_EXCEPTIONS - bool "Enable C++ exceptions" - default n - help - Enabling this option compiles all IDF C++ files with exception support enabled. - - Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws - an exception will abort instead. - - Enabling this option currently adds an additional ~500 bytes of heap overhead - when an exception is thrown in user code for the first time. - -config CXX_EXCEPTIONS_EMG_POOL_SIZE - int "Emergency Pool Size" - default 0 - depends on CXX_EXCEPTIONS - help - Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate - memory for thrown exceptions when there is not enough memory on the heap. - -choice STACK_CHECK_MODE - prompt "Stack smashing protection mode" - default STACK_CHECK_NONE - help - Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack - smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. - The guards are initialized when a function is entered and then checked when the function exits. - If a guard check fails, program is halted. Protection has the following modes: - - In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with buffers larger than - 8 bytes are protected. - - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions to be protected -- those that - have local array definitions, or have references to local frame addresses. - - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected. - - Modes have the following impact on code performance and coverage: - - performance: NORMAL > STRONG > OVERALL - - coverage: NORMAL < STRONG < OVERALL - - -config STACK_CHECK_NONE - bool "None" -config STACK_CHECK_NORM - bool "Normal" -config STACK_CHECK_STRONG - bool "Strong" -config STACK_CHECK_ALL - bool "Overall" -endchoice - -config STACK_CHECK - bool - default !STACK_CHECK_NONE - help - Stack smashing protection. - -endmenu # Compiler Options - -menu "Component config" -source "$COMPONENT_KCONFIGS" -endmenu + # Hidden option to support checking for this specific target in C code and Kconfig files + config IDF_TARGET_ESP8266 + bool + default "y" if IDF_TARGET="esp8266" + default "n" + + config IDF_CMAKE + bool + option env="IDF_CMAKE" + + + config IDF_TARGET_ENV + # A proxy to get environment variable $IDF_TARGET + string + option env="IDF_TARGET" + + config IDF_TARGET + # This option records the IDF target when sdkconfig is generated the first time. + # It is not updated if environment variable $IDF_TARGET changes later, and + # the build system is responsible for detecting the mismatch between + # CONFIG_IDF_TARGET and $IDF_TARGET. + string + default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV="" + default IDF_TARGET_ENV + + + menu "SDK tool configuration" + config SDK_TOOLPREFIX + string "Compiler toolchain path/prefix" + default "xtensa-lx106-elf-" + help + The prefix/path that is used to call the toolchain. The default setting assumes + a crosstool-ng gcc setup that is in your PATH. + + config SDK_PYTHON + string "Python 2 interpreter" + depends on !IDF_CMAKE + default "python" + help + The executable name/path that is used to run python. On some systems Python 2.x + may need to be invoked as python2. + + (Note: This option is used with the legacy GNU Make build system only.) + + config SDK_MAKE_WARN_UNDEFINED_VARIABLES + bool "'make' warns on undefined variables" + depends on !IDF_CMAKE + default "n" + help + Adds --warn-undefined-variables to MAKEFLAGS. This causes make to + print a warning any time an undefined variable is referenced. + + This option helps find places where a variable reference is misspelled + or otherwise missing, but it can be unwanted if you have Makefiles which + depend on undefined variables expanding to an empty string. + + (Note: this option is used with the legacy GNU Make build system only.) + + endmenu # SDK tool configuration + + source "$COMPONENT_KCONFIGS_PROJBUILD" + + menu "Compiler options" + + choice COMPILER_OPTIMIZATION + prompt "Optimization Level" + default COMPILER_OPTIMIZATION_LEVEL_DEBUG + help + This option sets compiler optimization level (gcc -O argument). + + - for "Release" setting, -Os flag is added to CFLAGS. + - for "Debug" setting, -Og flag is added to CFLAGS. + + "Release" with -Os produces smaller & faster compiled code but it + may be harder to correlated code addresses to source files when debugging. + + To add custom optimization settings, set CFLAGS and/or CPPFLAGS + in project makefile, before including $(IDF_PATH)/make/project.mk. Note that + custom optimization levels may be unsupported. + + config COMPILER_OPTIMIZATION_LEVEL_DEBUG + bool "Debug (-Og)" + config COMPILER_OPTIMIZATION_LEVEL_RELEASE + bool "Release (-Os)" + endchoice + + choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL + prompt "Assertion level" + default COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE + help + Assertions can be: + + - Enabled. Failure will print verbose assertion details. This is the default. + + - Set to "silent" to save code size (failed assertions will abort() but user + needs to use the aborting address to find the line number with the failed assertion.) + + - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added + to CPPFLAGS in this case. + + config COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE + prompt "Enabled" + bool + help + Enable assertions. Assertion content and line number will be printed on failure. + + config COMPILER_OPTIMIZATION_ASSERTIONS_SILENT + prompt "Silent (saves code size)" + bool + help + Enable silent assertions. Failed assertions will abort(), user needs to + use the aborting address to find the line number with the failed assertion. + + config COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE + prompt "Disabled (sets -DNDEBUG)" + bool + help + If assertions are disabled, -DNDEBUG is added to CPPFLAGS. + + endchoice # assertions + + menuconfig COMPILER_CXX_EXCEPTIONS + bool "Enable C++ exceptions" + default n + help + Enabling this option compiles all IDF C++ files with exception support enabled. + + Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code + which throws an exception will abort instead. + + Enabling this option currently adds an additional ~500 bytes of heap overhead + when an exception is thrown in user code for the first time. + + choice COMPILER_STACK_CHECK_MODE + prompt "Stack smashing protection mode" + default COMPILER_STACK_CHECK_MODE_NONE + help + Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack + smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. + The guards are initialized when a function is entered and then checked when the function exits. + If a guard check fails, program is halted. Protection has the following modes: + + - In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with + buffers larger than 8 bytes are protected. + + - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions + to be protected -- those that have local array definitions, or have references to local frame + addresses. + + - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected. + + Modes have the following impact on code performance and coverage: + + - performance: NORMAL > STRONG > OVERALL + + - coverage: NORMAL < STRONG < OVERALL + + + config COMPILER_STACK_CHECK_MODE_NONE + bool "None" + config COMPILER_STACK_CHECK_MODE_NORM + bool "Normal" + config COMPILER_STACK_CHECK_MODE_STRONG + bool "Strong" + config COMPILER_STACK_CHECK_MODE_ALL + bool "Overall" + endchoice + + config COMPILER_STACK_CHECK + bool + default !COMPILER_STACK_CHECK_MODE_NONE + help + Stack smashing protection. + + config COMPILER_WARN_WRITE_STRINGS + bool "Enable -Wwrite-strings warning flag" + default "n" + help + Adds -Wwrite-strings flag for the C/C++ compilers. + + For C, this gives string constants the type ``const char[]`` so that + copying the address of one into a non-const ``char *`` pointer + produces a warning. This warning helps to find at compile time code + that tries to write into a string constant. + + For C++, this warns about the deprecated conversion from string + literals to ``char *``. + + + endmenu # Compiler Options + + menu "Component config" + source "$COMPONENT_KCONFIGS" + endmenu diff --git a/README.md b/README.md index 8532b6728..56b4d4c61 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +# ESP8266 RTOS Software Development Kit + +[![Documentation Status](https://readthedocs.com/projects/espressif-esp8266-rtos-sdk/badge/?version=latest)](https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/?badge=latest) + + # ** IMPORTANT NOTICE ** ## About this repository @@ -31,7 +36,14 @@ Actions to be taken for *ESP8266_RTOS_SDK v3.0* include the following items: ## Get toolchain -You can get toolchain from arduio firstly. +v8.4.0 + +* [Windows](https://dl.espressif.com/dl/xtensa-lx106-elf-gcc8_4_0-esp-2020r3-win32.zip) +* [Mac](https://dl.espressif.com/dl/xtensa-lx106-elf-gcc8_4_0-esp-2020r3-macos.tar.gz) +* [Linux(64)](https://dl.espressif.com/dl/xtensa-lx106-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz) +* [Linux(32)](https://dl.espressif.com/dl/xtensa-lx106-elf-gcc8_4_0-esp-2020r3-linux-i686.tar.gz) + +If you are still using old version SDK(< 3.0), please use toolchain v4.8.5, as following: * [Windows](https://dl.espressif.com/dl/xtensa-lx106-elf-win32-1.22.0-88-gde0bdc1-4.8.5.tar.gz) * [Mac](https://dl.espressif.com/dl/xtensa-lx106-elf-osx-1.22.0-88-gde0bdc1-4.8.5.tar.gz) @@ -59,7 +71,7 @@ export IDF_PATH=~/esp/ESP8266_RTOS_SDK ``` ## Start a Project -Now you are ready to prepare your application for ESP8266. To start off quickly, we can use `examples/get-started/project_template` project from `examples` directory in SDK. +Now you are ready to prepare your application for ESP8266. To start off quickly, we can use `examples/get-started/hello_world` project from `examples` directory in SDK. Once you've found the project you want to work with, change to its directory and you can configure and build it. @@ -69,10 +81,10 @@ You are almost there. To be able to proceed further, connect ESP8266 board to PC ## Configuring the Project -Being in terminal window, go to directory of `project_template` application by typing `cd ~/esp/ESP8266_RTOS_SDK/examples/get-started/project_template`. Then start project configuration utility `menuconfig`: +Being in terminal window, go to directory of `hello_world` application by typing `cd ~/esp/ESP8266_RTOS_SDK/examples/get-started/hello_world`. Then start project configuration utility `menuconfig`: ``` -cd ~/esp/ESP8266_RTOS_SDK/examples/get-started/project_template +cd ~/esp/ESP8266_RTOS_SDK/examples/get-started/hello_world make menuconfig ``` diff --git a/SUPPORT_POLICY_CN.md b/SUPPORT_POLICY_CN.md new file mode 100644 index 000000000..4dceb76ab --- /dev/null +++ b/SUPPORT_POLICY_CN.md @@ -0,0 +1,54 @@ +有关 ESP8266 RTOS SDK 的最新支持政策,详见 [支持期限政策](./SUPPORT_POLICY_CN.md)。 +支持期限政策 +================= + +* [English Version](./SUPPORT_POLICY_EN.md) + +ESP8266 RTOS SDK 的每个主要版本和次要版本(如 V3.0、V3.1 等)自其首次稳定版本发布之日起将维护 18 个月。 + +维护意味着 ESP8266 RTOS SDK 团队将会对 GitHub 上的发布分支继续进行 bug 修复、安全修补等,并根据需求定期发布新的 bugfix 版本。 + +在某一版本支持期限结束,停止更新维护 (EOL) 前,建议用户升级到较新的 ESP8266 RTOS SDK 版本。根据《支持期限政策》,我们将停止对 EOL 版本进行 bug 修复。 + +《支持期限政策》不适用于预发布版本(包括 beta、preview、`-rc` 和 `-dev` 版本等)。有时,在发布的版本中存在被标记为 "Preview" 的特定功能,则该功能也不在支持期限内。 + +长期支持版本 +------------ + +有些发布版本(例如 ESP8266 RTOS SDK V3.1)属于长期支持 (LTS) 版本。LTS 版本将自其首次稳定版本发布之日起维护 30 个月(2.5 年)。 + +关于长期维护版本,在 github 上面正式的`第1次`发布该版本 release 的时候,会在标题上额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +后续的维护版本不会再额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +示例 +----- + +ESP8266 RTOS SDK V3.1 于 2019 年 01 月发布,属于 LTS 版本,自正式发布日开始将维护 30 个月至 2021 年 07 月停止。 + +- V3.1 的首个发布版本为 2019 年 01 月发布的 `v3.1`。 +- ESP8266 RTOS SDK 团队将持续进行 bug 修复、安全修补等更新,并 backport 至分支 `release/v3.1`。 +- 定期从 release 分支创建稳定的 bugfix 版本,比如,`v3.1.1`、`v3.1.2` 等,并建议用户保持使用最新的 bugfix 版本。 +- V3.1 的 bugfix 版本发布将持续 30 个月至 2021 年 07 月,届时所有 V3.1.x 将停止更新维护。 + +现有版本 +-------- + +ESP8266 RTOS SDK V3.3 及所有后续更新版本都将遵守该《支持期限政策》。每一版本发布时将同时公布其支持期限。 + +对于该政策公布之日前发布的其他版本,应适用下述支持期限: + +- ESP8266 RTOS SDK V3.3.x 将维护至 2021 年 12 月。 +- ESP8266 RTOS SDK V3.2.x 将维护至 2020 年 12 月。 +- ESP8266 RTOS SDK V3.1.x 作为长期维护版本,将维护至 2021 年 7 月。 +- ESP8266 RTOS SDK V3.0.x 将维护至 2020 年 10 月。 +- ESP8266 RTOS SDK V2.1.x 作为长期维护版本,将维护至 2021 年 4 月。 +- ESP8266 RTOS SDK V2.0.x 及之前的版本均已停止更新维护 (EOL)。 \ No newline at end of file diff --git a/SUPPORT_POLICY_EN.md b/SUPPORT_POLICY_EN.md new file mode 100644 index 000000000..cb8c5533e --- /dev/null +++ b/SUPPORT_POLICY_EN.md @@ -0,0 +1,56 @@ +The latest support policy for ESP8266 RTOS SDK can be found at [Support Policy](./SUPPORT_POLICY_EN.md). + +Support Period Policy +================= + +* [中文版](./SUPPORT_POLICY_CN.md) + +Each ESP8266 RTOS SDK major and minor release (V3.0, V3.1, etc) is supported for 18 months after the initial stable release date. + +Supported means that the ESP8266 RTOS SDK team will continue to apply bug fixes, security fixes, etc to the release branch on GitHub, and periodically make new bugfix releases as needed. + +Users are encouraged to upgrade to a newer ESP8266 RTOS SDK release before the support period finishes and the release becomes End of Life (EOL). It is our policy to not continue fixing bugs in End of Life releases. + +Pre-release versions (betas, previews, -rc and -dev versions, etc) are not covered by any support period. Sometimes a particular feature is marked as "Preview" in a release, which means it is also not covered by the support period. + + +Long Term Support releases +------------ + +Some releases (for example, ESP8266 RTOS SDK V3.1) are designated Long Term Support (LTS). LTS releases are supported for 30 months (2.5 years) after the initial stable release date. + +We will add a `(LTS)` tag when we release a long term support version on GitHub at the first time. For example: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +But we will not add `(LTS)` tag to the following bug fix versions. For example: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +Example +----- + +ESP8266 RTOS SDK V3.1 was released in January 2019 and is a Long Term Support (LTS) release, meaning it will be supported for 30 months until July 2021. + +- The first V3.1 release was `v3.1` in January 2019. +- The ESP8266 RTOS SDK team continues to backport bug fixes, security fixes, etc to the release branch `release/v3.1`。 +- Periodically stable bugfix releases are created from the release branch. For example `v3.1.1`、`v3.1.2`, etc. Users are encouraged to always update to the latest bugfix release. +- V3.1 bugfix releases continue until July 2021, when all V3.1.x releases become End of Life. + +Existing Releases +-------- + +ESP8266 RTOS SDK V3.3 and all newer releases will follow this support period policy. The support period for each release will be announced when the release is made. + +For releases made before the support period policy was announced, the following support periods apply: + +- ESP8266 RTOS SDK V3.2.x will be supported until December 2021. +- ESP8266 RTOS SDK V3.2.x will be supported until December 2020. +- ESP8266 RTOS SDK V3.1.x is Long Term Support (LTS) release, will be supported until July 2021. +- ESP8266 RTOS SDK V3.0.x will be supported until October 2020. +- ESP8266 RTOS SDK V2.1.x is Long Term Support (LTS) release, will be supported until April 2021. +- ESP8266 RTOS SDK V2.0.x and earlier versions are already End of Life. diff --git a/add_path.sh b/add_path.sh new file mode 100755 index 000000000..f365c3f5c --- /dev/null +++ b/add_path.sh @@ -0,0 +1,19 @@ +# This shell snippet appends useful esp-idf tools to your PATH environment +# variable. This means you can run esp-idf tools without needing to give the +# full path. +# +# Use this script like this: +# +# . ${IDF_PATH}/add_path.sh +# +if [ -z ${IDF_PATH} ]; then + echo "IDF_PATH must be set before including this script." +else + IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool" + IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/" + IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/" + export PATH="${IDF_ADD_PATHS_EXTRAS}:${PATH}" + echo "Added to PATH: ${IDF_ADD_PATHS_EXTRAS}" +fi + + diff --git a/components/VERSION.md b/components/VERSION.md deleted file mode 100644 index 80c767307..000000000 --- a/components/VERSION.md +++ /dev/null @@ -1,33 +0,0 @@ -# Version of 3rd party components - -## axTLS - -## cJSON -- Source: https://github.com/DaveGamble/cJSON -- Version: 1.7.6 - -## freeRTOS -- Source: https://github.com/aws/amazon-freertos -- Version: 1.2.3(10.0.1) - -## Lwip -- Source: https://git.savannah.nongnu.org/git/lwip.git -- Version: 2.0.3 - -## mbedTLS -- Source: https://github.com/ARMmbed/mbedtls -- Version: 2.8.0 - -## nopoll(websocket) - -## paho MQTT -- Source: https://github.com/eclipse/paho.mqtt.embedded-c -- Version: 29ab2aa - -## spiffs - -## wolfSSL -- Source: https://github.com/wolfSSL/wolfssl -- Version: 3.14.0 - -> Espressif uses commercial version. \ No newline at end of file diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt new file mode 100644 index 000000000..7321db292 --- /dev/null +++ b/components/app_update/CMakeLists.txt @@ -0,0 +1,56 @@ +idf_component_register(SRCS "esp_ota_ops.c" "esp_app_desc.c" + INCLUDE_DIRS "include" + REQUIRES spi_flash partition_table bootloader_support) + +# esp_app_desc structure is added as an undefined symbol because otherwise the +# linker will ignore this structure as it has no other files depending on it. +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc") + +# cut PROJECT_VER and PROJECT_NAME to required 32 characters. +idf_build_get_property(project_ver PROJECT_VER) +idf_build_get_property(project_name PROJECT_NAME) +string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT) +string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT) + +set_source_files_properties( + SOURCE "esp_app_desc.c" "esp_app_desc.c" + PROPERTIES COMPILE_DEFINITIONS + "PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"") + +if(NOT BOOTLOADER_BUILD) + partition_table_get_partition_info(otadata_offset "--partition-type data --partition-subtype ota" "offset") + partition_table_get_partition_info(otadata_size "--partition-type data --partition-subtype ota" "size") + + # Add custom target for generating empty otadata partition for flashing + if(otadata_size AND otadata_offset) + idf_build_get_property(build_dir BUILD_DIR) + set(blank_otadata_file ${build_dir}/ota_data_initial.bin) + + idf_build_get_property(idf_path IDF_PATH) + idf_build_get_property(python PYTHON) + add_custom_command(OUTPUT ${blank_otadata_file} + COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py + ${otadata_size} ${blank_otadata_file}) + + add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file}) + add_dependencies(flash blank_ota_data) + + set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py) + + set(esptool_args --esptool-args before=${CONFIG_ESPTOOLPY_BEFORE} after=${CONFIG_ESPTOOLPY_AFTER}) + + add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}" + COMMAND ${otatool_py} ${esptool_args} + --partition-table-file ${PARTITION_CSV_PATH} + --partition-table-offset ${PARTITION_TABLE_OFFSET} + read_otadata) + + add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}" + COMMAND ${otatool_py} ${esptool_args} + --partition-table-file ${PARTITION_CSV_PATH} + --partition-table-offset ${PARTITION_TABLE_OFFSET} + erase_otadata) + + esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT) + endif() +endif() diff --git a/components/app_update/Kconfig b/components/app_update/Kconfig index 67643b9fd..aa9d138a1 100644 --- a/components/app_update/Kconfig +++ b/components/app_update/Kconfig @@ -12,4 +12,40 @@ config APP_UPDATE_CHECK_APP_HASH help If enable this option, app update will check the hash of app binary data after downloading it. + config APP_COMPILE_TIME_DATE + bool "Use time/date stamp for app" + default y + help + If set, then the app will be built with the current time/date stamp. It is stored in the app description + structure. If not set, time/date stamp will be excluded from app image. This can be useful for getting the + same binary image files made from the same source, but at different times. + + config APP_EXCLUDE_PROJECT_VER_VAR + bool "Exclude PROJECT_VER from firmware image" + default n + help + The PROJECT_VER variable from the build system will not affect the firmware image. + This value will not be contained in the esp_app_desc structure. + + config APP_EXCLUDE_PROJECT_NAME_VAR + bool "Exclude PROJECT_NAME from firmware image" + default n + help + The PROJECT_NAME variable from the build system will not affect the firmware image. + This value will not be contained in the esp_app_desc structure. + + config APP_PROJECT_VER_FROM_CONFIG + bool "Get the project version from Kconfig" + default n + help + If this is enabled, then config item APP_PROJECT_VER will be used for the variable PROJECT_VER. + Other ways to set PROJECT_VER will be ignored. + + config APP_PROJECT_VER + string "Project version" + default "1" + depends on APP_PROJECT_VER_FROM_CONFIG + help + Project version + endmenu diff --git a/components/app_update/Makefile.projbuild b/components/app_update/Makefile.projbuild index b47ee4ad7..4081aab97 100644 --- a/components/app_update/Makefile.projbuild +++ b/components/app_update/Makefile.projbuild @@ -1,8 +1,57 @@ +# Generate partition binary +# +.PHONY: blank_ota_data erase_otadata read_otadata -ifdef CONFIG_APP_UPDATE_CHECK_APP_SUM -CFLAGS += -DCONFIG_ENABLE_BOOT_CHECK_SUM=1 +OTATOOL_PY := $(PYTHON) $(COMPONENT_PATH)/otatool.py +PARTTOOL_PY := $(PYTHON) $(IDF_PATH)/components/partition_table/parttool.py + +# Generate blank partition file +BLANK_OTA_DATA_FILE = $(BUILD_DIR_BASE)/ota_data_initial.bin + +# Copy PARTITION_TABLE_CSV_PATH definition here from $IDF_PATH/components/partition_table/Makefile.projbuild +# to avoid undefined variables warning for PARTITION_TABLE_CSV_PATH +ifndef PARTITION_TABLE_CSV_PATH +PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(IDF_PATH)/components/partition_table)) +PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(call dequote,$(CONFIG_PARTITION_TABLE_FILENAME)))) endif -ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH -CFLAGS += -DCONFIG_ENABLE_BOOT_CHECK_SHA256=1 +$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies + $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \ + $(PYTHON) $(IDF_PATH)/components/partition_table/gen_empty_partition.py $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE); \ + fi; ) + $(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \ + echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) ) + +blank_ota_data: $(BLANK_OTA_DATA_FILE) + +# If there is no otadata partition, both OTA_DATA_OFFSET and BLANK_OTA_DATA_FILE +# expand to empty values. +ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE) + +ESPTOOL_ARGS := --esptool-args port=$(CONFIG_ESPTOOLPY_PORT) baud=$(CONFIG_ESPTOOLPY_BAUD) before=$(CONFIG_ESPTOOLPY_BEFORE) after=$(CONFIG_ESPTOOLPY_AFTER) + +erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies + $(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \ + --partition-table-offset $(PARTITION_TABLE_OFFSET) \ + erase_otadata + +read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies + $(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \ + --partition-table-offset $(partition_table_offset) \ + read_otadata + +erase_ota: erase_otadata + @echo "WARNING: erase_ota is deprecated. Use erase_otadata instead." + +all: blank_ota_data +flash: blank_ota_data +ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT +encrypted-flash: blank_ota_data endif + +TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt +export TMP_DEFINES + +clean: + rm -f $(BLANK_OTA_DATA_FILE) + rm -f $(TMP_DEFINES) diff --git a/components/app_update/component.mk b/components/app_update/component.mk index c2c4c03a1..14713393d 100755 --- a/components/app_update/component.mk +++ b/components/app_update/component.mk @@ -3,3 +3,52 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +COMPONENT_ADD_LDFLAGS += -u esp_app_desc + +ifndef IS_BOOTLOADER_BUILD + # If ``CONFIG_APP_PROJECT_VER_FROM_CONFIG`` option is set, the value of ``CONFIG_APP_PROJECT_VER`` will be used + # Else, if ``PROJECT_VER`` variable set in project Makefile file, its value will be used. + # Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. + # Else, if the project is located inside a Git repository, the output of git describe will be used. + # Otherwise, ``PROJECT_VER`` will be "1". + ifdef CONFIG_APP_PROJECT_VER_FROM_CONFIG + PROJECT_VER:= $(CONFIG_APP_PROJECT_VER) + else + ifneq ("${PROJECT_VER}", "") + PROJECT_VER:= $(PROJECT_VER) + else + ifneq ("$(wildcard ${PROJECT_PATH}/version.txt)","") + PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt) + else + GIT_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty 2> /dev/null) + ifeq ("${GIT_PROJECT_VER}", "") + PROJECT_VER := "1" + $(info Project is not inside a git repository, or git repository has no commits) + $(info will not use 'git describe' to determine PROJECT_VER.) + else + PROJECT_VER:= $(GIT_PROJECT_VER) + endif # a git repository + endif # version.txt + endif # PROJECT_VER + endif # CONFIG_APP_PROJECT_VER_FROM_CONFIG + + # cut PROJECT_VER and PROJECT_NAME to required 32 characters. + PROJECT_VER_CUT := $(shell echo "$(PROJECT_VER)" | cut -c 1-31) + PROJECT_NAME_CUT := $(shell echo "$(PROJECT_NAME)" | cut -c 1-31) + + $(info App "$(PROJECT_NAME_CUT)" version: $(PROJECT_VER_CUT)) + + NEW_DEFINES:= "$(PROJECT_VER_CUT) $(PROJECT_NAME_CUT) $(IDF_VER)" + ifeq ("$(wildcard ${TMP_DEFINES})","") + OLD_DEFINES:= "" + else + OLD_DEFINES:= "$(shell cat $(TMP_DEFINES))" + endif + + # If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc. + ifneq (${NEW_DEFINES}, ${OLD_DEFINES}) + $(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;) + endif + + esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\""$(PROJECT_VER_CUT)"\" -D PROJECT_NAME=\""$(PROJECT_NAME_CUT)"\" +endif # IS_BOOTLOADER_BUILD diff --git a/components/app_update/esp_app_desc.c b/components/app_update/esp_app_desc.c new file mode 100644 index 000000000..299ae3cad --- /dev/null +++ b/components/app_update/esp_app_desc.c @@ -0,0 +1,85 @@ +// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_ota_ops.h" +#include "esp_attr.h" +#include "sdkconfig.h" + +// Application version info +const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { + .magic_word = ESP_APP_DESC_MAGIC_WORD, +#ifdef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR + .version = "", +#else + .version = PROJECT_VER, +#endif + +#ifdef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR + .project_name = "", +#else + .project_name = PROJECT_NAME, +#endif + .idf_ver = IDF_VER, + +#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION + .secure_version = CONFIG_BOOTLOADER_APP_SECURE_VERSION, +#else + .secure_version = 0, +#endif + +#ifdef CONFIG_APP_COMPILE_TIME_DATE + .time = __TIME__, + .date = __DATE__, +#else + .time = "", + .date = "", +#endif +}; + + +#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR +_Static_assert(sizeof(PROJECT_VER) <= sizeof(esp_app_desc.version), "PROJECT_VER is longer than version field in structure"); +#endif +_Static_assert(sizeof(IDF_VER) <= sizeof(esp_app_desc.idf_ver), "IDF_VER is longer than idf_ver field in structure"); +#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR +_Static_assert(sizeof(PROJECT_NAME) <= sizeof(esp_app_desc.project_name), "PROJECT_NAME is longer than project_name field in structure"); +#endif + +const esp_app_desc_t *esp_ota_get_app_description(void) +{ + return &esp_app_desc; +} + +/* The following two functions may be called from the panic handler + * or core dump, hence IRAM_ATTR. + */ + +static inline char to_hex_digit(unsigned val) +{ + return (val < 10) ? ('0' + val) : ('a' + val - 10); +} + +int esp_ota_get_app_elf_sha256(char* dst, size_t size) +{ + size_t n = MIN((size - 1) / 2, sizeof(esp_app_desc.app_elf_sha256)); + const uint8_t* src = esp_app_desc.app_elf_sha256; + for (size_t i = 0; i < n; ++i) { + dst[2*i] = to_hex_digit(src[i] >> 4); + dst[2*i + 1] = to_hex_digit(src[i] & 0xf); + } + dst[2*n] = 0; + return 2*n + 1; +} diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 7dfc4c068..941d27bd4 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -31,10 +31,10 @@ #include "esp_ota_ops.h" #include "sys/queue.h" -#include "crc.h" +#include "rom/crc.h" #include "esp_log.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include "spi_flash.h" esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt); #endif @@ -69,6 +69,28 @@ static ota_select s_ota_select[2]; const static char *TAG = "esp_ota_ops"; +#ifndef CONFIG_ESP8266_BOOT_COPY_APP +static inline int esp_ota_verify_binary(const esp_partition_pos_t *pos, esp_image_header_t *image) +{ + const int32_t entry = image->entry_addr - 0x40200010; + + ESP_LOGD(TAG, "OTA binary start entry 0x%x, partition start from 0x%x to 0x%x\n", entry, pos->offset, + pos->offset + pos->size); + + if (pos->offset + pos->size <= 0x100000) { + if (entry <= 0 || entry <= pos->offset || entry >= pos->offset + pos->size) { + const char *doc_str = "<>"; + + ESP_LOGE(TAG, "**Important**: The OTA binary link data is error, " + "please refer to document %s for how to generate OTA binaries", doc_str); + return ESP_ERR_INVALID_ARG; + } + } + + return ESP_OK; +} +#endif + /* Return true if this is an OTA app partition */ static bool is_ota_partition(const esp_partition_t *p) { @@ -152,7 +174,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size) return ESP_ERR_OTA_VALIDATE_FAILED; } -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 if (esp_flash_encryption_enabled()) { /* Can only write 16 byte blocks to flash, so need to cache anything else */ size_t copy_len; @@ -244,6 +266,13 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle) goto cleanup; } +#ifndef CONFIG_ESP8266_BOOT_COPY_APP + if (esp_ota_verify_binary(&part_pos, &data.image) != ESP_OK) { + ret = ESP_ERR_OTA_VALIDATE_FAILED; + goto cleanup; + } +#endif + #ifdef CONFIG_SECURE_BOOT_ENABLED ret = esp_secure_boot_verify_signature(it->part->address, data.image_len); if (ret != ESP_OK) { @@ -325,7 +354,7 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype) if (SUB_TYPE_ID(subtype) >= ota_app_count) { return ESP_ERR_INVALID_ARG; } -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 const void *result = NULL; static spi_flash_mmap_memory_t ota_data_map; ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map); @@ -339,7 +368,7 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype) } #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 ret = spi_flash_read(find_partition->address, &s_ota_select[0], sizeof(ota_select)); if (ret != ESP_OK) { ESP_LOGE(TAG, "read failed"); @@ -473,7 +502,7 @@ const esp_partition_t *esp_ota_get_boot_partition(void) return NULL; } -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 const void *result = NULL; static spi_flash_mmap_memory_t ota_data_map; ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map); @@ -488,7 +517,7 @@ const esp_partition_t *esp_ota_get_boot_partition(void) #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 ret = spi_flash_read(find_partition->address, &s_ota_select[0], sizeof(ota_select)); if (ret != ESP_OK) { ESP_LOGE(TAG, "read failed"); @@ -539,13 +568,10 @@ const esp_partition_t* esp_ota_get_running_partition(void) /* Find the flash address of this exact function. By definition that is part of the currently running firmware. Then find the enclosing partition. */ -#ifdef CONFIG_TARGET_PLATFORM_ESP32 size_t phys_offs = spi_flash_cache2phys(esp_ota_get_running_partition); assert (phys_offs != SPI_FLASH_CACHE2PHYS_FAIL); /* indicates cache2phys lookup is buggy */ -#endif -#if CONFIG_TARGET_PLATFORM_ESP32 esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); @@ -561,9 +587,6 @@ const esp_partition_t* esp_ota_get_running_partition(void) } abort(); /* Partition table is invalid or corrupt */ -#else - return esp_ota_get_boot_partition(); -#endif } @@ -614,3 +637,25 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t * return default_ota; } + +esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc) +{ + if (partition == NULL || app_desc == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if(partition->type != ESP_PARTITION_TYPE_APP) { + return ESP_ERR_NOT_SUPPORTED; + } + + esp_err_t err = esp_partition_read(partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), app_desc, sizeof(esp_app_desc_t)); + if (err != ESP_OK) { + return err; + } + + if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) { + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index 3d1155c3c..dc9d10130 100755 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -21,6 +21,7 @@ #include "esp_err.h" #include "esp_partition.h" #include "esp_spi_flash.h" +#include "esp_app_format.h" #ifdef __cplusplus extern "C" @@ -174,6 +175,30 @@ const esp_partition_t* esp_ota_get_running_partition(void); */ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from); +/** + * @brief Return esp_app_desc structure. This structure includes app version. + * + * Return description for running app. + * @return Pointer to esp_app_desc structure. + */ +const esp_app_desc_t *esp_ota_get_app_description(void); + +/** + * @brief Returns esp_app_desc structure for app partition. This structure includes app version. + * + * Returns a description for the requested app partition. + * @param[in] partition Pointer to app partition. (only app partition) + * @param[out] app_desc Structure of info about app. + * @return + * - ESP_OK Successful. + * - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect. + * - ESP_ERR_NOT_SUPPORTED Partition is not application. + * - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size. + * - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition. + * - or one of error codes from lower-level flash driver. + */ +esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc); + #ifdef __cplusplus } #endif diff --git a/components/app_update/otatool.py b/components/app_update/otatool.py new file mode 100755 index 000000000..20f69fa92 --- /dev/null +++ b/components/app_update/otatool.py @@ -0,0 +1,388 @@ +#!/usr/bin/env python +# +# otatool is used to perform ota-level operations - flashing ota partition +# erasing ota partition and switching ota partition +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import print_function, division +import argparse +import os +import sys +import binascii +import tempfile +import collections +import struct + +try: + from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET +except ImportError: + COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components")) + PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, "partition_table") + + sys.path.append(PARTTOOL_DIR) + from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET + +__version__ = '2.0' + +SPI_FLASH_SEC_SIZE = 0x2000 + +quiet = False + + +def status(msg): + if not quiet: + print(msg) + + +class OtatoolTarget(): + + OTADATA_PARTITION = PartitionType("data", "ota") + + def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None, + spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[], + esptool_read_args=[], esptool_erase_args=[]): + self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args, + esptool_write_args, esptool_read_args, esptool_erase_args) + self.spi_flash_sec_size = spi_flash_sec_size + + temp_file = tempfile.NamedTemporaryFile(delete=False) + temp_file.close() + try: + self.target.read_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name) + with open(temp_file.name, "rb") as f: + self.otadata = f.read() + except Exception: + self.otadata = None + finally: + os.unlink(temp_file.name) + + def _check_otadata_partition(self): + if not self.otadata: + raise Exception("No otadata partition found") + + def erase_otadata(self): + self._check_otadata_partition() + self.target.erase_partition(OtatoolTarget.OTADATA_PARTITION) + + def _get_otadata_info(self): + info = [] + + otadata_info = collections.namedtuple("otadata_info", "seq crc") + + for i in range(2): + start = i * (self.spi_flash_sec_size >> 1) + + seq = bytearray(self.otadata[start:start + 4]) + crc = bytearray(self.otadata[start + 28:start + 32]) + + seq = struct.unpack('>I', seq) + crc = struct.unpack('>I', crc) + + info.append(otadata_info(seq[0], crc[0])) + + return info + + def _get_partition_id_from_ota_id(self, ota_id): + if isinstance(ota_id, int): + return PartitionType("app", "ota_" + str(ota_id)) + else: + return PartitionName(ota_id) + + def switch_ota_partition(self, ota_id): + self._check_otadata_partition() + + sys.path.append(PARTTOOL_DIR) + import gen_esp32part as gen + + def is_otadata_info_valid(status): + seq = status.seq % (1 << 32) + crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32)) + return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc + + partition_table = self.target.partition_table + + ota_partitions = list() + + for i in range(gen.NUM_PARTITION_SUBTYPE_APP_OTA): + ota_partition = filter(lambda p: p.subtype == (gen.MIN_PARTITION_SUBTYPE_APP_OTA + i), partition_table) + + try: + ota_partitions.append(list(ota_partition)[0]) + except IndexError: + break + + ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype) + + if not ota_partitions: + raise Exception("No ota app partitions found") + + # Look for the app partition to switch to + ota_partition_next = None + + try: + if isinstance(ota_id, int): + ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions) + else: + ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions) + + ota_partition_next = list(ota_partition_next)[0] + except IndexError: + raise Exception("Partition to switch to not found") + + otadata_info = self._get_otadata_info() + + # Find the copy to base the computation for ota sequence number on + otadata_compute_base = -1 + + # Both are valid, take the max as computation base + if is_otadata_info_valid(otadata_info[0]) and is_otadata_info_valid(otadata_info[1]): + if otadata_info[0].seq >= otadata_info[1].seq: + otadata_compute_base = 0 + else: + otadata_compute_base = 1 + # Only one copy is valid, use that + elif is_otadata_info_valid(otadata_info[0]): + otadata_compute_base = 0 + elif is_otadata_info_valid(otadata_info[1]): + otadata_compute_base = 1 + # Both are invalid (could be initial state - all 0xFF's) + else: + pass + + ota_seq_next = 0 + ota_partitions_num = len(ota_partitions) + + target_seq = (ota_partition_next.subtype & 0x0F) + 1 + + # Find the next ota sequence number + if otadata_compute_base == 0 or otadata_compute_base == 1: + base_seq = otadata_info[otadata_compute_base].seq % (1 << 32) + + i = 0 + while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num: + i += 1 + + ota_seq_next = target_seq % ota_partitions_num + i * ota_partitions_num + else: + ota_seq_next = target_seq + + # Create binary data from computed values + ota_seq_next = struct.pack("I", ota_seq_next) + ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32) + ota_seq_crc_next = struct.pack("I", ota_seq_crc_next) + + temp_file = tempfile.NamedTemporaryFile(delete=False) + temp_file.close() + + try: + with open(temp_file.name, "wb") as otadata_next_file: + start = (1 if otadata_compute_base == 0 else 0) * (self.spi_flash_sec_size >> 1) + + otadata_next_file.write(self.otadata) + + otadata_next_file.seek(start) + otadata_next_file.write(ota_seq_next) + + otadata_next_file.seek(start + 28) + otadata_next_file.write(ota_seq_crc_next) + + otadata_next_file.flush() + + self.target.write_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name) + finally: + os.unlink(temp_file.name) + + def read_ota_partition(self, ota_id, output): + self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output) + + def write_ota_partition(self, ota_id, input): + self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input) + + def erase_ota_partition(self, ota_id): + self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id)) + + +def _read_otadata(target): + target._check_otadata_partition() + + otadata_info = target._get_otadata_info() + + print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC")) + print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc, + otadata_info[1].seq, otadata_info[1].crc)) + + +def _erase_otadata(target): + target.erase_otadata() + status("Erased ota_data partition contents") + + +def _switch_ota_partition(target, ota_id): + target.switch_ota_partition(ota_id) + + +def _read_ota_partition(target, ota_id, output): + target.read_ota_partition(ota_id, output) + status("Read ota partition contents to file {}".format(output)) + + +def _write_ota_partition(target, ota_id, input): + target.write_ota_partition(ota_id, input) + status("Written contents of file {} to ota partition".format(input)) + + +def _erase_ota_partition(target, ota_id): + target.erase_ota_partition(ota_id) + status("Erased contents of ota partition") + + +def main(): + global quiet + + parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool") + + parser.add_argument("--quiet", "-q", help="suppress stderr messages", action="store_true") + parser.add_argument("--esptool-args", help="additional main arguments for esptool", nargs="+") + parser.add_argument("--esptool-write-args", help="additional subcommand arguments for esptool write_flash", nargs="+") + parser.add_argument("--esptool-read-args", help="additional subcommand arguments for esptool read_flash", nargs="+") + parser.add_argument("--esptool-erase-args", help="additional subcommand arguments for esptool erase_region", nargs="+") + + # There are two possible sources for the partition table: a device attached to the host + # or a partition table CSV/binary file. These sources are mutually exclusive. + parser.add_argument("--port", "-p", help="port where the device to read the partition table from is attached") + + parser.add_argument("--baud", "-b", help="baudrate to use", type=int) + + parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", type=str) + + parser.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from; \ + overrides device attached to specified port as the partition table source when defined") + + subparsers = parser.add_subparsers(dest="operation", help="run otatool -h for additional help") + + spi_flash_sec_size = argparse.ArgumentParser(add_help=False) + spi_flash_sec_size.add_argument("--spi-flash-sec-size", help="value of SPI_FLASH_SEC_SIZE macro", type=str) + + # Specify the supported operations + subparsers.add_parser("read_otadata", help="read otadata partition", parents=[spi_flash_sec_size]) + subparsers.add_parser("erase_otadata", help="erase otadata partition") + + slot_or_name_parser = argparse.ArgumentParser(add_help=False) + slot_or_name_parser_args = slot_or_name_parser.add_mutually_exclusive_group() + slot_or_name_parser_args.add_argument("--slot", help="slot number of the ota partition", type=int) + slot_or_name_parser_args.add_argument("--name", help="name of the ota partition") + + subparsers.add_parser("switch_ota_partition", help="switch otadata partition", parents=[slot_or_name_parser, spi_flash_sec_size]) + + read_ota_partition_subparser = subparsers.add_parser("read_ota_partition", help="read contents of an ota partition", parents=[slot_or_name_parser]) + read_ota_partition_subparser.add_argument("--output", help="file to write the contents of the ota partition to") + + write_ota_partition_subparser = subparsers.add_parser("write_ota_partition", help="write contents to an ota partition", parents=[slot_or_name_parser]) + write_ota_partition_subparser.add_argument("--input", help="file whose contents to write to the ota partition") + + subparsers.add_parser("erase_ota_partition", help="erase contents of an ota partition", parents=[slot_or_name_parser]) + + args = parser.parse_args() + + quiet = args.quiet + + # No operation specified, display help and exit + if args.operation is None: + if not quiet: + parser.print_help() + sys.exit(1) + + target_args = {} + + if args.port: + target_args["port"] = args.port + + if args.partition_table_file: + target_args["partition_table_file"] = args.partition_table_file + + if args.partition_table_offset: + target_args["partition_table_offset"] = int(args.partition_table_offset, 0) + + try: + if args.spi_flash_sec_size: + target_args["spi_flash_sec_size"] = int(args.spi_flash_sec_size, 0) + except AttributeError: + pass + + if args.esptool_args: + target_args["esptool_args"] = args.esptool_args + + if args.esptool_write_args: + target_args["esptool_write_args"] = args.esptool_write_args + + if args.esptool_read_args: + target_args["esptool_read_args"] = args.esptool_read_args + + if args.esptool_erase_args: + target_args["esptool_erase_args"] = args.esptool_erase_args + + if args.baud: + target_args["baud"] = args.baud + + target = OtatoolTarget(**target_args) + + # Create the operation table and execute the operation + common_args = {'target':target} + + ota_id = [] + + try: + if args.name is not None: + ota_id = ["name"] + else: + if args.slot is not None: + ota_id = ["slot"] + except AttributeError: + pass + + otatool_ops = { + 'read_otadata':(_read_otadata, []), + 'erase_otadata':(_erase_otadata, []), + 'switch_ota_partition':(_switch_ota_partition, ota_id), + 'read_ota_partition':(_read_ota_partition, ["output"] + ota_id), + 'write_ota_partition':(_write_ota_partition, ["input"] + ota_id), + 'erase_ota_partition':(_erase_ota_partition, ota_id) + } + + (op, op_args) = otatool_ops[args.operation] + + for op_arg in op_args: + common_args.update({op_arg:vars(args)[op_arg]}) + + try: + common_args['ota_id'] = common_args.pop('name') + except KeyError: + try: + common_args['ota_id'] = common_args.pop('slot') + except KeyError: + pass + + if quiet: + # If exceptions occur, suppress and exit quietly + try: + op(**common_args) + except Exception: + sys.exit(2) + else: + op(**common_args) + + +if __name__ == '__main__': + main() diff --git a/components/app_update/project_include.cmake b/components/app_update/project_include.cmake new file mode 100644 index 000000000..70b896f05 --- /dev/null +++ b/components/app_update/project_include.cmake @@ -0,0 +1,8 @@ + +# Set empty otadata partition file for flashing, if OTA data partition in +# partition table +# (NB: because of component dependency, we know partition_table +# project_include.cmake has already been included.) +if(${OTADATA_PARTITION_OFFSET}) + set(BLANK_OTADATA_FILE "ota_data_initial.bin") +endif() diff --git a/components/aws_iot/Kconfig b/components/aws_iot/Kconfig deleted file mode 100644 index 9144f1660..000000000 --- a/components/aws_iot/Kconfig +++ /dev/null @@ -1,159 +0,0 @@ -menuconfig AWS_IOT_SDK - bool "Amazon Web Services IoT Platform" - help - Select this option to enable support for the AWS IoT platform, - via the esp-idf component for the AWS IoT Device C SDK. - -config AWS_IOT_MQTT_HOST - string "AWS IoT Endpoint Hostname" - depends on AWS_IOT_SDK - default "" - help - Default endpoint host name to connect to AWS IoT MQTT/S gateway - - This is the custom endpoint hostname and is specific to an AWS - IoT account. You can find it by logging into your AWS IoT - Console and clicking the Settings button. The endpoint hostname - is shown under the "Custom Endpoint" heading on this page. - - If you need per-device hostnames for different regions or - accounts, you can override the default hostname in your app. - -config AWS_IOT_MQTT_PORT - int "AWS IoT MQTT Port" - depends on AWS_IOT_SDK - default 8883 - range 0 65535 - help - Default port number to connect to AWS IoT MQTT/S gateway - - If you need per-device port numbers for different regions, you can - override the default port number in your app. - - -config AWS_IOT_MQTT_TX_BUF_LEN - int "MQTT TX Buffer Length" - depends on AWS_IOT_SDK - default 512 - range 32 65536 - help - Maximum MQTT transmit buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be sent. - - Sending longer messages will fail. - -config AWS_IOT_MQTT_RX_BUF_LEN - int "MQTT RX Buffer Length" - depends on AWS_IOT_SDK - default 512 - range 32 65536 - help - Maximum MQTT receive buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be - received. - - Longer messages are dropped. - - - -config AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS - int "Maximum MQTT Topic Filters" - depends on AWS_IOT_SDK - default 5 - range 1 100 - help - Maximum number of concurrent MQTT topic filters. - - -config AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - int "Auto reconnect initial interval (ms)" - depends on AWS_IOT_SDK - default 1000 - range 10 3600000 - help - Initial delay before making first reconnect attempt, if the AWS IoT connection fails. - Client will perform exponential backoff, starting from this value. - -config AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - int "Auto reconnect maximum interval (ms)" - depends on AWS_IOT_SDK - default 128000 - range 10 3600000 - help - Maximum delay between reconnection attempts. If the exponentially increased delay - interval reaches this value, the client will stop automatically attempting to reconnect. - -menu "Thing Shadow" - depends on AWS_IOT_SDK - -config AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - bool "Override Shadow RX buffer size" - depends on AWS_IOT_SDK - default n - help - Allows setting a different Thing Shadow RX buffer - size. This is the maximum size of a Thing Shadow - message in bytes, plus one. - - If not overridden, the default value is the MQTT RX Buffer length plus one. If overriden, do not set higher than the default value. - -config AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER - int "Maximum RX Buffer (bytes)" - depends on AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - default 513 - range 32 65536 - help - Allows setting a different Thing Shadow RX buffer size. - This is the maximum size of a Thing Shadow message in bytes, - plus one. - - -config AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES - int "Maximum unique client ID size (bytes)" - depends on AWS_IOT_SDK - default 80 - range 4 1000 - help - Maximum size of the Unique Client Id. - -config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS - int "Maximum simultaneous responses" - depends on AWS_IOT_SDK - default 10 - range 1 100 - help - At any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested - -config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES - int "Maximum simultaneous Thing Name operations" - depends on AWS_IOT_SDK - default 10 - range 1 100 - help - We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time - -config AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED - int "Maximum expected JSON tokens" - depends on AWS_IOT_SDK - default 120 - help - These are the max tokens that is expected to be in the Shadow JSON document. Includes the metadata which is published - -config AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME - int "Maximum topic length (not including Thing Name)" - depends on AWS_IOT_SDK - default 60 - range 10 1000 - help - All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name - -config AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME - int "Maximum Thing Name length" - depends on AWS_IOT_SDK - default 20 - range 4 1000 - help - Maximum length of a Thing Name. - -endmenu # Thing Shadow - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md deleted file mode 100644 index c25809649..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md +++ /dev/null @@ -1,196 +0,0 @@ -# Change Log -## [2.2.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.1) (Dec 26, 2017) - -Bugfixes: - - - [#115](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/115) - Issue with new client metrics - -Pull requests: - - - [#112](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/112) - Initialize msqParams.isRetained to 0 in publishToShadowAction() - - [#118](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/118) - mqttInitParams.mqttPacketTimeout_ms initialized - -## [2.2.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.0) (Nov 22, 2017) - -New Features: - - - Added SDK metrics string into connect packet - -Bugfixes: - - - [#49](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/49) - Add support for SHADOW_JSON_STRING as supported value - - [#57](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/57) - remove unistd.h - - [#58](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/58) - Fix return type of aws_iot_mqtt_internal_is_topic_matched - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/95) - Fix extraneous assignment - - [#62](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/62) - Clearing SubscriptionList entries in shadowActionAcks after subscription failure - - [#63](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/63) - Stack overflow when IOT_DEBUG is enabled - - [#66](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/66) - Bug in send packet function - - [#69](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/69) - Fix for broken deleteActionHandler in shadow API - - [#71](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/71) - Prevent messages on /update/accepted from incrementing shadowJsonVersionNum in delta - - [#73](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/73) - wait for all messages to be received in subscribe publish sample - - [#96](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/96) - destroy TLS instance even if disconnect send fails - - Fix for aws_iot_mqtt_resubscribe not properly resubscribing to all topics - - Update MbedTLS Network layer Readme to remove specific version link - - Fix for not Passing througheError code on aws_iot_shadow_connect failure - - Allow sending of SHADOW_JSON_OBJECT to the shadow - - Ignore delta token callback for metadata - - Fix infinite publish exiting early in subscribe publish sample - -Improvements: - - - Updated jsmn to latest commit - - Change default keepalive interval to 600 seconds - -Pull requests: - - - [#29](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/29) - three small fixes - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/59) - Fixed MQTT header constructing and parsing - - [#88](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/88) - Fix username and password are confused - - [#78](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/78) - Fixed compilation warnings - - [#102](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/102) - Corrected markdown headers - - [#105](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/105) - Fixed warnings when compiling - -## [2.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.1) (Sep 5, 2016) - -Bugfixes/Improvements: - - - Network layer interface improvements to address reported issues - - Incorporated GitHub pull request [#41](https://github.com/aws/aws-iot-device-sdk-embedded-c/pull/41) - - Bugfixes for issues [#36](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/36) and [#33](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/33) - -## [2.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.0) (Jun 15, 2016) - -New features: - - - Added unit tests, further details can be found in the testing readme [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md) - - Added sample to demonstrate building the SDK as library - - Added sample to demonstrate building the SDK in C++ - -Bugfixes/Improvements: - - - Increased default value of Maximum Reconnect Wait interval to 128 secs - - Increased default value of MQTT Command Timeout in Shadow Connect to 20 secs - - Shadow null/length checks - - Client Id Length not passed correctly in shadow connect - - Add extern C to headers and source files, added sample to demonstrate usage with C++ - - Delete/Accepted not being reported, callback added for delete/accepted - - Append IOT_ to all Debug macros (eg. DEBUG is now IOT_DEBUG) - - Fixed exit on error for subscribe_publish_sample - -## [2.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.0.0) (April 28, 2016) - -New features: - - - Refactored API to make it instance specific. This is a breaking change in the API from 1.x releases because a Client Instance parameter had to be added to all APIs - - Added Threading library porting layer wrapper - - Added support for multiple connections from one application - - Shadows and connections de-linked, connection needs to be set up separately, can be used independently of shadow - - Added integration tests for testing SDK functionality - -Bugfixes/Improvements: - - - Yield cannot be called again while waiting for application callback to return - - Fixed issue with TLS layer handles not being cleaned up properly on connection failure reported [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/16) - - Renamed timer_linux.h to timer_platform.h as requested [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/5) - - Adds support for disconnect handler to shadow. A similar pull request can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/9) - - New SDK folder structure, cleaned and simplified code structure - - Removed Paho Wrapper, Merge MQTT into SDK code, added specific error codes - - Refactored Network and Timer layer wrappers, added specific error codes - - Refactored samples and makefiles - -## [1.1.2](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.2) (April 22, 2016) - -Bugfixes/Improvements: - - - Signature mismatch in MQTT library file fixed - - Makefiles have a protective target on the top to prevent accidental execution - -## [1.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.1) (April 1, 2016) - -Bugfixes/Improvements: - - - Removing the Executable bit from all the files in the repository. Fixing [this](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/14) issue - - Refactoring MQTT client to remove declaration after statement warnings - - Fixing [this](https://forums.aws.amazon.com/thread.jspa?threadID=222467&tstart=0) bug - - -## [1.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.0) (February 10, 2016) -Features: - - - Auto Reconnect and Resubscribe - -Bugfixes/Improvements: - - - MQTT buffer handling incase of bigger message - - Large timeout values converted to seconds and milliseconds - - Dynamic loading of Shadow parameters. Client ID and Thing Name are not hard-coded - - MQTT Library refactored - - -## [1.0.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.1) (October 21, 2015) - -Bugfixes/Improvements: - - - Paho name changed to Eclipse Paho - - Renamed the Makefiles in the samples directory - - Device Shadow - Delete functionality macro fixed - - `subscribe_publish_sample` updated - -## [1.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.0) (October 8, 2015) - -Features: - - - Release to github - - SDK tarballs made available for public download - -Bugfixes/Improvements: - - Updated API documentation - -## 0.4.0 (October 5, 2015) - -Features: - - - Thing Shadow Actions - Update, Delete, Get for any Thing Name - - aws_iot_config.h file for easy configuration of parameters - - Sample app for talking with console's Interactive guide - - disconnect handler for the MQTT client library - -Bugfixes/Improvements: - - - mbedTLS read times out every 10 ms instead of hanging for ever - - mbedTLS handshake failure handled - -## 0.3.0 (September 14, 2015) - -Features: - - - Testing with mbedTLS, prepping for relase - -Bugfixes/Improvements: - - - Refactored to break out timer and network interfaces - -## 0.2.0 (September 2, 2015) - -Features: - - - Added initial Shadow implementation + example - - Added hostname verification to OpenSSL example - - Added iot_log interface - - Initial API Docs (Doxygen) - -Bugfixes/Improvements: - - - Fixed yield timeout - - Refactored APIs to pass by reference vs value - -## 0.1.0 (August 12, 2015) - -Features: - - - Initial beta release - - MQTT Publish and Subscribe - - TLS mutual auth on linux with OpenSSL - -Bugfixes/Improvements: - - N/A diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk b/components/aws_iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk deleted file mode 100644 index 9f3c3054f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk +++ /dev/null @@ -1,575 +0,0 @@ -#--------- -# -# MakefileWorker.mk -# -# Include this helper file in your makefile -# It makes -# A static library -# A test executable -# -# See this example for parameter settings -# examples/Makefile -# -#---------- -# Inputs - these variables describe what to build -# -# INCLUDE_DIRS - Directories used to search for include files. -# This generates a -I for each directory -# SRC_DIRS - Directories containing source file to built into the library -# SRC_FILES - Specific source files to build into library. Helpful when not all code -# in a directory can be built for test (hopefully a temporary situation) -# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# TEST_SRC_FILES - Specific source files to build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner -# These do not go in a library. They are explicitly included in the test runner -#---------- -# You can adjust these variables to influence how to build the test target -# and where to put and name outputs -# See below to determine defaults -# COMPONENT_NAME - the name of the thing being built -# TEST_TARGET - name the test executable. By default it is -# $(COMPONENT_NAME)_tests -# Helpful if you want 1 > make files in the same directory with different -# executables as output. -# CPPUTEST_HOME - where CppUTest home dir found -# TARGET_PLATFORM - Influences how the outputs are generated by modifying the -# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the -# normal objs and lib directories. Also modifies where to search for the -# CPPUTEST_LIB to link against. -# CPPUTEST_OBJS_DIR - a directory where o and d files go -# CPPUTEST_LIB_DIR - a directory where libs go -# CPPUTEST_ENABLE_DEBUG - build for debug -# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete -# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out -# of the test harness -# CPPUTEST_USE_GCOV - Turn on coverage analysis -# Clean then build with this flag set to Y, then 'make gcov' -# CPPUTEST_MAPFILE - generate a map file -# CPPUTEST_WARNINGFLAGS - overly picky by default -# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make -# other targets. Like CSlim, which is part of fitnesse -# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user -# specification of source files and directories that aren't below -# the user's Makefile in the directory tree, like: -# SRC_DIRS += ../../lib/foo -# It defaults to N, and shouldn't be necessary except in the above case. -#---------- -# -# Other flags users can initialize to sneak in their settings -# CPPUTEST_CXXFLAGS - flags for the C++ compiler -# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor -# CPPUTEST_CFLAGS - flags for the C complier -# CPPUTEST_LDFLAGS - Linker flags -#---------- - -# Some behavior is weird on some platforms. Need to discover the platform. - -# Platforms -UNAME_OUTPUT = "$(shell uname -a)" -MACOSX_STR = Darwin -MINGW_STR = MINGW -CYGWIN_STR = CYGWIN -LINUX_STR = Linux -SUNOS_STR = SunOS -UNKNWOWN_OS_STR = Unknown - -# Compilers -CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" -CLANG_STR = clang -SUNSTUDIO_CXX_STR = SunStudio - -UNAME_OS = $(UNKNWOWN_OS_STR) - -ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) - UNAME_OS = $(MINGW_STR) -endif - -ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) - UNAME_OS = $(CYGWIN_STR) -endif - -ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) - UNAME_OS = $(LINUX_STR) -endif - -ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) - UNAME_OS = $(MACOSX_STR) -#lion has a problem with the 'v' part of -a - UNAME_OUTPUT = "$(shell uname -pmnrs)" -endif - -ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) - UNAME_OS = $(SUNOS_STR) - - SUNSTUDIO_CXX_ERR_STR = CC -flags -ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) - CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" - COMPILER_NAME = $(SUNSTUDIO_CXX_STR) -endif -endif - -ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) - COMPILER_NAME = $(CLANG_STR) -endif - -#Kludge for mingw, it does not have cc.exe, but gcc.exe will do -ifeq ($(UNAME_OS),$(MINGW_STR)) - CC := gcc -endif -# RHEL5 is always going to use GCC, CC is going for the old verison -CC := gcc -#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the -# Standard C++ library as a shared library. Unbelievable. -ifeq ($(UNAME_OS),$(MINGW_STR)) - CPPUTEST_LDFLAGS += -static -endif -ifeq ($(UNAME_OS),$(CYGWIN_STR)) - CPPUTEST_LDFLAGS += -static -endif - - -#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic -ifeq ($(UNAME_OS),$(MACOSX_STR)) -ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) - CPPUTEST_PEDANTIC_ERRORS = N -endif -endif - -ifndef COMPONENT_NAME - COMPONENT_NAME = name_this_in_the_makefile -endif - -# Debug on by default -ifndef CPPUTEST_ENABLE_DEBUG - CPPUTEST_ENABLE_DEBUG = Y -endif - -# new and delete for memory leak detection on by default -ifndef CPPUTEST_USE_MEM_LEAK_DETECTION - CPPUTEST_USE_MEM_LEAK_DETECTION = Y -endif - -# Use the standard C library -ifndef CPPUTEST_USE_STD_C_LIB - CPPUTEST_USE_STD_C_LIB = Y -endif - -# Use the standard C++ library -ifndef CPPUTEST_USE_STD_CPP_LIB - CPPUTEST_USE_STD_CPP_LIB = Y -endif - -# Use gcov, off by default -ifndef CPPUTEST_USE_GCOV - CPPUTEST_USE_GCOV = N -endif - -ifndef CPPUTEST_PEDANTIC_ERRORS - CPPUTEST_PEDANTIC_ERRORS = Y -endif - -# Default warnings -ifndef CPPUTEST_WARNINGFLAGS - CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wswitch-default -Wswitch-enum -Wconversion -ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) - CPPUTEST_WARNINGFLAGS += -pedantic-errors -endif -ifeq ($(UNAME_OS),$(LINUX_STR)) -# CPPUTEST_WARNINGFLAGS += -Wsign-conversion -endif - CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual - CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes -endif - -#Wonderful extra compiler warnings with clang -ifeq ($(COMPILER_NAME),$(CLANG_STR)) -# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. -# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) -# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor -# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. - CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables - CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded -endif - -# Uhm. Maybe put some warning flags for SunStudio here? -ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) - CPPUTEST_CXX_WARNINGFLAGS = - CPPUTEST_C_WARNINGFLAGS = -endif - -# Default dir for temporary files (d, o) -ifndef CPPUTEST_OBJS_DIR -ifndef TARGET_PLATFORM - CPPUTEST_OBJS_DIR = objs -else - CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) -endif -endif - -# Default dir for the output library -ifndef CPPUTEST_LIB_DIR -ifndef TARGET_PLATFORM - CPPUTEST_LIB_DIR = testLibs -else - CPPUTEST_LIB_DIR = testLibs/$(TARGET_PLATFORM) -endif -endif - -# No map by default -ifndef CPPUTEST_MAP_FILE - CPPUTEST_MAP_FILE = N -endif - -# No extentions is default -ifndef CPPUTEST_USE_EXTENSIONS - CPPUTEST_USE_EXTENSIONS = N -endif - -# No VPATH is default -ifndef CPPUTEST_USE_VPATH - CPPUTEST_USE_VPATH := N -endif -# Make empty, instead of 'N', for usage in $(if ) conditionals -ifneq ($(CPPUTEST_USE_VPATH), Y) - CPPUTEST_USE_VPATH := -endif - -ifndef TARGET_PLATFORM -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB) -else -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB)/$(TARGET_PLATFORM) -endif - -# -------------------------------------- -# derived flags in the following area -# -------------------------------------- - -# Without the C library, we'll need to disable the C++ library and ... -ifeq ($(CPPUTEST_USE_STD_C_LIB), N) - CPPUTEST_USE_STD_CPP_LIB = N - CPPUTEST_USE_MEM_LEAK_DETECTION = N - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED - CPPUTEST_CPPFLAGS += -nostdinc -endif - -CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION - -ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED -else - ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorNewMacros.h - endif - ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorMallocMacros.h - endif -endif - -ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) - CPPUTEST_CXXFLAGS += -g - CPPUTEST_CFLAGS += -g - CPPUTEST_LDFLAGS += -g -endif - -ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED -ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) - CPPUTEST_CXXFLAGS += -nostdinc++ -endif -endif - -ifdef $(GMOCK_HOME) - GTEST_HOME = $(GMOCK_HOME)/gtest - CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include - GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a - LD_LIBRARIES += $(GMOCK_LIBRARY) - CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS - CPPUTEST_WARNINGFLAGS = - CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) - GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a - LD_LIBRARIES += $(GTEST_LIBRARY) -endif - - -ifeq ($(CPPUTEST_USE_GCOV), Y) - CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage - CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage -endif - -CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) -CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) -CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) -CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) -CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) - -TARGET_MAP = $(COMPONENT_NAME).map.txt -ifeq ($(CPPUTEST_MAP_FILE), Y) - CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) -endif - -# Link with CppUTest lib -CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a - -ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) -CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a -endif - -ifdef CPPUTEST_STATIC_REALTIME - LD_LIBRARIES += -lrt -endif - -TARGET_LIB = \ - $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a - -ifndef TEST_TARGET - ifndef TARGET_PLATFORM - TEST_TARGET = $(COMPONENT_NAME)_tests - else - TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests - endif -endif - -#Helper Functions -get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) -get_dirs_from_dirspec = $(wildcard $1) -get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) -__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) -src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) -src_to_o = $(call src_to,.o,$1) -src_to_d = $(call src_to,.d,$1) -src_to_gcda = $(call src_to,.gcda,$1) -src_to_gcno = $(call src_to,.gcno,$1) -time = $(shell date +%s) -delta_t = $(eval minus, $1, $2) -debug_print_list = $(foreach word,$1,echo " $(word)";) echo; - -#Derived -STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) - -SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) -OBJ = $(call src_to_o,$(SRC)) - -STUFF_TO_CLEAN += $(OBJ) - -TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) -TEST_OBJS = $(call src_to_o,$(TEST_SRC)) -STUFF_TO_CLEAN += $(TEST_OBJS) - - -MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) -MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) -STUFF_TO_CLEAN += $(MOCKS_OBJS) - -ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) - -# If we're using VPATH -ifeq ($(CPPUTEST_USE_VPATH), Y) -# gather all the source directories and add them - VPATH += $(sort $(dir $(ALL_SRC))) -# Add the component name to the objs dir path, to differentiate between same-name objects - CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) -endif - -#LCOV html generation -BUILD_OUTPUT_DIR=build_output -COVERAGE_DIR=$(BUILD_OUTPUT_DIR)/generated-coverage -LCOV_INFO_FILE=$(TEST_TARGET).info -LCOV_SUMMARY_FILE=$(TEST_TARGET)_summary.info - -#Test coverage with gcov -GCOV_OUTPUT = gcov_output.txt -GCOV_REPORT = gcov_report.txt -GCOV_ERROR = gcov_error.txt -GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) -GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) -TEST_OUTPUT = $(TEST_TARGET).txt -STUFF_TO_CLEAN += \ - $(GCOV_OUTPUT)\ - $(GCOV_REPORT)\ - $(GCOV_REPORT).html\ - $(GCOV_ERROR)\ - $(GCOV_GCDA_FILES)\ - $(GCOV_GCNO_FILES)\ - $(TEST_OUTPUT) - -#The gcda files for gcov need to be deleted before each run -#To avoid annoying messages. -GCOV_CLEAN = $(SILENCE)$(RM) -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) -RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) - -ifeq ($(CPPUTEST_USE_GCOV), Y) - - ifeq ($(COMPILER_NAME),$(CLANG_STR)) - LD_LIBRARIES += --coverage - else - LD_LIBRARIES += -lgcov - endif -endif - - -INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) -INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) -MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) -INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) - -CPPUTEST_CPPFLAGS += $(INCLUDES) - -DEP_FILES = $(call src_to_d, $(ALL_SRC)) -STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) -STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output - -# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags -CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) -CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) -CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) -LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) - -# Don't consider creating the archive a warning condition that does STDERR output -ARFLAGS := $(ARFLAGS)c - -DEP_FLAGS=-MMD -MP - -# Some macros for programs to be overridden. For some reason, these are not in Make defaults -RANLIB = ranlib - -# Targets - -ALL_TARGETS += cpputest_all -ALL_TARGETS_CLEAN += cpputest_clean -.PHONY: cpputest_all -cpputest_all: start $(TEST_TARGET) gcov - $(RUN_TEST_TARGET) - -.PHONY: start -start: $(TEST_TARGET) - $(SILENCE)START_TIME=$(call time) - -.PHONY: all_no_tests -all_no_tests: $(TEST_TARGET) - -.PHONY: flags -flags: - @echo - @echo "OS ${UNAME_OS}" - @echo "Compile C and C++ source with CPPFLAGS:" - @$(call debug_print_list,$(CPPFLAGS)) - @echo "Compile C++ source with CXXFLAGS:" - @$(call debug_print_list,$(CXXFLAGS)) - @echo "Compile C source with CFLAGS:" - @$(call debug_print_list,$(CFLAGS)) - @echo "Link with LDFLAGS:" - @$(call debug_print_list,$(LDFLAGS)) - @echo "Link with LD_LIBRARIES:" - @$(call debug_print_list,$(LD_LIBRARIES)) - @echo "Create libraries with ARFLAGS:" - @$(call debug_print_list,$(ARFLAGS)) - -TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) -test-deps: $(TEST_DEPS) - -$(TEST_TARGET): $(TEST_DEPS) - @echo Linking $@ - $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) - -$(TARGET_LIB): $(OBJ) - @echo Building archive $@ - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(AR) $(ARFLAGS) $@ $^ - $(SILENCE)$(RANLIB) $@ - -test: $(TEST_TARGET) - $(RUN_TEST_TARGET) $(COMMAND_LINE_ARGUMENTS) | tee $(TEST_OUTPUT) -vtest: $(TEST_TARGET) - $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) - -$(CPPUTEST_OBJS_DIR)/%.o: %.cc - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.cpp - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.c - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -ifneq "$(MAKECMDGOALS)" "clean" --include $(DEP_FILES) -endif - -.PHONY: cpputest_clean -cpputest_clean: - @echo Making clean - $(SILENCE)$(RM) $(STUFF_TO_CLEAN) - $(SILENCE)$(RM) -rf gcov $(CPPUTEST_OBJS_DIR) - $(SILENCE)find . -name "*.gcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.gcda" | xargs $(RM) -f - -#realclean gets rid of all gcov, o and d files in the directory tree -#not just the ones made by this makefile -.PHONY: realclean -realclean: clean - $(SILENCE)$(RM) -rf gcov - $(SILENCE)$(RM) -rf $(BUILD_OUTPUT_DIR) - $(SILENCE)find . -name "*.gdcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.[do]" | xargs $(RM) -f - -gcov: test - $(SILENCE)mkdir -p $(BUILD_OUTPUT_DIR) -ifeq ($(CPPUTEST_USE_VPATH), Y) - $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) -else - $(SILENCE)for d in $(SRC_DIRS) ; do \ - FILES=`ls $$d/*.c $$d/*.cc $$d/*.cpp 2> /dev/null` ; \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$FILES >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done - $(SILENCE)for f in $(SRC_FILES) ; do \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done -endif - $(SILENCE)./filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) - $(SILENCE)mkdir -p gcov - $(SILENCE)mv *.gcov gcov - $(SILENCE)mv gcov_* gcov - $(SILENCE)mkdir -p $(COVERAGE_DIR) - $(SILENCE)lcov -d $(CPPUTEST_OBJS_DIR) -c -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) $(LCOV_EXCLUDE_PATTERN) -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) "*CppUTest*" -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --summary ./$(COVERAGE_DIR)/$(LCOV_INFO_FILE) &> $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) - $(SILENCE)echo ansic:line:`grep -E -o "([0-9]*\.[0-9]+|[0-9]+)" $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) | head -1` >> $(COVERAGE_DIR)/coverage-data.txt - $(SILENCE)genhtml -o $(COVERAGE_DIR) $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - @echo "See gcov directory for details" - -.PHONEY: format -format: - $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) - -.PHONEY: debug -debug: - @echo - @echo "Target Source files:" - @$(call debug_print_list,$(SRC)) - @echo "Target Object files:" - @$(call debug_print_list,$(OBJ)) - @echo "Test Source files:" - @$(call debug_print_list,$(TEST_SRC)) - @echo "Test Object files:" - @$(call debug_print_list,$(TEST_OBJS)) - @echo "Mock Source files:" - @$(call debug_print_list,$(MOCKS_SRC)) - @echo "Mock Object files:" - @$(call debug_print_list,$(MOCKS_OBJS)) - @echo "All Input Dependency files:" - @$(call debug_print_list,$(DEP_FILES)) - @echo Stuff to clean: - @$(call debug_print_list,$(STUFF_TO_CLEAN)) - @echo Includes: - @$(call debug_print_list,$(INCLUDES)) - --include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/LICENSE.txt b/components/aws_iot/aws-iot-device-sdk-embedded-C/LICENSE.txt deleted file mode 100644 index 1b6cbea0c..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/LICENSE.txt +++ /dev/null @@ -1,120 +0,0 @@ -############################################################################################################################# - - -Apache License -Version 2.0, January 2004 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and - 2. You must cause any modified files to carry prominent notices stating that You changed the files; and - 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. -You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - - -############################################################################################################################# - - -Components are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - - -############################################################################################################################# - - -Copyright (C) 2012, iSEC Partners. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -############################################################################################################################# - - _ _ ____ _ - Project ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - -This software is licensed as described in the file COPYING, which -you should have received as part of this distribution. The terms -are also available at http://curl.haxx.se/docs/copyright.html. - -You may opt to use, copy, modify, merge, publish, distribute and/or sell -copies of the Software, and permit persons to whom the Software is -furnished to do so, under the terms of the COPYING file. - -This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -KIND, either express or implied. - - -############################################################################################################################# - - -Copyright (c) 2010 Serge A. Zaitsev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -############################################################################################################################# - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/Makefile deleted file mode 100644 index eebdb171f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -#Set this to @ to keep the makefile quiet -ifndef SILENCE - SILENCE = @ -endif - -CC = gcc -RM = rm - -DEBUG = - -#--- Inputs ----# -COMPONENT_NAME = IotSdkC - -ALL_TARGETS := build-cpputest -ALL_TARGETS_CLEAN := - -CPPUTEST_USE_EXTENSIONS = Y -CPP_PLATFORM = Gcc -CPPUTEST_CFLAGS += -std=gnu99 -CPPUTEST_LDFLAGS += -lpthread -CPPUTEST_CFLAGS += -D__USE_BSD -CPPUTEST_USE_GCOV = Y - -#IoT client directory -IOT_CLIENT_DIR = . - -APP_DIR = $(IOT_CLIENT_DIR)/tests/unit -APP_NAME = aws_iot_sdk_unit_tests -APP_SRC_FILES = $(shell find $(APP_DIR)/src -name '*.cpp') -APP_SRC_FILES = $(shell find $(APP_DIR)/src -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -CPPUTEST_DIR = $(IOT_CLIENT_DIR)/external_libs/CppUTest - -# Provide paths for CppUTest to run Unit Tests otherwise build will fail -ifndef CPPUTEST_INCLUDE - CPPUTEST_INCLUDE = $(CPPUTEST_DIR)/include -endif - -ifndef CPPUTEST_BUILD_LIB - CPPUTEST_BUILD_LIB = $(CPPUTEST_DIR) -endif - -CPPUTEST_LDFLAGS += -ldl $(CPPUTEST_BUILD_LIB)/libCppUTest.a - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(APP_DIR)/tls_mock -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR) -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -EXTERNAL_LIBS += -L$(CPPUTEST_BUILD_LIB) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_DIRS += $(CPPUTEST_INCLUDE) - -TEST_SRC_DIRS = $(APP_DIR)/src - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS = cd $(CPPUTEST_DIR) && -PRE_MAKE_CMDS += cmake CMakeLists.txt && -PRE_MAKE_CMDS += make && -PRE_MAKE_CMDS += cd - && -PRE_MAKE_CMDS += pwd && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTest/libCppUTest.a $(CPPUTEST_DIR)/libCppUTest.a && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTestExt/libCppUTestExt.a $(CPPUTEST_DIR)/libCppUTestExt.a - -# Using TLS Mock for running Unit Tests -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls_params.c -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls.c - -ISYSTEM_HEADERS += $(IOT_ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(LOG_FLAGS) - -LCOV_EXCLUDE_PATTERN = "tests/unit/*" -LCOV_EXCLUDE_PATTERN += "tests/integration/*" -LCOV_EXCLUDE_PATTERN += "external_libs/*" - -#use this section for running a specific group of tests, comment this to run all -#ONLY FOR TESTING PURPOSE -#COMMAND_LINE_ARGUMENTS += -g CommonTests -#COMMAND_LINE_ARGUMENTS += -v - -build-cpputest: - $(PRE_MAKE_CMDS) - -include CppUTestMakefileWorker.mk - -.PHONY: run-unit-tests -run-unit-tests: $(ALL_TARGETS) - @echo $(ALL_TARGETS) - -.PHONY: clean -clean: - $(MAKE) -C $(CPPUTEST_DIR) clean - $(RM) -rf build_output - $(RM) -rf gcov - $(RM) -rf objs - $(RM) -rf testLibs \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/NOTICE.txt b/components/aws_iot/aws-iot-device-sdk-embedded-C/NOTICE.txt deleted file mode 100644 index c3f856f11..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/NOTICE.txt +++ /dev/null @@ -1,16 +0,0 @@ -AWS C SDK for Internet of Things Service -Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -This product includes software developed by -Amazon Inc (http://www.amazon.com/). - -********************** -THIRD PARTY COMPONENTS -********************** -This software includes third party software subject to the following licensing: -- Embedded C MQTT Client - From the Eclipse Paho Project - EPL v1.0 -- mbedTLS (external library, included in tarball or downloaded separately) - Apache 2.0 -- jsmn (JSON Parsing) - MIT -- cURL (hostname verification) - MIT - -The licenses for these third party components are included in LICENSE.txt diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/PortingGuide.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/PortingGuide.md deleted file mode 100644 index 18baaf3c1..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/PortingGuide.md +++ /dev/null @@ -1,147 +0,0 @@ -# Porting Guide - -## Scope -The scope of this document is to provide instructions to modify the provided source files and functions in this SDK to run in a variety of embedded C–based environments (e.g. real-time OS, embedded Linux) and to be adjusted to use a specific TLS implementation as available with specific hardware platforms. - -## Contents of the SDK - -The C-code files of this SDK are delivered via the following directory structure (see comment behind folder name for an explanation of its content). - -Current SDK Directory Layout (mbedTLS) - -|--`certs` (Private key, device certificate and Root CA)
-|--`docs` (Developer guide & API documentation)
-|--`external_libs` (external libraries - jsmn, mbedTLS)
-|--`include` (Header files of the AWS IoT device SDK)
-|--`src` (Source files of the AWS IoT device SDK)
-|--`platform` (Platform specific files)
-|--`samples` (Samples including makefiles for building on mbedTLS)
-|--`tests` (Tests for verifying SDK is functioning as expected)
- -All makefiles in this SDK were configured using the documented folder structure above, so moving or renaming folders will require modifications to makefiles. - -## Explanation of folders and their content - - * `certs` : This directory is initially empty and will need to contain the private key, the client certificate and the root CA. The client certificate and private key can be downloaded from the AWS IoT console or be created using the AWS CLI commands. The root CA can be downloaded from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem). - - * `docs` : SDK API and file documentation. - - * `external_libs` : The mbedTLS and jsmn source files. The jsmn source files are always present. The mbedTLS source files are only included when downloading the tarball version of the SDK. - - * `include` : This directory contains the header files that an application using the SDK needs to include. - - * `src` : This directory contains the SDK source code including the MQTT library, device shadow code and utilities. - - * `platform` : Platform specific files for timer, TLS and threading layers. Includes a reference implementation for the linux using mbedTLS and pthread. - - * `samples` : This directory contains sample applications as well as their makefiles. The samples include a simple MQTT example which publishes and subscribes to the AWS IoT service as well as a device shadow example that shows example usage of the device shadow functionality. - - * `tests` : Contains tests for verifying SDK functionality. For further details please check the readme file included with the tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/README.md/). - -## Integrating the SDK into your environment - -This section explains the API calls that need to be implemented in order for the Device SDK to run on your platform. The SDK interfaces follow the driver model where only prototypes are defined by the Device SDK itself while the implementation is delegated to the user of the SDK to adjust it to the platform in use. The following sections list the needed functionality for the device SDK to run successfully on any given platform. - -### Timer Functions - -A timer implementation is necessary to handle request timeouts (sending MQTT connect, subscribe, etc. commands) as well as connection maintenance (MQTT keep-alive pings). Timers need millisecond resolution and are polled for expiration so these can be implemented using a "milliseconds since startup" free-running counter if desired. In the synchronous sample provided with this SDK only one command will be "in flight" at one point in time plus the client's ping timer. - -Define the `Timer` Struct as in `timer_platform.h` - -`void init_timer(Timer *);` -init_timer - A timer structure is initialized to a clean state. - -`bool has_timer_expired(Timer *);` -has_timer_expired - a polling function to determine if the timer has expired. - -`void countdown_ms(Timer *, uint32_t);` -countdown_ms - set the timer to expire in x milliseconds and start the timer. - -`void countdown_sec(Timer *, uint32_t);` -countdown_sec - set the timer to expire in x seconds and start the timer. - -`uint32_t left_ms(Timer *);` -left_ms - query time in milliseconds left on the timer. - - -### Network Functions - -In order for the MQTT client stack to be able to communicate via the TCP/IP network protocol stack using a mutually authenticated TLS connection, the following API calls need to be implemented for your platform. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `TLSDataParams` Struct as in `network_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, const char *pDeviceCertLocation, - const char *pDevicePrivateKeyLocation, const char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag);` -Initialize the network client / structure. - -`IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams);` -Create a TLS TCP socket to the configure address using the credentials provided via the NewNetwork API call. This will include setting up certificate locations / arrays. - - -`IoT_Error_t iot_tls_write(Network*, unsigned char*, size_t, Timer *, size_t *);` -Write to the TLS network buffer. - -`IoT_Error_t iot_tls_read(Network*, unsigned char*, size_t, Timer *, size_t *);` -Read from the TLS network buffer. - -`IoT_Error_t iot_tls_disconnect(Network *pNetwork);` -Disconnect API - -`IoT_Error_t iot_tls_destroy(Network *pNetwork);` -Clean up the connection - -`IoT_Error_t iot_tls_is_connected(Network *pNetwork);` -Check if the TLS layer is still connected - -The TLS library generally provides the API for the underlying TCP socket. - - -### Threading Functions - -The MQTT client uses a state machine to control operations in multi-threaded situations. However it requires a mutex implementation to guarantee thread safety. This is not required in situations where thread safety is not important and it is disabled by default. The _ENABLE_THREAD_SUPPORT_ macro needs to be defined in aws_iot_config.h to enable this layer. You will also need to add the -lpthread linker flag for the compiler if you are using the provided reference implementation. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `IoT_Mutex_t` Struct as in `threads_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *);` -Initialize the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *);` -Lock the mutex provided as argument - -`IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *);` -Unlock the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *);` -Destroy the mutex provided as argument. - -The threading layer provides the implementation of mutexes used for thread-safe operations. - -### Sample Porting: - -Marvell has ported the SDK for their development boards. [These](https://github.com/marvell-iot/aws_starter_sdk/tree/master/sdk/external/aws_iot/platform/wmsdk) files are example implementations of the above mentioned functions. -This provides a port of the timer and network layer. The threading layer is not a part of this port. - -## Time source for certificate validation - -As part of the TLS handshake the device (client) needs to validate the server certificate which includes validation of the certificate lifetime requiring that the device is aware of the actual time. Devices should be equipped with a real time clock or should be able to obtain the current time via NTP. Bypassing validation of the lifetime of a certificate is not recommended as it exposes the device to a security vulnerability, as it will still accept server certificates even when they have already has_timer_expired. - -## Integration into operating system -### Single-Threaded implementation - -The single threaded implementation implies that the sample application code (SDK + MQTT client) is called periodically by the firmware application running on the main thread. This is done by calling the function `aws_iot_mqtt_yield` (in the simple pub-sub example) and by calling `aws_iot_shadow_yield()` (in the device shadow example). In both cases the keep-alive time is set to 10 seconds. This means that the yield functions need to be called at a minimum frequency of once every 10 seconds. Note however that the `iot_mqtt_yield()` function takes care of reading incoming MQTT messages from the IoT service as well and hence should be called more frequently depending on the timing requirements of an application. All incoming messages can only be processed at the frequency at which `yield` is called. - -### Multi-Threaded implementation - -In the simple multi-threaded case the `yield` function can be moved to a background thread. Ensure this task runs at the frequency described above. In this case, depending on the OS mechanism, a message queue or mailbox could be used to proxy incoming MQTT messages from the callback to the worker task responsible for responding to or dispatching messages. A similar mechanism could be employed to queue publish messages from threads into a publish queue that are processed by a publishing task. Ensure the threading layer is enabled as the library is not thread safe otherwise. -There is a validation test for the multi-threaded implementation that can be found with the integration tests. You can find further details in the Readme for the integration tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/integration/README.md). We have run the validation test with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. - -## Sample applications - -The sample apps in this SDK provide a working implementation for mbedTLS. They use a reference implementation for linux provided with the SDK. Threading layer is enabled in the subscribe publish sample. diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/README.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/README.md deleted file mode 100644 index 8b762d4a7..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/README.md +++ /dev/null @@ -1,117 +0,0 @@ -## ***** NOTICE ***** -This repository is moving to a new branching system. The master branch will now contain bug fixes/features that have been minimally tested to ensure nothing major is broken. The release branch will contain new releases for the SDK that have been tested thoroughly on all supported platforms. Please ensure that you are tracking the release branch for all production work. - -This change will allow us to push out bug fixes quickly and avoid having situations where issues stay open for a very long time. - -## Overview - -The AWS IoT device SDK for embedded C is a collection of C source files which can be used in embedded applications to securely connect to the [AWS IoT platform](http://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html). It includes transport clients **MQTT**, **TLS** implementations and examples for their use. It also supports AWS IoT specific features such as **Thing Shadow**. It is distributed in source form and intended to be built into customer firmware along with application code, other libraries and RTOS. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). - -## Features -The Device SDK simplifies access to the Pub/Sub functionality of the AWS IoT broker via MQTT and provide APIs to interact with Thing Shadows. The SDK has been tested to work with the AWS IoT platform to ensure best interoperability of a device with the AWS IoT platform. - -### MQTT Connection -The Device SDK provides functionality to create and maintain a mutually authenticated TLS connection over which it runs MQTT. This connection is used for any further publish operations and allow for subscribing to MQTT topics which will call a configurable callback function when these topics are received. - -### Thing Shadow -The Device SDK implements the specific protocol for Thing Shadows to retrieve, update and delete Thing Shadows adhering to the protocol that is implemented to ensure correct versioning and support for client tokens. It abstracts the necessary MQTT topic subscriptions by automatically subscribing to and unsubscribing from the reserved topics as needed for each API call. Inbound state change requests are automatically signalled via a configurable callback. - -## Design Goals of this SDK -The embedded C SDK was specifically designed for resource constrained devices (running on micro-controllers and RTOS). - -Primary aspects are: - * Flexibility in picking and choosing functionality (reduce memory footprint) - * Static memory only (no malloc’s) - * Configurable resource usage(JSON tokens, MQTT subscription handlers, etc…) - * Can be ported to a different RTOS, uses wrappers for OS specific functions - -For more information on the Architecture of the SDK refer [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -## Collection of Metrics -Beginning with Release v2.2.0 of the SDK, AWS collects usage metrics indicating which language and version of the SDK is being used. This allows us to prioritize our resources towards addressing issues faster in SDKs that see the most and is an important data point. However, we do understand that not all customers would want to report this data by default. In that case, the sending of usage metrics can be easily disabled by the user by setting the `DISABLE_METRICS` flag to true in the -`aws_iot_config.h` for each application. - -## How to get started ? -Ensure you understand the AWS IoT platform and create the necessary certificates and policies. For more information on the AWS IoT platform please visit the [AWS IoT developer guide](http://docs.aws.amazon.com/iot/latest/developerguide/iot-security-identity.html). - -In order to quickly get started with the AWS IoT platform, we have ported the SDK for POSIX type Operating Systems like Ubuntu, OS X and RHEL. The SDK is configured for the mbedTLS library and can be built out of the box with *GCC* using *make utility*. You'll need to download mbedTLS from the official ARMmbed repository. We recommend that you pick the latest version in order to have up-to-date security fixes. - -## Installation -This section explains the individual steps to retrieve the necessary files and be able to build your first application using the AWS IoT device SDK for embedded C. - -Steps: - - * Create a directory to hold your application e.g. (/home//aws_iot/my_app) - * Change directory to this new directory - * Download the SDK to device and place in the newly created directory - * Expand the tarball (tar -xf ). This will create the below directories: - * `certs` - TLS certificates directory - * `docs` - SDK API and file documentation. This folder is not present on GitHub. You can access the documentation [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - * `external_libs` - The mbedTLS and jsmn source files - * `include` - The AWS IoT SDK header files - * `platform` - Platform specific files for timer, TLS and threading layers - * `samples` - The sample applications - * `src` - The AWS IoT SDK source files - * `tests` - Contains tests for verifying that the SDK is functioning as expected. More information can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md) - * View further information on how to use the SDK in the Readme file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md) - -Also, for a guided example on getting started with the Thing Shadow, visit the AWS IoT Console's [Interactive Guide](https://console.aws.amazon.com/iot). - -## Porting to different platforms -As Embedded devices run on different Real Time Operating Systems and TCP/IP stacks, it is one of the important design goals for the Device SDK to keep it portable. Please refer to the [porting guide](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/PortingGuide.md) to get more information on how to make this SDK run on your devices (i.e. micro-controllers). - -## Migrating from 1.x to 2.x -The 2.x branch makes several changes to the SDK. This section provides information on what changes will be required in the client application for migrating from v1.x to 2.x. - - * The first change is in the folder structure. Client applications using the SDK now need to keep only the certs, external_libs, include, src and platform folder in their application. The folder descriptions can be found above - * All the SDK headers are in the `include` folder. These need to be added to the makefile as include directories - * The source files are in the `src` folder. These need to be added to the makefile as one of the source directories - * Similar to 1.x, the platform folder contains the platform specific headers and source files. These need to be added to the makefile as well - * The `platform/threading` folder only needs to be added if multi-threading is required, and the `_ENABLE_THREAD_SUPPORT_` macro is defined in config - * The list below provides a mapping for migrating from the major APIs used in 1.x to the new APIs: - - | Description | 1.x | 2.x | - | :---------- | :-- | :-- | - | Initializing the client | ```void aws_iot_mqtt_init(MQTTClient_t *pClient);``` | ```IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams);``` | - | Connect | ```IoT_Error_t aws_iot_mqtt_connect(MQTTConnectParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams);``` | - | Subscribe | ```IoT_Error_t aws_iot_mqtt_subscribe(MQTTSubscribeParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData);``` | - | Unsubscribe | ```IoT_Error_t aws_iot_mqtt_unsubscribe(char *pTopic);``` | ```IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen);``` | - | Yield | ```IoT_Error_t aws_iot_mqtt_yield(int timeout);``` | ```IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms);``` | - | Publish | ```IoT_Error_t aws_iot_mqtt_publish(MQTTPublishParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, IoT_Publish_Message_Params *pParams);``` | - | Disconnect | ```IoT_Error_t aws_iot_mqtt_disconnect(void);``` | ```IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient);``` | - -You can find more information on how to use the new APIs in the Readme file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md) - -## Resources -[API Documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -[MQTT 3.1.1 Spec](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html) - -## Support -If you have any technical questions about AWS IoT Device SDK, use the [AWS IoT forum](https://forums.aws.amazon.com/forum.jspa?forumID=210). -For any other questions on AWS IoT, contact [AWS Support](https://aws.amazon.com/contact-us/). - -## Sample APIs -Connecting to the AWS IoT MQTT platform - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_init(&client, &iotInitParams); -rc = aws_iot_mqtt_connect(&client, &iotConnectParams); -``` - - -Subscribe to a topic - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); -``` - - -Update Thing Shadow from a device - -``` -rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, pJsonDocumentBuffer, ShadowUpdateStatusCallback, - pCallbackContext, TIMEOUT_4SEC, persistenSubscription); -``` diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/certs/README.txt b/components/aws_iot/aws-iot-device-sdk-embedded-C/certs/README.txt deleted file mode 100644 index 8df3d0208..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/certs/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copy certificates for running the samples and tests provided with the SDK into this directory -# Certificates can be created and downloaded from the AWS IoT Console -# The IoT Client takes the full path of the certificates as an input parameter while initializing -# This is the default folder for the certificates only for samples and tests. A different path can be specified if required. \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt b/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt deleted file mode 100644 index 5b2e09255..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Copy source code for CppUTest into this directory -# The SDK was tested internally with CppUTest v3.6 which can be found here - https://github.com/cpputest/cpputest/releases/tag/v3.6 \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c deleted file mode 100644 index e920e8620..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.c - * @brief Implementation of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return 0; -} - -/** - * Fills next token with JSON string. - */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return 0; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - if(token->type != type || parser->toksuper == -1) { - return JSMN_ERROR_INVAL; - } - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { -#ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; -#else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } -#endif - } - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - } - } - - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } - - return count; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h deleted file mode 100644 index e0ffb1bc4..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.h - * @brief Definition of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#ifndef __JSMN_H_ -#define __JSMN_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 -} jsmntype_t; - -enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 -}; - -/** - * JSON token description. - * type type (object, array, string etc.) - * start start position in JSON data string - * end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); - -#ifdef __cplusplus -} -#endif - -#endif /* __JSMN_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt b/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt deleted file mode 100644 index a3ff466ba..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copy source code for mbedTLS into this directory -# -# You'll need to download mbedTLS from the official ARMmbed repository and -# place the files here. We recommend that you pick the latest version in -# order to have up-to-date security fixes. diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/filterGcov.sh b/components/aws_iot/aws-iot-device-sdk-embedded-C/filterGcov.sh deleted file mode 100755 index fee4a0327..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/filterGcov.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -INPUT_FILE=$1 -TEMP_FILE1=${INPUT_FILE}1.tmp -TEMP_FILE2=${INPUT_FILE}2.tmp -TEMP_FILE3=${INPUT_FILE}3.tmp -ERROR_FILE=$2 -OUTPUT_FILE=$3 -HTML_OUTPUT_FILE=$3.html -TEST_RESULTS=$4 - -flattenGcovOutput() { -while read line1 -do - read line2 - echo $line2 " " $line1 - read junk - read junk -done < ${INPUT_FILE} -} - -getRidOfCruft() { -sed '-e s/^Lines.*://g' \ - '-e s/^[0-9]\./ &/g' \ - '-e s/^[0-9][0-9]\./ &/g' \ - '-e s/of.*File/ /g' \ - "-e s/'//g" \ - '-e s/^.*\/usr\/.*$//g' \ - '-e s/^.*\.$//g' -} - -flattenPaths() { -sed \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/\.\.\//\//g' -} - -getFileNameRootFromErrorFile() { -sed '-e s/gc..:cannot open .* file//g' ${ERROR_FILE} -} - -writeEachNoTestCoverageFile() { -while read line -do - echo " 0.00% " ${line} -done -} - -createHtmlOutput() { - echo "" - echo "" - sed "-e s/.*% /
CoverageFile
&<\/td>/" \ - "-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/&<\/a><\/td><\/tr>/" - echo "
" - sed "-e s/.*/&
/g" < ${TEST_RESULTS} -} - -flattenGcovOutput | getRidOfCruft | flattenPaths > ${TEMP_FILE1} -getFileNameRootFromErrorFile | writeEachNoTestCoverageFile | flattenPaths > ${TEMP_FILE2} -cat ${TEMP_FILE1} ${TEMP_FILE2} | sort | uniq > ${OUTPUT_FILE} -createHtmlOutput < ${OUTPUT_FILE} > ${HTML_OUTPUT_FILE} -rm -f ${TEMP_FILE1} ${TEMP_FILE2} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h deleted file mode 100644 index 03f297b21..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_error.h - * @brief Definition of error types for the SDK. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_ERROR_H_ -#define AWS_IOT_SDK_SRC_IOT_ERROR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Used to avoid warnings in case of unused parameters in function pointers */ -#define IOT_UNUSED(x) (void)(x) - -/*! \public - * @brief IoT Error enum - * - * Enumeration of return values from the IoT_* functions within the SDK. - * Values less than -1 are specific error codes - * Value of -1 is a generic failure response - * Value of 0 is a generic success response - * Values greater than 0 are specific non-error return codes - */ -typedef enum { - /** Returned when the Network physical layer is connected */ - NETWORK_PHYSICAL_LAYER_CONNECTED = 6, - /** Returned when the Network is manually disconnected */ - NETWORK_MANUALLY_DISCONNECTED = 5, - /** Returned when the Network is disconnected and the reconnect attempt is in progress */ - NETWORK_ATTEMPTING_RECONNECT = 4, - /** Return value of yield function to indicate auto-reconnect was successful */ - NETWORK_RECONNECTED = 3, - /** Returned when a read attempt is made on the TLS buffer and it is empty */ - MQTT_NOTHING_TO_READ = 2, - /** Returned when a connection request is successful and packet response is connection accepted */ - MQTT_CONNACK_CONNECTION_ACCEPTED = 1, - /** Success return value - no error occurred */ - SUCCESS = 0, - /** A generic error. Not enough information for a specific error code */ - FAILURE = -1, - /** A required parameter was passed as null */ - NULL_VALUE_ERROR = -2, - /** The TCP socket could not be established */ - TCP_CONNECTION_ERROR = -3, - /** The TLS handshake failed */ - SSL_CONNECTION_ERROR = -4, - /** Error associated with setting up the parameters of a Socket */ - TCP_SETUP_ERROR = -5, - /** A timeout occurred while waiting for the TLS handshake to complete. */ - NETWORK_SSL_CONNECT_TIMEOUT_ERROR = -6, - /** A Generic write error based on the platform used */ - NETWORK_SSL_WRITE_ERROR = -7, - /** SSL initialization error at the TLS layer */ - NETWORK_SSL_INIT_ERROR = -8, - /** An error occurred when loading the certificates. The certificates could not be located or are incorrectly formatted. */ - NETWORK_SSL_CERT_ERROR = -9, - /** SSL Write times out */ - NETWORK_SSL_WRITE_TIMEOUT_ERROR = -10, - /** SSL Read times out */ - NETWORK_SSL_READ_TIMEOUT_ERROR = -11, - /** A Generic error based on the platform used */ - NETWORK_SSL_READ_ERROR = -12, - /** Returned when the Network is disconnected and reconnect is either disabled or physical layer is disconnected */ - NETWORK_DISCONNECTED_ERROR = -13, - /** Returned when the Network is disconnected and the reconnect attempt has timed out */ - NETWORK_RECONNECT_TIMED_OUT_ERROR = -14, - /** Returned when the Network is already connected and a connection attempt is made */ - NETWORK_ALREADY_CONNECTED_ERROR = -15, - /** Network layer Error Codes */ - /** Network layer Random number generator seeding failed */ - NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED = -16, - /** A generic error code for Network layer errors */ - NETWORK_SSL_UNKNOWN_ERROR = -17, - /** Returned when the physical layer is disconnected */ - NETWORK_PHYSICAL_LAYER_DISCONNECTED = -18, - /** Returned when the root certificate is invalid */ - NETWORK_X509_ROOT_CRT_PARSE_ERROR = -19, - /** Returned when the device certificate is invalid */ - NETWORK_X509_DEVICE_CRT_PARSE_ERROR = -20, - /** Returned when the private key failed to parse */ - NETWORK_PK_PRIVATE_KEY_PARSE_ERROR = -21, - /** Returned when the network layer failed to open a socket */ - NETWORK_ERR_NET_SOCKET_FAILED = -22, - /** Returned when the server is unknown */ - NETWORK_ERR_NET_UNKNOWN_HOST = -23, - /** Returned when connect request failed */ - NETWORK_ERR_NET_CONNECT_FAILED = -24, - /** Returned when there is nothing to read in the TLS read buffer */ - NETWORK_SSL_NOTHING_TO_READ = -25, - /** A connection could not be established. */ - MQTT_CONNECTION_ERROR = -26, - /** A timeout occurred while waiting for the TLS handshake to complete */ - MQTT_CONNECT_TIMEOUT_ERROR = -27, - /** A timeout occurred while waiting for the TLS request complete */ - MQTT_REQUEST_TIMEOUT_ERROR = -28, - /** The current client state does not match the expected value */ - MQTT_UNEXPECTED_CLIENT_STATE_ERROR = -29, - /** The client state is not idle when request is being made */ - MQTT_CLIENT_NOT_IDLE_ERROR = -30, - /** The MQTT RX buffer received corrupt or unexpected message */ - MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR = -31, - /** The MQTT RX buffer received a bigger message. The message will be dropped */ - MQTT_RX_BUFFER_TOO_SHORT_ERROR = -32, - /** The MQTT TX buffer is too short for the outgoing message. Request will fail */ - MQTT_TX_BUFFER_TOO_SHORT_ERROR = -33, - /** The client is subscribed to the maximum possible number of subscriptions */ - MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR = -34, - /** Failed to decode the remaining packet length on incoming packet */ - MQTT_DECODE_REMAINING_LENGTH_ERROR = -35, - /** Connect request failed with the server returning an unknown error */ - MQTT_CONNACK_UNKNOWN_ERROR = -36, - /** Connect request failed with the server returning an unacceptable protocol version error */ - MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -37, - /** Connect request failed with the server returning an identifier rejected error */ - MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -38, - /** Connect request failed with the server returning an unavailable error */ - MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -39, - /** Connect request failed with the server returning a bad userdata error */ - MQTT_CONNACK_BAD_USERDATA_ERROR = -40, - /** Connect request failed with the server failing to authenticate the request */ - MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -41, - /** An error occurred while parsing the JSON string. Usually malformed JSON. */ - JSON_PARSE_ERROR = -42, - /** Shadow: The response Ack table is currently full waiting for previously published updates */ - SHADOW_WAIT_FOR_PUBLISH = -43, - /** Any time an snprintf writes more than size value, this error will be returned */ - SHADOW_JSON_BUFFER_TRUNCATED = -44, - /** Any time an snprintf encounters an encoding error or not enough space in the given buffer */ - SHADOW_JSON_ERROR = -45, - /** Mutex initialization failed */ - MUTEX_INIT_ERROR = -46, - /** Mutex lock request failed */ - MUTEX_LOCK_ERROR = -47, - /** Mutex unlock request failed */ - MUTEX_UNLOCK_ERROR = -48, - /** Mutex destroy failed */ - MUTEX_DESTROY_ERROR = -49, -} IoT_Error_t; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_ERROR_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h deleted file mode 100644 index ceb02b31d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_json_utils.h - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifndef AWS_IOT_SDK_SRC_JSON_UTILS_H_ -#define AWS_IOT_SDK_SRC_JSON_UTILS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "aws_iot_error.h" -#include "jsmn.h" - -// utility functions -/** - * @brief JSON Equality Check - * - * Given a token pointing to a particular JSON node and an - * input string, check to see if the key is equal to the string. - * - * @param json json string - * @param tok json token - pointer to key to test for equality - * @param s input string for key to test equality - * - * @return 0 if equal, 1 otherwise - */ -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s); - -/** - * @brief Parse a signed 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a float value from a JSON node. - * - * Given a JSON node parse the float value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param f address of float to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a double value from a JSON node. - * - * Given a JSON node parse the double value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param d address of double to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a boolean value from a JSON node. - * - * Given a JSON node parse the boolean value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param b address of boolean to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a string value from a JSON node. - * - * Given a JSON node parse the string value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param s address of string to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseStringValue(char *buf, const char *jsonString, jsmntok_t *token); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_JSON_UTILS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h deleted file mode 100644 index 60c26086c..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_log.h - * @brief Logging macros for the SDK. - * This file defines common logging macros with log levels to be used within the SDK. - * These macros can also be used in the IoT application code as a common way to output - * logs. The log levels can be tuned by modifying the makefile. Removing (commenting - * out) the IOT_* statement in the makefile disables that log level. - * - * It is expected that the macros below will be modified or replaced when porting to - * specific hardware platforms as printf may not be the desired behavior. - */ - -#ifndef _IOT_LOG_H -#define _IOT_LOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @brief Debug level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_DEBUG -#define IOT_DEBUG(...) \ - {\ - printf("DEBUG: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#define IOT_DEBUG(...) -#endif - -/** - * @brief Debug level trace logging macro. - * - * Macro to print message function entry and exit - */ -#ifdef ENABLE_IOT_TRACE -#define FUNC_ENTRY \ - {\ - printf("FUNC_ENTRY: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT \ - {\ - printf("FUNC_EXIT: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT_RC(x) \ - {\ - printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } -#else -#define FUNC_ENTRY - -#define FUNC_EXIT -#define FUNC_EXIT_RC(x) { return x; } -#endif - -/** - * @brief Info level logging macro. - * - * Macro to expose desired log message. Info messages do not include automatic function names and line numbers. - */ -#ifdef ENABLE_IOT_INFO -#define IOT_INFO(...) \ - {\ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#define IOT_INFO(...) -#endif - -/** - * @brief Warn level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_WARN -#define IOT_WARN(...) \ - { \ - printf("WARN: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#define IOT_WARN(...) -#endif - -/** - * @brief Error level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_ERROR -#define IOT_ERROR(...) \ - { \ - printf("ERROR: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#define IOT_ERROR(...) -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _IOT_LOG_H diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h deleted file mode 100644 index bf0618946..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.h - * @brief Client definition for MQTT - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -#define MAX_PACKET_ID 65535 - -typedef struct _Client AWS_IoT_Client; - -/** - * @brief Quality of Service Type - * - * Defining a QoS type. - * @note QoS 2 is \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef enum QoS { - QOS0 = 0, - QOS1 = 1 -} QoS; - -/** - * @brief Publish Message Parameters Type - * - * Defines a type for MQTT Publish messages. Used for both incoming and out going messages - * - */ -typedef struct { - QoS qos; ///< Message Quality of Service - uint8_t isRetained; ///< Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - uint8_t isDup; ///< Is this message a duplicate QoS > 0 message? Handled automatically by the MQTT client. - uint16_t id; ///< Message sequence identifier. Handled automatically by the MQTT client. - void *payload; ///< Pointer to MQTT message payload (bytes). - size_t payloadLen; ///< Length of MQTT payload. -} IoT_Publish_Message_Params; - -/** - * @brief MQTT Version Type - * - * Defining an MQTT version type. Only 3.1.1 is supported at this time - * - */ -typedef enum { - MQTT_3_1_1 = 4 ///< MQTT 3.1.1 (protocol message byte = 4) -} MQTT_Ver_t; - -/** - * @brief Last Will and Testament Definition - * - * Defining a type for the MQTT "Last Will and Testament" (LWT) parameters. - * @note Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTW - char *pTopicName; ///< The LWT topic to which the LWT message will be published - uint16_t topicNameLen; ///< The length of the LWT topic, 16 bit unsinged integer - char *pMessage; ///< Message to be delivered as LWT - uint16_t msgLen; ///< The length of the Message, 16 bit unsinged integer - bool isRetained; ///< NOT supported. The retained flag for the LWT message (see MQTTAsync_message.retained) - QoS qos; ///< QoS of LWT message -} IoT_MQTT_Will_Options; -extern const IoT_MQTT_Will_Options iotMqttWillOptionsDefault; - -#define IoT_MQTT_Will_Options_Initializer { {'M', 'Q', 'T', 'W'}, NULL, 0, NULL, 0, false, QOS0 } - -/** - * @brief MQTT Connection Parameters - * - * Defining a type for MQTT connection parameters. Passed into client when establishing a connection. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTC - MQTT_Ver_t MQTTVersion; ///< Desired MQTT version used during connection - const char *pClientID; ///< Pointer to a string defining the MQTT client ID (this needs to be unique \b per \b device across your AWS account) - uint16_t clientIDLen; ///< Client Id Length. 16 bit unsigned integer - uint16_t keepAliveIntervalInSec; ///< MQTT keep alive interval in seconds. Defines inactivity time allowed before determining the connection has been lost. - bool isCleanSession; ///< MQTT clean session. True = this session is to be treated as clean. Previous server state is cleared and no stated is retained from this connection. - bool isWillMsgPresent; ///< Is there a LWT associated with this connection? - IoT_MQTT_Will_Options will; ///< MQTT LWT parameters. - char *pUsername; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t usernameLen; ///< Username Length. 16 bit unsigned integer - char *pPassword; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t passwordLen; ///< Password Length. 16 bit unsigned integer -} IoT_Client_Connect_Params; -extern const IoT_Client_Connect_Params iotClientConnectParamsDefault; - -#define IoT_Client_Connect_Params_initializer { {'M', 'Q', 'T', 'C'}, MQTT_3_1_1, NULL, 0, 60, true, false, \ - IoT_MQTT_Will_Options_Initializer, NULL, 0, NULL, 0 } - -/** - * @brief Disconnect Callback Handler Type - * - * Defining a TYPE for definition of disconnect callback function pointers. - * - */ -typedef void (*iot_disconnect_handler)(AWS_IoT_Client *, void *); - -/** - * @brief MQTT Initialization Parameters - * - * Defining a type for MQTT initialization parameters. - * Passed into client when to initialize the client - * - */ -typedef struct { - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - char *pHostURL; ///< Pointer to a string defining the endpoint for the MQTT service - uint16_t port; ///< MQTT service listening port - const char *pRootCALocation; ///< Pointer to a string defining the Root CA file (full file, not path) - const char *pDeviceCertLocation; ///< Pointer to a string defining the device identity certificate file (full file, not path) - const char *pDevicePrivateKeyLocation; ///< Pointer to a string defining the device private key file (full file, not path) - uint32_t mqttPacketTimeout_ms; ///< Timeout for reading a complete MQTT packet. In milliseconds - uint32_t mqttCommandTimeout_ms; ///< Timeout for MQTT blocking calls. In milliseconds - uint32_t tlsHandshakeTimeout_ms; ///< TLS handshake timeout. In milliseconds - bool isSSLHostnameVerify; ///< Client should perform server certificate hostname validation - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss - void *disconnectHandlerData; ///< Data to pass as argument when disconnect handler is called -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; ///< Timeout for Thread blocking calls. Set to 0 to block until lock is obtained. In milliseconds -#endif -} IoT_Client_Init_Params; -extern const IoT_Client_Init_Params iotClientInitParamsDefault; - -#ifdef _ENABLE_THREAD_SUPPORT_ -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL, false } -#else -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL } -#endif - -/** - * @brief MQTT Client State Type - * - * Defining a type for MQTT Client State - * - */ -typedef enum _ClientState { - CLIENT_STATE_INVALID = 0, - CLIENT_STATE_INITIALIZED = 1, - CLIENT_STATE_CONNECTING = 2, - CLIENT_STATE_CONNECTED_IDLE = 3, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS = 4, - CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS = 5, - CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS = 6, - CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS = 7, - CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS = 8, - CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN = 9, - CLIENT_STATE_DISCONNECTING = 10, - CLIENT_STATE_DISCONNECTED_ERROR = 11, - CLIENT_STATE_DISCONNECTED_MANUALLY = 12, - CLIENT_STATE_PENDING_RECONNECT = 13 -} ClientState; - -/** - * @brief Application Callback Handler Type - * - * Defining a TYPE for definition of application callback function pointers. - * Used to send incoming data to the application - * - */ -typedef void (*pApplicationHandler_t)(AWS_IoT_Client *pClient, char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams, void *pClientData); - -/** - * @brief MQTT Message Handler - * - * Defining a type for MQTT Message Handlers. - * Used to pass incoming data back to the application - * - */ -typedef struct _MessageHandlers { - const char *topicName; - uint16_t topicNameLen; - QoS qos; - pApplicationHandler_t pApplicationHandler; - void *pApplicationHandlerData; -} MessageHandlers; /* Message handlers are indexed by subscription topic */ - -/** - * @brief MQTT Client Status - * - * Defining a type for MQTT Client Status - * Contains information about the state of the MQTT Client - * - */ -typedef struct _ClientStatus { - ClientState clientState; - bool isPingOutstanding; - bool isAutoReconnectEnabled; -} ClientStatus; - -/** - * @brief MQTT Client Data - * - * Defining a type for MQTT Client Data - * Contains data used by the MQTT Client - * - */ -typedef struct _ClientData { - uint16_t nextPacketId; - - uint32_t packetTimeoutMs; - uint32_t commandTimeoutMs; - uint16_t keepAliveInterval; - uint32_t currentReconnectWaitInterval; - uint32_t counterNetworkDisconnected; - - /* The below values are initialized with the - * lengths of the TX/RX buffers and never modified - * afterwards */ - size_t writeBufSize; - size_t readBufSize; - - unsigned char writeBuf[AWS_IOT_MQTT_TX_BUF_LEN]; - unsigned char readBuf[AWS_IOT_MQTT_RX_BUF_LEN]; - -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; - IoT_Mutex_t state_change_mutex; - IoT_Mutex_t tls_read_mutex; - IoT_Mutex_t tls_write_mutex; -#endif - - IoT_Client_Connect_Params options; - - MessageHandlers messageHandlers[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS]; - iot_disconnect_handler disconnectHandler; - - void *disconnectHandlerData; -} ClientData; - -/** - * @brief MQTT Client - * - * Defining a type for MQTT Client - * - */ -struct _Client { - Timer pingTimer; - Timer reconnectDelayTimer; - - ClientStatus clientStatus; - ClientData clientData; - Network networkStack; -}; - -/** - * @brief What is the next available packet Id - * - * Called to retrieve the next packet id to be used for outgoing packets. - * Automatically increments the last sent packet id variable - * - * @param pClient Reference to the IoT Client - * - * @return next packet id as a 16 bit unsigned integer - */ -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient); - -/** - * @brief Set the connection parameters for the IoT Client - * - * Called to set the connection parameters for the IoT Client. - * Used to update the connection parameters provided before the last connect. - * Won't take effect until the next time connect is called - * - * @param pClient Reference to the IoT Client - * @param pNewConnectParams Reference to the new Connection Parameters structure - * - * @return IoT_Error_t Type defining successful/failed API call - */ -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pNewConnectParams); - -/** - * @brief Is the MQTT client currently connected? - * - * Called to determine if the MQTT client is currently connected. Used to support logic - * in the device application around reconnecting and managing offline state. - * - * @param pClient Reference to the IoT Client - * - * @return true = connected, false = not currently connected - */ -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient); - -/** - * @brief Get the current state of the client - * - * Called to get the current state of the client - * - * @param pClient Reference to the IoT Client - * - * @return ClientState value equal to the current state of the client - */ -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient); - -/** - * @brief Is the MQTT client set to reconnect automatically? - * - * Called to determine if the MQTT client is set to reconnect automatically. - * Used to support logic in the device application around reconnecting - * - * @param pClient Reference to the IoT Client - * - * @return true = enabled, false = disabled - */ -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient); - -/** - * @brief Set the IoT Client disconnect handler - * - * Called to set the IoT Client disconnect handler - * The disconnect handler is called whenever the client disconnects with error - * - * @param pClient Reference to the IoT Client - * @param pConnectHandler Reference to the new Disconnect Handler - * @param pDisconnectHandlerData Reference to the data to be passed as argument when disconnect handler is called - * - * @return IoT_Error_t Type defining successful/failed API call - */ -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData); - -/** - * @brief Enable or Disable AutoReconnect on Network Disconnect - * - * Called to enable or disabled the auto reconnect features provided with the SDK - * - * @param pClient Reference to the IoT Client - * @param newStatus set to true for enabling and false for disabling - * - * @return IoT_Error_t Type defining successful/failed API call - */ -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus); - -/** - * @brief Get count of Network Disconnects - * - * Called to get the number of times a network disconnect occurred due to errors - * - * @param pClient Reference to the IoT Client - * - * @return uint32_t the disconnect count - */ -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient); - -/** - * @brief Reset Network Disconnect conter - * - * Called to reset the Network Disconnect counter to zero - * - * @param pClient Reference to the IoT Client - */ -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h deleted file mode 100644 index 43d24870d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.h - * @brief Internal MQTT functions not exposed to application - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H -#define AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" - -/* Enum order should match the packet ids array defined in MQTTFormat.c */ -typedef enum msgTypes { - UNKNOWN = -1, - CONNECT = 1, - CONNACK = 2, - PUBLISH = 3, - PUBACK = 4, - PUBREC = 5, - PUBREL = 6, - PUBCOMP = 7, - SUBSCRIBE = 8, - SUBACK = 9, - UNSUBSCRIBE = 10, - UNSUBACK = 11, - PINGREQ = 12, - PINGRESP = 13, - DISCONNECT = 14 -} MessageTypes; - -/* Macros for parsing header fields from incoming MQTT frame. */ -#define MQTT_HEADER_FIELD_TYPE(_byte) ((_byte >> 4) & 0x0F) -#define MQTT_HEADER_FIELD_DUP(_byte) ((_byte & (1 << 3)) >> 3) -#define MQTT_HEADER_FIELD_QOS(_byte) ((_byte & (3 << 1)) >> 1) -#define MQTT_HEADER_FIELD_RETAIN(_byte) ((_byte & (1 << 0)) >> 0) - -/** - * Bitfields for the MQTT header byte. - */ -typedef union { - unsigned char byte; /**< the whole byte */ -} MQTTHeader; - -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained); - -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen); -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *, unsigned char *, - uint16_t *, unsigned char *, size_t); - -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len); - -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length); -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen); - -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr); -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt); - -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr); -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c); -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen); - -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType); -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes packetType, size_t *pSerializedLength); -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen); - -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState); - -#ifdef _ENABLE_THREAD_SUPPORT_ - -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h deleted file mode 100644 index fef12ee2a..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h +++ /dev/null @@ -1,199 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_interface.h - * @brief Interface definition for MQTT client. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" -#include "aws_iot_mqtt_client.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -/** - * @brief MQTT Client Initialization Function - * - * Called to initialize the MQTT Client - * - * @param pClient Reference to the IoT Client - * @param pInitParams Pointer to MQTT connection parameters - * - * @return IoT_Error_t Type defining successful/failed API call - */ -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, const IoT_Client_Init_Params *pInitParams); - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pConnectParams); - -/** - * @brief Publish an MQTT message on a topic - * - * Called to publish an MQTT message on a topic. - * @note Call is blocking. In the case of a QoS 0 message the function returns - * after the message was successfully passed to the TLS layer. In the case of QoS 1 - * the function returns after the receipt of the PUBACK control packet. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Pointer to Publish Message parameters - * - * @return An IoT Error Type defining successful/failed publish - */ -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams); - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pApplicationHandler_t Reference to the handler function for this subscription - * @param pApplicationHandlerData Data to be passed as argument to the application handler callback - * - * @return An IoT Error Type defining successful/failed subscription - */ -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData); - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to resubscribe to the topics that the client has active subscriptions on. - * Internally called when autoreconnect is enabled - * - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed subscription - */ -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient); - -/** - * @brief Unsubscribe to an MQTT topic. - * - * Called to send an unsubscribe message to the broker requesting removal of a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * - * @return An IoT Error Type defining successful/failed unsubscribe call - */ -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen); - -/** - * @brief Disconnect an MQTT Connection - * - * Called to send a disconnect message to the broker. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed send of the disconnect control packet. - */ -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient); - -/** - * @brief Yield to the MQTT client - * - * Called to yield the current thread to the underlying MQTT client. This time is used by - * the MQTT client to manage PING requests to monitor the health of the TCP connection as - * well as periodically check the socket receive buffer for subscribe messages. Yield() - * must be called at a rate faster than the keepalive interval. It must also be called - * at a rate faster than the incoming message rate as this is the only way the client receives - * processing time to manage incoming messages. - * - * @param pClient Reference to the IoT Client - * @param timeout_ms Maximum number of milliseconds to pass thread execution to the client. - * - * @return An IoT Error Type defining successful/failed client processing. - * If this call results in an error it is likely the MQTT connection has dropped. - * iot_is_mqtt_connected can be called to confirm. - */ -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms); - -/** - * @brief MQTT Manual Re-Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * using parameters from the last time a connection was attempted - * Use after disconnect to start the reconnect process manually - * Makes only one reconnect attempt Sets the client state to - * pending reconnect in case of failure - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h deleted file mode 100644 index a5f875593..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_interface.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h deleted file mode 100644 index 818b35f0e..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @file aws_iot_shadow_interface.h - * @brief Interface for thing shadow - * - * These are the functions and structs to manage/interact the Thing Shadow(in the cloud). - * This SDK will let you interact with your own thing shadow or any other shadow using its Thing Name. - * There are totally 3 actions a device can perform on the shadow - Get, Update and Delete. - * - * Currently the device should use MQTT/S underneath. In the future this will also support other protocols. As it supports MQTT, the shadow needs to connect and disconnect. - * It will also work on the pub/sub model. On performing any action, the acknowledgment will be received in either accepted or rejected. For Example: - * If we want to perform a GET on the thing shadow the following messages will be sent and received: - * 1. A MQTT Publish on the topic - $aws/things/{thingName}/shadow/get - * 2. Subscribe to MQTT topics - $aws/things/{thingName}/shadow/get/accepted and $aws/things/{thingName}/shadow/get/rejected. - * If the request was successful we will receive the things json document in the accepted topic. - * - * - */ -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_json_data.h" - -/*! - * @brief Shadow Initialization parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowIniTParametersDefault to initialize this struct - * - * - * - */ -typedef struct { - char *pHost; ///< This will be unique to a customer and can be retrieved from the console - uint16_t port; ///< By default the port is 8883 - const char *pRootCA; ///< Location with the Filename of the Root CA - const char *pClientCRT; ///< Location of Device certs signed by AWS IoT service - const char *pClientKey; ///< Location of Device private key - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss. -} ShadowInitParameters_t; - -/*! - * @brief Shadow Connect parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowConnectParametersDefault to initialize this struct - * - *d - * - */ -typedef struct { - const char *pMyThingName; ///< Every device has a Thing Shadow and this is the placeholder for name - const char *pMqttClientId; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - uint16_t mqttClientIdLen; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - pApplicationHandler_t deleteActionHandler; ///< Callback to be invoked when Thing shadow for this device is deleted -} ShadowConnectParameters_t; - -/*! - * @brief This is set to defaults from the configuration file - * The certs are set to NULL because they need the path to the file. shadow_sample.c file demonstrates on how to get the relative path - * - * \relates ShadowInitParameters_t - */ -extern const ShadowInitParameters_t ShadowInitParametersDefault; - -/*! - * @brief This is set to defaults from the configuration file - * The length of the client id is initialized as 0. This is due to C language limitations of using constant literals - * only for creating const variables. The client id will be assigned using the value from aws_iot_config.h but the - * length needs to be assigned in code. shadow_sample.c file demonstrates this. - * - * \relates ShadowConnectParameters_t - */ -extern const ShadowConnectParameters_t ShadowConnectParametersDefault; - - -/** - * @brief Initialize the Thing Shadow before use - * - * This function takes care of initializing the internal book-keeping data structures and initializing the IoT client. - * - * @param pClient A new MQTT Client to be used as the protocol layer. Will be initialized with pParams. - * @return An IoT Error Type defining successful/failed Initialization - */ -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, const ShadowInitParameters_t *pParams); - -/** - * @brief Connect to the AWS IoT Thing Shadow service over MQTT - * - * This function does the TLSv1.2 handshake and establishes the MQTT connection - * - * @param pClient MQTT Client used as the protocol layer - * @param pParams Shadow Conenction parameters like TLS cert location - * @return An IoT Error Type defining successful/failed Connection - */ -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, const ShadowConnectParameters_t *pParams); - -/** - * @brief Yield function to let the background tasks of MQTT and Shadow - * - * This function could be use in a separate thread waiting for the incoming messages, ensuring the connection is kept alive with the AWS Service. - * It also ensures the expired requests of Shadow actions are cleared and Timeout callback is executed. - * @note All callbacks ever used in the SDK will be executed in the context of this function. - * - * @param pClient MQTT Client used as the protocol layer - * @param timeout in milliseconds, This is the maximum time the yield function will wait for a message and/or read the messages from the TLS buffer - * @return An IoT Error Type defining successful/failed Yield - */ -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout); - -/** - * @brief Disconnect from the AWS IoT Thing Shadow service over MQTT - * - * This will close the underlying TCP connection, MQTT connection will also be closed - * - * @param pClient MQTT Client used as the protocol layer - * @return An IoT Error Type defining successful/failed disconnect status - */ -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient); - -/** - * @brief Thing Shadow Acknowledgment enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_ACK_TIMEOUT, SHADOW_ACK_REJECTED, SHADOW_ACK_ACCEPTED -} Shadow_Ack_Status_t; - -/** - * @brief Thing Shadow Action type enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_GET, SHADOW_UPDATE, SHADOW_DELETE -} ShadowActions_t; - - -/** - * @brief Function Pointer typedef used as the callback for every action - * - * This function will be called from the context of \c aws_iot_shadow_yield() context - * - * @param pThingName Thing Name of the response received - * @param action The response of the action - * @param status Informs if the action was Accepted/Rejected or Timed out - * @param pReceivedJsonDocument Received JSON document - * @param pContextData the void* data passed in during the action call(update, get or delete) - * - */ -typedef void (*fpActionCallback_t)(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData); - -/** - * @brief This function is the one used to perform an Update action to a Thing Name's Shadow. - * - * update is one of the most frequently used functionality by a device. In most cases the device may be just reporting few params to update the thing shadow in the cloud - * Update Action if no callback or if the JSON document does not have a client token then will just publish the update and not track it. - * - * @note The update has to subscribe to two topics update/accepted and update/rejected. This function waits 2 seconds to ensure the subscriptions are registered before publishing the update message. - * The following steps are performed on using this function: - * 1. Subscribe to Shadow topics - $aws/things/{thingName}/shadow/update/accepted and $aws/things/{thingName}/shadow/update/rejected - * 2. wait for 2 seconds for the subscription to take effect - * 3. Publish on the update topic - $aws/things/{thingName}/shadow/update - * 4. In the \c aws_iot_shadow_yield() function the response will be handled. In case of timeout or if the response is received, the subscription to shadow response topics are un-subscribed from. - * On the contrary if the persistent subscription is set to true then the un-subscribe will not be done. The topics will always be listened to. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the shadow that needs to be Updated - * @param pJsonString The update action expects a JSON document to send. The JSON String should be a null terminated string. This JSON document should adhere to the AWS IoT Thing Shadow specification. To help in the process of creating this document- SDK provides apis in \c aws_iot_shadow_json_data.h - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device updates the same shadow then this should be set to true to avoid repeated subscription and unsubscription. If the Thing Name is one off update then this should be set to false - * @return An IoT Error Type defining successful/failed update action - */ -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Get action to a Thing Name's Shadow. - * - * One use of this function is usually to get the config of a device at boot up. - * It is similar to the Update function internally except it does not take a JSON document as the input. The entire JSON document will be sent over the accepted topic - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the JSON document that is needed - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device gets the same Sahdow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off get then this should be set to false - * @return An IoT Error Type defining successful/failed get action - */ -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Delete action to a Thing Name's Shadow. - * - * This is not a very common use case for device. It is generally the responsibility of the accompanying app to do the delete. - * It is similar to the Update function internally except it does not take a JSON document as the input. The Thing Shadow referred by the ThingName will be deleted. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the Shadow that should be deleted - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device deletes the same Shadow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off delete then this should be set to false - * @return An IoT Error Type defining successful/failed delete action - */ -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscriptions); - -/** - * @brief This function is used to listen on the delta topic of #AWS_IOT_MY_THING_NAME mentioned in the aws_iot_config.h file. - * - * Any time a delta is published the Json document will be delivered to the pStruct->cb. If you don't want the parsing done by the SDK then use the jsonStruct_t key set to "state". A good example of this is displayed in the sample_apps/shadow_console_echo.c - * - * @param pClient MQTT Client used as the protocol layer - * @param pStruct The struct used to parse JSON value - * @return An IoT Error Type defining successful/failed delta registering - */ -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pClient, jsonStruct_t *pStruct); - -/** - * @brief Reset the last received version number to zero. - * This will be useful if the Thing Shadow is deleted and would like to to reset the local version - * @return no return values - * - */ -void aws_iot_shadow_reset_last_received_version(void); - -/** - * @brief Version of a document is received with every accepted/rejected and the SDK keeps track of the last received version of the JSON document of #AWS_IOT_MY_THING_NAME shadow - * - * One exception to this version tracking is that, the SDK will ignore the version from update/accepted topic. Rest of the responses will be scanned to update the version number. - * Accepting version change for update/accepted may cause version conflicts for delta message if the update message is received before the delta. - * - * @return version number of the last received response - * - */ -uint32_t aws_iot_shadow_get_last_received_version(void); - -/** - * @brief Enable the ignoring of delta messages with old version number - * - * As we use MQTT underneath, there could be more than 1 of the same message if we use QoS 0. To avoid getting called for the same message, this functionality should be enabled. All the old message will be ignored - */ -void aws_iot_shadow_enable_discard_old_delta_msgs(void); - -/** - * @brief Disable the ignoring of delta messages with old version number - */ -void aws_iot_shadow_disable_discard_old_delta_msgs(void); - -/** - * @brief This function is used to enable or disable autoreconnect - * - * Any time a disconnect happens the underlying MQTT client attempts to reconnect if this is set to true - * - * @param pClient MQTT Client used as the protocol layer - * @param newStatus The new status to set the autoreconnect option to - * - * @return An IoT Error Type defining successful/failed operation - */ -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus); - -#ifdef __cplusplus -} -#endif - -#endif //AWS_IOT_SDK_SRC_IOT_SHADOW_H_ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h deleted file mode 100644 index a84713ece..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_shadow_json_data.h" - -bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount); - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition); - -void aws_iot_shadow_internal_get_request_json(char *pJsonDocument); - -void aws_iot_shadow_internal_delete_request_json(char *pJsonDocument); - -void resetClientTokenSequenceNum(void); - - -bool isReceivedJsonValid(const char *pJsonDocument); - -void FillWithClientToken(char *pStringToUpdateClientToken); - -bool extractClientToken(const char *pJsonDocumentToBeSent, char *pExtractedClientToken); - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber); - -#ifdef __cplusplus -} -#endif - -#endif // AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h deleted file mode 100644 index deaf9a177..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file aws_iot_shadow_json_data.h - * @brief This file is the interface for all the Shadow related JSON functions. - */ - -#include - -/** - * @brief This is a static JSON object that could be used in code - * - */ -typedef struct jsonStruct jsonStruct_t; - -/** - * @brief Every JSON name value can have a callback. The callback should follow this signature - */ -typedef void (*jsonStructCallback_t)(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t); - -/** - * @brief All the JSON object types enum - * - * JSON number types need to be split into proper integer / floating point data types and sizes on embedded platforms. - */ -typedef enum { - SHADOW_JSON_INT32, - SHADOW_JSON_INT16, - SHADOW_JSON_INT8, - SHADOW_JSON_UINT32, - SHADOW_JSON_UINT16, - SHADOW_JSON_UINT8, - SHADOW_JSON_FLOAT, - SHADOW_JSON_DOUBLE, - SHADOW_JSON_BOOL, - SHADOW_JSON_STRING, - SHADOW_JSON_OBJECT -} JsonPrimitiveType; - -/** - * @brief This is the struct form of a JSON Key value pair - */ -struct jsonStruct { - const char *pKey; ///< JSON key - void *pData; ///< pointer to the data (JSON value) - JsonPrimitiveType type; ///< type of JSON - jsonStructCallback_t cb; ///< callback to be executed on receiving the Key value pair -}; - -/** - * @brief Initialize the JSON document with Shadow expected name/value - * - * This Function will fill the JSON Buffer with a null terminated string. Internally it uses snprintf - * This function should always be used First, followed by iot_shadow_add_reported and/or iot_shadow_add_desired. - * Always finish the call sequence with iot_finalize_json_document - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Add the reported section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "reported":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass teh max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Add the desired section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "desired":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass the max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Finalize the JSON document with Shadow expected client Token. - * - * This function will automatically increment the client token every time this function is called. - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. If the finalized section is not invoked then the JSON doucment will not be valid - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Fill the given buffer with client token for tracking the Repsonse. - * - * This function will add the AWS_IOT_MQTT_CLIENT_ID with a sequence number. Every time this function is used the sequence number gets incremented - * - * - * @param pBufferToBeUpdatedWithClientToken buffer to be updated with the client token string - * @param maxSizeOfJsonDocument maximum size of the pBufferToBeUpdatedWithClientToken that can be used - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h deleted file mode 100644 index 075a726da..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ - -#define SHADOW_CLIENT_TOKEN_STRING "clientToken" -#define SHADOW_VERSION_STRING "version" - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h deleted file mode 100644 index fc2de0322..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_config.h" - - -extern uint32_t shadowJsonVersionNum; -extern bool shadowDiscardOldDeltaFlag; - -extern char myThingName[MAX_SIZE_OF_THING_NAME]; -extern uint16_t myThingNameLen; -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; -extern uint16_t mqttClientIDLen; - -void initializeRecords(AWS_IoT_Client *pClient); -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action); -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky); -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky); - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent); -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds); -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex); -void HandleExpiredResponseCallbacks(void); -void initDeltaTokens(void); -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h deleted file mode 100644 index 1b544d759..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_version.h - * @brief Constants defining the release version of the SDK. - * - * This file contains constants defining the release version of the SDK. - * This file is modified by AWS upon release of the SDK and should not be - * modified by the consumer of the SDK. The provided samples show example - * usage of these constants. - * - * Versioning of the SDK follows the MAJOR.MINOR.PATCH Semantic Versioning guidelines. - * @see http://semver.org/ - */ -#ifndef SRC_UTILS_AWS_IOT_VERSION_H_ -#define SRC_UTILS_AWS_IOT_VERSION_H_ - -/** - * @brief MAJOR version, incremented when incompatible API changes are made. - */ -#define VERSION_MAJOR 2 -/** - * @brief MINOR version when functionality is added in a backwards-compatible manner. - */ -#define VERSION_MINOR 2 -/** - * @brief PATCH version when backwards-compatible bug fixes are made. - */ -#define VERSION_PATCH 1 -/** - * @brief TAG is an (optional) tag appended to the version if a more descriptive verion is needed. - */ -#define VERSION_TAG "" - -#endif /* SRC_UTILS_AWS_IOT_VERSION_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/network_interface.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/network_interface.h deleted file mode 100644 index d3d73c6d6..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/network_interface.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file network_interface.h - * @brief Network interface definition for MQTT client. - * - * Defines an interface to the TLS layer to be used by the MQTT client. - * Starting point for porting the SDK to the networking layer of a new platform. - */ - -#ifndef __NETWORK_INTERFACE_H_ -#define __NETWORK_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "timer_interface.h" -#include "network_platform.h" - -/** - * @brief Network Type - * - * Defines a type for the network struct. See structure definition below. - */ -typedef struct Network Network; - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct { - const char *pRootCALocation; ///< Pointer to string containing the filename (including path) of the root CA file. - const char *pDeviceCertLocation; ///< Pointer to string containing the filename (including path) of the device certificate. - const char *pDevicePrivateKeyLocation; ///< Pointer to string containing the filename (including path) of the device private key file. - const char *pDestinationURL; ///< Pointer to string containing the endpoint of the MQTT service. - uint16_t DestinationPort; ///< Integer defining the connection port of the MQTT service. - uint32_t timeout_ms; ///< Unsigned integer defining the TLS handshake timeout value in milliseconds. - bool ServerVerificationFlag; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended. -} TLSConnectParams; - -/** - * @brief Network Structure - * - * Structure for defining a network connection. - */ -struct Network { - IoT_Error_t (*connect)(Network *, TLSConnectParams *); - - IoT_Error_t (*read)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to read from the network - IoT_Error_t (*write)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to write to the network - IoT_Error_t (*disconnect)(Network *); ///< Function pointer pointing to the network function to disconnect from the network - IoT_Error_t (*isConnected)(Network *); ///< Function pointer pointing to the network function to check if TLS is connected - IoT_Error_t (*destroy)(Network *); ///< Function pointer pointing to the network function to destroy the network object - - TLSConnectParams tlsConnectParams; ///< TLSConnect params structure containing the common connection parameters - TLSDataParams tlsDataParams; ///< TLSData params structure containing the connection data parameters that are specific to the library being used -}; - -/** - * @brief Initialize the TLS implementation - * - * Perform any initialization required by the TLS layer. - * Connects the interface to implementation by setting up - * the network layer function pointers to platform implementations. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param pRootCALocation - Path of the location of the Root CA - * @param pDeviceCertLocation - Path to the location of the Device Cert - * @param pDevicyPrivateKeyLocation - Path to the location of the device private key file - * @param pDestinationURL - The target endpoint to connect to - * @param DestinationPort - The port on the target to connect to - * @param timeout_ms - The value to use for timeout of operation - * @param ServerVerificationFlag - used to decide whether server verification is needed or not - * - * @return IoT_Error_t - successful initialization or TLS error - */ -IoT_Error_t iot_tls_init(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation, - const char *pDevicePrivateKeyLocation, const char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag); - -/** - * @brief Create a TLS socket and open the connection - * - * Creates an open socket connection including TLS handshake. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param TLSParams - TLSConnectParams defines the properties of the TLS connection. - * @return IoT_Error_t - successful connection or TLS error - */ -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams); - -/** - * @brief Write bytes to the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - buffer to write to socket - * @param integer - number of bytes to write - * @param Timer * - operation timer - * @return integer - number of bytes written or TLS error - * @return IoT_Error_t - successful write or TLS error code - */ -IoT_Error_t iot_tls_write(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Read bytes from the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - pointer to buffer where read bytes should be copied - * @param size_t - number of bytes to read - * @param Timer * - operation timer - * @param size_t - pointer to store number of bytes read - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_read(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Disconnect from network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_disconnect(Network *pNetwork); - -/** - * @brief Perform any tear-down or cleanup of TLS layer - * - * Called to cleanup any resources required for the TLS layer. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - successful cleanup or TLS error code - */ -IoT_Error_t iot_tls_destroy(Network *pNetwork); - -/** - * @brief Check if TLS layer is still connected - * - * Called to check if the TLS layer is still connected or not. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - TLS error code indicating status of network physical layer connection - */ -IoT_Error_t iot_tls_is_connected(Network *pNetwork); - -#ifdef __cplusplus -} -#endif - -#endif //__NETWORK_INTERFACE_H_ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h deleted file mode 100644 index b4bc3705d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file threads_interface.h - * @brief Thread interface definition for MQTT client. - * - * Defines an interface that can be used by system components for multithreaded situations. - * Starting point for porting the SDK to the threading hardware layer of a new platform. - */ - -#include "aws_iot_config.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef __THREADS_INTERFACE_H_ -#define __THREADS_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "threads_platform.h" - -#include - -/** - * @brief Mutex Type - * - * Forward declaration of a mutex struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "threads_platform.h". - * - */ -typedef struct _IoT_Mutex_t IoT_Mutex_t; - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * This is a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change. - * This is not a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *); - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *); - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *); - -#ifdef __cplusplus -} -#endif - -#endif /*__THREADS_INTERFACE_H_*/ -#endif /*_ENABLE_THREAD_SUPPORT_*/ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h deleted file mode 100644 index 0bef0fc94..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file timer_interface.h - * @brief Timer interface definition for MQTT client. - * - * Defines an interface to timers that can be used by other system - * components. MQTT client requires timers to handle timeouts and - * MQTT keep alive. - * Starting point for porting the SDK to the timer hardware layer of a new platform. - */ - -#ifndef __TIMER_INTERFACE_H_ -#define __TIMER_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "timer_platform.h" - -#include -#include - -/** - * @brief Timer Type - * - * Forward declaration of a timer struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "timer_.h" and include that file above. - * - */ -typedef struct Timer Timer; - -/** - * @brief Check if a timer is expired - * - * Call this function passing in a timer to check if that timer has expired. - * - * @param Timer - pointer to the timer to be checked for expiration - * @return bool - true = timer expired, false = timer not expired - */ -bool has_timer_expired(Timer *); - -/** - * @brief Create a timer (milliseconds) - * - * Sets the timer to expire in a specified number of milliseconds. - * - * @param Timer - pointer to the timer to be set to expire in milliseconds - * @param uint32_t - set the timer to expire in this number of milliseconds - */ -void countdown_ms(Timer *, uint32_t); - -/** - * @brief Create a timer (seconds) - * - * Sets the timer to expire in a specified number of seconds. - * - * @param Timer - pointer to the timer to be set to expire in seconds - * @param uint32_t - set the timer to expire in this number of seconds - */ -void countdown_sec(Timer *, uint32_t); - -/** - * @brief Check the time remaining on a given timer - * - * Checks the input timer and returns the number of milliseconds remaining on the timer. - * - * @param Timer - pointer to the timer to be set to checked - * @return int - milliseconds left on the countdown timer - */ -uint32_t left_ms(Timer *); - -/** - * @brief Initialize a timer - * - * Performs any initialization required to the timer passed in. - * - * @param Timer - pointer to the timer to be initialized - */ -void init_timer(Timer *); - -#ifdef __cplusplus -} -#endif - -#endif //__TIMER_INTERFACE_H_ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c deleted file mode 100644 index 47a085143..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file timer.c - * @brief Linux implementation of the timer interface. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include "timer_platform.h" - -bool has_timer_expired(Timer *timer) { - struct timeval now, res; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - struct timeval now; -#ifdef __cplusplus - struct timeval interval = {timeout / 1000, static_cast((timeout % 1000) * 1000)}; -#else - struct timeval interval = {timeout / 1000, (int)((timeout % 1000) * 1000)}; -#endif - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -uint32_t left_ms(Timer *timer) { - struct timeval now, res; - uint32_t result_ms = 0; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - if(res.tv_sec >= 0) { - result_ms = (uint32_t) (res.tv_sec * 1000 + res.tv_usec / 1000); - } - return result_ms; -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - struct timeval now; - struct timeval interval = {timeout, 0}; - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -void init_timer(Timer *timer) { - timer->end_time = (struct timeval) {0, 0}; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h deleted file mode 100644 index 1fe5003d4..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ -#define SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file timer_platform.h - */ -#include -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - struct timeval end_time; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c deleted file mode 100644 index 1e2e8e106..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "network_interface.h" -#include "network_platform.h" - - -/* This is the value used for ssl read timeout */ -#define IOT_SSL_READ_TIMEOUT 10 - -/* This defines the value of the debug buffer that gets allocated. - * The value can be altered based on memory constraints - */ -#ifdef ENABLE_IOT_DEBUG -#define MBEDTLS_DEBUG_BUFFER_SIZE 2048 -#endif - -/* - * This is a function to do further verification if needed on the cert received - */ - -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[1024]; - ((void) data); - - IOT_DEBUG("\nVerify requested for (Depth %d):\n", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - IOT_DEBUG("%s", buf); - - if((*flags) == 0) { - IOT_DEBUG(" This certificate has no flags\n"); - } else { - IOT_DEBUG(buf, sizeof(buf), " ! ", *flags); - IOT_DEBUG("%s\n", buf); - } - - return 0; -} - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = 0; - const char *pers = "aws_iot_tls_wrapper"; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char vrfy_buf[512]; - -#ifdef ENABLE_IOT_DEBUG - unsigned char buf[MBEDTLS_DEBUG_BUFFER_SIZE]; -#endif - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - IOT_DEBUG("\n . Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) pers, strlen(pers))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - IOT_DEBUG(" . Loading the CA root certificate ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); - if(ret < 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - IOT_DEBUG(" ok (%d skipped)\n", ret); - - IOT_DEBUG(" . Loading the client cert. and key..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret); - IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - IOT_DEBUG(" ok\n"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - IOT_DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - IOT_ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } IOT_DEBUG(" ok\n"); - - IOT_DEBUG(" . Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != - 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - IOT_DEBUG(" ok\n"); - - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - IOT_DEBUG(" . Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - IOT_ERROR(" Unable to verify the server's certificate. " - "Either it is invalid,\n" - " or you didn't set ca_file or ca_path " - "to an appropriate value.\n" - " Alternatively, you may want to use " - "auth_mode=optional for testing purposes.\n"); - } - return SSL_CONNECTION_ERROR; - } - } - - IOT_DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - IOT_DEBUG(" [ Record expansion is %d ]\n", ret); - } else { - IOT_DEBUG(" [ Record expansion is unknown (compression) ]\n"); - } - - IOT_DEBUG(" . Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - IOT_ERROR(" failed\n"); - mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags); - IOT_ERROR("%s\n", vrfy_buf); - ret = SSL_CONNECTION_ERROR; - } else { - IOT_DEBUG(" ok\n"); - ret = SUCCESS; - } - } else { - IOT_DEBUG(" Server Verification skipped\n"); - ret = SUCCESS; - } - -#ifdef ENABLE_IOT_DEBUG - if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - IOT_DEBUG(" . Peer certificate information ...\n"); - mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - IOT_DEBUG("%s\n", buf); - } -#endif - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT); - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t written_so_far; - bool isErrorFlag = false; - int frags, ret; - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - for(written_so_far = 0, frags = 0; - written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { - while(!has_timer_expired(timer) && - (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - IOT_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - isErrorFlag = true; - break; - } - } - if(isErrorFlag) { - break; - } - } - - *written_len = written_so_far; - - if(isErrorFlag) { - return NETWORK_SSL_WRITE_ERROR; - } else if(has_timer_expired(timer) && written_so_far != len) { - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - size_t rxLen = 0; - int ret; - - while (len > 0) { - // This read will timeout after IOT_SSL_READ_TIMEOUT if there's no data to be read - ret = mbedtls_ssl_read(ssl, pMsg, len); - if (ret > 0) { - rxLen += ret; - pMsg += ret; - len -= ret; - } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) { - return NETWORK_SSL_READ_ERROR; - } - - // Evaluate timeout after the read to make sure read is done at least once - if (has_timer_expired(timer)) { - break; - } - } - - if (len == 0) { - *read_len = rxLen; - return SUCCESS; - } - - if (rxLen == 0) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h deleted file mode 100644 index c2810a1c8..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#include "mbedtls/config.h" - -#include "mbedtls/platform.h" -#include "mbedtls/net.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h deleted file mode 100644 index 8a520c637..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_interface.h" -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef IOTSDKC_THREADS_PLATFORM_H_H -#define IOTSDKC_THREADS_PLATFORM_H_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - pthread_mutex_t lock; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* IOTSDKC_THREADS_PLATFORM_H_H */ -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c deleted file mode 100644 index 65a310fb0..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_platform.h" -#ifdef _ENABLE_THREAD_SUPPORT_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_init(&(pMutex->lock), NULL)) { - return MUTEX_INIT_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_lock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_trylock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_unlock(&(pMutex->lock))) { - return MUTEX_UNLOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_destroy(&(pMutex->lock))) { - return MUTEX_DESTROY_ERROR; - } - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/README.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/README.md deleted file mode 100644 index 7ac0fa5e3..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/README.md +++ /dev/null @@ -1,42 +0,0 @@ -## Overview -This folder contains several samples that demonstrate various SDK functions. The Readme file also includes a walk-through of the subscribe publish sample to explain how the SDK is used. The samples are currently provided with Makefiles for building them on linux. For each sample: - - * Explore the makefile. The makefile for each sample provides a reference on how to set up makefiles for client applications - * Explore the example. It connects to AWS IoT platform using MQTT and demonstrates few actions that can be performed by the SDK - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in location referenced in the example (certs/) - * Ensure you have [created a thing](https://docs.aws.amazon.com/iot/latest/developerguide/create-thing.html) through your AWS IoT Console with name matching the definition AWS_IOT_MY_THING_NAME in the `aws_iot_config.h` file - * Place device identity cert and private key in locations referenced in the example (certs/) - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Build the example using make (`make`) - * Run sample application (./subscribe_publish_sample or ./shadow_sample). The sample will print status messages to stdout - * All samples are written in C unless otherwise mentioned. The following sample applications are included: - * `subscribe_publish_sample` - a simple pub/sub MQTT example - * `subscribe_publish_cpp_sample` - a simple pub/sub MQTT example written in C++ - * `subscribe_publish_library_sample` - a simple pub/sub MQTT example which builds the SDK as a separate library - * `shadow_sample` - a simple device shadow example using a connected window example - * `shadow_sample_console_echo` - a sample to work with the AWS IoT Console interactive guide - -## Subscribe Publish Sample -This is a simple pub/sub MQTT example. It connects a single MQTT client to the server and subscribes to a test topic. Then it proceeds to publish messages on this topic and yields after each publish to ensure that the message was received. - - * The sample first creates an instance of the AWS_IoT_Client - * The next step is to initialize the client. The aws_iot_mqtt_init API is called for this purpose. The API takes the client instance and an IoT_Client_Init_Params variable to set the initial values for the client. The Init params include values like host URL, port, certificates, disconnect handler etc. - * If the call to the init API was successful, we can proceed to call connect. The API is called aws_iot_mqtt_connect. It takes the client instance and IoT_Client_Connect_Params variable as arguments. The IoT_Client_Connect_Params is optional after the first call to connect as the client retains the original values that were provided to support reconnect. The Connect params include values like Client Id, MQTT Version etc. - * If the connect API call was successful, we can proceed to subscribe and publish on this connect. The connect API call will return an error code, specific to the type of error that occurred, in case the call fails. - * It is important to remember here that there is no dynamic memory allocation in the SDK. Any values that are passed as a pointer to the APIs should not be freed unless they are not required any further. For example, if the variable that stores the certificate path is freed after the init call is made, the connect call will fail. Similarly, if it is freed after the connect API returns success, any future connect calls (including reconnects) will fail. - * The next step for this sample is to subscribe to the test topic. The API to be called for subscribe is aws_iot_mqtt_subscribe. It takes as arguments, the IoT Client instance, topic name, the length of the topic name, QoS, the subscribe callback handler and an optional pointer to some data to be returned to the subscribe handler - * The next step it to call the publish API to send a message on the test topic. The sample sends two different messages, one QoS0 and one QoS1. The - * The publish API takes the client instance, topic name to publish to, topic name length and a variable of type IoT_Publish_Message_Params. The IoT_Publish_Message_Params contains the payload, length of the payload and QoS. - * If the publish API calls are successful, the sample proceeds to call the yield API. The yield API takes the client instance and a timeout value in milliseconds as arguments. - * The yield API is called to let the SDK process any incoming messages. It also periodically sends out the PING request to prevent disconnect and, if enabled, it also performs auto-reconnect and resubscribe. - * The yield API should be called periodically to process the PING request as well as read any messages in the receive buffer. It should be called once at least every TTL/2 time periods to ensure disconnect does not happen. There can only be one yield in progress at a time. Therefore, in multi-threaded scenarios one thread can be a dedicated yield thread while other threads handle other operations. - * The sample sends out messages equal to the value set in publish count unless infinite publishing flag is set - -For further information on each API please read the API documentation. - -## Subscribe Publish Cpp Sample -This is the same sample as above but it is built using a C++ compiler. It demonstrates how the SDK can be used in a C++ program. - -## Subscribe Publish Library Sample -This is also the same code as the Subscribe Publish sample. In this case, the SDK is built as a separate library and then used in the sample program. \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile deleted file mode 100644 index 6199b0484..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h deleted file mode 100644 index 62abce4a2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c deleted file mode 100644 index 9a0b270be..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file shadow_sample.c - * @brief A simple connected window example demonstrating the use of Thing Shadow - */ - -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/*! - * The goal of this sample application is to demonstrate the capabilities of shadow. - * This device(say Connected Window) will open the window of a room based on temperature - * It can report to the Shadow the following parameters: - * 1. temperature of the room (double) - * 2. status of the window (open or close) - * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] - * - * The two variables from a device's perspective are double temperature and bool windowOpen - * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback - The Json Document in the cloud will be - { - "reported": { - "temperature": 0, - "windowOpen": false - }, - "desired": { - "windowOpen": false - } - } - */ - -#define ROOMTEMPERATURE_UPPERLIMIT 32.0f -#define ROOMTEMPERATURE_LOWERLIMIT 25.0f -#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -static char certDirectory[PATH_MAX + 1] = "../../../certs"; -static char HostAddress[255] = AWS_IOT_MQTT_HOST; -static uint32_t port = AWS_IOT_MQTT_PORT; -static uint8_t numPubs = 5; - -static void simulateRoomTemperature(float *pRoomTemperature) { - static float deltaChange; - - if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { - deltaChange = -0.5f; - } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { - deltaChange = 0.5f; - } - - *pRoomTemperature += deltaChange; -} - -void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} - -void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - IOT_UNUSED(pJsonString); - IOT_UNUSED(JsonStringDataLen); - - if(pContext != NULL) { - IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData)); - } -} - -void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) { - switch(opt) { - case 'h': - strcpy(HostAddress, optarg); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strcpy(certDirectory, optarg); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'n': - numPubs = atoi(optarg); - IOT_DEBUG("num pubs %s", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - IoT_Error_t rc = FAILURE; - int32_t i = 0; - - char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; - size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); - char *pJsonStringToUpdate; - float temperature = 0.0; - - bool windowOpen = false; - jsonStruct_t windowActuator; - windowActuator.cb = windowActuate_Callback; - windowActuator.pData = &windowOpen; - windowActuator.pKey = "windowOpen"; - windowActuator.type = SHADOW_JSON_BOOL; - - jsonStruct_t temperatureHandler; - temperatureHandler.cb = NULL; - temperatureHandler.pKey = "temperature"; - temperatureHandler.pData = &temperature; - temperatureHandler.type = SHADOW_JSON_FLOAT; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); - - if(SUCCESS != rc) { - IOT_ERROR("Shadow Register Delta Error"); - } - temperature = STARTING_ROOMTEMPERATURE; - - // loop and publish a change in temperature - while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - rc = aws_iot_shadow_yield(&mqttClient, 200); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - IOT_INFO("\n=======================================================================================\n"); - IOT_INFO("On Device: window state %s", windowOpen ? "true" : "false"); - simulateRoomTemperature(&temperature); - - rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, - &windowActuator); - if(SUCCESS == rc) { - rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - IOT_INFO("Update Shadow: %s", JsonDocumentBuffer); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer, - ShadowUpdateStatusCallback, NULL, 4, true); - } - } - } - IOT_INFO("*****************************************************************************************\n"); - sleep(1); - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if(SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile deleted file mode 100644 index 8447901d8..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_console_echo -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(MQTT_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(MQTT_SRC_FILES) -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) - -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h deleted file mode 100644 index 62abce4a2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c deleted file mode 100644 index 1c491fbd5..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/** - * @file shadow_console_echo.c - * @brief Echo received Delta message - * - * This application will echo the message received in delta, as reported. - * for example: - * Received Delta message - * { - * "state": { - * "switch": "on" - * } - * } - * This delta message means the desired switch position has changed to "on" - * - * This application will take this delta message and publish it back as the reported message from the device. - * { - * "state": { - * "reported": { - * "switch": "on" - * } - * } - * } - * - * This update message will remove the delta that was created. If this message was not removed then the AWS IoT Thing Shadow is going to always have a delta and keep sending delta any time an update is applied to the Shadow - * This example will not use any of the json builder/helper functions provided in the aws_iot_shadow_json_data.h. - * @note Ensure the buffer sizes in aws_iot_config.h are big enough to receive the delta message. The delta message will also contain the metadata with the timestamps - */ - -char certDirectory[PATH_MAX + 1] = "../../../certs"; -char HostAddress[255] = AWS_IOT_MQTT_HOST; -uint32_t port = AWS_IOT_MQTT_PORT; -bool messageArrivedOnDelta = false; - -/* - * @note The delta message is always sent on the "state" key in the json - * @note Any time messages are bigger than AWS_IOT_MQTT_RX_BUF_LEN the underlying MQTT library will ignore it. The maximum size of the message that can be received is limited to the AWS_IOT_MQTT_RX_BUF_LEN - */ -char stringToEchoDelta[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - -// Helper functions -void parseInputArgsForConnectParams(int argc, char** argv); - -// Shadow Callback for receiving the delta -void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t); - -void UpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData); - -int main(int argc, char** argv) { - IoT_Error_t rc = SUCCESS; - int32_t i = 0; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc){ - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - jsonStruct_t deltaObject; - deltaObject.pData = stringToEchoDelta; - deltaObject.pKey = "state"; - deltaObject.type = SHADOW_JSON_OBJECT; - deltaObject.cb = DeltaCallback; - - /* - * Register the jsonStruct object - */ - rc = aws_iot_shadow_register_delta(&mqttClient, &deltaObject); - - // Now wait in the loop to receive any message sent from the console - while (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - /* - * Lets check for the incoming messages for 200 ms. - */ - rc = aws_iot_shadow_yield(&mqttClient, 200); - - if (NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - if (messageArrivedOnDelta) { - IOT_INFO("\nSending delta message back %s\n", stringToEchoDelta); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, stringToEchoDelta, UpdateStatusCallback, NULL, 2, true); - messageArrivedOnDelta = false; - } - - // sleep for some time in seconds - sleep(1); - } - - if (SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if (SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} -/** - * @brief This function builds a full Shadow expected JSON document by putting the data in the reported section - * - * @param pJsonDocument Buffer to be filled up with the JSON data - * @param maxSizeOfJsonDocument maximum size of the buffer that could be used to fill - * @param pReceivedDeltaData This is the data that will be embedded in the reported section of the JSON document - * @param lengthDelta Length of the data - */ -bool buildJSONForReported(char *pJsonDocument, size_t maxSizeOfJsonDocument, const char *pReceivedDeltaData, uint32_t lengthDelta) { - int32_t ret; - - if (NULL == pJsonDocument) { - return false; - } - - char tempClientTokenBuffer[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - if(aws_iot_fill_with_client_token(tempClientTokenBuffer, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE) != SUCCESS){ - return false; - } - - ret = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{\"reported\":%.*s}, \"clientToken\":\"%s\"}", lengthDelta, pReceivedDeltaData, tempClientTokenBuffer); - - if (ret >= maxSizeOfJsonDocument || ret < 0) { - return false; - } - - return true; -} - -void parseInputArgsForConnectParams(int argc, char** argv) { - int opt; - - while (-1 != (opt = getopt(argc, argv, "h:p:c:"))) { - switch (opt) { - case 'h': - strcpy(HostAddress, optarg); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strcpy(certDirectory, optarg); - IOT_DEBUG("cert root directory %s", optarg); - break; - case '?': - if (optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if (isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - - -void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t) { - IOT_UNUSED(pJsonStruct_t); - - IOT_DEBUG("Received Delta message %.*s", valueLength, pJsonValueBuffer); - - if (buildJSONForReported(stringToEchoDelta, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonValueBuffer, valueLength)) { - messageArrivedOnDelta = true; - } -} - -void UpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/Makefile deleted file mode 100644 index 9f604348f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = g++ - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_cpp_sample -APP_SRC_FILES = $(APP_NAME).cpp - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED -COMPILER_FLAGS += -std=c++0x - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/aws_iot_config.h deleted file mode 100644 index 62abce4a2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/aws_iot_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/subscribe_publish_cpp_sample.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/subscribe_publish_cpp_sample.cpp deleted file mode 100644 index 20fee197f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_cpp_sample/subscribe_publish_cpp_sample.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file subscribe_publish_cpp_sample.cpp - * @brief simple MQTT publish and subscribe on the same topic in C++ - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -/** - * @brief Default cert location - */ -char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -uint32_t publishCount = 0; - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strcpy(HostAddress, optarg); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strcpy(certDirectory, optarg); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile deleted file mode 100644 index bad284924..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_library_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(APP_NAME).c $(COMPILER_FLAGS) -o $(APP_NAME) -L. -lAwsIotSdk $(LD_FLAG) $(INCLUDE_ALL_DIRS) - -all: libAwsIotSdk.a - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -libAwsIotSdk.a: $(SRC_FILES:.c=.o) - ar rcs $@ $^ - -%.o : %.c - $(CC) -c $< -o $@ $(COMPILER_FLAGS) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - rm -f $(APP_DIR)/libAwsIotSdk.a - $(MBED_TLS_MAKE_CMD) clean diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h deleted file mode 100644 index 62abce4a2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c deleted file mode 100644 index b4c292936..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file subscribe_publish_library_sample.c - * @brief simple MQTT publish and subscribe on the same topic using the SDK as a library - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -/** - * @brief Default cert location - */ -char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -uint32_t publishCount = 0; - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strcpy(HostAddress, optarg); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strcpy(certDirectory, optarg); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile deleted file mode 100644 index 4b3239106..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h deleted file mode 100644 index 62abce4a2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c deleted file mode 100644 index 5d4e968dd..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -/** - * @brief Default cert location - */ -char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -uint32_t publishCount = 0; - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strcpy(HostAddress, optarg); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strcpy(certDirectory, optarg); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - if(publishCount == 0 && !infinitePublishFlag) { - break; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - // Wait for all the messages to be received - aws_iot_mqtt_yield(&client, 100); - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c deleted file mode 100644 index 1614eb26f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_json_utils.c - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_json_utils.h" - -#include -#include -#include - -#ifdef __cplusplus -#include -#else - -#include - -#endif - -#include "aws_iot_log.h" - -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if(tok->type == JSMN_STRING) { - if((int) strlen(s) == tok->end - tok->start) { - if(strncmp(json + tok->start, s, (size_t) (tok->end - tok->start)) == 0) { - return 0; - } - } - } - return -1; -} - -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu32, i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu16, i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - uint32_t i_word; - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu32, &i_word))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - if (i_word > UINT8_MAX) { - IOT_WARN("Token value %u exceeds 8 bits", i_word); - return JSON_PARSE_ERROR; - } - *i = i_word; - - return SUCCESS; -} - -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%" SCNi32, i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - int32_t i_word; - if(1 != sscanf(jsonString + token->start, "%" SCNi32, &i_word)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - if(i_word < INT16_MIN || i_word > INT16_MAX) { - IOT_WARN("Token value %d out of range for 16-bit int", i_word); - return JSON_PARSE_ERROR; - } - *i = i_word; - - return SUCCESS; -} - -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - int32_t i_word; - if(1 != sscanf(jsonString + token->start, "%" SCNi32, &i_word)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - if(i_word < INT8_MIN || i_word > INT8_MAX) { - IOT_WARN("Token value %d out of range for 8-bit int", i_word); - return JSON_PARSE_ERROR; - } - *i = i_word; - - return SUCCESS; -} - -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%f", f)) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%lf", d)) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a primitive."); - return JSON_PARSE_ERROR; - } - if(jsonString[token->start] == 't' && jsonString[token->start + 1] == 'r' && jsonString[token->start + 2] == 'u' - && jsonString[token->start + 3] == 'e') { - *b = true; - } else if(jsonString[token->start] == 'f' && jsonString[token->start + 1] == 'a' - && jsonString[token->start + 2] == 'l' && jsonString[token->start + 3] == 's' - && jsonString[token->start + 4] == 'e') { - *b = false; - } else { - IOT_WARN("Token was not a bool."); - return JSON_PARSE_ERROR; - } - return SUCCESS; -} - -IoT_Error_t parseStringValue(char *buf, const char *jsonString, jsmntok_t *token) { - uint16_t size = 0; - if(token->type != JSMN_STRING) { - IOT_WARN("Token was not a string."); - return JSON_PARSE_ERROR; - } - size = (uint16_t) (token->end - token->start); - memcpy(buf, jsonString + token->start, size); - buf[size] = '\0'; - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c deleted file mode 100644 index 5ea0f75ba..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c +++ /dev/null @@ -1,327 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.c - * @brief MQTT client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_log.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -#define SDK_METRICS_LEN 25 -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -const IoT_Client_Init_Params iotClientInitParamsDefault = IoT_Client_Init_Params_initializer; -const IoT_MQTT_Will_Options iotMqttWillOptionsDefault = IoT_MQTT_Will_Options_Initializer; -const IoT_Client_Connect_Params iotClientConnectParamsDefault = IoT_Client_Connect_Params_initializer; - -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - return CLIENT_STATE_INVALID; - } - - FUNC_EXIT_RC(pClient->clientStatus.clientState); -} - -#ifdef _ENABLE_THREAD_SUPPORT_ -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - FUNC_ENTRY; - IoT_Error_t threadRc = FAILURE; - - if(NULL == pClient || NULL == pMutex){ - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == pClient->clientData.isBlockOnThreadLockEnabled) { - threadRc = aws_iot_thread_mutex_trylock(pMutex); - } else { - threadRc = aws_iot_thread_mutex_lock(pMutex); - /* Should never return Error because the above request blocks until lock is obtained */ - } - - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - if(NULL == pClient || NULL == pMutex) { - return NULL_VALUE_ERROR; - } - IOT_UNUSED(pClient); - return aws_iot_thread_mutex_unlock(pMutex); -} -#endif - -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState) { - IoT_Error_t rc; -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc = FAILURE; -#endif - - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - rc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS != rc) { - return rc; - } -#endif - if(expectedCurrentState == aws_iot_mqtt_get_client_state(pClient)) { - pClient->clientStatus.clientState = newState; - rc = SUCCESS; - } else { - rc = MQTT_UNEXPECTED_CLIENT_STATE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS == rc && SUCCESS != threadRc) { - rc = threadRc; - } -#endif - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pNewConnectParams) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pNewConnectParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.options.isWillMsgPresent = pNewConnectParams->isWillMsgPresent; - pClient->clientData.options.MQTTVersion = pNewConnectParams->MQTTVersion; - pClient->clientData.options.pClientID = pNewConnectParams->pClientID; - pClient->clientData.options.clientIDLen = pNewConnectParams->clientIDLen; -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - pClient->clientData.options.pUsername = (char*)&pUsernameTemp[0]; - pClient->clientData.options.usernameLen = strlen(pUsernameTemp); -#else - pClient->clientData.options.pUsername = pNewConnectParams->pUsername; - pClient->clientData.options.usernameLen = pNewConnectParams->usernameLen; -#endif - pClient->clientData.options.pPassword = pNewConnectParams->pPassword; - pClient->clientData.options.passwordLen = pNewConnectParams->passwordLen; - pClient->clientData.options.will.pTopicName = pNewConnectParams->will.pTopicName; - pClient->clientData.options.will.topicNameLen = pNewConnectParams->will.topicNameLen; - pClient->clientData.options.will.pMessage = pNewConnectParams->will.pMessage; - pClient->clientData.options.will.msgLen = pNewConnectParams->will.msgLen; - pClient->clientData.options.will.qos = pNewConnectParams->will.qos; - pClient->clientData.options.will.isRetained = pNewConnectParams->will.isRetained; - pClient->clientData.options.keepAliveIntervalInSec = pNewConnectParams->keepAliveIntervalInSec; - pClient->clientData.options.isCleanSession = pNewConnectParams->isCleanSession; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, const IoT_Client_Init_Params *pInitParams) { - uint32_t i; - IoT_Error_t rc; - IoT_Client_Connect_Params default_options = IoT_Client_Connect_Params_initializer; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || 0 == pInitParams->port || - NULL == pInitParams->pRootCALocation || NULL == pInitParams->pDevicePrivateKeyLocation || - NULL == pInitParams->pDeviceCertLocation) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - pClient->clientData.messageHandlers[i].topicName = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandler = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandlerData = NULL; - pClient->clientData.messageHandlers[i].qos = QOS0; - } - - pClient->clientData.packetTimeoutMs = pInitParams->mqttPacketTimeout_ms; - pClient->clientData.commandTimeoutMs = pInitParams->mqttCommandTimeout_ms; - pClient->clientData.writeBufSize = AWS_IOT_MQTT_TX_BUF_LEN; - pClient->clientData.readBufSize = AWS_IOT_MQTT_RX_BUF_LEN; - pClient->clientData.counterNetworkDisconnected = 0; - pClient->clientData.disconnectHandler = pInitParams->disconnectHandler; - pClient->clientData.disconnectHandlerData = pInitParams->disconnectHandlerData; - pClient->clientData.nextPacketId = 1; - - /* Initialize default connection options */ - rc = aws_iot_mqtt_set_connect_params(pClient, &default_options); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - pClient->clientData.isBlockOnThreadLockEnabled = pInitParams->isBlockOnThreadLockEnabled; - rc = aws_iot_thread_mutex_init(&(pClient->clientData.state_change_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_read_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } -#endif - - pClient->clientStatus.isPingOutstanding = 0; - pClient->clientStatus.isAutoReconnectEnabled = pInitParams->enableAutoReconnect; - - rc = iot_tls_init(&(pClient->networkStack), pInitParams->pRootCALocation, pInitParams->pDeviceCertLocation, - pInitParams->pDevicePrivateKeyLocation, pInitParams->pHostURL, pInitParams->port, - pInitParams->tlsHandshakeTimeout_ms, pInitParams->isSSLHostnameVerify); - - if(SUCCESS != rc) { - pClient->clientStatus.clientState = CLIENT_STATE_INVALID; - FUNC_EXIT_RC(rc); - } - - init_timer(&(pClient->pingTimer)); - init_timer(&(pClient->reconnectDelayTimer)); - - pClient->clientStatus.clientState = CLIENT_STATE_INITIALIZED; - - FUNC_EXIT_RC(SUCCESS); -} - -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient) { - return pClient->clientData.nextPacketId = (uint16_t) ((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : ( - pClient->clientData.nextPacketId + 1)); -} - -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) { - bool isConnected; - - FUNC_ENTRY; - - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - switch(pClient->clientStatus.clientState) { - case CLIENT_STATE_INVALID: - case CLIENT_STATE_INITIALIZED: - case CLIENT_STATE_CONNECTING: - isConnected = false; - break; - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - isConnected = true; - break; - case CLIENT_STATE_DISCONNECTING: - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - default: - isConnected = false; - break; - } - - FUNC_EXIT_RC(isConnected); -} - -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - FUNC_EXIT_RC(pClient->clientStatus.isAutoReconnectEnabled); -} - -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus) { - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - pClient->clientStatus.isAutoReconnectEnabled = newStatus; - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pDisconnectHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.disconnectHandler = pDisconnectHandler; - pClient->clientData.disconnectHandlerData = pDisconnectHandlerData; - FUNC_EXIT_RC(SUCCESS); -} - -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient) { - return pClient->clientData.counterNetworkDisconnected; -} - -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient) { - pClient->clientData.counterNetworkDisconnected = 0; -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c deleted file mode 100644 index 26e28655d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c +++ /dev/null @@ -1,687 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Sergio R. Caprile - non-blocking packet read functions for stream transport - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.c - * @brief MQTT client internal API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_common_internal.h" - -/* Max length of packet header */ -#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 - -/** - * Encodes the message length according to the MQTT algorithm - * @param buf the buffer into which the encoded data is written - * @param length the length to be encoded - * @return the number of bytes written to buffer - */ -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length) { - size_t outLen = 0; - unsigned char encodedByte; - - FUNC_ENTRY; - do { - encodedByte = (unsigned char) (length % 128); - length /= 128; - /* if there are more digits to encode, set the top bit of this digit */ - if(length > 0) { - encodedByte |= 0x80; - } - buf[outLen++] = encodedByte; - } while(length > 0); - - FUNC_EXIT_RC(outLen); -} - -/** - * Decodes the message length according to the MQTT algorithm - * @param the buffer containing the message - * @param value the decoded length returned - * @return the number of bytes read from the socket - */ -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen) { - unsigned char encodedByte; - uint32_t multiplier, len; - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *decodedLen = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - encodedByte = *buf; - buf++; - *decodedLen += (encodedByte & 127) * multiplier; - multiplier *= 128; - } while((encodedByte & 128) != 0); - - *readBytesLen = len; - - FUNC_EXIT_RC(SUCCESS); -} - -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len) { - rem_len += 1; /* header byte */ - /* now remaining_length field (MQTT 3.1.1 - 2.2.3)*/ - if(rem_len < 128) { - rem_len += 1; - } else if(rem_len < 16384) { - rem_len += 2; - } else if(rem_len < 2097152) { - rem_len += 3; - } else { - rem_len += 4; - } - return rem_len; -} - -/** - * Calculates uint16 packet id from two bytes read from the input buffer - * Checks Endianness at runtime - * - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the value calculated - */ -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr) { - unsigned char *ptr = *pptr; - uint16_t len = 0; - uint8_t firstByte = (uint8_t) (*ptr); - uint8_t secondByte = (uint8_t) (*(ptr + 1)); - len = (uint16_t) (secondByte + (256 * firstByte)); - - *pptr += 2; - return len; -} - -/** - * Writes an integer as 2 bytes to an output buffer. - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param anInt the integer to write - */ -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt) { - **pptr = (unsigned char) (anInt / 256); - (*pptr)++; - **pptr = (unsigned char) (anInt % 256); - (*pptr)++; -} - -/** - * Reads one character from the input buffer. - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the character read - */ -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr) { - unsigned char c = **pptr; - (*pptr)++; - return c; -} - -/** - * Writes one character to an output buffer. - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param c the character to write - */ -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c) { - **pptr = c; - (*pptr)++; -} - -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen) { - /* Nothing that calls this function will have a stringLen with a size larger than 2 bytes (MQTT 3.1.1 - 1.5.3) */ - aws_iot_mqtt_internal_write_uint_16(pptr, stringLen); - if(stringLen > 0) { - memcpy(*pptr, string, stringLen); - *pptr += stringLen; - } -} - -/** - * Initialize the MQTTHeader structure. Used to ensure that Header bits are - * always initialized using the proper mappings. No Endianness issues here since - * the individual fields are all less than a byte. Also generates no warnings since - * all fields are initialized using hex constants - */ -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained) { - FUNC_ENTRY; - - if(NULL == pHeader) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Set all bits to zero */ - pHeader->byte = 0; - uint8_t type = 0; - switch(message_type) { - case UNKNOWN: - /* Should never happen */ - return FAILURE; - case CONNECT: - type = 0x01; - break; - case CONNACK: - type = 0x02; - break; - case PUBLISH: - type = 0x03; - break; - case PUBACK: - type = 0x04; - break; - case PUBREC: - type = 0x05; - break; - case PUBREL: - type = 0x06; - break; - case PUBCOMP: - type = 0x07; - break; - case SUBSCRIBE: - type = 0x08; - break; - case SUBACK: - type = 0x09; - break; - case UNSUBSCRIBE: - type = 0x0A; - break; - case UNSUBACK: - type = 0x0B; - break; - case PINGREQ: - type = 0x0C; - break; - case PINGRESP: - type = 0x0D; - break; - case DISCONNECT: - type = 0x0E; - break; - default: - /* Should never happen */ - FUNC_EXIT_RC(FAILURE); - } - - pHeader->byte = type << 4; - pHeader->byte |= dup << 3; - - switch(qos) { - case QOS0: - break; - case QOS1: - pHeader->byte |= 1 << 1; - break; - default: - /* Using QOS0 as default */ - break; - } - - pHeader->byte |= (1 == retained) ? 0x01 : 0x00; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer) { - - size_t sentLen, sent; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(length >= pClient->clientData.writeBufSize) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - rc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } -#endif - - sentLen = 0; - sent = 0; - - while(sent < length && !has_timer_expired(pTimer)) { - rc = pClient->networkStack.write(&(pClient->networkStack), - &pClient->clientData.writeBuf[sent], - (length - sent), - pTimer, - &sentLen); - if(SUCCESS != rc) { - /* there was an error writing the data */ - break; - } - sent += sentLen; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - rc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } -#endif - - if(sent == length) { - /* record the fact that we have successfully sent the packet */ - //countdown_sec(&c->pingTimer, c->clientData.keepAliveInterval); - FUNC_EXIT_RC(SUCCESS); - } - - FUNC_EXIT_RC(FAILURE); -} - -static IoT_Error_t _aws_iot_mqtt_internal_decode_packet_remaining_len(AWS_IoT_Client *pClient, - size_t *rem_len, Timer *pTimer) { - unsigned char encodedByte; - size_t multiplier, len; - IoT_Error_t rc; - - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *rem_len = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - - rc = pClient->networkStack.read(&(pClient->networkStack), &encodedByte, 1, pTimer, &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - *rem_len += ((encodedByte & 127) * multiplier); - multiplier *= 128; - } while((encodedByte & 128) != 0); - - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - size_t len, rem_len, total_bytes_read, bytes_to_be_read, read_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - Timer packetTimer; - init_timer(&packetTimer); - countdown_ms(&packetTimer, pClient->clientData.packetTimeoutMs); - - rem_len = 0; - total_bytes_read = 0; - bytes_to_be_read = 0; - read_len = 0; - - rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf, 1, pTimer, &read_len); - /* 1. read the header byte. This has the packet type in it */ - if(NETWORK_SSL_NOTHING_TO_READ == rc) { - return MQTT_NOTHING_TO_READ; - } else if(SUCCESS != rc) { - return rc; - } - - len = 1; - - /* Use the constant packet receive timeout, instead of the variable (remaining) pTimer time, to - * determine packet receiving timeout. This is done so we don't prematurely time out packet receiving - * if the remaining time in pTimer is too short. - */ - pTimer = &packetTimer; - - /* 2. read the remaining length. This is variable in itself */ - rc = _aws_iot_mqtt_internal_decode_packet_remaining_len(pClient, &rem_len, pTimer); - if(SUCCESS != rc) { - return rc; - } - - /* if the buffer is too short then the message will be dropped silently */ - if(rem_len >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - do { - rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf, bytes_to_be_read, - pTimer, &read_len); - if(SUCCESS == rc) { - total_bytes_read += read_len; - if((rem_len - total_bytes_read) >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - } else { - bytes_to_be_read = rem_len - total_bytes_read; - } - } - } while(total_bytes_read < rem_len && SUCCESS == rc); - return MQTT_RX_BUFFER_TOO_SHORT_ERROR; - } - - /* put the original remaining length into the read buffer */ - len += aws_iot_mqtt_internal_write_len_to_buffer(pClient->clientData.readBuf + 1, (uint32_t) rem_len); - - /* 3. read the rest of the buffer using a callback to supply the rest of the data */ - if(rem_len > 0) { - rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf + len, rem_len, pTimer, - &read_len); - if(SUCCESS != rc || read_len != rem_len) { - return FAILURE; - } - } - - header.byte = pClient->clientData.readBuf[0]; - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - FUNC_EXIT_RC(rc); -} - -// assume topic filter and name is in correct format -// # can only be at end -// + and # can only be next to separator -static bool _aws_iot_mqtt_internal_is_topic_matched(char *pTopicFilter, char *pTopicName, uint16_t topicNameLen) { - - char *curf, *curn, *curn_end; - - if(NULL == pTopicFilter || NULL == pTopicName) { - return false; - } - - curf = pTopicFilter; - curn = pTopicName; - curn_end = curn + topicNameLen; - - while(*curf && (curn < curn_end)) { - if(*curn == '/' && *curf != '/') { - break; - } - if(*curf != '+' && *curf != '#' && *curf != *curn) { - break; - } - if(*curf == '+') { - /* skip until we meet the next separator, or end of string */ - char *nextpos = curn + 1; - while(nextpos < curn_end && *nextpos != '/') - nextpos = ++curn + 1; - } else if(*curf == '#') { - /* skip until end of string */ - curn = curn_end - 1; - } - - curf++; - curn++; - }; - - return (curn == curn_end) && (*curf == '\0'); -} - -static IoT_Error_t _aws_iot_mqtt_internal_deliver_message(AWS_IoT_Client *pClient, char *pTopicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *pMessageParams) { - uint32_t itr; - IoT_Error_t rc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pTopicName) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* This function can be called from all MQTT APIs - * But while callback return is in progress, Yield should not be called. - * The state for CB_RETURN accomplishes that, as yield cannot be called while in that state */ - clientState = aws_iot_mqtt_get_client_state(pClient); - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN); - - /* Find the right message handler - indexed by topic */ - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++itr) { - if(NULL != pClient->clientData.messageHandlers[itr].topicName) { - if(((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen) - && - (strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0)) - || _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName, - pTopicName, topicNameLen)) { - if(NULL != pClient->clientData.messageHandlers[itr].pApplicationHandler) { - pClient->clientData.messageHandlers[itr].pApplicationHandler(pClient, pTopicName, topicNameLen, - pMessageParams, - pClient->clientData.messageHandlers[itr].pApplicationHandlerData); - } - } - } - } - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN, clientState); - - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_handle_publish(AWS_IoT_Client *pClient, Timer *pTimer) { - char *topicName; - uint16_t topicNameLen; - uint32_t len; - IoT_Error_t rc; - IoT_Publish_Message_Params msg; - - FUNC_ENTRY; - - topicName = NULL; - topicNameLen = 0; - len = 0; - - rc = aws_iot_mqtt_internal_deserialize_publish(&msg.isDup, &msg.qos, &msg.isRetained, - &msg.id, &topicName, &topicNameLen, - (unsigned char **) &msg.payload, &msg.payloadLen, - pClient->clientData.readBuf, - pClient->clientData.readBufSize); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_internal_deliver_message(pClient, topicName, topicNameLen, &msg); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - if(QOS0 == msg.qos) { - /* No further processing required for QoS0 */ - FUNC_EXIT_RC(SUCCESS); - } - - /* Message assumed to be QoS1 since we do not support QoS2 at this time */ - rc = aws_iot_mqtt_internal_serialize_ack(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - PUBACK, 0, msg.id, &len); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_send_packet(pClient, len, pTimer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - IoT_Error_t rc; - -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc; -#endif - - if(NULL == pClient || NULL == pTimer) { - return NULL_VALUE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } -#endif - - /* read the socket, see what work is due */ - rc = _aws_iot_mqtt_internal_read_packet(pClient, pTimer, pPacketType); - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc && (MQTT_NOTHING_TO_READ == rc || SUCCESS == rc)) { - return threadRc; - } -#endif - - if(MQTT_NOTHING_TO_READ == rc) { - /* Nothing to read, not a cycle failure */ - return SUCCESS; - } else if(SUCCESS != rc) { - return rc; - } - - switch(*pPacketType) { - case CONNACK: - case PUBACK: - case SUBACK: - case UNSUBACK: - /* SDK is blocking, these responses will be forwarded to calling function to process */ - break; - case PUBLISH: { - rc = _aws_iot_mqtt_internal_handle_publish(pClient, pTimer); - break; - } - case PUBREC: - case PUBCOMP: - /* QoS2 not supported at this time */ - break; - case PINGRESP: { - pClient->clientStatus.isPingOutstanding = 0; - countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval); - break; - } - default: { - /* Either unknown packet type or Failure occurred - * Should not happen */ - rc = MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR; - break; - } - } - - return rc; -} - -/* only used in single-threaded mode where one command at a time is in process */ -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer) { - IoT_Error_t rc; - uint8_t read_packet_type; - - FUNC_ENTRY; - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - read_packet_type = 0; - do { - if(has_timer_expired(pTimer)) { - /* we timed out */ - rc = MQTT_REQUEST_TIMEOUT_ERROR; - break; - } - rc = aws_iot_mqtt_internal_cycle_read(pClient, pTimer, &read_packet_type); - } while(NETWORK_DISCONNECTED_ERROR != rc && read_packet_type != packetType); - - if(MQTT_REQUEST_TIMEOUT_ERROR != rc && NETWORK_DISCONNECTED_ERROR != rc && read_packet_type != packetType) { - FUNC_EXIT_RC(FAILURE); - } - - /* Something failed or we didn't receive the expected packet, return error code */ - FUNC_EXIT_RC(rc); -} - -/** - * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket - * @param buf the buffer into which the packet will be serialized - * @param buflen the length in bytes of the supplied buffer, to avoid overruns - * @param packettype the message type - * @param serialized length - * @return IoT_Error_t indicating function execution status - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, MessageTypes packetType, - size_t *pSerializedLength) { - unsigned char *ptr; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLength) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Buffer should have at least 2 bytes for the header */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - ptr = pTxBuf; - - rc = aws_iot_mqtt_internal_init_header(&header, packetType, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 0); - *pSerializedLength = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c deleted file mode 100644 index ae6bd4b41..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c +++ /dev/null @@ -1,627 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_connect.c - * @brief MQTT client connect API definition and related functions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_mqtt_client_common_internal.h" - -typedef union { - uint8_t all; /**< all connect flags */ -#if defined(REVERSED) - struct - { - unsigned int username : 1; /**< 3.1 user name */ - unsigned int password : 1; /**< 3.1 password */ - unsigned int willRetain : 1; /**< will retain setting */ - unsigned int willQoS : 2; /**< will QoS value */ - unsigned int will : 1; /**< will flag */ - unsigned int cleansession : 1; /**< clean session flag */ - unsigned int : 1; /**< unused */ - } bits; -#else - struct { - unsigned int : 1; - /**< unused */ - unsigned int cleansession : 1; - /**< cleansession flag */ - unsigned int will : 1; - /**< will flag */ - unsigned int willQoS : 2; - /**< will QoS value */ - unsigned int willRetain : 1; - /**< will retain setting */ - unsigned int password : 1; - /**< 3.1 password */ - unsigned int username : 1; /**< 3.1 user name */ - } bits; -#endif -} MQTT_Connect_Header_Flags; -/**< connect flags byte */ - -typedef union { - uint8_t all; /**< all connack flags */ -#if defined(REVERSED) - struct - { - unsigned int sessionpresent : 1; /**< session present flag */ - unsigned int : 7; /**< unused */ - } bits; -#else - struct { - unsigned int : 7; - /**< unused */ - unsigned int sessionpresent : 1; /**< session present flag */ - } bits; -#endif -} MQTT_Connack_Header_Flags; -/**< connack flags byte */ - -typedef enum { - CONNACK_CONNECTION_ACCEPTED = 0, - CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, - CONNACK_IDENTIFIER_REJECTED_ERROR = 2, - CONNACK_SERVER_UNAVAILABLE_ERROR = 3, - CONNACK_BAD_USERDATA_ERROR = 4, - CONNACK_NOT_AUTHORIZED_ERROR = 5 -} MQTT_Connack_Return_Codes; /**< Connect request response codes from server */ - - -/** - * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. - * @param options the options to be used to build the connect packet - * @param the length of buffer needed to contain the serialized version of the packet - * @return IoT_Error_t indicating function execution status - */ -static uint32_t _aws_iot_get_connect_packet_length(IoT_Client_Connect_Params *pConnectParams) { - uint32_t len; - /* Enable when adding further MQTT versions */ - /*size_t len = 0; - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - len = 10; - break; - }*/ - FUNC_ENTRY; - - len = 10; // Len = 10 for MQTT_3_1_1 - len = len + pConnectParams->clientIDLen + 2; - - if(pConnectParams->isWillMsgPresent) { - len = len + pConnectParams->will.topicNameLen + 2 + pConnectParams->will.msgLen + 2; - } - - if(NULL != pConnectParams->pUsername) { - len = len + pConnectParams->usernameLen + 2; - } - - if(NULL != pConnectParams->pPassword) { - len = len + pConnectParams->passwordLen + 2; - } - - FUNC_EXIT_RC(len); -} - -/** - * Serializes the connect options into the buffer. - * @param buf the buffer into which the packet will be serialized - * @param len the length in bytes of the supplied buffer - * @param options the options to be used to build the connect packet - * @param serialized length - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t txBufLen, - IoT_Client_Connect_Params *pConnectParams, - size_t *pSerializedLen) { - unsigned char *ptr; - uint32_t len; - IoT_Error_t rc; - MQTTHeader header = {0}; - MQTT_Connect_Header_Flags flags = {0}; - - FUNC_ENTRY; - - if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen || - (NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) || - (NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Check needed here before we start writing to the Tx buffer */ - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - break; - default: - return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - } - - ptr = pTxBuf; - len = _aws_iot_get_connect_packet_length(pConnectParams); - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, CONNECT, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, len); /* write remaining length */ - - // Enable if adding support for more versions - //if(MQTT_3_1_1 == pConnectParams->MQTTVersion) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion); - //} - - flags.all = 0; - if (pConnectParams->isCleanSession) - { - flags.all |= 1 << 1; - } - - if (pConnectParams->isWillMsgPresent) - { - flags.all |= 1 << 2; - flags.all |= pConnectParams->will.qos << 3; - flags.all |= pConnectParams->will.isRetained << 5; - } - - if(pConnectParams->pPassword) { - flags.all |= 1 << 6; - } - - if(pConnectParams->pUsername) { - flags.all |= 1 << 7; - } - - aws_iot_mqtt_internal_write_char(&ptr, flags.all); - aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec); - - /* If the code have passed the check for incorrect values above, no client id was passed as argument */ - if(NULL == pConnectParams->pClientID) { - aws_iot_mqtt_internal_write_uint_16(&ptr, 0); - } else { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen); - } - - if(pConnectParams->isWillMsgPresent) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName, - pConnectParams->will.topicNameLen); - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen); - } - - if(pConnectParams->pUsername) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen); - } - - if(pConnectParams->pPassword) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen); - } - - *pSerializedLen = (size_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into connack data - return code - * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) - * @param connack_rc returned integer value of the connack return code - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buflen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curdata, *enddata; - unsigned char connack_rc_char; - uint32_t decodedLen, readBytesLen; - IoT_Error_t rc; - MQTT_Connack_Header_Flags flags = {0}; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable, - * using that as minimum size - * MQTT v3.1.1 Specification 3.2.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - curdata = pRxBuf; - enddata = NULL; - decodedLen = 0; - readBytesLen = 0; - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - if(CONNACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */ - curdata += (readBytesLen); - enddata = curdata + decodedLen; - if(2 != (enddata - curdata)) { - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - - flags.all = aws_iot_mqtt_internal_read_char(&curdata); - *pSessionPresent = flags.bits.sessionpresent; - connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata); - switch(connack_rc_char) { - case CONNACK_CONNECTION_ACCEPTED: - *pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED; - break; - case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR: - *pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - break; - case CONNACK_IDENTIFIER_REJECTED_ERROR: - *pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR; - break; - case CONNACK_SERVER_UNAVAILABLE_ERROR: - *pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR; - break; - case CONNACK_BAD_USERDATA_ERROR: - *pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR; - break; - case CONNACK_NOT_AUTHORIZED_ERROR: - *pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR; - break; - default: - *pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR; - break; - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Check if client state is valid for a connect request - * - * Called to check if client state is valid for a connect request - * @param pClient Reference to the IoT Client - * - * @return bool true = state is valid, false = not valid - */ -static bool _aws_iot_mqtt_is_client_state_valid_for_connect(ClientState clientState) { - bool isValid = false; - - switch(clientState) { - case CLIENT_STATE_INVALID: - isValid = false; - break; - case CLIENT_STATE_INITIALIZED: - isValid = true; - break; - case CLIENT_STATE_CONNECTING: - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - case CLIENT_STATE_DISCONNECTING: - isValid = false; - break; - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - isValid = true; - break; - default: - break; - } - - return isValid; -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the internal function which is called by the connect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pConnectParams) { - Timer connect_timer; - IoT_Error_t connack_rc = FAILURE; - char sessionPresent = 0; - size_t len = 0; - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - - if(NULL != pConnectParams) { - /* override default options if new options were supplied */ - rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - } - - rc = pClient->networkStack.connect(&(pClient->networkStack), NULL); - if(SUCCESS != rc) { - /* TLS Connect failed, return error */ - FUNC_EXIT_RC(rc); - } - - init_timer(&connect_timer); - countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs); - - pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec; - rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - &(pClient->clientData.options), &len); - if(SUCCESS != rc || 0 >= len) { - FUNC_EXIT_RC(rc); - } - - /* send the connect packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* this will be a blocking call, wait for the CONNACK */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Received CONNACK, check the return code */ - rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { - FUNC_EXIT_RC(connack_rc); - } - - pClient->clientStatus.isPingOutstanding = false; - countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the outer function which does the validations and calls the internal connect above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pConnectParams) { - IoT_Error_t rc, disconRc; - ClientState clientState; - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - - if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) { - /* Don't send connect packet again if we are already connected - * or in the process of connecting/disconnecting */ - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING); - - rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams); - - if(SUCCESS != rc) { - pClient->networkStack.disconnect(&(pClient->networkStack)); - disconRc = pClient->networkStack.destroy(&(pClient->networkStack)); - if (SUCCESS != disconRc) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR); - } else { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE); - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Disconnect an MQTT Connection - * - * Called to send a disconnect message to the broker. - * This is the internal function which is called by the disconnect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed send of the disconnect control packet. - */ -IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) { - /* We might wait for incomplete incoming publishes to complete */ - Timer timer; - size_t serialized_len = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - DISCONNECT, - &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - /* send the disconnect packet */ - if(serialized_len > 0) { - aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - } - - /* Clean network stack */ - pClient->networkStack.disconnect(&(pClient->networkStack)); - rc = pClient->networkStack.destroy(&(pClient->networkStack)); - if(0 != rc) { - /* TLS Destroy failed, return error */ - FUNC_EXIT_RC(FAILURE); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Disconnect an MQTT Connection - * - * Called to send a disconnect message to the broker. - * This is the outer function which does the validations and calls the internal disconnect above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed send of the disconnect control packet. - */ -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) { - ClientState clientState; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(!aws_iot_mqtt_is_client_connected(pClient)) { - /* Network is already disconnected. Do nothing */ - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_internal_disconnect(pClient); - - if(SUCCESS != rc) { - pClient->clientStatus.clientState = clientState; - } else { - /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */ - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY; - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief MQTT Manual Re-Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * using parameters from the last time a connection was attempted - * Use after disconnect to start the reconnect process manually - * Makes only one reconnect attempt. Sets the client state to - * pending reconnect in case of failure - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - - /* Ignoring return code. failures expected if network is disconnected */ - rc = aws_iot_mqtt_connect(pClient, NULL); - - /* If still disconnected handle disconnect */ - if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, CLIENT_STATE_PENDING_RECONNECT); - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - rc = aws_iot_mqtt_resubscribe(pClient); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - FUNC_EXIT_RC(NETWORK_RECONNECTED); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c deleted file mode 100644 index 081a98c2b..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c +++ /dev/null @@ -1,428 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_publish.c - * @brief MQTT client publish API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * @param stringVar pointer to the String into which the data is to be read - * @param stringLen pointer to variable which has the length of the string - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param enddata pointer to the end of the data: do not read beyond - * @return SUCCESS if successful, FAILURE if not - */ -static IoT_Error_t _aws_iot_mqtt_read_string_with_len(char **stringVar, uint16_t *stringLen, - unsigned char **pptr, unsigned char *enddata) { - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - /* the first two bytes are the length of the string */ - /* enough length to read the integer? */ - if(enddata - (*pptr) > 1) { - *stringLen = aws_iot_mqtt_internal_read_uint16_t(pptr); /* increments pptr to point past length */ - if(&(*pptr)[*stringLen] <= enddata) { - *stringVar = (char *) *pptr; - *pptr += *stringLen; - rc = SUCCESS; - } - } - - FUNC_EXIT_RC(rc); -} - -/** - * Serializes the supplied publish data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup uint8_t - the MQTT dup flag - * @param qos QoS - the MQTT QoS value - * @param retained uint8_t - the MQTT retained flag - * @param packetId uint16_t - the MQTT packet identifier - * @param pTopicName char * - the MQTT topic in the publish - * @param topicNameLen uint16_t - the length of the Topic Name - * @param pPayload byte buffer - the MQTT publish payload - * @param payloadLen size_t - the length of the MQTT payload - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBuf, size_t txBufLen, uint8_t dup, - QoS qos, uint8_t retained, uint16_t packetId, - const char *pTopicName, uint16_t topicNameLen, - const unsigned char *pPayload, size_t payloadLen, - uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pPayload || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 0; - - rem_len += (uint32_t) (topicNameLen + payloadLen + 2); - if(qos > 0) { - rem_len += 2; /* packetId */ - } - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, PUBLISH, qos, dup, retained); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */; - - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicName, topicNameLen); - - if(qos > 0) { - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - } - - memcpy(ptr, pPayload, payloadLen); - ptr += payloadLen; - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Serializes the ack packet into the supplied buffer. - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param msgType the MQTT packet type - * @param dup the MQTT dup flag - * @param packetId the MQTT packet identifier - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen) { - unsigned char *ptr; - QoS requestQoS; - IoT_Error_t rc; - MQTTHeader header = {0}; - FUNC_ENTRY; - if(NULL == pTxBuf || pSerializedLen == NULL) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - - /* Minimum byte length required by ACK headers is - * 2 for fixed and 2 for variable part */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - requestQoS = (PUBREL == msgType) ? QOS1 : QOS0; - rc = aws_iot_mqtt_internal_init_header(&header, msgType, requestQoS, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 2); /* write remaining length */ - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Publish an MQTT message on a topic - * - * Called to publish an MQTT message on a topic. - * @note Call is blocking. In the case of a QoS 0 message the function returns - * after the message was successfully passed to the TLS layer. In the case of QoS 1 - * the function returns after the receipt of the PUBACK control packet. - * This is the internal function which is called by the publish API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Pointer to Publish Message parameters - * - * @return An IoT Error Type defining successful/failed publish - */ -static IoT_Error_t _aws_iot_mqtt_internal_publish(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *pParams) { - Timer timer; - uint32_t len = 0; - uint16_t packet_id; - unsigned char dup, type; - IoT_Error_t rc; - - FUNC_ENTRY; - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - if(QOS1 == pParams->qos) { - pParams->id = aws_iot_mqtt_get_next_packet_id(pClient); - } - - rc = _aws_iot_mqtt_internal_serialize_publish(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - pParams->qos, pParams->isRetained, pParams->id, pTopicName, - topicNameLen, (unsigned char *) pParams->payload, - pParams->payloadLen, &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the publish packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Wait for ack if QoS1 */ - if(QOS1 == pParams->qos) { - rc = aws_iot_mqtt_internal_wait_for_read(pClient, PUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, &packet_id, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Publish an MQTT message on a topic - * - * Called to publish an MQTT message on a topic. - * @note Call is blocking. In the case of a QoS 0 message the function returns - * after the message was successfully passed to the TLS layer. In the case of QoS 1 - * the function returns after the receipt of the PUBACK control packet. - * This is the outer function which does the validations and calls the internal publish above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Pointer to Publish Message parameters - * - * @return An IoT Error Type defining successful/failed publish - */ -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams) { - IoT_Error_t rc, pubRc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || 0 == topicNameLen || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - pubRc = _aws_iot_mqtt_internal_publish(pClient, pTopicName, topicNameLen, pParams); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS, clientState); - if(SUCCESS == pubRc && SUCCESS != rc) { - pubRc = rc; - } - - FUNC_EXIT_RC(pubRc); -} - -/** - * Deserializes the supplied (wire) buffer into publish data - * @param dup returned uint8_t - the MQTT dup flag - * @param qos returned QoS type - the MQTT QoS value - * @param retained returned uint8_t - the MQTT retained flag - * @param pPacketId returned uint16_t - the MQTT packet identifier - * @param pTopicName returned String - the MQTT topic in the publish - * @param topicNameLen returned uint16_t - the length of the MQTT topic in the publish - * @param payload returned byte buffer - the MQTT publish payload - * @param payloadlen returned size_t - the length of the MQTT payload - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData = pRxBuf; - unsigned char *endData = NULL; - IoT_Error_t rc = FAILURE; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == dup || NULL == qos || NULL == retained || NULL == pPacketId) { - FUNC_EXIT_RC(FAILURE); - } - - /* Publish header size is at least four bytes. - * Fixed header is two bytes. - * Variable header size depends on QoS And Topic Name. - * QoS level 0 doesn't have a message identifier (0 - 2 bytes) - * Topic Name length fields decide size of topic name field (at least 2 bytes) - * MQTT v3.1.1 Specification 3.3.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(PUBLISH != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *qos = (QoS) MQTT_HEADER_FIELD_QOS(header.byte); - *retained = MQTT_HEADER_FIELD_RETAIN(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curData += (readBytesLen); - endData = curData + decodedLen; - - /* do we have enough data to read the protocol version byte? */ - if(SUCCESS != _aws_iot_mqtt_read_string_with_len(pTopicName, topicNameLen, &curData, endData) - || (0 > (endData - curData))) { - FUNC_EXIT_RC(FAILURE); - } - - if(QOS0 != *qos) { - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - } - - *payloadLen = (size_t) (endData - curData); - *payload = curData; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into an ack - * @param pPacketType returned integer - the MQTT packet type - * @param dup returned integer - the MQTT dup flag - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBuflen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, unsigned char *dup, - uint16_t *pPacketId, unsigned char *pRxBuf, - size_t rxBuflen) { - IoT_Error_t rc = FAILURE; - unsigned char *curdata = pRxBuf; - unsigned char *enddata = NULL; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pPacketType || NULL == dup || NULL == pPacketId || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* PUBACK fixed header size is two bytes, variable header is 2 bytes, MQTT v3.1.1 Specification 3.4.1 */ - if(4 > rxBuflen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curdata += (readBytesLen); - enddata = curdata + decodedLen; - - if(enddata - curdata < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curdata); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c deleted file mode 100644 index c1a863209..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c +++ /dev/null @@ -1,441 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied subscribe data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup unsigned char - the MQTT dup flag - * @param packetId uint16_t - the MQTT packet identifier - * @param topicCount - number of members in the topicFilters and reqQos arrays - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names - * @param pRequestedQoSs - array of requested QoS - * @param pSerializedLen - the length of the serialized data - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size_t txBufLen, - unsigned char dup, uint16_t packetId, uint32_t topicCount, - const char **pTopicNameList, uint16_t *pTopicNameLenList, - QoS *pRequestedQoSs, uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t itr, rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 2; /* packetId */ - - for(itr = 0; itr < topicCount; ++itr) { - rem_len += (uint32_t) (pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, SUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(itr = 0; itr < topicCount; ++itr) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[itr], pTopicNameLenList[itr]); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pRequestedQoSs[itr]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into suback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param maxExpectedQoSCount - the maximum number of members allowed in the grantedQoSs array - * @param pGrantedQoSCount returned uint32_t - number of members in the grantedQoSs array - * @param pGrantedQoSs returned array of QoS type - the granted qualities of service - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_t maxExpectedQoSCount, - uint32_t *pGrantedQoSCount, QoS *pGrantedQoSs, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData, *endData; - uint32_t decodedLen, readBytesLen; - IoT_Error_t decodeRc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pPacketId || NULL == pGrantedQoSCount || NULL == pGrantedQoSs) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - curData = pRxBuf; - endData = NULL; - decodeRc = FAILURE; - decodedLen = 0; - readBytesLen = 0; - - /* SUBACK header size is 4 bytes for header and at least one byte for QoS payload - * Need at least a 5 bytes buffer. MQTT3.1.1 specification 3.9 - */ - if(5 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(SUBACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - decodeRc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != decodeRc) { - FUNC_EXIT_RC(decodeRc); - } - - curData += (readBytesLen); - endData = curData + decodedLen; - if(endData - curData < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - - *pGrantedQoSCount = 0; - while(curData < endData) { - if(*pGrantedQoSCount > maxExpectedQoSCount) { - FUNC_EXIT_RC(FAILURE); - } - pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/* Returns MAX_MESSAGE_HANDLERS value if no free index is available */ -static uint32_t _aws_iot_mqtt_get_free_message_handler_index(AWS_IoT_Client *pClient) { - uint32_t itr; - - FUNC_ENTRY; - - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - break; - } - } - - FUNC_EXIT_RC(itr); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. This is the internal function which is called by the - * subscribe API to perform the operation. Not meant to be called directly as - * it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pApplicationHandler_t Reference to the handler function for this subscription - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, QoS qos, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData) { - uint16_t txPacketId, rxPacketId; - uint32_t serializedLen, indexOfFreeMessageHandler, count; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - serializedLen = 0; - count = 0; - txPacketId = aws_iot_mqtt_get_next_packet_id(pClient); - rxPacketId = 0; - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - indexOfFreeMessageHandler = _aws_iot_mqtt_get_free_message_handler_index(pClient); - if(AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS <= indexOfFreeMessageHandler) { - FUNC_EXIT_RC(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&rxPacketId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* TODO : Figure out how to test this before activating this check */ - //if(txPacketId != rxPacketId) { - /* Different SUBACK received than expected. Return error - * This can cause issues if the request timeout value is too small */ - // return RX_MESSAGE_INVALID_ERROR; - //} - - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicName = - pTopicName; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicNameLen = - topicNameLen; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandler = - pApplicationHandler; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandlerData = - pApplicationHandlerData; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].qos = qos; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. This is the outer function which does the validations and - * calls the internal subscribe above to perform the actual operation. - * It is also responsible for client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pApplicationHandler_t Reference to the handler function for this subscription - * - * @return An IoT Error Type defining successful/failed subscription - */ -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData) { - ClientState clientState; - IoT_Error_t rc, subRc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || NULL == pApplicationHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos, - pApplicationHandler, pApplicationHandlerData); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == subRc && SUCCESS != rc) { - subRc = rc; - } - - FUNC_EXIT_RC(subRc); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. - * This is the internal function which is called by the resubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_resubscribe(AWS_IoT_Client *pClient) { - uint16_t packetId; - uint32_t len, count, existingSubCount, itr; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - - packetId = 0; - len = 0; - count = 0; - existingSubCount = _aws_iot_mqtt_get_free_message_handler_index(pClient); - - for(itr = 0; itr < existingSubCount; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - continue; - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, - &(pClient->clientData.messageHandlers[itr].topicName), - &(pClient->clientData.messageHandlers[itr].topicNameLen), - &(pClient->clientData.messageHandlers[itr].qos), &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&packetId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. - * This is the outer function which does the validations and calls the internal resubscribe above - * to perform the actual operation. It is also responsible for client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed subscription - */ -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) { - IoT_Error_t rc, resubRc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - resubRc = _aws_iot_mqtt_internal_resubscribe(pClient); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, - CLIENT_STATE_CONNECTED_IDLE); - if(SUCCESS == resubRc && SUCCESS != rc) { - resubRc = rc; - } - - FUNC_EXIT_RC(resubRc); -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c deleted file mode 100644 index fcbb97a98..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_unsubscribe.c - * @brief MQTT client unsubscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending - * @param pTxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param txBufLen the length in bytes of the data in the supplied buffer - * @param dup integer - the MQTT dup flag - * @param packetId integer - the MQTT packet identifier - * @param count - number of members in the topicFilters array - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names in pTopicNameList - * @param pSerializedLen - the length of the serialized data - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, size_t txBufLen, - uint8_t dup, uint16_t packetId, - uint32_t count, const char **pTopicNameList, - uint16_t *pTopicNameLenList, uint32_t *pSerializedLen) { - unsigned char *ptr = pTxBuf; - uint32_t i = 0; - uint32_t rem_len = 2; /* packetId */ - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - for(i = 0; i < count; ++i) { - rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, UNSUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */ - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(i = 0; i < count; ++i) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - - -/** - * Deserializes the supplied (wire) buffer into unsuback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char type = 0; - unsigned char dup = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, pPacketId, pRxBuf, rxBufLen); - if(SUCCESS == rc && UNSUBACK != type) { - rc = FAILURE; - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Unsubscribe to an MQTT topic. - * - * Called to send an unsubscribe message to the broker requesting removal of a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. - * This is the internal function which is called by the unsubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * - * @return An IoT Error Type defining successful/failed unsubscribe call - */ -static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, - uint16_t topicFilterLen) { - /* No NULL checks because this is a static internal function */ - - Timer timer; - - uint16_t packet_id; - uint32_t serializedLen = 0; - uint32_t i = 0; - IoT_Error_t rc; - bool subscriptionExists = false; - - FUNC_ENTRY; - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - subscriptionExists = true; - } - } - - if(false == subscriptionExists) { - FUNC_EXIT_RC(FAILURE); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_unsubscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, &pTopicFilter, - &topicFilterLen, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the unsubscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_wait_for_read(pClient, UNSUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_deserialize_unsuback(&packet_id, pClient->clientData.readBuf, pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - pClient->clientData.messageHandlers[i].topicName = NULL; - /* We don't want to break here, in case the same topic is registered - * with 2 callbacks. Unlikely scenario */ - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Unsubscribe to an MQTT topic. - * - * Called to send an unsubscribe message to the broker requesting removal of a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. - * This is the outer function which does the validations and calls the internal unsubscribe above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * - * @return An IoT Error Type defining successful/failed unsubscribe call - */ -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) { - IoT_Error_t rc, unsubRc; - ClientState clientState; - - if(NULL == pClient || NULL == pTopicFilter) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - return NETWORK_DISCONNECTED_ERROR; - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - return MQTT_CLIENT_NOT_IDLE_ERROR; - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - return rc; - } - - unsubRc = _aws_iot_mqtt_internal_unsubscribe(pClient, pTopicFilter, topicFilterLen); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == unsubRc && SUCCESS != rc) { - unsubRc = rc; - } - - return unsubRc; -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c deleted file mode 100644 index c40bcbbb4..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_yield.c - * @brief MQTT client yield API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * This is for the case when the aws_iot_mqtt_internal_send_packet Fails. - */ -static void _aws_iot_mqtt_force_client_disconnect(AWS_IoT_Client *pClient) { - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - pClient->networkStack.disconnect(&(pClient->networkStack)); - pClient->networkStack.destroy(&(pClient->networkStack)); -} - -static IoT_Error_t _aws_iot_mqtt_handle_disconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_disconnect(pClient); - if(rc != SUCCESS) { - // If the aws_iot_mqtt_internal_send_packet prevents us from sending a disconnect packet then we have to clean the stack - _aws_iot_mqtt_force_client_disconnect(pClient); - } - - if(NULL != pClient->clientData.disconnectHandler) { - pClient->clientData.disconnectHandler(pClient, pClient->clientData.disconnectHandlerData); - } - - /* Reset to 0 since this was not a manual disconnect */ - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); -} - - -static IoT_Error_t _aws_iot_mqtt_handle_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(!has_timer_expired(&(pClient->reconnectDelayTimer))) { - /* Timer has not expired. Not time to attempt reconnect yet. - * Return attempting reconnect */ - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - rc = NETWORK_PHYSICAL_LAYER_DISCONNECTED; - if(NULL != pClient->networkStack.isConnected) { - rc = pClient->networkStack.isConnected(&(pClient->networkStack)); - } - - if(NETWORK_PHYSICAL_LAYER_CONNECTED == rc) { - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - FUNC_EXIT_RC(NETWORK_RECONNECTED); - } - } - - pClient->clientData.currentReconnectWaitInterval *= 2; - - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - FUNC_EXIT_RC(NETWORK_RECONNECT_TIMED_OUT_ERROR); - } - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_keep_alive(AWS_IoT_Client *pClient) { - IoT_Error_t rc = SUCCESS; - Timer timer; - size_t serialized_len; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(0 == pClient->clientData.keepAliveInterval) { - FUNC_EXIT_RC(SUCCESS); - } - - if(!has_timer_expired(&pClient->pingTimer)) { - FUNC_EXIT_RC(SUCCESS); - } - - if(pClient->clientStatus.isPingOutstanding) { - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } - - /* there is no ping outstanding - send one */ - init_timer(&timer); - - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - serialized_len = 0; - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - PINGREQ, &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the ping packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - if(SUCCESS != rc) { - //If sending a PING fails we can no longer determine if we are connected. In this case we decide we are disconnected and begin reconnection attempts - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } - - pClient->clientStatus.isPingOutstanding = true; - /* start a timer to wait for PINGRESP from server */ - countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Yield to the MQTT client - * - * Called to yield the current thread to the underlying MQTT client. This time is used by - * the MQTT client to manage PING requests to monitor the health of the TCP connection as - * well as periodically check the socket receive buffer for subscribe messages. Yield() - * must be called at a rate faster than the keepalive interval. It must also be called - * at a rate faster than the incoming message rate as this is the only way the client receives - * processing time to manage incoming messages. - * This is the internal function which is called by the yield API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param timeout_ms Maximum number of milliseconds to pass thread execution to the client. - * - * @return An IoT Error Type defining successful/failed client processing. - * If this call results in an error it is likely the MQTT connection has dropped. - * iot_is_mqtt_connected can be called to confirm. - */ -static IoT_Error_t _aws_iot_mqtt_internal_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t yieldRc = SUCCESS; - - uint8_t packet_type; - ClientState clientState; - Timer timer; - init_timer(&timer); - countdown_ms(&timer, timeout_ms); - - FUNC_ENTRY; - - // evaluate timeout at the end of the loop to make sure the actual yield runs at least once - do { - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_PENDING_RECONNECT == clientState) { - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - yieldRc = NETWORK_RECONNECT_TIMED_OUT_ERROR; - break; - } - yieldRc = _aws_iot_mqtt_handle_reconnect(pClient); - /* Network reconnect attempted, check if yield timer expired before - * doing anything else */ - continue; - } - - yieldRc = aws_iot_mqtt_internal_cycle_read(pClient, &timer, &packet_type); - if(SUCCESS == yieldRc) { - yieldRc = _aws_iot_mqtt_keep_alive(pClient); - } else { - // SSL read and write errors are terminal, connection must be closed and retried - if(NETWORK_SSL_READ_ERROR == yieldRc || NETWORK_SSL_READ_TIMEOUT_ERROR == yieldRc - || NETWORK_SSL_WRITE_ERROR == yieldRc || NETWORK_SSL_WRITE_TIMEOUT_ERROR == yieldRc) { - yieldRc = _aws_iot_mqtt_handle_disconnect(pClient); - } - } - - if(NETWORK_DISCONNECTED_ERROR == yieldRc) { - pClient->clientData.counterNetworkDisconnected++; - if(1 == pClient->clientStatus.isAutoReconnectEnabled) { - yieldRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, - CLIENT_STATE_PENDING_RECONNECT); - if(SUCCESS != yieldRc) { - FUNC_EXIT_RC(yieldRc); - } - - pClient->clientData.currentReconnectWaitInterval = AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL; - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - /* Depending on timer values, it is possible that yield timer has expired - * Set to rc to attempting reconnect to inform client that autoreconnect - * attempt has started */ - yieldRc = NETWORK_ATTEMPTING_RECONNECT; - } else { - break; - } - } else if(SUCCESS != yieldRc) { - break; - } - } while(!has_timer_expired(&timer)); - - FUNC_EXIT_RC(yieldRc); -} - -/** - * @brief Yield to the MQTT client - * - * Called to yield the current thread to the underlying MQTT client. This time is used by - * the MQTT client to manage PING requests to monitor the health of the TCP connection as - * well as periodically check the socket receive buffer for subscribe messages. Yield() - * must be called at a rate faster than the keepalive interval. It must also be called - * at a rate faster than the incoming message rate as this is the only way the client receives - * processing time to manage incoming messages. - * This is the outer function which does the validations and calls the internal yield above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param timeout_ms Maximum number of milliseconds to pass thread execution to the client. - * - * @return An IoT Error Type defining successful/failed client processing. - * If this call results in an error it is likely the MQTT connection has dropped. - * iot_is_mqtt_connected can be called to confirm. - */ -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t rc, yieldRc; - ClientState clientState; - - if(NULL == pClient || 0 == timeout_ms) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - /* Check if network was manually disconnected */ - if(CLIENT_STATE_DISCONNECTED_MANUALLY == clientState) { - FUNC_EXIT_RC(NETWORK_MANUALLY_DISCONNECTED); - } - - /* If we are in the pending reconnect state, skip other checks. - * Pending reconnect state is only set when auto-reconnect is enabled */ - if(CLIENT_STATE_PENDING_RECONNECT != clientState) { - /* Check if network is disconnected and auto-reconnect is not enabled */ - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - /* Check if client is idle, if not another operation is in progress and we should return */ - if(CLIENT_STATE_CONNECTED_IDLE != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - yieldRc = _aws_iot_mqtt_internal_yield(pClient, timeout_ms); - - if(NETWORK_DISCONNECTED_ERROR != yieldRc && NETWORK_ATTEMPTING_RECONNECT != yieldRc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS, - CLIENT_STATE_CONNECTED_IDLE); - if(SUCCESS == yieldRc && SUCCESS != rc) { - yieldRc = rc; - } - } - - FUNC_EXIT_RC(yieldRc); -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c deleted file mode 100644 index 6f29cafde..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow.c - * @brief Shadow client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_shadow_records.h" - -const ShadowInitParameters_t ShadowInitParametersDefault = {(char *) AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, NULL, NULL, - NULL, false, NULL}; - -const ShadowConnectParameters_t ShadowConnectParametersDefault = {(char *) AWS_IOT_MY_THING_NAME, - (char *) AWS_IOT_MQTT_CLIENT_ID, 0, NULL}; - -static char deleteAcceptedTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -void aws_iot_shadow_reset_last_received_version(void) { - shadowJsonVersionNum = 0; -} - -uint32_t aws_iot_shadow_get_last_received_version(void) { - return shadowJsonVersionNum; -} - -void aws_iot_shadow_enable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = true; -} - -void aws_iot_shadow_disable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = false; -} - -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, const ShadowInitParameters_t *pParams) { - IoT_Client_Init_Params mqttInitParams; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - mqttInitParams.enableAutoReconnect = pParams->enableAutoReconnect; - mqttInitParams.pHostURL = pParams->pHost; - mqttInitParams.port = pParams->port; - mqttInitParams.pRootCALocation = pParams->pRootCA; - mqttInitParams.pDeviceCertLocation = pParams->pClientCRT; - mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey; - mqttInitParams.mqttPacketTimeout_ms = 5000; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = pParams->disconnectHandler; - - rc = aws_iot_mqtt_init(pClient, &mqttInitParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - resetClientTokenSequenceNum(); - aws_iot_shadow_reset_last_received_version(); - initDeltaTokens(); - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, const ShadowConnectParameters_t *pParams) { - IoT_Error_t rc = SUCCESS; - uint16_t deleteAcceptedTopicLen; - IoT_Client_Connect_Params ConnectParams = iotClientConnectParamsDefault; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - snprintf(myThingName, MAX_SIZE_OF_THING_NAME, "%s", pParams->pMyThingName); - snprintf(mqttClientID, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES, "%s", pParams->pMqttClientId); - - ConnectParams.keepAliveIntervalInSec = 600; // NOTE: Temporary fix - ConnectParams.MQTTVersion = MQTT_3_1_1; - ConnectParams.isCleanSession = true; - ConnectParams.isWillMsgPresent = false; - ConnectParams.pClientID = pParams->pMqttClientId; - ConnectParams.clientIDLen = pParams->mqttClientIdLen; - ConnectParams.pPassword = NULL; - ConnectParams.pUsername = NULL; - - rc = aws_iot_mqtt_connect(pClient, &ConnectParams); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - initializeRecords(pClient); - - if(NULL != pParams->deleteActionHandler) { - snprintf(deleteAcceptedTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, - "$aws/things/%s/shadow/delete/accepted", myThingName); - deleteAcceptedTopicLen = (uint16_t) strlen(deleteAcceptedTopic); - rc = aws_iot_mqtt_subscribe(pClient, deleteAcceptedTopic, deleteAcceptedTopicLen, QOS1, - pParams->deleteActionHandler, (void *) myThingName); - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruct_t *pStruct) { - if(NULL == pMqttClient || NULL == pStruct) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pMqttClient)) { - return MQTT_CONNECTION_ERROR; - } - - return registerJsonTokenOnDelta(pStruct); -} - -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout) { - if(NULL == pClient) { - return NULL_VALUE_ERROR; - } - - HandleExpiredResponseCallbacks(); - return aws_iot_mqtt_yield(pClient, timeout); -} - -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) { - return aws_iot_mqtt_disconnect(pClient); -} - -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe) { - IoT_Error_t rc; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_UPDATE, pJsonString, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char deleteRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - aws_iot_shadow_internal_delete_request_json(deleteRequestJsonBuf); - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char getRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - aws_iot_shadow_internal_get_request_json(getRequestJsonBuf); - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_GET, getRequestJsonBuf, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus) { - return aws_iot_mqtt_autoreconnect_set_status(pClient, newStatus); -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c deleted file mode 100644 index ed0f0cf84..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow_actions.c - * @brief Shadow client Action API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_actions.h" - -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_records.h" -#include "aws_iot_config.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - bool isClientTokenPresent = false; - bool isAckWaitListFree = false; - uint8_t indexAckWaitList; - char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - - FUNC_ENTRY; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, extractedClientToken); - - if(isClientTokenPresent && (NULL != callback)) { - if(getNextFreeIndexOfAckWaitList(&indexAckWaitList)) { - isAckWaitListFree = true; - } - - if(isAckWaitListFree) { - if(!isSubscriptionPresent(pThingName, action)) { - ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky); - } else { - incrementSubscriptionCnt(pThingName, action, isSticky); - } - } - else { - ret_val = FAILURE; - } - } - - if(SUCCESS == ret_val) { - ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent); - } - - if(isClientTokenPresent && (NULL != callback) && (SUCCESS == ret_val) && isAckWaitListFree) { - addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext, - timeout_seconds); - } - - FUNC_EXIT_RC(ret_val); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c deleted file mode 100644 index 2ac49e2c7..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow_json.c - * @brief Shadow client JSON parsing API definitions - */ - -#ifdef __cplusplus -extern "C" { -#include -#else - -#include - -#endif - -#include "aws_iot_shadow_json.h" - -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_config.h" - -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; - -static uint32_t clientTokenNum = 0; - -//helper functions -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData); - -void resetClientTokenSequenceNum(void) { - clientTokenNum = 0; -} - -static void emptyJsonWithClientToken(char *pJsonDocument) { - sprintf(pJsonDocument, "{\"clientToken\":\""); - FillWithClientToken(pJsonDocument + strlen(pJsonDocument)); - sprintf(pJsonDocument + strlen(pJsonDocument), "\"}"); -} - -void aws_iot_shadow_internal_get_request_json(char *pJsonDocument) { - emptyJsonWithClientToken(pJsonDocument); -} - -void aws_iot_shadow_internal_delete_request_json(char *pJsonDocument) { - emptyJsonWithClientToken(pJsonDocument); -} - -static inline IoT_Error_t checkReturnValueOfSnPrintf(int32_t snPrintfReturn, size_t maxSizeOfJsonDocument) { - if(snPrintfReturn < 0) { - return SHADOW_JSON_ERROR; - } else if((size_t) snPrintfReturn >= maxSizeOfJsonDocument) { - return SHADOW_JSON_BUFFER_TRUNCATED; - } - return SUCCESS; -} - -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - - IoT_Error_t ret_val = SUCCESS; - int32_t snPrintfReturn = 0; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - snPrintfReturn = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{"); - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizeOfJsonDocument); - - return ret_val; - -} - -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - size_t tempSize = 0; - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - va_list pArgs; - jsonStruct_t *pTemporary = NULL; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"desired\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - return ret_val; - } - } else { - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - jsonStruct_t *pTemporary; - va_list pArgs; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"reported\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - return ret_val; - } - } else { - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - - -int32_t FillWithClientTokenSize(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - int32_t snPrintfReturn; - snPrintfReturn = snprintf(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument, "%s-%d", mqttClientID, - (int) clientTokenNum++); - - return snPrintfReturn; -} - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - - int32_t snPrintfRet = 0; - snPrintfRet = FillWithClientTokenSize(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument); - return checkReturnValueOfSnPrintf(snPrintfRet, maxSizeOfJsonDocument); - -} - -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - IoT_Error_t ret_val = SUCCESS; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - // strlen(ShadowTxBuffer) - 1 is to ensure we remove the last ,(comma) that was added - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "}, \"%s\":\"", - SHADOW_CLIENT_TOKEN_STRING); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - // refactor this XXX repeated code - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = FillWithClientTokenSize(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"}"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - return ret_val; -} - -void FillWithClientToken(char *pBufferToBeUpdatedWithClientToken) { - sprintf(pBufferToBeUpdatedWithClientToken, "%s-%d", mqttClientID, (int) clientTokenNum++); -} - -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData) { - int32_t snPrintfReturn = 0; - IoT_Error_t ret_val = SUCCESS; - - if(maxSizoStringBuffer == 0) { - return SHADOW_JSON_ERROR; - } - - if(type == SHADOW_JSON_INT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi32",", *(int32_t *) (pData)); - } else if(type == SHADOW_JSON_INT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi16",", *(int16_t *) (pData)); - } else if(type == SHADOW_JSON_INT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi8",", *(int8_t *) (pData)); - } else if(type == SHADOW_JSON_UINT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu32",", *(uint32_t *) (pData)); - } else if(type == SHADOW_JSON_UINT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu16",", *(uint16_t *) (pData)); - } else if(type == SHADOW_JSON_UINT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu8",", *(uint8_t *) (pData)); - } else if(type == SHADOW_JSON_DOUBLE) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(double *) (pData)); - } else if(type == SHADOW_JSON_FLOAT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(float *) (pData)); - } else if(type == SHADOW_JSON_BOOL) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", *(bool *) (pData) ? "true" : "false"); - } else if(type == SHADOW_JSON_STRING) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "\"%s\",", (char *) (pData)); - } else if(type == SHADOW_JSON_OBJECT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", (char *) (pData)); - } - - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizoStringBuffer); - - return ret_val; -} - -static jsmn_parser shadowJsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; - -bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount) { - int32_t tokenCount; - - IOT_UNUSED(pJsonHandler); - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object\n"); - return false; - } - - *pTokenCount = tokenCount; - - return true; -} - -static IoT_Error_t UpdateValueIfNoObject(const char *pJsonString, jsonStruct_t *pDataStruct, jsmntok_t token) { - IoT_Error_t ret_val = SUCCESS; - if(pDataStruct->type == SHADOW_JSON_BOOL) { - ret_val = parseBooleanValue((bool *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT32) { - ret_val = parseInteger32Value((int32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT16) { - ret_val = parseInteger16Value((int16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT8) { - ret_val = parseInteger8Value((int8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT32) { - ret_val = parseUnsignedInteger32Value((uint32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT16) { - ret_val = parseUnsignedInteger16Value((uint16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT8) { - ret_val = parseUnsignedInteger8Value((uint8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_FLOAT) { - ret_val = parseFloatValue((float *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_DOUBLE) { - ret_val = parseDoubleValue((double *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_STRING) { - ret_val = parseStringValue((char *) pDataStruct->pData, pJsonString, &token); - } - - return ret_val; -} - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition) { - int32_t i; - uint32_t dataLength; - jsmntok_t dataToken; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), pDataStruct->pKey) == 0) { - dataToken = jsonTokenStruct[i + 1]; - dataLength = (uint32_t) (dataToken.end - dataToken.start); - UpdateValueIfNoObject(pJsonDocument, pDataStruct, dataToken); - *pDataPosition = dataToken.start; - *pDataLength = dataLength; - return true; - } else if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), "metadata") == 0) { - return false; - } - } - return false; -} - -bool isReceivedJsonValid(const char *pJsonDocument) { - int32_t tokenCount; - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - return true; -} - -bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken) { - int32_t tokenCount, i; - uint8_t length; - jsmntok_t ClientJsonToken; - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) { - ClientJsonToken = jsonTokenStruct[i + 1]; - length = (uint8_t) (ClientJsonToken.end - ClientJsonToken.start); - strncpy(pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length); - pExtractedClientToken[length] = '\0'; - return true; - } - } - - return false; -} - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber) { - int32_t i; - IoT_Error_t ret_val = SUCCESS; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), SHADOW_VERSION_STRING) == 0) { - ret_val = parseUnsignedInteger32Value(pVersionNumber, pJsonDocument, &jsonTokenStruct[i + 1]); - if(ret_val == SUCCESS) { - return true; - } - } - } - return false; -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c deleted file mode 100644 index 034866799..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_records.h" - -#include -#include - -#include "timer_interface.h" -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_config.h" - -typedef struct { - char clientTokenID[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - char thingName[MAX_SIZE_OF_THING_NAME]; - ShadowActions_t action; - fpActionCallback_t callback; - void *pCallbackContext; - bool isFree; - Timer timer; -} ToBeReceivedAckRecord_t; - -typedef struct { - const char *pKey; - void *pStruct; - jsonStructCallback_t callback; - bool isFree; -} JsonTokenTable_t; - -typedef struct { - char Topic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t count; - bool isFree; - bool isSticky; -} SubscriptionRecord_t; - -typedef enum { - SHADOW_ACCEPTED, SHADOW_REJECTED, SHADOW_ACTION -} ShadowAckTopicTypes_t; - -ToBeReceivedAckRecord_t AckWaitList[MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME]; - -AWS_IoT_Client *pMqttClient; - -char myThingName[MAX_SIZE_OF_THING_NAME]; -char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; - -char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define MAX_TOPICS_AT_ANY_GIVEN_TIME 2*MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME -SubscriptionRecord_t SubscriptionList[MAX_TOPICS_AT_ANY_GIVEN_TIME]; - -#define SUBSCRIBE_SETTLING_TIME 2 -char shadowRxBuf[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - -static JsonTokenTable_t tokenTable[MAX_JSON_TOKEN_EXPECTED]; -static uint32_t tokenTableIndex = 0; -static bool deltaTopicSubscribedFlag = false; -uint32_t shadowJsonVersionNum = 0; -bool shadowDiscardOldDeltaFlag = true; - -// local helper functions -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType); - -static int16_t getNextFreeIndexOfSubscriptionList(void); - -static void unsubscribeFromAcceptedAndRejected(uint8_t index); - -void initDeltaTokens(void) { - uint32_t i; - for(i = 0; i < MAX_JSON_TOKEN_EXPECTED; i++) { - tokenTable[i].isFree = true; - } - tokenTableIndex = 0; - deltaTopicSubscribedFlag = false; -} - -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct) { - - IoT_Error_t rc = SUCCESS; - - if(!deltaTopicSubscribedFlag) { - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/update/delta", myThingName); - rc = aws_iot_mqtt_subscribe(pMqttClient, shadowDeltaTopic, (uint16_t) strlen(shadowDeltaTopic), QOS0, - shadow_delta_callback, NULL); - deltaTopicSubscribedFlag = true; - } - - if(tokenTableIndex >= MAX_JSON_TOKEN_EXPECTED) { - return FAILURE; - } - - tokenTable[tokenTableIndex].pKey = pStruct->pKey; - tokenTable[tokenTableIndex].callback = pStruct->cb; - tokenTable[tokenTableIndex].pStruct = pStruct; - tokenTable[tokenTableIndex].isFree = false; - tokenTableIndex++; - - return rc; -} - -static int16_t getNextFreeIndexOfSubscriptionList(void) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(SubscriptionList[i].isFree) { - SubscriptionList[i].isFree = false; - return i; - } - } - return -1; -} - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType) { - - char actionBuf[10]; - char ackTypeBuf[10]; - - if(SHADOW_GET == action) { - strncpy(actionBuf, "get", 10); - } else if(SHADOW_UPDATE == action) { - strncpy(actionBuf, "update", 10); - } else if(SHADOW_DELETE == action) { - strncpy(actionBuf, "delete", 10); - } - - if(SHADOW_ACCEPTED == ackType) { - strncpy(ackTypeBuf, "accepted", 10); - } else if(SHADOW_REJECTED == ackType) { - strncpy(ackTypeBuf, "rejected", 10); - } - - if(SHADOW_ACTION == ackType) { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s", pThingName, actionBuf); - } else { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf, - ackTypeBuf); - } -} - -static bool isValidShadowVersionUpdate(const char *pTopicName) { - if(strstr(pTopicName, myThingName) != NULL && - ((strstr(pTopicName, "get/accepted") != NULL) || - (strstr(pTopicName, "delta") != NULL))) { - return true; - } - return false; -} - -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint8_t i; - void *pJsonHandler = NULL; - char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(isValidShadowVersionUpdate(topicName)) { - uint32_t tempVersionNumber = 0; - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } - } - } - - if(extractClientToken(shadowRxBuf, temporaryClientToken)) { - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { - Shadow_Ack_Status_t status = SHADOW_ACK_REJECTED; - if(strstr(topicName, "accepted") != NULL) { - status = SHADOW_ACK_ACCEPTED; - } else if(strstr(topicName, "rejected") != NULL) { - status = SHADOW_ACK_REJECTED; - } - if(status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - unsubscribeFromAcceptedAndRejected(i); - AckWaitList[i].isFree = true; - return; - } - } - } - } - } -} - -static int16_t findIndexOfSubscriptionList(const char *pTopic) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(pTopic, SubscriptionList[i].Topic) == 0)) { - return i; - } - } - } - return -1; -} - -static void unsubscribeFromAcceptedAndRejected(uint8_t index) { - - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Error_t ret_val = SUCCESS; - - int16_t indexSubList; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_REJECTED); - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameAccepted); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameAccepted, - (uint16_t) strlen(TemporaryTopicNameAccepted)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameRejected); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameRejected, - (uint16_t) strlen(TemporaryTopicNameRejected)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } -} - -void initializeRecords(AWS_IoT_Client *pClient) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - AckWaitList[i].isFree = true; - } - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - SubscriptionList[i].isFree = true; - SubscriptionList[i].count = 0; - SubscriptionList[i].isSticky = false; - } - - pMqttClient = pClient; -} - -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action) { - - uint8_t i = 0; - bool isAcceptedPresent = false; - bool isRejectedPresent = false; - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0)) { - isAcceptedPresent = true; - } else if((strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - isRejectedPresent = true; - } - } - } - - if(isRejectedPresent && isAcceptedPresent) { - return true; - } - - return false; -} - -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - - bool clearBothEntriesFromList = true; - int16_t indexAcceptedSubList = 0; - int16_t indexRejectedSubList = 0; - Timer subSettlingtimer; - indexAcceptedSubList = getNextFreeIndexOfSubscriptionList(); - indexRejectedSubList = getNextFreeIndexOfSubscriptionList(); - - if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) { - topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexAcceptedSubList].count = 1; - SubscriptionList[indexAcceptedSubList].isSticky = isSticky; - topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action, - SHADOW_REJECTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexRejectedSubList].count = 1; - SubscriptionList[indexRejectedSubList].isSticky = isSticky; - clearBothEntriesFromList = false; - - // wait for SUBSCRIBE_SETTLING_TIME seconds to let the subscription take effect - init_timer(&subSettlingtimer); - countdown_sec(&subSettlingtimer, SUBSCRIBE_SETTLING_TIME); - while(!has_timer_expired(&subSettlingtimer)); - - } - } - } - - if(clearBothEntriesFromList) { - if(indexAcceptedSubList >= 0) { - SubscriptionList[indexAcceptedSubList].isFree = true; - } - if(indexRejectedSubList >= 0) { - SubscriptionList[indexRejectedSubList].isFree = true; - } - if(SubscriptionList[indexAcceptedSubList].count == 1) { - aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic)); - } - } - - return ret_val; -} - -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky) { - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t i; - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0) - || (strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - SubscriptionList[i].count++; - SubscriptionList[i].isSticky = isSticky; - } - } - } -} - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent) { - IoT_Error_t ret_val = SUCCESS; - char TemporaryTopicName[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Publish_Message_Params msgParams; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - return NULL_VALUE_ERROR; - } - - topicNameFromThingAndAction(TemporaryTopicName, pThingName, action, SHADOW_ACTION); - - msgParams.qos = QOS0; - msgParams.isRetained = 0; - msgParams.payloadLen = strlen(pJsonDocumentToBeSent); - msgParams.payload = (char *) pJsonDocumentToBeSent; - ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t) strlen(TemporaryTopicName), &msgParams); - - return ret_val; -} - -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex) { - uint8_t i; - bool rc = false; - - if(NULL == pIndex) { - return false; - } - - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(AckWaitList[i].isFree) { - *pIndex = i; - rc = true; - break; - } - } - - return rc; -} - -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds) { - AckWaitList[indexAckWaitList].callback = callback; - strncpy(AckWaitList[indexAckWaitList].clientTokenID, pExtractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE); - strncpy(AckWaitList[indexAckWaitList].thingName, pThingName, MAX_SIZE_OF_THING_NAME); - AckWaitList[indexAckWaitList].pCallbackContext = pCallbackContext; - AckWaitList[indexAckWaitList].action = action; - init_timer(&(AckWaitList[indexAckWaitList].timer)); - countdown_sec(&(AckWaitList[indexAckWaitList].timer), timeout_seconds); - AckWaitList[indexAckWaitList].isFree = false; -} - -void HandleExpiredResponseCallbacks(void) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(has_timer_expired(&(AckWaitList[i].timer))) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, SHADOW_ACK_TIMEOUT, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - AckWaitList[i].isFree = true; - unsubscribeFromAcceptedAndRejected(i); - } - } - } -} - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint32_t i = 0; - void *pJsonHandler = NULL; - int32_t DataPosition; - uint32_t dataLength; - uint32_t tempVersionNumber = 0; - - FUNC_ENTRY; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(shadowDiscardOldDeltaFlag) { - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } else { - IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber, - shadowJsonVersionNum); - return; - } - } - } - - for(i = 0; i < tokenTableIndex; i++) { - if(!tokenTable[i].isFree) { - if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount, - (jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) { - if(tokenTable[i].callback != NULL) { - tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength, - (jsonStruct_t *) tokenTable[i].pStruct); - } - } - } - } -} - -#ifdef __cplusplus -} -#endif diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/README.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/README.md deleted file mode 100644 index 3625bae68..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Tests -This folder contains tests to verify SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -A description for each folder is given below - -## integration -This folder contains integration tests that run directly against the server. For further information on how to run these tests check out the [Integration Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/integration/README.md/). - -## unit -This folder contains unit tests that test SDK functionality against a Mock TLS layer. They are built using the CppUTest testing framework. For further information on how to run these tests check out the [Unit Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/unit/README.md/). \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile deleted file mode 100644 index e8353a641..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc -RM = rm - -DEBUG = - -#IoT client directory -IOT_CLIENT_DIR = ../.. - -APP_DIR = $(IOT_CLIENT_DIR)/tests/integration -APP_NAME = integration_tests_mbedtls -MT_APP_NAME = integration_tests_mbedtls_mt -APP_SRC_FILES = $(shell find $(APP_DIR)/src/ -name '*.c') -MT_APP_SRC_FILES = $(shell find $(APP_DIR)/multithreadingTest/ -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR)/include - -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -# Logging level control -#LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common -PLATFORM_THREAD_DIR = $(PLATFORM_DIR)/pthread -PLATFORM_NETWORK_DIR = $(PLATFORM_DIR)/mbedtls - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_THREAD_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_NETWORK_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_NETWORK_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_THREAD_DIR)/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -MT_SRC_FILES += $(MT_APP_SRC_FILES) -MT_SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS += cd $(TEMP_MBEDTLS_SRC_DIR) && make - -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -g3 -o $(APP_DIR)/$(APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); -MAKE_MT_CMD = $(CC) $(MT_SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(MT_APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); - -ifeq ($(CODE_SIZE_ENABLE),Y) -POST_MAKE_CMDS += $(CC) -c $(SRC_FILES) $(INCLUDE_ALL_DIRS) -fstack-usage; -POST_MAKE_CMDS += (size --format=Berkeley *.o > $(APP_NAME)_size_info.txt); -POST_MAKE_CMDS += (cat *.su >> $(APP_NAME)_stack_usage.txt); -POST_MAKE_CMDS += ($(RM) *.o); -POST_MAKE_CMDS += ($(RM) *.su); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_size_info.txt); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_stack_usage.txt); -endif - -all: - $(PRE_MAKE_CMDS) - $(DEBUG)$(MAKE_CMD) - $(DEBUG)$(MAKE_MT_CMD) - ./$(APP_NAME) - ./$(MT_APP_NAME) - $(POST_MAKE_CMDS) - -clean: - $(RM) -f $(APP_DIR)/$(APP_NAME) - $(RM) -f $(APP_DIR)/$(MT_APP_NAME) - $(CLEAN_CMD) - -ALL_TARGETS_CLEAN += test-integration-assert-clean \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md deleted file mode 100644 index b3ea04b25..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md +++ /dev/null @@ -1,44 +0,0 @@ -## Integration Tests -This folder contains integration tests to verify Embedded C SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -To run these tests, follow the below steps: - - * Place device identity cert and private key in locations referenced in the `certs` folder - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in `certs` folder - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Update the Host endpoint in the `aws_iot_config.h` file - * Build the example using make. (''make''). The tests will run automatically as a part of the build process - * For more detailed Debug output, enable the IOT_DEBUG flag in `Logging level control` section of the Makefile. IOT_TRACE can be enabled as well for very detailed information on what functions are being executed - * More information on the each test is below - -### Integration test configuration -For all the tests below, there is additional configuration in the `integ_tests_config.h`. The configuration options are explained below: - - * PUBLISH_COUNT - Number of messages to publish in each publish thread - * MAX_PUB_THREAD_COUNT - Maximum number of threads to create for the multi-threading test - * RX_RECEIVE_PERCENTAGE - Minimum percentage of messages that must be received back by the yield thread. This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish thread when it is created. In every other case, 100% messages should be received - * CONNECT_MAX_ATTEMPT_COUNT - Max number of initial connect retries - * THREAD_SLEEP_INTERVAL_USEC - Interval that each thread sleeps for - * INTEGRATION_TEST_TOPIC - Test topic to publish on - * INTEGRATION_TEST_CLIENT_ID - Client ID to be used for single client tests - * INTEGRATION_TEST_CLIENT_ID_PUB, INTEGRATION_TEST_CLIENT_ID_SUB - Client IDs to be used for multiple client tests - -### Test 1 - Basic Connectivity Test -This test verifies basic connectivity with the server. It creates one client instance and connects to the server. It subscribes to the Integration Test topic. Then it creates two threads, one publish thread and one yield thread. The publish thread publishes `PUBLISH_COUNT` messages on the test topic and the yield thread receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 2 - Multiple Client Connectivity Test -This test verifies usage of multiple clients in the same application. It creates two client instances and both connect to the server. One client instance subscribes to the Integration Test topic. The other client instance publishes `PUBLISH_COUNT` messages on the test topic and the yield instance receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 3 - Auto Reconnect Test -This test verifies Auto-reconnect functionality. It creates one client instance. Then it performs 3 separate tests - - * Tests the disconnect handler by causing a TLS layer disconnect. - * Tests manual reconnect API by causing a TLS layer disconnect with auto-reconnect disabled - * Lastly, it tests the Auto-reconnect API by enabling auto-reconnect. It renames the rootCA file to a different name to prevent immediate reconnect, verifies the error codes are returned properly and that the reconnect algorithm is running. Once that check is satisfied, it renames the rootCA file back to the original names and verifies the client was able to reconnect. - -### Test 4 - Multi-threading Validation Test -This test is used to validate thread-safe operations. This creates on client instance, one yield thread, one thread to test subscribe/unsubscribe behavior and MAX_PUB_THREAD_COUNT number of publish threads. Then it proceeds to publish PUBLISH_COUNT messages on the test topic from each publish thread. The subscribe/unsubscribe thread runs in the background constantly subscribing and unsubscribing to a second test topic. The yield threads records which messages were received. - -The test verifies whether all the messages that were published were received or not. It also checks for errors that could occur in multi-threaded scenarios. The test has been run with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h deleted file mode 100644 index 5a3889cdd..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h deleted file mode 100644 index a10933806..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ -#define TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ - -/* Number of messages to publish in each publish thread */ -#define PUBLISH_COUNT 100 - -/* Maximum number of threads to create for the multi-threading test */ -#define MAX_PUB_THREAD_COUNT 3 - -/* Minimum percentage of messages that must be received back by the yield thread. - * This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish - * thread when it is created. In every other case, 100% messages should be received. */ -#define RX_RECEIVE_PERCENTAGE 99.0f - -/* Max number of initial connect retries */ -#define CONNECT_MAX_ATTEMPT_COUNT 3 - -/* Interval that each thread sleeps for */ -#define THREAD_SLEEP_INTERVAL_USEC 500000 - -/* Test topic to publish on */ -#define INTEGRATION_TEST_TOPIC "Tests/Integration/EmbeddedC" - -/* Client ID to be used for single client tests */ -#define INTEGRATION_TEST_CLIENT_ID "EMB_C_SDK_INTEG_TESTER" - -/* Client IDs to be used for multiple client tests */ -#define INTEGRATION_TEST_CLIENT_ID_PUB "EMB_C_SDK_INTEG_TESTER_PUB" -#define INTEGRATION_TEST_CLIENT_ID_SUB "EMB_C_SDK_INTEG_TESTER_SUB" - -#endif /* TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h deleted file mode 100644 index 39da671ce..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h +++ /dev/null @@ -1,43 +0,0 @@ - -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_integration_common.h - * @brief Integration Test common header - */ - -#ifndef TESTS_INTEGRATION_H_ -#define TESTS_INTEGRATION_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -int aws_iot_mqtt_tests_basic_connectivity(); -int aws_iot_mqtt_tests_multiple_clients(); -int aws_iot_mqtt_tests_auto_reconnect(); - -#endif /* TESTS_INTEGRATION_COMMON_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c deleted file mode 100644 index cee6ad205..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * multithreadedTest.c - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" - -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -static bool terminate_yield_thread; -static bool terminate_subUnsub_thread; - -static unsigned int countArray[MAX_PUB_THREAD_COUNT][PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; -static unsigned int threadStatus[MAX_PUB_THREAD_COUNT]; - -typedef struct ThreadData { - int threadId; - AWS_IoT_Client *client; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[30]; - char *temp = NULL; - unsigned int tempRow = 0, tempCol = 0; - IoT_Error_t rc; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(30 >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\n Message received : %s", tempBuf); - temp = strtok(tempBuf, " ,:"); - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok(NULL, " ,:"); - temp = strtok(NULL, " ,:"); - tempCol = atoi(temp); - if(NULL == temp) { - return; - } - if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { - countArray[tempRow - 1][tempCol]++; - } else { - IOT_WARN(" \nUnexpected Thread : %d, Message : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG(" Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - //DEBUG("\n Yielding \n"); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[30]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - snprintf(cPayload, 30, "Thread : %d, Msg : %d", threadId, itr); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(SUCCESS != rc) { - IOT_WARN("\nFailed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d --> %d\n ", threadId, itr, rc, - aws_iot_mqtt_get_client_state(pClient)); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(SUCCESS != rc) { - IOT_ERROR("\nFailed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d --> %d Second Attempt \n", threadId, - itr, rc, aws_iot_mqtt_get_client_state(pClient)); - } - } - } - threadStatus[threadId - 1] = 1; - return 0; - -} - -static void *aws_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - char testTopic[50]; - snprintf(testTopic, 50, "%s_temp", INTEGRATION_TEST_TOPIC); - while(SUCCESS == rc && false == terminate_subUnsub_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_subscribe(pClient, testTopic, strlen(testTopic), QOS1, - aws_iot_mqtt_tests_message_aggregator, NULL); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Subscribe Returned : %d ", rc); - } - - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_unsubscribe(pClient, testTopic, strlen(testTopic)); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Unsubscribe Returned : %d ", rc); - } - } -} - -int aws_iot_mqtt_tests_multi_threading_validation() { - pthread_t publish_thread[MAX_PUB_THREAD_COUNT], yield_thread, sub_unsub_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - - char clientId[50]; - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - int threadId[MAX_PUB_THREAD_COUNT]; - int pubThreadReturn[MAX_PUB_THREAD_COUNT]; - int yieldThreadReturn = 0, subUnsubThreadReturn = 0; - float percentOfRxMsg = 0.0; - int finishedThreadCount = 0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval connectTime, subscribeTopic; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData[MAX_PUB_THREAD_COUNT]; - AWS_IoT_Client client; - terminate_yield_thread = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - threadId[j] = j + 1; - threadStatus[j] = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[j][i] = 0; - } - } - - printf("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - IOT_DEBUG(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = 8883; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - initParams.isBlockOnThreadLockEnabled = true; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("ERROR Connecting %d\n", rc); - return -1; - } - - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("\n## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - printf("\nRunning Test! "); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - subUnsubThreadReturn = pthread_create(&sub_unsub_thread, NULL, aws_iot_mqtt_tests_sub_unsub_thread_runner, &client); - - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - threadData[i].client = &client; - threadData[i].threadId = threadId[i]; - pubThreadReturn[i] = pthread_create(&publish_thread[i], NULL, aws_iot_mqtt_tests_publish_thread_runner, - &threadData[i]); - } - - /* Wait until all publish threads have finished */ - do { - finishedThreadCount = 0; - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { finishedThreadCount += threadStatus[i]; } - printf("\nFinished thread count : %d \n", finishedThreadCount); - sleep(1); - } while(finishedThreadCount < MAX_PUB_THREAD_COUNT); - - printf("\nFinished publishing!!"); - - terminate_yield_thread = true; - terminate_subUnsub_thread = true; - - /* Allow time for yield_thread and sub_sunsub thread to exit */ - sleep(1); - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - printf("\n\nCalculating Results!! \n\n"); - for(i = 0; i < PUBLISH_COUNT; i++) { - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - if(countArray[j][i] > 0) { - rxMsgCount++; - } - } - } - - printf("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); - if(RX_RECEIVE_PERCENTAGE <= percentOfRxMsg && 0 == rxMsgBufferTooBigCounter && 0 == rxUnexpectedNumberCounter && - 0 == wrongYieldCount) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} - -int main() { - printf("\n\n"); - printf("******************************************************************\n"); - printf("* Starting MQTT Version 3.1.1 Multithreading Validation Test *\n"); - printf("******************************************************************\n"); - int rc = aws_iot_mqtt_tests_multi_threading_validation(); - if(0 != rc) { - printf("\n*******************************************************************\n"); - printf("*MQTT Version 3.1.1 Multithreading Validation Test FAILED! RC : %d \n", rc); - printf("*******************************************************************\n"); - return 1; - } - - printf("******************************************************************\n"); - printf("* MQTT Version 3.1.1 Multithreading Validation Test SUCCESS!! *\n"); - printf("******************************************************************\n"); - - return 0; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c deleted file mode 100644 index 140af676c..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c +++ /dev/null @@ -1,236 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_auto_reconnect.c - * @brief Integration Test for automatic reconnect - */ - -#include "aws_iot_test_integration_common.h" - -static char ModifiedPathBuffer[PATH_MAX + 1]; -char root_CA[PATH_MAX + 1]; - -bool terminate_yield_with_rc_thread = false; -IoT_Error_t yieldRC; -bool captureYieldReturnCode = false; - -/** - * This function renames the rootCA.crt file to a temporary name to cause connect failure - */ -int aws_iot_mqtt_tests_block_tls_connect() { - char replaceFileName[] = {"rootCATemp.crt"}; - char *pFileNamePosition = NULL; - - char mvCommand[2 * PATH_MAX + 10]; - strcpy(ModifiedPathBuffer, root_CA); - pFileNamePosition = strstr(ModifiedPathBuffer, AWS_IOT_ROOT_CA_FILENAME); - strncpy(pFileNamePosition, replaceFileName, strlen(replaceFileName)); - snprintf(mvCommand, 2 * PATH_MAX + 10, "mv %s %s", root_CA, ModifiedPathBuffer); - return system(mvCommand); -} - -/** - * Always ensure this function is called after block_tls_connect - */ -int aws_iot_mqtt_tests_unblock_tls_connect() { - char mvCommand[2 * PATH_MAX + 10]; - snprintf(mvCommand, 2 * PATH_MAX + 10, "mv %s %s", ModifiedPathBuffer, root_CA); - return system(mvCommand); -} - -void *aws_iot_mqtt_tests_yield_with_rc(void *ptr) { - IoT_Error_t rc = SUCCESS; - - struct timeval start, end, result; - static int cntr = 0; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - while(terminate_yield_with_rc_thread == false - && (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - usleep(500000); - printf(" Client state : %d ", aws_iot_mqtt_get_client_state(pClient)); - rc = aws_iot_mqtt_yield(pClient, 100); - printf("yield rc %d\n", rc); - if(captureYieldReturnCode && SUCCESS != rc) { - printf("yield rc capture %d\n", rc); - captureYieldReturnCode = false; - yieldRC = rc; - } - } -} - -unsigned int disconnectedCounter = 0; - -void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - disconnectedCounter++; -} - -int aws_iot_mqtt_tests_auto_reconnect() { - pthread_t reconnectTester_thread, yield_thread; - int yieldThreadReturn = 0; - int test_result = 0; - - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char clientId[50]; - AWS_IoT_Client client; - - IoT_Error_t rc = SUCCESS; - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int) time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - IoT_Client_Init_Params initParams; - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = 8883; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 20000; - initParams.tlsHandshakeTimeout_ms = 5000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - IoT_Client_Connect_Params connectParams; - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *) &clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(rc != SUCCESS) { - printf("ERROR Connecting %d\n", rc); - return -1; - } - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - /* - * Test disconnect handler - */ - printf("1. Test Disconnect Handler\n"); - aws_iot_mqtt_tests_block_tls_connect(); - iot_tls_disconnect(&(client.networkStack)); - sleep(connectParams.keepAliveIntervalInSec + 1); - if(disconnectedCounter == 1) { - printf("Success invoking Disconnect Handler\n"); - } else { - aws_iot_mqtt_tests_unblock_tls_connect(); - printf("Failure to invoke Disconnect Handler\n"); - return -1; - } - aws_iot_mqtt_tests_unblock_tls_connect(); - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - - /* - * Manual Reconnect Test - */ - printf("2. Test Manual Reconnect, Current Client state : %d \n", aws_iot_mqtt_get_client_state(&client)); - rc = aws_iot_mqtt_attempt_reconnect(&client); - if(rc != NETWORK_RECONNECTED) { - printf("ERROR reconnecting manually %d\n", rc); - return -4; - } - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // ensure atleast 1 cycle of yield is executed to get the yield status to SUCCESS - sleep(1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success reconnecting manually\n"); - } else { - printf("Failure to reconnect manually\n"); - return -3; - } - } - terminate_yield_with_rc_thread = true; - - /* - * Auto Reconnect Test - */ - - printf("3. Test Auto_reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(rc != SUCCESS) { - printf("Error: Failed to enable auto-reconnect %d \n", rc); - } - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // Disconnect - aws_iot_mqtt_tests_block_tls_connect(); - iot_tls_disconnect(&(client.networkStack)); - - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - if(disconnectedCounter == 2) { - printf("Success: disconnect handler invoked on enabling auto-reconnect\n"); - } else { - printf("Failure: disconnect handler not invoked on enabling auto-reconnect : %d\n", disconnectedCounter); - return -7; - } - aws_iot_mqtt_tests_unblock_tls_connect(); - sleep(connectParams.keepAliveIntervalInSec + 1); - captureYieldReturnCode = true; - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == SUCCESS) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - if(true == aws_iot_mqtt_is_client_connected(&client)) { - printf("Success: is Mqtt connected api\n"); - } else { - printf("Failure: is Mqtt Connected api\n"); - return -7; - } - - rc = aws_iot_mqtt_disconnect(&client); - return rc; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c deleted file mode 100644 index 217e06d82..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c +++ /dev/null @@ -1,276 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_basic_connectivity.c - * @brief Integration Test for basic client connectivity - */ - -#include "aws_iot_test_integration_common.h" - -static bool terminate_yield_thread; -static bool isPubThreadFinished; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; - -typedef struct ThreadData { - AWS_IoT_Client *client; - int threadId; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[30]; - char *temp = NULL; - unsigned int tempRow = 0, tempCol = 0; - IoT_Error_t rc; - - if(params->payloadLen <= 30) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - temp = strtok(tempBuf, " ,:"); - temp = strtok(NULL, " ,:"); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok(NULL, " ,:"); - temp = strtok(NULL, " ,:"); - tempCol = atoi(temp); - if(NULL == temp) { - return; - } - if(tempCol > 0 && tempCol <= PUBLISH_COUNT) { - countArray[tempCol - 1]++; - } else { - IOT_WARN(" \n Thread : %d, Msg : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, - struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG("Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && terminate_yield_thread == false) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); // Client is busy, wait to get lock - - if(SUCCESS != rc) { - IOT_DEBUG("\nYield Returned : %d ", rc); - } - } -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int i = 0; - char cPayload[100]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(i = 0; i < PUBLISH_COUNT; i++) { - snprintf(cPayload, 100, "Thread : %d, Msg : %d", threadId, i + 1); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(rc != SUCCESS) { - IOT_WARN("Error Publishing #%d --> %d\n ", i, rc); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(rc != SUCCESS) { - IOT_ERROR("Error Publishing #%d --> %d Second Attempt \n", i, rc); - } - } - } - isPubThreadFinished = true; - return 0; -} - -int aws_iot_mqtt_tests_basic_connectivity() { - pthread_t publish_thread, yield_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char clientId[50]; - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - int pubThreadReturn; - int yieldThreadReturn = 0; - float percentOfRxMsg = 0.0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval connectTime, subscribeTopic; - struct timeval start, end; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData; - AWS_IoT_Client client; - - terminate_yield_thread = false; - isPubThreadFinished = false; - - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[i] = 0; - } - - IOT_DEBUG("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf("\n\nClient ID : %s \n", clientId); - - IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = 8883; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&connectTime, NULL); - rc = aws_iot_mqtt_connect(&client, &connectParams); - gettimeofday(&end, NULL); - timersub(&end, &start, &connectTime); - - connectCounter++; - } while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - IOT_DEBUG("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - sleep(1); - - threadData.client = &client; - threadData.threadId = 1; - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &threadData); - - do { - sleep(1); //Let all threads run - } while(!isPubThreadFinished); - - // This sleep is to ensure that the last publish message has enough time to be received by us - sleep(1); - - terminate_yield_thread = true; - sleep(1); - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - for(i = 0; i < PUBLISH_COUNT; i++) { - if(countArray[i] > 0) { - rxMsgCount++; - } - } - - IOT_DEBUG("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0 && - wrongYieldCount == 0) { - IOT_DEBUG("\n\nSuccess: %f \%\n", percentOfRxMsg); - IOT_DEBUG("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - IOT_DEBUG("QoS 1 re publish count %d\n", rePublishCount); - IOT_DEBUG("Connection Attempts %d\n", connectCounter); - IOT_DEBUG("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - IOT_ERROR("\n\nFailure: %f\n", percentOfRxMsg); - IOT_ERROR("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - IOT_ERROR("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - IOT_ERROR("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c deleted file mode 100644 index 5ce5bd029..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_integration_runner.c - * @brief Integration Test runner - */ - -#include "aws_iot_test_integration_common.h" - -int main() { - int rc = 0; - printf("\n\n"); - printf("*************************************************************************************************\n"); - printf("* Starting TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client *\n"); - printf("*************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_basic_connectivity(); - if(0 != rc) { - printf("\n********************************************************************************************************\n"); - printf("* TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client FAILED! RC : %4d *\n", rc); - printf("********************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************\n"); - printf("* Test 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client SUCCESS!! *\n"); - printf("*************************************************************************************************\n"); - - printf("\n\n"); - printf("************************************************************************************************************\n"); - printf("* Starting TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients *\n"); - printf("************************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_multiple_clients(); - if(0 != rc) { - printf("\n*******************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients FAILED! RC : %4d *\n", rc); - printf("*******************************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients SUCCESS!! *\n"); - printf("*************************************************************************************************************\n"); - - printf("\n\n"); - printf("*********************************************************\n"); - printf("* Starting TEST 3 MQTT Version 3.1.1 Auto Reconnect *\n"); - printf("*********************************************************\n"); - rc = aws_iot_mqtt_tests_auto_reconnect(); - if(0 != rc) { - printf("\n***************************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect FAILED! RC : %4d *\n", rc); - printf("***************************************************************\n"); - return 1; - } - printf("\n**********************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect SUCCESS!! *\n"); - printf("**********************************************************\n"); - - return 0; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c deleted file mode 100644 index d017e4fbc..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c +++ /dev/null @@ -1,274 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_multiple_clients.c - * @brief Integration Test for multiple clients from the same application - */ - -#include "aws_iot_test_integration_common.h" - -static bool terminate_yield_thread; -static bool isPubThreadFinished; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[10]; - unsigned int tempInt = 0; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(10 >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - tempInt = atoi(tempBuf); - if(0 < tempInt && PUBLISH_COUNT >= tempInt) { - countArray[tempInt - 1]++; - } else { - rxUnexpectedNumberCounter++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_connect_client_to_service(AWS_IoT_Client *pClient, struct timeval *pConnectTime, - char *clientId, char *rootCA, char *clientCRT, - char *clientKey) { - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - IoT_Error_t rc; - struct timeval start, end; - - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = 8883; - initParams.pRootCALocation = rootCA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 5000; - initParams.tlsHandshakeTimeout_ms = 2000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - rc = aws_iot_mqtt_init(pClient, &initParams); - printf("\n Init response : %d", rc); - - printf("\nRoot CA Path : %s\nClientCRT : %s\nClientKey : %s \nClient ID : %s", rootCA, clientCRT, - clientKey, clientId); - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(pClient, &connectParams); - printf("\nConnect response : %d ", rc); - gettimeofday(&end, NULL); - timersub(&end, &start, pConnectTime); - - return rc; -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - printf("\nSub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[10]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - sprintf(cPayload, "%d", itr + 1); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - printf("\n Publishing %s", cPayload); - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d\n ", itr, rc); - usleep(300000); - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - rePublishCount++; - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d Second Attempt \n", itr, rc); - } - } - usleep(300000); - } - isPubThreadFinished = true; -} - - -int aws_iot_mqtt_tests_multiple_clients() { - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - - char subClientId[50]; - char pubClientId[50]; - - int itr = 0; - int rxMsgCount = 0; - int test_result = 0; - int pubThreadReturn = 0; - int yieldThreadReturn = 0; - unsigned int connectCounter = 0; - float percentOfRxMsg = 0.0; - - IoT_Error_t rc = SUCCESS; - pthread_t yield_thread; - pthread_t publish_thread; - struct timeval connectTime; - struct timeval subscribeTopic; - - AWS_IoT_Client pubClient; - AWS_IoT_Client subClient; - - terminate_yield_thread = false; - isPubThreadFinished = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - - srand((unsigned int)time(NULL)); - snprintf(subClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_SUB, rand() % 10000); - snprintf(pubClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_PUB, rand() % 10000); - - getcwd(CurrentWD, sizeof(CurrentWD)); - - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - countArray[itr] = 0; - } - - printf(" \n Connecting Pub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&pubClient, &connectTime, pubClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && CONNECT_MAX_ATTEMPT_COUNT > connectCounter); - - if(SUCCESS == rc) { - printf("\n## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - printf("\n## Connect Failed. error code %d\n", rc); - return -1; - } - - printf("\n Connecting Sub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&subClient, &connectTime, subClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - printf("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&subClient, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &subClient); - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &pubClient); - - /* This sleep is to ensure that the last publish message has enough time to be received by us */ - do { - sleep(1); - } while(!isPubThreadFinished); - - /* Kill yield thread */ - terminate_yield_thread = true; - sleep(1); - - aws_iot_mqtt_disconnect(&pubClient); - aws_iot_mqtt_disconnect(&subClient); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - if(countArray[itr] > 0) { - rxMsgCount++; - } - } - - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - test_result = -2; - } - return test_result; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md deleted file mode 100644 index a58e2e475..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Unit Tests -This folder contains unit tests to verify Embedded C SDK functionality. These have been tested to work with Linux using CppUTest as the testing framework. -CppUTest is not provided along with this code. It needs to be separately downloaded. These tests have been verified to work with CppUTest v3.6, which can be found [here](https://github.com/cpputest/cpputest/tree/v3.6). -Each test contains a comment describing what is being tested. The Tests can be run using the Makefile provided in the root folder for the SDK. There are a total of 187 tests. - -To run these tests, follow the below steps: - - * Copy the code for CppUTest v3.6 from github to external_libs/CppUTest - * Navigate to SDK Root folder - * run `make run-unit-tests` - -This will run all unit tests and generate coverage report in the build_output folder. The report can be viewed by opening /build_output/generated-coverage/index.html in a browser. \ No newline at end of file diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h deleted file mode 100644 index e22db062e..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_config.h - * @brief IoT Client Unit Testing - IoT Config - */ - -#ifndef IOT_TESTS_UNIT_CONFIG_H_ -#define IOT_TESTS_UNIT_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "localhost" -#define AWS_IOT_MQTT_PORT 8883 -#define AWS_IOT_MQTT_CLIENT_ID "C-SDK_UnitTestClient" -#define AWS_IOT_MY_THING_NAME "C-SDK_UnitTestThing" -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" -#define AWS_IOT_CERTIFICATE_FILENAME "cert.crt" -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 -#define AWS_IOT_MQTT_RX_BUF_LEN 512 -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 /** {"clientToken": ">>uniqueClientID<<+sequenceNumber"}*/ -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 /** {"clientToken": ">>uniqueClientID+sequenceNumber<<"}*/ -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 /** >>{"clientToken": "uniqueClientID+sequenceNumber"}<<*/ -#define MAX_SIZE_OF_THINGNAME 30 -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 -#define MAX_JSON_TOKEN_EXPECTED 120 -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 -#define MAX_SIZE_OF_THING_NAME 20 -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 - -#endif /* IOT_TESTS_UNIT_CONFIG_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h deleted file mode 100644 index d8a180683..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.h - * @brief IoT Client Unit Testing - Helper Functions - */ - -#ifndef IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ - -#include -#include "aws_iot_mqtt_client_interface.h" - -typedef struct { - unsigned char PacketType; - unsigned int RemainingLength; - unsigned int ProtocolLength; - unsigned char ProtocolName[4]; - unsigned int ProtocolLevel; - unsigned char ConnectFlag; - unsigned int KeepAlive; -} ConnectBufferProofread; - -void ResetInvalidParameters(void); - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler); - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen); - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, - QoS qos, bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, - uint16_t passwordLen); - -void printBuffer(unsigned char *buffer, size_t len); - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode); - -void setTLSRxBufferForPuback(void); - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForSubFail(void); - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg); - -void setTLSRxBufferForUnsuback(void); - -void setTLSRxBufferForPingresp(void); - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos); - -unsigned char isLastTLSTxMessagePuback(void); - -unsigned char isLastTLSTxMessagePingreq(void); - -unsigned char isLastTLSTxMessageDisconnect(void); - -void setTLSRxBufferDelay(int seconds, int microseconds); - -void ResetTLSBuffer(void); - -unsigned char generateMultipleSubTopics(char *des, int boundary); - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length); - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf); - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes); - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf); - -void printPrfrdParams(ConnectBufferProofread *params); - -#endif /* IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h deleted file mode 100644 index 455a387b3..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_helper.h - * @brief IoT Client Unit Testing - Shadow Helper functions - */ - -#ifndef IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ - -#define AWS_THINGS_TOPIC "$aws/things/" -#define SHADOW_TOPIC "/shadow/" -#define ACCEPTED_TOPIC "/accepted" -#define REJECTED_TOPIC "/rejected" -#define UPDATE_TOPIC "update" -#define GET_TOPIC "get" -#define DELETE_TOPIC "delete" - - -#define GET_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC ACCEPTED_TOPIC -#define GET_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC REJECTED_TOPIC -#define GET_PUB_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC - -#define DELETE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC ACCEPTED_TOPIC -#define DELETE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC REJECTED_TOPIC - -#define UPDATE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC ACCEPTED_TOPIC -#define UPDATE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC REJECTED_TOPIC - -#endif /* IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp deleted file mode 100644 index 449647ecc..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_common_tests.cpp - * @brief IoT Client Unit Testing - Common Tests - */ - -#include -#include - -TEST_GROUP_C(CommonTests){ - TEST_GROUP_C_SETUP_WRAPPER(CommonTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(CommonTests) -}; - -TEST_GROUP_C_WRAPPER(CommonTests, NullClientGetState) -TEST_GROUP_C_WRAPPER(CommonTests, NullClientSetAutoreconnect) - -TEST_GROUP_C_WRAPPER(CommonTests, UnexpectedAckFiltering) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageIgnore) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageReadNextMessage) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c deleted file mode 100644 index e7a852e24..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_common_tests_helper.h - * @brief IoT Client Unit Testing - Common Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static AWS_IoT_Client iotClient; - -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; -char cPayload[100]; - -char cbBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 2]; - -static void iot_tests_unit_common_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, - void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - cbBuffer[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(CommonTests) { - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - IoT_Error_t rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("\n\nMQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(CommonTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -TEST_C(CommonTests, NullClientGetState) { - ClientState cs = aws_iot_mqtt_get_client_state(NULL); - CHECK_EQUAL_C_INT(CLIENT_STATE_INVALID, cs); -} - -TEST_C(CommonTests, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_mqtt_autoreconnect_set_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -// Unexpected Ack section -TEST_C(CommonTests, UnexpectedAckFiltering) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("\n-->Running CommonTests - Unexpected Ack Filtering\n"); - // Assume we are connected and have not done anything yet - // Connack - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Puback - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: OoS1 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: QoS0 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Unsuback - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -TEST_C(CommonTests, BigMQTTRxMessageIgnore) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_TX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Ignore Large Incoming Message \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_TX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); -} - -/** - * - * On receiving a big message into the TLS buffer the MQTT client should flush it out, otherwise it can cause undefined behavior. - */ -TEST_C(CommonTests, BigMQTTRxMessageReadNextMessage) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_TX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Clear Buffer when large message received and continue reading \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_TX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); - - ResetTLSBuffer(); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - expectedCallbackString[3] = '\0'; - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(rc, SUCCESS); - CHECK_EQUAL_C_STRING("XXX", cbBuffer); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp deleted file mode 100644 index bfb3823b2..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_connect.cpp - * @brief IoT Client Unit Testing - Connect API Tests - */ - -#include -#include - -TEST_GROUP_C(ConnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(ConnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ConnectTests) -}; - -/* B:1 - Init with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientInit) -/* B:2 - Connect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientConnect) -/* B:3 - Connect with Null/Empty endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullHost) -/* B:4 - Connect with Null/Empty port */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPort) -/* B:5 - Connect with Null/Empty root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullRootCAPath) -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientCertificate) -/* B:7 - Connect with Null/Empty private key Path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPrivateKeyPath) -/* B:8 - Connect with Null/Empty client ID */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientID) -/* B:9 - Connect with invalid Endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidEndpoint) -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPort) -/* B:11 - Connect with invalid Root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRootCAPath) -/* B:12 - Connect with invalid Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidClientCertPath) -/* B:13 - Connect with invalid private key path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPrivateKeyPath) -/* B:14 - Connect, no response timeout */ -TEST_GROUP_C_WRAPPER(ConnectTests, NoResponseTimeout) -/* B:15 - Connect, connack malformed, too large */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnackTooLarge) -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_GROUP_C_WRAPPER(ConnectTests, FixedHeaderCorrupted) -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRemainingLength) -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_GROUP_C_WRAPPER(ConnectTests, UnacceptableProtocolVersion) -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_GROUP_C_WRAPPER(ConnectTests, IndentifierRejected) -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_GROUP_C_WRAPPER(ConnectTests, ServerUnavailable) -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_GROUP_C_WRAPPER(ConnectTests, BadUserNameOrPassword) -/* B:22 - Connect, connack returned error, not authorized */ -TEST_GROUP_C_WRAPPER(ConnectTests, NotAuthorized) -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_GROUP_C_WRAPPER(ConnectTests, SuccessAfterDelayedConnack) -/* B:24 - Connect, connack returned success */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectSuccess) -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_GROUP_C_WRAPPER(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectDisconnectConnect) -/* B:27 - Connect attempt, Clean session, Subscribe */ -TEST_GROUP_C_WRAPPER(ConnectTests, cleanSessionInitSubscribers) -/* B:28 - Connect attempt, power cycle with clean session false */ -TEST_GROUP_C_WRAPPER(ConnectTests, PowerCycleWithCleanSessionFalse) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c deleted file mode 100644 index 0aea77ceb..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c +++ /dev/null @@ -1,720 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_connect_helper.c - * @brief IoT Client Unit Testing - Connect API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" - -#include "aws_iot_log.h" - -static bool unitTestIsMqttConnected = false; - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static IoT_Publish_Message_Params testPubMsgParams; -static ConnectBufferProofread prfrdParams; - -static char subTopic1[12] = "sdk/Topic1"; -static char subTopic2[12] = "sdk/Topic2"; - -#define NO_MSG_XXXX "XXXX" -static char CallbackMsgStringclean[100] = NO_MSG_XXXX; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgStringclean[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(ConnectTests) { - IoT_Error_t rc = SUCCESS; - unitTestIsMqttConnected = false; - rc = aws_iot_mqtt_disconnect(&iotClient); - ResetTLSBuffer(); - ResetInvalidParameters(); -} - -TEST_GROUP_C_TEARDOWN(ConnectTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* B:1 - Init with Null/empty client instance */ -TEST_C(ConnectTests, NullClientInit) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:1 - Init with Null/empty client instance \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(NULL, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:1 - Init with Null/empty client instance \n"); -} - -/* B:2 - Connect with Null/empty client instance */ -TEST_C(ConnectTests, NullClientConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:2 - Connect with Null/empty client instance \n"); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(NULL, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:2 - Connect with Null/empty client instance \n"); -} - -/* B:3 - Connect with Null/Empty endpoint */ -TEST_C(ConnectTests, NullHost) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:3 - Connect with Null/Empty endpoint \n"); - - InitMQTTParamsSetup(&initParams, NULL, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:3 - Connect with Null/Empty endpoint \n"); -} - -/* B:4 - Connect with Null/Empty port */ -TEST_C(ConnectTests, NullPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:4 - Connect with Null/Empty port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, 0, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:4 - Connect with Null/Empty port \n"); -} - -/* B:5 - Connect with Null/Empty root CA path */ -TEST_C(ConnectTests, NullRootCAPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:6 - Connect with Null/Empty root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pRootCALocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:6 - Connect with Null/Empty root CA path \n"); -} - -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_C(ConnectTests, NullClientCertificate) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:7 - Connect with Null/Empty Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDeviceCertLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:7 - Connect with Null/Empty Client certificate path \n"); -} - -/* B:7 - Connect with Null/Empty private key Path */ -TEST_C(ConnectTests, NullPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty private key Path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDevicePrivateKeyLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty private key Path \n"); -} - -/* B:8 - Connect with Null/Empty client ID */ -TEST_C(ConnectTests, NullClientID) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty client ID \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - /* If no client id is passed but a length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, NULL, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is passed but 0 length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is NULL and length is 0 then request succeeds */ - ConnectMQTTParamsSetup(&connectParams, NULL, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty client ID \n"); -} - -/* B:9 - Connect with invalid Endpoint */ -TEST_C(ConnectTests, InvalidEndpoint) { - IoT_Error_t rc = SUCCESS; - char invalidEndPoint[20]; - snprintf(invalidEndPoint, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:9 - Connect with invalid Endpoint \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidEndpointFilter = invalidEndPoint; - initParams.pHostURL = invalidEndpointFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:9 - Connect with invalid Endpoint \n"); -} - -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_C(ConnectTests, InvalidPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:10 - Connect with invalid correct endpoint but invalid port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPortFilter = 1234; - initParams.port = invalidPortFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:10 - Connect with invalid correct endpoint but invalid port \n"); -} - -/* B:11 - Connect with invalid Root CA path */ -TEST_C(ConnectTests, InvalidRootCAPath) { - IoT_Error_t rc = SUCCESS; - char invalidRootCAPath[20]; - snprintf(invalidRootCAPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:11 - Connect with invalid Root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidRootCAPathFilter = invalidRootCAPath; - initParams.pRootCALocation = invalidRootCAPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:11 - Connect with invalid Root CA path \n"); -} - -/* B:12 - Connect with invalid Client certificate path */ -TEST_C(ConnectTests, InvalidClientCertPath) { - IoT_Error_t rc = SUCCESS; - char invalidCertPath[20]; - snprintf(invalidCertPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:12 - Connect with invalid Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidCertPathFilter = invalidCertPath; - initParams.pDeviceCertLocation = invalidCertPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:12 - Connect with invalid Client certificate path \n"); -} - -/* B:13 - Connect with invalid private key path */ -TEST_C(ConnectTests, InvalidPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - char invalidPrivKeyPath[20]; - snprintf(invalidPrivKeyPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:13 - Connect with invalid private key path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPrivKeyPathFilter = invalidPrivKeyPath; - initParams.pDevicePrivateKeyLocation = invalidPrivKeyPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:13 - Connect with invalid private key path \n"); -} - -/* B:14 - Connect, no response timeout */ -TEST_C(ConnectTests, NoResponseTimeout) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:14 - Connect, no response timeout \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - B:14 - Connect, no response timeout \n"); -} - -/* B:15 - Connect, connack malformed, too large */ -TEST_C(ConnectTests, ConnackTooLarge) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:15 - Connect, connack malformed, too large \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x15); /* Set remaining length to a larger than expected value */ - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:15 - Connect, connack malformed, too large \n"); -} - -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_C(ConnectTests, FixedHeaderCorrupted) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:16 - Connect, connack malformed, fixed header corrupted \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[0] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:16 - Connect, connack malformed, fixed header corrupted \n"); -} - -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_C(ConnectTests, InvalidRemainingLength) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:17 - Connect, connack malformed, invalid remaining length \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_DECODE_REMAINING_LENGTH_ERROR, rc); - - IOT_DEBUG("-->Success - B:17 - Connect, connack malformed, invalid remaining length \n"); -} - -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_C(ConnectTests, UnacceptableProtocolVersion) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:18 - Connect, connack returned error, unacceptable protocol version \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.MQTTVersion = 7; - setTLSRxBufferForConnack(&connectParams, 0, 1); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR, rc); - - IOT_DEBUG("-->Success - B:18 - Connect, connack returned error, unacceptable protocol version \n"); -} - -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_C(ConnectTests, IndentifierRejected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:19 - Connect, connack returned error, identifier rejected \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR, rc); - - IOT_DEBUG("-->Success - B:19 - Connect, connack returned error, identifier rejected \n"); -} - -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_C(ConnectTests, ServerUnavailable) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:20 - Connect, connack returned error, Server unavailable \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 3); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR, rc); - - IOT_DEBUG("-->Success - B:20 - Connect, connack returned error, Server unavailable \n"); -} - -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_C(ConnectTests, BadUserNameOrPassword) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:21 - Connect, connack returned error, bad user name or password \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 4); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_BAD_USERDATA_ERROR, rc); - - IOT_DEBUG("-->Success - B:21 - Connect, connack returned error, bad user name or password \n"); -} - -/* B:22 - Connect, connack returned error, not authorized */ -TEST_C(ConnectTests, NotAuthorized) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("\n-->Running Connect Tests - B:22 - Connect, connack returned error, not authorized \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 5); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_NOT_AUTHORIZED_ERROR, rc); - - IOT_DEBUG("\n-->Success - B:22 - Connect, connack returned error, not authorized \n"); -} - -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_C(ConnectTests, SuccessAfterDelayedConnack) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:23 - Connect, connack return after half command timeout delay, success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - setTLSRxBufferDelay(0, (int) initParams.mqttCommandTimeout_ms/2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:23 - Connect, connack return after half command timeout delay, success \n"); -} - -/* B:24 - Connect, connack returned success */ -TEST_C(ConnectTests, ConnectSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:24 - Connect, connack returned success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:24 - Connect, connack returned success \n"); -} - -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_C(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) { - IoT_Error_t rc = SUCCESS; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Connect Tests - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = (1 << 16) - 1; - setTLSRxBufferForConnack(&connectParams, 0, 0); - - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - - IOT_DEBUG("-->Success - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); -} - -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_C(ConnectTests, ConnectDisconnectConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - // disconnect - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(false, unitTestIsMqttConnected); - - ResetTLSBuffer(); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - IOT_DEBUG("-->Success - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); -} - -/* B:27 - Connect attempt, Clean session, Subscribe - * connect with clean session true and subscribe to a topic1, set msg to topic1 and ensure it is received - * connect cs false, set msg to topic1 and nothing should come in, Sub to topic2 and check if msg is received - * connect cs false and send msg to topic2 and should be received - * cs true and everything should be clean again - */ -TEST_C(ConnectTests, cleanSessionInitSubscribers) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "msg topic"; - - IOT_DEBUG("-->Running Connect Tests - B:27 - Connect attempt, Clean session, Subscribe \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session true and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //1. subscribe to a topic1 and - testPubMsgParams.payload = expectedCallbackString; - testPubMsgParams.payloadLen = (uint16_t) strlen(expectedCallbackString); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic1, (uint16_t) strlen(subTopic1), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //1. receive message - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - rc = aws_iot_mqtt_disconnect(&iotClient); - - //2. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //3. set msg to topic1 and should receive the topic1 message - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - //4. ,sub to topic2 - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic2, (uint16_t) strlen(subTopic2), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //5. and check if topic 2 msg is received - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - rc = aws_iot_mqtt_disconnect(&iotClient); - - //6. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //7. set msg to topic2 and - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - //8. should be received - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - IOT_DEBUG("-->Success - B:27 - Connect attempt, Clean session, Subscribe \n"); - -} - -/* B:28 - Connect attempt, power cycle with clean session false - * This test is to ensure we can initialize the subscribe table in mqtt even when connecting with CS = false - * currently the AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS is set to 5 - */ -TEST_C(ConnectTests, PowerCycleWithCleanSessionFalse) { - IoT_Error_t rc = SUCCESS; - int itr = 0; - char subTestTopic[12]; - uint16_t subTestTopicLen = 0; - - IOT_DEBUG("-->Running Connect Tests - B:28 - Connect attempt, power cycle with clean session false \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //2. subscribe to max number of topics - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - //3. Subscribe to one more topic. Should return error - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - B:28 - Connect attempt, power cycle with clean session false \n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp deleted file mode 100644 index 09edca39b..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_disconnect.cpp - * @brief IoT Client Unit Testing - Disconnect API Tests - */ - -#include -#include - -TEST_GROUP_C(DisconnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(DisconnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(DisconnectTests) -}; - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientDisconnect) -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientSetDisconnectHandler) -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetDisconnectHandlerNullHandler) -/* F:4 - Disconnect attempt, not connected */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNotConnected) -/* F:5 - Disconnect success */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNoAckSuccess) -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, HandlerInvokedOnDisconnect) -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetHandlerAndInvokedOnDisconnect) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c deleted file mode 100644 index 161a1e478..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_disconnect_helper.c - * @brief IoT Client Unit Testing - Disconnect Tests helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static bool handlerInvoked = false; - -void disconnectTestHandler(AWS_IoT_Client *pClient, void *disconHandlerParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconHandlerParam); - - handlerInvoked = true; -} - -TEST_GROUP_C_SETUP(DisconnectTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, disconnectTestHandler); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(DisconnectTests) { } - - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_C(DisconnectTests, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_C(DisconnectTests, NullClientSetDisconnectHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(NULL, disconnectTestHandler, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_C(DisconnectTests, SetDisconnectHandlerNullHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(&iotClient, NULL, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:4 - Disconnect attempt, not connected */ -TEST_C(DisconnectTests, disconnectNotConnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:4 - Disconnect attempt, not connected \n"); - - /* First make sure client is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - /* Check client is disconnected */ - CHECK_EQUAL_C_INT(false, aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Now call disconnect again */ - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - F:4 - Disconnect attempt, not connected \n"); -} - -/* F:5 - Disconnect success */ -TEST_C(DisconnectTests, disconnectNoAckSuccess) { - IoT_Error_t rc = SUCCESS; - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_C(DisconnectTests, HandlerInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:6 - Disconnect, Handler invoked on disconnect \n"); - - handlerInvoked = false; - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of half keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:6 - Disconnect, Handler invoked on disconnect \n"); -} - - -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_C(DisconnectTests, SetHandlerAndInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - IOT_DEBUG("-->Running Disconnect Tests - F:7 - Disconnect, with set handler and invoked on disconnect \n"); - - handlerInvoked = false; - InitMQTTParamsSetup(&initParams, "localhost", 8883, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - aws_iot_mqtt_set_disconnect_handler(&iotClient, disconnectTestHandler, NULL); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - ResetTLSBuffer(); - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:7 - Disconnect, with set handler and invoked on disconnect \n"); -} - diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c deleted file mode 100644 index afa676dce..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c +++ /dev/null @@ -1,538 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.c - * @brief IoT Client Unit Testing - Helper Functions - */ - -#include -#include -#include "aws_iot_mqtt_client.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -#define SDK_METRICS_LEN 25 -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#define CONNACK_SUBACK_PACKET_SIZE 9 -#define PUBACK_PACKET_SIZE 4 -#define SUBACK_PACKET_SIZE 5 -#define UNSUBACK_PACKET_SIZE 4 -#define PINGRESP_PACKET_SIZE 2 - -void ResetInvalidParameters(void) { - invalidEndpointFilter = NULL; - invalidRootCAPathFilter = NULL; - invalidCertPathFilter = NULL; - invalidPrivKeyPathFilter = NULL; - invalidPortFilter = 0; -} - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler) { - params->pHostURL = pHost; - params->port = port; - params->mqttCommandTimeout_ms = 5000; - params->tlsHandshakeTimeout_ms = 5000; - params->enableAutoReconnect = enableAutoReconnect; - params->disconnectHandler = disconnectHandler; - params->disconnectHandlerData = NULL; - params->isSSLHostnameVerify = true; - params->pDeviceCertLocation = AWS_IOT_ROOT_CA_FILENAME; - params->pDevicePrivateKeyLocation = AWS_IOT_CERTIFICATE_FILENAME; - params->pRootCALocation = AWS_IOT_PRIVATE_KEY_FILENAME; -} - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = 1; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->isWillMsgPresent = false; - params->pUsername = NULL; - params->usernameLen = 0; - params->pPassword = NULL; - params->passwordLen = 0; -} - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, QoS qos, - bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, uint16_t passwordLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = isCleanSession; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->pUsername = pUsername; - params->usernameLen = userNameLen; - params->pPassword = pPassword; - params->passwordLen = passwordLen; - params->isWillMsgPresent = isWillMsgPresent; - params->will.pMessage = pWillMessage; - params->will.msgLen = willMsgLen; - params->will.pTopicName = pWillTopicName; - params->will.topicNameLen = willTopicNameLen; - params->will.qos = qos; - params->will.isRetained = false; -} - -void printBuffer(unsigned char *buffer, size_t len) { - size_t i; - printf("\n--\n"); - for(i = 0; i < len; i++) { - printf("%d: %c, %d\n", (uint32_t)i, buffer[i], buffer[i]); - } - printf("\n--\n"); -} - -#define CONNACK_PACKET_SIZE 4 - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode) { - RxBuffer.NoMsgFlag = false; - - if(params->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = connackResponseCode; - - RxBuffer.len = CONNACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - - RxBuffer.NoMsgFlag = false; - - if(conParams->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = (unsigned char) (0x0); - - RxBuffer.pBuffer[4] = (unsigned char) (0x90); - RxBuffer.pBuffer[5] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[6] = (unsigned char) (2); - RxBuffer.pBuffer[7] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[8] = (unsigned char) (qos); - - RxBuffer.len = CONNACK_SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPuback(void) { - size_t i; - - RxBuffer.NoMsgFlag = true; - RxBuffer.len = PUBACK_PACKET_SIZE; - RxIndex = 0; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x40); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = (unsigned char) (0x02); - RxBuffer.pBuffer[3] = (unsigned char) (0x00); - RxBuffer.NoMsgFlag = false; -} - -void setTLSRxBufferForSubFail(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (128); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.pBuffer[5] = (unsigned char) (0x90); - RxBuffer.pBuffer[6] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[7] = (unsigned char) (2); - RxBuffer.pBuffer[8] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[9] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE * 2; - RxIndex = 0; -} - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForUnsuback(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xB0); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // No payload - RxBuffer.len = UNSUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPingresp(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xD0); - RxBuffer.pBuffer[1] = (unsigned char) (0x00); - RxBuffer.len = PINGRESP_PACKET_SIZE; - RxIndex = 0; -} - -void ResetTLSBuffer(void) { - size_t i; - RxBuffer.len = 0; - RxBuffer.NoMsgFlag = true; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxIndex = 0; - RxBuffer.expiry_time.tv_sec = 0; - RxBuffer.expiry_time.tv_usec = 0; - TxBuffer.len = 0; - for(i = 0; i < TxBuffer.BufMaxSize; i++) { - TxBuffer.pBuffer[i] = 0; - } -} - -void setTLSRxBufferDelay(int seconds, int microseconds) { - struct timeval now, duration, result; - duration.tv_sec = seconds; - duration.tv_usec = microseconds; - - gettimeofday(&now, NULL); - timeradd(&now, &duration, &result); - RxBuffer.expiry_time.tv_sec = result.tv_sec; - RxBuffer.expiry_time.tv_usec = result.tv_usec; -} - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg) { - size_t VariableLen = topicNameLen + 2 + 2; - size_t i = 0, cursor = 0, packetIdStartLoc = 0, payloadStartLoc = 0, VarHeaderStartLoc = 0; - size_t PayloadLen = strlen(pMsg) + 1; - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x30 | ((params.qos << 1) & 0xF));// QoS1 - cursor++; // Move the cursor - - // Remaining Length - // Translate the Remaining Length into packet bytes - encodeRemainingLength(RxBuffer.pBuffer, &cursor, VariableLen + PayloadLen); - - VarHeaderStartLoc = cursor - 1; - // Variable header - RxBuffer.pBuffer[VarHeaderStartLoc + 1] = (unsigned char) ((topicNameLen & 0xFF00) >> 8); - RxBuffer.pBuffer[VarHeaderStartLoc + 2] = (unsigned char) (topicNameLen & 0xFF); - for(i = 0; i < topicNameLen; i++) { - RxBuffer.pBuffer[VarHeaderStartLoc + 3 + i] = (unsigned char) topicName[i]; - } - - packetIdStartLoc = VarHeaderStartLoc + topicNameLen + 2; - payloadStartLoc = (packetIdStartLoc + 1); - - if(QOS0 != qos) { - // packet id only for QoS 1 or 2 - RxBuffer.pBuffer[packetIdStartLoc + 1] = 2; - RxBuffer.pBuffer[packetIdStartLoc + 2] = 3; - payloadStartLoc = packetIdStartLoc + 3; - } - - // payload - for(i = 0; i < PayloadLen; i++) { - RxBuffer.pBuffer[payloadStartLoc + i] = (unsigned char) pMsg[i]; - } - - RxBuffer.len = VariableLen + PayloadLen + 2; // 2 for fixed header - RxIndex = 0; - //printBuffer(RxBuffer.pBuffer, RxBuffer.len); -} - -unsigned char isLastTLSTxMessagePuback() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0x40 ? 1 : 0); -} - -unsigned char isLastTLSTxMessagePingreq() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xC0 ? 1 : 0); -} - -unsigned char isLastTLSTxMessageDisconnect() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xE0 ? 1 : 0); -} - -unsigned char generateMultipleSubTopics(char *des, int boundary) { - int i; - int currLen = 0; - char *op1 = des; - unsigned char ret = (unsigned char) (des == NULL ? 0 : 1); - while(*op1 != '\0') { - currLen++; - op1++; - } - // Save 1 byte for terminator '\0' - for(i = 0; i < boundary - currLen - 1; i++) { - //printf("%d\n", i); - strcat(des, "a"); - } - return ret; -} - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length) { - unsigned char c; - // watch out for the type of length, could be over flow. Limits = 256MB - // No boundary check for 256MB!! - do { - c = (unsigned char) (length % 128); - length /= 128; - if(length > 0) c |= (unsigned char) (0x80); // If there is still another byte following - buf[(*st)++] = c; - } while(length > 0); - // At this point, *st should be the next position for a new part of data in the packet -} - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf) { - unsigned char *op = buf; - // Get packet type - unsigned char *ele1 = op; - unsigned int multiplier = 1; - int cnt = 0; - unsigned char *ele2; - unsigned int x; - unsigned char *op2; - params->PacketType = *ele1; - op++; - // Get remaining length (length bytes more than 4 bytes are ignored) - params->RemainingLength = 0; - do { - ele2 = op; - params->RemainingLength += ((unsigned int) (*ele2 & (0x7F)) * multiplier); - multiplier *= 128; - cnt++; - op++; - } while((*ele2 & (0x80)) != 0 && cnt < 4); - // At this point, op should be updated to the start address of the next chunk of information - // Get protocol length - params->ProtocolLength = 0; - params->ProtocolLength += (256 * (unsigned int) (*op++)); - params->ProtocolLength += (unsigned int) (*op++); - // Get protocol name - for(x = 0; x < params->ProtocolLength; x++) { - params->ProtocolName[x] = *op; - op++; - } - // Get protocol level - params->ProtocolLevel = (unsigned int) (*op++); - // Get connect flags - params->ConnectFlag = (*op++); - // Get keepalive - op2 = op; - params->KeepAlive = 0; - params->KeepAlive += (256 * (unsigned int) (*op2++)); // get rid of the sign bit - op++; - params->KeepAlive += (unsigned int) (*op2++); - op++; - - return op; -} - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes) { - bool ret = true; - int i; - unsigned char myByte[8]; // Construct our own connect flag byte according to the settings -#if !DISABLE_METRICS - myByte[0] = (unsigned char) (1); // User Name Flag -#else - myByte[0] = (unsigned char) (settings->pUsername == NULL ? 0 : 1); // User Name Flag -#endif - myByte[1] = (unsigned char) (settings->pPassword == NULL ? 0 : 1); // Password Flag - myByte[2] = 0; // Will Retain - // QoS - if(QOS1 == settings->will.qos) { - myByte[3] = 0; - myByte[4] = 1; - } else { // default QoS is QOS0 - myByte[3] = 0; - myByte[4] = 0; - } - // - myByte[5] = (unsigned char) settings->isWillMsgPresent; // Will Flag - myByte[6] = (unsigned char) settings->isCleanSession; // Clean Session - myByte[7] = 0; // Retained - // - for(i = 0; i < 8; i++) { - if(myByte[i] != (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01)) { - printf("ex %x ac %x\n", (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01) + '0', myByte[i]); - ret = false; - break; - } - } - return ret; -} - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf) { - // Construct our own payload according to the settings to see if the real one matches with it - unsigned int ClientIDLen = (unsigned int) strlen(settings->pClientID); - unsigned int WillTopicLen = (unsigned int) strlen(settings->will.pTopicName); - unsigned int WillMsgLen = (unsigned int) strlen(settings->will.pMessage); -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, - VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - unsigned int UsernameLen = (unsigned int)strlen(pUsernameTemp); -#else - unsigned int UsernameLen = (unsigned int) settings->usernameLen; -#endif - unsigned int PasswordLen = (unsigned int) settings->passwordLen; - unsigned int myPayloadLen = ClientIDLen + 2 + WillTopicLen + 2 + WillMsgLen + UsernameLen + 2 + PasswordLen; - char *myPayload = (char *) malloc(sizeof(char) * (myPayloadLen + 1)); // reserve 1 byte for '\0' - // Construction starts... - unsigned int i; - bool ret = false; - char *op = myPayload; - *op = (char) (ClientIDLen & 0x0FF00); // MSB There is a writeInt inside paho... MQTTString.lenstring.len != 0 - op++; - *op = (char) (ClientIDLen & 0x00FF); // LSB - op++; - // ClientID - for(i = 0; i < ClientIDLen; i++) { - *op = settings->pClientID[i]; - op++; - } - if(true == settings->isWillMsgPresent) { - // WillTopic - for(i = 0; i < WillTopicLen; i++) { - *op = settings->will.pTopicName[i]; - op++; - } - // WillMsg Len - *op = (char) (WillMsgLen & 0x0FF00); // MSB - op++; - *op = (char) (WillMsgLen & 0x00FF); // LSB - op++; - // WillMsg - for(i = 0; i < WillMsgLen; i++) { - *op = settings->will.pMessage[i]; - op++; - } - } - // Username -#if !DISABLE_METRICS - for(i = 0; i < strlen(pUsernameTemp); i++) - { - *op = pUsernameTemp[i]; - op++; - } -#else - if(NULL != settings->pUsername) { - for(i = 0; i < UsernameLen; i++) { - *op = settings->pUsername[i]; - op++; - } - } -#endif - // PasswordLen + Password - if(NULL != settings->pPassword) { - *op = (char) (PasswordLen & 0x0FF00); // MSB - op++; - *op = (char) (PasswordLen & 0x00FF); // LSB - op++; - // - for(i = 0; i < PasswordLen; i++) { - *op = settings->pPassword[i]; - op++; - } - } - // - *op = '\0'; - ret = strcmp(myPayload, (const char *)payloadBuf) == 0 ? true : false; - free(myPayload); - return ret; -} - -void printPrfrdParams(ConnectBufferProofread *params) { - unsigned int i; - printf("\n----------------\n"); - printf("PacketType: %x\n", params->PacketType); - printf("RemainingLength: %u\n", params->RemainingLength); - printf("ProtocolLength: %u\n", params->ProtocolLength); - printf("ProtocolName: "); - for(i = 0; i < params->ProtocolLength; i++) { - printf("%c", params->ProtocolName[i]); - } - printf("\n"); - printf("ProtocolLevel: %u\n", params->ProtocolLevel); - printf("ConnectFlag: %x\n", params->ConnectFlag); - printf("KeepAliveInterval: %u\n", params->KeepAlive); - printf("----------------\n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp deleted file mode 100644 index 68c10921d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_json_utils.cpp - * @brief IoT Client Unit Testing - JSON Utility Tests - */ - -#include -#include - -TEST_GROUP_C(JsonUtils) { - TEST_GROUP_C_SETUP_WRAPPER(JsonUtils) - TEST_GROUP_C_TEARDOWN_WRAPPER(JsonUtils) -}; - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringLongerStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringEmptyStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnBoolean) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanTrue) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanFalse) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnInvalidJson) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleSmallDouble) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatSmallFloat) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnString) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c deleted file mode 100644 index c32c95794..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c +++ /dev/null @@ -1,810 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_json_utils_helper.c - * @brief IoT Client Unit Testing - JSON Utility Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Error_t rc = SUCCESS; - -static jsmn_parser test_parser; -static jsmntok_t t[128]; - -TEST_GROUP_C_SETUP(JsonUtils) { - jsmn_init(&test_parser); -} - -TEST_GROUP_C_TEARDOWN(JsonUtils) { - -} - -TEST_C(JsonUtils, ParseStringBasic) { - int r; - const char *json = "{\"x\":\"test1\"}"; - char parsedString[50]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Basic String Parsing \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("test1", parsedString); -} - -TEST_C(JsonUtils, ParseStringLongerStringIsValid) { - int r; - const char *json = "{\"x\":\"this is a longer string for test 2\"}"; - char parsedString[50]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse long string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("this is a longer string for test 2", parsedString); -} - -TEST_C(JsonUtils, ParseStringEmptyStringIsValid) { int r; - const char *json = "{\"x\":\"\"}"; - char parsedString[50]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse empty string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("", parsedString); -} - -TEST_C(JsonUtils, ParseStringErrorOnInteger) { - int r; - const char *json = "{\"x\":3}"; - char parsedString[50]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse integer as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseStringErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - char parsedString[50]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanTrue) { - int r; - const char *json = "{\"x\":true}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with true value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanFalse) { - int r; - const char *json = "{\"x\":false}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with false value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(0, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnString) { - int r; - const char *json = "{\"x\":\"not a bool\"}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse string as boolean returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnInvalidJson) { - int r; - const char *json = "{\"x\":frue}"; // Invalid - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean returns error with invalid json \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleBasic) { - int r; - const char *json = "{\"x\":20.5}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleSmallDouble) { - int r; - const char *json = "{\"x\":0.000004}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(0.000004, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(-56.78, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseFloatBasic) { - int r; - const char *json = "{\"x\":20.5}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatSmallFloat) { - int r; - const char *json = "{\"x\":0.0004}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(0.0004f == parsedFloat); -} - -TEST_C(JsonUtils, ParseFloatErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - float parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(-56.78f == parsedFloat); -} - -TEST_C(JsonUtils, ParseIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(2147483647, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":32767}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(32767, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":127}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(127, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-30, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(1 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(2147483647 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":65535}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(65535, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":255}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(255, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp deleted file mode 100644 index da188e0fe..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_publish.cpp - * @brief IoT Client Unit Testing - Publish API Tests - */ - -#include -#include - -TEST_GROUP_C(PublishTests) { - TEST_GROUP_C_SETUP_WRAPPER(PublishTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(PublishTests) -}; - -/* E:1 - Publish with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullClient) -/* E:2 - Publish with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullTopic) -/* E:3 - Publish with Null/empty payload */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullParams) -/* E:4 - Publish with network disconnected */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNetworkDisconnected) -/* E:5 - Publish with QoS2 */ -/* Not required here, enum value doesn't exist for QoS2 */ -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureToReceivePuback) -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureDelayedPuback) -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success10msDelayedPuback) -/* E:9 - Publish QoS0 success */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS0NoPubackSuccess) -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c deleted file mode 100644 index 2f2c6406c..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_publish_helper.c - * @brief IoT Client Unit Testing - Publish API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -char cPayload[100]; - -TEST_GROUP_C_SETUP(PublishTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - sprintf(cPayload, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(PublishTests) { } - -/* E:1 - Publish with Null/empty client instance */ -TEST_C(PublishTests, PublishNullClient) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:1 - Publish with Null/empty client instance \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(NULL, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:1 - Publish with Null/empty client instance \n"); -} - -/* E:2 - Publish with Null/empty Topic Name */ -TEST_C(PublishTests, PublishNullTopic) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:2 - Publish with Null/empty Topic Name \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(&iotClient, NULL, 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 0, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:2 - Publish with Null/empty Topic Name \n"); -} - -/* E:3 - Publish with Null/empty payload */ -TEST_C(PublishTests, PublishNullParams) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:3 - Publish with Null/empty payload \n"); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:3 - Publish with Null/empty payload \n"); -} - -/* E:4 - Publish with network disconnected */ -TEST_C(PublishTests, PublishNetworkDisconnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:4 - Publish with network disconnected \n"); - - /* Ensure network is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - E:4 - Publish with network disconnected \n"); -} - -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_C(PublishTests, publishQoS1FailureToReceivePuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:6 - Publish with QoS1 send success, Puback not received \n"); - - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:6 - Publish with QoS1 send success, Puback not received \n"); -} - -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_C(PublishTests, publishQoS1FailureDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); - - setTLSRxBufferDelay(10, 0); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); -} - -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_C(PublishTests, publishQoS1Success10msDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); - - ResetTLSBuffer(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); -} - -/* E:9 - Publish QoS0 success */ -TEST_C(PublishTests, publishQoS0NoPubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:9 - Publish QoS0 success \n"); - - testPubMsgParams.qos = QOS0; // switch to a Qos0 PUB - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:9 - Publish QoS0 success \n"); -} - -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_C(PublishTests, publishQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:10 - Publish with QoS1 send success, Puback received \n"); - - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:10 - Publish with QoS1 send success, Puback received \n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp deleted file mode 100644 index ba1f5cb48..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_runner.cpp - * @brief IoT Client Unit Testing - Runner - */ - -#include - -int main(int ac, char **argv) { - return CommandLineTestRunner::RunAllTests(ac, argv); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp deleted file mode 100644 index 991e2a6ac..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action.cpp - * @brief IoT Client Unit Testing - Shadow Action Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowActionTests) { - TEST_GROUP_C_SETUP_WRAPPER(ShadowActionTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowActionTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, DeleteTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UpdateTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocumentTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) -TEST_GROUP_C_WRAPPER(ShadowActionTests, WrongTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InvalidInboundJSONInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, AcceptedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, RejectedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, PublishFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetVersionFromAckStatus) -TEST_GROUP_C_WRAPPER(ShadowActionTests, StickyNonStickyNeverConflict) -TEST_GROUP_C_WRAPPER(ShadowActionTests, ACKWaitingMoreThanAllowed) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InboundDataTooBigForBuffer) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoClientTokenForShadowAction) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoCallbackForShadowAction) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c deleted file mode 100644 index 59bb3c84a..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c +++ /dev/null @@ -1,870 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action_helper.c - * @brief IoT Client Unit Testing - Shadow Action API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_shadow_helper.h" - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_log.h" - -#define SIZE_OF_UPDATE_DOCUMENT 200 -#define TEST_JSON_RESPONSE_FULL_DOCUMENT "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_DELETE_DOCUMENT "{\"version\":2,\"timestamp\":1443473857,\"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static char jsonFullDocument[200]; -static ShadowActions_t actionRx; - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action) { - char actionBuf[10]; - - if(SHADOW_GET == action) { - strcpy(actionBuf, "get"); - } else if(SHADOW_UPDATE == action) { - strcpy(actionBuf, "update"); - } else if(SHADOW_DELETE == action) { - strcpy(actionBuf, "delete"); - } - - snprintf(pTopic, 100, "$aws/things/%s/shadow/%s", pThingName, actionBuf); -} - -TEST_GROUP_C_SETUP(ShadowActionTests) { - IoT_Error_t ret_val = SUCCESS; - char cPayload[100]; - char topic[120]; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - setTLSRxBufferForPuback(); - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload) + 1; - topicNameFromThingAndAction(topic, AWS_IOT_MY_THING_NAME, SHADOW_GET); - setTLSRxBufferForDoubleSuback(topic, strlen(topic), QOS1, testPubMsgParams); -} - -TEST_GROUP_C_TEARDOWN(ShadowActionTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_shadow_disconnect(&client); - IOT_UNUSED(rc); -} - -static void actionCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(SHADOW_ACK_TIMEOUT != status) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -// Happy path for Get, Update, Delete -TEST_C(ShadowActionTests, GetTheFullJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document \n"); -} - -TEST_C(ShadowActionTests, DeleteTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - char deleteRequestJson[120]; - - IOT_DEBUG("-->Running Shadow Action Tests - Delete json document \n"); - - aws_iot_shadow_internal_delete_request_json(deleteRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_DELETE, deleteRequestJson, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_DELETE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_DELETE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(DELETE_ACCEPTED_TOPIC, strlen(DELETE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_DELETE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_DELETE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Delete json document \n"); -} - -TEST_C(ShadowActionTests, UpdateTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char updateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - char expectedUpdateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - double doubleData = 4.0908f; - float floatData = 3.445f; - bool boolData = true; - jsonStruct_t dataFloatHandler; - jsonStruct_t dataDoubleHandler; - jsonStruct_t dataBoolHandler; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Update json document \n"); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; - - dataBoolHandler.cb = NULL; - dataBoolHandler.pData = &boolData; - dataBoolHandler.pKey = "boolData"; - dataBoolHandler.type = SHADOW_JSON_BOOL; - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 2, &dataDoubleHandler, - &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 1, &dataBoolHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(expectedUpdateRequestJson, SIZE_OF_UPDATE_DOCUMENT, - "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000},\"desired\":{\"boolData\":true}}, \"clientToken\":\"%s-0\"}", - AWS_IOT_MQTT_CLIENT_ID); - CHECK_EQUAL_C_STRING(expectedUpdateRequestJson, updateRequestJson); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, updateRequestJson, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - snprintf(jsonFullDocument, 200, "%s", ""); - params.payloadLen = strlen(TEST_JSON_RESPONSE_UPDATE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_UPDATE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(UPDATE_ACCEPTED_TOPIC, strlen(UPDATE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_UPDATE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Update json document \n"); -} - -TEST_C(ShadowActionTests, GetTheFullJSONDocumentTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document timeout \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document timeout \n"); -} - -// Subscribe and UnSubscribe on reception of thing names. Will perform the test with Get operation -TEST_C(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - Subscribe to get/accepted and get/rejected \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - Subscribe to get/accepted and get/rejected \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - unsubscribe to get/accepted and get/rejected on response \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - unsubscribe to get/accepted and get/rejected on response \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Unsubscribe to get/accepted and get/rejected on get timeout \n"); - - snprintf(jsonFullDocument, 200, "aa"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("aa", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Unsubscribe to get/accepted and get/rejected on get timeout \n"); -} - - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(num) "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\",\"version\":" #num "}" - -TEST_C(ShadowActionTests, GetVersionFromAckStatus) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - IoT_Publish_Message_Params params2; - - IOT_DEBUG("-->Running Shadow Action Tests - Get version from Ack status \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(1); - params.payloadLen = strlen(params.payload); - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(1u == aws_iot_shadow_get_last_received_version()); - - ResetTLSBuffer(); - params2.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(132387); - params2.payloadLen = strlen(params2.payload); - params2.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params2, - params2.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(132387u == aws_iot_shadow_get_last_received_version()); - - IOT_DEBUG("-->Success - Get version from Ack status \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"TroubleToken1234\"}" - -TEST_C(ShadowActionTests, WrongTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Wrong token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Wrong token in get response \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - No token in get response \n"); -} - -TEST_C(ShadowActionTests, InvalidInboundJSONInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Invalid inbound json in get response \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen("{\"state\":{{"); - params.payload = "{\"state\":{{"; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Invalid inbound json in get response \n"); -} - -TEST_C(ShadowActionTests, AcceptedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Accepted sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Accepted sub fails get request \n"); -} - -TEST_C(ShadowActionTests, RejectedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Rejected sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params); - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(GET_REJECTED_TOPIC, strlen(GET_REJECTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Rejected sub fails get request \n"); -} - -TEST_C(ShadowActionTests, PublishFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - publish fails on get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - publish fails on get request \n"); -} - -TEST_C(ShadowActionTests, StickyNonStickyNeverConflict) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Sticky and non-sticky subscriptions do not conflict \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - // Non-sticky shadow get, same thing name. Should never unsub since they are sticky - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - CHECK_EQUAL_C_STRING("No Message", LastSubscribeMessage); - CHECK_EQUAL_C_STRING("No Message", SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Sticky and non-sticky subscriptions do not conflict \n"); - -} - -TEST_C(ShadowActionTests, ACKWaitingMoreThanAllowed) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - - IOT_DEBUG("-->Running Shadow Action Tests - Ack waiting more than allowed wait time \n"); - - // 1st - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 2nd - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 3rd - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 4th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 5th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 6th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 7th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 8th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 9th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 10th - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 11th - // Should return some error code, since we are running out of ACK space - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - IOT_DEBUG("-->Success - Ack waiting more than allowed wait time \n"); -} - -#define JSON_SIZE_OVERFLOW "{\"state\":{\"reported\":{\"file\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" - -TEST_C(ShadowActionTests, InboundDataTooBigForBuffer) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Inbound data too big for buffer \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(JSON_SIZE_OVERFLOW); - params.payload = JSON_SIZE_OVERFLOW; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Inbound data too big for buffer \n"); -} - -#define TEST_JSON_RESPONSE_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoClientTokenForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No client token for shadow action \n"); - - snprintf(getRequestJson, 120, "{}"); - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no token to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No client token for shadow action \n"); -} - -TEST_C(ShadowActionTests, NoCallbackForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[120]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No callback for shadow action \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, NULL, NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no callback to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No callback for shadow action"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp deleted file mode 100644 index db9c0b25d..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta.cpp - * @brief IoT Client Unit Testing - Shadow Delta Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowDeltaTest){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowDeltaTest) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowDeltaTest) -}; - -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaSuccess) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaInt) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaIntNoCallback) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaNestedObject) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c deleted file mode 100644 index 0ec18c0a1..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c +++ /dev/null @@ -1,319 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta_helper.c - * @brief IoT Client Unit Testing - Shadow Delta Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static char receivedNestedObject[100] = ""; -static char sentNestedObjectData[100] = "{\"sensor1\":23}"; -static char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define SHADOW_DELTA_UPDATE "$aws/things/%s/shadow/update/delta" - -#undef AWS_IOT_MY_THING_NAME -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" - -void genericCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); -} - -void nestedObjectCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); - snprintf(receivedNestedObject, 100, "%.*s", JsonStringDataLen, pJsonStringData); -} - -TEST_GROUP_C_SETUP(ShadowDeltaTest) { - IoT_Error_t ret_val = SUCCESS; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, SHADOW_DELTA_UPDATE, AWS_IOT_MY_THING_NAME); -} - -TEST_GROUP_C_TEARDOWN(ShadowDeltaTest) { - -} - -TEST_C(ShadowDeltaTest, registerDeltaSuccess) { - jsonStruct_t windowHandler; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"window\":true}},\"version\":1}"; - bool windowOpenData = false; - IoT_Publish_Message_Params params; - IoT_Error_t ret_val = SUCCESS; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta success \n"); - - windowHandler.cb = genericCallback; - windowHandler.pKey = "window"; - windowHandler.type = SHADOW_JSON_BOOL; - windowHandler.pData = &windowOpenData; - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &windowHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - ret_val = aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_INT(true, windowOpenData); -} - - -TEST_C(ShadowDeltaTest, registerDeltaInt) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer \n"); - - intHandler.cb = genericCallback; - intHandler.pKey = "length"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, registerDeltaIntNoCallback) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length_nocb\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer with no callback \n"); - - intHandler.cb = NULL; - intHandler.pKey = "length_nocb"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, DeltaNestedObject) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - char deltaJSONString[100]; - - printf("\n-->Running Shadow Delta Tests - Delta received with nested object \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} - - -// Send back to back version and ensure a wrong version is ignored with old message enabled -TEST_C(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) { - IoT_Error_t ret_val = SUCCESS; - char deltaJSONString[100]; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - IoT_Publish_Message_Params params; - - printf("\n-->Running Shadow Delta Tests - delta received, old version ignored \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - aws_iot_shadow_reset_last_received_version(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - aws_iot_shadow_disable_discard_old_delta_msgs(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp deleted file mode 100644 index 8feb144e5..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder.cpp - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowJsonBuilderTests){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowJsonBuilderTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowJsonBuilderTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, PassingNullValue) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, SmallBuffer) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c deleted file mode 100644 index 8cd9fc9a1..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder_helper.c - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static jsonStruct_t dataFloatHandler; -static jsonStruct_t dataDoubleHandler; -static double doubleData = 4.0908f; -static float floatData = 3.445f; -static AWS_IoT_Client iotClient; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -TEST_GROUP_C_SETUP(ShadowJsonBuilderTests) { - IoT_Error_t ret_val; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&iotClient, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&iotClient, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; -} - -TEST_GROUP_C_TEARDOWN(ShadowJsonBuilderTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" - -#define SIZE_OF_UPFATE_BUF 200 - -TEST_C(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) { - IoT_Error_t ret_val; - char updateRequestJson[SIZE_OF_UPFATE_BUF]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Update the Json document builder \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, updateRequestJson); -} - -TEST_C(ShadowJsonBuilderTests, PassingNullValue) { - IoT_Error_t ret_val; - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Passing Null value to Shadow json builder \n"); - - ret_val = aws_iot_shadow_init_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_reported(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_desired(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); -} - -TEST_C(ShadowJsonBuilderTests, SmallBuffer) { - IoT_Error_t ret_val; - char updateRequestJson[14]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Json Buffer is too small \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_BUFFER_TRUNCATED, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp deleted file mode 100644 index dd4d02a6b..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields.cpp - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowNullFields){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowNullFields) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowNullFields) -}; - -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientInit) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientConnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullHost) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullPort) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientID) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullUpdateDocument) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientYield) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientDisconnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowGet) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowUpdate) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowDelete) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientSetAutoreconnect) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c deleted file mode 100644 index 462b730e3..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c +++ /dev/null @@ -1,148 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields_helper.c - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static ShadowActions_t actionRx; -static char jsonFullDocument[200]; - -void actionCallbackNullTest(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(status != SHADOW_ACK_TIMEOUT) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -TEST_GROUP_C_SETUP(ShadowNullFields) { - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(ShadowNullFields) { } - -TEST_C(ShadowNullFields, NullHost) { - shadowInitParams.pHost = NULL; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullPort) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = 0; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientID) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = NULL; - rc = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientInit) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - IoT_Error_t rc = aws_iot_shadow_init(NULL, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientConnect) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - rc = aws_iot_shadow_connect(NULL, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullUpdateDocument) { - IoT_Error_t rc = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, NULL, actionCallbackNullTest, - NULL, 4, false); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientYield) { - IoT_Error_t rc = aws_iot_shadow_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_shadow_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowGet) { - IoT_Error_t rc = aws_iot_shadow_get(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowUpdate) { - IoT_Error_t rc = aws_iot_shadow_update(NULL, AWS_IOT_MY_THING_NAME, jsonFullDocument, - actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowDelete) { - IoT_Error_t rc = aws_iot_shadow_delete(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_shadow_set_autoreconnect_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp deleted file mode 100644 index 205cc076a..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_subscribe.cpp - * @brief IoT Client Unit Testing - Subscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(SubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(SubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(SubscribeTests) -}; - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullClient) -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullTopic) -/* C:3 - Subscribe with Null client callback */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandler) -/* C:4 - Subscribe with Null client callback data */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandlerData) -/* C:5 - Subscribe with no connection */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNoConnection) -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0FailureOnNoSuback) -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1FailureOnNoSuback) - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0Success) -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1Success) - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) - -/* C:15 - Subscribe, malformed response */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeMalformedResponse) - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMultipleTopicsSuccess) -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubcribeToMaxAllowedTopicsSuccess) -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubcribeToMaxPlusOneAllowedTopicsFailure) - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithPluskeySuccess) -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c deleted file mode 100644 index d710f41d6..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c +++ /dev/null @@ -1,606 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_subscribe_helper.c - * @brief IoT Client Unit Testing - Subscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static char CallbackMsgString1[100] = {"XXXX"}; -static char CallbackMsgString2[100] = {"XXXX"}; -static char CallbackMsgString3[100] = {"XXXX"}; -static char CallbackMsgString4[100] = {"XXXX"}; -static char CallbackMsgString5[100] = {"XXXX"}; -static char CallbackMsgString6[100] = {"XXXX"}; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler1(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - printf("callback topic %s\n", topicName); - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString1[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler2(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString2[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler3(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString3[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler4(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString4[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler5(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString5[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler6(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString6[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(SubscribeTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(SubscribeTests) { } - - - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_C(SubscribeTests, SubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(NULL, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_C(SubscribeTests, SubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, NULL, 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:3 - Subscribe with Null client callback */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandler) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, NULL, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* C:4 - Subscribe with Null client callback data */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandlerData) { - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} -/* C:5 - Subscribe with no connection */ -TEST_C(SubscribeTests, SubscribeNoConnection) { - /* Disconnect first */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - - rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS0FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:7 - Subscribe attempt, QoS0, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:7 - Subscribe attempt, QoS0, no response timeout \n"); -} -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS1FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:8 - Subscribe attempt, QoS1, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:8 - Subscribe attempt, QoS1, no response timeout \n"); -} - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS0Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:9 - Subscribe QoS0 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:9 - Subscribe QoS0 success, suback received \n"); -} - -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:10 - Subscribe QoS1 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:10 - Subscribe QoS1 success, suback received \n"); -} - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:11 - Subscribe, QoS0, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:11 - Subscribe, QoS0, delayed suback, success \n"); -} - -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:12 - Subscribe, QoS1, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:12 - Subscribe, QoS1, delayed suback, success \n"); -} - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "Test msg - unit test"; - - IOT_DEBUG("-->Running Subscribe Tests - C:13 - Subscribe QoS0 success, no puback sent on message \n"); - - ResetTLSBuffer(); - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - testPubMsgParams.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - } - CHECK_EQUAL_C_INT(0, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:13 - Subscribe QoS0 success, no puback sent on message \n"); -} - -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:14 - Subscribe QoS1 success, puback sent on message \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - C:14 - Subscribe QoS1 success, puback sent on message \n"); -} - -/* C:15 - Subscribe, malformed response */ -TEST_C(SubscribeTests, subscribeMalformedResponse) {} - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_C(SubscribeTests, SubscribeToMultipleTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:16 - Subscribe, multiple topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - - IOT_DEBUG("-->Success - C:16 - Subscribe, multiple topics, messages on each topic \n"); -} -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_C(SubscribeTests, SubcribeToMaxAllowedTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "topics sdk/Test1"; - char expectedCallbackString2[] = "topics sdk/Test2"; - char expectedCallbackString3[] = "topics sdk/Test3"; - char expectedCallbackString4[] = "topics sdk/Test4"; - char expectedCallbackString5[] = "topics sdk/Test5"; - - IOT_DEBUG("-->Running Subscribe Tests - C:17 - Subscribe, max topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test2", 9, QOS1, testPubMsgParams, expectedCallbackString2); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test3", 9, QOS1, testPubMsgParams, expectedCallbackString3); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test4", 9, QOS1, testPubMsgParams, expectedCallbackString4); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test5", 9, QOS1, testPubMsgParams, expectedCallbackString5); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - CHECK_EQUAL_C_STRING(expectedCallbackString2, CallbackMsgString2); - CHECK_EQUAL_C_STRING(expectedCallbackString3, CallbackMsgString3); - CHECK_EQUAL_C_STRING(expectedCallbackString4, CallbackMsgString4); - CHECK_EQUAL_C_STRING(expectedCallbackString5, CallbackMsgString5); - - IOT_DEBUG("-->Success - C:17 - Subscribe, max topics, messages on each topic \n"); -} -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_C(SubscribeTests, SubcribeToMaxPlusOneAllowedTopicsFailure) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:18 - Subscribe, max topics, another subscribe \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test6", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test6", 9, QOS1, iot_subscribe_callback_handler6, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - C:18 - Subscribe, max topics, another subscribe \n"); -} - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_C(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: sub/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); - - // Set up the subscribed topic, including '#' - setTLSRxBufferForSuback("sdk/Test/#", strlen("sdk/Test/#"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/#", strlen("sdk/Test/#"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '#'] Checking first sub topic message, with '#' be the last..\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub/sub", strlen("sdk/Test/sub/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '#'] Checking second sub topic message, with '#' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: sub2, Hashkey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub2", strlen("sdk/Test/sub2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); -} -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_C(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:20 - Subscribe with '#', subscribed to all subtopics \n"); - - // Set up the subscribed topic, with '#' in the middle - // Topic directory not permitted, should fail - setTLSRxBufferForSuback("sdk/#/sub", strlen("sdk/#/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/#/sub", strlen("sdk/#/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Now provide a published message from a sub directoy with this sub topic - IOT_DEBUG("[Matching '#'] Checking sub topic message, with '#' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1/sub", strlen("sdk/Test/foo1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("NOT_VISITED", CallbackMsgString); - - IOT_DEBUG("-->Success - C:20 - Subscribe with '#', subscribed to all subtopics \n"); -} -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_C(SubscribeTests, subscribeTopicWithPluskeySuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: 1/sub, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:21 - Subscribe with '+' as wildcard success \n"); - - // Set up the subscribed topic, including '+' - setTLSRxBufferForSuback("sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/1/sub", strlen("sdk/Test/1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' in the middle...\n"); - snprintf(expectedCallbackString, 100, "New message: 2/sub, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/2/sub", strlen("sdk/Test/2/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:21 - Subscribe with '+' as wildcard success \n"); -} -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_C(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:22 - Subscribe with '+' as last character in topic name, Success \n"); - - // Set up the subscribed topic, with '+' comes the last - setTLSRxBufferForSuback("sdk/Test/+", strlen("sdk/Test/+"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+", strlen("sdk/Test/+"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' be the last...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1", strlen("sdk/Test/foo1"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide a published message from another single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: foo2, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo2", strlen("sdk/Test/foo2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:22 - Subscribe with '+' as last character in topic name, Success \n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp deleted file mode 100644 index bedea1f38..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe.cpp - * @brief IoT Client Unit Testing - Unsubscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(UnsubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(UnsubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(UnsubscribeTests) -}; - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullClient) -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullTopic) -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNotSubscribed) - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) -/* D:8 - Unsubscribe, QoS1, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) - -/* D:10 - Unsubscribe, success, message on topic ignored */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MsgAfterUnsubscribe) -/* D:11 - Unsubscribe after max topics reached */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MaxTopicsSubscription) -/* D:12 - Repeated Subscribe and Unsubscribe */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, RepeatedSubUnSub) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c deleted file mode 100644 index a4d245378..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe_helper.c - * @brief IoT Client Unit Testing - Unsubscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(UnsubscribeTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(UnsubscribeTests) { } - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_C(UnsubscribeTests, UnsubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(NULL, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_C(UnsubscribeTests, UnsubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, NULL, 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_C(UnsubscribeTests, UnsubscribeNotSubscribed) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(FAILURE, rc); -} - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:4 - Unsubscribe, QoS0, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:4 - Unsubscribe, QoS0, No response, timeout \n"); -} - -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:5 - Unsubscribe, QoS1, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:5 - Unsubscribe, QoS1, No response, timeout \n"); -} - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:6 - Unsubscribe, QoS0, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:6 - Unsubscribe, QoS0, success \n"); -} - -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); -} - -/* D:8 - Unsubscribe, QoS1, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:8 - Unsubscribe, QoS1, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:8 - Unsubscribe, QoS1, success \n"); -} - -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); -} - -/* D:10 - Unsubscribe, success, message on topic ignored - * 1. Subscribe to topic 1 - * 2. Send message and receive it - * 3. Unsubscribe to topic 1 - * 4. Should not receive message - */ -TEST_C(UnsubscribeTests, MsgAfterUnsubscribe) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:10 - Unsubscribe, success, message on topic ignored \n"); - - // 1. - setTLSRxBufferForSuback("topic1", 6, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "topic1", 6, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // 2. - snprintf(expectedCallbackString, 100, "Message for topic1"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //3. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, "topic1", 6); - CHECK_EQUAL_C_INT(SUCCESS, rc); - //reset the string - snprintf(CallbackMsgString, 100, " "); - - // 4. - // Have a new message published to that topic coming in - snprintf(expectedCallbackString, 100, "Message after unsubscribe"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // No new msg was received - CHECK_EQUAL_C_STRING(" ", CallbackMsgString); - - IOT_DEBUG("-->Success - D:10 - Unsubscribe, success, message on topic ignored \n"); -} - -/* D:11 - Unsubscribe after max topics reached - * 1. Subscribe to max topics + 1 fail for last subscription - * 2. Unsubscribe from one topic - * 3. Subscribe again and should have no error - * 4. Receive msg test - last subscribed topic - */ -TEST_C(UnsubscribeTests, MaxTopicsSubscription) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char topics[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS + 1][10]; - char expectedCallbackString[] = "Message after subscribe - topic[i]"; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:11 - Unsubscribe after max topics reached \n"); - - // 1. - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - // 2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i - 1], (uint16_t) strlen(topics[i - 1])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //3. - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //4. - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - IOT_DEBUG("-->Success - D:11 - Unsubscribe after max topics reached \n"); -} - -/* D:12 - Repeated Subscribe and Unsubscribe - * 1. subscribe and unsubscribe for more than the max subscribed topic - * 2. ensure every time the subscribed topic msg is received - */ -TEST_C(UnsubscribeTests, RepeatedSubUnSub) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char expectedCallbackString[100]; - char topics[3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS][10]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:12 - Repeated Subscribe and Unsubscribe \n"); - - - for(i = 0; i < 3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - //1. - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], 10, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], 10, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - snprintf(expectedCallbackString, 10, "message##%d", i); - testPubMsgParams.payload = (void *) expectedCallbackString; - testPubMsgParams.payloadLen = strlen(expectedCallbackString); - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:12 - Repeated Subscribe and Unsubscribe \n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp deleted file mode 100644 index 8eeb203f0..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_yield.cpp - * @brief IoT Client Unit Testing - Yield API Tests - */ - -#include -#include - -TEST_GROUP_C(YieldTests){ - TEST_GROUP_C_SETUP_WRAPPER(YieldTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(YieldTests) -}; - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(YieldTests, NullClientYield) -/* G:2 - Yield with zero yield timeout */ -TEST_GROUP_C_WRAPPER(YieldTests, ZeroTimeoutYield) -/* G:3 - Yield, network disconnected, never connected */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedNeverConnected) -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedDisconnectedManually) -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldInSubscribeCallback) -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectNoAutoReconnect) - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldSuccessNoMessages) -/* G:8 - Yield, network connected, ping request/response */ -TEST_GROUP_C_WRAPPER(YieldTests, PingRequestPingResponse) - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectTimeout) -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectSuccess) -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectManualAutoReconnect) -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, resubscribeSuccessfulReconnect) diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c deleted file mode 100644 index ca0ea3390..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c +++ /dev/null @@ -1,452 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_yield_helper.c - * @brief IoT Client Unit Testing - Yield API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; -static IoT_Publish_Message_Params testPubMsgParams; - -static ConnectBufferProofread prfrdParams; -static char CallbackMsgString[100]; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static bool dcHandlerInvoked = false; - -static void iot_tests_unit_acr_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_tests_unit_yield_test_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - IoT_Error_t rc = SUCCESS; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - rc = aws_iot_mqtt_yield(pClient, 1000); - CHECK_EQUAL_C_INT(MQTT_CLIENT_NOT_IDLE_ERROR, rc); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -void iot_tests_unit_disconnect_handler(AWS_IoT_Client *pClient, void *disconParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconParam); - dcHandlerInvoked = true; -} - - -TEST_GROUP_C_SETUP(YieldTests) { - IoT_Error_t rc = SUCCESS; - dcHandlerInvoked = false; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(YieldTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_C(YieldTests, NullClientYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* G:2 - Yield with zero yield timeout */ - -TEST_C(YieldTests, ZeroTimeoutYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(&iotClient, 0); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* G:3 - Yield, network disconnected, never connected */ - -TEST_C(YieldTests, YieldNetworkDisconnectedNeverConnected) { - AWS_IoT_Client tempIotClient; - IoT_Error_t rc; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&tempIotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&tempIotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} - -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_C(YieldTests, YieldNetworkDisconnectedDisconnectedManually) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_MANUALLY_DISCONNECTED, rc); -} - -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_C(YieldTests, YieldInSubscribeCallback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Yield Tests - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, - iot_tests_unit_yield_test_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); -} - -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_C(YieldTests, disconnectNoAutoReconnect) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - sleep((uint16_t)(iotClient.clientData.keepAliveInterval)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); -} - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_C(YieldTests, YieldSuccessNoMessages) { - IoT_Error_t rc; - int i; - - IOT_DEBUG("-->Running Yield Tests - G:7 - Yield, network connected, no incoming messages \n"); - - for(i = 0; i < 100; i++) { - CallbackMsgString[i] = 'x'; - } - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - /* Check no messages were received */ - for(i = 0; i < 100; i++) { - if('x' != CallbackMsgString[i]) { - rc = FAILURE; - } - } - } - - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - G:7 - Yield, network connected, no incoming messages \n"); -} - -/* G:8 - Yield, network connected, ping request/response */ -TEST_C(YieldTests, PingRequestPingResponse) { - IoT_Error_t rc = SUCCESS; - int i = 0; - int j = 0; - int attempt = 3; - - IOT_DEBUG("-->Running Yield Tests - G:8 - Yield, network connected, ping request/response \n"); - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", iotClient.clientData.keepAliveInterval); - - for(i = 0; i < attempt; i++) { - IOT_DEBUG("[Round_%d/Total_%d] Waiting for %d sec...\n", i + 1, attempt, iotClient.clientData.keepAliveInterval); - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - - for(j = 0; j <= iotClient.clientData.keepAliveInterval; j++) { - sleep(1); - IOT_DEBUG("[Waited %d secs]", j + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - /* Check whether ping was processed correctly and new Ping request was generated */ - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - IOT_DEBUG("-->Success - G:8 - Yield, network connected, ping request/response \n"); -} - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_C(YieldTests, disconnectAutoReconnectTimeout) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); -} - -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_C(YieldTests, disconnectAutoReconnectSuccess) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:10 - Yield, disconnected, Auto-reconnect successful \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - printf("\nWakeup"); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:10 - Yield, disconnected, Auto-reconnect successful \n"); -} - -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_C(YieldTests, disconnectManualAutoReconnect) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:11 - Yield, disconnected, Manual reconnect \n"); - - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_C(!aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_C(!aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - dcHandlerInvoked = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_attempt_reconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_RECONNECTED, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(false, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:11 - Yield, disconnected, Manual reconnect \n"); -} - -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_C(YieldTests, resubscribeSuccessfulReconnect) { - IoT_Error_t rc = FAILURE; - char cPayload[100]; - bool connected = false; - bool autoReconnectEnabled = false; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Yield Tests - G:12 - Yield, resubscribe to all topics on reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - ResetTLSBuffer(); - - /* Subscribe to a topic */ - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_tests_unit_acr_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - ResetTLSBuffer(); - - autoReconnectEnabled = aws_iot_is_autoreconnect_enabled(&iotClient); - CHECK_EQUAL_C_INT(1, autoReconnectEnabled); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - - ResetTLSBuffer(); - setTLSRxBufferForConnackAndSuback(&connectParams, 0, subTopic, subTopicLen, QOS1); - - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - /* Test if reconnect worked */ - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, connected); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:12 - Yield, resubscribe to all topics on reconnect \n"); -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c deleted file mode 100644 index f9a6cc71a..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include - -#include "network_interface.h" -#include "aws_iot_tests_unit_mock_tls_params.h" - - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - return SUCCESS; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - IOT_UNUSED(pNetwork); - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, - params->timeout_ms, params->ServerVerificationFlag); - } - - if(NULL != invalidEndpointFilter && 0 == strcmp(invalidEndpointFilter, pNetwork->tlsConnectParams.pDestinationURL)) { - return NETWORK_ERR_NET_UNKNOWN_HOST; - } - - if(invalidPortFilter == pNetwork->tlsConnectParams.DestinationPort) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidRootCAPathFilter && 0 == strcmp(invalidRootCAPathFilter, pNetwork->tlsConnectParams.pRootCALocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidCertPathFilter && 0 == strcmp(invalidCertPathFilter, pNetwork->tlsConnectParams.pDeviceCertLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidPrivKeyPathFilter && 0 == strcmp(invalidPrivKeyPathFilter, pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - IOT_UNUSED(pNetwork); - - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t i = 0; - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - IOT_UNUSED(pNetwork); - IOT_UNUSED(timer); - - for(i = 0; (i < len) && left_ms(timer) > 0; i++) { - TxBuffer.pBuffer[i] = pMsg[i]; - } - TxBuffer.len = len; - *written_len = len; - - /* Save last two subscribed topics */ - if((TxBuffer.pBuffer[0] == 0x82 ? true : false)) { - snprintf(SecondLastSubscribeMessage, lastSubscribeMsgLen, "%s", LastSubscribeMessage); - secondLastSubscribeMsgLen = lastSubscribeMsgLen; - - firstByte = (uint8_t)(TxBuffer.pBuffer[4]); - secondByte = (uint8_t)(TxBuffer.pBuffer[5]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(LastSubscribeMessage, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[6])); // Added one for null character - lastSubscribeMsgLen = topicNameLen + 1u; - } - - return SUCCESS; -} - -static unsigned char isTimerExpired(struct timeval target_time) { - unsigned char ret_val = 0; - struct timeval now, result; - - if(target_time.tv_sec != 0 || target_time.tv_usec != 0) { - gettimeofday(&now, NULL); - timersub(&(target_time), &now, &result); - if(result.tv_sec < 0 || (result.tv_sec == 0 && result.tv_usec <= 0)) { - ret_val = 1; - } - } else { - ret_val = 1; - } - return ret_val; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *pTimer, size_t *read_len) { - IOT_UNUSED(pNetwork); - IOT_UNUSED(pTimer); - - if(RxIndex > TLSMaxBufferSize - 1) { - RxIndex = TLSMaxBufferSize - 1; - } - - if(RxBuffer.len <= RxIndex || !isTimerExpired(RxBuffer.expiry_time)) { - return NETWORK_SSL_NOTHING_TO_READ; - } - - if((false == RxBuffer.NoMsgFlag) && (RxIndex < RxBuffer.len)) { - memcpy(pMsg, &(RxBuffer.pBuffer[RxIndex]), len); - RxIndex += len; - *read_len = len; - } - - return SUCCESS; -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c deleted file mode 100644 index efe855062..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.c - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#include "aws_iot_tests_unit_mock_tls_params.h" - -unsigned char RxBuf[TLSMaxBufferSize]; -unsigned char TxBuf[TLSMaxBufferSize]; -char LastSubscribeMessage[TLSMaxBufferSize]; -size_t lastSubscribeMsgLen; -char SecondLastSubscribeMessage[TLSMaxBufferSize]; -size_t secondLastSubscribeMsgLen; - -TlsBuffer RxBuffer = {.pBuffer = RxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize}; -TlsBuffer TxBuffer = {.pBuffer = TxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize}; - -size_t RxIndex = 0; - -char *invalidEndpointFilter; -char *invalidRootCAPathFilter; -char *invalidCertPathFilter; -char *invalidPrivKeyPathFilter; -uint16_t invalidPortFilter; diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h deleted file mode 100644 index 22a9ead5a..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.h - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#ifndef UNITTESTS_MOCKS_TLS_PARAMS_H_ -#define UNITTESTS_MOCKS_TLS_PARAMS_H_ - -#include -#include -#include -#include - -#define TLSMaxBufferSize 1024 -#define NO_MSG_LENGTH_MENTIONED -1 - -typedef struct { - unsigned char *pBuffer; - size_t len; - bool NoMsgFlag; - struct timeval expiry_time; - size_t BufMaxSize; -} TlsBuffer; - - -extern TlsBuffer RxBuffer; -extern TlsBuffer TxBuffer; - -extern size_t RxIndex; -extern unsigned char RxBuf[TLSMaxBufferSize]; -extern unsigned char TxBuf[TLSMaxBufferSize]; -extern char LastSubscribeMessage[TLSMaxBufferSize]; -extern size_t lastSubscribeMsgLen; -extern char SecondLastSubscribeMessage[TLSMaxBufferSize]; -extern size_t secondLastSubscribeMsgLen; - -extern char hostAddress[512]; -extern uint16_t port; -extern uint32_t handshakeTimeout_ms; - -extern char *invalidEndpointFilter; -extern char *invalidRootCAPathFilter; -extern char *invalidCertPathFilter; -extern char *invalidPrivKeyPathFilter; -extern uint16_t invalidPortFilter; - -#endif /* UNITTESTS_MOCKS_TLS_PARAMS_H_ */ diff --git a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h b/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h deleted file mode 100644 index 1bbec842f..000000000 --- a/components/aws_iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by chaurah on 3/22/16. -// - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - uint32_t flags; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/components/aws_iot/component.mk b/components/aws_iot/component.mk deleted file mode 100644 index cd1b15eee..000000000 --- a/components/aws_iot/component.mk +++ /dev/null @@ -1,20 +0,0 @@ -# -# Component Makefile -# - -ifdef CONFIG_AWS_IOT_SDK - -COMPONENT_ADD_INCLUDEDIRS := include aws-iot-device-sdk-embedded-C/include - -COMPONENT_SRCDIRS := aws-iot-device-sdk-embedded-C/src port - -# Check the submodule is initialised -COMPONENT_SUBMODULES := aws-iot-device-sdk-embedded-C - - -else -# Disable AWS IoT support -COMPONENT_ADD_INCLUDEDIRS := -COMPONENT_ADD_LDFLAGS := -COMPONENT_SRCDIRS := -endif diff --git a/components/aws_iot/include/aws_iot_config.h b/components/aws_iot/include/aws_iot_config.h deleted file mode 100644 index c98f7dea2..000000000 --- a/components/aws_iot/include/aws_iot_config.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef _AWS_IOT_CONFIG_H_ -#define _AWS_IOT_CONFIG_H_ - -#include "aws_iot_log.h" - -// This configuration macro needs to be available globally to enable threading -#define _ENABLE_THREAD_SUPPORT_ - -// These values are defined in the menuconfig of the AWS IoT component. -// However, you can override these constants from your own code. -#define AWS_IOT_MQTT_HOST CONFIG_AWS_IOT_MQTT_HOST ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT CONFIG_AWS_IOT_MQTT_PORT ///< default port for MQTT/S - -// These values are defaults and are used for ShadowConnectParametersDefault. -// You should override them from your own code. -#define AWS_IOT_MQTT_CLIENT_ID "ESP32" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "ESP32" ///< Thing Name of the Shadow this device is associated with - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN CONFIG_AWS_IOT_MQTT_TX_BUF_LEN ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN CONFIG_AWS_IOT_MQTT_RX_BUF_LEN ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#ifdef CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER -#define SHADOW_MAX_SIZE_OF_RX_BUFFER CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER ///< Maximum size of the SHADOW buffer to store the received Shadow message, including NULL terminating byte -#else -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN + 1) -#endif - -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE (MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10) ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE (MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20) ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME ///< All shadow actions have to be published or subscribed to a topic which is of the formablogt $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES (MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME) ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#endif /* _AWS_IOT_CONFIG_H_ */ diff --git a/components/aws_iot/include/aws_iot_log.h b/components/aws_iot/include/aws_iot_log.h deleted file mode 100644 index 9a2043b3e..000000000 --- a/components/aws_iot/include/aws_iot_log.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -/* (these two headers aren't used here, but AWS IoT SDK code relies on them - being included from here...) */ -#include -#include - -#include "esp_log.h" - -/* This is a stub replacement for the aws_iot_log.h header in the AWS IoT SDK, - which redirects their logging framework into the esp-idf logging framework. - - The current (2.1.1) upstream AWS IoT SDK doesn't allow this as some of its - headers include aws_iot_log.h, but our modified fork does. -*/ - -// redefine the AWS IoT log functions to call into the IDF log layer -#define IOT_DEBUG(format, ...) ESP_LOGD("aws_iot", format, ##__VA_ARGS__) -#define IOT_INFO(format, ...) ESP_LOGI("aws_iot", format, ##__VA_ARGS__) -#define IOT_WARN(format, ...) ESP_LOGW("aws_iot", format, ##__VA_ARGS__) -#define IOT_ERROR(format, ...) ESP_LOGE("aws_iot", format, ##__VA_ARGS__) - -/* Function tracing macros used in AWS IoT SDK, - mapped to "verbose" level output -*/ -#define FUNC_ENTRY ESP_LOGV("aws_iot", "FUNC_ENTRY: %s L#%d \n", __func__, __LINE__) -#define FUNC_EXIT_RC(x) \ - do { \ - ESP_LOGV("aws_iot", "FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } while(0) diff --git a/components/aws_iot/include/network_platform.h b/components/aws_iot/include/network_platform.h deleted file mode 100644 index a5e87d71a..000000000 --- a/components/aws_iot/include/network_platform.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/platform.h" -#include "mbedtls/net_sockets.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/components/aws_iot/include/threads_platform.h b/components/aws_iot/include/threads_platform.h deleted file mode 100644 index 011a1a0b2..000000000 --- a/components/aws_iot/include/threads_platform.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_interface.h" - -#ifndef AWS_IOTSDK_THREADS_PLATFORM_H -#define AWS_IOTSDK_THREADS_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - SemaphoreHandle_t mutex; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOTSDK_THREADS_PLATFORM_H */ - - diff --git a/components/aws_iot/include/timer_platform.h b/components/aws_iot/include/timer_platform.h deleted file mode 100644 index 07e7385db..000000000 --- a/components/aws_iot/include/timer_platform.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef AWS_IOT_PLATFORM_H -#define AWS_IOT_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - uint32_t start_ticks; - uint32_t timeout_ticks; - uint32_t last_polled_ticks; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_PLATFORM_H */ diff --git a/components/aws_iot/port/network_mbedtls_wrapper.c b/components/aws_iot/port/network_mbedtls_wrapper.c deleted file mode 100644 index 157c78f0f..000000000 --- a/components/aws_iot/port/network_mbedtls_wrapper.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_error.h" -#include "network_interface.h" -#include "network_platform.h" - -#include "mbedtls/esp_debug.h" - -#include "esp_log.h" - -#ifdef CONFIG_USE_VFS -#include "esp_vfs.h" -#endif - -static const char *TAG = "aws_iot"; - -/* This is the value used for ssl read timeout */ -#define IOT_SSL_READ_TIMEOUT 10 - -/* - * This is a function to do further verification if needed on the cert received. - * - * Currently used to print debug-level information about each cert. - */ -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[256]; - ((void) data); - - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - ESP_LOGD(TAG, "%s", buf); - - if((*flags) == 0) { - ESP_LOGD(TAG, " This certificate has no flags"); - } else { - ESP_LOGD(TAG, "Verify result:%s", buf); - } - } - - return 0; -} - -static void _iot_tls_set_connect_params(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation, - const char *pDevicePrivateKeyLocation, const char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation, - const char *pDevicePrivateKeyLocation, const char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = SUCCESS; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char info_buf[256]; - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - -#ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); -#endif - - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - ESP_LOGD(TAG, "Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) TAG, strlen(TAG))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - /* Load root CA... - - Certs/keys can be paths or they can be raw data. These use a - very basic heuristic: if the cert starts with '/' then it's a - path, if it's longer than this then it's raw cert data (PEM or DER, - neither of which can start with a slash. */ - if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading CA root certificate from file ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); -#else - ESP_LOGE(TAG, "Not to support load CA root certificate from file ..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, - strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); - } - - if(ret < 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - ESP_LOGD(TAG, "ok (%d skipped)", ret); - - /* Load client certificate... */ - if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading client cert from file..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), - pNetwork->tlsConnectParams.pDeviceCertLocation); -#else - ESP_LOGE(TAG, "Not support to load client cert from file..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded client certificate..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), - (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, - strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - /* Parse client private key... */ - if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { -#ifdef CONFIG_USE_VFS - ESP_LOGD(TAG, "Loading client private key from file..."); - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - ""); -#else - ESP_LOGE(TAG, "Not support to load client private key from file..."); - return NETWORK_SSL_CERT_ERROR; -#endif - } else { - ESP_LOGD(TAG, "Loading embedded client private key..."); - ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), - (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, - (const unsigned char *)"", 0); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - - /* Done parsing certs */ - ESP_LOGD(TAG, "ok"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - - /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ - if (pNetwork->tlsConnectParams.DestinationPort == 443) { - const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - } - - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); - return SSL_CONNECTION_ERROR; - } - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - ESP_LOGE(TAG, " Unable to verify the server's certificate. "); - } - return SSL_CONNECTION_ERROR; - } - } - - ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); - } else { - ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); - } - - ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - ESP_LOGE(TAG, "failed"); - mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); - ESP_LOGE(TAG, "%s", info_buf); - ret = SSL_CONNECTION_ERROR; - } else { - ESP_LOGD(TAG, "ok"); - ret = SUCCESS; - } - } else { - ESP_LOGW(TAG, " Server Verification skipped"); - ret = SUCCESS; - } - - if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - ESP_LOGD(TAG, "Peer certificate information:"); - mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - ESP_LOGD(TAG, "%s", info_buf); - } - } - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t written_so_far; - bool isErrorFlag = false; - int frags, ret = 0; - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - for(written_so_far = 0, frags = 0; - written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { - while(!has_timer_expired(timer) && - (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - isErrorFlag = true; - break; - } - } - if(isErrorFlag) { - break; - } - } - - *written_len = written_so_far; - - if(isErrorFlag) { - return NETWORK_SSL_WRITE_ERROR; - } else if(has_timer_expired(timer) && written_so_far != len) { - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - mbedtls_ssl_context *ssl = &(tlsDataParams->ssl); - mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf); - uint32_t read_timeout; - size_t rxLen = 0; - int ret; - - read_timeout = ssl_conf->read_timeout; - - while (len > 0) { - - /* Make sure we never block on read for longer than timer has left, - but also that we don't block indefinitely (ie read_timeout > 0) */ - mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer)))); - - ret = mbedtls_ssl_read(ssl, pMsg, len); - - /* Restore the old timeout */ - mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout); - - if (ret > 0) { - rxLen += ret; - pMsg += ret; - len -= ret; - } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) { - return NETWORK_SSL_READ_ERROR; - } - - // Evaluate timeout after the read to make sure read is done at least once - if (has_timer_expired(timer)) { - break; - } - } - - if (len == 0) { - *read_len = rxLen; - return SUCCESS; - } - - if (rxLen == 0) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} diff --git a/components/aws_iot/port/threads_freertos.c b/components/aws_iot/port/threads_freertos.c deleted file mode 100644 index 065ead78c..000000000 --- a/components/aws_iot/port/threads_freertos.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "threads_platform.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - - pMutex->mutex = xSemaphoreCreateRecursiveMutex(); - return pMutex->mutex ? SUCCESS : MUTEX_INIT_ERROR; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { - xSemaphoreTakeRecursive(pMutex->mutex, portMAX_DELAY); - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { - if (xSemaphoreTakeRecursive(pMutex->mutex, 0)) { - return SUCCESS; - } else { - return MUTEX_LOCK_ERROR; - } -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if (xSemaphoreGiveRecursive(pMutex->mutex)) { - return SUCCESS; - } else { - return MUTEX_UNLOCK_ERROR; - } -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - vSemaphoreDelete(pMutex->mutex); - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - diff --git a/components/aws_iot/port/timer.c b/components/aws_iot/port/timer.c deleted file mode 100644 index ee4d8b5be..000000000 --- a/components/aws_iot/port/timer.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file timer.c - * @brief FreeRTOS implementation of the timer interface uses ticks. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "timer_platform.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" - -const static char *TAG = "aws_timer"; - -bool has_timer_expired(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - bool expired = (now - timer->start_ticks) >= timer->timeout_ticks; - - /* AWS IoT SDK isn't very RTOS friendly because it polls for "done - timers" a lot without ever sleeping on them. So we hack in some - amount of sleeping here: if it seems like the caller is polling - an unexpired timer in a tight loop then we delay a tick to let - things progress elsewhere. - */ - if(!expired && now == timer->last_polled_ticks) { - vTaskDelay(1); - } - timer->last_polled_ticks = now; - return expired; -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - timer->start_ticks = xTaskGetTickCount(); - timer->timeout_ticks = timeout / portTICK_PERIOD_MS; - timer->last_polled_ticks = 0; -} - -uint32_t left_ms(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - uint32_t elapsed = now - timer->start_ticks; - if (elapsed < timer->timeout_ticks) { - return (timer->timeout_ticks - elapsed) * portTICK_PERIOD_MS; - } else { - return 0; - } -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - if (timeout > UINT32_MAX / 1000) { - ESP_LOGE(TAG, "timeout is out of range: %ds", timeout); - } - countdown_ms(timer, timeout * 1000); -} - -void init_timer(Timer *timer) { - timer->start_ticks = 0; - timer->timeout_ticks = 0; - timer->last_polled_ticks = 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/bootloader/CMakeLists.txt b/components/bootloader/CMakeLists.txt new file mode 100644 index 000000000..465d9cdd3 --- /dev/null +++ b/components/bootloader/CMakeLists.txt @@ -0,0 +1,21 @@ +idf_component_register(PRIV_REQUIRES partition_table) + +# Do not generate flash file when building bootloader or is in early expansion of the build +if(BOOTLOADER_BUILD) + return() +endif() + +# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash` +if(NOT CONFIG_SECURE_BOOT_ENABLED) + set(flash_bootloader FLASH_IN_PROJECT) +endif() + +# Set values used in flash_bootloader_args.in and generate flash file +# for bootloader +esptool_py_flash_project_args(bootloader 0x0 + ${BOOTLOADER_BUILD_DIR}/bootloader.bin + ${flash_bootloader} + FLASH_FILE_TEMPLATE flash_bootloader_args.in) + +esptool_py_custom_target(bootloader-flash bootloader "bootloader") +add_dependencies(bootloader partition_table) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 5efa1dc35..2e108b512 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -1,4 +1,31 @@ menu "Bootloader config" + +config BOOTLOADER_INIT_SPI_FLASH + bool "Bootloader init SPI flash" + default y + help + Enable this option, software will initialize SPI flash clock and I/O mode at bootloader instead of at APP. + So it will speed up system starting and reduce the time cost at loading firmware. + + If your system bootloader is based on v3.0, the option must not be enable, because the v3.0 bootloader don't support + this function. + +config BOOTLOADER_DISABLE_JTAG_IO + bool "Bootloader disable JTAG I/O" + default n + help + Enable this option, when SoC brings up and bootloader initializes hardware, it will + disable JTAG's I/O and set these GPIOs to be normal I/O with inputting mode. + + If users use JTAG to help develop, please disable this option. + +config BOOTLOADER_FAST_BOOT + bool "Bootloader fast boot" + default n + help + Enable this option, after initializing hardware, bootloader will try to load boot image + information from RTC memory directly and then run image without verifying it. + choice LOG_BOOTLOADER_LEVEL bool "Bootloader log verbosity" default LOG_BOOTLOADER_LEVEL_INFO @@ -28,23 +55,11 @@ config LOG_BOOTLOADER_LEVEL default 4 if LOG_BOOTLOADER_LEVEL_DEBUG default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE -config BOOTLOADER_CHECK_APP_SUM - bool "Check APP binary data sum before loading" - default y - help - If enable this option, bootloader will check the sum of app binary data before load it to run. - -config BOOTLOADER_CHECK_APP_HASH - bool "Check APP binary data hash before loading" - default n - help - If enable this option, bootloader will check the hash of app binary data before load it to run. - config BOOTLOADER_SPI_WP_PIN int "SPI Flash WP Pin when customising pins via efuse (read help)" range 0 33 default 7 - depends on (FLASHMODE_QIO || FLASHMODE_QOUT) && TARGET_PLATFORM_ESP32 + depends on (ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT) && IDF_TARGET_ESP32 help This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been overriden by setting the efuses SPI_PAD_CONFIG_xxx. @@ -58,7 +73,7 @@ config BOOTLOADER_SPI_WP_PIN choice BOOTLOADER_VDDSDIO_BOOST bool "VDDSDIO LDO voltage" default BOOTLOADER_VDDSDIO_BOOST_1_9V - depends on TARGET_PLATFORM_ESP32 + depends on IDF_TARGET_ESP32 help If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE or MTDI bootstrapping pin), bootloader will change LDO settings to @@ -70,7 +85,7 @@ choice BOOTLOADER_VDDSDIO_BOOST config BOOTLOADER_VDDSDIO_BOOST_1_8V bool "1.8V" - depends on !ESPTOOLPY_FLASHFREQ_80M && TARGET_PLATFORM_ESP32 + depends on !ESPTOOLPY_FLASHFREQ_80M && IDF_TARGET_ESP32 config BOOTLOADER_VDDSDIO_BOOST_1_9V bool "1.9V" endchoice @@ -78,7 +93,7 @@ endchoice config BOOTLOADER_FACTORY_RESET bool "GPIO triggers factory reset" default N - depends on TARGET_PLATFORM_ESP32 + depends on IDF_TARGET_ESP32 help Allows to reset the device to factory settings: - clear one or more data partitions; @@ -88,7 +103,7 @@ config BOOTLOADER_FACTORY_RESET config BOOTLOADER_NUM_PIN_FACTORY_RESET int "Number of the GPIO input for factory reset" - depends on BOOTLOADER_FACTORY_RESET && TARGET_PLATFORM_ESP32 + depends on BOOTLOADER_FACTORY_RESET && IDF_TARGET_ESP32 range 0 39 default 4 help @@ -108,31 +123,40 @@ config BOOTLOADER_DATA_FACTORY_RESET default "nvs" help Allows customers to select which data partitions will be erased while factory reset. - + Specify the names of partitions as a comma-delimited with optional spaces for readability. (Like this: "nvs, phy_init, ...") Make sure that the name specified in the partition table and here are the same. Partitions of type "app" cannot be specified here. config BOOTLOADER_APP_TEST bool "GPIO triggers boot from test app partition" - default N - depends on TARGET_PLATFORM_ESP32 + default n help Allows to run the test app from "TEST" partition. A boot from "test" partition will occur if there is a GPIO input pulled low while device starts up. See settings below. +config BOOTLOADER_APP_TEST_IN_OTA_1 + depends on BOOTLOADER_APP_TEST && IDF_TARGET_ESP8266 + bool "Put test app in the ota_1 partition" + default y + help + For the small SPI Flash solution, there maybe no enough space for the test app partition. + By enable this option, test app will locate in ota_1 partition by default. + After ota, the test app will be erased and re-write as new app. + + If you disable this, make sure there has a test app partition in you partition table CVS. + config BOOTLOADER_NUM_PIN_APP_TEST int "Number of the GPIO input to boot TEST partition" depends on BOOTLOADER_APP_TEST - range 0 39 - default 18 + range 0 15 + default 2 help The selected GPIO will be configured as an input with internal pull-up enabled. - To trigger a test app, this GPIO must be pulled low on reset. + To trigger a test app(the second ota firmware), this GPIO must be pulled low on reset. After the GPIO input is deactivated and the device reboots, the old application will boot. (factory or OTA[x]). - Note that GPIO34-39 do not have an internal pullup and an external one must be provided. config BOOTLOADER_HOLD_TIME_GPIO int "Hold time of GPIO for reset/test mode (seconds)" @@ -142,11 +166,28 @@ config BOOTLOADER_HOLD_TIME_GPIO The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. +config BOOTLOADER_STORE_OFFSET + hex "Bootloader store offset in the flash" + default 0x0 + help + Bootloader store offset in the flash, if you have extra private bootloader to boot the + bootloader of the SDK's bootloader, you can set the option to store SDK's bootloader + to other space in the flash instead of "0x0". + +config BOOTLOADER_FLASH_XMC_SUPPORT + bool "Enable the support for flash chips of XMC (READ HELP FIRST)" + default y + help + Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow. + XMC chips will be forbidden to be used, when this option is disabled. + + DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. + endmenu # Bootloader menu "Security features" - depends on TARGET_PLATFORM_ESP32 + depends on IDF_TARGET_ESP32 config SECURE_BOOT_ENABLED bool "Enable secure boot in bootloader (READ DOCS FIRST)" diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 734e30925..070706fd1 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -18,7 +18,7 @@ SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KE export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component # Has a matching value in bootloader_support esp_flash_partitions.h -BOOTLOADER_OFFSET := 0x0000 +BOOTLOADER_OFFSET := $(CONFIG_BOOTLOADER_STORE_OFFSET) # Custom recursive make for bootloader sub-project # diff --git a/components/bootloader/flash_bootloader_args.in b/components/bootloader/flash_bootloader_args.in new file mode 100644 index 000000000..2867c5aaf --- /dev/null +++ b/components/bootloader/flash_bootloader_args.in @@ -0,0 +1,4 @@ +--flash_mode ${ESPFLASHMODE} +--flash_size ${ESPFLASHSIZE} +--flash_freq ${ESPFLASHFREQ} +${OFFSET} ${IMAGE} diff --git a/components/bootloader/project_include.cmake b/components/bootloader/project_include.cmake new file mode 100644 index 000000000..fe0a783c3 --- /dev/null +++ b/components/bootloader/project_include.cmake @@ -0,0 +1,127 @@ +set(BOOTLOADER_OFFSET 0x1000) + +# Do not generate flash file when building bootloader +if(BOOTLOADER_BUILD) + return() +endif() + +# Glue to build the bootloader subproject binary as an external +# cmake project under this one +# +# +idf_build_get_property(build_dir BUILD_DIR) +set(BOOTLOADER_BUILD_DIR "${build_dir}/bootloader") +set(bootloader_binary_files + "${BOOTLOADER_BUILD_DIR}/bootloader.elf" + "${BOOTLOADER_BUILD_DIR}/bootloader.bin" + "${BOOTLOADER_BUILD_DIR}/bootloader.map" + ) + +idf_build_get_property(project_dir PROJECT_DIR) + +# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens +# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES. +# For both cases, the user either sets binaries to be signed during build or not +# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES. +# +# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject +# via config. +if(CONFIG_SECURE_SIGNED_APPS) + add_custom_target(gen_secure_boot_keys) + + if(CONFIG_SECURE_BOOT_ENABLED) + # Check that the configuration is sane + if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR + (NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)) + fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?") + endif() + + if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) + set(bootloader_binary_files + ${bootloader_binary_files} + "${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin" + "${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin" + "${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin" + ) + endif() + endif() + + # Since keys are usually given relative to main project dir, get the absolute paths to the keys + # for use by the bootloader subproject. Replace the values in config with these absolute paths, + # so that bootloader subproject does not need to assume main project dir to obtain path to the keys. + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + get_filename_component(secure_boot_signing_key + "${CONFIG_SECURE_BOOT_SIGNING_KEY}" + ABSOLUTE BASE_DIR "${project_dir}") + + if(NOT EXISTS ${secure_boot_signing_key}) + # If the signing key is not found, create a phony gen_secure_boot_signing_key target that + # fails the build. fail_at_build_time causes a cmake run next time + # (to pick up a new signing key if one exists, etc.) + fail_at_build_time(gen_secure_boot_signing_key + "Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:" + "\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}") + else() + add_custom_target(gen_secure_boot_signing_key) + endif() + + set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components + set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}") + + add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key) + else() + + get_filename_component(secure_boot_verification_key + ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} + ABSOLUTE BASE_DIR "${project_dir}") + + if(NOT EXISTS ${secure_boot_verification_key}) + # If the verification key is not found, create a phony gen_secure_boot_verification_key target that + # fails the build. fail_at_build_time causes a cmake run next time + # (to pick up a new verification key if one exists, etc.) + fail_at_build_time(gen_secure_boot_verification_key + "Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist." + "\tThis can be extracted from the private signing key." + "\tSee docs/security/secure-boot.rst for details.") + else() + add_custom_target(gen_secure_boot_verification_key) + endif() + + set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}") + + add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key) + endif() +endif() + +idf_build_get_property(idf_path IDF_PATH) +idf_build_get_property(idf_target IDF_TARGET) +idf_build_get_property(sdkconfig SDKCONFIG) + +externalproject_add(bootloader + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject" + BINARY_DIR "${BOOTLOADER_BUILD_DIR}" + CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target} + -DPYTHON_DEPS_CHECKED=1 + -DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR} + ${sign_key_arg} ${ver_key_arg} + # LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since + # the bootloader common component requirements depends on this and + # config variables are not available before project() call. + -DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS} + INSTALL_COMMAND "" + BUILD_ALWAYS 1 # no easy way around this... + BUILD_BYPRODUCTS ${bootloader_binary_files} + ) + +if(CONFIG_SECURE_SIGNED_APPS) + add_dependencies(bootloader gen_secure_boot_keys) +endif() + +# this is a hack due to an (annoying) shortcoming in cmake, it can't +# extend the 'clean' target to the external project +# see thread: https://cmake.org/pipermail/cmake/2016-December/064660.html +# +# So for now we just have the top-level build remove the final build products... +set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + ${bootloader_binary_files}) diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt new file mode 100644 index 000000000..33ef8ce2f --- /dev/null +++ b/components/bootloader/subproject/CMakeLists.txt @@ -0,0 +1,128 @@ +cmake_minimum_required(VERSION 3.5) + +if(NOT SDKCONFIG) + message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed " + "in by the parent build process.") +endif() + +if(NOT IDF_PATH) + message(FATAL_ERROR "Bootloader subproject expects the IDF_PATH variable to be passed " + "in by the parent build process.") +endif() + +if(NOT IDF_TARGET) + message(FATAL_ERROR "Bootloader subproject expects the IDF_TARGET variable to be passed " + "in by the parent build process.") +endif() + +set(COMPONENTS bootloader esptool_py partition_table esp8266 bootloader_support log spi_flash main) +set(BOOTLOADER_BUILD 1) +include("${IDF_PATH}/tools/cmake/project.cmake") +set(common_req log esp_common) +if(LEGACY_INCLUDE_COMMON_HEADERS) + list(APPEND common_req soc) +endif() +idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}") +idf_build_set_property(__OUTPUT_SDKCONFIG 0) +project(bootloader) + +idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND) + +string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") +string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}") +set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}") + +if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) + if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT) + set(key_digest_len 192) + else() + set(key_digest_len 256) + endif() + + get_filename_component(bootloader_digest_bin + "bootloader-reflash-digest.bin" + ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") + + get_filename_component(secure_bootloader_key + "secure-bootloader-key-${key_digest_len}.bin" + ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") + + add_custom_command(OUTPUT "${secure_bootloader_key}" + COMMAND ${ESPSECUREPY} digest_private_key + --keylen "${key_digest_len}" + --keyfile "${SECURE_BOOT_SIGNING_KEY}" + "${secure_bootloader_key}" + VERBATIM) + + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + add_custom_target(gen_secure_bootloader_key ALL DEPENDS "${secure_bootloader_key}") + else() + if(NOT EXISTS "${secure_bootloader_key}") + message(FATAL_ERROR + "No pre-generated key for a reflashable secure bootloader is available, " + "due to signing configuration." + "\nTo generate one, you can use this command:" + "\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}" + "\nIf a signing key is present, then instead use:" + "\n\t${espsecurepy} digest_private_key " + "--keylen (192/256) --keyfile KEYFILE " + "${secure_bootloader_key}") + endif() + add_custom_target(gen_secure_bootloader_key) + endif() + + add_custom_command(OUTPUT "${bootloader_digest_bin}" + COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}" + COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}" + -o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin" + DEPENDS gen_secure_bootloader_key gen_project_binary + VERBATIM) + + add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}") +endif() + +if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) + add_custom_command(TARGET bootloader.elf POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + COMMAND ${CMAKE_COMMAND} -E echo + "Bootloader built. Secure boot enabled, so bootloader not flashed automatically." + COMMAND ${CMAKE_COMMAND} -E echo + "One-time flash command is:" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin" + COMMAND ${CMAKE_COMMAND} -E echo + "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device" + VERBATIM) +elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) + add_custom_command(TARGET bootloader.elf POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + COMMAND ${CMAKE_COMMAND} -E echo + "Bootloader built and secure digest generated." + COMMAND ${CMAKE_COMMAND} -E echo + "Secure boot enabled, so bootloader not flashed automatically." + COMMAND ${CMAKE_COMMAND} -E echo + "Burn secure boot key to efuse using:" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${espefusepy} burn_key secure_boot ${secure_bootloader_key}" + COMMAND ${CMAKE_COMMAND} -E echo + "First time flash command is:" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin" + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + COMMAND ${CMAKE_COMMAND} -E echo + "To reflash the bootloader after initial flash:" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${esptoolpy_write_flash} 0x0 ${bootloader_digest_bin}" + COMMAND ${CMAKE_COMMAND} -E echo + "==============================================================================" + COMMAND ${CMAKE_COMMAND} -E echo + "* After first boot, only re-flashes of this kind (with same key) will be accepted." + COMMAND ${CMAKE_COMMAND} -E echo + "* Not recommended to re-use the same secure boot keyfile on multiple production devices." + DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin + VERBATIM) +endif() diff --git a/components/bootloader/subproject/Makefile b/components/bootloader/subproject/Makefile index ebd028c6e..d05b8104c 100644 --- a/components/bootloader/subproject/Makefile +++ b/components/bootloader/subproject/Makefile @@ -8,14 +8,15 @@ endif PROJECT_NAME := bootloader -COMPONENTS := esptool_py main bootloader_support spi_flash log esp8266 util +COMPONENTS := esptool_py main bootloader_support spi_flash log $(IDF_TARGET) # Clear C and CXX from top level project CFLAGS = CXXFLAGS = #We cannot include the esp8266 component directly but we need its includes. -CFLAGS += -I $(IDF_PATH)/components/esp8266/include -I $(IDF_PATH)/components/util/include +CFLAGS += -I $(IDF_PATH)/components/$(IDF_TARGET)/include -I $(IDF_PATH)/components/mbedtls/port/include/$(IDF_TARGET) +CFLAGS += -I $(IDF_PATH)/components/esp_common/include # The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included. # diff --git a/components/bootloader/subproject/main/CMakeLists.txt b/components/bootloader/subproject/main/CMakeLists.txt new file mode 100644 index 000000000..f9da8b987 --- /dev/null +++ b/components/bootloader/subproject/main/CMakeLists.txt @@ -0,0 +1,11 @@ +idf_component_register(SRCS "bootloader_start.c" + REQUIRES bootloader bootloader_support spi_flash) + +idf_build_get_property(target IDF_TARGET) +set(scripts "${target}.bootloader.ld" + "${target}.bootloader.rom.ld" + "${ESP8266_BOOTLOADER_LINKER_SCRIPTS}") + +target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}") + +target_link_libraries(${COMPONENT_LIB} INTERFACE "${ESP8266_BOOTLOADER_LIBS}") diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index b5c68ea3d..d79496db8 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -18,8 +18,11 @@ #include "bootloader_config.h" #include "bootloader_init.h" #include "bootloader_utility.h" +#include "bootloader_common.h" #include "esp_image_format.h" +#include "esp_spi_flash.h" #include "esp_log.h" +#include "driver/soc.h" static const char* TAG = "boot"; @@ -28,11 +31,24 @@ static int selected_boot_partition(const bootloader_state_t *bs); void call_start_cpu(void) { + esp_irqflag_t irq; + + irq = soc_save_local_irq(); + ESP_LOGD(TAG, "CPU local irq: 0x%x", irq); + +#ifdef CONFIG_BOOTLOADER_FAST_BOOT + REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); +#endif + // 1. Hardware initialization if(bootloader_init() != ESP_OK){ return; } +#ifdef CONFIG_BOOTLOADER_FAST_BOOT + bootloader_utility_fast_boot_image(); +#endif + // 2. Select image to boot esp_image_metadata_t image_data; if(select_image(&image_data) != ESP_OK){ @@ -97,6 +113,11 @@ static int selected_boot_partition(const bootloader_state_t *bs) #ifdef CONFIG_BOOTLOADER_APP_TEST if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) { ESP_LOGI(TAG, "Detect a boot condition of the test firmware"); +#ifdef CONFIG_BOOTLOADER_APP_TEST_IN_OTA_1 + /* In this case, test bin will locate in ota_1 by default. + This is the solution for small Flash. */ + return 1; +#else if (bs->test.offset != 0) { boot_index = TEST_APP_INDEX; return boot_index; @@ -104,6 +125,19 @@ static int selected_boot_partition(const bootloader_state_t *bs) ESP_LOGE(TAG, "Test firmware is not found in partition table"); return INVALID_INDEX; } +#endif + } +#endif +#ifdef CONFIG_ESP8266_BOOT_COPY_APP + if (boot_index == 1) { + ESP_LOGI(TAG, "Copy application from OAT1 to OTA0, please wait ..."); + int ret = esp_patition_copy_ota1_to_ota0(bs); + if (ret) { + ESP_LOGE(TAG, "Fail to initialize OTA0"); + return INVALID_INDEX; + } + + boot_index = 0; } #endif // Customer implementation. diff --git a/components/bootloader/subproject/main/component.mk b/components/bootloader/subproject/main/component.mk index fd4cc90c4..76688a32d 100644 --- a/components/bootloader/subproject/main/component.mk +++ b/components/bootloader/subproject/main/component.mk @@ -10,6 +10,6 @@ LINKER_SCRIPTS := \ $(IDF_PATH)/components/esp8266/ld/esp8266.rom.ld \ esp8266.bootloader.rom.ld -COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS)) +COMPONENT_ADD_LDFLAGS += -L $(IDF_PATH)/components/esp8266/lib -lcore -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS)) COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS) diff --git a/components/bootloader/subproject/main/esp8266.bootloader.ld b/components/bootloader/subproject/main/esp8266.bootloader.ld index 122dfd332..17572a531 100644 --- a/components/bootloader/subproject/main/esp8266.bootloader.ld +++ b/components/bootloader/subproject/main/esp8266.bootloader.ld @@ -12,8 +12,8 @@ MEMORY { dport0_seg : org = 0x3FF00000, len = 0x10 - /* All .data/.bss/heap are in this segment. */ - dram_seg : org = 0x3FFE8000, len = 0x18000 + /* All .data/.bss/heap are in this segment. Reserve 1KB for old boot or ROM boot */ + dram_seg : org = 0x3FFE8000, len = 0x18000 - 0x400 /* Functions which are critical should be put in this segment. */ iram_seg : org = 0x40100000, len = 0x8000 @@ -124,3 +124,5 @@ SECTIONS _heap_start = ABSOLUTE(.); } >dram_seg } + +PROVIDE ( rtc_sys_info = 0x60001100 ); diff --git a/components/bootloader/subproject/main/esp8266.bootloader.rom.ld b/components/bootloader/subproject/main/esp8266.bootloader.rom.ld index a9e485592..27d35bbee 100644 --- a/components/bootloader/subproject/main/esp8266.bootloader.rom.ld +++ b/components/bootloader/subproject/main/esp8266.bootloader.rom.ld @@ -1,7 +1,12 @@ PROVIDE ( ets_memcpy = 0x400018b4 ); PROVIDE ( SPIRead = 0x40004b1c ); +PROVIDE ( SPIWrite = 0x40004a4c ); +PROVIDE ( SPIEraseSector = 0x40004a00 ); + +PROVIDE ( gpio_input_get = 0x40004cf0 ); PROVIDE ( xthal_get_ccount = 0x4000dd38 ); PROVIDE ( uart_div_modify = 0x400039d8 ); -PROVIDE ( ets_io_vprintf = 0x40001f00 ); \ No newline at end of file +PROVIDE ( ets_io_vprintf = 0x40001f00 ); +PROVIDE ( ets_rom_delay_us = 0x40002ecc ); \ No newline at end of file diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt new file mode 100644 index 000000000..574dfe7ed --- /dev/null +++ b/components/bootloader_support/CMakeLists.txt @@ -0,0 +1,14 @@ +set(COMPONENT_SRCDIRS "src") + +if(${BOOTLOADER_BUILD}) + set(COMPONENT_ADD_INCLUDEDIRS "include include_priv") + set(COMPONENT_REQUIRES) + set(COMPONENT_PRIV_REQUIRES spi_flash) +else() + set(COMPONENT_ADD_INCLUDEDIRS "include") + set(COMPONENT_PRIV_INCLUDEDIRS "include_priv") + set(COMPONENT_REQUIRES) + set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls) +endif() + +register_component() diff --git a/components/bootloader_support/Makefile.projbuild b/components/bootloader_support/Makefile.projbuild index 6def8a294..ee62930c6 100644 --- a/components/bootloader_support/Makefile.projbuild +++ b/components/bootloader_support/Makefile.projbuild @@ -5,11 +5,3 @@ $(SECURE_BOOT_SIGNING_KEY): @echo "Keep key file safe after generating." @echo "(See secure boot documentation for risks & alternatives.)" @exit 1 - -ifdef CONFIG_BOOTLOADER_CHECK_APP_SUM -CFLAGS += -DCONFIG_ENABLE_BOOT_CHECK_SUM=1 -endif - -ifdef CONFIG_BOOTLOADER_CHECK_APP_HASH -CFLAGS += -DCONFIG_ENABLE_BOOT_CHECK_SHA256=1 -endif diff --git a/components/bootloader_support/include/esp_app_format.h b/components/bootloader_support/include/esp_app_format.h new file mode 100644 index 000000000..a21ad60ed --- /dev/null +++ b/components/bootloader_support/include/esp_app_format.h @@ -0,0 +1,38 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include + +#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */ + +/** + * @brief Description about application. + */ +typedef struct { + uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */ + uint32_t secure_version; /*!< Secure version */ + uint32_t reserv1[2]; /*!< reserv1 */ + char version[32]; /*!< Application version */ + char project_name[32]; /*!< Project name */ + char time[16]; /*!< Compile time */ + char date[16]; /*!< Compile date*/ + char idf_ver[32]; /*!< Version IDF */ + uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */ + uint32_t reserv2[20]; /*!< reserv2 */ +} esp_app_desc_t; + +/** @cond */ +_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes"); +/** @endcond */ diff --git a/components/spi_flash/include/esp_flash_data_types.h b/components/bootloader_support/include/esp_flash_data_types.h similarity index 100% rename from components/spi_flash/include/esp_flash_data_types.h rename to components/bootloader_support/include/esp_flash_data_types.h diff --git a/components/bootloader_support/include/esp_flash_partitions.h b/components/bootloader_support/include/esp_flash_partitions.h index ee4131011..79c35b050 100644 --- a/components/bootloader_support/include/esp_flash_partitions.h +++ b/components/bootloader_support/include/esp_flash_partitions.h @@ -23,11 +23,11 @@ /* Pre-partition table fixed flash offsets */ #define ESP_BOOTLOADER_DIGEST_OFFSET 0x0 -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #define ESP_BOOTLOADER_OFFSET 0x1000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */ #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #define ESP_BOOTLOADER_OFFSET 0x0000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */ #endif diff --git a/components/bootloader_support/include/esp_image_format.h b/components/bootloader_support/include/esp_image_format.h index c8be9f661..c427cffa4 100644 --- a/components/bootloader_support/include/esp_image_format.h +++ b/components/bootloader_support/include/esp_image_format.h @@ -44,7 +44,7 @@ enum { ESP_IMAGE_SPI_SPEED_80M = 0xF } esp_image_spi_freq_t; -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 /* Supported SPI flash sizes */ typedef enum { ESP_IMAGE_FLASH_SIZE_1MB = 0, @@ -56,7 +56,7 @@ typedef enum { } esp_image_flash_size_t; #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 /* Supported SPI flash sizes */ typedef enum { ESP_IMAGE_FLASH_SIZE_512KB = 0, @@ -87,7 +87,7 @@ typedef struct { uint8_t spi_size: 4; uint32_t entry_addr; -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 /* WP pin when SPI pins set via efuse (read by ROM bootloader, the IDF bootloader uses software to configure the WP * pin and sets this field to 0xEE=disabled) */ uint8_t wp_pin; @@ -102,11 +102,11 @@ typedef struct { #endif } __attribute__((packed)) esp_image_header_t; -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 _Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes"); #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 _Static_assert(sizeof(esp_image_header_t) == 8, "binary image header should be 8 bytes"); #endif diff --git a/components/bootloader_support/include_priv/bootloader_config.h b/components/bootloader_support/include_priv/bootloader_config.h index dc5c6a6b2..78160341d 100644 --- a/components/bootloader_support/include_priv/bootloader_config.h +++ b/components/bootloader_support/include_priv/bootloader_config.h @@ -22,6 +22,7 @@ extern "C" { #endif +#include "sdkconfig.h" #include "esp_flash_data_types.h" #define SPI_SEC_SIZE 0x1000 @@ -34,6 +35,9 @@ typedef struct { esp_partition_pos_t ota_info; esp_partition_pos_t factory; esp_partition_pos_t test; +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + esp_partition_pos_t rf; +#endif esp_partition_pos_t ota[MAX_OTA_SLOTS]; uint32_t app_count; uint32_t selected_subtype; diff --git a/components/bootloader_support/include_priv/bootloader_flash.h b/components/bootloader_support/include_priv/bootloader_flash.h index 763136e03..101a32752 100644 --- a/components/bootloader_support/include_priv/bootloader_flash.h +++ b/components/bootloader_support/include_priv/bootloader_flash.h @@ -22,6 +22,11 @@ #define FLASH_SECTOR_SIZE 0x1000 +#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */ +#define CMD_RDJEDECID 0x9F /* Read the JEDEC ID of the flash */ + +#define XMC_VENDOR_ID 0x20 + /* Provide a Flash API for bootloader_support code, that can be used from bootloader or app code. @@ -100,4 +105,20 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool */ esp_err_t bootloader_flash_erase_sector(size_t sector); +/** + * @brief Read the SFDP of the flash + * + * @param sfdp_addr Address of the parameter to read + * @param miso_byte_num Bytes to read + * @return The read SFDP, little endian, 4 bytes at most + */ +uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num); + +/** + * @brief Startup flow recommended by XMC. Call at startup before any erase/write operation. + * + * @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write). + */ +esp_err_t bootloader_flash_xmc_startup(void); + #endif diff --git a/components/bootloader_support/include_priv/bootloader_utility.h b/components/bootloader_support/include_priv/bootloader_utility.h index 6cf6a77e1..a2bc83288 100644 --- a/components/bootloader_support/include_priv/bootloader_utility.h +++ b/components/bootloader_support/include_priv/bootloader_utility.h @@ -62,3 +62,8 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ * @param[in] data Structure to hold on-flash image metadata. */ void bootloader_utility_load_image(const esp_image_metadata_t* image_data); + +/** + * @brief Loading boot image information from RTC memory and then running image without verifying. + */ +void bootloader_utility_fast_boot_image(void); diff --git a/components/bootloader_support/src/bootloader_clock.c b/components/bootloader_support/src/bootloader_clock.c index ecc77b40c..d46d1aea3 100644 --- a/components/bootloader_support/src/bootloader_clock.c +++ b/components/bootloader_support/src/bootloader_clock.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include "rom/uart.h" #include "rom/rtc.h" diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 1772a9785..5267a66f1 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include @@ -160,16 +160,23 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include #include +#include + #include "esp_err.h" #include "esp_log.h" -#include "crc.h" +#include "rom/crc.h" + +#include "rom/gpio.h" #include "bootloader_config.h" +#include "bootloader_common.h" + +static const char *TAG = "bootloader_common"; uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s) { @@ -181,4 +188,24 @@ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s) return s->ota_seq != UINT32_MAX && s->crc == bootloader_common_ota_select_crc(s); } +esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec) +{ + gpio_pad_select_gpio(num_pin); + gpio_pad_pullup(num_pin); + + uint32_t tm_start = esp_log_early_timestamp(); + if (GPIO_INPUT_GET(num_pin) == 1) { + ESP_LOGD(TAG, "gpio %d input %x", num_pin, GPIO_INPUT_GET(num_pin)); + return GPIO_NOT_HOLD; + } + do { + if (GPIO_INPUT_GET(num_pin) != 0) { + ESP_LOGD(TAG, "gpio %d input %x", num_pin, GPIO_INPUT_GET(num_pin)); + return GPIO_SHORT_HOLD; + } + } while (delay_sec > ((esp_log_early_timestamp() - tm_start) / 1000L)); + ESP_LOGD(TAG, "gpio %d input %x", num_pin, GPIO_INPUT_GET(num_pin)); + return GPIO_LONG_HOLD; +} + #endif diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 4a6a134d8..47edf2126 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include @@ -256,30 +256,33 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include #include #include "esp_err.h" #include "esp_log.h" +#include "esp8266/rom_functions.h" #ifndef BOOTLOADER_BUILD #include "esp_spi_flash.h" +#else +#include "bootloader_flash.h" +#include "priv/esp_spi_flash_raw.h" #endif -extern void Cache_Read_Disable(); -extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); +#ifdef CONFIG_SOC_FULL_ICACHE +#define SOC_CACHE_SIZE 1 // 32KB +#else +#define SOC_CACHE_SIZE 0 // 16KB +#endif -static const char *TAG = "bootloader_flash"; +#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT -typedef enum { SPI_FLASH_RESULT_OK = 0, - SPI_FLASH_RESULT_ERR = 1, - SPI_FLASH_RESULT_TIMEOUT = 2 } SpiFlashOpResult; +#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF) -SpiFlashOpResult SPIRead(uint32_t addr, void *dst, uint32_t size); -SpiFlashOpResult SPIWrite(uint32_t addr, const uint8_t *src, uint32_t size); -SpiFlashOpResult SPIEraseSector(uint32_t sector_num); +static const char *TAG = "bootloader_flash"; static bool mapped; @@ -290,21 +293,48 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size) return NULL; /* can't map twice */ } - /* ToDo: Improve the map policy! */ - - Cache_Read_Disable(); + /* 0: 0x000000 - 0x1fffff */ + /* 1: 0x200000 - 0x3fffff */ + /* 2: 0x400000 - 0x5fffff */ + /* 3: 0x600000 - 0x7fffff */ + + uint32_t region; + uint32_t sub_region; + uint32_t mapped_src; + + if (src_addr < 0x200000) { + region = 0; + } else if (src_addr < 0x400000) { + region = 1; + } else if (src_addr < 0x600000) { + region = 2; + } else if (src_addr < 0x800000) { + region = 3; + } else { + ESP_LOGE(TAG, "flash mapped address %p is invalid", (void *)src_addr); + while (1); + } - /* 0 and 0x100000 address use same mmap addresss 0x40200000 */ - if (src_addr < 0x100000) { - Cache_Read_Enable(0, 0, 0); + /* 0: 0x000000 - 0x0fffff \ */ + /* \ */ + /* 0x40200000 */ + /* / */ + /* 1: 0x100000 - 0x1fffff / */ + mapped_src = src_addr & 0x1fffff; + if (mapped_src < 0x100000) { + sub_region = 0; } else { - Cache_Read_Enable(1, 0, 0); - src_addr -= 0x100000; + sub_region = 1; + mapped_src -= 0x100000; } + Cache_Read_Disable(); + + Cache_Read_Enable(sub_region, region, SOC_CACHE_SIZE); + mapped = true; - return (void *)(0x40200000 + src_addr); + return (void *)(0x40200000 + mapped_src); } void bootloader_munmap(const void *mapping) @@ -373,4 +403,150 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) return ESP_OK; } +#ifdef BOOTLOADER_BUILD +uint32_t bootloader_read_flash_id(void) +{ + uint32_t id = spi_flash_get_id_raw(&g_rom_flashchip); + id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); + return id; +} + +#if XMC_SUPPORT +static bool is_xmc_chip_strict(uint32_t rdid) +{ + uint32_t vendor_id = BYTESHIFT(rdid, 2); + uint32_t mfid = BYTESHIFT(rdid, 1); + uint32_t cpid = BYTESHIFT(rdid, 0); + + if (vendor_id != XMC_VENDOR_ID) { + return false; + } + + bool matched = false; + if (mfid == 0x40) { + if (cpid >= 0x13 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x41) { + if (cpid >= 0x17 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x50) { + if (cpid >= 0x15 && cpid <= 0x16) { + matched = true; + } + } + return matched; +} + +bool bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) +{ + bool ret; + spi_cmd_t cmd; + + cmd.cmd = command; + cmd.cmd_len = 1; + cmd.addr = NULL; + cmd.addr_len = 0; + cmd.dummy_bits = 0; + cmd.data = NULL; + cmd.data_len = 0; + + ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_TX, &cmd); + if (!ret) { + ESP_LOGE(TAG, "failed to write cmd=%02x", command); + } + + return ret; +} + +uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num) +{ + bool ret; + spi_cmd_t cmd; + uint32_t data = 0; + uint32_t addr = sfdp_addr << 8; + + cmd.cmd = CMD_RDSFDP; + cmd.cmd_len = 1; + cmd.addr = &addr; + cmd.addr_len = 3; + cmd.dummy_bits = 8; + cmd.data = &data; + cmd.data_len = miso_byte_num; + + ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_RX, &cmd); + if (!ret) { + ESP_LOGE(TAG, "failed to read sfdp"); + } + + return data; +} + +esp_err_t bootloader_flash_xmc_startup(void) +{ + extern void ets_rom_delay_us(uint16_t us); + + uint32_t id = bootloader_read_flash_id(); + + // If the RDID value is a valid XMC one, may skip the flow + const bool fast_check = true; + if (fast_check && is_xmc_chip_strict(id)) { + ESP_LOGD(TAG, "XMC chip detected by RDID (%08X), skip.", id); + return ESP_OK; + } + + // Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow + const int sfdp_mfid_addr = 0x10; + uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff); + if (mf_id != XMC_VENDOR_ID) { + ESP_LOGD(TAG, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id); + return ESP_OK; + } + + ESP_LOGI(TAG, "XM25QHxxC startup flow"); + // Enter DPD + bootloader_execute_flash_command(0xB9, 0, 0, 0); + // Enter UDPD + bootloader_execute_flash_command(0x79, 0, 0, 0); + // Exit UDPD + bootloader_execute_flash_command(0xFF, 0, 0, 0); + // Delay tXUDPD + ets_rom_delay_us(2000); + // Release Power-down + bootloader_execute_flash_command(0xAB, 0, 0, 0); + ets_rom_delay_us(20); + // Read flash ID and check again + id = bootloader_read_flash_id(); + if (!is_xmc_chip_strict(id)) { + ESP_LOGE(TAG, "XMC flash startup fail"); + return ESP_FAIL; + } + + return ESP_OK; +} +#else +static bool is_xmc_chip(uint32_t rdid) +{ + uint32_t vendor_id = (rdid >> 16) &0xff; + + return vendor_id == XMC_VENDOR_ID; +} + +esp_err_t bootloader_flash_xmc_startup(void) +{ + uint32_t id = bootloader_read_flash_id(); + + if (is_xmc_chip(id)) { + ESP_LOGE(TAG, "XMC chip detected(%08X) while support disable.", id); + return ESP_FAIL; + } else { + ESP_LOGI(TAG, "flash chip is %08X", id); + } + + return ESP_OK; +} +#endif +#endif + #endif diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index a7e518bbc..2ca04d11f 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include @@ -164,7 +164,7 @@ static esp_err_t bootloader_main() ESP_LOGI(TAG, "Enabling RNG early entropy source..."); bootloader_random_enable(); -#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT +#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT bootloader_enable_qio_mode(); #endif @@ -536,7 +536,7 @@ void __assert_func(const char *file, int line, const char *func, const char *exp #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include @@ -553,7 +553,24 @@ void __assert_func(const char *file, int line, const char *func, const char *exp #include "esp8266/pin_mux_register.h" #include "esp8266/rom_functions.h" -#define BOOTLOADER_CONSOLE_CLK_FREQ 52 * 1000 * 1000 +#define BOOTLOADER_CONSOLE_CLK_FREQ ((CONFIG_ESP8266_XTAL_FREQ * 2) * 1000 * 1000) + +/** + * XTAL=26MHz, UART baudrate=74880 (default) + * XTAL=40MHz, UART baudrate=115200 (default) + */ + +#if CONFIG_ESP_CONSOLE_UART_NUM == 0 +# if CONFIG_ESP8266_XTAL_FREQ == 26 && CONFIG_ESP_CONSOLE_UART_BAUDRATE == 74880 +# define ESP8266_MODIFY_UART_BAUDRATE 0 +# elif CONFIG_ESP8266_XTAL_FREQ == 40 && CONFIG_ESP_CONSOLE_UART_BAUDRATE == 115200 +# define ESP8266_MODIFY_UART_BAUDRATE 0 +# endif +#endif + +#ifndef ESP8266_MODIFY_UART_BAUDRATE +# define ESP8266_MODIFY_UART_BAUDRATE 1 +#endif extern int _bss_start; extern int _bss_end; @@ -568,7 +585,7 @@ static void update_flash_config(const esp_image_header_t* pfhdr); static void uart_console_configure(void) { -#if CONFIG_CONSOLE_UART_SWAP_IO +#if CONFIG_ESP_UART0_SWAP_IO while (READ_PERI_REG(UART_STATUS(0)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); @@ -578,24 +595,38 @@ static void uart_console_configure(void) SET_PERI_REG_MASK(UART_SWAP_REG, 0x4); #endif -#if CONFIG_CONSOLE_UART_NUM == 1 +#if CONFIG_ESP_CONSOLE_UART_NUM == 1 PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); - CLEAR_PERI_REG_MASK(UART_CONF1(CONFIG_CONSOLE_UART_NUM), UART_RX_FLOW_EN); - CLEAR_PERI_REG_MASK(UART_CONF0(CONFIG_CONSOLE_UART_NUM), UART_TX_FLOW_EN); + CLEAR_PERI_REG_MASK(UART_CONF1(CONFIG_ESP_CONSOLE_UART_NUM), UART_RX_FLOW_EN); + CLEAR_PERI_REG_MASK(UART_CONF0(CONFIG_ESP_CONSOLE_UART_NUM), UART_TX_FLOW_EN); - WRITE_PERI_REG(UART_CONF0(CONFIG_CONSOLE_UART_NUM), + WRITE_PERI_REG(UART_CONF0(CONFIG_ESP_CONSOLE_UART_NUM), 0 // None parity | (1 << 4) // 1-bit stop | (3 << 2) // 8-bit data | 0 // None flow control | 0); // None Inverse - SET_PERI_REG_MASK(UART_CONF0(CONFIG_CONSOLE_UART_NUM), UART_RXFIFO_RST | UART_TXFIFO_RST); - CLEAR_PERI_REG_MASK(UART_CONF0(CONFIG_CONSOLE_UART_NUM), UART_RXFIFO_RST | UART_TXFIFO_RST); + SET_PERI_REG_MASK(UART_CONF0(CONFIG_ESP_CONSOLE_UART_NUM), UART_RXFIFO_RST | UART_TXFIFO_RST); + CLEAR_PERI_REG_MASK(UART_CONF0(CONFIG_ESP_CONSOLE_UART_NUM), UART_RXFIFO_RST | UART_TXFIFO_RST); #endif - uart_div_modify(CONFIG_CONSOLE_UART_NUM, BOOTLOADER_CONSOLE_CLK_FREQ / CONFIG_CONSOLE_UART_BAUDRATE); +#if ESP8266_MODIFY_UART_BAUDRATE + + /* Wait UART TX over */ + + while(1) { + int uart_status = REG_READ(UART_STATUS(CONFIG_ESP_CONSOLE_UART_NUM)); + int tx_bytes = (uart_status >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT; + + if (!tx_bytes) { + break; + } + } + + uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, BOOTLOADER_CONSOLE_CLK_FREQ / CONFIG_ESP_CONSOLE_UART_BAUDRATE); +#endif } esp_err_t bootloader_init() @@ -611,8 +642,26 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { + esp_err_t ret; + +#ifdef CONFIG_BOOTLOADER_DISABLE_JTAG_IO + /* Set GPIO 12-15 to be normal GPIO */ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); + + /* Set GPIO 12-15 to be input mode */ + GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, BIT12 | BIT13 | BIT14 | BIT15); +#endif + uart_console_configure(); + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + return ESP_FAIL; + } + esp_image_header_t fhdr; if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { ESP_LOGE(TAG, "failed to load bootloader header!"); @@ -623,42 +672,31 @@ static esp_err_t bootloader_main() ESP_LOGI(TAG, "compile time " __TIME__ ); - print_flash_info(&fhdr); +#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT) + fhdr.spi_mode = CONFIG_SPI_FLASH_MODE; +#endif + + extern void phy_reg_default(void); + phy_reg_default(); update_flash_config(&fhdr); + print_flash_info(&fhdr); + return ESP_OK; } static void update_flash_config(const esp_image_header_t* pfhdr) { - // uint32_t size; - // switch(pfhdr->spi_size) { - // case ESP_IMAGE_FLASH_SIZE_1MB: - // size = 1; - // break; - // case ESP_IMAGE_FLASH_SIZE_2MB: - // case ESP_IMAGE_FLASH_SIZE_2MB_C1: - // size = 2; - // break; - // case ESP_IMAGE_FLASH_SIZE_4MB: - // case ESP_IMAGE_FLASH_SIZE_4MB_C1: - // size = 4; - // break; - // case ESP_IMAGE_FLASH_SIZE_8MB: - // size = 8; - // break; - // case ESP_IMAGE_FLASH_SIZE_16MB: - // size = 16; - // break; - // default: - // size = 2; - // } +#ifdef CONFIG_BOOTLOADER_INIT_SPI_FLASH + extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode); - // Set flash chip size -// esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode - // TODO: set frequency + esp_spi_flash_init(pfhdr->spi_speed, pfhdr->spi_mode); + + ESP_LOGD(TAG, "bootloader initialize SPI flash clock and I/O"); +#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */ + + Cache_Read_Disable(); } static void print_flash_info(const esp_image_header_t* phdr) diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index bf75c8d71..6c1ab83bb 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include "bootloader_random.h" #include "soc/cpu.h" diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index 6e4b06a9d..782665678 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include "bootloader_sha.h" #include @@ -170,7 +170,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest #endif -#elif defined(CONFIG_TARGET_PLATFORM_ESP8266) +#elif defined(CONFIG_IDF_TARGET_ESP8266) #ifndef BOOTLOADER_BUILD @@ -218,217 +218,29 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest #else #include "bootloader_sha.h" -#include -#include -#include -#include - -typedef void* bootloader_sha256_handle_t; - -// Code from mbedTLS sha256 - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define GET_UINT32_BE(n,b,i) \ -do { \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} while( 0 ) - -#define PUT_UINT32_BE(n,b,i) \ -do { \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} while( 0 ) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - -typedef struct { - uint32_t total[2]; - uint32_t state[8]; - uint8_t buffer[64]; -} mbedtls_sha256_context; - -static const uint32_t K[] = -{ - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, -}; - -static mbedtls_sha256_context s_sha256; - -static int internal_sha256_process(mbedtls_sha256_context *ctx, const uint8_t data[64]) -{ - uint32_t temp1, temp2, W[64]; - uint32_t A[8]; - unsigned int i; - - for( i = 0; i < 8; i++ ) - A[i] = ctx->state[i]; +#include "esp_sha.h" - for( i = 0; i < 64; i++ ) - { - if( i < 16 ) - GET_UINT32_BE( W[i], data, 4 * i ); - else - R( i ); +// typedef esp_sha_t* bootloader_sha256_handle_t; - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); - - temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; - A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; - } - - for( i = 0; i < 8; i++ ) - ctx->state[i] += A[i]; - - return( 0 ); -} +static esp_sha256_t s_sha256_ctx; bootloader_sha256_handle_t bootloader_sha256_start() { - mbedtls_sha256_context *ctx = &s_sha256; + esp_sha256_t *ctx = &s_sha256_ctx; - memset(ctx, 0, sizeof(mbedtls_sha256_context)); - - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; + esp_sha256_init(ctx); return ctx; } void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) { - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - size_t ilen = data_len; - const uint8_t *input = (const uint8_t *)data; - - int ret; - size_t fill; - uint32_t left; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy((void *)(ctx->buffer + left), input, fill); - - if( ( ret = internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) - return ; - - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - if( ( ret = internal_sha256_process( ctx, input ) ) != 0 ) - return ; - - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); + esp_sha256_update((esp_sha256_t *)handle, data, data_len); } void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) { - uint32_t last, padn; - uint32_t high, low; - uint8_t msglen[8]; - uint8_t *output = digest; - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - - static const unsigned char sha256_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - bootloader_sha256_data(ctx, sha256_padding, padn); - - bootloader_sha256_data(ctx, msglen, 8); - - PUT_UINT32_BE( ctx->state[0], output, 0 ); - PUT_UINT32_BE( ctx->state[1], output, 4 ); - PUT_UINT32_BE( ctx->state[2], output, 8 ); - PUT_UINT32_BE( ctx->state[3], output, 12 ); - PUT_UINT32_BE( ctx->state[4], output, 16 ); - PUT_UINT32_BE( ctx->state[5], output, 20 ); - PUT_UINT32_BE( ctx->state[6], output, 24 ); - - PUT_UINT32_BE( ctx->state[7], output, 28 ); - - return ; + esp_sha256_finish((esp_sha256_t *)handle, digest); } #endif diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index b7e828838..b5d90c1fc 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include @@ -478,7 +478,7 @@ static void set_cache_and_start_app( #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include #include @@ -493,15 +493,8 @@ static void set_cache_and_start_app( #include "esp_log.h" #include "esp_flash_partitions.h" - -#ifdef CONFIG_SOC_FULL_ICACHE -#define SOC_CACHE_SIZE 1 // 32KB -#else -#define SOC_CACHE_SIZE 0 // 16KB -#endif - -#define ESP_CACHE1_ADDR_MAX 0x100000 -#define ESP_CACHE2_ADDR_MAX 0x200000 +#include "esp_fast_boot.h" +#include "esp_private/esp_system_internal.h" static const char* TAG = "boot"; @@ -512,6 +505,14 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) esp_err_t err; int num_partitions; + rtc_sys_info.old_sysconf_addr = 0; +#ifdef CONFIG_ESP8266_OTA_FROM_OLD + if (esp_patition_table_init_location()) { + ESP_LOGE(TAG, "Failed to update partition table location"); + return false; + } +#endif + #ifdef CONFIG_SECURE_BOOT_ENABLED if(esp_secure_boot_enabled()) { ESP_LOGI(TAG, "Verifying partition table signature..."); @@ -583,6 +584,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) partition_usage = "OTA data"; break; case PART_SUBTYPE_DATA_RF: +#ifdef CONFIG_LOAD_OLD_RF_PARAMETER + bs->rf = partition->pos; +#endif partition_usage = "RF data"; break; case PART_SUBTYPE_DATA_WIFI: @@ -605,6 +609,13 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) bootloader_munmap(partitions); +#ifdef CONFIG_ESP8266_OTA_FROM_OLD + if (esp_patition_table_init_data(bs)) { + ESP_LOGE(TAG,"Failed to update partition data"); + return false; + } +#endif + ESP_LOGI(TAG,"End of partition table"); return true; } @@ -733,6 +744,16 @@ static bool try_load_partition(const esp_partition_pos_t *partition, esp_image_m #define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x" +static void bootloader_utility_start_image(uint32_t image_start, uint32_t image_size, uint32_t entry_addr) +{ + void (*user_start)(size_t start_addr); + + bootloader_mmap(image_start, image_size); + + user_start = (void *)entry_addr; + user_start(image_start); +} + bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result) { int index = start_index; @@ -783,9 +804,6 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ void bootloader_utility_load_image(const esp_image_metadata_t* image_data) { - void (*user_start)(size_t start_addr); - extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); - #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) esp_err_t err; #endif @@ -829,26 +847,18 @@ void bootloader_utility_load_image(const esp_image_metadata_t* image_data) copy loaded segments to RAM, set up caches for mapped segments, and start application unpack_load_app(image_data); #else - size_t map; + bootloader_utility_start_image(image_data->start_addr, image_data->image_len, image_data->image.entry_addr); +#endif /* BOOTLOADER_UNPACK_APP */ +} - if (image_data->start_addr < ESP_CACHE1_ADDR_MAX - && image_data->start_addr + image_data->image_len < ESP_CACHE1_ADDR_MAX) { - map = 0; - } else if (image_data->start_addr >= ESP_CACHE1_ADDR_MAX - && image_data->start_addr < ESP_CACHE2_ADDR_MAX - && image_data->start_addr + image_data->image_len < ESP_CACHE2_ADDR_MAX) { - map = 1; - } else { - ESP_LOGE(TAG, "ERROR: app bin error, start_addr %x image_len %d\n", image_data->start_addr, image_data->image_len); - /* Blocking here to let user judge. */ - while (1); - } +void bootloader_utility_fast_boot_image(void) +{ + uint32_t image_start, image_size, image_entry; - Cache_Read_Enable(map, 0, SOC_CACHE_SIZE); + if (!esp_fast_boot_get_info(&image_start, &image_size, &image_entry)) { + bootloader_utility_start_image(image_start, image_size, image_entry); + } - user_start = (void *)image_data->image.entry_addr; - user_start(image_data->start_addr); -#endif /* BOOTLOADER_UNPACK_APP */ + ESP_LOGD(TAG, "fast boot image fail"); } - #endif diff --git a/components/bootloader_support/src/efuse.c b/components/bootloader_support/src/efuse.c index c3e23b1b1..9d40b3592 100644 --- a/components/bootloader_support/src/efuse.c +++ b/components/bootloader_support/src/efuse.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include "esp_efuse.h" #include "esp_log.h" diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 23c89c5f9..525717786 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include @@ -360,7 +360,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui dest[w_i] = w ^ ((w_i & 1) ? ram_obfs_value[0] : ram_obfs_value[1]); } #endif -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH // SHA_CHUNK determined experimentally as the optimum size // to call bootloader_sha256_data() with. This is a bit // counter-intuitive, but it's ~3ms better than using the @@ -583,7 +583,7 @@ static void debug_log_hash(const uint8_t *image_hash, const char *label) #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include #include @@ -652,7 +652,7 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t #if defined(CONFIG_SECURE_BOOT_ENABLED) static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data); #endif -#if defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data); #endif @@ -691,8 +691,8 @@ esp_err_t esp_image_load(esp_image_load_mode_t mode, const esp_partition_pos_t * #ifdef CONFIG_SECURE_BOOT_ENABLED if (1) { #else -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH +#ifdef CONFIG_IDF_TARGET_ESP32 if (data->image.hash_appended) #endif { @@ -769,7 +769,7 @@ goto err; // secure boot images have a signature appended err = verify_secure_boot_signature(sha_handle, data); #else -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH // No secure boot, but SHA-256 can be appended for basic corruption detection if (sha_handle != NULL #ifdef CONFIG_ENABLE_BOOT_CHECK_OCD @@ -812,7 +812,7 @@ goto err; if (err == ESP_OK) { err = ESP_ERR_IMAGE_INVALID; } -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH if (sha_handle != NULL) { // Need to finish the hash process to free the handle bootloader_sha256_finish(sha_handle, NULL); @@ -858,7 +858,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme ESP_LOGE(TAG, "bootloader_flash_read failed at 0x%08x", flash_addr); return err; } -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH if (sha_handle != NULL) { bootloader_sha256_data(sha_handle, header, sizeof(esp_image_segment_header_t)); } @@ -934,7 +934,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum) { esp_err_t ret = ESP_OK; -#if defined(CONFIG_ENABLE_BOOT_CHECK_SUM) || defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_SUM) || defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) const char *src = (const char *)data_addr; #ifndef BOOTLOADER_BUILD uint32_t *pbuf; @@ -944,7 +944,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui return ESP_FAIL; } #else - static char pbuf[SHA_CHUNK]; + static uint32_t pbuf[SHA_CHUNK / sizeof(uint32_t)]; #endif for (int i = 0; i < data_len; i += SHA_CHUNK) { @@ -961,14 +961,12 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui goto exit; } -#if defined(CONFIG_ENABLE_BOOT_CHECK_SUM) - uint32_t *psum = (uint32_t *)pbuf; - +#if defined(CONFIG_APP_UPDATE_CHECK_APP_SUM) for (int i = 0; i < bytes / sizeof(uint32_t); i++) - *checksum ^= psum[i]; + *checksum ^= pbuf[i]; #endif -#if defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) if (sha_handle != NULL) bootloader_sha256_data(sha_handle, pbuf, bytes); #endif @@ -1045,7 +1043,7 @@ esp_err_t esp_image_verify_bootloader(uint32_t *length) static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data) { esp_err_t err = ESP_OK; -#if defined(CONFIG_ENABLE_BOOT_CHECK_SUM) || defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_SUM) || defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) uint32_t unpadded_length = data->image_len; uint32_t length = unpadded_length + 1; // Add a byte for the checksum length = (length + 15) & ~15; // Pad to next full 16 byte block @@ -1058,7 +1056,7 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t return ESP_ERR_IMAGE_INVALID; } -#if defined(CONFIG_ENABLE_BOOT_CHECK_SUM) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_SUM) uint8_t calc = buf[length - unpadded_length - 1]; uint8_t checksum = (checksum_word >> 24) ^ (checksum_word >> 16) @@ -1071,12 +1069,12 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t } #endif -#ifdef CONFIG_ENABLE_BOOT_CHECK_SHA256 +#ifdef CONFIG_APP_UPDATE_CHECK_APP_HASH if (sha_handle != NULL) { bootloader_sha256_data(sha_handle, buf, length - unpadded_length); } -#if CONFIG_TARGET_PLATFORM_ESP32 +#if CONFIG_IDF_TARGET_ESP32 if (data->image.hash_appended) #endif { @@ -1091,7 +1089,7 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t return err; } -#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) static void debug_log_hash(const uint8_t *image_hash, const char *caption); #endif @@ -1102,7 +1100,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han // For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash // appended to the image for corruption detection -#if CONFIG_TARGET_PLATFORM_ESP32 +#if CONFIG_IDF_TARGET_ESP32 if (data->image.hash_appended) #endif { @@ -1143,7 +1141,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han } #endif -#if defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data) { uint8_t image_hash[HASH_LEN]; @@ -1171,7 +1169,7 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i } #endif -#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_ENABLE_BOOT_CHECK_SHA256) +#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_APP_UPDATE_CHECK_APP_HASH) // Log a hash as a hex string static void debug_log_hash(const uint8_t *image_hash, const char *label) diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 8d21c37de..f6b51f6d3 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include diff --git a/components/bootloader_support/src/flash_partitions.c b/components/bootloader_support/src/flash_partitions.c index f258ca648..1f4487eff 100644 --- a/components/bootloader_support/src/flash_partitions.c +++ b/components/bootloader_support/src/flash_partitions.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include "esp_flash_partitions.h" @@ -91,7 +91,7 @@ esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition #endif -#ifdef CONFIG_TARGET_PLATFORM_ESP8266 +#ifdef CONFIG_IDF_TARGET_ESP8266 #include #include @@ -101,6 +101,7 @@ esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition #include "esp_err.h" #include "esp_flash_partitions.h" #include "esp_log.h" +#include "esp8266/rom_functions.h" static const char *TAG = "flash_parts"; @@ -108,7 +109,7 @@ esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition { int md5_found = 0; int num_parts; - uint32_t chip_size = 2 * 1024 * 1024;// = g_rom_flashchip.chip_size; + uint32_t chip_size = g_rom_flashchip.chip_size; *num_partitions = 0; for (num_parts = 0; num_parts < ESP_PARTITION_TABLE_MAX_ENTRIES; num_parts++) { diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 571515b52..db4ded7cc 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include #include @@ -208,7 +208,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, ESP_LOGD(TAG, "Enabling QIO mode..."); esp_rom_spiflash_read_mode_t mode; -#if CONFIG_FLASHMODE_QOUT +#if CONFIG_ESPTOOLPY_FLASHMODE_QOUT mode = ESP_ROM_SPIFLASH_QOUT_MODE; #else mode = ESP_ROM_SPIFLASH_QIO_MODE; diff --git a/components/bootloader_support/src/secure_boot.c b/components/bootloader_support/src/secure_boot.c index 8eb26ec50..79f4f8aa8 100644 --- a/components/bootloader_support/src/secure_boot.c +++ b/components/bootloader_support/src/secure_boot.c @@ -14,7 +14,7 @@ #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include diff --git a/components/bootloader_support/src/secure_boot_signatures.c b/components/bootloader_support/src/secure_boot_signatures.c index 4a216a361..d0ccd13db 100644 --- a/components/bootloader_support/src/secure_boot_signatures.c +++ b/components/bootloader_support/src/secure_boot_signatures.c @@ -13,7 +13,7 @@ // limitations under the License. #include "sdkconfig.h" -#ifdef CONFIG_TARGET_PLATFORM_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 #include "bootloader_flash.h" #include "bootloader_sha.h" diff --git a/components/bootloader_support/test/component.mk b/components/bootloader_support/test/component.mk deleted file mode 100644 index 8c6eb513e..000000000 --- a/components/bootloader_support/test/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -#Component Makefile -# -COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/bootloader_support/test/test_verify_image.c b/components/bootloader_support/test/test_verify_image.c deleted file mode 100644 index 7994667f3..000000000 --- a/components/bootloader_support/test/test_verify_image.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Tests for bootloader_support esp_load(ESP_IMAGE_VERIFY, ...) - */ - -#include -#include -#include "string.h" -#include "rom/ets_sys.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/xtensa_api.h" -#include "unity.h" -#include "bootloader_common.h" -#include "esp_partition.h" -#include "esp_ota_ops.h" -#include "esp_image_format.h" - -TEST_CASE("Verify bootloader image in flash", "[bootloader_support]") -{ - const esp_partition_pos_t fake_bootloader_partition = { - .offset = ESP_BOOTLOADER_OFFSET, - .size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET, - }; - esp_image_metadata_t data = { 0 }; - TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_load(ESP_IMAGE_VERIFY, &fake_bootloader_partition, &data)); - TEST_ASSERT_NOT_EQUAL(0, data.image_len); - - uint32_t bootloader_length = 0; - TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_verify_bootloader(&bootloader_length)); - TEST_ASSERT_EQUAL(data.image_len, bootloader_length); -} - -TEST_CASE("Verify unit test app image", "[bootloader_support]") -{ - esp_image_metadata_t data = { 0 }; - const esp_partition_t *running = esp_ota_get_running_partition(); - TEST_ASSERT_NOT_EQUAL(NULL, running); - const esp_partition_pos_t running_pos = { - .offset = running->address, - .size = running->size, - }; - - TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_load(ESP_IMAGE_VERIFY, &running_pos, &data)); - TEST_ASSERT_NOT_EQUAL(0, data.image_len); - TEST_ASSERT_TRUE(data.image_len <= running->size); -} - -void check_label_search (int num_test, const char *list, const char *t_label, bool result) -{ - // gen_esp32part.py trims up to 16 characters - // and the string may not have a null terminal symbol. - // below is cutting as it does the generator. - char label[16 + 1] = {0}; - strncpy(label, t_label, sizeof(label) - 1); - - bool ret = bootloader_common_label_search(list, label); - if (ret != result) { - printf("%d) %s | %s \n", num_test, list, label); - } - TEST_ASSERT_MESSAGE(ret == result, "Test failed"); -} - -TEST_CASE("Test label_search", "[bootloader_support]") -{ - TEST_ASSERT_FALSE(bootloader_common_label_search(NULL, NULL)); - TEST_ASSERT_FALSE(bootloader_common_label_search("nvs", NULL)); - - check_label_search(1, "nvs", "nvs", true); - check_label_search(2, "nvs, ", "nvs", true); - check_label_search(3, "nvs1", "nvs", false); - check_label_search(3, "nvs1, ", "nvs", false); - check_label_search(4, "nvs1nvs1, phy", "nvs1", false); - check_label_search(5, "nvs1, nvs1, phy", "nvs1", true); - check_label_search(6, "nvs12, nvs12, phy", "nvs1", false); - check_label_search(7, "nvs12, nvs1, phy", "nvs1", true); - check_label_search(8, "nvs12, nvs3, phy, nvs1","nvs1", true); - check_label_search(9, "nvs1nvs1, phy, nvs", "nvs", true); - check_label_search(10, "nvs1nvs1, phy, nvs1", "nvs", false); - check_label_search(11, "nvs1, nvs, phy, nvs1", "nvs", true); - check_label_search(12, "nvs1, nvs2, phy, nvs","nvs", true); - check_label_search(13, "ota_data, backup_nvs", "nvs", false); - check_label_search(14, "nvs1, nvs2, ota, nvs", "vs1", false); - - check_label_search(20, "12345678901234, phy, nvs1", "12345678901234", true); - check_label_search(21, "123456789012345, phy, nvs1", "123456789012345", true); - check_label_search(22, "1234567890123456, phy, nvs1", "1234567890123456", true); - check_label_search(23, "12345678901234567, phy, nvs1", "12345678901234567", false); - check_label_search(24, "1234567890123456, phy, nvs1", "12345678901234567", true); - check_label_search(25, "phy, 1234567890123456, nvs1", "12345678901234567", true); - -} diff --git a/components/cjson/CMakeLists.txt b/components/cjson/CMakeLists.txt deleted file mode 100644 index 0b8ba83d6..000000000 --- a/components/cjson/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(COMPONENT_SRCDIRS cJSON) -set(COMPONENT_ADD_INCLUDEDIRS cJSON) - -set(COMPONENT_REQUIRES "") - -register_component() diff --git a/components/cjson/cJSON/CHANGELOG.md b/components/cjson/cJSON/CHANGELOG.md deleted file mode 100644 index b7b53e361..000000000 --- a/components/cjson/cJSON/CHANGELOG.md +++ /dev/null @@ -1,347 +0,0 @@ -1.7.6 -===== -Fixes: ------- -* Add `SONAME` to the ELF files built by the Makefile (see #252), thanks @YanhaoMo for reporting -* Add include guards and `extern "C"` to `cJSON_Utils.h` (see #256), thanks @daschfg for reporting - -Other changes: --------------- -* Mark the Makefile as deprecated in the README. - -1.7.5 -===== -Fixes: ------- -* Fix a bug in the JSON Patch implementation of `cJSON Utils` (see #251), thanks @bobkocisko. - -1.7.4 -===== -Fixes: ------- -* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added (#248). Thanks @hhallen for reporting. - -1.7.3 -===== -Fixes: ------- -* Fix potential double free, thanks @projectgus for reporting (see #241) - -1.7.2 -===== -Fixes: ------- -* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting (see #240) - -1.7.1 -===== -Fixes: ------- -* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting (see #230) -* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting (see #230) - -1.7.0 -===== -Features: ---------- -* Large rewrite of the documentation, see #215 -* Added the `cJSON_GetStringValue` function -* Added the `cJSON_CreateStringReference` function -* Added the `cJSON_CreateArrayReference` function -* Added the `cJSON_CreateObjectReference` function -* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see #226 - -Fixes: ------- -* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see #210 -* Fix linking the tests when building as static library, see #213 -* New overrides for the CMake option `BUILD_SHARED_LIBS`, see #207 - -Other Changes: --------------- -* Readme: Explain how to include cJSON, see #211 -* Removed some trailing spaces in the code, thanks @yangfl, see#212 -* Updated [Unity](https://github.com/ThrowTheSwitch/Unity) and [json-patch-tests](https://github.com/json-patch/json-patch-tests) - -1.6.0 -===== -Features: ---------- -* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see #178 -* UTF-8 byte order marks are now ignored, see #184 -* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see #202, thanks @Casperinous -* Better support for MSVC and Visual Studio - -Other Changes: --------------- -* Add the new warnings `-Wswitch-enum`, `-Wused-but-makred-unused`, `-Wmissing-variable-declarations`, `-Wunused-macro` -* More number printing tests. -* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r - -1.5.9 -===== -* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`. See #200, thanks @rmallins - -1.5.8 -===== -* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this (#195) - -1.5.7 -===== -Fixes: ------- -* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue -* Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk - -1.5.6 -===== -Fixes: ------- -* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer. (#183) Thanks @msichal for reporting #182 - -1.5.5 -===== -Fixes: ------- -* Fix pointers to nested arrays in cJSON_Utils (9abe75e072050f34732a7169740989a082b65134) -* Fix an error with case sensitivity handling in cJSON_Utils (b9cc911831b0b3e1bb72f142389428e59f882b38) -* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other (03ba72faec115160d1f3aea5582d9b6af5d3e473) See #180, thanks @zhengqb for reporting - -1.5.4 -===== -Fixes: ------- -* Fix build with GCC 7.1.1 and optimization level `-O2` (bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be) - -Other Changes: --------------- -* Update [Unity](https://github.com/ThrowTheSwitch/Unity) to 3b69beaa58efc41bbbef70a32a46893cae02719d - -1.5.3 -===== -Fixes: ------- -* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item (#174) - -1.5.2 -===== -Fixes: ------- -* Fix a reading buffer overflow in `parse_string` (a167d9e381e5c84bc03de4e261757b031c0c690d) -* Fix compiling with -Wcomma (186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad) -* Remove leftover attribute from tests (b537ca70a35680db66f1f5b8b437f7114daa699a) - -1.5.1 -===== -Fixes: ------- -* Add gcc version guard to the Makefile (#164), thanks @juvasquezg -* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used (#166), thanks @prefetchnta - -1.5.0 -===== -Features: ---------- -* cJSON finally prints numbers without losing precision (#153) thanks @DeboraG -* `cJSON_Compare` recursively checks if two cJSON items contain the same values (#148) -* Provide case sensitive versions of every function where it matters (#158, #159) -* Added `cJSON_ReplaceItemViaPointer` and `cJSON_DetachItemViaPointer` -* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. (02a05eea4e6ba41811f130b322660bea8918e1a0) - - -Enhancements: -------------- -* Parse into a buffer, this will allow parsing `\u0000` in the future (not quite yet though) -* General simplifications and readability improvements -* More unit tests -* Update [unity](https://github.com/ThrowTheSwitch/Unity) testing library to 2.4.1 -* Add the [json-patch-tests](https://github.com/json-patch/json-patch-tests) test suite to test cJSON_Utils. -* Move all tests from `test_utils.c` to unit tests with unity. - -Fixes: ------- -* Fix some warnings with the Microsoft compiler (#139) thanks @PawelWMS -* Fix several bugs in cJSON_Utils, mostly found with [json-patch-tests](https://github.com/json-patch/json-patch-tests) -* Prevent a stack overflow by specifying a maximum nesting depth `CJSON_NESTING_LIMIT` - -Other Changes: --------------- -* Move generated files in the `library_config` subdirectory. - -1.4.7 -===== -Fixes: ------- -* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it) (075a06f40bdc4f836c7dd7cad690d253a57cfc50) -* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive` (51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9) thanks @PawelWMS - -1.4.6 -===== -Fixes: ------- -* Several corrections in the README -* Making clear that `valueint` should not be written to -* Fix overflow detection in `ensure` (2683d4d9873df87c4bdccc523903ddd78d1ad250) -* Fix a potential null pointer dereference in cJSON_Utils (795c3acabed25c9672006b2c0f40be8845064827) -* Replace incorrect `sizeof('\0')` with `sizeof("")` (84237ff48e69825c94261c624eb0376d0c328139) -* Add caveats section to the README (50b3c30dfa89830f8f477ce33713500740ac3b79) -* Make cJSON locale independent (#146) Thanks @peterh for reporting -* Fix compiling without CMake with MSVC (#147) Thanks @dertuxmalwieder for reporting - -1.4.5 -===== -Fixes: ------- -* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper (#138 ef34500693e8c4a2849d41a4bd66fd19c9ec46c2) -* Workaround for internal compiler error in GCC 5.4.0 and 6.3.1 on x86 (2f65e80a3471d053fdc3f8aed23d01dd1782a5cb [GCC bugreport](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097)) - -1.4.4 -===== -Fixes: --------- -* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware) e58f7ec027d00b7cdcbf63e518c1b5268b29b3da -* Fix an off by one error (cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka -* Double check the offset of the print buffer in `ensure` (1934059554b9a0971e00f79e96900f422cfdd114) - -Improvements: -------------- -* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated` (4bfb88009342fb568295a7f6dc4b7fee74fbf022) - -1.4.3 -===== -Fixes: ------- -* Fix compilation of the tests on 32 bit PowerPC and potentially other systems (4ec6e76ea2eec16f54b58e8c95b4c734e59481e4) -* Fix compilation with old GCC compilers (4.3+ were tested) (227d3398d6b967879761ebe02c1b63dbd6ea6e0d, 466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also #126 - -1.4.2 -===== -Fixes: ------- -* Fix minimum required cmake version (30e1e7af7c63db9b55f5a3cda977a6c032f0b132) -* Fix detection of supported compiler flags (76e5296d0d05ceb3018a9901639e0e171b44a557) -* Run `cJSON_test` and `cJSON_test_utils` along with unity tests (c597601cf151a757dcf800548f18034d4ddfe2cb) - -1.4.1 -===== -Fix: Make `print_number` abort with a failure in out of memory situations (cf1842dc6f64c49451a022308b4415e4d468be0a) - -1.4.0 -===== -Features --------- -* Functions to check the type of an item (#120) -* Use dllexport on windows and fvisibility on Unix systems for public functions (#116), thanks @mjerris -* Remove trailing zeroes from printed numbers (#123) -* Expose the internal boolean type `cJSON_bool` in the header (2d3520e0b9d0eb870e8886e8a21c571eeddbb310) - -Fixes ------ -* Fix handling of NULL pointers in `cJSON_ArrayForEach` (b47d0e34caaef298edfb7bd09a72cfff21d231ff) -* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning) (9d07917feb1b613544a7513d19233d4c851ad7ad) - -Other Improvements ------------------- -* internally use realloc if available (#110) -* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) (#111) -* unit tests for the print functions (#112) -* Always use buffered printing (#113) -* simplify the print functions (#114) -* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` (#122) - -1.3.2 -===== -Fix: ----- -- Don't build the unity library if testing is disabled ( #121 ). Thanks @ffontaine - -1.3.1 -===== -Bugfix release that fixes an out of bounds read #118. This shouldn't have any security implications. - -1.3.0 -===== -This release includes a lot of rework in the parser and includes the Cunity unit testing framework, as well as some fixes. I increased the minor version number because there were quite a lot of internal changes. - -Features: ---------- -- New type for cJSON structs: `cJSON_Invalid` (#108) - -Fixes: ------- -- runtime checks for a lot of potential integer overflows -- fix incorrect return in cJSON_PrintBuffered (cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3) -- fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson) -- fix potentially undefined behavior when assigning big numbers to `valueint` (41e2837df1b1091643aff073f2313f6ff3cc10f4) - - Numbers exceeding `INT_MAX` or lower than `INT_MIN` will be explicitly assigned to `valueint` as `INT_MAX` and `INT_MIN` respectively (saturation on overflow). - - fix the `cJSON_SetNumberValue` macro (87f77274de6b3af00fb9b9a7f3b900ef382296c2), this slightly changes the behavior, see commit message - -Introduce unit tests --------------------- - -Started writing unit tests with the [Cunity](https://github.com/ThrowTheSwitch/Unity) testing framework. Currently this covers the parser functions. - -Also: -- Support for running the tests with [Valgrind](http://valgrind.org) -- Support for compiling the tests with [AddressSanitizer](https://github.com/google/sanitizers) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html). -- `travis.yml` file for running unit tests on travis. (not enabled for the repository yet though #102) - -Simplifications ---------------- - -After having unit tests for the parser function in place, I started refactoring the parser functions (as well as others) and making them easier to read and maintain. -- Use `strtod` from the standard library for parsing numbers (074766997246481dfc72bfa78f07898a2716473f) -- Use goto-fail in several parser functions (#100) -- Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. (#109) -- Simplify the buffer allocation strategy to always doubling the needed amount (9f6fa94c91a87b71e4c6868dbf2ce431a48517b0) -- Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function (cf862d0fed7f9407e4b046d78d3d8050d2080d12) - -Other changes -------------- -- Prevent the usage of incompatible C and header versions via preprocessor directive (123bb1af7bfae41d805337fef4b41045ef6c7d25) -- Let CMake automatically detect compiler flags -- Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) (#98) -- Change internal sizes from `int` to `size_t` (ecd5678527a6bc422da694e5be9e9979878fe6a0) -- Change internal strings from `char*` to `unsigned char*` (28b9ba4334e0f7309e867e874a31f395c0ac2474) -- Add `const` in more places - -1.2.1 -===== -Fixes: ------- -- Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf (#96) - -1.2.0 -===== -Features: ---------- -- Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu (#65, #90) - -Fixes: ------- -- Compiler warning if const is casted away, Thanks @gatzka (#83) -- Fix compile error with strict-overflow on PowerPC, (#85) -- Fix typo in the README, thanks @MicroJoe (#88) -- Add compile flag for compatibility with C++ compilers - -1.1.0 -===== -- Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle (#72) -- More compiler warnings when using Clang or GCC, thanks @gatzka (#75, #78) -- fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan (#81) -- fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option - -1.0.2 -===== -Rename internal boolean type, see #71. - -1.0.1 -===== -Small bugfix release. -- Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see d47339e2740360e6e0994527d5e4752007480f3a -- improve code readability -- initialize all variables - -1.0.0 -===== -This is the first official versioned release of cJSON. It provides an API version for the shared library and improved Makefile and CMake build files. diff --git a/components/cjson/cJSON/CMakeLists.txt b/components/cjson/cJSON/CMakeLists.txt deleted file mode 100644 index fc8c042ef..000000000 --- a/components/cjson/cJSON/CMakeLists.txt +++ /dev/null @@ -1,247 +0,0 @@ -set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 2.8.5) - -project(cJSON C) - -include(GNUInstallDirs) - -set(PROJECT_VERSION_MAJOR 1) -set(PROJECT_VERSION_MINOR 7) -set(PROJECT_VERSION_PATCH 6) -set(CJSON_VERSION_SO 1) -set(CJSON_UTILS_VERSION_SO 1) -set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") - - -set(custom_compiler_flags) - -include(CheckCCompilerFlag) -option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON) -if (ENABLE_CUSTOM_COMPILER_FLAGS) - if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) - list(APPEND custom_compiler_flags - -std=c89 - -pedantic - -Wall - -Wextra - -Werror - -Wstrict-prototypes - -Wwrite-strings - -Wshadow - -Winit-self - -Wcast-align - -Wformat=2 - -Wmissing-prototypes - -Wstrict-overflow=2 - -Wcast-qual - -Wundef - -Wswitch-default - -Wconversion - -Wc++-compat - -fstack-protector-strong - -Wcomma - -Wdouble-promotion - -Wparentheses - -Wformat-overflow - -Wunused-macros - -Wmissing-variable-declarations - -Wused-but-marked-unused - -Wswitch-enum - ) - elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") - list(APPEND custom_compiler_flags - /GS - /Za - /sdl - /W4 - ) - endif() -endif() - -option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF) -if (ENABLE_SANITIZERS) - list(APPEND custom_compiler_flags - -fno-omit-frame-pointer - -fsanitize=address - -fsanitize=undefined - -fsanitize=float-divide-by-zero - -fsanitize=float-cast-overflow - -fsanitize-address-use-after-scope - -fsanitize=integer - -01 - -fno-sanitize-recover - ) -endif() - -option(ENABLE_SAFE_STACK "Enables the SafeStack instrumentation pass by the Code Pointer Integrity Project" OFF) -if (ENABLE_SAFE_STACK) - if (ENABLE_SANITIZERS) - message(FATAL_ERROR "ENABLE_SAFE_STACK cannot be used in combination with ENABLE_SANITIZERS") - endif() - list(APPEND custom_compiler_flags - -fsanitize=safe-stack - ) -endif() - -option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On) -if (ENABLE_PUBLIC_SYMBOLS) - list(APPEND custom_compiler_flags -fvisibility=hidden) - add_definitions(-DCJSON_EXPORT_SYMBOLS -DCJSON_API_VISIBILITY) -endif() -option(ENABLE_HIDDEN_SYMBOLS "Hide library symbols." Off) -if (ENABLE_HIDDEN_SYMBOLS) - add_definitions(-DCJSON_HIDE_SYMBOLS -UCJSON_API_VISIBILITY) -endif() - -# apply custom compiler flags -foreach(compiler_flag ${custom_compiler_flags}) - #remove problematic characters - string(REGEX REPLACE "[^a-zA-Z0-9]" "" current_variable ${compiler_flag}) - - CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}") - if (FLAG_SUPPORTED_${current_variable}) - list(APPEND supported_compiler_flags) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}") - endif() -endforeach() - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}") - -option(BUILD_SHARED_LIBS "Build shared libraries" ON) -option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON) - -#cJSON -set(CJSON_LIB cjson) - -file(GLOB HEADERS cJSON.h) -set(SOURCES cJSON.c) - -option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off) -option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF) -option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON) - -if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS)) - set(CJSON_LIBRARY_TYPE SHARED) -else() - set(CJSON_LIBRARY_TYPE STATIC) -endif() - - -if (NOT BUILD_SHARED_AND_STATIC_LIBS) - add_library("${CJSON_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS}" "${SOURCES}") -else() - # See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F - add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}") - add_library("${CJSON_LIB}-static" STATIC "${HEADERS}" "${SOURCES}") - set_target_properties("${CJSON_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_LIB}") - set_target_properties("${CJSON_LIB}-static" PROPERTIES PREFIX "lib") -endif() -if (NOT WIN32) - target_link_libraries("${CJSON_LIB}" m) -endif() - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY) - -install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") -install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") -install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_LIB}") -if (BUILD_SHARED_AND_STATIC_LIBS) - install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") -endif() -if(ENABLE_TARGET_EXPORT) - # export library information for CMake projects - install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") -endif() - -set_target_properties("${CJSON_LIB}" - PROPERTIES - SOVERSION "${CJSON_VERSION_SO}" - VERSION "${PROJECT_VERSION}") - -#cJSON_Utils -option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF) -if(ENABLE_CJSON_UTILS) - set(CJSON_UTILS_LIB cjson_utils) - - file(GLOB HEADERS_UTILS cJSON_Utils.h) - set(SOURCES_UTILS cJSON_Utils.c) - - if (NOT BUILD_SHARED_AND_STATIC_LIBS) - add_library("${CJSON_UTILS_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS_UTILS}" "${SOURCES_UTILS}") - target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}") - else() - add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}") - target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}") - add_library("${CJSON_UTILS_LIB}-static" STATIC "${HEADERS_UTILS}" "${SOURCES_UTILS}") - target_link_libraries("${CJSON_UTILS_LIB}-static" "${CJSON_LIB}-static") - set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_UTILS_LIB}") - set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES PREFIX "lib") - endif() - - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY) - - install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}") - if (BUILD_SHARED_AND_STATIC_LIBS) - install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") - endif() - install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") - if(ENABLE_TARGET_EXPORT) - # export library information for CMake projects - install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") - endif() - - set_target_properties("${CJSON_UTILS_LIB}" - PROPERTIES - SOVERSION "${CJSON_UTILS_VERSION_SO}" - VERSION "${PROJECT_VERSION}") -endif() - -# create the other package config files -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfig.cmake.in" - ${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY) -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in" - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY) - -# Install package config files -install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake - DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") - -option(ENABLE_CJSON_TEST "Enable building cJSON test" ON) -if(ENABLE_CJSON_TEST) - enable_testing() - - set(TEST_CJSON cJSON_test) - add_executable("${TEST_CJSON}" test.c) - target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}") - - add_test(NAME ${TEST_CJSON} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/${TEST_CJSON}") - - # Disable -fsanitize=float-divide-by-zero for cJSON_test - if (FLAG_SUPPORTED_fsanitizefloatdividebyzero) - if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero") - else() - target_compile_options(${TEST_CJSON} PRIVATE "-fno-sanitize=float-divide-by-zero") - endif() - endif() - - #"check" target that automatically builds everything and runs the tests - add_custom_target(check - COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure - DEPENDS ${TEST_CJSON}) -endif() - -# Enable the use of locales -option(ENABLE_LOCALES "Enable the use of locales" ON) -if(ENABLE_LOCALES) - add_definitions(-DENABLE_LOCALES) -endif() - -add_subdirectory(tests) -add_subdirectory(fuzzing) diff --git a/components/cjson/cJSON/CONTRIBUTORS.md b/components/cjson/cJSON/CONTRIBUTORS.md deleted file mode 100644 index 302ad4dfd..000000000 --- a/components/cjson/cJSON/CONTRIBUTORS.md +++ /dev/null @@ -1,47 +0,0 @@ -Contributors -============ - -Original Author: [Dave Gamble](https://github.com/DaveGamble) -Current Maintainer: [Max Bruckner](https://github.com/FSMaxB) - -* [Ajay Bhargav](https://github.com/ajaybhargav) -* [Alper Akcan](https://github.com/alperakcan) -* [Anton Sergeev](https://github.com/anton-sergeev) -* [Bob Kocisko](https://github.com/bobkocisko) -* [Christian Schulze](https://github.com/ChristianSch) -* [Casperinous](https://github.com/Casperinous) -* [Debora Grosse](https://github.com/DeboraG) -* [dieyushi](https://github.com/dieyushi) -* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang) -* Eswar Yaganti -* [Evan Todd](https://github.com/etodd) -* [Fabrice Fontaine](https://github.com/ffontaine) -* Ian Mobley -* Irwan Djadjadi -* [IvanVoid](https://github.com/npi3pak) -* [Jakub Wilk](https://github.com/jwilk) -* [Jiri Zouhar](https://github.com/loigu) -* [Jonathan Fether](https://github.com/jfether) -* [Julián Vásquez](https://github.com/juvasquezg) -* [Kevin Branigan](https://github.com/kbranigan) -* [Kyle Chisholm](https://github.com/ChisholmKyle) -* [Linus Wallgren](https://github.com/ecksun) -* Mike Pontillo -* [Mike Jerris](https://github.com/mjerris) -* [Mike Robinson](https://github.com/mhrobinson) -* Paulo Antonio Alvarez -* [Pawel Winogrodzki](https://github.com/PawelWMS) -* [prefetchnta](https://github.com/prefetchnta) -* [Rafael Leal Dias](https://github.com/rafaeldias) -* [Robin Mallinson](https://github.com/rmallins) -* [Rod Vagg](https://github.com/rvagg) -* [Roland Meertens](https://github.com/rmeertens) -* [Romain Porte](https://github.com/MicroJoe) -* [Simon Ricaldone](https://github.com/simon-p-r) -* [Stephan Gatzka](https://github.com/gatzka) -* [Weston Schmidt](https://github.com/schmidtw) -* [yangfl](https://github.com/yangfl) - -And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0) - -Also thanks to all the people who reported bugs and suggested new features. diff --git a/components/cjson/cJSON/LICENSE b/components/cjson/cJSON/LICENSE deleted file mode 100644 index 78deb0406..000000000 --- a/components/cjson/cJSON/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/components/cjson/cJSON/Makefile b/components/cjson/cJSON/Makefile deleted file mode 100644 index 0b302a079..000000000 --- a/components/cjson/cJSON/Makefile +++ /dev/null @@ -1,157 +0,0 @@ -CJSON_OBJ = cJSON.o -UTILS_OBJ = cJSON_Utils.o -CJSON_LIBNAME = libcjson -UTILS_LIBNAME = libcjson_utils -CJSON_TEST = cJSON_test - -CJSON_TEST_SRC = cJSON.c test.c - -LDLIBS = -lm - -LIBVERSION = 1.7.6 -CJSON_SOVERSION = 1 -UTILS_SOVERSION = 1 - -CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION) -UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION) - -PREFIX ?= /usr/local -INCLUDE_PATH ?= include/cjson -LIBRARY_PATH ?= lib - -INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) - -INSTALL ?= cp -a - -# validate gcc version for use fstack-protector-strong -MIN_GCC_VERSION = "4.9" -GCC_VERSION := "`gcc -dumpversion`" -IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)") -ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1" - CFLAGS += -fstack-protector-strong -else - CFLAGS += -fstack-protector -endif - -R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS) - -uname := $(shell sh -c 'uname -s 2>/dev/null || echo false') - -#library file extensions -SHARED = so -STATIC = a - -## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS) -ifeq (Darwin, $(uname)) - SHARED = dylib - CJSON_SO_LDFLAG = "" - UTILS_SO_LDFLAG = "" -endif - -#cJSON library names -CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED) -CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION) -CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION) -CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC) - -#cJSON_Utils library names -UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED) -UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION) -UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION) -UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC) - -SHARED_CMD = $(CC) -shared -o - -.PHONY: all shared static tests clean install - -all: shared static tests - -shared: $(CJSON_SHARED) $(UTILS_SHARED) - -static: $(CJSON_STATIC) $(UTILS_STATIC) - -tests: $(CJSON_TEST) - -test: tests - ./$(CJSON_TEST) - -.c.o: - $(CC) -c $(R_CFLAGS) $< - -#tests -#cJSON -$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h - $(CC) $(R_CFLAGS) $(CJSON_TEST_SRC) -o $@ $(LDLIBS) -I. - -#static libraries -#cJSON -$(CJSON_STATIC): $(CJSON_OBJ) - $(AR) rcs $@ $< -#cJSON_Utils -$(UTILS_STATIC): $(UTILS_OBJ) - $(AR) rcs $@ $< - -#shared libraries .so.1.0.0 -#cJSON -$(CJSON_SHARED_VERSION): $(CJSON_OBJ) - $(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS) -#cJSON_Utils -$(UTILS_SHARED_VERSION): $(UTILS_OBJ) - $(CC) -shared -o $@ $< $(UTILS_SO_LDFLAG) $(LDFLAGS) - -#objects -#cJSON -$(CJSON_OBJ): cJSON.c cJSON.h -#cJSON_Utils -$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h - - -#links .so -> .so.1 -> .so.1.0.0 -#cJSON -$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION) - ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) -$(CJSON_SHARED): $(CJSON_SHARED_SO) - ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED) -#cJSON_Utils -$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION) - ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) -$(UTILS_SHARED): $(UTILS_SHARED_SO) - ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED) - -#install -#cJSON -install-cjson: - mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH) - $(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH) -#cJSON_Utils -install-utils: install-cjson - $(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH) - $(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH) - -install: install-cjson install-utils - -#uninstall -#cJSON -uninstall-cjson: uninstall-utils - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED) - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION) - $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO) - rmdir $(INSTALL_LIBRARY_PATH) - $(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h - rmdir $(INSTALL_INCLUDE_PATH) -#cJSON_Utils -uninstall-utils: - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED) - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION) - $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO) - $(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h - -uninstall: uninstall-utils uninstall-cjson - -clean: - $(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files - $(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON - $(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils - $(RM) $(CJSON_TEST) #delete test diff --git a/components/cjson/cJSON/README.md b/components/cjson/cJSON/README.md deleted file mode 100644 index c6b788f97..000000000 --- a/components/cjson/cJSON/README.md +++ /dev/null @@ -1,531 +0,0 @@ -# cJSON - -Ultralightweight JSON parser in ANSI C. - -## Table of contents -* [License](#license) -* [Usage](#usage) - * [Welcome to cJSON](#welcome-to-cjson) - * [Building](#building) - * [Copying the source](#copying-the-source) - * [CMake](#cmake) - * [Makefile](#makefile) - * [Including cJSON](#including-cjson) - * [Data Structure](#data-structure) - * [Working with the data structure](#working-with-the-data-structure) - * [Basic types](#basic-types) - * [Arrays](#arrays) - * [Objects](#objects) - * [Parsing JSON](#parsing-json) - * [Printing JSON](#printing-json) - * [Example](#example) - * [Printing](#printing) - * [Parsing](#parsing) - * [Caveats](#caveats) - * [Zero Character](#zero-character) - * [Character Encoding](#character-encoding) - * [C Standard](#c-standard) - * [Floating Point Numbers](#floating-point-numbers) - * [Deep Nesting Of Arrays And Objects](#deep-nesting-of-arrays-and-objects) - * [Thread Safety](#thread-safety) - * [Case Sensitivity](#case-sensitivity) - * [Duplicate Object Members](#duplicate-object-members) - * [Enjoy cJSON!](#enjoy-cjson) - -## License - -MIT License - -> Copyright (c) 2009-2017 Dave Gamble and cJSON contributors -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - -## Usage - -### Welcome to cJSON. - -cJSON aims to be the dumbest possible parser that you can get your job done with. -It's a single file of C, and a single header file. - -JSON is described best here: http://www.json.org/ -It's like XML, but fat-free. You use it to move data around, store things, or just -generally represent your program's state. - -As a library, cJSON exists to take away as much legwork as it can, but not get in your way. -As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it -in one of two modes: Auto and Manual. Let's have a quick run-through. - -I lifted some JSON from this page: http://www.json.org/fatfree.html -That page inspired me to write cJSON, which is a parser that tries to share the same -philosophy as JSON itself. Simple, dumb, out of the way. - -### Building - -There are several ways to incorporate cJSON into your project. - -#### copying the source -Because the entire library is only one C file and one header file, you can just copy `cJSON.h` and `cJSON.c` to your projects source and start using it. - -cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible. - -#### CMake -With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it. - -``` -mkdir build -cd build -cmake .. -``` - -This will create a Makefile and a bunch of other files. You can then compile it: - -``` -make -``` - -And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library. - -You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`: -* `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default) -* `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default) -* `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default) -* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang, GCC and MSVC). Turn off if it makes problems. (on by default) -* `-DENABLE_VALGRIND=On`: Run tests with [valgrind](http://valgrind.org). (off by default) -* `-DENABLE_SANITIZERS=On`: Compile cJSON with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) enabled (if possible). (off by default) -* `-DENABLE_SAFE_STACK`: Enable the [SafeStack](https://clang.llvm.org/docs/SafeStack.html) instrumentation pass. Currently only works with the Clang compiler. (off by default) -* `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default) -* `-DBUILD_SHARED_AND_STATIC_LIBS=On`: Build both shared and static libraries. (off by default) -* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation. -* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default ) -* `-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On`: Enable overriding the value of `BUILD_SHARED_LIBS` with `-DCJSON_BUILD_SHARED_LIBS`. - -If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example: -``` -mkdir build -cd build -cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr -make -make DESTDIR=$pkgdir install -``` - -On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows. - -#### Makefile -**NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs. - -If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON: - -Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite). - -``` -make all -``` - -If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. - -### Including cJSON -If you installed it via CMake or the Makefile, you can include cJSON like this: - -```c -#include -``` - -### Data Structure - -cJSON represents JSON data using the `cJSON` struct data type: - -```c -/* The cJSON structure: */ -typedef struct cJSON -{ - struct cJSON *next; - struct cJSON *prev; - struct cJSON *child; - int type; - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - double valuedouble; - char *string; -} cJSON; -``` - -An item of this type represents a JSON value. The type is stored in `type` as a bit-flag (**this means that you cannot find out the type by just comparing the value of `type`**). - -To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type. - -The type can be one of the following: -* `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes. -* `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`. -* `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`. -* `cJSON_NULL` (check with `cJSON_IsNull`): Represents a `null` value. -* `cJSON_Number` (check with `cJSON_IsNumber`): Represents a number value. The value is stored as a double in `valuedouble` and also in `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`. -* `cJSON_String` (check with `cJSON_IsString`): Represents a string value. It is stored in the form of a zero terminated string in `valuestring`. -* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev == NULL` and the last element `next == NULL`. -* `cJSON_Object` (check with `cJSON_IsObject`): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in `string`. -* `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON. - -Additionally there are the following two flags: -* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not it's children/valuestring. -* `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`. - -### Working with the data structure - -For every value type there is a `cJSON_Create...` function that can be used to create an item of that type. -All of these will allocate a `cJSON` struct that can later be deleted with `cJSON_Delete`. -Note that you have to delete them at some point, otherwise you will get a memory leak. -**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well. - -#### Basic types -* **null** is created with `cJSON_CreateNull` -* **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool` -* **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint` -* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for it's lifetime, useful for constants) - -#### Arrays - -You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`. - -To add items to an array, use `cJSON_AddItemToArray` to append items to the end. -Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere. -To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right. - -If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak. - -Deleting items is done with `cJSON_DeleteItemFromArray`. It works like `cJSON_DetachItemFromArray`, but deletes the detached item via `cJSON_Delete`. - -You can also replace an item in an array in place. Either with `cJSON_ReplaceItemInArray` using an index or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place. - -To get the size of an array, use `cJSON_GetArraySize`. Use `cJSON_GetArrayItem` to get an element at a given index. - -Because an array is stored as a linked list, iterating it via index is inefficient (`O(n²)`), so you can iterate over an array using the `cJSON_ArrayForEach` macro in `O(n)` time complexity. - -#### Objects - -You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`. - -To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`. -Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere. - -If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak. - -Deleting items is done with `cJSON_DeleteItemFromObjectCaseSensitive`. It works like `cJSON_DetachItemFromObjectCaseSensitive` followed by `cJSON_Delete`. - -You can also replace an item in an object in place. Either with `cJSON_ReplaceItemInObjectCaseSensitive` using a key or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place. - -To get the size of an object, you can use `cJSON_GetArraySize`, this works because internally objects are stored as arrays. - -If you want to access an item in an object, use `cJSON_GetObjectItemCaseSensitive`. - -To iterate over an object, you can use the `cJSON_ArrayForEach` macro the same way as for arrays. - -cJSON also provides convenient helper functions for quickly creating a new item and adding it to an object, like `cJSON_AddNullToObject`. They return a pointer to the new item or `NULL` if they failed. - -### Parsing JSON - -Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`. - -```c -cJSON *json = cJSON_Parse(string); -``` - -It will parse the JSON and allocate a tree of `cJSON` items that represents it. Once it returns, you are fully responsible for deallocating it after use with `cJSON_Delete`. - -The allocator used by `cJSON_Parse` is `malloc` and `free` by default but can be changed (globally) with `cJSON_InitHooks`. - -If an error occurs a pointer to the position of the error in the input string can be accessed using `cJSON_GetErrorPtr`. Note though that this can produce race conditions in multithreading scenarios, in that case it is better to use `cJSON_ParseWithOpts` with `return_parse_end`. -By default, characters in the input string that follow the parsed JSON will not be considered as an error. - -If you want more options, use `cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)`. -`return_parse_end` returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing `cJSON_GetErrorPtr` in a thread safe way). `require_null_terminated`, if set to `1` will make it an error if the input string contains data after the JSON. - -### Printing JSON - -Given a tree of `cJSON` items, you can print them as a string using `cJSON_Print`. - -```c -char *string = cJSON_Print(json); -``` - -It will allocate a string and print a JSON representation of the tree into it. Once it returns, you are fully responsible for deallocating it after use with your allocator. (usually `free`, depends on what has been set with `cJSON_InitHooks`). - -`cJSON_Print` will print with whitespace for formatting. If you want to print without formatting, use `cJSON_PrintUnformatted`. - -If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for it's first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued. - -These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough. - -### Example -In this example we want to build and parse the following JSON: - -```json -{ - "name": "Awesome 4K", - "resolutions": [ - { - "width": 1280, - "height": 720 - }, - { - "width": 1920, - "height": 1080 - }, - { - "width": 3840, - "height": 2160 - } - ] -} -``` - -#### Printing -Let's build the above JSON and print it to a string: -```c -//create a monitor with a list of supported resolutions -char* create_monitor(void) -{ - const unsigned int resolution_numbers[3][2] = { - {1280, 720}, - {1920, 1080}, - {3840, 2160} - }; - char *string = NULL; - cJSON *name = NULL; - cJSON *resolutions = NULL; - cJSON *resolution = NULL; - cJSON *width = NULL; - cJSON *height = NULL; - size_t index = 0; - - cJSON *monitor = cJSON_CreateObject(); - if (monitor == NULL) - { - goto end; - } - - name = cJSON_CreateString("Awesome 4K"); - if (name == NULL) - { - goto end; - } - /* after creation was successful, immediately add it to the monitor, - * thereby transfering ownership of the pointer to it */ - cJSON_AddItemToObject(monitor, "name", name); - - resolutions = cJSON_CreateArray(); - if (resolutions == NULL) - { - goto end; - } - cJSON_AddItemToObject(monitor, "resolutions", resolutions); - - for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index) - { - resolution = cJSON_CreateObject(); - if (resolution == NULL) - { - goto end; - } - cJSON_AddItemToArray(resolutions, resolution); - - width = cJSON_CreateNumber(resolution_numbers[index][0]); - if (width == NULL) - { - goto end; - } - cJSON_AddItemToObject(resolution, "width", width); - - height = cJSON_CreateNumber(resolution_numbers[index][1]); - if (height == NULL) - { - goto end; - } - cJSON_AddItemToObject(resolution, "height", height); - } - - string = cJSON_Print(monitor); - if (string == NULL) - { - fprintf(stderr, "Failed to print monitor.\n"); - } - -end: - cJSON_Delete(monitor); - return string; -} -``` - -Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier: -```c -char *create_monitor_with_helpers(void) -{ - const unsigned int resolution_numbers[3][2] = { - {1280, 720}, - {1920, 1080}, - {3840, 2160} - }; - char *string = NULL; - cJSON *resolutions = NULL; - size_t index = 0; - - cJSON *monitor = cJSON_CreateObject(); - - if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL) - { - goto end; - } - - resolutions = cJSON_AddArrayToObject(monitor, "resolutions"); - if (resolutions == NULL) - { - goto end; - } - - for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index) - { - cJSON *resolution = cJSON_CreateObject(); - - if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL) - { - goto end; - } - - if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL) - { - goto end; - } - - cJSON_AddItemToArray(resolutions, resolution); - } - - string = cJSON_Print(monitor); - if (string == NULL) { - fprintf(stderr, "Failed to print monitor.\n"); - } - -end: - cJSON_Delete(monitor); - return string; -} -``` - -#### Parsing -In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output: - -```c -/* return 1 if the monitor supports full hd, 0 otherwise */ -int supports_full_hd(const char * const monitor) -{ - const cJSON *resolution = NULL; - const cJSON *resolutions = NULL; - const cJSON *name = NULL; - int status = 0; - cJSON *monitor_json = cJSON_Parse(monitor); - if (monitor_json == NULL) - { - const char *error_ptr = cJSON_GetErrorPtr(); - if (error_ptr != NULL) - { - fprintf(stderr, "Error before: %s\n", error_ptr); - } - status = 0; - goto end; - } - - name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name"); - if (cJSON_IsString(name) && (name->valuestring != NULL)) - { - printf("Checking monitor \"%s\"\n", name->valuestring); - } - - resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions"); - cJSON_ArrayForEach(resolution, resolutions) - { - cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width"); - cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height"); - - if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height)) - { - status = 0; - goto end; - } - - if ((width->valuedouble == 1920) && (height->valuedouble == 1080)) - { - status = 1; - goto end; - } - } - -end: - cJSON_Delete(monitor_json); - return status; -} -``` - -Note that there are no NULL checks except for the result of `cJSON_Parse` because `cJSON_GetObjectItemCaseSensitive` checks for `NULL` inputs already, so a `NULL` value is just propagated and `cJSON_IsNumber` and `cJSON_IsString` return `0` if the input is `NULL`. - -### Caveats - -#### Zero Character - -cJSON doesn't support strings that contain the zero character `'\0'` or `\u0000`. This is impossible with the current API because strings are zero terminated. - -#### Character Encoding - -cJSON only supports UTF-8 encoded input. In most cases it doesn't reject invalid UTF-8 as input though, it just propagates it through as is. As long as the input doesn't contain invalid UTF-8, the output will always be valid UTF-8. - -#### C Standard - -cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't follow this standard, correct behavior is not guaranteed. - -NOTE: ANSI C is not C++ therefore it shouldn't be compiled with a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed. - -#### Floating Point Numbers - -cJSON does not officially support any `double` implementations other than IEEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid. - -The maximum length of a floating point literal that cJSON supports is currently 63 characters. - -#### Deep Nesting Of Arrays And Objects - -cJSON doesn't support arrays and objects that are nested too deeply because this would result in a stack overflow. To prevent this cJSON limits the depth to `CJSON_NESTING_LIMIT` which is 1000 by default but can be changed at compile time. - -#### Thread Safety - -In general cJSON is **not thread safe**. - -However it is thread safe under the following conditions: -* `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead) -* `cJSON_InitHooks` is only ever called before using cJSON in any threads. -* `setlocale` is never called before all calls to cJSON functions have returned. - -#### Case Sensitivity - -When cJSON was originally created, it didn't follow the JSON standard and didn't make a distinction between uppercase and lowercase letters. If you want the correct, standard compliant, behavior, you need to use the `CaseSensitive` functions where available. - -#### Duplicate Object Members - -cJSON supports parsing and printing JSON that contains objects that have multiple members with the same name. `cJSON_GetObjectItemCaseSensitive` however will always only return the first one. - -# Enjoy cJSON! - -- Dave Gamble (original author) -- Max Bruckner (current maintainer) -- and the other [cJSON contributors](CONTRIBUTORS.md) diff --git a/components/cjson/cJSON/appveyor.yml b/components/cjson/cJSON/appveyor.yml deleted file mode 100644 index 464bf0388..000000000 --- a/components/cjson/cJSON/appveyor.yml +++ /dev/null @@ -1,86 +0,0 @@ -os: Visual Studio 2015 - -# ENABLE_CUSTOM_COMPILER_FLAGS - on by default -# ENABLE_SANITIZERS - off by default -# ENABLE_PUBLIC_SYMBOLS - on by default -# BUILD_SHARED_LIBS - on by default -# ENABLE_TARGET_EXPORT - on by default -# ENABLE_CJSON_UTILS - off by default -# ENABLE_CJSON_TEST -on by default -# ENABLE_VALGRIND - off by default -# ENABLE_FUZZING - off by default - -environment: - matrix: - - GENERATOR: "Visual Studio 14 2015" - BUILD_SHARED_LIBS: ON - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 14 2015" - BUILD_SHARED_LIBS: OFF - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 12 2013" - BUILD_SHARED_LIBS: ON - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 12 2013" - BUILD_SHARED_LIBS: OFF - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 11 2012" - BUILD_SHARED_LIBS: ON - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 11 2012" - BUILD_SHARED_LIBS: OFF - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 10 2010" - BUILD_SHARED_LIBS: ON - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 10 2010" - BUILD_SHARED_LIBS: OFF - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 9 2008" - BUILD_SHARED_LIBS: ON - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - - GENERATOR: "Visual Studio 9 2008" - BUILD_SHARED_LIBS: OFF - ENABLE_CJSON_TEST: OFF - ENABLE_CJSON_UTILS: ON - - -platform: - - x86 - - x64 -matrix: - exclude: - - platform: x64 - GENERATOR: "Visual Studio 9 2008" - -configuration: - - Release - - -build_script: - - ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" } - - cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -DENABLE_CJSON_TEST=%ENABLE_CJSON_TEST% -H. -Bbuild - - cmake --build build --config "%CONFIGURATION%" - - -on_failure: - - ps: if(Test-Path builds/CMakeFiles/CMakeOutput.log) { cat builds/CMakeFiles/CMakeOutput.log } - - ps: if(Test-Path builds/CMakeFiles/CMakeError.log) { cat builds/CMakeFiles/CMakeError.log } \ No newline at end of file diff --git a/components/cjson/cJSON/cJSON.c b/components/cjson/cJSON/cJSON.c deleted file mode 100644 index cbc62a215..000000000 --- a/components/cjson/cJSON/cJSON.c +++ /dev/null @@ -1,2978 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning (push) -/* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ENABLE_LOCALES -#include -#endif - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#ifndef CJSON_SPRINTF_FLOAT -#define CJSON_SPRINTF_FLOAT 0 -#endif - -#include "cJSON.h" - -/* define our own boolean type */ -#define true ((cJSON_bool)1) -#define false ((cJSON_bool)0) - -typedef struct { - const unsigned char *json; - size_t position; -} error; -static error global_error = { NULL, 0 }; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) -{ - return (const char*) (global_error.json + global_error.position); -} - -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { - if (!cJSON_IsString(item)) { - return NULL; - } - - return item->valuestring; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 6) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) -{ - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) -{ - if ((string1 == NULL) || (string2 == NULL)) - { - return 1; - } - - if (string1 == string2) - { - return 0; - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks -{ - void *(*allocate)(size_t size); - void (*deallocate)(void *pointer); - void *(*reallocate)(void *pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ -static void *internal_malloc(size_t size) -{ - return malloc(size); -} -static void internal_free(void *pointer) -{ - free(pointer); -} -static void *internal_realloc(void *pointer, size_t size) -{ - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; - -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) -{ - size_t length = 0; - unsigned char *copy = NULL; - - if (string == NULL) - { - return NULL; - } - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) - { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) -{ - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) -{ - cJSON *next = NULL; - while (item != NULL) - { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { - cJSON_Delete(item->child); - } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { - global_hooks.deallocate(item->valuestring); - } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - global_hooks.deallocate(item->string); - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) -{ -#ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct -{ - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { - return false; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if (number >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) -{ - if (number >= INT_MAX) - { - object->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - object->valueint = INT_MIN; - } - else - { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -typedef struct -{ - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) -{ - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) - { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) - { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) - { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { - newsize = INT_MAX; - } - else - { - return NULL; - } - } - else - { - newsize = needed * 2; - } - - if (p->hooks.reallocate != NULL) - { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } - else - { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) - { - memcpy(newbuffer, p->buffer, p->offset + 1); - } - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) -{ - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26]; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - - if (output_buffer == NULL) - { - return false; - } - - /* This checks for NaN and Infinity */ - if ((d * 0) != 0) - { - length = sprintf((char*)number_buffer, "null"); - } - else - { -#if CJSON_SPRINTF_FLOAT - double test; - - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); - - /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) - { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); - } -#else - long d32 = (long)d; - - length = sprintf((char*)number_buffer, "%ld", d32); - - if ((double)d32 != d) { - size_t precision = 14; - unsigned char *pbuf = number_buffer; - - if (d < 0.0) { - d = (double)d32 - d + 0.00000000000001; - } else { - d = d - (double)d32; - } - - pbuf = &number_buffer[length]; - *pbuf++ = '.'; - length++; - - while (d > 0.0 && precision--) { - d *= 10.0; - unsigned char tmp = (unsigned char)d; - - *pbuf++ = tmp + '0'; - length++; - - d -= (double)tmp; - } - - pbuf = &number_buffer[length - 1]; - - while (*pbuf == '0') { - pbuf--; - length--; - } - - *++pbuf = 0; - } -#endif - } - - /* sprintf failed or buffer overrun occured */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) -{ - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) - { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ - { - return 0; - } - - if (i < 3) - { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) -{ - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { - /* invalid second half of the surrogate pair */ - goto fail; - } - - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } - else if (codepoint < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } - else - { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) - { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) -{ - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else - { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { - goto fail; - } - - switch (input_pointer[1]) - { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - input_buffer->offset = (size_t) (input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if (output != NULL) - { - input_buffer->hooks.deallocate(output); - } - - if (input_pointer != NULL) - { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) -{ - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) - { - return false; - } - - /* empty string */ - if (input == NULL) - { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) - { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { - /* normal character, copy */ - *output_pointer = *input_pointer; - } - else - { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) - { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) -{ - return print_string_ptr((unsigned char*)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL)) - { - return NULL; - } - - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; - } - - if (buffer->offset == buffer->length) - { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { - return NULL; - } - - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { - buffer->offset += 3; - } - - return buffer; -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - cJSON *item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if (value == NULL) - { - goto fail; - } - - buffer.content = (const unsigned char*)value; - buffer.length = strlen((const char*)value) + sizeof(""); - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ - { - goto fail; - } - - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { - goto fail; - } - } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); - } - - return item; - -fail: - if (item != NULL) - { - cJSON_Delete(item); - } - - if (value != NULL) - { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; - - if (buffer.offset < buffer.length) - { - local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { - local_error.position = buffer.length - 1; - } - - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -#define cjson_min(a, b) ((a < b) ? a : b) - -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) -{ - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { - goto fail; - } - - /* print the value */ - if (!print_value(item, buffer)) - { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); - buffer->buffer = NULL; - if (printed == NULL) { - goto fail; - } - } - else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { - goto fail; - } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - } - - return printed; - -fail: - if (buffer->buffer != NULL) - { - hooks->deallocate(buffer->buffer); - } - - if (printed != NULL) - { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) -{ - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) -{ - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if (prebuffer < 0) - { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if (!print_value(item, &p)) - { - global_hooks.deallocate(p.buffer); - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if ((len < 0) || (buf == NULL)) - { - return false; - } - - p.buffer = (unsigned char*)buf; - p.length = (size_t)len; - p.offset = 0; - p.noalloc = true; - p.format = fmt; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) -{ - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { - return parse_string(item, input_buffer); - } - /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { - return parse_number(item, input_buffer); - } - /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { - return parse_array(item, input_buffer); - } - /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) - { - return false; - } - - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (buffer_at_offset(input_buffer)[0] != '[') - { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { - return false; - } - update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ','; - if(output_buffer->format) - { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { - goto fail; /* faile to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) - { - if (output_buffer->format) - { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { - return false; - } - for (i = 0; i < output_buffer->depth; i++) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ':'; - if (output_buffer->format) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - if (current_item->next) - { - *output_pointer++ = ','; - } - - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { - return false; - } - if (output_buffer->format) - { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) -{ - cJSON *child = NULL; - size_t size = 0; - - if (array == NULL) - { - return 0; - } - - child = array->child; - - while(child != NULL) - { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON* get_array_item(const cJSON *array, size_t index) -{ - cJSON *current_child = NULL; - - if (array == NULL) - { - return NULL; - } - - current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) -{ - if (index < 0) - { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) -{ - cJSON *current_element = NULL; - - if ((object == NULL) || (name == NULL)) - { - return NULL; - } - - current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) - { - current_element = current_element->next; - } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { - current_element = current_element->next; - } - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) -{ - cJSON *reference = NULL; - if (item == NULL) - { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if (reference == NULL) - { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) -{ - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL)) - { - return false; - } - - child = array->child; - - if (child == NULL) - { - /* list is empty, start new one */ - array->child = item; - } - else - { - /* append to the end */ - while (child->next) - { - child = child->next; - } - suffix_object(child, item); - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - add_item_to_array(array, item); -} - -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void* cast_away_const(const void* string) -{ - return (void*)string; -} -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop -#endif - - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) -{ - char *new_key = NULL; - int new_type = cJSON_Invalid; - - if ((object == NULL) || (string == NULL) || (item == NULL)) - { - return false; - } - - if (constant_key) - { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - if (array == NULL) - { - return; - } - - add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - if ((object == NULL) || (string == NULL)) - { - return; - } - - add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) -{ - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) -{ - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) -{ - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) -{ - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) -{ - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) -{ - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) -{ - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) -{ - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) -{ - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) -{ - if ((parent == NULL) || (item == NULL)) - { - return NULL; - } - - if (item->prev != NULL) - { - /* not the first element */ - item->prev->next = item->next; - } - if (item->next != NULL) - { - /* not the last element */ - item->next->prev = item->prev; - } - - if (item == parent->child) - { - /* first element */ - parent->child = item->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) -{ - if (which < 0) - { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *after_inserted = NULL; - - if (which < 0) - { - return; - } - - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { - add_item_to_array(array, newitem); - return; - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) -{ - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) - { - return false; - } - - if (replacement == item) - { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if (replacement->next != NULL) - { - replacement->next->prev = replacement; - } - if (replacement->prev != NULL) - { - replacement->prev->next = replacement; - } - if (parent->child == item) - { - parent->child = replacement; - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - if (which < 0) - { - return; - } - - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) -{ - if ((replacement == NULL) || (string == NULL)) - { - return false; - } - - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { - cJSON_free(replacement->string); - } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - replacement->type &= ~cJSON_StringIsConst; - - cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); - - return true; -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) -{ - replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = b ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (num <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0;a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (strings == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) -{ - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { - goto fail; - } - } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) - { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - goto fail; - } - if (next != NULL) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - - return newitem; - -fail: - if (newitem != NULL) - { - cJSON_Delete(newitem); - } - - return NULL; -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) -{ - unsigned char *into = (unsigned char*)json; - - if (json == NULL) - { - return; - } - - while (*json) - { - if (*json == ' ') - { - json++; - } - else if (*json == '\t') - { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') - { - json++; - } - else if (*json=='\n') - { - json++; - } - else if ((*json == '/') && (json[1] == '/')) - { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) - { - json++; - } - } - else if ((*json == '/') && (json[1] == '*')) - { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) - { - json++; - } - json += 2; - } - else if (*json == '\"') - { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) - { - if (*json == '\\') - { - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else - { - /* All other characters. */ - *into++ = (unsigned char)*json++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) -{ - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) - { - return false; - } - - /* check if type is valid */ - switch (a->type & 0xFF) - { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if (a == b) - { - return true; - } - - switch (a->type & 0xFF) - { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if (a->valuedouble == b->valuedouble) - { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { - return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) - { - return true; - } - - return false; - - case cJSON_Array: - { - cJSON *a_element = a->child; - cJSON *b_element = b->child; - - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: - { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) - { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) - { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) -{ - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void *object) -{ - global_hooks.deallocate(object); -} diff --git a/components/cjson/cJSON/cJSON.h b/components/cjson/cJSON/cJSON.h deleted file mode 100644 index 15eda75fa..000000000 --- a/components/cjson/cJSON/cJSON.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 6 - -#include - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks -{ - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does - -*/ - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type __stdcall -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall -#endif -#else /* !WIN32 */ -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ -#ifndef CJSON_NESTING_LIMIT -#define CJSON_NESTING_LIMIT 1000 -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* Check if the item is a string and return its valuestring */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); - -/* These utilities create an Array of count items. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); - - -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) - -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ -CJSON_PUBLIC(void *) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void *object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/cjson/cJSON/cJSON_Utils.c b/components/cjson/cJSON/cJSON_Utils.c deleted file mode 100644 index 0d199f883..000000000 --- a/components/cjson/cJSON/cJSON_Utils.c +++ /dev/null @@ -1,1449 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUCC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning (push) -/* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) -#endif - -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif -#ifdef __GNUCC__ -#pragma GCC visibility pop -#endif - -#include "cJSON_Utils.h" - -/* define our own boolean type */ -#define true ((cJSON_bool)1) -#define false ((cJSON_bool)0) - -static unsigned char* cJSONUtils_strdup(const unsigned char* const string) -{ - size_t length = 0; - unsigned char *copy = NULL; - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*) cJSON_malloc(length); - if (copy == NULL) - { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -/* string comparison which doesn't consider NULL pointers equal */ -static int compare_strings(const unsigned char *string1, const unsigned char *string2, const cJSON_bool case_sensitive) -{ - if ((string1 == NULL) || (string2 == NULL)) - { - return 1; - } - - if (string1 == string2) - { - return 0; - } - - if (case_sensitive) - { - return strcmp((const char*)string1, (const char*)string2); - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */ -static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive) -{ - if ((name == NULL) || (pointer == NULL)) - { - return false; - } - - for (; (*name != '\0') && (*pointer != '\0') && (*pointer != '/'); (void)name++, pointer++) /* compare until next '/' */ - { - if (*pointer == '~') - { - /* check for escaped '~' (~0) and '/' (~1) */ - if (((pointer[1] != '0') || (*name != '~')) && ((pointer[1] != '1') || (*name != '/'))) - { - /* invalid escape sequence or wrong character in *name */ - return false; - } - else - { - pointer++; - } - } - else if ((!case_sensitive && (tolower(*name) != tolower(*pointer))) || (case_sensitive && (*name != *pointer))) - { - return false; - } - } - if (((*pointer != 0) && (*pointer != '/')) != (*name != 0)) - { - /* one string has ended, the other not */ - return false;; - } - - return true; -} - -/* calculate the length of a string if encoded as JSON pointer with ~0 and ~1 escape sequences */ -static size_t pointer_encoded_length(const unsigned char *string) -{ - size_t length; - for (length = 0; *string != '\0'; (void)string++, length++) - { - /* character needs to be escaped? */ - if ((*string == '~') || (*string == '/')) - { - length++; - } - } - - return length; -} - -/* copy a string while escaping '~' and '/' with ~0 and ~1 JSON pointer escape codes */ -static void encode_string_as_pointer(unsigned char *destination, const unsigned char *source) -{ - for (; source[0] != '\0'; (void)source++, destination++) - { - if (source[0] == '/') - { - destination[1] = '1'; - destination++; - } - else if (source[0] == '~') - { - destination[0] = '~'; - destination[1] = '1'; - destination++; - } - else - { - destination[0] = source[0]; - } - } - - destination[0] = '\0'; -} - -CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target) -{ - size_t child_index = 0; - cJSON *current_child = 0; - - if ((object == NULL) || (target == NULL)) - { - return NULL; - } - - if (object == target) - { - /* found */ - return (char*)cJSONUtils_strdup((const unsigned char*)""); - } - - /* recursively search all children of the object or array */ - for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++) - { - unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target); - /* found the target? */ - if (target_pointer != NULL) - { - if (cJSON_IsArray(object)) - { - /* reserve enough memory for a 64 bit integer + '/' and '\0' */ - unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/")); - /* check if conversion to unsigned long is valid - * This should be eliminated at compile time by dead code elimination - * if size_t is an alias of unsigned long, or if it is bigger */ - if (child_index > ULONG_MAX) - { - cJSON_free(target_pointer); - return NULL; - } - sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* / */ - cJSON_free(target_pointer); - - return (char*)full_pointer; - } - - if (cJSON_IsObject(object)) - { - unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2); - full_pointer[0] = '/'; - encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string); - strcat((char*)full_pointer, (char*)target_pointer); - cJSON_free(target_pointer); - - return (char*)full_pointer; - } - - /* reached leaf of the tree, found nothing */ - cJSON_free(target_pointer); - return NULL; - } - } - - /* not found */ - return NULL; -} - -/* non broken version of cJSON_GetArrayItem */ -static cJSON *get_array_item(const cJSON *array, size_t item) -{ - cJSON *child = array ? array->child : NULL; - while ((child != NULL) && (item > 0)) - { - item--; - child = child->next; - } - - return child; -} - -static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index) -{ - size_t parsed_index = 0; - size_t position = 0; - - if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/'))) - { - /* leading zeroes are not permitted */ - return 0; - } - - for (position = 0; (pointer[position] >= '0') && (pointer[0] <= '9'); position++) - { - parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0'); - - } - - if ((pointer[position] != '\0') && (pointer[position] != '/')) - { - return 0; - } - - *index = parsed_index; - - return 1; -} - -static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive) -{ - cJSON *current_element = object; - - if (pointer == NULL) - { - return NULL; - } - - /* follow path of the pointer */ - while ((pointer[0] == '/') && (current_element != NULL)) - { - pointer++; - if (cJSON_IsArray(current_element)) - { - size_t index = 0; - if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index)) - { - return NULL; - } - - current_element = get_array_item(current_element, index); - } - else if (cJSON_IsObject(current_element)) - { - current_element = current_element->child; - /* GetObjectItem. */ - while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive)) - { - current_element = current_element->next; - } - } - else - { - return NULL; - } - - /* skip to the next path token or end of string */ - while ((pointer[0] != '\0') && (pointer[0] != '/')) - { - pointer++; - } - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer) -{ - return get_item_from_pointer(object, pointer, false); -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer) -{ - return get_item_from_pointer(object, pointer, true); -} - -/* JSON Patch implementation. */ -static void decode_pointer_inplace(unsigned char *string) -{ - unsigned char *decoded_string = string; - - if (string == NULL) { - return; - } - - for (; *string; (void)decoded_string++, string++) - { - if (string[0] == '~') - { - if (string[1] == '0') - { - decoded_string[0] = '~'; - } - else if (string[1] == '1') - { - decoded_string[1] = '/'; - } - else - { - /* invalid escape sequence */ - return; - } - - string++; - } - } - - decoded_string[0] = '\0'; -} - -/* non-broken cJSON_DetachItemFromArray */ -static cJSON *detach_item_from_array(cJSON *array, size_t which) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - /* item doesn't exist */ - return NULL; - } - if (c->prev) - { - /* not the first element */ - c->prev->next = c->next; - } - if (c->next) - { - c->next->prev = c->prev; - } - if (c==array->child) - { - array->child = c->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - c->prev = c->next = NULL; - - return c; -} - -/* detach an item at the given path */ -static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive) -{ - unsigned char *parent_pointer = NULL; - unsigned char *child_pointer = NULL; - cJSON *parent = NULL; - cJSON *detached_item = NULL; - - /* copy path and split it in parent and child */ - parent_pointer = cJSONUtils_strdup(path); - if (parent_pointer == NULL) { - goto cleanup; - } - - child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */ - if (child_pointer == NULL) - { - goto cleanup; - } - /* split strings */ - child_pointer[0] = '\0'; - child_pointer++; - - parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); - decode_pointer_inplace(child_pointer); - - if (cJSON_IsArray(parent)) - { - size_t index = 0; - if (!decode_array_index_from_pointer(child_pointer, &index)) - { - goto cleanup; - } - detached_item = detach_item_from_array(parent, index); - } - else if (cJSON_IsObject(parent)) - { - detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer); - } - else - { - /* Couldn't find object to remove child from. */ - goto cleanup; - } - -cleanup: - if (parent_pointer != NULL) - { - cJSON_free(parent_pointer); - } - - return detached_item; -} - -/* sort lists using mergesort */ -static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive) -{ - cJSON *first = list; - cJSON *second = list; - cJSON *current_item = list; - cJSON *result = list; - cJSON *result_tail = NULL; - - if ((list == NULL) || (list->next == NULL)) - { - /* One entry is sorted already. */ - return result; - } - - while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0)) - { - /* Test for list sorted. */ - current_item = current_item->next; - } - if ((current_item == NULL) || (current_item->next == NULL)) - { - /* Leave sorted lists unmodified. */ - return result; - } - - /* reset pointer to the beginning */ - current_item = list; - while (current_item != NULL) - { - /* Walk two pointers to find the middle. */ - second = second->next; - current_item = current_item->next; - /* advances current_item two steps at a time */ - if (current_item != NULL) - { - current_item = current_item->next; - } - } - if ((second != NULL) && (second->prev != NULL)) - { - /* Split the lists */ - second->prev->next = NULL; - } - - /* Recursively sort the sub-lists. */ - first = sort_list(first, case_sensitive); - second = sort_list(second, case_sensitive); - result = NULL; - - /* Merge the sub-lists */ - while ((first != NULL) && (second != NULL)) - { - cJSON *smaller = NULL; - if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, false) < 0) - { - smaller = first; - } - else - { - smaller = second; - } - - if (result == NULL) - { - /* start merged list with the smaller element */ - result_tail = smaller; - result = smaller; - } - else - { - /* add smaller element to the list */ - result_tail->next = smaller; - smaller->prev = result_tail; - result_tail = smaller; - } - - if (first == smaller) - { - first = first->next; - } - else - { - second = second->next; - } - } - - if (first != NULL) - { - /* Append rest of first list. */ - if (result == NULL) - { - return first; - } - result_tail->next = first; - first->prev = result_tail; - } - if (second != NULL) - { - /* Append rest of second list */ - if (result == NULL) - { - return second; - } - result_tail->next = second; - second->prev = result_tail; - } - - return result; -} - -static void sort_object(cJSON * const object, const cJSON_bool case_sensitive) -{ - if (object == NULL) - { - return; - } - object->child = sort_list(object->child, case_sensitive); -} - -static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive) -{ - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) - { - /* mismatched type. */ - return false; - } - switch (a->type & 0xFF) - { - case cJSON_Number: - /* numeric mismatch. */ - if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble)) - { - return false; - } - else - { - return true; - } - - case cJSON_String: - /* string mismatch. */ - if (strcmp(a->valuestring, b->valuestring) != 0) - { - return false; - } - else - { - return true; - } - - case cJSON_Array: - for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) - { - cJSON_bool identical = compare_json(a, b, case_sensitive); - if (!identical) - { - return false; - } - } - - /* array size mismatch? (one of both children is not NULL) */ - if ((a != NULL) || (b != NULL)) - { - return false; - } - else - { - return true; - } - - case cJSON_Object: - sort_object(a, case_sensitive); - sort_object(b, case_sensitive); - for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) - { - cJSON_bool identical = false; - /* compare object keys */ - if (compare_strings((unsigned char*)a->string, (unsigned char*)b->string, case_sensitive)) - { - /* missing member */ - return false; - } - identical = compare_json(a, b, case_sensitive); - if (!identical) - { - return false; - } - } - - /* object length mismatch (one of both children is not null) */ - if ((a != NULL) || (b != NULL)) - { - return false; - } - else - { - return true; - } - - default: - break; - } - - /* null, true or false */ - return true; -} - -/* non broken version of cJSON_InsertItemInArray */ -static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON *newitem) -{ - cJSON *child = array->child; - while (child && (which > 0)) - { - child = child->next; - which--; - } - if (which > 0) - { - /* item is after the end of the array */ - return 0; - } - if (child == NULL) - { - cJSON_AddItemToArray(array, newitem); - return 1; - } - - /* insert into the linked list */ - newitem->next = child; - newitem->prev = child->prev; - child->prev = newitem; - - /* was it at the beginning */ - if (child == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } - - return 1; -} - -static cJSON *get_object_item(const cJSON * const object, const char* name, const cJSON_bool case_sensitive) -{ - if (case_sensitive) - { - return cJSON_GetObjectItemCaseSensitive(object, name); - } - - return cJSON_GetObjectItem(object, name); -} - -enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST }; - -static enum patch_operation decode_patch_operation(const cJSON * const patch, const cJSON_bool case_sensitive) -{ - cJSON *operation = get_object_item(patch, "op", case_sensitive); - if (!cJSON_IsString(operation)) - { - return INVALID; - } - - if (strcmp(operation->valuestring, "add") == 0) - { - return ADD; - } - - if (strcmp(operation->valuestring, "remove") == 0) - { - return REMOVE; - } - - if (strcmp(operation->valuestring, "replace") == 0) - { - return REPLACE; - } - - if (strcmp(operation->valuestring, "move") == 0) - { - return MOVE; - } - - if (strcmp(operation->valuestring, "copy") == 0) - { - return COPY; - } - - if (strcmp(operation->valuestring, "test") == 0) - { - return TEST; - } - - return INVALID; -} - -/* overwrite and existing item with another one and free resources on the way */ -static void overwrite_item(cJSON * const root, const cJSON replacement) -{ - if (root == NULL) - { - return; - } - - if (root->string != NULL) - { - cJSON_free(root->string); - } - if (root->valuestring != NULL) - { - cJSON_free(root->valuestring); - } - if (root->child != NULL) - { - cJSON_Delete(root->child); - } - - memcpy(root, &replacement, sizeof(cJSON)); -} - -static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive) -{ - cJSON *path = NULL; - cJSON *value = NULL; - cJSON *parent = NULL; - enum patch_operation opcode = INVALID; - unsigned char *parent_pointer = NULL; - unsigned char *child_pointer = NULL; - int status = 0; - - path = get_object_item(patch, "path", case_sensitive); - if (!cJSON_IsString(path)) - { - /* malformed patch. */ - status = 2; - goto cleanup; - } - - opcode = decode_patch_operation(patch, case_sensitive); - if (opcode == INVALID) - { - status = 3; - goto cleanup; - } - else if (opcode == TEST) - { - /* compare value: {...} with the given path */ - status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive); - goto cleanup; - } - - /* special case for replacing the root */ - if (path->valuestring[0] == '\0') - { - if (opcode == REMOVE) - { - static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; - - overwrite_item(object, invalid); - - status = 0; - goto cleanup; - } - - if ((opcode == REPLACE) || (opcode == ADD)) - { - value = get_object_item(patch, "value", case_sensitive); - if (value == NULL) - { - /* missing "value" for add/replace. */ - status = 7; - goto cleanup; - } - - value = cJSON_Duplicate(value, 1); - if (value == NULL) - { - /* out of memory for add/replace. */ - status = 8; - goto cleanup; - } - - overwrite_item(object, *value); - - /* delete the duplicated value */ - cJSON_free(value); - value = NULL; - - /* the string "value" isn't needed */ - if (object->string != NULL) - { - cJSON_free(object->string); - object->string = NULL; - } - - status = 0; - goto cleanup; - } - } - - if ((opcode == REMOVE) || (opcode == REPLACE)) - { - /* Get rid of old. */ - cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive); - if (old_item == NULL) - { - status = 13; - goto cleanup; - } - cJSON_Delete(old_item); - if (opcode == REMOVE) - { - /* For Remove, this job is done. */ - status = 0; - goto cleanup; - } - } - - /* Copy/Move uses "from". */ - if ((opcode == MOVE) || (opcode == COPY)) - { - cJSON *from = get_object_item(patch, "from", case_sensitive); - if (from == NULL) - { - /* missing "from" for copy/move. */ - status = 4; - goto cleanup; - } - - if (opcode == MOVE) - { - value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive); - } - if (opcode == COPY) - { - value = get_item_from_pointer(object, from->valuestring, case_sensitive); - } - if (value == NULL) - { - /* missing "from" for copy/move. */ - status = 5; - goto cleanup; - } - if (opcode == COPY) - { - value = cJSON_Duplicate(value, 1); - } - if (value == NULL) - { - /* out of memory for copy/move. */ - status = 6; - goto cleanup; - } - } - else /* Add/Replace uses "value". */ - { - value = get_object_item(patch, "value", case_sensitive); - if (value == NULL) - { - /* missing "value" for add/replace. */ - status = 7; - goto cleanup; - } - value = cJSON_Duplicate(value, 1); - if (value == NULL) - { - /* out of memory for add/replace. */ - status = 8; - goto cleanup; - } - } - - /* Now, just add "value" to "path". */ - - /* split pointer in parent and child */ - parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); - child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); - if (child_pointer != NULL) - { - child_pointer[0] = '\0'; - child_pointer++; - } - parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); - decode_pointer_inplace(child_pointer); - - /* add, remove, replace, move, copy, test. */ - if ((parent == NULL) || (child_pointer == NULL)) - { - /* Couldn't find object to add to. */ - status = 9; - goto cleanup; - } - else if (cJSON_IsArray(parent)) - { - if (strcmp((char*)child_pointer, "-") == 0) - { - cJSON_AddItemToArray(parent, value); - value = NULL; - } - else - { - size_t index = 0; - if (!decode_array_index_from_pointer(child_pointer, &index)) - { - status = 11; - goto cleanup; - } - - if (!insert_item_in_array(parent, index, value)) - { - status = 10; - goto cleanup; - } - value = NULL; - } - } - else if (cJSON_IsObject(parent)) - { - if (case_sensitive) - { - cJSON_DeleteItemFromObjectCaseSensitive(parent, (char*)child_pointer); - } - else - { - cJSON_DeleteItemFromObject(parent, (char*)child_pointer); - } - cJSON_AddItemToObject(parent, (char*)child_pointer, value); - value = NULL; - } - else /* parent is not an object */ - { - /* Couldn't find object to add to. */ - status = 9; - goto cleanup; - } - -cleanup: - if (value != NULL) - { - cJSON_Delete(value); - } - if (parent_pointer != NULL) - { - cJSON_free(parent_pointer); - } - - return status; -} - -CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches) -{ - const cJSON *current_patch = NULL; - int status = 0; - - if (!cJSON_IsArray(patches)) - { - /* malformed patches. */ - return 1; - } - - if (patches != NULL) - { - current_patch = patches->child; - } - - while (current_patch != NULL) - { - status = apply_patch(object, current_patch, false); - if (status != 0) - { - return status; - } - current_patch = current_patch->next; - } - - return 0; -} - -CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches) -{ - const cJSON *current_patch = NULL; - int status = 0; - - if (!cJSON_IsArray(patches)) - { - /* malformed patches. */ - return 1; - } - - if (patches != NULL) - { - current_patch = patches->child; - } - - while (current_patch != NULL) - { - status = apply_patch(object, current_patch, true); - if (status != 0) - { - return status; - } - current_patch = current_patch->next; - } - - return 0; -} - -static void compose_patch(cJSON * const patches, const unsigned char * const operation, const unsigned char * const path, const unsigned char *suffix, const cJSON * const value) -{ - cJSON *patch = NULL; - - if ((patches == NULL) || (operation == NULL) || (path == NULL)) - { - return; - } - - patch = cJSON_CreateObject(); - if (patch == NULL) - { - return; - } - cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)operation)); - - if (suffix == NULL) - { - cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path)); - } - else - { - size_t suffix_length = pointer_encoded_length(suffix); - size_t path_length = strlen((const char*)path); - unsigned char *full_path = (unsigned char*)cJSON_malloc(path_length + suffix_length + sizeof("/")); - - sprintf((char*)full_path, "%s/", (const char*)path); - encode_string_as_pointer(full_path + path_length + 1, suffix); - - cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)full_path)); - cJSON_free(full_path); - } - - if (value != NULL) - { - cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(value, 1)); - } - cJSON_AddItemToArray(patches, patch); -} - -CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value) -{ - compose_patch(array, (const unsigned char*)operation, (const unsigned char*)path, NULL, value); -} - -static void create_patches(cJSON * const patches, const unsigned char * const path, cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) -{ - if ((from == NULL) || (to == NULL)) - { - return; - } - - if ((from->type & 0xFF) != (to->type & 0xFF)) - { - compose_patch(patches, (const unsigned char*)"replace", path, 0, to); - return; - } - - switch (from->type & 0xFF) - { - case cJSON_Number: - if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble)) - { - compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); - } - return; - - case cJSON_String: - if (strcmp(from->valuestring, to->valuestring) != 0) - { - compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); - } - return; - - case cJSON_Array: - { - size_t index = 0; - cJSON *from_child = from->child; - cJSON *to_child = to->child; - unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */ - - /* generate patches for all array elements that exist in both "from" and "to" */ - for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++) - { - /* check if conversion to unsigned long is valid - * This should be eliminated at compile time by dead code elimination - * if size_t is an alias of unsigned long, or if it is bigger */ - if (index > ULONG_MAX) - { - cJSON_free(new_path); - return; - } - sprintf((char*)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */ - create_patches(patches, new_path, from_child, to_child, case_sensitive); - } - - /* remove leftover elements from 'from' that are not in 'to' */ - for (; (from_child != NULL); (void)(from_child = from_child->next)) - { - /* check if conversion to unsigned long is valid - * This should be eliminated at compile time by dead code elimination - * if size_t is an alias of unsigned long, or if it is bigger */ - if (index > ULONG_MAX) - { - cJSON_free(new_path); - return; - } - sprintf((char*)new_path, "%lu", (unsigned long)index); - compose_patch(patches, (const unsigned char*)"remove", path, new_path, NULL); - } - /* add new elements in 'to' that were not in 'from' */ - for (; (to_child != NULL); (void)(to_child = to_child->next), index++) - { - compose_patch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to_child); - } - cJSON_free(new_path); - return; - } - - case cJSON_Object: - { - cJSON *from_child = NULL; - cJSON *to_child = NULL; - sort_object(from, case_sensitive); - sort_object(to, case_sensitive); - - from_child = from->child; - to_child = to->child; - /* for all object values in the object with more of them */ - while ((from_child != NULL) || (to_child != NULL)) - { - int diff; - if (from_child == NULL) - { - diff = 1; - } - else if (to_child == NULL) - { - diff = -1; - } - else - { - diff = compare_strings((unsigned char*)from_child->string, (unsigned char*)to_child->string, case_sensitive); - } - - if (diff == 0) - { - /* both object keys are the same */ - size_t path_length = strlen((const char*)path); - size_t from_child_name_length = pointer_encoded_length((unsigned char*)from_child->string); - unsigned char *new_path = (unsigned char*)cJSON_malloc(path_length + from_child_name_length + sizeof("/")); - - sprintf((char*)new_path, "%s/", path); - encode_string_as_pointer(new_path + path_length + 1, (unsigned char*)from_child->string); - - /* create a patch for the element */ - create_patches(patches, new_path, from_child, to_child, case_sensitive); - cJSON_free(new_path); - - from_child = from_child->next; - to_child = to_child->next; - } - else if (diff < 0) - { - /* object element doesn't exist in 'to' --> remove it */ - compose_patch(patches, (const unsigned char*)"remove", path, (unsigned char*)from_child->string, NULL); - - from_child = from_child->next; - } - else - { - /* object element doesn't exist in 'from' --> add it */ - compose_patch(patches, (const unsigned char*)"add", path, (unsigned char*)to_child->string, to_child); - - to_child = to_child->next; - } - } - return; - } - - default: - break; - } -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to) -{ - cJSON *patches = NULL; - - if ((from == NULL) || (to == NULL)) - { - return NULL; - } - - patches = cJSON_CreateArray(); - create_patches(patches, (const unsigned char*)"", from, to, false); - - return patches; -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to) -{ - cJSON *patches = NULL; - - if ((from == NULL) || (to == NULL)) - { - return NULL; - } - - patches = cJSON_CreateArray(); - create_patches(patches, (const unsigned char*)"", from, to, true); - - return patches; -} - -CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object) -{ - sort_object(object, false); -} - -CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object) -{ - sort_object(object, true); -} - -static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_bool case_sensitive) -{ - cJSON *patch_child = NULL; - - if (!cJSON_IsObject(patch)) - { - /* scalar value, array or NULL, just duplicate */ - cJSON_Delete(target); - return cJSON_Duplicate(patch, 1); - } - - if (!cJSON_IsObject(target)) - { - cJSON_Delete(target); - target = cJSON_CreateObject(); - } - - patch_child = patch->child; - while (patch_child != NULL) - { - if (cJSON_IsNull(patch_child)) - { - /* NULL is the indicator to remove a value, see RFC7396 */ - if (case_sensitive) - { - cJSON_DeleteItemFromObjectCaseSensitive(target, patch_child->string); - } - else - { - cJSON_DeleteItemFromObject(target, patch_child->string); - } - } - else - { - cJSON *replace_me = NULL; - cJSON *replacement = NULL; - - if (case_sensitive) - { - replace_me = cJSON_DetachItemFromObjectCaseSensitive(target, patch_child->string); - } - else - { - replace_me = cJSON_DetachItemFromObject(target, patch_child->string); - } - - replacement = merge_patch(replace_me, patch_child, case_sensitive); - if (replacement == NULL) - { - return NULL; - } - - cJSON_AddItemToObject(target, patch_child->string, replacement); - } - patch_child = patch_child->next; - } - return target; -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch) -{ - return merge_patch(target, patch, false); -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch) -{ - return merge_patch(target, patch, true); -} - -static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) -{ - cJSON *from_child = NULL; - cJSON *to_child = NULL; - cJSON *patch = NULL; - if (to == NULL) - { - /* patch to delete everything */ - return cJSON_CreateNull(); - } - if (!cJSON_IsObject(to) || !cJSON_IsObject(from)) - { - return cJSON_Duplicate(to, 1); - } - - sort_object(from, case_sensitive); - sort_object(to, case_sensitive); - - from_child = from->child; - to_child = to->child; - patch = cJSON_CreateObject(); - while (from_child || to_child) - { - int diff; - if (from_child != NULL) - { - if (to_child != NULL) - { - diff = strcmp(from_child->string, to_child->string); - } - else - { - diff = -1; - } - } - else - { - diff = 1; - } - - if (diff < 0) - { - /* from has a value that to doesn't have -> remove */ - cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull()); - - from_child = from_child->next; - } - else if (diff > 0) - { - /* to has a value that from doesn't have -> add to patch */ - cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1)); - - to_child = to_child->next; - } - else - { - /* object key exists in both objects */ - if (!compare_json(from_child, to_child, case_sensitive)) - { - /* not identical --> generate a patch */ - cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child)); - } - - /* next key in the object */ - from_child = from_child->next; - to_child = to_child->next; - } - } - if (patch->child == NULL) - { - /* no patch generated */ - cJSON_Delete(patch); - return NULL; - } - - return patch; -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to) -{ - return generate_merge_patch(from, to, false); -} - -CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to) -{ - return generate_merge_patch(from, to, true); -} diff --git a/components/cjson/cJSON/cJSON_Utils.h b/components/cjson/cJSON/cJSON_Utils.h deleted file mode 100644 index a970c6504..000000000 --- a/components/cjson/cJSON/cJSON_Utils.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON_Utils__h -#define cJSON_Utils__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "cJSON.h" - -/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ -CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer); -CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer); - -/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ -/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ -CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to); -CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to); -/* Utility for generating patch array entries. */ -CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value); -/* Returns 0 for success. */ -CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches); -CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches); - -/* -// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: -//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches) -//{ -// cJSON *modme = cJSON_Duplicate(*object, 1); -// int error = cJSONUtils_ApplyPatches(modme, patches); -// if (!error) -// { -// cJSON_Delete(*object); -// *object = modme; -// } -// else -// { -// cJSON_Delete(modme); -// } -// -// return error; -//} -// Code not added to library since this strategy is a LOT slower. -*/ - -/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ -/* target will be modified by patch. return value is new ptr for target. */ -CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch); -CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch); -/* generates a patch to move from -> to */ -/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ -CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to); -CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to); - -/* Given a root object and a target object, construct a pointer from one to the other. */ -CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target); - -/* Sorts the members of the object into alphabetical order. */ -CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object); -CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/cjson/cJSON/fuzzing/.gitignore b/components/cjson/cJSON/fuzzing/.gitignore deleted file mode 100644 index c82a26201..000000000 --- a/components/cjson/cJSON/fuzzing/.gitignore +++ /dev/null @@ -1 +0,0 @@ -afl-build diff --git a/components/cjson/cJSON/fuzzing/CMakeLists.txt b/components/cjson/cJSON/fuzzing/CMakeLists.txt deleted file mode 100644 index fdd7126e9..000000000 --- a/components/cjson/cJSON/fuzzing/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -option(ENABLE_FUZZING "Create executables and targets for fuzzing cJSON with afl." Off) -if (ENABLE_FUZZING) - find_program(AFL_FUZZ afl-fuzz) - if ("${AFL_FUZZ}" MATCHES "AFL_FUZZ-NOTFOUND") - message(FATAL_ERROR "Couldn't find afl-fuzz.") - endif() - - add_executable(afl-main afl.c) - target_link_libraries(afl-main "${CJSON_LIB}") - - if (NOT ENABLE_SANITIZERS) - message(FATAL_ERROR "Enable sanitizers with -DENABLE_SANITIZERS=On to do fuzzing.") - endif() - - option(ENABLE_FUZZING_PRINT "Fuzz printing functions together with parser." On) - set(fuzz_print_parameter "no") - if (ENABLE_FUZZING_PRINT) - set(fuzz_print_parameter "yes") - endif() - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") - - add_custom_target(afl - COMMAND "${AFL_FUZZ}" -i "${CMAKE_CURRENT_SOURCE_DIR}/inputs" -o "${CMAKE_CURRENT_BINARY_DIR}/findings" -x "${CMAKE_CURRENT_SOURCE_DIR}/json.dict" -- "${CMAKE_CURRENT_BINARY_DIR}/afl-main" "@@" "${fuzz_print_parameter}" - DEPENDS afl-main) - - -endif() diff --git a/components/cjson/cJSON/fuzzing/afl-prepare-linux.sh b/components/cjson/cJSON/fuzzing/afl-prepare-linux.sh deleted file mode 100755 index 41c9b8996..000000000 --- a/components/cjson/cJSON/fuzzing/afl-prepare-linux.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -x -echo core | sudo tee /proc/sys/kernel/core_pattern -echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor diff --git a/components/cjson/cJSON/fuzzing/afl.c b/components/cjson/cJSON/fuzzing/afl.c deleted file mode 100644 index 036ed14bc..000000000 --- a/components/cjson/cJSON/fuzzing/afl.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "../cJSON.h" - -static char *read_file(const char *filename) -{ - FILE *file = NULL; - long length = 0; - char *content = NULL; - size_t read_chars = 0; - - /* open in read binary mode */ - file = fopen(filename, "rb"); - if (file == NULL) - { - goto cleanup; - } - - /* get the length */ - if (fseek(file, 0, SEEK_END) != 0) - { - goto cleanup; - } - length = ftell(file); - if (length < 0) - { - goto cleanup; - } - if (fseek(file, 0, SEEK_SET) != 0) - { - goto cleanup; - } - - /* allocate content buffer */ - content = (char*)malloc((size_t)length + sizeof("")); - if (content == NULL) - { - goto cleanup; - } - - /* read the file into memory */ - read_chars = fread(content, sizeof(char), (size_t)length, file); - if ((long)read_chars != length) - { - free(content); - content = NULL; - goto cleanup; - } - content[read_chars] = '\0'; - - -cleanup: - if (file != NULL) - { - fclose(file); - } - - return content; -} - -int main(int argc, char** argv) -{ - const char *filename = NULL; - cJSON *item = NULL; - char *json = NULL; - int status = EXIT_FAILURE; - char *printed_json = NULL; - - if ((argc < 2) || (argc > 3)) - { - printf("Usage:\n"); - printf("%s input_file [enable_printing]\n", argv[0]); - printf("\t input_file: file containing the test data\n"); - printf("\t enable_printing: print after parsing, 'yes' or 'no', defaults to 'no'\n"); - goto cleanup; - } - - filename = argv[1]; - -#if __AFL_HAVE_MANUAL_CONTROL - while (__AFL_LOOP(1000)) - { -#endif - status = EXIT_SUCCESS; - - json = read_file(filename); - if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0')) - { - status = EXIT_FAILURE; - goto cleanup; - } - item = cJSON_Parse(json + 2); - if (item == NULL) - { - goto cleanup; - } - - if ((argc == 3) && (strncmp(argv[2], "yes", 3) == 0)) - { - int do_format = 0; - if (json[1] == 'f') - { - do_format = 1; - } - - if (json[0] == 'b') - { - /* buffered printing */ - printed_json = cJSON_PrintBuffered(item, 1, do_format); - } - else - { - /* unbuffered printing */ - if (do_format) - { - printed_json = cJSON_Print(item); - } - else - { - printed_json = cJSON_PrintUnformatted(item); - } - } - if (printed_json == NULL) - { - status = EXIT_FAILURE; - goto cleanup; - } - printf("%s\n", printed_json); - } - -cleanup: - if (item != NULL) - { - cJSON_Delete(item); - item = NULL; - } - if (json != NULL) - { - free(json); - json = NULL; - } - if (printed_json != NULL) - { - free(printed_json); - printed_json = NULL; - } -#if __AFL_HAVE_MANUAL_CONTROL - } -#endif - - return status; -} diff --git a/components/cjson/cJSON/fuzzing/afl.sh b/components/cjson/cJSON/fuzzing/afl.sh deleted file mode 100755 index 8f0f02fb0..000000000 --- a/components/cjson/cJSON/fuzzing/afl.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -mkdir -p afl-build || exit 1 -cd afl-build || exit 1 -#cleanup -rm -r -- * - -CC=afl-clang-fast cmake ../.. -DENABLE_FUZZING=On -DENABLE_SANITIZERS=On -DBUILD_SHARED_LIBS=Off -make afl diff --git a/components/cjson/cJSON/fuzzing/inputs/test1 b/components/cjson/cJSON/fuzzing/inputs/test1 deleted file mode 100644 index 6a0c0d7c5..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test1 +++ /dev/null @@ -1,22 +0,0 @@ -bf{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} diff --git a/components/cjson/cJSON/fuzzing/inputs/test10 b/components/cjson/cJSON/fuzzing/inputs/test10 deleted file mode 100644 index 01e9a82f6..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test10 +++ /dev/null @@ -1 +0,0 @@ -bf["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] diff --git a/components/cjson/cJSON/fuzzing/inputs/test11 b/components/cjson/cJSON/fuzzing/inputs/test11 deleted file mode 100644 index e81d60d78..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test11 +++ /dev/null @@ -1,8 +0,0 @@ -bf{ -"name": "Jack (\"Bee\") Nimble", -"format": {"type": "rect", -"width": 1920, -"height": 1080, -"interlace": false,"frame rate": 24 -} -} diff --git a/components/cjson/cJSON/fuzzing/inputs/test2 b/components/cjson/cJSON/fuzzing/inputs/test2 deleted file mode 100644 index 3fdf8cb78..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test2 +++ /dev/null @@ -1,11 +0,0 @@ -bf{"menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test3 b/components/cjson/cJSON/fuzzing/inputs/test3 deleted file mode 100644 index 11edd2f27..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test3 +++ /dev/null @@ -1,26 +0,0 @@ -bf{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test3.bu b/components/cjson/cJSON/fuzzing/inputs/test3.bu deleted file mode 100644 index eaac4e31d..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test3.bu +++ /dev/null @@ -1,26 +0,0 @@ -bu{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test3.uf b/components/cjson/cJSON/fuzzing/inputs/test3.uf deleted file mode 100644 index edad97784..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test3.uf +++ /dev/null @@ -1,26 +0,0 @@ -uf{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test3.uu b/components/cjson/cJSON/fuzzing/inputs/test3.uu deleted file mode 100644 index 1356b6d99..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test3.uu +++ /dev/null @@ -1,26 +0,0 @@ -uu{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test4 b/components/cjson/cJSON/fuzzing/inputs/test4 deleted file mode 100644 index 943943d24..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test4 +++ /dev/null @@ -1,88 +0,0 @@ -bf{"web-app": { - "servlet": [ - { - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500}}, - { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2"}}, - { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet"}, - - { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet"}, - { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true}}], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*"}, - - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test5 b/components/cjson/cJSON/fuzzing/inputs/test5 deleted file mode 100644 index f6cc84e13..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test5 +++ /dev/null @@ -1,27 +0,0 @@ -bf{"menu": { - "header": "SVG Viewer", - "items": [ - {"id": "Open"}, - {"id": "OpenNew", "label": "Open New"}, - null, - {"id": "ZoomIn", "label": "Zoom In"}, - {"id": "ZoomOut", "label": "Zoom Out"}, - {"id": "OriginalView", "label": "Original View"}, - null, - {"id": "Quality"}, - {"id": "Pause"}, - {"id": "Mute"}, - null, - {"id": "Find", "label": "Find..."}, - {"id": "FindAgain", "label": "Find Again"}, - {"id": "Copy"}, - {"id": "CopyAgain", "label": "Copy Again"}, - {"id": "CopySVG", "label": "Copy SVG"}, - {"id": "ViewSVG", "label": "View SVG"}, - {"id": "ViewSource", "label": "View Source"}, - {"id": "SaveAs", "label": "Save As"}, - null, - {"id": "Help"}, - {"id": "About", "label": "About Adobe CVG Viewer..."} - ] -}} diff --git a/components/cjson/cJSON/fuzzing/inputs/test6 b/components/cjson/cJSON/fuzzing/inputs/test6 deleted file mode 100644 index af279752e..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test6 +++ /dev/null @@ -1,16 +0,0 @@ -bf - - - - - Application Error - - - - - diff --git a/components/cjson/cJSON/fuzzing/inputs/test7 b/components/cjson/cJSON/fuzzing/inputs/test7 deleted file mode 100644 index 4a3c0b7a1..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test7 +++ /dev/null @@ -1,22 +0,0 @@ -bf[ - { - "precision": "zip", - "Latitude": 37.7668, - "Longitude": -122.3959, - "Address": "", - "City": "SAN FRANCISCO", - "State": "CA", - "Zip": "94107", - "Country": "US" - }, - { - "precision": "zip", - "Latitude": 37.371991, - "Longitude": -122.026020, - "Address": "", - "City": "SUNNYVALE", - "State": "CA", - "Zip": "94085", - "Country": "US" - } - ] diff --git a/components/cjson/cJSON/fuzzing/inputs/test8 b/components/cjson/cJSON/fuzzing/inputs/test8 deleted file mode 100644 index 3ffe570ce..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test8 +++ /dev/null @@ -1,13 +0,0 @@ -bf{ - "Image": { - "Width": 800, - "Height": 600, - "Title": "View from 15th Floor", - "Thumbnail": { - "Url": "http:/*www.example.com/image/481989943", - "Height": 125, - "Width": "100" - }, - "IDs": [116, 943, 234, 38793] - } - } diff --git a/components/cjson/cJSON/fuzzing/inputs/test9 b/components/cjson/cJSON/fuzzing/inputs/test9 deleted file mode 100644 index 28c9033ad..000000000 --- a/components/cjson/cJSON/fuzzing/inputs/test9 +++ /dev/null @@ -1,5 +0,0 @@ -bf[ - [0, -1, 0], - [1, 0, 0], - [0, 0, 1] - ] diff --git a/components/cjson/cJSON/fuzzing/json.dict b/components/cjson/cJSON/fuzzing/json.dict deleted file mode 100644 index 9bb03d7fd..000000000 --- a/components/cjson/cJSON/fuzzing/json.dict +++ /dev/null @@ -1,47 +0,0 @@ -# -# AFL dictionary for JSON -# ----------------------------- -# - -object_start="{" -object_end="}" -object_empty="{}" -object_one_element="{\"one\":1}" -object_two_elements="{\"1\":1,\"2\":2}" -object_separator=":" - -array_start="[" -array_end="]" -array_empty="[]" -array_one_element="[1]" -array_two_elements="[1,2]" - -separator="," - -escape_sequence_b="\\b" -escape_sequence_f="\\f" -escape_sequence_n="\\n" -escape_sequence_r="\\r" -escape_sequence_t="\\t" -escape_sequence_quote="\\\"" -escape_sequence_backslash="\\\\" -escape_sequence_slash="\\/" -escape_sequence_utf16_base="\\u" -escape_sequence_utf16="\\u12ab" - -number_integer="1" -number_double="1.0" -number_negative_integer="-1" -number_negative_double="-1.0" -number_engineering1="1e1" -number_engineering2="1e-1" -number_positive_integer="+1" -number_positive_double="+1.0" -number_e="e" -number_plus="+" -number_minus="-" -number_separator="." - -null="null" -true="true" -false="false" diff --git a/components/cjson/cJSON/library_config/cJSONConfig.cmake.in b/components/cjson/cJSON/library_config/cJSONConfig.cmake.in deleted file mode 100644 index 909f7a9ae..000000000 --- a/components/cjson/cJSON/library_config/cJSONConfig.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# Whether the utils lib was build. -set(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@) - -# The include directories used by cJSON -set(CJSON_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@") -set(CJSON_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@") - -get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# The cJSON library -set(CJSON_LIBRARY "@CJSON_LIB@") -if(@ENABLE_TARGET_EXPORT@) - # Include the target - include("${_dir}/cjson.cmake") -endif() - -if(CJSON_UTILS_FOUND) - # The cJSON utils library - set(CJSON_UTILS_LIBRARY @CJSON_UTILS_LIB@) - # All cJSON libraries - set(CJSON_LIBRARIES "@CJSON_UTILS_LIB@" "@CJSON_LIB@") - if(@ENABLE_TARGET_EXPORT@) - # Include the target - include("${_dir}/cjson_utils.cmake") - endif() -else() - # All cJSON libraries - set(CJSON_LIBRARIES "@CJSON_LIB@") -endif() diff --git a/components/cjson/cJSON/library_config/cJSONConfigVersion.cmake.in b/components/cjson/cJSON/library_config/cJSONConfigVersion.cmake.in deleted file mode 100644 index 22ffec0f6..000000000 --- a/components/cjson/cJSON/library_config/cJSONConfigVersion.cmake.in +++ /dev/null @@ -1,11 +0,0 @@ -set(PACKAGE_VERSION "@PROJECT_VERSION@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() diff --git a/components/cjson/cJSON/library_config/libcjson.pc.in b/components/cjson/cJSON/library_config/libcjson.pc.in deleted file mode 100644 index 7e616bbd7..000000000 --- a/components/cjson/cJSON/library_config/libcjson.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ - -Name: libcjson -Version: @PROJECT_VERSION@ -Description: Ultralightweight JSON parser in ANSI C -URL: https://github.com/DaveGamble/cJSON -Libs: -L${libdir} -lcjson -Libs.Private: -lm -Cflags: -I${includedir} diff --git a/components/cjson/cJSON/library_config/libcjson_utils.pc.in b/components/cjson/cJSON/library_config/libcjson_utils.pc.in deleted file mode 100644 index 830259fa2..000000000 --- a/components/cjson/cJSON/library_config/libcjson_utils.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ - -Name: libcjson_utils -Version: @PROJECT_VERSION@ -Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON. -URL: https://github.com/DaveGamble/cJSON -Libs: -L${libdir} -lcjson_utils -Cflags: -I${includedir} -Requires: libcjson diff --git a/components/cjson/cJSON/test.c b/components/cjson/cJSON/test.c deleted file mode 100644 index 66154e04b..000000000 --- a/components/cjson/cJSON/test.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include -#include "cJSON.h" - -/* Used by some code below as an example datatype. */ -struct record -{ - const char *precision; - double lat; - double lon; - const char *address; - const char *city; - const char *state; - const char *zip; - const char *country; -}; - - -/* Create a bunch of objects as demonstration. */ -static int print_preallocated(cJSON *root) -{ - /* declarations */ - char *out = NULL; - char *buf = NULL; - char *buf_fail = NULL; - size_t len = 0; - size_t len_fail = 0; - - /* formatted print */ - out = cJSON_Print(root); - - /* create buffer to succeed */ - /* the extra 5 bytes are because of inaccuracies when reserving memory */ - len = strlen(out) + 5; - buf = (char*)malloc(len); - if (buf == NULL) - { - printf("Failed to allocate memory.\n"); - exit(1); - } - - /* create buffer to fail */ - len_fail = strlen(out); - buf_fail = (char*)malloc(len_fail); - if (buf_fail == NULL) - { - printf("Failed to allocate memory.\n"); - exit(1); - } - - /* Print to buffer */ - if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) { - printf("cJSON_PrintPreallocated failed!\n"); - if (strcmp(out, buf) != 0) { - printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n"); - printf("cJSON_Print result:\n%s\n", out); - printf("cJSON_PrintPreallocated result:\n%s\n", buf); - } - free(out); - free(buf_fail); - free(buf); - return -1; - } - - /* success */ - printf("%s\n", buf); - - /* force it to fail */ - if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) { - printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n"); - printf("cJSON_Print result:\n%s\n", out); - printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail); - free(out); - free(buf_fail); - free(buf); - return -1; - } - - free(out); - free(buf_fail); - free(buf); - return 0; -} - -/* Create a bunch of objects as demonstration. */ -static void create_objects(void) -{ - /* declare a few. */ - cJSON *root = NULL; - cJSON *fmt = NULL; - cJSON *img = NULL; - cJSON *thm = NULL; - cJSON *fld = NULL; - int i = 0; - - /* Our "days of the week" array: */ - const char *strings[7] = - { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - }; - /* Our matrix: */ - int numbers[3][3] = - { - {0, -1, 0}, - {1, 0, 0}, - {0 ,0, 1} - }; - /* Our "gallery" item: */ - int ids[4] = { 116, 943, 234, 38793 }; - /* Our array of "records": */ - struct record fields[2] = - { - { - "zip", - 37.7668, - -1.223959e+2, - "", - "SAN FRANCISCO", - "CA", - "94107", - "US" - }, - { - "zip", - 37.371991, - -1.22026e+2, - "", - "SUNNYVALE", - "CA", - "94085", - "US" - } - }; - volatile double zero = 0.0; - - /* Here we construct some JSON standards, from the JSON site. */ - - /* Our "Video" datatype: */ - root = cJSON_CreateObject(); - cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); - cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); - cJSON_AddStringToObject(fmt, "type", "rect"); - cJSON_AddNumberToObject(fmt, "width", 1920); - cJSON_AddNumberToObject(fmt, "height", 1080); - cJSON_AddFalseToObject (fmt, "interlace"); - cJSON_AddNumberToObject(fmt, "frame rate", 24); - - /* Print to text */ - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our "days of the week" array: */ - root = cJSON_CreateStringArray(strings, 7); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our matrix: */ - root = cJSON_CreateArray(); - for (i = 0; i < 3; i++) - { - cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); - } - - /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our "gallery" item: */ - root = cJSON_CreateObject(); - cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); - cJSON_AddNumberToObject(img, "Width", 800); - cJSON_AddNumberToObject(img, "Height", 600); - cJSON_AddStringToObject(img, "Title", "View from 15th Floor"); - cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject()); - cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); - cJSON_AddNumberToObject(thm, "Height", 125); - cJSON_AddStringToObject(thm, "Width", "100"); - cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4)); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our array of "records": */ - root = cJSON_CreateArray(); - for (i = 0; i < 2; i++) - { - cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); - cJSON_AddStringToObject(fld, "precision", fields[i].precision); - cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); - cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); - cJSON_AddStringToObject(fld, "Address", fields[i].address); - cJSON_AddStringToObject(fld, "City", fields[i].city); - cJSON_AddStringToObject(fld, "State", fields[i].state); - cJSON_AddStringToObject(fld, "Zip", fields[i].zip); - cJSON_AddStringToObject(fld, "Country", fields[i].country); - } - - /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - root = cJSON_CreateObject(); - cJSON_AddNumberToObject(root, "number", 1.0 / zero); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); -} - -int main(void) -{ - /* print the version */ - printf("Version: %s\n", cJSON_Version()); - - /* Now some samplecode for building objects concisely: */ - create_objects(); - - return 0; -} diff --git a/components/cjson/cJSON/tests/CMakeLists.txt b/components/cjson/cJSON/tests/CMakeLists.txt deleted file mode 100644 index 79672927e..000000000 --- a/components/cjson/cJSON/tests/CMakeLists.txt +++ /dev/null @@ -1,112 +0,0 @@ -if(ENABLE_CJSON_TEST) - add_library(unity "${CJSON_LIBRARY_TYPE}" unity/src/unity.c) - - # Disable -Werror for Unity - if (FLAG_SUPPORTED_Werror) - if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") - else() - target_compile_options(unity PRIVATE "-Wno-error") - endif() - endif() - # Disable -fvisibility=hidden for Unity - if (FLAG_SUPPORTED_fvisibilityhidden) - if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default") - else() - target_compile_options(unity PRIVATE "-fvisibility=default") - endif() - endif() - # Disable -fsanitize=float-divide-by-zero for Unity (GCC bug on x86 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097) - if (FLAG_SUPPORTED_fsanitizefloatdividebyzero AND (CMAKE_C_COMPILER_ID STREQUAL "GNU")) - if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero") - else() - target_compile_options(unity PRIVATE "-fno-sanitize=float-divide-by-zero") - endif() - endif() - # Disable -Wswitch-enum for Unity - if (FLAG_SUPPORTED_Wswitchenum) - if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-switch-enum") - else() - target_compile_options(unity PRIVATE "-Wno-switch-enum") - endif() - endif() - - #copy test files - file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs") - file(GLOB test_files "inputs/*") - file(COPY ${test_files} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/inputs/") - - set(unity_tests - parse_examples - parse_number - parse_hex4 - parse_string - parse_array - parse_object - parse_value - print_string - print_number - print_array - print_object - print_value - misc_tests - parse_with_opts - compare_tests - cjson_add - readme_examples - ) - - option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.") - if (ENABLE_VALGRIND) - find_program(MEMORYCHECK_COMMAND valgrind) - if ("${MEMORYCHECK_COMMAND}" MATCHES "MEMORYCHECK_COMMAND-NOTFOUND") - message(WARNING "Valgrind couldn't be found.") - unset(MEMORYCHECK_COMMAND) - else() - set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1 --suppressions=${CMAKE_CURRENT_SOURCE_DIR}/../valgrind.supp) - endif() - endif() - - foreach(unity_test ${unity_tests}) - add_executable("${unity_test}" "${unity_test}.c") - target_link_libraries("${unity_test}" "${CJSON_LIB}" unity) - if(MEMORYCHECK_COMMAND) - add_test(NAME "${unity_test}" - COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${unity_test}") - else() - add_test(NAME "${unity_test}" - COMMAND "./${unity_test}") - endif() - endforeach() - - add_dependencies(check ${unity_tests}) - - if (ENABLE_CJSON_UTILS) - #copy test files - file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/json-patch-tests") - file(GLOB test_files "json-patch-tests/*") - file(COPY ${test_files} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/json-patch-tests/") - - set (cjson_utils_tests - json_patch_tests - old_utils_tests - misc_utils_tests) - - foreach (cjson_utils_test ${cjson_utils_tests}) - add_executable("${cjson_utils_test}" "${cjson_utils_test}.c") - target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity) - if(MEMORYCHECK_COMMAND) - add_test(NAME "${cjson_utils_test}" - COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${cjson_utils_test}") - else() - add_test(NAME "${cjson_utils_test}" - COMMAND "./${cjson_utils_test}") - endif() - endforeach() - - add_dependencies(check ${cjson_utils_tests}) - endif() -endif() diff --git a/components/cjson/cJSON/tests/cjson_add.c b/components/cjson/cJSON/tests/cjson_add.c deleted file mode 100644 index 01668a94c..000000000 --- a/components/cjson/cJSON/tests/cjson_add.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void *failing_malloc(size_t size) -{ - (void)size; - return NULL; -} - -static cJSON_Hooks failing_hooks = { - failing_malloc, - free -}; - -static void cjson_add_null_should_add_null(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *null = NULL; - - cJSON_AddNullToObject(root, "null"); - - TEST_ASSERT_NOT_NULL(null = cJSON_GetObjectItemCaseSensitive(root, "null")); - TEST_ASSERT_EQUAL_INT(null->type, cJSON_NULL); - - cJSON_Delete(root); -} - -static void cjson_add_null_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddNullToObject(NULL, "null")); - TEST_ASSERT_NULL(cJSON_AddNullToObject(root, NULL)); - - cJSON_Delete(root); -} - -static void cjson_add_null_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddNullToObject(root, "null")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_true_should_add_true(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *true_item = NULL; - - cJSON_AddTrueToObject(root, "true"); - - TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true")); - TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True); - - cJSON_Delete(root); -} - -static void cjson_add_true_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddTrueToObject(NULL, "true")); - TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, NULL)); - - cJSON_Delete(root); -} - -static void cjson_add_true_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, "true")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_false_should_add_false(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *false_item = NULL; - - cJSON_AddFalseToObject(root, "false"); - - TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false")); - TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False); - - cJSON_Delete(root); -} - -static void cjson_add_false_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddFalseToObject(NULL, "false")); - TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, NULL)); - - cJSON_Delete(root); -} - -static void cjson_add_false_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, "false")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_bool_should_add_bool(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *true_item = NULL; - cJSON *false_item = NULL; - - /* true */ - cJSON_AddBoolToObject(root, "true", true); - TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true")); - TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True); - - /* false */ - cJSON_AddBoolToObject(root, "false", false); - TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false")); - TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False); - - cJSON_Delete(root); -} - -static void cjson_add_bool_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddBoolToObject(NULL, "false", false)); - TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, NULL, false)); - - cJSON_Delete(root); -} - -static void cjson_add_bool_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, "false", false)); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_number_should_add_number(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *number = NULL; - - cJSON_AddNumberToObject(root, "number", 42); - - TEST_ASSERT_NOT_NULL(number = cJSON_GetObjectItemCaseSensitive(root, "number")); - - TEST_ASSERT_EQUAL_INT(number->type, cJSON_Number); - TEST_ASSERT_EQUAL_DOUBLE(number->valuedouble, 42); - TEST_ASSERT_EQUAL_INT(number->valueint, 42); - - cJSON_Delete(root); -} - -static void cjson_add_number_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddNumberToObject(NULL, "number", 42)); - TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, NULL, 42)); - - cJSON_Delete(root); -} - -static void cjson_add_number_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, "number", 42)); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_string_should_add_string(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *string = NULL; - - cJSON_AddStringToObject(root, "string", "Hello World!"); - - TEST_ASSERT_NOT_NULL(string = cJSON_GetObjectItemCaseSensitive(root, "string")); - TEST_ASSERT_EQUAL_INT(string->type, cJSON_String); - TEST_ASSERT_EQUAL_STRING(string->valuestring, "Hello World!"); - - cJSON_Delete(root); -} - -static void cjson_add_string_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddStringToObject(NULL, "string", "string")); - TEST_ASSERT_NULL(cJSON_AddStringToObject(root, NULL, "string")); - - cJSON_Delete(root); -} - -static void cjson_add_string_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddStringToObject(root, "string", "string")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cjson_add_raw_should_add_raw(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *raw = NULL; - - cJSON_AddRawToObject(root, "raw", "{}"); - - TEST_ASSERT_NOT_NULL(raw = cJSON_GetObjectItemCaseSensitive(root, "raw")); - TEST_ASSERT_EQUAL_INT(raw->type, cJSON_Raw); - TEST_ASSERT_EQUAL_STRING(raw->valuestring, "{}"); - - cJSON_Delete(root); -} - -static void cjson_add_raw_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddRawToObject(NULL, "raw", "{}")); - TEST_ASSERT_NULL(cJSON_AddRawToObject(root, NULL, "{}")); - - cJSON_Delete(root); -} - -static void cjson_add_raw_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddRawToObject(root, "raw", "{}")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cJSON_add_object_should_add_object(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *object = NULL; - - cJSON_AddObjectToObject(root, "object"); - TEST_ASSERT_NOT_NULL(object = cJSON_GetObjectItemCaseSensitive(root, "object")); - TEST_ASSERT_EQUAL_INT(object->type, cJSON_Object); - - cJSON_Delete(root); -} - -static void cjson_add_object_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddObjectToObject(NULL, "object")); - TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, NULL)); - - cJSON_Delete(root); -} - -static void cjson_add_object_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, "object")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -static void cJSON_add_array_should_add_array(void) -{ - cJSON *root = cJSON_CreateObject(); - cJSON *array = NULL; - - cJSON_AddArrayToObject(root, "array"); - TEST_ASSERT_NOT_NULL(array = cJSON_GetObjectItemCaseSensitive(root, "array")); - TEST_ASSERT_EQUAL_INT(array->type, cJSON_Array); - - cJSON_Delete(root); -} - -static void cjson_add_array_should_fail_with_null_pointers(void) -{ - cJSON *root = cJSON_CreateObject(); - - TEST_ASSERT_NULL(cJSON_AddArrayToObject(NULL, "array")); - TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, NULL)); - - cJSON_Delete(root); -} - -static void cjson_add_array_should_fail_on_allocation_failure(void) -{ - cJSON *root = cJSON_CreateObject(); - - cJSON_InitHooks(&failing_hooks); - - TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, "array")); - - cJSON_InitHooks(NULL); - - cJSON_Delete(root); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(cjson_add_null_should_add_null); - RUN_TEST(cjson_add_null_should_fail_with_null_pointers); - RUN_TEST(cjson_add_null_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_true_should_add_true); - RUN_TEST(cjson_add_true_should_fail_with_null_pointers); - RUN_TEST(cjson_add_true_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_false_should_add_false); - RUN_TEST(cjson_add_false_should_fail_with_null_pointers); - RUN_TEST(cjson_add_false_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_bool_should_add_bool); - RUN_TEST(cjson_add_bool_should_fail_with_null_pointers); - RUN_TEST(cjson_add_bool_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_number_should_add_number); - RUN_TEST(cjson_add_number_should_fail_with_null_pointers); - RUN_TEST(cjson_add_number_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_string_should_add_string); - RUN_TEST(cjson_add_string_should_fail_with_null_pointers); - RUN_TEST(cjson_add_string_should_fail_on_allocation_failure); - - RUN_TEST(cjson_add_raw_should_add_raw); - RUN_TEST(cjson_add_raw_should_fail_with_null_pointers); - RUN_TEST(cjson_add_raw_should_fail_on_allocation_failure); - - RUN_TEST(cJSON_add_object_should_add_object); - RUN_TEST(cjson_add_object_should_fail_with_null_pointers); - RUN_TEST(cjson_add_object_should_fail_on_allocation_failure); - - RUN_TEST(cJSON_add_array_should_add_array); - RUN_TEST(cjson_add_array_should_fail_with_null_pointers); - RUN_TEST(cjson_add_array_should_fail_on_allocation_failure); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/common.h b/components/cjson/cJSON/tests/common.h deleted file mode 100644 index 4db6bf8c2..000000000 --- a/components/cjson/cJSON/tests/common.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef CJSON_TESTS_COMMON_H -#define CJSON_TESTS_COMMON_H - -#include "../cJSON.c" - -void reset(cJSON *item); -void reset(cJSON *item) { - if ((item != NULL) && (item->child != NULL)) - { - cJSON_Delete(item->child); - } - if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference)) - { - global_hooks.deallocate(item->valuestring); - } - if ((item->string != NULL) && !(item->type & cJSON_StringIsConst)) - { - global_hooks.deallocate(item->string); - } - - memset(item, 0, sizeof(cJSON)); -} - -char* read_file(const char *filename); -char* read_file(const char *filename) { - FILE *file = NULL; - long length = 0; - char *content = NULL; - size_t read_chars = 0; - - /* open in read binary mode */ - file = fopen(filename, "rb"); - if (file == NULL) - { - goto cleanup; - } - - /* get the length */ - if (fseek(file, 0, SEEK_END) != 0) - { - goto cleanup; - } - length = ftell(file); - if (length < 0) - { - goto cleanup; - } - if (fseek(file, 0, SEEK_SET) != 0) - { - goto cleanup; - } - - /* allocate content buffer */ - content = (char*)malloc((size_t)length + sizeof("")); - if (content == NULL) - { - goto cleanup; - } - - /* read the file into memory */ - read_chars = fread(content, sizeof(char), (size_t)length, file); - if ((long)read_chars != length) - { - free(content); - content = NULL; - goto cleanup; - } - content[read_chars] = '\0'; - - -cleanup: - if (file != NULL) - { - fclose(file); - } - - return content; -} - -/* assertion helper macros */ -#define assert_has_type(item, item_type) TEST_ASSERT_BITS_MESSAGE(0xFF, item_type, item->type, "Item doesn't have expected type.") -#define assert_has_no_reference(item) TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, item->type, "Item should not have a string as reference.") -#define assert_has_no_const_string(item) TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, item->type, "Item should not have a const string.") -#define assert_has_valuestring(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->valuestring, "Valuestring is NULL.") -#define assert_has_no_valuestring(item) TEST_ASSERT_NULL_MESSAGE(item->valuestring, "Valuestring is not NULL.") -#define assert_has_string(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->string, "String is NULL") -#define assert_has_no_string(item) TEST_ASSERT_NULL_MESSAGE(item->string, "String is not NULL.") -#define assert_not_in_list(item) \ - TEST_ASSERT_NULL_MESSAGE(item->next, "Linked list next pointer is not NULL.");\ - TEST_ASSERT_NULL_MESSAGE(item->prev, "Linked list previous pointer is not NULL.") -#define assert_has_child(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->child, "Item doesn't have a child.") -#define assert_has_no_child(item) TEST_ASSERT_NULL_MESSAGE(item->child, "Item has a child.") -#define assert_is_invalid(item) \ - assert_has_type(item, cJSON_Invalid);\ - assert_not_in_list(item);\ - assert_has_no_child(item);\ - assert_has_no_string(item);\ - assert_has_no_valuestring(item) - -#endif diff --git a/components/cjson/cJSON/tests/compare_tests.c b/components/cjson/cJSON/tests/compare_tests.c deleted file mode 100644 index 63b6d4a0b..000000000 --- a/components/cjson/cJSON/tests/compare_tests.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON_bool compare_from_string(const char * const a, const char * const b, const cJSON_bool case_sensitive) -{ - cJSON *a_json = NULL; - cJSON *b_json = NULL; - cJSON_bool result = false; - - a_json = cJSON_Parse(a); - TEST_ASSERT_NOT_NULL_MESSAGE(a_json, "Failed to parse a."); - b_json = cJSON_Parse(b); - TEST_ASSERT_NOT_NULL_MESSAGE(b_json, "Failed to parse b."); - - result = cJSON_Compare(a_json, b_json, case_sensitive); - - cJSON_Delete(a_json); - cJSON_Delete(b_json); - - return result; -} - -static void cjson_compare_should_compare_null_pointer_as_not_equal(void) -{ - TEST_ASSERT_FALSE(cJSON_Compare(NULL, NULL, true)); - TEST_ASSERT_FALSE(cJSON_Compare(NULL, NULL, false)); -} - -static void cjson_compare_should_compare_invalid_as_not_equal(void) -{ - cJSON invalid[1]; - memset(invalid, '\0', sizeof(invalid)); - - TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false)); - TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, true)); -} - -static void cjson_compare_should_compare_numbers(void) -{ - TEST_ASSERT_TRUE(compare_from_string("1", "1", true)); - TEST_ASSERT_TRUE(compare_from_string("1", "1", false)); - TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true)); - TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false)); - - TEST_ASSERT_FALSE(compare_from_string("1", "2", true)); - TEST_ASSERT_FALSE(compare_from_string("1", "2", false)); -} - -static void cjson_compare_should_compare_booleans(void) -{ - /* true */ - TEST_ASSERT_TRUE(compare_from_string("true", "true", true)); - TEST_ASSERT_TRUE(compare_from_string("true", "true", false)); - - /* false */ - TEST_ASSERT_TRUE(compare_from_string("false", "false", true)); - TEST_ASSERT_TRUE(compare_from_string("false", "false", false)); - - /* mixed */ - TEST_ASSERT_FALSE(compare_from_string("true", "false", true)); - TEST_ASSERT_FALSE(compare_from_string("true", "false", false)); - TEST_ASSERT_FALSE(compare_from_string("false", "true", true)); - TEST_ASSERT_FALSE(compare_from_string("false", "true", false)); -} - -static void cjson_compare_should_compare_null(void) -{ - TEST_ASSERT_TRUE(compare_from_string("null", "null", true)); - TEST_ASSERT_TRUE(compare_from_string("null", "null", false)); - - TEST_ASSERT_FALSE(compare_from_string("null", "true", true)); - TEST_ASSERT_FALSE(compare_from_string("null", "true", false)); -} - -static void cjson_compare_should_not_accept_invalid_types(void) -{ - cJSON invalid[1]; - memset(invalid, '\0', sizeof(invalid)); - - invalid->type = cJSON_Number | cJSON_String; - - TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, true)); - TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false)); -} - -static void cjson_compare_should_compare_strings(void) -{ - TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", true)); - TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", false)); - - TEST_ASSERT_FALSE(compare_from_string("\"ABCDEFG\"", "\"abcdefg\"", true)); - TEST_ASSERT_FALSE(compare_from_string("\"ABCDEFG\"", "\"abcdefg\"", false)); -} - -static void cjson_compare_should_compare_raw(void) -{ - cJSON *raw1 = NULL; - cJSON *raw2 = NULL; - - raw1 = cJSON_Parse("\"[true, false]\""); - TEST_ASSERT_NOT_NULL(raw1); - raw2 = cJSON_Parse("\"[true, false]\""); - TEST_ASSERT_NOT_NULL(raw2); - - raw1->type = cJSON_Raw; - raw2->type = cJSON_Raw; - - TEST_ASSERT_TRUE(cJSON_Compare(raw1, raw2, true)); - TEST_ASSERT_TRUE(cJSON_Compare(raw1, raw2, false)); - - cJSON_Delete(raw1); - cJSON_Delete(raw2); -} - -static void cjson_compare_should_compare_arrays(void) -{ - TEST_ASSERT_TRUE(compare_from_string("[]", "[]", true)); - TEST_ASSERT_TRUE(compare_from_string("[]", "[]", false)); - - TEST_ASSERT_TRUE(compare_from_string("[false,true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", true)); - TEST_ASSERT_TRUE(compare_from_string("[false,true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", false)); - - TEST_ASSERT_TRUE(compare_from_string("[[[1], 2]]", "[[[1], 2]]", true)); - TEST_ASSERT_TRUE(compare_from_string("[[[1], 2]]", "[[[1], 2]]", false)); - - TEST_ASSERT_FALSE(compare_from_string("[true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", true)); - TEST_ASSERT_FALSE(compare_from_string("[true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", false)); - - /* Arrays that are a prefix of another array */ - TEST_ASSERT_FALSE(compare_from_string("[1,2,3]", "[1,2]", true)); - TEST_ASSERT_FALSE(compare_from_string("[1,2,3]", "[1,2]", false)); -} - -static void cjson_compare_should_compare_objects(void) -{ - TEST_ASSERT_TRUE(compare_from_string("{}", "{}", true)); - TEST_ASSERT_TRUE(compare_from_string("{}", "{}", false)); - - TEST_ASSERT_TRUE(compare_from_string( - "{\"false\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - "{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - true)); - TEST_ASSERT_FALSE(compare_from_string( - "{\"False\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - "{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - true)); - TEST_ASSERT_TRUE(compare_from_string( - "{\"False\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - "{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - false)); - TEST_ASSERT_FALSE(compare_from_string( - "{\"Flse\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - "{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}", - false)); - /* test objects that are a subset of each other */ - TEST_ASSERT_FALSE(compare_from_string( - "{\"one\": 1, \"two\": 2}", - "{\"one\": 1, \"two\": 2, \"three\": 3}", - true)) - TEST_ASSERT_FALSE(compare_from_string( - "{\"one\": 1, \"two\": 2}", - "{\"one\": 1, \"two\": 2, \"three\": 3}", - false)) -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(cjson_compare_should_compare_null_pointer_as_not_equal); - RUN_TEST(cjson_compare_should_compare_invalid_as_not_equal); - RUN_TEST(cjson_compare_should_compare_numbers); - RUN_TEST(cjson_compare_should_compare_booleans); - RUN_TEST(cjson_compare_should_compare_null); - RUN_TEST(cjson_compare_should_not_accept_invalid_types); - RUN_TEST(cjson_compare_should_compare_strings); - RUN_TEST(cjson_compare_should_compare_raw); - RUN_TEST(cjson_compare_should_compare_arrays); - RUN_TEST(cjson_compare_should_compare_objects); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/inputs/test1 b/components/cjson/cJSON/tests/inputs/test1 deleted file mode 100644 index eacfbf5e6..000000000 --- a/components/cjson/cJSON/tests/inputs/test1 +++ /dev/null @@ -1,22 +0,0 @@ -{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} diff --git a/components/cjson/cJSON/tests/inputs/test1.expected b/components/cjson/cJSON/tests/inputs/test1.expected deleted file mode 100644 index a5839e849..000000000 --- a/components/cjson/cJSON/tests/inputs/test1.expected +++ /dev/null @@ -1,22 +0,0 @@ -{ - "glossary": { - "title": "example glossary", - "GlossDiv": { - "title": "S", - "GlossList": { - "GlossEntry": { - "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { - "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] - }, - "GlossSee": "markup" - } - } - } - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test10 b/components/cjson/cJSON/tests/inputs/test10 deleted file mode 100644 index d19eb8b5d..000000000 --- a/components/cjson/cJSON/tests/inputs/test10 +++ /dev/null @@ -1 +0,0 @@ -["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] diff --git a/components/cjson/cJSON/tests/inputs/test10.expected b/components/cjson/cJSON/tests/inputs/test10.expected deleted file mode 100644 index 747ba62ce..000000000 --- a/components/cjson/cJSON/tests/inputs/test10.expected +++ /dev/null @@ -1 +0,0 @@ -["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test11 b/components/cjson/cJSON/tests/inputs/test11 deleted file mode 100644 index 039c61b90..000000000 --- a/components/cjson/cJSON/tests/inputs/test11 +++ /dev/null @@ -1,8 +0,0 @@ -{ -"name": "Jack (\"Bee\") Nimble", -"format": {"type": "rect", -"width": 1920, -"height": 1080, -"interlace": false,"frame rate": 24 -} -} diff --git a/components/cjson/cJSON/tests/inputs/test11.expected b/components/cjson/cJSON/tests/inputs/test11.expected deleted file mode 100644 index 24e72ece2..000000000 --- a/components/cjson/cJSON/tests/inputs/test11.expected +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Jack (\"Bee\") Nimble", - "format": { - "type": "rect", - "width": 1920, - "height": 1080, - "interlace": false, - "frame rate": 24 - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test2 b/components/cjson/cJSON/tests/inputs/test2 deleted file mode 100644 index 5600991a4..000000000 --- a/components/cjson/cJSON/tests/inputs/test2 +++ /dev/null @@ -1,11 +0,0 @@ -{"menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} diff --git a/components/cjson/cJSON/tests/inputs/test2.expected b/components/cjson/cJSON/tests/inputs/test2.expected deleted file mode 100644 index d42a0170b..000000000 --- a/components/cjson/cJSON/tests/inputs/test2.expected +++ /dev/null @@ -1,18 +0,0 @@ -{ - "menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [{ - "value": "New", - "onclick": "CreateNewDoc()" - }, { - "value": "Open", - "onclick": "OpenDoc()" - }, { - "value": "Close", - "onclick": "CloseDoc()" - }] - } - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test3 b/components/cjson/cJSON/tests/inputs/test3 deleted file mode 100644 index 7f74acaa8..000000000 --- a/components/cjson/cJSON/tests/inputs/test3 +++ /dev/null @@ -1,26 +0,0 @@ -{"widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } -}} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test3.expected b/components/cjson/cJSON/tests/inputs/test3.expected deleted file mode 100644 index a9b9c55a8..000000000 --- a/components/cjson/cJSON/tests/inputs/test3.expected +++ /dev/null @@ -1,28 +0,0 @@ -{ - "widget": { - "debug": "on", - "window": { - "title": "Sample Konfabulator Widget", - "name": "main_window", - "width": 500, - "height": 500 - }, - "image": { - "src": "Images/Sun.png", - "name": "sun1", - "hOffset": 250, - "vOffset": 250, - "alignment": "center" - }, - "text": { - "data": "Click Here", - "size": 36, - "style": "bold", - "name": "text1", - "hOffset": 250, - "vOffset": 100, - "alignment": "center", - "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" - } - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test4 b/components/cjson/cJSON/tests/inputs/test4 deleted file mode 100644 index 55cd56b17..000000000 --- a/components/cjson/cJSON/tests/inputs/test4 +++ /dev/null @@ -1,88 +0,0 @@ -{"web-app": { - "servlet": [ - { - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500}}, - { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2"}}, - { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet"}, - - { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet"}, - { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true}}], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*"}, - - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test4.expected b/components/cjson/cJSON/tests/inputs/test4.expected deleted file mode 100644 index 3648a95bb..000000000 --- a/components/cjson/cJSON/tests/inputs/test4.expected +++ /dev/null @@ -1,94 +0,0 @@ -{ - "web-app": { - "servlet": [{ - "servlet-name": "cofaxCDS", - "servlet-class": "org.cofax.cds.CDSServlet", - "init-param": { - "configGlossary:installationAt": "Philadelphia, PA", - "configGlossary:adminEmail": "ksm@pobox.com", - "configGlossary:poweredBy": "Cofax", - "configGlossary:poweredByIcon": "/images/cofax.gif", - "configGlossary:staticPath": "/content/static", - "templateProcessorClass": "org.cofax.WysiwygTemplate", - "templateLoaderClass": "org.cofax.FilesTemplateLoader", - "templatePath": "templates", - "templateOverridePath": "", - "defaultListTemplate": "listTemplate.htm", - "defaultFileTemplate": "articleTemplate.htm", - "useJSP": false, - "jspListTemplate": "listTemplate.jsp", - "jspFileTemplate": "articleTemplate.jsp", - "cachePackageTagsTrack": 200, - "cachePackageTagsStore": 200, - "cachePackageTagsRefresh": 60, - "cacheTemplatesTrack": 100, - "cacheTemplatesStore": 50, - "cacheTemplatesRefresh": 15, - "cachePagesTrack": 200, - "cachePagesStore": 100, - "cachePagesRefresh": 10, - "cachePagesDirtyRead": 10, - "searchEngineListTemplate": "forSearchEnginesList.htm", - "searchEngineFileTemplate": "forSearchEngines.htm", - "searchEngineRobotsDb": "WEB-INF/robots.db", - "useDataStore": true, - "dataStoreClass": "org.cofax.SqlDataStore", - "redirectionClass": "org.cofax.SqlRedirection", - "dataStoreName": "cofax", - "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", - "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", - "dataStoreUser": "sa", - "dataStorePassword": "dataStoreTestQuery", - "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", - "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", - "dataStoreInitConns": 10, - "dataStoreMaxConns": 100, - "dataStoreConnUsageLimit": 100, - "dataStoreLogLevel": "debug", - "maxUrlLength": 500 - } - }, { - "servlet-name": "cofaxEmail", - "servlet-class": "org.cofax.cds.EmailServlet", - "init-param": { - "mailHost": "mail1", - "mailHostOverride": "mail2" - } - }, { - "servlet-name": "cofaxAdmin", - "servlet-class": "org.cofax.cds.AdminServlet" - }, { - "servlet-name": "fileServlet", - "servlet-class": "org.cofax.cds.FileServlet" - }, { - "servlet-name": "cofaxTools", - "servlet-class": "org.cofax.cms.CofaxToolsServlet", - "init-param": { - "templatePath": "toolstemplates/", - "log": 1, - "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", - "logMaxSize": "", - "dataLog": 1, - "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", - "dataLogMaxSize": "", - "removePageCache": "/content/admin/remove?cache=pages&id=", - "removeTemplateCache": "/content/admin/remove?cache=templates&id=", - "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", - "lookInContext": 1, - "adminGroupID": 4, - "betaServer": true - } - }], - "servlet-mapping": { - "cofaxCDS": "/", - "cofaxEmail": "/cofaxutil/aemail/*", - "cofaxAdmin": "/admin/*", - "fileServlet": "/static/*", - "cofaxTools": "/tools/*" - }, - "taglib": { - "taglib-uri": "cofax.tld", - "taglib-location": "/WEB-INF/tlds/cofax.tld" - } - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test5 b/components/cjson/cJSON/tests/inputs/test5 deleted file mode 100644 index 49980ca25..000000000 --- a/components/cjson/cJSON/tests/inputs/test5 +++ /dev/null @@ -1,27 +0,0 @@ -{"menu": { - "header": "SVG Viewer", - "items": [ - {"id": "Open"}, - {"id": "OpenNew", "label": "Open New"}, - null, - {"id": "ZoomIn", "label": "Zoom In"}, - {"id": "ZoomOut", "label": "Zoom Out"}, - {"id": "OriginalView", "label": "Original View"}, - null, - {"id": "Quality"}, - {"id": "Pause"}, - {"id": "Mute"}, - null, - {"id": "Find", "label": "Find..."}, - {"id": "FindAgain", "label": "Find Again"}, - {"id": "Copy"}, - {"id": "CopyAgain", "label": "Copy Again"}, - {"id": "CopySVG", "label": "Copy SVG"}, - {"id": "ViewSVG", "label": "View SVG"}, - {"id": "ViewSource", "label": "View Source"}, - {"id": "SaveAs", "label": "Save As"}, - null, - {"id": "Help"}, - {"id": "About", "label": "About Adobe CVG Viewer..."} - ] -}} diff --git a/components/cjson/cJSON/tests/inputs/test5.expected b/components/cjson/cJSON/tests/inputs/test5.expected deleted file mode 100644 index 886ed58fd..000000000 --- a/components/cjson/cJSON/tests/inputs/test5.expected +++ /dev/null @@ -1,54 +0,0 @@ -{ - "menu": { - "header": "SVG Viewer", - "items": [{ - "id": "Open" - }, { - "id": "OpenNew", - "label": "Open New" - }, null, { - "id": "ZoomIn", - "label": "Zoom In" - }, { - "id": "ZoomOut", - "label": "Zoom Out" - }, { - "id": "OriginalView", - "label": "Original View" - }, null, { - "id": "Quality" - }, { - "id": "Pause" - }, { - "id": "Mute" - }, null, { - "id": "Find", - "label": "Find..." - }, { - "id": "FindAgain", - "label": "Find Again" - }, { - "id": "Copy" - }, { - "id": "CopyAgain", - "label": "Copy Again" - }, { - "id": "CopySVG", - "label": "Copy SVG" - }, { - "id": "ViewSVG", - "label": "View SVG" - }, { - "id": "ViewSource", - "label": "View Source" - }, { - "id": "SaveAs", - "label": "Save As" - }, null, { - "id": "Help" - }, { - "id": "About", - "label": "About Adobe CVG Viewer..." - }] - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test6 b/components/cjson/cJSON/tests/inputs/test6 deleted file mode 100644 index d5cb28f67..000000000 --- a/components/cjson/cJSON/tests/inputs/test6 +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Application Error - - - - - \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test7 b/components/cjson/cJSON/tests/inputs/test7 deleted file mode 100644 index 330853664..000000000 --- a/components/cjson/cJSON/tests/inputs/test7 +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "precision": "zip", - "Latitude": 37.7668, - "Longitude": -122.3959, - "Address": "", - "City": "SAN FRANCISCO", - "State": "CA", - "Zip": "94107", - "Country": "US" - }, - { - "precision": "zip", - "Latitude": 37.371991, - "Longitude": -122.026020, - "Address": "", - "City": "SUNNYVALE", - "State": "CA", - "Zip": "94085", - "Country": "US" - } - ] diff --git a/components/cjson/cJSON/tests/inputs/test7.expected b/components/cjson/cJSON/tests/inputs/test7.expected deleted file mode 100644 index 15adf7938..000000000 --- a/components/cjson/cJSON/tests/inputs/test7.expected +++ /dev/null @@ -1,19 +0,0 @@ -[{ - "precision": "zip", - "Latitude": 37.7668, - "Longitude": -122.3959, - "Address": "", - "City": "SAN FRANCISCO", - "State": "CA", - "Zip": "94107", - "Country": "US" - }, { - "precision": "zip", - "Latitude": 37.371991, - "Longitude": -122.02602, - "Address": "", - "City": "SUNNYVALE", - "State": "CA", - "Zip": "94085", - "Country": "US" - }] \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test8 b/components/cjson/cJSON/tests/inputs/test8 deleted file mode 100644 index 4b1f5b97c..000000000 --- a/components/cjson/cJSON/tests/inputs/test8 +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Image": { - "Width": 800, - "Height": 600, - "Title": "View from 15th Floor", - "Thumbnail": { - "Url": "http:/*www.example.com/image/481989943", - "Height": 125, - "Width": "100" - }, - "IDs": [116, 943, 234, 38793] - } - } diff --git a/components/cjson/cJSON/tests/inputs/test8.expected b/components/cjson/cJSON/tests/inputs/test8.expected deleted file mode 100644 index 2e6b731ff..000000000 --- a/components/cjson/cJSON/tests/inputs/test8.expected +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Image": { - "Width": 800, - "Height": 600, - "Title": "View from 15th Floor", - "Thumbnail": { - "Url": "http:/*www.example.com/image/481989943", - "Height": 125, - "Width": "100" - }, - "IDs": [116, 943, 234, 38793] - } -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/inputs/test9 b/components/cjson/cJSON/tests/inputs/test9 deleted file mode 100644 index 2a939b96c..000000000 --- a/components/cjson/cJSON/tests/inputs/test9 +++ /dev/null @@ -1,5 +0,0 @@ -[ - [0, -1, 0], - [1, 0, 0], - [0, 0, 1] - ] diff --git a/components/cjson/cJSON/tests/inputs/test9.expected b/components/cjson/cJSON/tests/inputs/test9.expected deleted file mode 100644 index 0eea3c94b..000000000 --- a/components/cjson/cJSON/tests/inputs/test9.expected +++ /dev/null @@ -1 +0,0 @@ -[[0, -1, 0], [1, 0, 0], [0, 0, 1]] \ No newline at end of file diff --git a/components/cjson/cJSON/tests/json-patch-tests/.editorconfig b/components/cjson/cJSON/tests/json-patch-tests/.editorconfig deleted file mode 100644 index dc79da48b..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -# EditorConfig is awesome: http://EditorConfig.org - -root = true - -[*] -end_of_line = lf -insert_final_newline = true -charset = utf-8 -trim_trailing_whitespace = true -indent_style = space diff --git a/components/cjson/cJSON/tests/json-patch-tests/.gitignore b/components/cjson/cJSON/tests/json-patch-tests/.gitignore deleted file mode 100644 index cd2b23de6..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*~ -\#* -!.editorconfig -!.gitignore diff --git a/components/cjson/cJSON/tests/json-patch-tests/.npmignore b/components/cjson/cJSON/tests/json-patch-tests/.npmignore deleted file mode 100644 index 2d6cdcb26..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.editorconfig -.gitignore diff --git a/components/cjson/cJSON/tests/json-patch-tests/README.md b/components/cjson/cJSON/tests/json-patch-tests/README.md deleted file mode 100644 index fb9e44784..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/README.md +++ /dev/null @@ -1,75 +0,0 @@ -JSON Patch Tests -================ - -These are test cases for implementations of [IETF JSON Patch (RFC6902)](http://tools.ietf.org/html/rfc6902). - -Some implementations can be found at [jsonpatch.com](http://jsonpatch.com). - - -Test Format ------------ - -Each test file is a JSON document that contains an array of test records. A -test record is an object with the following members: - -- doc: The JSON document to test against -- patch: The patch(es) to apply -- expected: The expected resulting document, OR -- error: A string describing an expected error -- comment: A string describing the test -- disabled: True if the test should be skipped - -All fields except 'doc' and 'patch' are optional. Test records consisting only -of a comment are also OK. - - -Files ------ - -- tests.json: the main test file -- spec_tests.json: tests from the RFC6902 spec - - -Writing Tests -------------- - -All tests should have a descriptive comment. Tests should be as -simple as possible - just what's required to test a specific piece of -behavior. If you want to test interacting behaviors, create tests for -each behavior as well as the interaction. - -If an 'error' member is specified, the error text should describe the -error the implementation should raise - *not* what's being tested. -Implementation error strings will vary, but the suggested error should -be easily matched to the implementation error string. Try to avoid -creating error tests that might pass because an incorrect error was -reported. - -Please feel free to contribute! - - -Credits -------- - -The seed test set was adapted from Byron Ruth's -[jsonpatch-js](https://github.com/bruth/jsonpatch-js/blob/master/test.js) and -extended by [Mike McCabe](https://github.com/mikemccabe). - - -License -------- - - Copyright 2014 The Authors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/components/cjson/cJSON/tests/json-patch-tests/cjson-utils-tests.json b/components/cjson/cJSON/tests/json-patch-tests/cjson-utils-tests.json deleted file mode 100644 index 28a5e3073..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/cjson-utils-tests.json +++ /dev/null @@ -1,91 +0,0 @@ -[ - { - "comment": "1", - "doc": { "foo": "bar"}, - "patch": [{ "op": "add", "path": "/baz", "value": "qux" }], - "expected": {"baz": "qux", "foo": "bar"} - }, - { - "comment": "2", - "doc": { "foo": [ "bar", "baz" ] }, - "patch": [{ "op": "add", "path": "/foo/1", "value": "qux" }], - "expected": {"foo": [ "bar", "qux", "baz" ] } - }, - { - "comment": "3", - "doc": {"baz": "qux","foo": "bar"}, - "patch": [{ "op": "remove", "path": "/baz" }], - "expected": {"foo": "bar" } - }, - { - "comment": "4", - "doc": { "foo": [ "bar", "qux", "baz" ] }, - "patch": [{ "op": "remove", "path": "/foo/1" }], - "expected": {"foo": [ "bar", "baz" ] } - }, - { - "comment": "5", - "doc": { "baz": "qux","foo": "bar"}, - "patch": [{ "op": "replace", "path": "/baz", "value": "boo" }], - "expected": {"baz": "boo","foo": "bar"} - }, - { - "comment": "6", - "doc": {"foo": {"bar": "baz","waldo": "fred"},"qux": {"corge": "grault"}}, - "patch": [{ "op": "move", "from": "/foo/waldo", "path": "/qux/thud" }], - "expected": {"foo": {"bar": "baz"},"qux": {"corge": "grault","thud": "fred"}} - }, - { - "comment": "7", - "doc": { "foo": [ "all", "grass", "cows", "eat" ] }, - "patch": [ { "op": "move", "from": "/foo/1", "path": "/foo/3" }], - "expected": { "foo": [ "all", "cows", "eat", "grass" ] } - }, - { - "comment": "8", - "doc": {"baz": "qux","foo": [ "a", 2, "c" ]}, - "patch": [{ "op": "test", "path": "/baz", "value": "qux" },{ "op": "test", "path": "/foo/1", "value": 2 }] - }, - { - "comment": "9", - "doc": { "baz": "qux" }, - "patch": [ { "op": "test", "path": "/baz", "value": "bar" }], - "error": "\"bar\" doesn't exist" - }, - { - "comment": "10", - "doc": { "foo": "bar" }, - "patch": [{ "op": "add", "path": "/child", "value": { "grandchild": { } } }], - "expected": {"foo": "bar","child": {"grandchild": {}}} - }, - { - "comment": "11", - "doc": { "foo": "bar" }, - "patch": [{ "op": "add", "path": "/baz", "value": "qux", "xyz": 123 }], - "expected": {"foo": "bar","baz": "qux"} - }, - { - "comment": "12", - "doc": { "foo": "bar" }, - "patch": [{ "op": "add", "path": "/baz/bat", "value": "qux" }], - "error": "Can't add to nonexistent object" - }, - { - "comment": "13", - "doc": {"/": 9,"~1": 10}, - "patch": [{"op": "test", "path": "/~01", "value": 10}] - }, - { - "comment": "14", - "doc": { "foo": ["bar"] }, - "patch": [ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] }], - "expected": {"foo": ["bar", ["abc", "def"]] } - }, - - { - "comment": "15", - "doc": {"foo": {"bar": 1}}, - "patch": [{"op": "add", "path": "/foo/bar/baz", "value": "5"}], - "error": "attempting to add to subfield of non-object" - } -] diff --git a/components/cjson/cJSON/tests/json-patch-tests/package.json b/components/cjson/cJSON/tests/json-patch-tests/package.json deleted file mode 100644 index 256f9368e..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "json-patch-test-suite", - "version": "1.1.0", - "description": "JSON Patch RFC 6902 test suite", - "repository": "github:json-patch/json-patch-tests", - "homepage": "https://github.com/json-patch/json-patch-tests", - "bugs": "https://github.com/json-patch/json-patch-tests/issues", - "keywords": [ - "JSON", - "Patch", - "test", - "suite" - ], - "license": "Apache-2.0" -} diff --git a/components/cjson/cJSON/tests/json-patch-tests/spec_tests.json b/components/cjson/cJSON/tests/json-patch-tests/spec_tests.json deleted file mode 100644 index c160535b3..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/spec_tests.json +++ /dev/null @@ -1,233 +0,0 @@ -[ - { - "comment": "4.1. add with missing object", - "doc": { "q": { "bar": 2 } }, - "patch": [ {"op": "add", "path": "/a/b", "value": 1} ], - "error": - "path /a does not exist -- missing objects are not created recursively" - }, - - { - "comment": "A.1. Adding an Object Member", - "doc": { - "foo": "bar" -}, - "patch": [ - { "op": "add", "path": "/baz", "value": "qux" } -], - "expected": { - "baz": "qux", - "foo": "bar" -} - }, - - { - "comment": "A.2. Adding an Array Element", - "doc": { - "foo": [ "bar", "baz" ] -}, - "patch": [ - { "op": "add", "path": "/foo/1", "value": "qux" } -], - "expected": { - "foo": [ "bar", "qux", "baz" ] -} - }, - - { - "comment": "A.3. Removing an Object Member", - "doc": { - "baz": "qux", - "foo": "bar" -}, - "patch": [ - { "op": "remove", "path": "/baz" } -], - "expected": { - "foo": "bar" -} - }, - - { - "comment": "A.4. Removing an Array Element", - "doc": { - "foo": [ "bar", "qux", "baz" ] -}, - "patch": [ - { "op": "remove", "path": "/foo/1" } -], - "expected": { - "foo": [ "bar", "baz" ] -} - }, - - { - "comment": "A.5. Replacing a Value", - "doc": { - "baz": "qux", - "foo": "bar" -}, - "patch": [ - { "op": "replace", "path": "/baz", "value": "boo" } -], - "expected": { - "baz": "boo", - "foo": "bar" -} - }, - - { - "comment": "A.6. Moving a Value", - "doc": { - "foo": { - "bar": "baz", - "waldo": "fred" - }, - "qux": { - "corge": "grault" - } -}, - "patch": [ - { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } -], - "expected": { - "foo": { - "bar": "baz" - }, - "qux": { - "corge": "grault", - "thud": "fred" - } -} - }, - - { - "comment": "A.7. Moving an Array Element", - "doc": { - "foo": [ "all", "grass", "cows", "eat" ] -}, - "patch": [ - { "op": "move", "from": "/foo/1", "path": "/foo/3" } -], - "expected": { - "foo": [ "all", "cows", "eat", "grass" ] -} - - }, - - { - "comment": "A.8. Testing a Value: Success", - "doc": { - "baz": "qux", - "foo": [ "a", 2, "c" ] -}, - "patch": [ - { "op": "test", "path": "/baz", "value": "qux" }, - { "op": "test", "path": "/foo/1", "value": 2 } -], - "expected": { - "baz": "qux", - "foo": [ "a", 2, "c" ] - } - }, - - { - "comment": "A.9. Testing a Value: Error", - "doc": { - "baz": "qux" -}, - "patch": [ - { "op": "test", "path": "/baz", "value": "bar" } -], - "error": "string not equivalent" - }, - - { - "comment": "A.10. Adding a nested Member Object", - "doc": { - "foo": "bar" -}, - "patch": [ - { "op": "add", "path": "/child", "value": { "grandchild": { } } } -], - "expected": { - "foo": "bar", - "child": { - "grandchild": { - } - } -} - }, - - { - "comment": "A.11. Ignoring Unrecognized Elements", - "doc": { - "foo":"bar" -}, - "patch": [ - { "op": "add", "path": "/baz", "value": "qux", "xyz": 123 } -], - "expected": { - "foo":"bar", - "baz":"qux" -} - }, - - { - "comment": "A.12. Adding to a Non-existent Target", - "doc": { - "foo": "bar" -}, - "patch": [ - { "op": "add", "path": "/baz/bat", "value": "qux" } -], - "error": "add to a non-existent target" - }, - - { - "comment": "A.13 Invalid JSON Patch Document", - "doc": { - "foo": "bar" - }, - "patch": [ - { "op": "add", "path": "/baz", "value": "qux", "op": "remove" } -], - "error": "operation has two 'op' members", - "disabled": true - }, - - { - "comment": "A.14. ~ Escape Ordering", - "doc": { - "/": 9, - "~1": 10 - }, - "patch": [{"op": "test", "path": "/~01", "value": 10}], - "expected": { - "/": 9, - "~1": 10 - } - }, - - { - "comment": "A.15. Comparing Strings and Numbers", - "doc": { - "/": 9, - "~1": 10 - }, - "patch": [{"op": "test", "path": "/~01", "value": "10"}], - "error": "number is not equal to string" - }, - - { - "comment": "A.16. Adding an Array Value", - "doc": { - "foo": ["bar"] - }, - "patch": [{ "op": "add", "path": "/foo/-", "value": ["abc", "def"] }], - "expected": { - "foo": ["bar", ["abc", "def"]] - } - } - -] diff --git a/components/cjson/cJSON/tests/json-patch-tests/tests.json b/components/cjson/cJSON/tests/json-patch-tests/tests.json deleted file mode 100644 index 86305c16d..000000000 --- a/components/cjson/cJSON/tests/json-patch-tests/tests.json +++ /dev/null @@ -1,434 +0,0 @@ -[ - { "comment": "empty list, empty docs", - "doc": {}, - "patch": [], - "expected": {} }, - - { "comment": "empty patch list", - "doc": {"foo": 1}, - "patch": [], - "expected": {"foo": 1} }, - - { "comment": "rearrangements OK?", - "doc": {"foo": 1, "bar": 2}, - "patch": [], - "expected": {"bar":2, "foo": 1} }, - - { "comment": "rearrangements OK? How about one level down ... array", - "doc": [{"foo": 1, "bar": 2}], - "patch": [], - "expected": [{"bar":2, "foo": 1}] }, - - { "comment": "rearrangements OK? How about one level down...", - "doc": {"foo":{"foo": 1, "bar": 2}}, - "patch": [], - "expected": {"foo":{"bar":2, "foo": 1}} }, - - { "comment": "add replaces any existing field", - "doc": {"foo": null}, - "patch": [{"op": "add", "path": "/foo", "value":1}], - "expected": {"foo": 1} }, - - { "comment": "toplevel array", - "doc": [], - "patch": [{"op": "add", "path": "/0", "value": "foo"}], - "expected": ["foo"] }, - - { "comment": "toplevel array, no change", - "doc": ["foo"], - "patch": [], - "expected": ["foo"] }, - - { "comment": "toplevel object, numeric string", - "doc": {}, - "patch": [{"op": "add", "path": "/foo", "value": "1"}], - "expected": {"foo":"1"} }, - - { "comment": "toplevel object, integer", - "doc": {}, - "patch": [{"op": "add", "path": "/foo", "value": 1}], - "expected": {"foo":1} }, - - { "comment": "Toplevel scalar values OK?", - "doc": "foo", - "patch": [{"op": "replace", "path": "", "value": "bar"}], - "expected": "bar", - "disabled": true }, - - { "comment": "replace object document with array document?", - "doc": {}, - "patch": [{"op": "add", "path": "", "value": []}], - "expected": [] }, - - { "comment": "replace array document with object document?", - "doc": [], - "patch": [{"op": "add", "path": "", "value": {}}], - "expected": {} }, - - { "comment": "append to root array document?", - "doc": [], - "patch": [{"op": "add", "path": "/-", "value": "hi"}], - "expected": ["hi"] }, - - { "comment": "Add, / target", - "doc": {}, - "patch": [ {"op": "add", "path": "/", "value":1 } ], - "expected": {"":1} }, - - { "comment": "Add, /foo/ deep target (trailing slash)", - "doc": {"foo": {}}, - "patch": [ {"op": "add", "path": "/foo/", "value":1 } ], - "expected": {"foo":{"": 1}} }, - - { "comment": "Add composite value at top level", - "doc": {"foo": 1}, - "patch": [{"op": "add", "path": "/bar", "value": [1, 2]}], - "expected": {"foo": 1, "bar": [1, 2]} }, - - { "comment": "Add into composite value", - "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, - "patch": [{"op": "add", "path": "/baz/0/foo", "value": "world"}], - "expected": {"foo": 1, "baz": [{"qux": "hello", "foo": "world"}]} }, - - { "doc": {"bar": [1, 2]}, - "patch": [{"op": "add", "path": "/bar/8", "value": "5"}], - "error": "Out of bounds (upper)" }, - - { "doc": {"bar": [1, 2]}, - "patch": [{"op": "add", "path": "/bar/-1", "value": "5"}], - "error": "Out of bounds (lower)" }, - - { "doc": {"foo": 1}, - "patch": [{"op": "add", "path": "/bar", "value": true}], - "expected": {"foo": 1, "bar": true} }, - - { "doc": {"foo": 1}, - "patch": [{"op": "add", "path": "/bar", "value": false}], - "expected": {"foo": 1, "bar": false} }, - - { "doc": {"foo": 1}, - "patch": [{"op": "add", "path": "/bar", "value": null}], - "expected": {"foo": 1, "bar": null} }, - - { "comment": "0 can be an array index or object element name", - "doc": {"foo": 1}, - "patch": [{"op": "add", "path": "/0", "value": "bar"}], - "expected": {"foo": 1, "0": "bar" } }, - - { "doc": ["foo"], - "patch": [{"op": "add", "path": "/1", "value": "bar"}], - "expected": ["foo", "bar"] }, - - { "doc": ["foo", "sil"], - "patch": [{"op": "add", "path": "/1", "value": "bar"}], - "expected": ["foo", "bar", "sil"] }, - - { "doc": ["foo", "sil"], - "patch": [{"op": "add", "path": "/0", "value": "bar"}], - "expected": ["bar", "foo", "sil"] }, - - { "comment": "push item to array via last index + 1", - "doc": ["foo", "sil"], - "patch": [{"op":"add", "path": "/2", "value": "bar"}], - "expected": ["foo", "sil", "bar"] }, - - { "comment": "add item to array at index > length should fail", - "doc": ["foo", "sil"], - "patch": [{"op":"add", "path": "/3", "value": "bar"}], - "error": "index is greater than number of items in array" }, - - { "comment": "test against implementation-specific numeric parsing", - "doc": {"1e0": "foo"}, - "patch": [{"op": "test", "path": "/1e0", "value": "foo"}], - "expected": {"1e0": "foo"} }, - - { "comment": "test with bad number should fail", - "doc": ["foo", "bar"], - "patch": [{"op": "test", "path": "/1e0", "value": "bar"}], - "error": "test op shouldn't get array element 1" }, - - { "doc": ["foo", "sil"], - "patch": [{"op": "add", "path": "/bar", "value": 42}], - "error": "Object operation on array target" }, - - { "doc": ["foo", "sil"], - "patch": [{"op": "add", "path": "/1", "value": ["bar", "baz"]}], - "expected": ["foo", ["bar", "baz"], "sil"], - "comment": "value in array add not flattened" }, - - { "doc": {"foo": 1, "bar": [1, 2, 3, 4]}, - "patch": [{"op": "remove", "path": "/bar"}], - "expected": {"foo": 1} }, - - { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, - "patch": [{"op": "remove", "path": "/baz/0/qux"}], - "expected": {"foo": 1, "baz": [{}]} }, - - { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, - "patch": [{"op": "replace", "path": "/foo", "value": [1, 2, 3, 4]}], - "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]} }, - - { "doc": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]}, - "patch": [{"op": "replace", "path": "/baz/0/qux", "value": "world"}], - "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "world"}]} }, - - { "doc": ["foo"], - "patch": [{"op": "replace", "path": "/0", "value": "bar"}], - "expected": ["bar"] }, - - { "doc": [""], - "patch": [{"op": "replace", "path": "/0", "value": 0}], - "expected": [0] }, - - { "doc": [""], - "patch": [{"op": "replace", "path": "/0", "value": true}], - "expected": [true] }, - - { "doc": [""], - "patch": [{"op": "replace", "path": "/0", "value": false}], - "expected": [false] }, - - { "doc": [""], - "patch": [{"op": "replace", "path": "/0", "value": null}], - "expected": [null] }, - - { "doc": ["foo", "sil"], - "patch": [{"op": "replace", "path": "/1", "value": ["bar", "baz"]}], - "expected": ["foo", ["bar", "baz"]], - "comment": "value in array replace not flattened" }, - - { "comment": "replace whole document", - "doc": {"foo": "bar"}, - "patch": [{"op": "replace", "path": "", "value": {"baz": "qux"}}], - "expected": {"baz": "qux"} }, - - { "comment": "test replace with missing parent key should fail", - "doc": {"bar": "baz"}, - "patch": [{"op": "replace", "path": "/foo/bar", "value": false}], - "error": "replace op should fail with missing parent key" }, - - { "comment": "spurious patch properties", - "doc": {"foo": 1}, - "patch": [{"op": "test", "path": "/foo", "value": 1, "spurious": 1}], - "expected": {"foo": 1} }, - - { "doc": {"foo": null}, - "patch": [{"op": "test", "path": "/foo", "value": null}], - "comment": "null value should be valid obj property" }, - - { "doc": {"foo": null}, - "patch": [{"op": "replace", "path": "/foo", "value": "truthy"}], - "expected": {"foo": "truthy"}, - "comment": "null value should be valid obj property to be replaced with something truthy" }, - - { "doc": {"foo": null}, - "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], - "expected": {"bar": null}, - "comment": "null value should be valid obj property to be moved" }, - - { "doc": {"foo": null}, - "patch": [{"op": "copy", "from": "/foo", "path": "/bar"}], - "expected": {"foo": null, "bar": null}, - "comment": "null value should be valid obj property to be copied" }, - - { "doc": {"foo": null}, - "patch": [{"op": "remove", "path": "/foo"}], - "expected": {}, - "comment": "null value should be valid obj property to be removed" }, - - { "doc": {"foo": "bar"}, - "patch": [{"op": "replace", "path": "/foo", "value": null}], - "expected": {"foo": null}, - "comment": "null value should still be valid obj property replace other value" }, - - { "doc": {"foo": {"foo": 1, "bar": 2}}, - "patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}], - "comment": "test should pass despite rearrangement" }, - - { "doc": {"foo": [{"foo": 1, "bar": 2}]}, - "patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}], - "comment": "test should pass despite (nested) rearrangement" }, - - { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, - "patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}], - "comment": "test should pass - no error" }, - - { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, - "patch": [{"op": "test", "path": "/foo", "value": [1, 2]}], - "error": "test op should fail" }, - - { "comment": "Whole document", - "doc": { "foo": 1 }, - "patch": [{"op": "test", "path": "", "value": {"foo": 1}}], - "disabled": true }, - - { "comment": "Empty-string element", - "doc": { "": 1 }, - "patch": [{"op": "test", "path": "/", "value": 1}] }, - - { "doc": { - "foo": ["bar", "baz"], - "": 0, - "a/b": 1, - "c%d": 2, - "e^f": 3, - "g|h": 4, - "i\\j": 5, - "k\"l": 6, - " ": 7, - "m~n": 8 - }, - "patch": [{"op": "test", "path": "/foo", "value": ["bar", "baz"]}, - {"op": "test", "path": "/foo/0", "value": "bar"}, - {"op": "test", "path": "/", "value": 0}, - {"op": "test", "path": "/a~1b", "value": 1}, - {"op": "test", "path": "/c%d", "value": 2}, - {"op": "test", "path": "/e^f", "value": 3}, - {"op": "test", "path": "/g|h", "value": 4}, - {"op": "test", "path": "/i\\j", "value": 5}, - {"op": "test", "path": "/k\"l", "value": 6}, - {"op": "test", "path": "/ ", "value": 7}, - {"op": "test", "path": "/m~0n", "value": 8}] }, - - { "comment": "Move to same location has no effect", - "doc": {"foo": 1}, - "patch": [{"op": "move", "from": "/foo", "path": "/foo"}], - "expected": {"foo": 1} }, - - { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, - "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], - "expected": {"baz": [{"qux": "hello"}], "bar": 1} }, - - { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, - "patch": [{"op": "move", "from": "/baz/0/qux", "path": "/baz/1"}], - "expected": {"baz": [{}, "hello"], "bar": 1} }, - - { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, - "patch": [{"op": "copy", "from": "/baz/0", "path": "/boo"}], - "expected": {"baz":[{"qux":"hello"}],"bar":1,"boo":{"qux":"hello"}} }, - - { "comment": "replacing the root of the document is possible with add", - "doc": {"foo": "bar"}, - "patch": [{"op": "add", "path": "", "value": {"baz": "qux"}}], - "expected": {"baz":"qux"}}, - - { "comment": "Adding to \"/-\" adds to the end of the array", - "doc": [ 1, 2 ], - "patch": [ { "op": "add", "path": "/-", "value": { "foo": [ "bar", "baz" ] } } ], - "expected": [ 1, 2, { "foo": [ "bar", "baz" ] } ]}, - - { "comment": "Adding to \"/-\" adds to the end of the array, even n levels down", - "doc": [ 1, 2, [ 3, [ 4, 5 ] ] ], - "patch": [ { "op": "add", "path": "/2/1/-", "value": { "foo": [ "bar", "baz" ] } } ], - "expected": [ 1, 2, [ 3, [ 4, 5, { "foo": [ "bar", "baz" ] } ] ] ]}, - - { "comment": "test remove with bad number should fail", - "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, - "patch": [{"op": "remove", "path": "/baz/1e0/qux"}], - "error": "remove op shouldn't remove from array with bad number" }, - - { "comment": "test remove on array", - "doc": [1, 2, 3, 4], - "patch": [{"op": "remove", "path": "/0"}], - "expected": [2, 3, 4] }, - - { "comment": "test repeated removes", - "doc": [1, 2, 3, 4], - "patch": [{ "op": "remove", "path": "/1" }, - { "op": "remove", "path": "/2" }], - "expected": [1, 3] }, - - { "comment": "test remove with bad index should fail", - "doc": [1, 2, 3, 4], - "patch": [{"op": "remove", "path": "/1e0"}], - "error": "remove op shouldn't remove from array with bad number" }, - - { "comment": "test replace with bad number should fail", - "doc": [""], - "patch": [{"op": "replace", "path": "/1e0", "value": false}], - "error": "replace op shouldn't replace in array with bad number" }, - - { "comment": "test copy with bad number should fail", - "doc": {"baz": [1,2,3], "bar": 1}, - "patch": [{"op": "copy", "from": "/baz/1e0", "path": "/boo"}], - "error": "copy op shouldn't work with bad number" }, - - { "comment": "test move with bad number should fail", - "doc": {"foo": 1, "baz": [1,2,3,4]}, - "patch": [{"op": "move", "from": "/baz/1e0", "path": "/foo"}], - "error": "move op shouldn't work with bad number" }, - - { "comment": "test add with bad number should fail", - "doc": ["foo", "sil"], - "patch": [{"op": "add", "path": "/1e0", "value": "bar"}], - "error": "add op shouldn't add to array with bad number" }, - - { "comment": "missing 'value' parameter to add", - "doc": [ 1 ], - "patch": [ { "op": "add", "path": "/-" } ], - "error": "missing 'value' parameter" }, - - { "comment": "missing 'value' parameter to replace", - "doc": [ 1 ], - "patch": [ { "op": "replace", "path": "/0" } ], - "error": "missing 'value' parameter" }, - - { "comment": "missing 'value' parameter to test", - "doc": [ null ], - "patch": [ { "op": "test", "path": "/0" } ], - "error": "missing 'value' parameter" }, - - { "comment": "missing value parameter to test - where undef is falsy", - "doc": [ false ], - "patch": [ { "op": "test", "path": "/0" } ], - "error": "missing 'value' parameter" }, - - { "comment": "missing from parameter to copy", - "doc": [ 1 ], - "patch": [ { "op": "copy", "path": "/-" } ], - "error": "missing 'from' parameter" }, - - { "comment": "missing from parameter to move", - "doc": { "foo": 1 }, - "patch": [ { "op": "move", "path": "" } ], - "error": "missing 'from' parameter" }, - - { "comment": "duplicate ops", - "doc": { "foo": "bar" }, - "patch": [ { "op": "add", "path": "/baz", "value": "qux", - "op": "move", "from":"/foo" } ], - "error": "patch has two 'op' members", - "disabled": true }, - - { "comment": "unrecognized op should fail", - "doc": {"foo": 1}, - "patch": [{"op": "spam", "path": "/foo", "value": 1}], - "error": "Unrecognized op 'spam'" }, - - { "comment": "test with bad array number that has leading zeros", - "doc": ["foo", "bar"], - "patch": [{"op": "test", "path": "/00", "value": "foo"}], - "error": "test op should reject the array value, it has leading zeros" }, - - { "comment": "test with bad array number that has leading zeros", - "doc": ["foo", "bar"], - "patch": [{"op": "test", "path": "/01", "value": "bar"}], - "error": "test op should reject the array value, it has leading zeros" }, - - { "comment": "Removing nonexistent field", - "doc": {"foo" : "bar"}, - "patch": [{"op": "remove", "path": "/baz"}], - "error": "removing a nonexistent field should fail" }, - - { "comment": "Removing nonexistent index", - "doc": ["foo", "bar"], - "patch": [{"op": "remove", "path": "/2"}], - "error": "removing a nonexistent index should fail" }, - - { "comment": "Patch with different capitalisation than doc", - "doc": {"foo":"bar"}, - "patch": [{"op": "add", "path": "/FOO", "value": "BAR"}], - "expected": {"foo": "bar", "FOO": "BAR"} - } - -] diff --git a/components/cjson/cJSON/tests/json_patch_tests.c b/components/cjson/cJSON/tests/json_patch_tests.c deleted file mode 100644 index c2c88a4f5..000000000 --- a/components/cjson/cJSON/tests/json_patch_tests.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" -#include "../cJSON_Utils.h" - -static cJSON *parse_test_file(const char * const filename) -{ - char *file = NULL; - cJSON *json = NULL; - - file = read_file(filename); - TEST_ASSERT_NOT_NULL_MESSAGE(file, "Failed to read file."); - - json = cJSON_Parse(file); - TEST_ASSERT_NOT_NULL_MESSAGE(json, "Failed to parse test json."); - TEST_ASSERT_TRUE_MESSAGE(cJSON_IsArray(json), "Json is not an array."); - - free(file); - - return json; -} - -static cJSON_bool test_apply_patch(const cJSON * const test) -{ - cJSON *doc = NULL; - cJSON *patch = NULL; - cJSON *expected = NULL; - cJSON *error_element = NULL; - cJSON *comment = NULL; - cJSON *disabled = NULL; - - cJSON *object = NULL; - cJSON_bool successful = false; - - /* extract all the data out of the test */ - comment = cJSON_GetObjectItemCaseSensitive(test, "comment"); - if (cJSON_IsString(comment)) - { - printf("Testing \"%s\"\n", comment->valuestring); - } - else - { - printf("Testing unkown\n"); - } - - disabled = cJSON_GetObjectItemCaseSensitive(test, "disabled"); - if (cJSON_IsTrue(disabled)) - { - printf("SKIPPED\n"); - return true; - } - - doc = cJSON_GetObjectItemCaseSensitive(test, "doc"); - TEST_ASSERT_NOT_NULL_MESSAGE(doc, "No \"doc\" in the test."); - patch = cJSON_GetObjectItemCaseSensitive(test, "patch"); - TEST_ASSERT_NOT_NULL_MESSAGE(patch, "No \"patch\"in the test."); - /* Make a working copy of 'doc' */ - object = cJSON_Duplicate(doc, true); - TEST_ASSERT_NOT_NULL(object); - - expected = cJSON_GetObjectItemCaseSensitive(test, "expected"); - error_element = cJSON_GetObjectItemCaseSensitive(test, "error"); - if (error_element != NULL) - { - /* excepting an error */ - TEST_ASSERT_TRUE_MESSAGE(0 != cJSONUtils_ApplyPatchesCaseSensitive(object, patch), "Test didn't fail as it's supposed to."); - - successful = true; - } - else - { - /* apply the patch */ - TEST_ASSERT_EQUAL_INT_MESSAGE(0, cJSONUtils_ApplyPatchesCaseSensitive(object, patch), "Failed to apply patches."); - successful = true; - - if (expected != NULL) - { - successful = cJSON_Compare(object, expected, true); - } - } - - cJSON_Delete(object); - - if (successful) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - - return successful; -} - -static cJSON_bool test_generate_test(cJSON *test) -{ - cJSON *doc = NULL; - cJSON *patch = NULL; - cJSON *expected = NULL; - cJSON *disabled = NULL; - - cJSON *object = NULL; - cJSON_bool successful = false; - - char *printed_patch = NULL; - - disabled = cJSON_GetObjectItemCaseSensitive(test, "disabled"); - if (cJSON_IsTrue(disabled)) - { - printf("SKIPPED\n"); - return true; - } - - doc = cJSON_GetObjectItemCaseSensitive(test, "doc"); - TEST_ASSERT_NOT_NULL_MESSAGE(doc, "No \"doc\" in the test."); - - /* Make a working copy of 'doc' */ - object = cJSON_Duplicate(doc, true); - TEST_ASSERT_NOT_NULL(object); - - expected = cJSON_GetObjectItemCaseSensitive(test, "expected"); - if (expected == NULL) - { - cJSON_Delete(object); - /* if there is no expected output, this test doesn't make sense */ - return true; - } - - patch = cJSONUtils_GeneratePatchesCaseSensitive(doc, expected); - TEST_ASSERT_NOT_NULL_MESSAGE(patch, "Failed to generate patches."); - - printed_patch = cJSON_Print(patch); - printf("%s\n", printed_patch); - free(printed_patch); - - /* apply the generated patch */ - TEST_ASSERT_EQUAL_INT_MESSAGE(0, cJSONUtils_ApplyPatchesCaseSensitive(object, patch), "Failed to apply generated patch."); - - successful = cJSON_Compare(object, expected, true); - - cJSON_Delete(patch); - cJSON_Delete(object); - - if (successful) - { - printf("generated patch: OK\n"); - } - else - { - printf("generated patch: FAILED\n"); - } - - return successful; -} - -static void cjson_utils_should_pass_json_patch_test_tests(void) -{ - cJSON *tests = parse_test_file("json-patch-tests/tests.json"); - cJSON *test = NULL; - - cJSON_bool failed = false; - cJSON_ArrayForEach(test, tests) - { - failed |= !test_apply_patch(test); - failed |= !test_generate_test(test); - } - - cJSON_Delete(tests); - - TEST_ASSERT_FALSE_MESSAGE(failed, "Some tests failed."); -} - -static void cjson_utils_should_pass_json_patch_test_spec_tests(void) -{ - cJSON *tests = parse_test_file("json-patch-tests/spec_tests.json"); - cJSON *test = NULL; - - cJSON_bool failed = false; - cJSON_ArrayForEach(test, tests) - { - failed |= !test_apply_patch(test); - failed |= !test_generate_test(test); - } - - cJSON_Delete(tests); - - TEST_ASSERT_FALSE_MESSAGE(failed, "Some tests failed."); -} - -static void cjson_utils_should_pass_json_patch_test_cjson_utils_tests(void) -{ - cJSON *tests = parse_test_file("json-patch-tests/cjson-utils-tests.json"); - cJSON *test = NULL; - - cJSON_bool failed = false; - cJSON_ArrayForEach(test, tests) - { - failed |= !test_apply_patch(test); - failed |= !test_generate_test(test); - } - - cJSON_Delete(tests); - - TEST_ASSERT_FALSE_MESSAGE(failed, "Some tests failed."); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(cjson_utils_should_pass_json_patch_test_tests); - RUN_TEST(cjson_utils_should_pass_json_patch_test_spec_tests); - RUN_TEST(cjson_utils_should_pass_json_patch_test_cjson_utils_tests); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/misc_tests.c b/components/cjson/cJSON/tests/misc_tests.c deleted file mode 100644 index a0b4f7eba..000000000 --- a/components/cjson/cJSON/tests/misc_tests.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - - -static void cjson_array_foreach_should_loop_over_arrays(void) -{ - cJSON array[1]; - cJSON elements[10]; - cJSON *element_pointer = NULL; - size_t i = 0; - - memset(array, 0, sizeof(array)); - memset(elements, 0, sizeof(elements)); - - /* create array */ - array[0].child = &elements[0]; - elements[0].prev = NULL; - elements[9].next = NULL; - for (i = 0; i < 9; i++) - { - elements[i].next = &elements[i + 1]; - elements[i + 1].prev = &elements[i]; - } - - i = 0; - cJSON_ArrayForEach(element_pointer, array) - { - TEST_ASSERT_TRUE_MESSAGE(element_pointer == &elements[i], "Not iterating over array properly"); - i++; - } -} - -static void cjson_array_foreach_should_not_dereference_null_pointer(void) -{ - cJSON *array = NULL; - cJSON *element = NULL; - cJSON_ArrayForEach(element, array); -} - -static void cjson_get_object_item_should_get_object_items(void) -{ - cJSON *item = NULL; - cJSON *found = NULL; - - item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}"); - - found = cJSON_GetObjectItem(NULL, "test"); - TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer."); - - found = cJSON_GetObjectItem(item, NULL); - TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string."); - - - found = cJSON_GetObjectItem(item, "one"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1); - - found = cJSON_GetObjectItem(item, "tWo"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2); - - found = cJSON_GetObjectItem(item, "three"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3); - - found = cJSON_GetObjectItem(item, "four"); - TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there."); - - cJSON_Delete(item); -} - -static void cjson_get_object_item_case_sensitive_should_get_object_items(void) -{ - cJSON *item = NULL; - cJSON *found = NULL; - - item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}"); - - found = cJSON_GetObjectItemCaseSensitive(NULL, "test"); - TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer."); - - found = cJSON_GetObjectItemCaseSensitive(item, NULL); - TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string."); - - found = cJSON_GetObjectItemCaseSensitive(item, "one"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1); - - found = cJSON_GetObjectItemCaseSensitive(item, "Two"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2); - - found = cJSON_GetObjectItemCaseSensitive(item, "tHree"); - TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item."); - TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3); - - found = cJSON_GetObjectItemCaseSensitive(item, "One"); - TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there."); - - cJSON_Delete(item); -} - -static void typecheck_functions_should_check_type(void) -{ - cJSON invalid[1]; - cJSON item[1]; - invalid->type = cJSON_Invalid; - invalid->type |= cJSON_StringIsConst; - item->type = cJSON_False; - item->type |= cJSON_StringIsConst; - - TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL)); - TEST_ASSERT_FALSE(cJSON_IsInvalid(item)); - TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid)); - - item->type = cJSON_False | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsFalse(NULL)); - TEST_ASSERT_FALSE(cJSON_IsFalse(invalid)); - TEST_ASSERT_TRUE(cJSON_IsFalse(item)); - TEST_ASSERT_TRUE(cJSON_IsBool(item)); - - item->type = cJSON_True | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsTrue(NULL)); - TEST_ASSERT_FALSE(cJSON_IsTrue(invalid)); - TEST_ASSERT_TRUE(cJSON_IsTrue(item)); - TEST_ASSERT_TRUE(cJSON_IsBool(item)); - - item->type = cJSON_NULL | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsNull(NULL)); - TEST_ASSERT_FALSE(cJSON_IsNull(invalid)); - TEST_ASSERT_TRUE(cJSON_IsNull(item)); - - item->type = cJSON_Number | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsNumber(NULL)); - TEST_ASSERT_FALSE(cJSON_IsNumber(invalid)); - TEST_ASSERT_TRUE(cJSON_IsNumber(item)); - - item->type = cJSON_String | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsString(NULL)); - TEST_ASSERT_FALSE(cJSON_IsString(invalid)); - TEST_ASSERT_TRUE(cJSON_IsString(item)); - - item->type = cJSON_Array | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsArray(NULL)); - TEST_ASSERT_FALSE(cJSON_IsArray(invalid)); - TEST_ASSERT_TRUE(cJSON_IsArray(item)); - - item->type = cJSON_Object | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsObject(NULL)); - TEST_ASSERT_FALSE(cJSON_IsObject(invalid)); - TEST_ASSERT_TRUE(cJSON_IsObject(item)); - - item->type = cJSON_Raw | cJSON_StringIsConst; - TEST_ASSERT_FALSE(cJSON_IsRaw(NULL)); - TEST_ASSERT_FALSE(cJSON_IsRaw(invalid)); - TEST_ASSERT_TRUE(cJSON_IsRaw(item)); -} - -static void cjson_should_not_parse_to_deeply_nested_jsons(void) -{ - char deep_json[CJSON_NESTING_LIMIT + 1]; - size_t position = 0; - - for (position = 0; position < sizeof(deep_json); position++) - { - deep_json[position] = '['; - } - deep_json[sizeof(deep_json) - 1] = '\0'; - - TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(deep_json), "To deep JSONs should not be parsed."); -} - -static void cjson_set_number_value_should_set_numbers(void) -{ - cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}}; - - cJSON_SetNumberValue(number, 1.5); - TEST_ASSERT_EQUAL(1, number->valueint); - TEST_ASSERT_EQUAL_DOUBLE(1.5, number->valuedouble); - - cJSON_SetNumberValue(number, -1.5); - TEST_ASSERT_EQUAL(-1, number->valueint); - TEST_ASSERT_EQUAL_DOUBLE(-1.5, number->valuedouble); - - cJSON_SetNumberValue(number, 1 + (double)INT_MAX); - TEST_ASSERT_EQUAL(INT_MAX, number->valueint); - TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble); - - cJSON_SetNumberValue(number, -1 + (double)INT_MIN); - TEST_ASSERT_EQUAL(INT_MIN, number->valueint); - TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble); -} - -static void cjson_detach_item_via_pointer_should_detach_items(void) -{ - cJSON list[4]; - cJSON parent[1]; - - memset(list, '\0', sizeof(list)); - - /* link the list */ - list[0].next = &(list[1]); - list[1].next = &(list[2]); - list[2].next = &(list[3]); - - list[3].prev = &(list[2]); - list[2].prev = &(list[1]); - list[1].prev = &(list[0]); - - parent->child = &list[0]; - - /* detach in the middle (list[1]) */ - TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle."); - TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL."); - TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0]))); - - /* detach beginning (list[0]) */ - TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning."); - TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL."); - TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (parent->child == &(list[2])), "Didn't set the new beginning."); - - /* detach end (list[3])*/ - TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end."); - TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL."); - TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end"); - - /* detach single item (list[2]) */ - TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item."); - TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL."); - TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL."); -} - -static void cjson_replace_item_via_pointer_should_replace_items(void) -{ - cJSON replacements[3]; - cJSON *beginning = NULL; - cJSON *middle = NULL; - cJSON *end = NULL; - cJSON *array = NULL; - - beginning = cJSON_CreateNull(); - TEST_ASSERT_NOT_NULL(beginning); - middle = cJSON_CreateNull(); - TEST_ASSERT_NOT_NULL(middle); - end = cJSON_CreateNull(); - TEST_ASSERT_NOT_NULL(end); - - array = cJSON_CreateArray(); - TEST_ASSERT_NOT_NULL(array); - - cJSON_AddItemToArray(array, beginning); - cJSON_AddItemToArray(array, middle); - cJSON_AddItemToArray(array, end); - - - memset(replacements, '\0', sizeof(replacements)); - - /* replace beginning */ - TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0]))); - TEST_ASSERT_NULL(replacements[0].prev); - TEST_ASSERT_TRUE(replacements[0].next == middle); - TEST_ASSERT_TRUE(middle->prev == &(replacements[0])); - TEST_ASSERT_TRUE(array->child == &(replacements[0])); - - /* replace middle */ - TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1]))); - TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0])); - TEST_ASSERT_TRUE(replacements[1].next == end); - TEST_ASSERT_TRUE(end->prev == &(replacements[1])); - - /* replace end */ - TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2]))); - TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1])); - TEST_ASSERT_NULL(replacements[2].next); - TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2])); - - cJSON_free(array); -} - -static void cjson_replace_item_in_object_should_preserve_name(void) -{ - cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }}; - cJSON *child = NULL; - cJSON *replacement = NULL; - - child = cJSON_CreateNumber(1); - TEST_ASSERT_NOT_NULL(child); - replacement = cJSON_CreateNumber(2); - TEST_ASSERT_NOT_NULL(replacement); - - cJSON_AddItemToObject(root, "child", child); - cJSON_ReplaceItemInObject(root, "child", replacement); - - TEST_ASSERT_TRUE(root->child == replacement); - TEST_ASSERT_EQUAL_STRING("child", replacement->string); - - cJSON_Delete(replacement); -} - -static void cjson_functions_shouldnt_crash_with_null_pointers(void) -{ - char buffer[10]; - cJSON *item = cJSON_CreateString("item"); - - cJSON_InitHooks(NULL); - TEST_ASSERT_NULL(cJSON_Parse(NULL)); - TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true)); - TEST_ASSERT_NULL(cJSON_Print(NULL)); - TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL)); - TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true)); - TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true)); - TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true)); - cJSON_Delete(NULL); - cJSON_GetArraySize(NULL); - TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0)); - TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item")); - TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL)); - TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item")); - TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL)); - TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item")); - TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL)); - TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL)); - TEST_ASSERT_FALSE(cJSON_IsFalse(NULL)); - TEST_ASSERT_FALSE(cJSON_IsTrue(NULL)); - TEST_ASSERT_FALSE(cJSON_IsBool(NULL)); - TEST_ASSERT_FALSE(cJSON_IsNull(NULL)); - TEST_ASSERT_FALSE(cJSON_IsNumber(NULL)); - TEST_ASSERT_FALSE(cJSON_IsString(NULL)); - TEST_ASSERT_FALSE(cJSON_IsArray(NULL)); - TEST_ASSERT_FALSE(cJSON_IsObject(NULL)); - TEST_ASSERT_FALSE(cJSON_IsRaw(NULL)); - TEST_ASSERT_NULL(cJSON_CreateString(NULL)); - TEST_ASSERT_NULL(cJSON_CreateRaw(NULL)); - TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10)); - TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10)); - TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10)); - TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10)); - cJSON_AddItemToArray(NULL, item); - cJSON_AddItemToArray(item, NULL); - cJSON_AddItemToObject(item, "item", NULL); - cJSON_AddItemToObject(item, NULL, item); - cJSON_AddItemToObject(NULL, "item", item); - cJSON_AddItemToObjectCS(item, "item", NULL); - cJSON_AddItemToObjectCS(item, NULL, item); - cJSON_AddItemToObjectCS(NULL, "item", item); - cJSON_AddItemReferenceToArray(NULL, item); - cJSON_AddItemReferenceToArray(item, NULL); - cJSON_AddItemReferenceToObject(item, "item", NULL); - cJSON_AddItemReferenceToObject(item, NULL, item); - cJSON_AddItemReferenceToObject(NULL, "item", item); - TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item)); - TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL)); - TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0)); - cJSON_DeleteItemFromArray(NULL, 0); - TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item")); - TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL)); - TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item")); - TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL)); - cJSON_DeleteItemFromObject(NULL, "item"); - cJSON_DeleteItemFromObject(item, NULL); - cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item"); - cJSON_DeleteItemFromObjectCaseSensitive(item, NULL); - cJSON_InsertItemInArray(NULL, 0, item); - cJSON_InsertItemInArray(item, 0, NULL); - TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item)); - TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item)); - TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL)); - cJSON_ReplaceItemInArray(item, 0, NULL); - cJSON_ReplaceItemInArray(NULL, 0, item); - cJSON_ReplaceItemInObject(NULL, "item", item); - cJSON_ReplaceItemInObject(item, NULL, item); - cJSON_ReplaceItemInObject(item, "item", NULL); - cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item); - cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item); - cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL); - TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true)); - TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false)); - TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false)); - cJSON_Minify(NULL); - /* skipped because it is only used via a macro that checks for NULL */ - /* cJSON_SetNumberHelper(NULL, 0); */ - - cJSON_Delete(item); -} - -static void *failing_realloc(void *pointer, size_t size) -{ - (void)size; - (void)pointer; - return NULL; -} - -static void ensure_should_fail_on_failed_realloc(void) -{ - printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}}; - buffer.buffer = (unsigned char*)malloc(100); - TEST_ASSERT_NOT_NULL(buffer.buffer); - - TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc."); -} - -static void skip_utf8_bom_should_skip_bom(void) -{ - const unsigned char string[] = "\xEF\xBB\xBF{}"; - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = string; - buffer.length = sizeof(string); - buffer.hooks = global_hooks; - - TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer); - TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset); -} - -static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void) -{ - const unsigned char string[] = " \xEF\xBB\xBF{}"; - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = string; - buffer.length = sizeof(string); - buffer.hooks = global_hooks; - buffer.offset = 1; - - TEST_ASSERT_NULL(skip_utf8_bom(&buffer)); -} - -static void cjson_get_string_value_should_get_a_string(void) -{ - cJSON *string = cJSON_CreateString("test"); - cJSON *number = cJSON_CreateNumber(1); - - TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring); - TEST_ASSERT_NULL(cJSON_GetStringValue(number)); - TEST_ASSERT_NULL(cJSON_GetStringValue(NULL)); - - cJSON_Delete(number); - cJSON_Delete(string); -} - -static void cjson_create_string_reference_should_create_a_string_reference(void) { - const char *string = "I am a string!"; - - cJSON *string_reference = cJSON_CreateStringReference(string); - TEST_ASSERT_TRUE(string_reference->valuestring == string); - TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type); - - cJSON_Delete(string_reference); -} - -static void cjson_create_object_reference_should_create_an_object_reference(void) { - cJSON *number_reference = NULL; - cJSON *number_object = cJSON_CreateObject(); - cJSON *number = cJSON_CreateNumber(42); - const char key[] = "number"; - - TEST_ASSERT_TRUE(cJSON_IsNumber(number)); - TEST_ASSERT_TRUE(cJSON_IsObject(number_object)); - cJSON_AddItemToObjectCS(number_object, key, number); - - number_reference = cJSON_CreateObjectReference(number); - TEST_ASSERT_TRUE(number_reference->child == number); - TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type); - - cJSON_Delete(number_object); - cJSON_Delete(number_reference); -} - -static void cjson_create_array_reference_should_create_an_array_reference(void) { - cJSON *number_reference = NULL; - cJSON *number_array = cJSON_CreateArray(); - cJSON *number = cJSON_CreateNumber(42); - - TEST_ASSERT_TRUE(cJSON_IsNumber(number)); - TEST_ASSERT_TRUE(cJSON_IsArray(number_array)); - cJSON_AddItemToArray(number_array, number); - - number_reference = cJSON_CreateArrayReference(number); - TEST_ASSERT_TRUE(number_reference->child == number); - TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type); - - cJSON_Delete(number_array); - cJSON_Delete(number_reference); -} - -static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void) -{ - cJSON *object = cJSON_CreateObject(); - cJSON *number = cJSON_CreateNumber(42); - char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks); - - TEST_ASSERT_NOT_NULL(object); - TEST_ASSERT_NOT_NULL(number); - TEST_ASSERT_NOT_NULL(name); - - number->string = name; - - /* The following should not have a use after free - * that would show up in valgrind or with AddressSanitizer */ - cJSON_AddItemToObject(object, number->string, number); - - cJSON_Delete(object); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(cjson_array_foreach_should_loop_over_arrays); - RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer); - RUN_TEST(cjson_get_object_item_should_get_object_items); - RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items); - RUN_TEST(typecheck_functions_should_check_type); - RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons); - RUN_TEST(cjson_set_number_value_should_set_numbers); - RUN_TEST(cjson_detach_item_via_pointer_should_detach_items); - RUN_TEST(cjson_replace_item_via_pointer_should_replace_items); - RUN_TEST(cjson_replace_item_in_object_should_preserve_name); - RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers); - RUN_TEST(ensure_should_fail_on_failed_realloc); - RUN_TEST(skip_utf8_bom_should_skip_bom); - RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning); - RUN_TEST(cjson_get_string_value_should_get_a_string); - RUN_TEST(cjson_create_string_reference_should_create_a_string_reference); - RUN_TEST(cjson_create_object_reference_should_create_an_object_reference); - RUN_TEST(cjson_create_array_reference_should_create_an_array_reference); - RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/misc_utils_tests.c b/components/cjson/cJSON/tests/misc_utils_tests.c deleted file mode 100644 index 7d300bc8e..000000000 --- a/components/cjson/cJSON/tests/misc_utils_tests.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" -#include "../cJSON_Utils.h" - -static void cjson_utils_functions_shouldnt_crash_with_null_pointers(void) -{ - cJSON *item = cJSON_CreateString("item"); - TEST_ASSERT_NOT_NULL(item); - - TEST_ASSERT_NULL(cJSONUtils_GetPointer(item, NULL)); - TEST_ASSERT_NULL(cJSONUtils_GetPointer(NULL, "pointer")); - TEST_ASSERT_NULL(cJSONUtils_GetPointerCaseSensitive(NULL, "pointer")); - TEST_ASSERT_NULL(cJSONUtils_GetPointerCaseSensitive(item, NULL)); - TEST_ASSERT_NULL(cJSONUtils_GeneratePatches(item, NULL)); - TEST_ASSERT_NULL(cJSONUtils_GeneratePatches(NULL, item)); - TEST_ASSERT_NULL(cJSONUtils_GeneratePatchesCaseSensitive(item, NULL)); - TEST_ASSERT_NULL(cJSONUtils_GeneratePatchesCaseSensitive(NULL, item)); - cJSONUtils_AddPatchToArray(item, "path", "add", NULL); - cJSONUtils_AddPatchToArray(item, "path", NULL, item); - cJSONUtils_AddPatchToArray(item, NULL, "add", item); - cJSONUtils_AddPatchToArray(NULL, "path", "add", item); - cJSONUtils_ApplyPatches(item, NULL); - cJSONUtils_ApplyPatches(NULL, item); - cJSONUtils_ApplyPatchesCaseSensitive(item, NULL); - cJSONUtils_ApplyPatchesCaseSensitive(NULL, item); - TEST_ASSERT_NULL(cJSONUtils_MergePatch(item, NULL)); - item = cJSON_CreateString("item"); - TEST_ASSERT_NULL(cJSONUtils_MergePatchCaseSensitive(item, NULL)); - item = cJSON_CreateString("item"); - /* these calls are actually valid */ - /* cJSONUtils_MergePatch(NULL, item); */ - /* cJSONUtils_MergePatchCaseSensitive(NULL, item);*/ - /* cJSONUtils_GenerateMergePatch(item, NULL); */ - /* cJSONUtils_GenerateMergePatch(NULL, item); */ - /* cJSONUtils_GenerateMergePatchCaseSensitive(item, NULL); */ - /* cJSONUtils_GenerateMergePatchCaseSensitive(NULL, item); */ - - TEST_ASSERT_NULL(cJSONUtils_FindPointerFromObjectTo(item, NULL)); - TEST_ASSERT_NULL(cJSONUtils_FindPointerFromObjectTo(NULL, item)); - cJSONUtils_SortObject(NULL); - cJSONUtils_SortObjectCaseSensitive(NULL); - - cJSON_Delete(item); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(cjson_utils_functions_shouldnt_crash_with_null_pointers); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/old_utils_tests.c b/components/cjson/cJSON/tests/old_utils_tests.c deleted file mode 100644 index 08da6a6dc..000000000 --- a/components/cjson/cJSON/tests/old_utils_tests.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" -#include "../cJSON_Utils.h" - -/* JSON Apply Merge tests: */ -static const char *merges[15][3] = -{ - {"{\"a\":\"b\"}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"}, - {"{\"a\":\"b\"}", "{\"b\":\"c\"}", "{\"a\":\"b\",\"b\":\"c\"}"}, - {"{\"a\":\"b\"}", "{\"a\":null}", "{}"}, - {"{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":null}", "{\"b\":\"c\"}"}, - {"{\"a\":[\"b\"]}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"}, - {"{\"a\":\"c\"}", "{\"a\":[\"b\"]}", "{\"a\":[\"b\"]}"}, - {"{\"a\":{\"b\":\"c\"}}", "{\"a\":{\"b\":\"d\",\"c\":null}}", "{\"a\":{\"b\":\"d\"}}"}, - {"{\"a\":[{\"b\":\"c\"}]}", "{\"a\":[1]}", "{\"a\":[1]}"}, - {"[\"a\",\"b\"]", "[\"c\",\"d\"]", "[\"c\",\"d\"]"}, - {"{\"a\":\"b\"}", "[\"c\"]", "[\"c\"]"}, - {"{\"a\":\"foo\"}", "null", "null"}, - {"{\"a\":\"foo\"}", "\"bar\"", "\"bar\""}, - {"{\"e\":null}", "{\"a\":1}", "{\"e\":null,\"a\":1}"}, - {"[1,2]", "{\"a\":\"b\",\"c\":null}", "{\"a\":\"b\"}"}, - {"{}","{\"a\":{\"bb\":{\"ccc\":null}}}", "{\"a\":{\"bb\":{}}}"} -}; - -static void json_pointer_tests(void) -{ - cJSON *root = NULL; - const char *json= - "{" - "\"foo\": [\"bar\", \"baz\"]," - "\"\": 0," - "\"a/b\": 1," - "\"c%d\": 2," - "\"e^f\": 3," - "\"g|h\": 4," - "\"i\\\\j\": 5," - "\"k\\\"l\": 6," - "\" \": 7," - "\"m~n\": 8" - "}"; - - root = cJSON_Parse(json); - - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, ""), root); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo"), cJSON_GetObjectItem(root, "foo")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo/0"), cJSON_GetObjectItem(root, "foo")->child); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo/0"), cJSON_GetObjectItem(root, "foo")->child); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/"), cJSON_GetObjectItem(root, "")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/a~1b"), cJSON_GetObjectItem(root, "a/b")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c%d"), cJSON_GetObjectItem(root, "c%d")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c^f"), cJSON_GetObjectItem(root, "c^f")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c|f"), cJSON_GetObjectItem(root, "c|f")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/i\\j"), cJSON_GetObjectItem(root, "i\\j")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/k\"l"), cJSON_GetObjectItem(root, "k\"l")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/ "), cJSON_GetObjectItem(root, " ")); - TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/m~0n"), cJSON_GetObjectItem(root, "m~n")); - - cJSON_Delete(root); -} - -static void misc_tests(void) -{ - /* Misc tests */ - int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - cJSON *object = NULL; - cJSON *nums = NULL; - cJSON *num6 = NULL; - char *pointer = NULL; - - printf("JSON Pointer construct\n"); - object = cJSON_CreateObject(); - nums = cJSON_CreateIntArray(numbers, 10); - num6 = cJSON_GetArrayItem(nums, 6); - cJSON_AddItemToObject(object, "numbers", nums); - - pointer = cJSONUtils_FindPointerFromObjectTo(object, num6); - TEST_ASSERT_EQUAL_STRING("/numbers/6", pointer); - free(pointer); - - pointer = cJSONUtils_FindPointerFromObjectTo(object, nums); - TEST_ASSERT_EQUAL_STRING("/numbers", pointer); - free(pointer); - - pointer = cJSONUtils_FindPointerFromObjectTo(object, object); - TEST_ASSERT_EQUAL_STRING("", pointer); - free(pointer); - - cJSON_Delete(object); -} - -static void sort_tests(void) -{ - /* Misc tests */ - const char *random = "QWERTYUIOPASDFGHJKLZXCVBNM"; - char buf[2] = {'\0', '\0'}; - cJSON *sortme = NULL; - size_t i = 0; - cJSON *current_element = NULL; - - /* JSON Sort test: */ - sortme = cJSON_CreateObject(); - for (i = 0; i < 26; i++) - { - buf[0] = random[i]; - cJSON_AddItemToObject(sortme, buf, cJSON_CreateNumber(1)); - } - - cJSONUtils_SortObject(sortme); - - /* check sorting */ - current_element = sortme->child->next; - for (i = 1; (i < 26) && (current_element != NULL) && (current_element->prev != NULL); i++) - { - TEST_ASSERT_TRUE(current_element->string[0] >= current_element->prev->string[0]); - current_element = current_element->next; - } - - cJSON_Delete(sortme); -} - -static void merge_tests(void) -{ - size_t i = 0; - char *patchtext = NULL; - char *after = NULL; - - /* Merge tests: */ - printf("JSON Merge Patch tests\n"); - for (i = 0; i < 15; i++) - { - cJSON *object_to_be_merged = cJSON_Parse(merges[i][0]); - cJSON *patch = cJSON_Parse(merges[i][1]); - patchtext = cJSON_PrintUnformatted(patch); - object_to_be_merged = cJSONUtils_MergePatch(object_to_be_merged, patch); - after = cJSON_PrintUnformatted(object_to_be_merged); - TEST_ASSERT_EQUAL_STRING(merges[i][2], after); - - free(patchtext); - free(after); - cJSON_Delete(object_to_be_merged); - cJSON_Delete(patch); - } -} - -static void generate_merge_tests(void) -{ - size_t i = 0; - char *patchedtext = NULL; - - /* Generate Merge tests: */ - for (i = 0; i < 15; i++) - { - cJSON *from = cJSON_Parse(merges[i][0]); - cJSON *to = cJSON_Parse(merges[i][2]); - cJSON *patch = cJSONUtils_GenerateMergePatch(from,to); - from = cJSONUtils_MergePatch(from,patch); - patchedtext = cJSON_PrintUnformatted(from); - TEST_ASSERT_EQUAL_STRING(merges[i][2], patchedtext); - - cJSON_Delete(from); - cJSON_Delete(to); - cJSON_Delete(patch); - free(patchedtext); - } -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(json_pointer_tests); - RUN_TEST(misc_tests); - RUN_TEST(sort_tests); - RUN_TEST(merge_tests); - RUN_TEST(generate_merge_tests); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_array.c b/components/cjson/cJSON/tests/parse_array.c deleted file mode 100644 index 69e0f4114..000000000 --- a/components/cjson/cJSON/tests/parse_array.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON item[1]; - -static void assert_is_array(cJSON *array_item) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(array_item, "Item is NULL."); - - assert_not_in_list(array_item); - assert_has_type(array_item, cJSON_Array); - assert_has_no_reference(array_item); - assert_has_no_const_string(array_item); - assert_has_no_valuestring(array_item); - assert_has_no_string(array_item); -} - -static void assert_not_array(const char *json) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*)json; - buffer.length = strlen(json) + sizeof(""); - buffer.hooks = global_hooks; - - TEST_ASSERT_FALSE(parse_array(item, &buffer)); - assert_is_invalid(item); -} - -static void assert_parse_array(const char *json) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*)json; - buffer.length = strlen(json) + sizeof(""); - buffer.hooks = global_hooks; - - TEST_ASSERT_TRUE(parse_array(item, &buffer)); - assert_is_array(item); -} - -static void parse_array_should_parse_empty_arrays(void) -{ - assert_parse_array("[]"); - assert_has_no_child(item); - - assert_parse_array("[\n\t]"); - assert_has_no_child(item); -} - - -static void parse_array_should_parse_arrays_with_one_element(void) -{ - - assert_parse_array("[1]"); - assert_has_child(item); - assert_has_type(item->child, cJSON_Number); - reset(item); - - assert_parse_array("[\"hello!\"]"); - assert_has_child(item); - assert_has_type(item->child, cJSON_String); - TEST_ASSERT_EQUAL_STRING("hello!", item->child->valuestring); - reset(item); - - assert_parse_array("[[]]"); - assert_has_child(item); - assert_is_array(item->child); - assert_has_no_child(item->child); - reset(item); - - assert_parse_array("[null]"); - assert_has_child(item); - assert_has_type(item->child, cJSON_NULL); - reset(item); -} - -static void parse_array_should_parse_arrays_with_multiple_elements(void) -{ - assert_parse_array("[1\t,\n2, 3]"); - assert_has_child(item); - TEST_ASSERT_NOT_NULL(item->child->next); - TEST_ASSERT_NOT_NULL(item->child->next->next); - TEST_ASSERT_NULL(item->child->next->next->next); - assert_has_type(item->child, cJSON_Number); - assert_has_type(item->child->next, cJSON_Number); - assert_has_type(item->child->next->next, cJSON_Number); - reset(item); - - { - size_t i = 0; - cJSON *node = NULL; - int expected_types[7] = - { - cJSON_Number, - cJSON_NULL, - cJSON_True, - cJSON_False, - cJSON_Array, - cJSON_String, - cJSON_Object - }; - assert_parse_array("[1, null, true, false, [], \"hello\", {}]"); - - node = item->child; - for ( - i = 0; - (i < (sizeof(expected_types)/sizeof(int))) - && (node != NULL); - (void)i++, node = node->next) - { - TEST_ASSERT_BITS(0xFF, expected_types[i], node->type); - } - TEST_ASSERT_EQUAL_INT(i, 7); - reset(item); - } -} - -static void parse_array_should_not_parse_non_arrays(void) -{ - assert_not_array(""); - assert_not_array("["); - assert_not_array("]"); - assert_not_array("{\"hello\":[]}"); - assert_not_array("42"); - assert_not_array("3.14"); - assert_not_array("\"[]hello world!\n\""); -} - -int main(void) -{ - /* initialize cJSON item */ - memset(item, 0, sizeof(cJSON)); - - UNITY_BEGIN(); - RUN_TEST(parse_array_should_parse_empty_arrays); - RUN_TEST(parse_array_should_parse_arrays_with_one_element); - RUN_TEST(parse_array_should_parse_arrays_with_multiple_elements); - RUN_TEST(parse_array_should_not_parse_non_arrays); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_examples.c b/components/cjson/cJSON/tests/parse_examples.c deleted file mode 100644 index 76215bbc9..000000000 --- a/components/cjson/cJSON/tests/parse_examples.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON *parse_file(const char *filename) -{ - cJSON *parsed = NULL; - char *content = read_file(filename); - - parsed = cJSON_Parse(content); - - if (content != NULL) - { - free(content); - } - - return parsed; -} - -static void do_test(const char *test_name) -{ - char *expected = NULL; - char *actual = NULL; - cJSON *tree = NULL; - - size_t test_name_length = 0; - /* path of the test input */ - char *test_path = NULL; - /* path of the expected output */ - char *expected_path = NULL; - - test_name_length = strlen(test_name); - - /* allocate file paths */ -#define TEST_DIR_PATH "inputs/" - test_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length); - TEST_ASSERT_NOT_NULL_MESSAGE(test_path, "Failed to allocate test_path buffer."); - expected_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length + sizeof(".expected")); - TEST_ASSERT_NOT_NULL_MESSAGE(expected_path, "Failed to allocate expected_path buffer."); - - /* create file paths */ - sprintf(test_path, TEST_DIR_PATH"%s", test_name); - sprintf(expected_path, TEST_DIR_PATH"%s.expected", test_name); - - /* read expected output */ - expected = read_file(expected_path); - TEST_ASSERT_NOT_NULL_MESSAGE(expected, "Failed to read expected output."); - - /* read and parse test */ - tree = parse_file(test_path); - TEST_ASSERT_NOT_NULL_MESSAGE(tree, "Failed to read of parse test."); - - /* print the parsed tree */ - actual = cJSON_Print(tree); - TEST_ASSERT_NOT_NULL_MESSAGE(actual, "Failed to print tree back to JSON."); - - - TEST_ASSERT_EQUAL_STRING(expected, actual); - - /* cleanup resources */ - if (expected != NULL) - { - free(expected); - } - if (tree != NULL) - { - cJSON_Delete(tree); - } - if (actual != NULL) - { - free(actual); - } - if (test_path != NULL) - { - free(test_path); - } - if (expected_path != NULL) - { - free(expected_path); - } -} - -static void file_test1_should_be_parsed_and_printed(void) -{ - do_test("test1"); -} - -static void file_test2_should_be_parsed_and_printed(void) -{ - do_test("test2"); -} - -static void file_test3_should_be_parsed_and_printed(void) -{ - do_test("test3"); -} - -static void file_test4_should_be_parsed_and_printed(void) -{ - do_test("test4"); -} - -static void file_test5_should_be_parsed_and_printed(void) -{ - do_test("test5"); -} - -static void file_test6_should_not_be_parsed(void) -{ - char *test6 = NULL; - cJSON *tree = NULL; - - test6 = read_file("inputs/test6"); - TEST_ASSERT_NOT_NULL_MESSAGE(test6, "Failed to read test6 data."); - - tree = cJSON_Parse(test6); - TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse what is not JSON."); - - TEST_ASSERT_EQUAL_PTR_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect."); - - if (test6 != NULL) - { - free(test6); - } - if (tree != NULL) - { - cJSON_Delete(tree); - } -} - -static void file_test7_should_be_parsed_and_printed(void) -{ - do_test("test7"); -} - -static void file_test8_should_be_parsed_and_printed(void) -{ - do_test("test8"); -} - -static void file_test9_should_be_parsed_and_printed(void) -{ - do_test("test9"); -} - -static void file_test10_should_be_parsed_and_printed(void) -{ - do_test("test10"); -} - -static void file_test11_should_be_parsed_and_printed(void) -{ - do_test("test11"); -} - -static void test12_should_not_be_parsed(void) -{ - const char *test12 = "{ \"name\": "; - cJSON *tree = NULL; - - tree = cJSON_Parse(test12); - TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse incomplete JSON."); - - TEST_ASSERT_EQUAL_PTR_MESSAGE(test12 + strlen(test12), cJSON_GetErrorPtr(), "Error pointer is incorrect."); - - if (tree != NULL) - { - cJSON_Delete(tree); - } -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(file_test1_should_be_parsed_and_printed); - RUN_TEST(file_test2_should_be_parsed_and_printed); - RUN_TEST(file_test3_should_be_parsed_and_printed); - RUN_TEST(file_test4_should_be_parsed_and_printed); - RUN_TEST(file_test5_should_be_parsed_and_printed); - RUN_TEST(file_test6_should_not_be_parsed); - RUN_TEST(file_test7_should_be_parsed_and_printed); - RUN_TEST(file_test8_should_be_parsed_and_printed); - RUN_TEST(file_test9_should_be_parsed_and_printed); - RUN_TEST(file_test10_should_be_parsed_and_printed); - RUN_TEST(file_test11_should_be_parsed_and_printed); - RUN_TEST(test12_should_not_be_parsed); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_hex4.c b/components/cjson/cJSON/tests/parse_hex4.c deleted file mode 100644 index 7115cbae9..000000000 --- a/components/cjson/cJSON/tests/parse_hex4.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void parse_hex4_should_parse_all_combinations(void) -{ - unsigned int number = 0; - unsigned char digits_lower[6]; - unsigned char digits_upper[6]; - /* test all combinations */ - for (number = 0; number <= 0xFFFF; number++) - { - TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_lower, "%.4x", number), "sprintf failed."); - TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_upper, "%.4X", number), "sprintf failed."); - - TEST_ASSERT_EQUAL_INT_MESSAGE(number, parse_hex4(digits_lower), "Failed to parse lowercase digits."); - TEST_ASSERT_EQUAL_INT_MESSAGE(number, parse_hex4(digits_upper), "Failed to parse uppercase digits."); - } -} - -static void parse_hex4_should_parse_mixed_case(void) -{ - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beef")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beeF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beEf")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beEF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEef")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEeF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEEf")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEEF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"Beef")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeeF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeEf")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeEF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEef")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEeF")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEf")); - TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEF")); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(parse_hex4_should_parse_all_combinations); - RUN_TEST(parse_hex4_should_parse_mixed_case); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_number.c b/components/cjson/cJSON/tests/parse_number.c deleted file mode 100644 index f499ab651..000000000 --- a/components/cjson/cJSON/tests/parse_number.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON item[1]; - -static void assert_is_number(cJSON *number_item) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(number_item, "Item is NULL."); - - assert_not_in_list(number_item); - assert_has_no_child(number_item); - assert_has_type(number_item, cJSON_Number); - assert_has_no_reference(number_item); - assert_has_no_const_string(number_item); - assert_has_no_valuestring(number_item); - assert_has_no_string(number_item); -} - -static void assert_parse_number(const char *string, int integer, double real) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*)string; - buffer.length = strlen(string) + sizeof(""); - - TEST_ASSERT_TRUE(parse_number(item, &buffer)); - assert_is_number(item); - TEST_ASSERT_EQUAL_INT(integer, item->valueint); - TEST_ASSERT_EQUAL_DOUBLE(real, item->valuedouble); -} - -static void parse_number_should_parse_zero(void) -{ - assert_parse_number("0", 0, 0); - assert_parse_number("0.0", 0, 0.0); - assert_parse_number("-0", 0, -0.0); -} - -static void parse_number_should_parse_negative_integers(void) -{ - assert_parse_number("-1", -1, -1); - assert_parse_number("-32768", -32768, -32768.0); - assert_parse_number("-2147483648", (int)-2147483648.0, -2147483648.0); -} - -static void parse_number_should_parse_positive_integers(void) -{ - assert_parse_number("1", 1, 1); - assert_parse_number("32767", 32767, 32767.0); - assert_parse_number("2147483647", (int)2147483647.0, 2147483647.0); -} - -static void parse_number_should_parse_positive_reals(void) -{ - assert_parse_number("0.001", 0, 0.001); - assert_parse_number("10e-10", 0, 10e-10); - assert_parse_number("10E-10", 0, 10e-10); - assert_parse_number("10e10", INT_MAX, 10e10); - assert_parse_number("123e+127", INT_MAX, 123e127); - assert_parse_number("123e-128", 0, 123e-128); -} - -static void parse_number_should_parse_negative_reals(void) -{ - assert_parse_number("-0.001", 0, -0.001); - assert_parse_number("-10e-10", 0, -10e-10); - assert_parse_number("-10E-10", 0, -10e-10); - assert_parse_number("-10e20", INT_MIN, -10e20); - assert_parse_number("-123e+127", INT_MIN, -123e127); - assert_parse_number("-123e-128", 0, -123e-128); -} - -int main(void) -{ - /* initialize cJSON item */ - memset(item, 0, sizeof(cJSON)); - UNITY_BEGIN(); - RUN_TEST(parse_number_should_parse_zero); - RUN_TEST(parse_number_should_parse_negative_integers); - RUN_TEST(parse_number_should_parse_positive_integers); - RUN_TEST(parse_number_should_parse_positive_reals); - RUN_TEST(parse_number_should_parse_negative_reals); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_object.c b/components/cjson/cJSON/tests/parse_object.c deleted file mode 100644 index 09858455a..000000000 --- a/components/cjson/cJSON/tests/parse_object.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON item[1]; - -static void assert_is_object(cJSON *object_item) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(object_item, "Item is NULL."); - - assert_not_in_list(object_item); - assert_has_type(object_item, cJSON_Object); - assert_has_no_reference(object_item); - assert_has_no_const_string(object_item); - assert_has_no_valuestring(object_item); - assert_has_no_string(object_item); -} - -static void assert_is_child(cJSON *child_item, const char *name, int type) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(child_item, "Child item is NULL."); - TEST_ASSERT_NOT_NULL_MESSAGE(child_item->string, "Child item doesn't have a name."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(name, child_item->string, "Child item has the wrong name."); - TEST_ASSERT_BITS(0xFF, type, child_item->type); -} - -static void assert_not_object(const char *json) -{ - parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - parsebuffer.content = (const unsigned char*)json; - parsebuffer.length = strlen(json) + sizeof(""); - parsebuffer.hooks = global_hooks; - - TEST_ASSERT_FALSE(parse_object(item, &parsebuffer)); - assert_is_invalid(item); - reset(item); -} - -static void assert_parse_object(const char *json) -{ - parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - parsebuffer.content = (const unsigned char*)json; - parsebuffer.length = strlen(json) + sizeof(""); - parsebuffer.hooks = global_hooks; - - TEST_ASSERT_TRUE(parse_object(item, &parsebuffer)); - assert_is_object(item); -} - -static void parse_object_should_parse_empty_objects(void) -{ - assert_parse_object("{}"); - assert_has_no_child(item); - reset(item); - - assert_parse_object("{\n\t}"); - assert_has_no_child(item); - reset(item); -} - -static void parse_object_should_parse_objects_with_one_element(void) -{ - - assert_parse_object("{\"one\":1}"); - assert_is_child(item->child, "one", cJSON_Number); - reset(item); - - assert_parse_object("{\"hello\":\"world!\"}"); - assert_is_child(item->child, "hello", cJSON_String); - reset(item); - - assert_parse_object("{\"array\":[]}"); - assert_is_child(item->child, "array", cJSON_Array); - reset(item); - - assert_parse_object("{\"null\":null}"); - assert_is_child(item->child, "null", cJSON_NULL); - reset(item); -} - -static void parse_object_should_parse_objects_with_multiple_elements(void) -{ - assert_parse_object("{\"one\":1\t,\t\"two\"\n:2, \"three\":3}"); - assert_is_child(item->child, "one", cJSON_Number); - assert_is_child(item->child->next, "two", cJSON_Number); - assert_is_child(item->child->next->next, "three", cJSON_Number); - reset(item); - - { - size_t i = 0; - cJSON *node = NULL; - int expected_types[7] = - { - cJSON_Number, - cJSON_NULL, - cJSON_True, - cJSON_False, - cJSON_Array, - cJSON_String, - cJSON_Object - }; - const char *expected_names[7] = - { - "one", - "NULL", - "TRUE", - "FALSE", - "array", - "world", - "object" - }; - assert_parse_object("{\"one\":1, \"NULL\":null, \"TRUE\":true, \"FALSE\":false, \"array\":[], \"world\":\"hello\", \"object\":{}}"); - - node = item->child; - for ( - i = 0; - (i < (sizeof(expected_types)/sizeof(int))) - && (node != NULL); - (void)i++, node = node->next) - { - assert_is_child(node, expected_names[i], expected_types[i]); - } - TEST_ASSERT_EQUAL_INT(i, 7); - reset(item); - } -} - -static void parse_object_should_not_parse_non_objects(void) -{ - assert_not_object(""); - assert_not_object("{"); - assert_not_object("}"); - assert_not_object("[\"hello\",{}]"); - assert_not_object("42"); - assert_not_object("3.14"); - assert_not_object("\"{}hello world!\n\""); -} - -int main(void) -{ - /* initialize cJSON item */ - memset(item, 0, sizeof(cJSON)); - - UNITY_BEGIN(); - RUN_TEST(parse_object_should_parse_empty_objects); - RUN_TEST(parse_object_should_not_parse_non_objects); - RUN_TEST(parse_object_should_parse_objects_with_multiple_elements); - RUN_TEST(parse_object_should_parse_objects_with_one_element); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_string.c b/components/cjson/cJSON/tests/parse_string.c deleted file mode 100644 index ceb1a8960..000000000 --- a/components/cjson/cJSON/tests/parse_string.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON item[1]; - -static void assert_is_string(cJSON *string_item) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(string_item, "Item is NULL."); - - assert_not_in_list(string_item); - assert_has_no_child(string_item); - assert_has_type(string_item, cJSON_String); - assert_has_no_reference(string_item); - assert_has_no_const_string(string_item); - assert_has_valuestring(string_item); - assert_has_no_string(string_item); -} - -static void assert_parse_string(const char *string, const char *expected) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*)string; - buffer.length = strlen(string) + sizeof(""); - buffer.hooks = global_hooks; - - TEST_ASSERT_TRUE_MESSAGE(parse_string(item, &buffer), "Couldn't parse string."); - assert_is_string(item); - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected."); - global_hooks.deallocate(item->valuestring); - item->valuestring = NULL; -} - -static void assert_not_parse_string(const char * const string) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*)string; - buffer.length = strlen(string) + sizeof(""); - buffer.hooks = global_hooks; - - TEST_ASSERT_FALSE_MESSAGE(parse_string(item, &buffer), "Malformed string should not be accepted."); - assert_is_invalid(item); -} - - - -static void parse_string_should_parse_strings(void) -{ - assert_parse_string("\"\"", ""); - assert_parse_string( - "\" !\\\"#$%&'()*+,-./\\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\"", - " !\"#$%&'()*+,-.//0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~"); - assert_parse_string( - "\"\\\"\\\\\\/\\b\\f\\n\\r\\t\\u20AC\\u732b\"", - "\"\\/\b\f\n\r\t€猫"); - reset(item); - assert_parse_string("\"\b\f\n\r\t\"", "\b\f\n\r\t"); - reset(item); -} - -static void parse_string_should_parse_utf16_surrogate_pairs(void) -{ - assert_parse_string("\"\\uD83D\\udc31\"", "🐱"); - reset(item); -} - -static void parse_string_should_not_parse_non_strings(void) -{ - assert_not_parse_string("this\" is not a string\""); - reset(item); - assert_not_parse_string(""); - reset(item); -} - -static void parse_string_should_not_parse_invalid_backslash(void) -{ - assert_not_parse_string("Abcdef\\123"); - reset(item); - assert_not_parse_string("Abcdef\\e23"); - reset(item); -} - -static void parse_string_should_not_overflow_with_closing_backslash(void) -{ - assert_not_parse_string("\"000000000000000000\\"); - reset(item); -} - -static void parse_string_should_parse_bug_94(void) -{ - const char string[] = "\"~!@\\\\#$%^&*()\\\\\\\\-\\\\+{}[]:\\\\;\\\\\\\"\\\\<\\\\>?/.,DC=ad,DC=com\""; - assert_parse_string(string, "~!@\\#$%^&*()\\\\-\\+{}[]:\\;\\\"\\<\\>?/.,DC=ad,DC=com"); - reset(item); -} - -int main(void) -{ - /* initialize cJSON item and error pointer */ - memset(item, 0, sizeof(cJSON)); - - UNITY_BEGIN(); - RUN_TEST(parse_string_should_parse_strings); - RUN_TEST(parse_string_should_parse_utf16_surrogate_pairs); - RUN_TEST(parse_string_should_not_parse_non_strings); - RUN_TEST(parse_string_should_not_parse_invalid_backslash); - RUN_TEST(parse_string_should_parse_bug_94); - RUN_TEST(parse_string_should_not_overflow_with_closing_backslash); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_value.c b/components/cjson/cJSON/tests/parse_value.c deleted file mode 100644 index 08ec3e7a2..000000000 --- a/components/cjson/cJSON/tests/parse_value.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static cJSON item[1]; - -static void assert_is_value(cJSON *value_item, int type) -{ - TEST_ASSERT_NOT_NULL_MESSAGE(value_item, "Item is NULL."); - - assert_not_in_list(value_item); - assert_has_type(value_item, type); - assert_has_no_reference(value_item); - assert_has_no_const_string(value_item); - assert_has_no_string(value_item); -} - -static void assert_parse_value(const char *string, int type) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.content = (const unsigned char*) string; - buffer.length = strlen(string) + sizeof(""); - buffer.hooks = global_hooks; - - TEST_ASSERT_TRUE(parse_value(item, &buffer)); - assert_is_value(item, type); -} - -static void parse_value_should_parse_null(void) -{ - assert_parse_value("null", cJSON_NULL); - reset(item); -} - -static void parse_value_should_parse_true(void) -{ - assert_parse_value("true", cJSON_True); - reset(item); -} - -static void parse_value_should_parse_false(void) -{ - assert_parse_value("false", cJSON_False); - reset(item); -} - -static void parse_value_should_parse_number(void) -{ - assert_parse_value("1.5", cJSON_Number); - reset(item); -} - -static void parse_value_should_parse_string(void) -{ - assert_parse_value("\"\"", cJSON_String); - reset(item); - assert_parse_value("\"hello\"", cJSON_String); - reset(item); -} - -static void parse_value_should_parse_array(void) -{ - assert_parse_value("[]", cJSON_Array); - reset(item); -} - -static void parse_value_should_parse_object(void) -{ - assert_parse_value("{}", cJSON_Object); - reset(item); -} - -int main(void) -{ - /* initialize cJSON item */ - memset(item, 0, sizeof(cJSON)); - UNITY_BEGIN(); - RUN_TEST(parse_value_should_parse_null); - RUN_TEST(parse_value_should_parse_true); - RUN_TEST(parse_value_should_parse_false); - RUN_TEST(parse_value_should_parse_number); - RUN_TEST(parse_value_should_parse_string); - RUN_TEST(parse_value_should_parse_array); - RUN_TEST(parse_value_should_parse_object); - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/parse_with_opts.c b/components/cjson/cJSON/tests/parse_with_opts.c deleted file mode 100644 index 84b69cfc9..000000000 --- a/components/cjson/cJSON/tests/parse_with_opts.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void parse_with_opts_should_handle_null(void) -{ - const char *error_pointer = NULL; - cJSON *item = NULL; - TEST_ASSERT_NULL_MESSAGE(cJSON_ParseWithOpts(NULL, &error_pointer, false), "Failed to handle NULL input."); - item = cJSON_ParseWithOpts("{}", NULL, false); - TEST_ASSERT_NOT_NULL_MESSAGE(item, "Failed to handle NULL error pointer."); - cJSON_Delete(item); - TEST_ASSERT_NULL_MESSAGE(cJSON_ParseWithOpts(NULL, NULL, false), "Failed to handle both NULL."); - TEST_ASSERT_NULL_MESSAGE(cJSON_ParseWithOpts("{", NULL, false), "Failed to handle NULL error pointer with parse error."); -} - -static void parse_with_opts_should_handle_empty_strings(void) -{ - const char empty_string[] = ""; - const char *error_pointer = NULL; - - TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, NULL, false)); - TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr()); - - TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, &error_pointer, false)); - TEST_ASSERT_EQUAL_PTR(empty_string, error_pointer); - TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr()); -} - -static void parse_with_opts_should_handle_incomplete_json(void) -{ - const char json[] = "{ \"name\": "; - const char *parse_end = NULL; - - TEST_ASSERT_NULL(cJSON_ParseWithOpts(json, &parse_end, false)); - TEST_ASSERT_EQUAL_PTR(json + strlen(json), parse_end); - TEST_ASSERT_EQUAL_PTR(json + strlen(json), cJSON_GetErrorPtr()); -} - -static void parse_with_opts_should_require_null_if_requested(void) -{ - cJSON *item = cJSON_ParseWithOpts("{}", NULL, true); - TEST_ASSERT_NOT_NULL(item); - cJSON_Delete(item); - item = cJSON_ParseWithOpts("{} \n", NULL, true); - TEST_ASSERT_NOT_NULL(item); - cJSON_Delete(item); - TEST_ASSERT_NULL(cJSON_ParseWithOpts("{}x", NULL, true)); -} - -static void parse_with_opts_should_return_parse_end(void) -{ - const char json[] = "[] empty array XD"; - const char *parse_end = NULL; - - cJSON *item = cJSON_ParseWithOpts(json, &parse_end, false); - TEST_ASSERT_NOT_NULL(item); - TEST_ASSERT_EQUAL_PTR(json + 2, parse_end); - cJSON_Delete(item); -} - -static void parse_with_opts_should_parse_utf8_bom(void) -{ - cJSON *with_bom = NULL; - cJSON *without_bom = NULL; - - with_bom = cJSON_ParseWithOpts("\xEF\xBB\xBF{}", NULL, true); - TEST_ASSERT_NOT_NULL(with_bom); - without_bom = cJSON_ParseWithOpts("{}", NULL, true); - TEST_ASSERT_NOT_NULL(with_bom); - - TEST_ASSERT_TRUE(cJSON_Compare(with_bom, without_bom, true)); - - cJSON_Delete(with_bom); - cJSON_Delete(without_bom); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(parse_with_opts_should_handle_null); - RUN_TEST(parse_with_opts_should_handle_empty_strings); - RUN_TEST(parse_with_opts_should_handle_incomplete_json); - RUN_TEST(parse_with_opts_should_require_null_if_requested); - RUN_TEST(parse_with_opts_should_return_parse_end); - RUN_TEST(parse_with_opts_should_parse_utf8_bom); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/print_array.c b/components/cjson/cJSON/tests/print_array.c deleted file mode 100644 index 4bee17f96..000000000 --- a/components/cjson/cJSON/tests/print_array.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void assert_print_array(const char * const expected, const char * const input) -{ - unsigned char printed_unformatted[1024]; - unsigned char printed_formatted[1024]; - - cJSON item[1]; - - printbuffer formatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - parsebuffer.content = (const unsigned char*)input; - parsebuffer.length = strlen(input) + sizeof(""); - parsebuffer.hooks = global_hooks; - - /* buffer for formatted printing */ - formatted_buffer.buffer = printed_formatted; - formatted_buffer.length = sizeof(printed_formatted); - formatted_buffer.offset = 0; - formatted_buffer.noalloc = true; - formatted_buffer.hooks = global_hooks; - - /* buffer for unformatted printing */ - unformatted_buffer.buffer = printed_unformatted; - unformatted_buffer.length = sizeof(printed_unformatted); - unformatted_buffer.offset = 0; - unformatted_buffer.noalloc = true; - unformatted_buffer.hooks = global_hooks; - - memset(item, 0, sizeof(item)); - TEST_ASSERT_TRUE_MESSAGE(parse_array(item, &parsebuffer), "Failed to parse array."); - - unformatted_buffer.format = false; - TEST_ASSERT_TRUE_MESSAGE(print_array(item, &unformatted_buffer), "Failed to print unformatted string."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted array is not correct."); - - formatted_buffer.format = true; - TEST_ASSERT_TRUE_MESSAGE(print_array(item, &formatted_buffer), "Failed to print formatted string."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted array is not correct."); - - reset(item); -} - -static void print_array_should_print_empty_arrays(void) -{ - assert_print_array("[]", "[]"); -} - -static void print_array_should_print_arrays_with_one_element(void) -{ - - assert_print_array("[1]", "[1]"); - assert_print_array("[\"hello!\"]", "[\"hello!\"]"); - assert_print_array("[[]]", "[[]]"); - assert_print_array("[null]", "[null]"); -} - -static void print_array_should_print_arrays_with_multiple_elements(void) -{ - assert_print_array("[1, 2, 3]", "[1,2,3]"); - assert_print_array("[1, null, true, false, [], \"hello\", {\n\t}]", "[1,null,true,false,[],\"hello\",{}]"); -} - -int main(void) -{ - /* initialize cJSON item */ - UNITY_BEGIN(); - - RUN_TEST(print_array_should_print_empty_arrays); - RUN_TEST(print_array_should_print_arrays_with_one_element); - RUN_TEST(print_array_should_print_arrays_with_multiple_elements); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/print_number.c b/components/cjson/cJSON/tests/print_number.c deleted file mode 100644 index 5ebb34897..000000000 --- a/components/cjson/cJSON/tests/print_number.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void assert_print_number(const char *expected, double input) -{ - unsigned char printed[1024]; - cJSON item[1]; - printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.buffer = printed; - buffer.length = sizeof(printed); - buffer.offset = 0; - buffer.noalloc = true; - buffer.hooks = global_hooks; - - memset(item, 0, sizeof(item)); - cJSON_SetNumberValue(item, input); - - TEST_ASSERT_TRUE_MESSAGE(print_number(item, &buffer), "Failed to print number."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, buffer.buffer, "Printed number is not as expected."); -} - -static void print_number_should_print_zero(void) -{ - assert_print_number("0", 0); -} - -static void print_number_should_print_negative_integers(void) -{ - assert_print_number("-1", -1.0); - assert_print_number("-32768", -32768.0); - assert_print_number("-2147483648", -2147483648.0); -} - -static void print_number_should_print_positive_integers(void) -{ - assert_print_number("1", 1.0); - assert_print_number("32767", 32767.0); - assert_print_number("2147483647", 2147483647.0); -} - -static void print_number_should_print_positive_reals(void) -{ - assert_print_number("0.123", 0.123); - assert_print_number("1e-09", 10e-10); - assert_print_number("1000000000000", 10e11); - assert_print_number("1.23e+129", 123e+127); - assert_print_number("1.23e-126", 123e-128); - assert_print_number("3.1415926535897931", 3.1415926535897931); -} - -static void print_number_should_print_negative_reals(void) -{ - assert_print_number("-0.0123", -0.0123); - assert_print_number("-1e-09", -10e-10); - assert_print_number("-1e+21", -10e20); - assert_print_number("-1.23e+129", -123e+127); - assert_print_number("-1.23e-126", -123e-128); -} - -static void print_number_should_print_non_number(void) -{ - TEST_IGNORE(); - /* FIXME: Cannot test this easily in C89! */ - /* assert_print_number("null", NaN); */ - /* assert_print_number("null", INFTY); */ - /* assert_print_number("null", -INFTY); */ -} - -int main(void) -{ - /* initialize cJSON item */ - UNITY_BEGIN(); - - RUN_TEST(print_number_should_print_zero); - RUN_TEST(print_number_should_print_negative_integers); - RUN_TEST(print_number_should_print_positive_integers); - RUN_TEST(print_number_should_print_positive_reals); - RUN_TEST(print_number_should_print_negative_reals); - RUN_TEST(print_number_should_print_non_number); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/print_object.c b/components/cjson/cJSON/tests/print_object.c deleted file mode 100644 index 70bbb43ce..000000000 --- a/components/cjson/cJSON/tests/print_object.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void assert_print_object(const char * const expected, const char * const input) -{ - unsigned char printed_unformatted[1024]; - unsigned char printed_formatted[1024]; - - cJSON item[1]; - - printbuffer formatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - - /* buffer for parsing */ - parsebuffer.content = (const unsigned char*)input; - parsebuffer.length = strlen(input) + sizeof(""); - parsebuffer.hooks = global_hooks; - - /* buffer for formatted printing */ - formatted_buffer.buffer = printed_formatted; - formatted_buffer.length = sizeof(printed_formatted); - formatted_buffer.offset = 0; - formatted_buffer.noalloc = true; - formatted_buffer.hooks = global_hooks; - - /* buffer for unformatted printing */ - unformatted_buffer.buffer = printed_unformatted; - unformatted_buffer.length = sizeof(printed_unformatted); - unformatted_buffer.offset = 0; - unformatted_buffer.noalloc = true; - unformatted_buffer.hooks = global_hooks; - - memset(item, 0, sizeof(item)); - TEST_ASSERT_TRUE_MESSAGE(parse_object(item, &parsebuffer), "Failed to parse object."); - - unformatted_buffer.format = false; - TEST_ASSERT_TRUE_MESSAGE(print_object(item, &unformatted_buffer), "Failed to print unformatted string."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted object is not correct."); - - formatted_buffer.format = true; - TEST_ASSERT_TRUE_MESSAGE(print_object(item, &formatted_buffer), "Failed to print formatted string."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted ojbect is not correct."); - - reset(item); -} - -static void print_object_should_print_empty_objects(void) -{ - assert_print_object("{\n}", "{}"); -} - -static void print_object_should_print_objects_with_one_element(void) -{ - - assert_print_object("{\n\t\"one\":\t1\n}", "{\"one\":1}"); - assert_print_object("{\n\t\"hello\":\t\"world!\"\n}", "{\"hello\":\"world!\"}"); - assert_print_object("{\n\t\"array\":\t[]\n}", "{\"array\":[]}"); - assert_print_object("{\n\t\"null\":\tnull\n}", "{\"null\":null}"); -} - -static void print_object_should_print_objects_with_multiple_elements(void) -{ - assert_print_object("{\n\t\"one\":\t1,\n\t\"two\":\t2,\n\t\"three\":\t3\n}", "{\"one\":1,\"two\":2,\"three\":3}"); - assert_print_object("{\n\t\"one\":\t1,\n\t\"NULL\":\tnull,\n\t\"TRUE\":\ttrue,\n\t\"FALSE\":\tfalse,\n\t\"array\":\t[],\n\t\"world\":\t\"hello\",\n\t\"object\":\t{\n\t}\n}", "{\"one\":1,\"NULL\":null,\"TRUE\":true,\"FALSE\":false,\"array\":[],\"world\":\"hello\",\"object\":{}}"); -} - -int main(void) -{ - /* initialize cJSON item */ - UNITY_BEGIN(); - - RUN_TEST(print_object_should_print_empty_objects); - RUN_TEST(print_object_should_print_objects_with_one_element); - RUN_TEST(print_object_should_print_objects_with_multiple_elements); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/print_string.c b/components/cjson/cJSON/tests/print_string.c deleted file mode 100644 index 83de1e7a5..000000000 --- a/components/cjson/cJSON/tests/print_string.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void assert_print_string(const char *expected, const char *input) -{ - unsigned char printed[1024]; - printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.buffer = printed; - buffer.length = sizeof(printed); - buffer.offset = 0; - buffer.noalloc = true; - buffer.hooks = global_hooks; - - TEST_ASSERT_TRUE_MESSAGE(print_string_ptr((const unsigned char*)input, &buffer), "Failed to print string."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed, "The printed string isn't as expected."); -} - -static void print_string_should_print_empty_strings(void) -{ - assert_print_string("\"\"", ""); - assert_print_string("\"\"", NULL); -} - -static void print_string_should_print_ascii(void) -{ - char ascii[0x7F]; - size_t i = 1; - - /* create ascii table */ - for (i = 1; i < 0x7F; i++) - { - ascii[i-1] = (char)i; - } - ascii[0x7F-1] = '\0'; - - assert_print_string("\"\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"", - ascii); -} - -static void print_string_should_print_utf8(void) -{ - assert_print_string("\"ü猫慕\"", "ü猫慕"); -} - -int main(void) -{ - /* initialize cJSON item */ - UNITY_BEGIN(); - - RUN_TEST(print_string_should_print_empty_strings); - RUN_TEST(print_string_should_print_ascii); - RUN_TEST(print_string_should_print_utf8); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/print_value.c b/components/cjson/cJSON/tests/print_value.c deleted file mode 100644 index d5908232c..000000000 --- a/components/cjson/cJSON/tests/print_value.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static void assert_print_value(const char *input) -{ - unsigned char printed[1024]; - cJSON item[1]; - printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - parse_buffer parsebuffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - buffer.buffer = printed; - buffer.length = sizeof(printed); - buffer.offset = 0; - buffer.noalloc = true; - buffer.hooks = global_hooks; - - parsebuffer.content = (const unsigned char*)input; - parsebuffer.length = strlen(input) + sizeof(""); - parsebuffer.hooks = global_hooks; - - memset(item, 0, sizeof(item)); - - TEST_ASSERT_TRUE_MESSAGE(parse_value(item, &parsebuffer), "Failed to parse value."); - - TEST_ASSERT_TRUE_MESSAGE(print_value(item, &buffer), "Failed to print value."); - TEST_ASSERT_EQUAL_STRING_MESSAGE(input, buffer.buffer, "Printed value is not as expected."); - - reset(item); -} - -static void print_value_should_print_null(void) -{ - assert_print_value("null"); -} - -static void print_value_should_print_true(void) -{ - assert_print_value("true"); -} - -static void print_value_should_print_false(void) -{ - assert_print_value("false"); -} - -static void print_value_should_print_number(void) -{ - assert_print_value("1.5"); -} - -static void print_value_should_print_string(void) -{ - assert_print_value("\"\""); - assert_print_value("\"hello\""); -} - -static void print_value_should_print_array(void) -{ - assert_print_value("[]"); -} - -static void print_value_should_print_object(void) -{ - assert_print_value("{}"); -} - -int main(void) -{ - /* initialize cJSON item */ - UNITY_BEGIN(); - - RUN_TEST(print_value_should_print_null); - RUN_TEST(print_value_should_print_true); - RUN_TEST(print_value_should_print_false); - RUN_TEST(print_value_should_print_number); - RUN_TEST(print_value_should_print_string); - RUN_TEST(print_value_should_print_array); - RUN_TEST(print_value_should_print_object); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/readme_examples.c b/components/cjson/cJSON/tests/readme_examples.c deleted file mode 100644 index f3fa44381..000000000 --- a/components/cjson/cJSON/tests/readme_examples.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#include "unity/examples/unity_config.h" -#include "unity/src/unity.h" -#include "common.h" - -static const char *json = "{\n\ -\t\"name\":\t\"Awesome 4K\",\n\ -\t\"resolutions\":\t[{\n\ -\t\t\t\"width\":\t1280,\n\ -\t\t\t\"height\":\t720\n\ -\t\t}, {\n\ -\t\t\t\"width\":\t1920,\n\ -\t\t\t\"height\":\t1080\n\ -\t\t}, {\n\ -\t\t\t\"width\":\t3840,\n\ -\t\t\t\"height\":\t2160\n\ -\t\t}]\n\ -}"; - -static char* create_monitor(void) -{ - const unsigned int resolution_numbers[3][2] = { - {1280, 720}, - {1920, 1080}, - {3840, 2160} - }; - char *string = NULL; - cJSON *name = NULL; - cJSON *resolutions = NULL; - cJSON *resolution = NULL; - cJSON *width = NULL; - cJSON *height = NULL; - size_t index = 0; - - cJSON *monitor = cJSON_CreateObject(); - if (monitor == NULL) - { - goto end; - } - - name = cJSON_CreateString("Awesome 4K"); - if (name == NULL) - { - goto end; - } - /* after creation was successful, immediately add it to the monitor, - * thereby transfering ownership of the pointer to it */ - cJSON_AddItemToObject(monitor, "name", name); - - resolutions = cJSON_CreateArray(); - if (resolutions == NULL) - { - goto end; - } - cJSON_AddItemToObject(monitor, "resolutions", resolutions); - - for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index) - { - resolution = cJSON_CreateObject(); - if (resolution == NULL) - { - goto end; - } - cJSON_AddItemToArray(resolutions, resolution); - - width = cJSON_CreateNumber(resolution_numbers[index][0]); - if (width == NULL) - { - goto end; - } - cJSON_AddItemToObject(resolution, "width", width); - - height = cJSON_CreateNumber(resolution_numbers[index][1]); - if (height == NULL) - { - goto end; - } - cJSON_AddItemToObject(resolution, "height", height); - } - - string = cJSON_Print(monitor); - if (string == NULL) - { - fprintf(stderr, "Failed to print monitor.\n"); - } - -end: - cJSON_Delete(monitor); - return string; -} - -static char *create_monitor_with_helpers(void) -{ - const unsigned int resolution_numbers[3][2] = { - {1280, 720}, - {1920, 1080}, - {3840, 2160} - }; - char *string = NULL; - cJSON *resolutions = NULL; - size_t index = 0; - - cJSON *monitor = cJSON_CreateObject(); - - if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL) - { - goto end; - } - - resolutions = cJSON_AddArrayToObject(monitor, "resolutions"); - if (resolutions == NULL) - { - goto end; - } - - for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index) - { - cJSON *resolution = cJSON_CreateObject(); - - if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL) - { - goto end; - } - - if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL) - { - goto end; - } - - cJSON_AddItemToArray(resolutions, resolution); - } - - string = cJSON_Print(monitor); - if (string == NULL) { - fprintf(stderr, "Failed to print monitor.\n"); - } - -end: - cJSON_Delete(monitor); - return string; -} - -/* return 1 if the monitor supports full hd, 0 otherwise */ -static int supports_full_hd(const char * const monitor) -{ - const cJSON *resolution = NULL; - const cJSON *resolutions = NULL; - const cJSON *name = NULL; - int status = 0; - cJSON *monitor_json = cJSON_Parse(monitor); - if (monitor_json == NULL) - { - const char *error_ptr = cJSON_GetErrorPtr(); - if (error_ptr != NULL) - { - fprintf(stderr, "Error before: %s\n", error_ptr); - } - status = 0; - goto end; - } - - name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name"); - if (cJSON_IsString(name) && (name->valuestring != NULL)) - { - printf("Checking monitor \"%s\"\n", name->valuestring); - } - - resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions"); - cJSON_ArrayForEach(resolution, resolutions) - { - cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width"); - cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height"); - - if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height)) - { - status = 0; - goto end; - } - - if ((width->valuedouble == 1920) && (height->valuedouble == 1080)) - { - status = 1; - goto end; - } - } - -end: - cJSON_Delete(monitor_json); - return status; -} - -static void create_monitor_should_create_a_monitor(void) -{ - char *monitor = create_monitor(); - - TEST_ASSERT_EQUAL_STRING(monitor, json); - - free(monitor); -} - -static void create_monitor_with_helpers_should_create_a_monitor(void) -{ - char *monitor = create_monitor_with_helpers(); - - TEST_ASSERT_EQUAL_STRING(json, monitor); - - free(monitor); -} - -static void supports_full_hd_should_check_for_full_hd_support(void) -{ - static const char *monitor_without_hd = "{\n\ -\t\t\"name\": \"lame monitor\",\n\ -\t\t\"resolutions\":\t[{\n\ -\t\t\t\"width\":\t640,\n\ -\t\t\t\"height\":\t480\n\ -\t\t}]\n\ -}"; - - TEST_ASSERT(supports_full_hd(json)); - TEST_ASSERT_FALSE(supports_full_hd(monitor_without_hd)); -} - -int main(void) -{ - UNITY_BEGIN(); - - RUN_TEST(create_monitor_should_create_a_monitor); - RUN_TEST(create_monitor_with_helpers_should_create_a_monitor); - RUN_TEST(supports_full_hd_should_check_for_full_hd_support); - - return UNITY_END(); -} diff --git a/components/cjson/cJSON/tests/unity/.gitattributes b/components/cjson/cJSON/tests/unity/.gitattributes deleted file mode 100644 index ad952260b..000000000 --- a/components/cjson/cJSON/tests/unity/.gitattributes +++ /dev/null @@ -1,30 +0,0 @@ -* text=auto - -# These files are text and should be normalized (convert crlf to lf) -*.rb text -*.test text -*.c text -*.cpp text -*.h text -*.txt text -*.yml text -*.s79 text -*.bat text -*.xcl text -*.inc text -*.info text -*.md text -makefile text -rakefile text - - -#These files are binary and should not be normalized -*.doc binary -*.odt binary -*.pdf binary -*.ewd binary -*.eww binary -*.dni binary -*.wsdt binary -*.dbgdt binary -*.mac binary diff --git a/components/cjson/cJSON/tests/unity/.gitignore b/components/cjson/cJSON/tests/unity/.gitignore deleted file mode 100644 index a383c3ccb..000000000 --- a/components/cjson/cJSON/tests/unity/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -build/ -test/sandbox -.DS_Store -examples/example_1/test1.exe -examples/example_1/test2.exe -examples/example_2/all_tests.exe -examples/example_1/test1.out -examples/example_1/test2.out -examples/example_2/all_tests.out diff --git a/components/cjson/cJSON/tests/unity/.travis.yml b/components/cjson/cJSON/tests/unity/.travis.yml deleted file mode 100644 index bd165b1e7..000000000 --- a/components/cjson/cJSON/tests/unity/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: c - -matrix: - include: - - os: osx - compiler: clang - osx_image: xcode7.3 - - os: linux - dist: trusty - compiler: gcc - -before_install: - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then rvm install 2.1 && rvm use 2.1 && ruby -v; fi - - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi -install: - - gem install rspec - - gem install rubocop -script: - - cd test && rake ci - - make -s - - make -s DEBUG=-m32 #32-bit architecture with 64-bit support - - make -s DEBUG=-m32 UNITY_SUPPORT_64= #32-bit build without 64-bit types - - make -s UNITY_INCLUDE_DOUBLE= # without double - - cd ../extras/fixture/test && rake ci - - make -s default noStdlibMalloc - - make -s C89 - - cd ../../../examples/example_1 && make -s ci - - cd ../example_2 && make -s ci - - cd ../example_3 && rake diff --git a/components/cjson/cJSON/tests/unity/README.md b/components/cjson/cJSON/tests/unity/README.md deleted file mode 100644 index ec73b4a1b..000000000 --- a/components/cjson/cJSON/tests/unity/README.md +++ /dev/null @@ -1,231 +0,0 @@ -Unity Test API -============== - -[![Unity Build Status](https://api.travis-ci.org/ThrowTheSwitch/Unity.png?branch=master)](https://travis-ci.org/ThrowTheSwitch/Unity) -__Copyright (c) 2007 - 2017 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__ - -Running Tests -------------- - - RUN_TEST(func, linenum) - -Each Test is run within the macro `RUN_TEST`. This macro performs necessary setup before the test is called and handles cleanup and result tabulation afterwards. - -Ignoring Tests --------------- - -There are times when a test is incomplete or not valid for some reason. At these times, TEST_IGNORE can be called. Control will immediately be returned to the caller of the test, and no failures will be returned. - - TEST_IGNORE() - -Ignore this test and return immediately - - TEST_IGNORE_MESSAGE (message) - -Ignore this test and return immediately. Output a message stating why the test was ignored. - -Aborting Tests --------------- - -There are times when a test will contain an infinite loop on error conditions, or there may be reason to escape from the test early without executing the rest of the test. A pair of macros support this functionality in Unity. The first `TEST_PROTECT` sets up the feature, and handles emergency abort cases. `TEST_ABORT` can then be used at any time within the tests to return to the last `TEST_PROTECT` call. - - TEST_PROTECT() - -Setup and Catch macro - - TEST_ABORT() - -Abort Test macro - -Example: - - main() - { - if (TEST_PROTECT()) - { - MyTest(); - } - } - -If MyTest calls `TEST_ABORT`, program control will immediately return to `TEST_PROTECT` with a return value of zero. - - -Unity Assertion Summary -======================= - -Basic Validity Tests --------------------- - - TEST_ASSERT_TRUE(condition) - -Evaluates whatever code is in condition and fails if it evaluates to false - - TEST_ASSERT_FALSE(condition) - -Evaluates whatever code is in condition and fails if it evaluates to true - - TEST_ASSERT(condition) - -Another way of calling `TEST_ASSERT_TRUE` - - TEST_ASSERT_UNLESS(condition) - -Another way of calling `TEST_ASSERT_FALSE` - - TEST_FAIL() - TEST_FAIL_MESSAGE(message) - -This test is automatically marked as a failure. The message is output stating why. - -Numerical Assertions: Integers ------------------------------- - - TEST_ASSERT_EQUAL_INT(expected, actual) - TEST_ASSERT_EQUAL_INT8(expected, actual) - TEST_ASSERT_EQUAL_INT16(expected, actual) - TEST_ASSERT_EQUAL_INT32(expected, actual) - TEST_ASSERT_EQUAL_INT64(expected, actual) - -Compare two integers for equality and display errors as signed integers. A cast will be performed -to your natural integer size so often this can just be used. When you need to specify the exact size, -like when comparing arrays, you can use a specific version: - - TEST_ASSERT_EQUAL_UINT(expected, actual) - TEST_ASSERT_EQUAL_UINT8(expected, actual) - TEST_ASSERT_EQUAL_UINT16(expected, actual) - TEST_ASSERT_EQUAL_UINT32(expected, actual) - TEST_ASSERT_EQUAL_UINT64(expected, actual) - -Compare two integers for equality and display errors as unsigned integers. Like INT, there are -variants for different sizes also. - - TEST_ASSERT_EQUAL_HEX(expected, actual) - TEST_ASSERT_EQUAL_HEX8(expected, actual) - TEST_ASSERT_EQUAL_HEX16(expected, actual) - TEST_ASSERT_EQUAL_HEX32(expected, actual) - TEST_ASSERT_EQUAL_HEX64(expected, actual) - -Compares two integers for equality and display errors as hexadecimal. Like the other integer comparisons, -you can specify the size... here the size will also effect how many nibbles are shown (for example, `HEX16` -will show 4 nibbles). - - TEST_ASSERT_EQUAL(expected, actual) - -Another way of calling TEST_ASSERT_EQUAL_INT - - TEST_ASSERT_INT_WITHIN(delta, expected, actual) - -Asserts that the actual value is within plus or minus delta of the expected value. This also comes in -size specific variants. - - - TEST_ASSERT_GREATER_THAN(threshold, actual) - -Asserts that the actual value is greater than the threshold. This also comes in size specific variants. - - - TEST_ASSERT_LESS_THAN(threshold, actual) - -Asserts that the actual value is less than the threshold. This also comes in size specific variants. - - -Arrays ------- - - _ARRAY - -You can append `_ARRAY` to any of these macros to make an array comparison of that type. Here you will -need to care a bit more about the actual size of the value being checked. You will also specify an -additional argument which is the number of elements to compare. For example: - - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements) - - _EACH_EQUAL - -Another array comparison option is to check that EVERY element of an array is equal to a single expected -value. You do this by specifying the EACH_EQUAL macro. For example: - - TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements) - -Numerical Assertions: Bitwise ------------------------------ - - TEST_ASSERT_BITS(mask, expected, actual) - -Use an integer mask to specify which bits should be compared between two other integers. High bits in the mask are compared, low bits ignored. - - TEST_ASSERT_BITS_HIGH(mask, actual) - -Use an integer mask to specify which bits should be inspected to determine if they are all set high. High bits in the mask are compared, low bits ignored. - - TEST_ASSERT_BITS_LOW(mask, actual) - -Use an integer mask to specify which bits should be inspected to determine if they are all set low. High bits in the mask are compared, low bits ignored. - - TEST_ASSERT_BIT_HIGH(bit, actual) - -Test a single bit and verify that it is high. The bit is specified 0-31 for a 32-bit integer. - - TEST_ASSERT_BIT_LOW(bit, actual) - -Test a single bit and verify that it is low. The bit is specified 0-31 for a 32-bit integer. - -Numerical Assertions: Floats ----------------------------- - - TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) - -Asserts that the actual value is within plus or minus delta of the expected value. - - TEST_ASSERT_EQUAL_FLOAT(expected, actual) - TEST_ASSERT_EQUAL_DOUBLE(expected, actual) - -Asserts that two floating point values are "equal" within a small % delta of the expected value. - -String Assertions ------------------ - - TEST_ASSERT_EQUAL_STRING(expected, actual) - -Compare two null-terminate strings. Fail if any character is different or if the lengths are different. - - TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) - -Compare two strings. Fail if any character is different, stop comparing after len characters. - - TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) - -Compare two null-terminate strings. Fail if any character is different or if the lengths are different. Output a custom message on failure. - - TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) - -Compare two strings. Fail if any character is different, stop comparing after len characters. Output a custom message on failure. - -Pointer Assertions ------------------- - -Most pointer operations can be performed by simply using the integer comparisons above. However, a couple of special cases are added for clarity. - - TEST_ASSERT_NULL(pointer) - -Fails if the pointer is not equal to NULL - - TEST_ASSERT_NOT_NULL(pointer) - -Fails if the pointer is equal to NULL - -Memory Assertions ------------------ - - TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) - -Compare two blocks of memory. This is a good generic assertion for types that can't be coerced into acting like -standard types... but since it's a memory compare, you have to be careful that your data types are packed. - -_MESSAGE --------- - -you can append _MESSAGE to any of the macros to make them take an additional argument. This argument -is a string that will be printed at the end of the failure strings. This is useful for specifying more -information about the problem. - diff --git a/components/cjson/cJSON/tests/unity/auto/colour_prompt.rb b/components/cjson/cJSON/tests/unity/auto/colour_prompt.rb deleted file mode 100644 index 0f1dc4e02..000000000 --- a/components/cjson/cJSON/tests/unity/auto/colour_prompt.rb +++ /dev/null @@ -1,118 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -if RUBY_PLATFORM =~ /(win|w)32$/ - begin - require 'Win32API' - rescue LoadError - puts 'ERROR! "Win32API" library not found' - puts '"Win32API" is required for colour on a windows machine' - puts ' try => "gem install Win32API" on the command line' - puts - end - # puts - # puts 'Windows Environment Detected...' - # puts 'Win32API Library Found.' - # puts -end - -class ColourCommandLine - def initialize - return unless RUBY_PLATFORM =~ /(win|w)32$/ - get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L') - @set_console_txt_attrb = - Win32API.new('kernel32', 'SetConsoleTextAttribute', %w(L N), 'I') - @hout = get_std_handle.call(-11) - end - - def change_to(new_colour) - if RUBY_PLATFORM =~ /(win|w)32$/ - @set_console_txt_attrb.call(@hout, win32_colour(new_colour)) - else - "\033[30;#{posix_colour(new_colour)};22m" - end - end - - def win32_colour(colour) - case colour - when :black then 0 - when :dark_blue then 1 - when :dark_green then 2 - when :dark_cyan then 3 - when :dark_red then 4 - when :dark_purple then 5 - when :dark_yellow, :narrative then 6 - when :default_white, :default, :dark_white then 7 - when :silver then 8 - when :blue then 9 - when :green, :success then 10 - when :cyan, :output then 11 - when :red, :failure then 12 - when :purple then 13 - when :yellow then 14 - when :white then 15 - else - 0 - end - end - - def posix_colour(colour) - # ANSI Escape Codes - Foreground colors - # | Code | Color | - # | 39 | Default foreground color | - # | 30 | Black | - # | 31 | Red | - # | 32 | Green | - # | 33 | Yellow | - # | 34 | Blue | - # | 35 | Magenta | - # | 36 | Cyan | - # | 37 | Light gray | - # | 90 | Dark gray | - # | 91 | Light red | - # | 92 | Light green | - # | 93 | Light yellow | - # | 94 | Light blue | - # | 95 | Light magenta | - # | 96 | Light cyan | - # | 97 | White | - - case colour - when :black then 30 - when :red, :failure then 31 - when :green, :success then 32 - when :yellow then 33 - when :blue, :narrative then 34 - when :purple, :magenta then 35 - when :cyan, :output then 36 - when :white, :default_white then 37 - when :default then 39 - else - 39 - end - end - - def out_c(mode, colour, str) - case RUBY_PLATFORM - when /(win|w)32$/ - change_to(colour) - $stdout.puts str if mode == :puts - $stdout.print str if mode == :print - change_to(:default_white) - else - $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts - $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print - end - end -end # ColourCommandLine - -def colour_puts(role, str) - ColourCommandLine.new.out_c(:puts, role, str) -end - -def colour_print(role, str) - ColourCommandLine.new.out_c(:print, role, str) -end diff --git a/components/cjson/cJSON/tests/unity/auto/colour_reporter.rb b/components/cjson/cJSON/tests/unity/auto/colour_reporter.rb deleted file mode 100644 index bb1fbfce3..000000000 --- a/components/cjson/cJSON/tests/unity/auto/colour_reporter.rb +++ /dev/null @@ -1,39 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt" - -$colour_output = true - -def report(message) - if !$colour_output - $stdout.puts(message) - else - message = message.join('\n') if message.class == Array - message.each_line do |line| - line.chomp! - colour = case line - when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i - Regexp.last_match(1).to_i.zero? ? :green : :red - when /PASS/ - :green - when /^OK$/ - :green - when /(?:FAIL|ERROR)/ - :red - when /IGNORE/ - :yellow - when /^(?:Creating|Compiling|Linking)/ - :white - else - :silver - end - colour_puts(colour, line) - end - end - $stdout.flush - $stderr.flush -end diff --git a/components/cjson/cJSON/tests/unity/auto/generate_config.yml b/components/cjson/cJSON/tests/unity/auto/generate_config.yml deleted file mode 100644 index 4a5e47424..000000000 --- a/components/cjson/cJSON/tests/unity/auto/generate_config.yml +++ /dev/null @@ -1,36 +0,0 @@ -#this is a sample configuration file for generate_module -#you would use it by calling generate_module with the -ygenerate_config.yml option -#files like this are useful for customizing generate_module to your environment -:generate_module: - :defaults: - #these defaults are used in place of any missing options at the command line - :path_src: ../src/ - :path_inc: ../src/ - :path_tst: ../test/ - :update_svn: true - :includes: - #use [] for no additional includes, otherwise list the includes on separate lines - :src: - - Defs.h - - Board.h - :inc: [] - :tst: - - Defs.h - - Board.h - - Exception.h - :boilerplates: - #these are inserted at the top of generated files. - #just comment out or remove if not desired. - #use %1$s where you would like the file name to appear (path/extension not included) - :src: | - //------------------------------------------- - // %1$s.c - //------------------------------------------- - :inc: | - //------------------------------------------- - // %1$s.h - //------------------------------------------- - :tst: | - //------------------------------------------- - // Test%1$s.c : Units tests for %1$s.c - //------------------------------------------- diff --git a/components/cjson/cJSON/tests/unity/auto/generate_module.rb b/components/cjson/cJSON/tests/unity/auto/generate_module.rb deleted file mode 100644 index 13b4cc74d..000000000 --- a/components/cjson/cJSON/tests/unity/auto/generate_module.rb +++ /dev/null @@ -1,308 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -# This script creates all the files with start code necessary for a new module. -# A simple module only requires a source file, header file, and test file. -# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware). - -require 'rubygems' -require 'fileutils' -require 'pathname' - -# TEMPLATE_TST -TEMPLATE_TST ||= '#include "unity.h" -%2$s#include "%1$s.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_%1$s_NeedToImplement(void) -{ - TEST_IGNORE_MESSAGE("Need to Implement %1$s"); -} -'.freeze - -# TEMPLATE_SRC -TEMPLATE_SRC ||= '%2$s#include "%1$s.h" -'.freeze - -# TEMPLATE_INC -TEMPLATE_INC ||= '#ifndef _%3$s_H -#define _%3$s_H -%2$s - -#endif // _%3$s_H -'.freeze - -class UnityModuleGenerator - ############################ - def initialize(options = nil) - here = File.expand_path(File.dirname(__FILE__)) + '/' - - @options = UnityModuleGenerator.default_options - case options - when NilClass then @options - when String then @options.merge!(UnityModuleGenerator.grab_config(options)) - when Hash then @options.merge!(options) - else raise 'If you specify arguments, it should be a filename or a hash of options' - end - - # Create default file paths if none were provided - @options[:path_src] = here + '../src/' if @options[:path_src].nil? - @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? - @options[:path_tst] = here + '../test/' if @options[:path_tst].nil? - @options[:path_src] += '/' unless @options[:path_src][-1] == 47 - @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47 - @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47 - - # Built in patterns - @patterns = { - 'src' => { - '' => { inc: [] } - }, - 'test' => { - '' => { inc: [] } - }, - 'dh' => { - 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] }, - 'Hardware' => { inc: [] } - }, - 'dih' => { - 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] }, - 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] }, - 'Hardware' => { inc: [] } - }, - 'mch' => { - 'Model' => { inc: [] }, - 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] }, - 'Hardware' => { inc: [] } - }, - 'mvp' => { - 'Model' => { inc: [] }, - 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] }, - 'View' => { inc: [] } - } - } - end - - ############################ - def self.default_options - { - pattern: 'src', - includes: { - src: [], - inc: [], - tst: [] - }, - update_svn: false, - boilerplates: {}, - test_prefix: 'Test', - mock_prefix: 'Mock' - } - end - - ############################ - def self.grab_config(config_file) - options = default_options - unless config_file.nil? || config_file.empty? - require 'yaml' - yaml_guts = YAML.load_file(config_file) - options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) - raise "No :unity or :cmock section found in #{config_file}" unless options - end - options - end - - ############################ - def files_to_operate_on(module_name, pattern = nil) - # strip any leading path information from the module name and save for later - subfolder = File.dirname(module_name) - module_name = File.basename(module_name) - - # create triad definition - prefix = @options[:test_prefix] || 'Test' - triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] }, - { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] }, - { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }] - - # prepare the pattern for use - pattern = (pattern || @options[:pattern] || 'src').downcase - patterns = @patterns[pattern] - raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil? - - # single file patterns (currently just 'test') can reject the other parts of the triad - triad.select! { |v| v[:inc] == :tst } if pattern == 'test' - - # Assemble the path/names of the files we need to work with. - files = [] - triad.each do |cfg| - patterns.each_pair do |pattern_file, pattern_traits| - submodule_name = create_filename(module_name, pattern_file) - filename = cfg[:prefix] + submodule_name + cfg[:ext] - files << { - path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath, - name: submodule_name, - template: cfg[:template], - boilerplate: cfg[:boilerplate], - includes: case (cfg[:inc]) - when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) }) - when :inc then (@options[:includes][:inc] || []) - when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) }) - end - } - end - end - - files - end - - ############################ - def create_filename(part1, part2 = '') - if part2.empty? - case (@options[:naming]) - when 'bumpy' then part1 - when 'camel' then part1 - when 'snake' then part1.downcase - when 'caps' then part1.upcase - else part1 - end - else - case (@options[:naming]) - when 'bumpy' then part1 + part2 - when 'camel' then part1 + part2 - when 'snake' then part1.downcase + '_' + part2.downcase - when 'caps' then part1.upcase + '_' + part2.upcase - else part1 + '_' + part2 - end - end - end - - ############################ - def generate(module_name, pattern = nil) - files = files_to_operate_on(module_name, pattern) - - # Abort if all of the module files already exist - all_files_exist = true - files.each do |file| - all_files_exist = false unless File.exist?(file[:path]) - end - raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist - - # Create Source Modules - files.each_with_index do |file, _i| - # If this file already exists, don't overwrite it. - if File.exist?(file[:path]) - puts "File #{file[:path]} already exists!" - next - end - # Create the path first if necessary. - FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false) - File.open(file[:path], 'w') do |f| - f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil? - f.write(file[:template] % [file[:name], - file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join, - file[:name].upcase]) - end - if @options[:update_svn] - `svn add \"#{file[:path]}\"` - if $!.exitstatus.zero? - puts "File #{file[:path]} created and added to source control" - else - puts "File #{file[:path]} created but FAILED adding to source control!" - end - else - puts "File #{file[:path]} created" - end - end - puts 'Generate Complete' - end - - ############################ - def destroy(module_name, pattern = nil) - files_to_operate_on(module_name, pattern).each do |filespec| - file = filespec[:path] - if File.exist?(file) - if @options[:update_svn] - `svn delete \"#{file}\" --force` - puts "File #{file} deleted and removed from source control" - else - FileUtils.remove(file) - puts "File #{file} deleted" - end - else - puts "File #{file} does not exist so cannot be removed." - end - end - puts 'Destroy Complete' - end -end - -############################ -# Handle As Command Line If Called That Way -if $0 == __FILE__ - destroy = false - options = {} - module_name = nil - - # Parse the command line parameters. - ARGV.each do |arg| - case arg - when /^-d/ then destroy = true - when /^-u/ then options[:update_svn] = true - when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1) - when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1) - when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1) - when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1) - when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1) - when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1)) - when /^(\w+)/ - raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil? - module_name = arg - when /^-(h|-help)/ - ARGV = [].freeze - else - raise "ERROR: Unknown option specified '#{arg}'" - end - end - - unless ARGV[0] - puts ["\nGENERATE MODULE\n-------- ------", - "\nUsage: ruby generate_module [options] module_name", - " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)", - " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)", - " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)", - ' -p"MCH" sets the output pattern to MCH.', - ' dh - driver hardware.', - ' dih - driver interrupt hardware.', - ' mch - model conductor hardware.', - ' mvp - model view presenter.', - ' src - just a source module, header and test. (DEFAULT)', - ' test - just a test file.', - ' -d destroy module instead of creating it.', - ' -n"camel" sets the file naming convention.', - ' bumpy - BumpyCaseFilenames.', - ' camel - camelCaseFilenames.', - ' snake - snake_case_filenames.', - ' caps - CAPS_CASE_FILENAMES.', - ' -u update subversion too (requires subversion command line)', - ' -y"my.yml" selects a different yaml config file for module generation', - ''].join("\n") - exit - end - - raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil? - if destroy - UnityModuleGenerator.new(options).destroy(module_name) - else - UnityModuleGenerator.new(options).generate(module_name) - end - -end diff --git a/components/cjson/cJSON/tests/unity/auto/generate_test_runner.rb b/components/cjson/cJSON/tests/unity/auto/generate_test_runner.rb deleted file mode 100644 index 344a2d0fb..000000000 --- a/components/cjson/cJSON/tests/unity/auto/generate_test_runner.rb +++ /dev/null @@ -1,454 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt')) - -class UnityTestRunnerGenerator - def initialize(options = nil) - @options = UnityTestRunnerGenerator.default_options - case options - when NilClass then @options - when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options)) - when Hash then @options.merge!(options) - else raise 'If you specify arguments, it should be a filename or a hash of options' - end - require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer" - end - - def self.default_options - { - includes: [], - defines: [], - plugins: [], - framework: :unity, - test_prefix: 'test|spec|should', - mock_prefix: 'Mock', - setup_name: 'setUp', - teardown_name: 'tearDown', - main_name: 'main', # set to :auto to automatically generate each time - main_export_decl: '', - cmdline_args: false, - use_param_tests: false - } - end - - def self.grab_config(config_file) - options = default_options - unless config_file.nil? || config_file.empty? - require 'yaml' - yaml_guts = YAML.load_file(config_file) - options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) - raise "No :unity or :cmock section found in #{config_file}" unless options - end - options - end - - def run(input_file, output_file, options = nil) - @options.merge!(options) unless options.nil? - - # pull required data from source file - source = File.read(input_file) - source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil) - tests = find_tests(source) - headers = find_includes(source) - testfile_includes = (headers[:local] + headers[:system]) - used_mocks = find_mocks(testfile_includes) - testfile_includes = (testfile_includes - used_mocks) - testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ } - - # build runner file - generate(input_file, output_file, tests, used_mocks, testfile_includes) - - # determine which files were used to return them - all_files_used = [input_file, output_file] - all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty? - all_files_used += @options[:includes] unless @options[:includes].empty? - all_files_used += headers[:linkonly] unless headers[:linkonly].empty? - all_files_used.uniq - end - - def generate(input_file, output_file, tests, used_mocks, testfile_includes) - File.open(output_file, 'w') do |output| - create_header(output, used_mocks, testfile_includes) - create_externs(output, tests, used_mocks) - create_mock_management(output, used_mocks) - create_suite_setup(output) - create_suite_teardown(output) - create_reset(output, used_mocks) - create_main(output, input_file, tests, used_mocks) - end - - return unless @options[:header_file] && !@options[:header_file].empty? - - File.open(@options[:header_file], 'w') do |output| - create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) - end - end - - def find_tests(source) - tests_and_line_numbers = [] - - source_scrubbed = source.clone - source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings - source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments - source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments - lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line - | (;|\{|\}) /x) # Match ;, {, and } as end of lines - - lines.each_with_index do |line, _index| - # find tests - next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/ - arguments = Regexp.last_match(1) - name = Regexp.last_match(2) - call = Regexp.last_match(3) - params = Regexp.last_match(4) - args = nil - if @options[:use_param_tests] && !arguments.empty? - args = [] - arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] } - end - tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 } - end - tests_and_line_numbers.uniq! { |v| v[:test] } - - # determine line numbers and create tests to run - source_lines = source.split("\n") - source_index = 0 - tests_and_line_numbers.size.times do |i| - source_lines[source_index..-1].each_with_index do |line, index| - next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/ - source_index += index - tests_and_line_numbers[i][:line_number] = source_index + 1 - break - end - end - - tests_and_line_numbers - end - - def find_includes(source) - # remove comments (block and line, in three steps to ensure correct precedence) - source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks - source.gsub!(/\/\*.*?\*\//m, '') # remove block comments - source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain) - - # parse out includes - includes = { - local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten, - system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }, - linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten - } - includes - end - - def find_mocks(includes) - mock_headers = [] - includes.each do |include_path| - include_file = File.basename(include_path) - mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}/i - end - mock_headers - end - - def create_header(output, mocks, testfile_includes = []) - output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') - create_runtest(output, mocks) - output.puts("\n/*=======Automagically Detected Files To Include=====*/") - output.puts('#ifdef __WIN32__') - output.puts('#define UNITY_INCLUDE_SETUP_STUBS') - output.puts('#endif') - output.puts("#include \"#{@options[:framework]}.h\"") - output.puts('#include "cmock.h"') unless mocks.empty? - output.puts('#include ') - output.puts('#include ') - if @options[:defines] && !@options[:defines].empty? - @options[:defines].each { |d| output.puts("#define #{d}") } - end - if @options[:header_file] && !@options[:header_file].empty? - output.puts("#include \"#{File.basename(@options[:header_file])}\"") - else - @options[:includes].flatten.uniq.compact.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") - end - testfile_includes.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") - end - end - mocks.each do |mock| - output.puts("#include \"#{mock.gsub('.h', '')}.h\"") - end - output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) - - return unless @options[:enforce_strict_ordering] - - output.puts('') - output.puts('int GlobalExpectCount;') - output.puts('int GlobalVerifyOrder;') - output.puts('char* GlobalOrderError;') - end - - def create_externs(output, tests, _mocks) - output.puts("\n/*=======External Functions This Runner Calls=====*/") - output.puts("extern void #{@options[:setup_name]}(void);") - output.puts("extern void #{@options[:teardown_name]}(void);") - tests.each do |test| - output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});") - end - output.puts('') - end - - def create_mock_management(output, mock_headers) - return if mock_headers.empty? - - output.puts("\n/*=======Mock Management=====*/") - output.puts('static void CMock_Init(void)') - output.puts('{') - - if @options[:enforce_strict_ordering] - output.puts(' GlobalExpectCount = 0;') - output.puts(' GlobalVerifyOrder = 0;') - output.puts(' GlobalOrderError = NULL;') - end - - mocks = mock_headers.map { |mock| File.basename(mock) } - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Init();") - end - output.puts("}\n") - - output.puts('static void CMock_Verify(void)') - output.puts('{') - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Verify();") - end - output.puts("}\n") - - output.puts('static void CMock_Destroy(void)') - output.puts('{') - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Destroy();") - end - output.puts("}\n") - end - - def create_suite_setup(output) - output.puts("\n/*=======Suite Setup=====*/") - output.puts('static void suite_setup(void)') - output.puts('{') - if @options[:suite_setup].nil? - # New style, call suiteSetUp() if we can use weak symbols - output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)') - output.puts(' suiteSetUp();') - output.puts('#endif') - else - # Old style, C code embedded in the :suite_setup option - output.puts(@options[:suite_setup]) - end - output.puts('}') - end - - def create_suite_teardown(output) - output.puts("\n/*=======Suite Teardown=====*/") - output.puts('static int suite_teardown(int num_failures)') - output.puts('{') - if @options[:suite_teardown].nil? - # New style, call suiteTearDown() if we can use weak symbols - output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)') - output.puts(' return suiteTearDown(num_failures);') - output.puts('#else') - output.puts(' return num_failures;') - output.puts('#endif') - else - # Old style, C code embedded in the :suite_teardown option - output.puts(@options[:suite_teardown]) - end - output.puts('}') - end - - def create_runtest(output, used_mocks) - cexception = @options[:plugins].include? :cexception - va_args1 = @options[:use_param_tests] ? ', ...' : '' - va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : '' - output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/") - output.puts('#define RUN_TEST_NO_ARGS') if @options[:use_param_tests] - output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\") - output.puts('{ \\') - output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\") - output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\') - output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args] - output.puts(' Unity.NumberOfTests++; \\') - output.puts(' CMock_Init(); \\') unless used_mocks.empty? - output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty? - output.puts(' if (TEST_PROTECT()) \\') - output.puts(' { \\') - output.puts(' CEXCEPTION_T e; \\') if cexception - output.puts(' Try { \\') if cexception - output.puts(" #{@options[:setup_name]}(); \\") - output.puts(" TestFunc(#{va_args2}); \\") - output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception - output.puts(' } \\') - output.puts(' if (TEST_PROTECT()) \\') - output.puts(' { \\') - output.puts(" #{@options[:teardown_name]}(); \\") - output.puts(' CMock_Verify(); \\') unless used_mocks.empty? - output.puts(' } \\') - output.puts(' CMock_Destroy(); \\') unless used_mocks.empty? - output.puts(' UnityConcludeTest(); \\') - output.puts(' } \\') if @options[:cmdline_args] - output.puts("}\n") - end - - def create_reset(output, used_mocks) - output.puts("\n/*=======Test Reset Option=====*/") - output.puts('void resetTest(void);') - output.puts('void resetTest(void)') - output.puts('{') - output.puts(' CMock_Verify();') unless used_mocks.empty? - output.puts(' CMock_Destroy();') unless used_mocks.empty? - output.puts(" #{@options[:teardown_name]}();") - output.puts(' CMock_Init();') unless used_mocks.empty? - output.puts(" #{@options[:setup_name]}();") - output.puts('}') - end - - def create_main(output, filename, tests, used_mocks) - output.puts("\n\n/*=======MAIN=====*/") - main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s - if @options[:cmdline_args] - if main_name != 'main' - output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);") - end - output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)") - output.puts('{') - output.puts(' int parse_status = UnityParseOptions(argc, argv);') - output.puts(' if (parse_status != 0)') - output.puts(' {') - output.puts(' if (parse_status < 0)') - output.puts(' {') - output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");") - output.puts(' UNITY_PRINT_EOL();') - if @options[:use_param_tests] - tests.each do |test| - if test[:args].nil? || test[:args].empty? - output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");") - output.puts(' UNITY_PRINT_EOL();') - else - test[:args].each do |args| - output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");") - output.puts(' UNITY_PRINT_EOL();') - end - end - end - else - tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") } - end - output.puts(' return 0;') - output.puts(' }') - output.puts(' return parse_status;') - output.puts(' }') - else - if main_name != 'main' - output.puts("#{@options[:main_export_decl]} int #{main_name}(void);") - end - output.puts("int #{main_name}(void)") - output.puts('{') - end - output.puts(' suite_setup();') - output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");") - if @options[:use_param_tests] - tests.each do |test| - if test[:args].nil? || test[:args].empty? - output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);") - else - test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") } - end - end - else - tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") } - end - output.puts - output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty? - output.puts(" return suite_teardown(UnityEnd());") - output.puts('}') - end - - def create_h_file(output, filename, tests, testfile_includes, used_mocks) - filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase - output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') - output.puts("#ifndef _#{filename}") - output.puts("#define _#{filename}\n\n") - output.puts("#include \"#{@options[:framework]}.h\"") - output.puts('#include "cmock.h"') unless used_mocks.empty? - @options[:includes].flatten.uniq.compact.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") - end - testfile_includes.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") - end - output.puts "\n" - tests.each do |test| - if test[:params].nil? || test[:params].empty? - output.puts("void #{test[:test]}(void);") - else - output.puts("void #{test[:test]}(#{test[:params]});") - end - end - output.puts("#endif\n\n") - end -end - -if $0 == __FILE__ - options = { includes: [] } - - # parse out all the options first (these will all be removed as we go) - ARGV.reject! do |arg| - case arg - when '-cexception' - options[:plugins] = [:cexception] - true - when /\.*\.ya?ml/ - options = UnityTestRunnerGenerator.grab_config(arg) - true - when /--(\w+)=\"?(.*)\"?/ - options[Regexp.last_match(1).to_sym] = Regexp.last_match(2) - true - when /\.*\.h/ - options[:includes] << arg - true - else false - end - end - - # make sure there is at least one parameter left (the input file) - unless ARGV[0] - puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)", - "\n input_test_file - this is the C file you want to create a runner for", - ' output - this is the name of the runner file to generate', - ' defaults to (input_test_file)_Runner', - ' files:', - ' *.yml / *.yaml - loads configuration from here in :unity or :cmock', - ' *.h - header files are added as #includes in runner', - ' options:', - ' -cexception - include cexception support', - ' --setup_name="" - redefine setUp func name to something else', - ' --teardown_name="" - redefine tearDown func name to something else', - ' --main_name="" - redefine main func name to something else', - ' --test_prefix="" - redefine test prefix from default test|spec|should', - ' --suite_setup="" - code to execute for setup of entire suite', - ' --suite_teardown="" - code to execute for teardown of entire suite', - ' --use_param_tests=1 - enable parameterized tests (disabled by default)', - ' --header_file="" - path/name of test header file to generate too'].join("\n") - exit 1 - end - - # create the default test runner name if not specified - ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1] - - UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) -end diff --git a/components/cjson/cJSON/tests/unity/auto/parse_output.rb b/components/cjson/cJSON/tests/unity/auto/parse_output.rb deleted file mode 100644 index f16cdb036..000000000 --- a/components/cjson/cJSON/tests/unity/auto/parse_output.rb +++ /dev/null @@ -1,220 +0,0 @@ -#============================================================ -# Author: John Theofanopoulos -# A simple parser. Takes the output files generated during the build process and -# extracts information relating to the tests. -# -# Notes: -# To capture an output file under VS builds use the following: -# devenv [build instructions] > Output.txt & type Output.txt -# -# To capture an output file under GCC/Linux builds use the following: -# make | tee Output.txt -# -# To use this parser use the following command -# ruby parseOutput.rb [options] [file] -# options: -xml : produce a JUnit compatible XML file -# file : file to scan for results -#============================================================ - -class ParseOutput - def initialize - @test_flag = false - @xml_out = false - @array_list = false - @total_tests = false - @class_index = false - end - - # Set the flag to indicate if there will be an XML output file or not - def set_xml_output - @xml_out = true - end - - # if write our output to XML - def write_xml_output - output = File.open('report.xml', 'w') - output << "\n" - @array_list.each do |item| - output << item << "\n" - end - output << "\n" - end - - # This function will try and determine when the suite is changed. This is - # is the name that gets added to the classname parameter. - def test_suite_verify(test_suite_name) - return if @test_flag - - @test_flag = true - # Split the path name - test_name = test_suite_name.split('/') - # Remove the extension - base_name = test_name[test_name.size - 1].split('.') - @test_suite = 'test.' + base_name[0] - printf "New Test: %s\n", @test_suite - end - - # Test was flagged as having passed so format the output - def test_passed(array) - last_item = array.length - 1 - test_name = array[last_item - 1] - test_suite_verify(array[@class_name]) - printf "%-40s PASS\n", test_name - - return unless @xml_out - - @array_list.push ' ' - end - - # Test was flagged as having passed so format the output. - # This is using the Unity fixture output and not the original Unity output. - def test_passed_unity_fixture(array) - test_suite = array[0].sub('TEST(', '') - test_suite = test_suite.sub(',', '') - test_name = array[1].sub(')', '') - - return unless @xml_out - - @array_list.push ' ' - end - - # Test was flagged as being ingored so format the output - def test_ignored(array) - last_item = array.length - 1 - test_name = array[last_item - 2] - reason = array[last_item].chomp - test_suite_verify(array[@class_name]) - printf "%-40s IGNORED\n", test_name - - if test_name.start_with? 'TEST(' - array2 = test_name.split(' ') - @test_suite = array2[0].sub('TEST(', '') - @test_suite = @test_suite.sub(',', '') - test_name = array2[1].sub(')', '') - end - - return unless @xml_out - - @array_list.push ' ' - @array_list.push ' ' + reason + ' ' - @array_list.push ' ' - end - - # Test was flagged as having failed so format the line - def test_failed(array) - last_item = array.length - 1 - test_name = array[last_item - 2] - reason = array[last_item].chomp + ' at line: ' + array[last_item - 3] - test_suite_verify(array[@class_name]) - printf "%-40s FAILED\n", test_name - - if test_name.start_with? 'TEST(' - array2 = test_name.split(' ') - @test_suite = array2[0].sub('TEST(', '') - @test_suite = @test_suite.sub(',', '') - test_name = array2[1].sub(')', '') - end - - return unless @xml_out - - @array_list.push ' ' - @array_list.push ' ' + reason + ' ' - @array_list.push ' ' - end - - # Figure out what OS we are running on. For now we are assuming if it's not Windows it must - # be Unix based. - def detect_os - os = RUBY_PLATFORM.split('-') - @class_name = if os.size == 2 - if os[1] == 'mingw32' - 1 - else - 0 - end - else - 0 - end - end - - # Main function used to parse the file that was captured. - def process(name) - @test_flag = false - @array_list = [] - - detect_os - - puts 'Parsing file: ' + name - - test_pass = 0 - test_fail = 0 - test_ignore = 0 - puts '' - puts '=================== RESULTS =====================' - puts '' - File.open(name).each do |line| - # Typical test lines look like this: - # /.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 - # /.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented - # /.c:115:test_tc5100_initCanVoidPtrs:PASS - # - # where path is different on Unix vs Windows devices (Windows leads with a drive letter) - line_array = line.split(':') - - # If we were able to split the line then we can look to see if any of our target words - # were found. Case is important. - if (line_array.size >= 4) || (line.start_with? 'TEST(') - # Determine if this test passed - if line.include? ':PASS' - test_passed(line_array) - test_pass += 1 - elsif line.include? ':FAIL:' - test_failed(line_array) - test_fail += 1 - elsif line.include? ':IGNORE:' - test_ignored(line_array) - test_ignore += 1 - elsif line.start_with? 'TEST(' - if line.include? ' PASS' - line_array = line.split(' ') - test_passed_unity_fixture(line_array) - test_pass += 1 - end - # If none of the keywords are found there are no more tests for this suite so clear - # the test flag - else - @test_flag = false - end - else - @test_flag = false - end - end - puts '' - puts '=================== SUMMARY =====================' - puts '' - puts 'Tests Passed : ' + test_pass.to_s - puts 'Tests Failed : ' + test_fail.to_s - puts 'Tests Ignored : ' + test_ignore.to_s - @total_tests = test_pass + test_fail + test_ignore - - return unless @xml_out - - heading = '' - @array_list.insert(0, heading) - write_xml_output - end -end - -# If the command line has no values in, used a default value of Output.txt -parse_my_file = ParseOutput.new - -if ARGV.size >= 1 - ARGV.each do |a| - if a == '-xml' - parse_my_file.set_xml_output - else - parse_my_file.process(a) - break - end - end -end diff --git a/components/cjson/cJSON/tests/unity/auto/stylize_as_junit.rb b/components/cjson/cJSON/tests/unity/auto/stylize_as_junit.rb deleted file mode 100755 index b3d8f4097..000000000 --- a/components/cjson/cJSON/tests/unity/auto/stylize_as_junit.rb +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/ruby -# -# unity_to_junit.rb -# -require 'fileutils' -require 'optparse' -require 'ostruct' -require 'set' - -require 'pp' - -VERSION = 1.0 - -class ArgvParser - # - # Return a structure describing the options. - # - def self.parse(args) - # The options specified on the command line will be collected in *options*. - # We set default values here. - options = OpenStruct.new - options.results_dir = '.' - options.root_path = '.' - options.out_file = 'results.xml' - - opts = OptionParser.new do |o| - o.banner = 'Usage: unity_to_junit.rb [options]' - - o.separator '' - o.separator 'Specific options:' - - o.on('-r', '--results ', 'Look for Unity Results files here.') do |results| - # puts "results #{results}" - options.results_dir = results - end - - o.on('-p', '--root_path ', 'Prepend this path to files in results.') do |root_path| - options.root_path = root_path - end - - o.on('-o', '--output ', 'XML file to generate.') do |out_file| - # puts "out_file: #{out_file}" - options.out_file = out_file - end - - o.separator '' - o.separator 'Common options:' - - # No argument, shows at tail. This will print an options summary. - o.on_tail('-h', '--help', 'Show this message') do - puts o - exit - end - - # Another typical switch to print the version. - o.on_tail('--version', 'Show version') do - puts "unity_to_junit.rb version #{VERSION}" - exit - end - end - - opts.parse!(args) - options - end # parse() -end # class OptparseExample - -class UnityToJUnit - include FileUtils::Verbose - attr_reader :report, :total_tests, :failures, :ignored - attr_writer :targets, :root, :out_file - - def initialize - @report = '' - @unit_name = '' - end - - def run - # Clean up result file names - results = @targets.map { |target| target.tr('\\', '/') } - # puts "Output File: #{@out_file}" - f = File.new(@out_file, 'w') - write_xml_header(f) - write_suites_header(f) - results.each do |result_file| - lines = File.readlines(result_file).map(&:chomp) - - raise "Empty test result file: #{result_file}" if lines.empty? - - result_output = get_details(result_file, lines) - tests, failures, ignored = parse_test_summary(lines) - result_output[:counts][:total] = tests - result_output[:counts][:failed] = failures - result_output[:counts][:ignored] = ignored - result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored]) - - # use line[0] from the test output to get the test_file path and name - test_file_str = lines[0].tr('\\', '/') - test_file_str = test_file_str.split(':') - test_file = if test_file_str.length < 2 - result_file - else - test_file_str[0] + ':' + test_file_str[1] - end - result_output[:source][:path] = File.dirname(test_file) - result_output[:source][:file] = File.basename(test_file) - - # save result_output - @unit_name = File.basename(test_file, '.*') - - write_suite_header(result_output[:counts], f) - write_failures(result_output, f) - write_tests(result_output, f) - write_ignored(result_output, f) - write_suite_footer(f) - end - write_suites_footer(f) - f.close - end - - def usage(err_msg = nil) - puts "\nERROR: " - puts err_msg if err_msg - puts 'Usage: unity_to_junit.rb [options]' - puts '' - puts 'Specific options:' - puts ' -r, --results Look for Unity Results files here.' - puts ' -p, --root_path Prepend this path to files in results.' - puts ' -o, --output XML file to generate.' - puts '' - puts 'Common options:' - puts ' -h, --help Show this message' - puts ' --version Show version' - - exit 1 - end - - protected - - def get_details(_result_file, lines) - results = results_structure - lines.each do |line| - line = line.tr('\\', '/') - _src_file, src_line, test_name, status, msg = line.split(/:/) - case status - when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg } - when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg } - when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg } - end - end - results - end - - def parse_test_summary(summary) - raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } - [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] - end - - def here - File.expand_path(File.dirname(__FILE__)) - end - - private - - def results_structure - { - source: { path: '', file: '' }, - successes: [], - failures: [], - ignores: [], - counts: { total: 0, passed: 0, failed: 0, ignored: 0 }, - stdout: [] - } - end - - def write_xml_header(stream) - stream.puts "" - end - - def write_suites_header(stream) - stream.puts '' - end - - def write_suite_header(counts, stream) - stream.puts "\t" - end - - def write_failures(results, stream) - result = results[:failures] - result.each do |item| - filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) - stream.puts "\t\t" - stream.puts "\t\t\t" - stream.puts "\t\t\t [File] #{filename} [Line] #{item[:line]} " - stream.puts "\t\t" - end - end - - def write_tests(results, stream) - result = results[:successes] - result.each do |item| - stream.puts "\t\t" - end - end - - def write_ignored(results, stream) - result = results[:ignores] - result.each do |item| - filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) - puts "Writing ignored tests for test harness: #{filename}" - stream.puts "\t\t" - stream.puts "\t\t\t" - stream.puts "\t\t\t [File] #{filename} [Line] #{item[:line]} " - stream.puts "\t\t" - end - end - - def write_suite_footer(stream) - stream.puts "\t" - end - - def write_suites_footer(stream) - stream.puts '' - end -end # UnityToJUnit - -if __FILE__ == $0 - # parse out the command options - options = ArgvParser.parse(ARGV) - - # create an instance to work with - utj = UnityToJUnit.new - begin - # look in the specified or current directory for result files - targets = "#{options.results_dir.tr('\\', '/')}**/*.test*" - - results = Dir[targets] - raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? - utj.targets = results - - # set the root path - utj.root = options.root_path - - # set the output XML file name - # puts "Output File from options: #{options.out_file}" - utj.out_file = options.out_file - - # run the summarizer - puts utj.run - rescue StandardError => e - utj.usage e.message - end -end diff --git a/components/cjson/cJSON/tests/unity/auto/test_file_filter.rb b/components/cjson/cJSON/tests/unity/auto/test_file_filter.rb deleted file mode 100644 index aad28e38e..000000000 --- a/components/cjson/cJSON/tests/unity/auto/test_file_filter.rb +++ /dev/null @@ -1,25 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -require'yaml' - -module RakefileHelpers - class TestFileFilter - def initialize(all_files = false) - @all_files = all_files - - return false unless @all_files - return false unless File.exist?('test_file_filter.yml') - - filters = YAML.load_file('test_file_filter.yml') - @all_files = filters[:all_files] - @only_files = filters[:only_files] - @exclude_files = filters[:exclude_files] - end - - attr_accessor :all_files, :only_files, :exclude_files - end -end diff --git a/components/cjson/cJSON/tests/unity/auto/type_sanitizer.rb b/components/cjson/cJSON/tests/unity/auto/type_sanitizer.rb deleted file mode 100644 index dafb8826e..000000000 --- a/components/cjson/cJSON/tests/unity/auto/type_sanitizer.rb +++ /dev/null @@ -1,6 +0,0 @@ -module TypeSanitizer - def self.sanitize_c_identifier(unsanitized) - # convert filename to valid C identifier by replacing invalid chars with '_' - unsanitized.gsub(/[-\/\\\.\,\s]/, '_') - end -end diff --git a/components/cjson/cJSON/tests/unity/auto/unity_test_summary.py b/components/cjson/cJSON/tests/unity/auto/unity_test_summary.py deleted file mode 100644 index 4c20e528d..000000000 --- a/components/cjson/cJSON/tests/unity/auto/unity_test_summary.py +++ /dev/null @@ -1,139 +0,0 @@ -#! python3 -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de -# [Released under MIT License. Please refer to license.txt for details] -# Based on the ruby script by Mike Karlesky, Mark VanderVoord, Greg Williams -# ========================================== -import sys -import os -import re -from glob import glob - -class UnityTestSummary: - def __init__(self): - self.report = '' - self.total_tests = 0 - self.failures = 0 - self.ignored = 0 - - def run(self): - # Clean up result file names - results = [] - for target in self.targets: - results.append(target.replace('\\', '/')) - - # Dig through each result file, looking for details on pass/fail: - failure_output = [] - ignore_output = [] - - for result_file in results: - lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) - if len(lines) == 0: - raise Exception("Empty test result file: %s" % result_file) - - details = self.get_details(result_file, lines) - failures = details['failures'] - ignores = details['ignores'] - if len(failures) > 0: failure_output.append('\n'.join(failures)) - if len(ignores) > 0: ignore_output.append('n'.join(ignores)) - tests,failures,ignored = self.parse_test_summary('\n'.join(lines)) - self.total_tests += tests - self.failures += failures - self.ignored += ignored - - if self.ignored > 0: - self.report += "\n" - self.report += "--------------------------\n" - self.report += "UNITY IGNORED TEST SUMMARY\n" - self.report += "--------------------------\n" - self.report += "\n".join(ignore_output) - - if self.failures > 0: - self.report += "\n" - self.report += "--------------------------\n" - self.report += "UNITY FAILED TEST SUMMARY\n" - self.report += "--------------------------\n" - self.report += '\n'.join(failure_output) - - self.report += "\n" - self.report += "--------------------------\n" - self.report += "OVERALL UNITY TEST SUMMARY\n" - self.report += "--------------------------\n" - self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored) - self.report += "\n" - - return self.report - - def set_targets(self, target_array): - self.targets = target_array - - def set_root_path(self, path): - self.root = path - - def usage(self, err_msg=None): - print("\nERROR: ") - if err_msg: - print(err_msg) - print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") - print(" result_file_directory - The location of your results files.") - print(" Defaults to current directory if not specified.") - print(" Should end in / if specified.") - print(" root_path - Helpful for producing more verbose output if using relative paths.") - sys.exit(1) - - def get_details(self, result_file, lines): - results = { 'failures': [], 'ignores': [], 'successes': [] } - for line in lines: - parts = line.split(':') - if len(parts) == 5: - src_file,src_line,test_name,status,msg = parts - elif len(parts) == 4: - src_file,src_line,test_name,status = parts - msg = '' - else: - continue - if len(self.root) > 0: - line_out = "%s%s" % (self.root, line) - else: - line_out = line - if status == 'IGNORE': - results['ignores'].append(line_out) - elif status == 'FAIL': - results['failures'].append(line_out) - elif status == 'PASS': - results['successes'].append(line_out) - return results - - def parse_test_summary(self, summary): - m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary) - if not m: - raise Exception("Couldn't parse test results: %s" % summary) - - return int(m.group(1)), int(m.group(2)), int(m.group(3)) - - -if __name__ == '__main__': - uts = UnityTestSummary() - try: - #look in the specified or current directory for result files - if len(sys.argv) > 1: - targets_dir = sys.argv[1] - else: - targets_dir = './' - targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) - if len(targets) == 0: - raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) - uts.set_targets(targets) - - #set the root path - if len(sys.argv) > 2: - root_path = sys.argv[2] - else: - root_path = os.path.split(__file__)[0] - uts.set_root_path(root_path) - - #run the summarizer - print(uts.run()) - except Exception as e: - uts.usage(e) diff --git a/components/cjson/cJSON/tests/unity/auto/unity_test_summary.rb b/components/cjson/cJSON/tests/unity/auto/unity_test_summary.rb deleted file mode 100644 index b37dc5fa7..000000000 --- a/components/cjson/cJSON/tests/unity/auto/unity_test_summary.rb +++ /dev/null @@ -1,136 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -# !/usr/bin/ruby -# -# unity_test_summary.rb -# -require 'fileutils' -require 'set' - -class UnityTestSummary - include FileUtils::Verbose - - attr_reader :report, :total_tests, :failures, :ignored - attr_writer :targets, :root - - def initialize(_opts = {}) - @report = '' - @total_tests = 0 - @failures = 0 - @ignored = 0 - end - - def run - # Clean up result file names - results = @targets.map { |target| target.tr('\\', '/') } - - # Dig through each result file, looking for details on pass/fail: - failure_output = [] - ignore_output = [] - - results.each do |result_file| - lines = File.readlines(result_file).map(&:chomp) - - raise "Empty test result file: #{result_file}" if lines.empty? - - output = get_details(result_file, lines) - failure_output << output[:failures] unless output[:failures].empty? - ignore_output << output[:ignores] unless output[:ignores].empty? - tests, failures, ignored = parse_test_summary(lines) - @total_tests += tests - @failures += failures - @ignored += ignored - end - - if @ignored > 0 - @report += "\n" - @report += "--------------------------\n" - @report += "UNITY IGNORED TEST SUMMARY\n" - @report += "--------------------------\n" - @report += ignore_output.flatten.join("\n") - end - - if @failures > 0 - @report += "\n" - @report += "--------------------------\n" - @report += "UNITY FAILED TEST SUMMARY\n" - @report += "--------------------------\n" - @report += failure_output.flatten.join("\n") - end - - @report += "\n" - @report += "--------------------------\n" - @report += "OVERALL UNITY TEST SUMMARY\n" - @report += "--------------------------\n" - @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n" - @report += "\n" - end - - def usage(err_msg = nil) - puts "\nERROR: " - puts err_msg if err_msg - puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/" - puts ' result_file_directory - The location of your results files.' - puts ' Defaults to current directory if not specified.' - puts ' Should end in / if specified.' - puts ' root_path - Helpful for producing more verbose output if using relative paths.' - exit 1 - end - - protected - - def get_details(_result_file, lines) - results = { failures: [], ignores: [], successes: [] } - lines.each do |line| - _src_file, _src_line, _test_name, status, _msg = line.split(/:/) - line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\') - case status - when 'IGNORE' then results[:ignores] << line_out - when 'FAIL' then results[:failures] << line_out - when 'PASS' then results[:successes] << line_out - end - end - results - end - - def parse_test_summary(summary) - raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } - [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] - end - - def here - File.expand_path(File.dirname(__FILE__)) - end -end - -if $0 == __FILE__ - - # parse out the command options - opts, args = ARGV.partition { |v| v =~ /^--\w+/ } - opts.map! { |v| v[2..-1].to_sym } - - # create an instance to work with - uts = UnityTestSummary.new(opts) - - begin - # look in the specified or current directory for result files - args[0] ||= './' - targets = "#{ARGV[0].tr('\\', '/')}**/*.test*" - results = Dir[targets] - raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? - uts.targets = results - - # set the root path - args[1] ||= Dir.pwd + '/' - uts.root = ARGV[1] - - # run the summarizer - puts uts.run - rescue StandardError => e - uts.usage e.message - end -end diff --git a/components/cjson/cJSON/tests/unity/auto/unity_to_junit.py b/components/cjson/cJSON/tests/unity/auto/unity_to_junit.py deleted file mode 100644 index 71dd56888..000000000 --- a/components/cjson/cJSON/tests/unity/auto/unity_to_junit.py +++ /dev/null @@ -1,146 +0,0 @@ -import sys -import os -from glob import glob - -from pyparsing import * -from junit_xml import TestSuite, TestCase - - -class UnityTestSummary: - def __init__(self): - self.report = '' - self.total_tests = 0 - self.failures = 0 - self.ignored = 0 - self.targets = 0 - self.root = None - self.test_suites = dict() - - def run(self): - # Clean up result file names - results = [] - for target in self.targets: - results.append(target.replace('\\', '/')) - - # Dig through each result file, looking for details on pass/fail: - for result_file in results: - lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) - if len(lines) == 0: - raise Exception("Empty test result file: %s" % result_file) - - # define an expression for your file reference - entry_one = Combine( - oneOf(list(alphas)) + ':/' + - Word(alphanums + '_-./')) - - entry_two = Word(printables + ' ', excludeChars=':') - entry = entry_one | entry_two - - delimiter = Literal(':').suppress() - tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName( - 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName( - 'tc_status') + Optional( - delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") - - eol = LineEnd().suppress() - sol = LineStart().suppress() - blank_line = sol + eol - - tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( - "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( - "tc_summary") - tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") - - # run it and see... - pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) - pp1.ignore(blank_line | OneOrMore("-")) - - result = list() - for l in lines: - result.append((pp1.parseString(l)).asDict()) - # delete empty results - result = filter(None, result) - - tc_list = list() - for r in result: - if 'tc_line' in r: - tmp_tc_line = r['tc_line'] - - # get only the file name which will be used as the classname - file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] - tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) - if 'tc_status' in tmp_tc_line: - if str(tmp_tc_line['tc_status']) == 'IGNORE': - if 'tc_msg' in tmp_tc_line: - tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], - output=r'[File]={0}, [Line]={1}'.format( - tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) - else: - tmp_tc.add_skipped_info(message=" ") - elif str(tmp_tc_line['tc_status']) == 'FAIL': - if 'tc_msg' in tmp_tc_line: - tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], - output=r'[File]={0}, [Line]={1}'.format( - tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) - else: - tmp_tc.add_failure_info(message=" ") - - tc_list.append((str(result_file), tmp_tc)) - - for k, v in tc_list: - try: - self.test_suites[k].append(v) - except KeyError: - self.test_suites[k] = [v] - ts = [] - for suite_name in self.test_suites: - ts.append(TestSuite(suite_name, self.test_suites[suite_name])) - - with open('result.xml', 'w') as f: - TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') - - return self.report - - def set_targets(self, target_array): - self.targets = target_array - - def set_root_path(self, path): - self.root = path - - @staticmethod - def usage(err_msg=None): - print("\nERROR: ") - if err_msg: - print(err_msg) - print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") - print(" result_file_directory - The location of your results files.") - print(" Defaults to current directory if not specified.") - print(" Should end in / if specified.") - print(" root_path - Helpful for producing more verbose output if using relative paths.") - sys.exit(1) - - -if __name__ == '__main__': - uts = UnityTestSummary() - try: - # look in the specified or current directory for result files - if len(sys.argv) > 1: - targets_dir = sys.argv[1] - else: - targets_dir = './' - targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) - if len(targets) == 0: - raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) - uts.set_targets(targets) - - # set the root path - if len(sys.argv) > 2: - root_path = sys.argv[2] - else: - root_path = os.path.split(__file__)[0] - uts.set_root_path(root_path) - - # run the summarizer - print(uts.run()) - except Exception as e: - UnityTestSummary.usage(e) diff --git a/components/cjson/cJSON/tests/unity/docs/ThrowTheSwitchCodingStandard.md b/components/cjson/cJSON/tests/unity/docs/ThrowTheSwitchCodingStandard.md deleted file mode 100644 index a85adef3d..000000000 --- a/components/cjson/cJSON/tests/unity/docs/ThrowTheSwitchCodingStandard.md +++ /dev/null @@ -1,207 +0,0 @@ -# ThrowTheSwitch.org Coding Standard - -Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part, -we try to follow these standards to unify our contributors' code into a cohesive -unit (puns intended). You might find places where these standards aren't -followed. We're not perfect. Please be polite where you notice these discrepancies -and we'll try to be polite when we notice yours. - -;) - - -## Why Have A Coding Standard? - -Being consistent makes code easier to understand. We've made an attempt to keep -our standard simple because we also believe that we can only expect someone to -follow something that is understandable. Please do your best. - - -## Our Philosophy - -Before we get into details on syntax, let's take a moment to talk about our -vision for these tools. We're C developers and embedded software developers. -These tools are great to test any C code, but catering to embedded software has -made us more tolerant of compiler quirks. There are a LOT of quirky compilers -out there. By quirky I mean "doesn't follow standards because they feel like -they have a license to do as they wish." - -Our philosophy is "support every compiler we can". Most often, this means that -we aim for writing C code that is standards compliant (often C89... that seems -to be a sweet spot that is almost always compatible). But it also means these -tools are tolerant of things that aren't common. Some that aren't even -compliant. There are configuration options to override the size of standard -types. There are configuration options to force Unity to not use certain -standard library functions. A lot of Unity is configurable and we have worked -hard to make it not TOO ugly in the process. - -Similarly, our tools that parse C do their best. They aren't full C parsers -(yet) and, even if they were, they would still have to accept non-standard -additions like gcc extensions or specifying `@0x1000` to force a variable to -compile to a particular location. It's just what we do, because we like -everything to Just Work™. - -Speaking of having things Just Work™, that's our second philosophy. By that, we -mean that we do our best to have EVERY configuration option have a logical -default. We believe that if you're working with a simple compiler and target, -you shouldn't need to configure very much... we try to make the tools guess as -much as they can, but give the user the power to override it when it's wrong. - - -## Naming Things - -Let's talk about naming things. Programming is all about naming things. We name -files, functions, variables, and so much more. While we're not always going to -find the best name for something, we actually put quite a bit of effort into -finding *What Something WANTS to be Called*™. - -When naming things, we more or less follow this hierarchy, the first being the -most important to us (but we do all four whenever possible): -1. Readable -2. Descriptive -3. Consistent -4. Memorable - - -#### Readable - -We want to read our code. This means we like names and flow that are more -naturally read. We try to avoid double negatives. We try to avoid cryptic -abbreviations (sticking to ones we feel are common). - - -#### Descriptive - -We like descriptive names for things, especially functions and variables. -Finding the right name for something is an important endeavor. You might notice -from poking around our code that this often results in names that are a little -longer than the average. Guilty. We're okay with a tiny bit more typing if it -means our code is easier to understand. - -There are two exceptions to this rule that we also stick to as religiously as -possible: - -First, while we realize hungarian notation (and similar systems for encoding -type information into variable names) is providing a more descriptive name, we -feel that (for the average developer) it takes away from readability and -therefore is to be avoided. - -Second, loop counters and other local throw-away variables often have a purpose -which is obvious. There's no need, therefore, to get carried away with complex -naming. We find i, j, and k are better loop counters than loopCounterVar or -whatnot. We only break this rule when we see that more description could improve -understanding of an algorithm. - - -#### Consistent - -We like consistency, but we're not really obsessed with it. We try to name our -configuration macros in a consistent fashion... you'll notice a repeated use of -UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to -remember each macro's details. - - -#### Memorable - -Where ever it doesn't violate the above principles, we try to apply memorable -names. Sometimes this means using something that is simply descriptive, but -often we strive for descriptive AND unique... we like quirky names that stand -out in our memory and are easier to search for. Take a look through the file -names in Ceedling and you'll get a good idea of what we are talking about here. -Why use preprocess when you can use preprocessinator? Or what better describes a -module in charge of invoking tasks during releases than release_invoker? Don't -get carried away. The names are still descriptive and fulfill the above -requirements, but they don't feel stale. - - -## C and C++ Details - -We don't really want to add to the style battles out there. Tabs or spaces? -How many spaces? Where do the braces go? These are age-old questions that will -never be answered... or at least not answered in a way that will make everyone -happy. - -We've decided on our own style preferences. If you'd like to contribute to these -projects (and we hope that you do), then we ask if you do your best to follow -the same. It will only hurt a little. We promise. - - -#### Whitespace - -Our C-style is to use spaces and to use 4 of them per indent level. It's a nice -power-of-2 number that looks decent on a wide screen. We have no more reason -than that. We break that rule when we have lines that wrap (macros or function -arguments or whatnot). When that happens, we like to indent further to line -things up in nice tidy columns. - -```C - if (stuff_happened) - { - do_something(); - } -``` - - -#### Case - -- Files - all lower case with underscores. -- Variables - all lower case with underscores -- Macros - all caps with underscores. -- Typedefs - all caps with underscores. (also ends with _T). -- Functions - camel cased. Usually named ModuleName_FuncName -- Constants and Globals - camel cased. - - -#### Braces - -The left brace is on the next line after the declaration. The right brace is -directly below that. Everything in between in indented one level. If you're -catching an error and you have a one-line, go ahead and to it on the same line. - -```C - while (blah) - { - //Like so. Even if only one line, we use braces. - } -``` - - -#### Comments - -Do you know what we hate? Old-school C block comments. BUT, we're using them -anyway. As we mentioned, our goal is to support every compiler we can, -especially embedded compilers. There are STILL C compilers out there that only -support old-school block comments. So that is what we're using. We apologize. We -think they are ugly too. - - -## Ruby Details - -Is there really such thing as a Ruby coding standard? Ruby is such a free form -language, it seems almost sacrilegious to suggest that people should comply to -one method! We'll keep it really brief! - - -#### Whitespace - -Our Ruby style is to use spaces and to use 2 of them per indent level. It's a -nice power-of-2 number that really grooves with Ruby's compact style. We have no -more reason than that. We break that rule when we have lines that wrap. When -that happens, we like to indent further to line things up in nice tidy columns. - - -#### Case - -- Files - all lower case with underscores. -- Variables - all lower case with underscores -- Classes, Modules, etc - Camel cased. -- Functions - all lower case with underscores -- Constants - all upper case with underscores - - -## Documentation - -Egad. Really? We use markdown and we like pdf files because they can be made to -look nice while still being portable. Good enough? - - -*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/components/cjson/cJSON/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/components/cjson/cJSON/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf deleted file mode 100644 index 28f0c3214..000000000 Binary files a/components/cjson/cJSON/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf and /dev/null differ diff --git a/components/cjson/cJSON/tests/unity/docs/UnityAssertionsReference.md b/components/cjson/cJSON/tests/unity/docs/UnityAssertionsReference.md deleted file mode 100644 index 2dcf5e3a2..000000000 --- a/components/cjson/cJSON/tests/unity/docs/UnityAssertionsReference.md +++ /dev/null @@ -1,770 +0,0 @@ -# Unity Assertions Reference - -## Background and Overview - -### Super Condensed Version - -- An assertion establishes truth (i.e. boolean True) for a single condition. -Upon boolean False, an assertion stops execution and reports the failure. -- Unity is mainly a rich collection of assertions and the support to gather up -and easily execute those assertions. -- The structure of Unity allows you to easily separate test assertions from -source code in, well, test code. -- Unity's assertions: -- Come in many, many flavors to handle different C types and assertion cases. -- Use context to provide detailed and helpful failure messages. -- Document types, expected values, and basic behavior in your source code for -free. - - -### Unity Is Several Things But Mainly It's Assertions - -One way to think of Unity is simply as a rich collection of assertions you can -use to establish whether your source code behaves the way you think it does. -Unity provides a framework to easily organize and execute those assertions in -test code separate from your source code. - - -### What's an Assertion? - -At their core, assertions are an establishment of truth - boolean truth. Was this -thing equal to that thing? Does that code doohickey have such-and-such property -or not? You get the idea. Assertions are executable code (to appreciate the big -picture on this read up on the difference between -[link:Dynamic Verification and Static Analysis]). A failing assertion stops -execution and reports an error through some appropriate I/O channel (e.g. -stdout, GUI, file, blinky light). - -Fundamentally, for dynamic verification all you need is a single assertion -mechanism. In fact, that's what the [assert() macro in C's standard library](http://en.wikipedia.org/en/wiki/Assert.h) -is for. So why not just use it? Well, we can do far better in the reporting -department. C's `assert()` is pretty dumb as-is and is particularly poor for -handling common data types like arrays, structs, etc. And, without some other -support, it's far too tempting to litter source code with C's `assert()`'s. It's -generally much cleaner, manageable, and more useful to separate test and source -code in the way Unity facilitates. - - -### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation - -Asserting a simple truth condition is valuable, but using the context of the -assertion is even more valuable. For instance, if you know you're comparing bit -flags and not just integers, then why not use that context to give explicit, -readable, bit-level feedback when an assertion fails? - -That's what Unity's collection of assertions do - capture context to give you -helpful, meaningful assertion failure messages. In fact, the assertions -themselves also serve as executable documentation about types and values in your -source code. So long as your tests remain current with your source and all those -tests pass, you have a detailed, up-to-date view of the intent and mechanisms in -your source code. And due to a wondrous mystery, well-tested code usually tends -to be well designed code. - - -## Assertion Conventions and Configurations - -### Naming and Parameter Conventions - -The convention of assertion parameters generally follows this order: - - TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) - -The very simplest assertion possible uses only a single "actual" parameter (e.g. -a simple null check). - -"Actual" is the value being tested and unlike the other parameters in an -assertion construction is the only parameter present in all assertion variants. -"Modifiers" are masks, ranges, bit flag specifiers, floating point deltas. -"Expected" is your expected value (duh) to compare to an "actual" value; it's -marked as an optional parameter because some assertions only need a single -"actual" parameter (e.g. null check). -"Size/count" refers to string lengths, number of array elements, etc. - -Many of Unity's assertions are apparent duplications in that the same data type -is handled by several assertions. The differences among these are in how failure -messages are presented. For instance, a `_HEX` variant of an assertion prints -the expected and actual values of that assertion formatted as hexadecimal. - - -#### TEST_ASSERT_X_MESSAGE Variants - -_All_ assertions are complemented with a variant that includes a simple string -message as a final parameter. The string you specify is appended to an assertion -failure message in Unity output. - -For brevity, the assertion variants with a message parameter are not listed -below. Just tack on `_MESSAGE` as the final component to any assertion name in -the reference list below and add a string as the final parameter. - -_Example:_ - - TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) - -becomes messageified like thus... - - TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message ) - - -#### TEST_ASSERT_X_ARRAY Variants - -Unity provides a collection of assertions for arrays containing a variety of -types. These are documented in the Array section below. These are almost on par -with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity -type assertion you can tack on `_ARRAY` and run assertions on an entire block of -memory. - - TEST_ASSERT_EQUAL_TYPEX_ARRAY( expected, actual, {size/count} ) - -"Expected" is an array itself. -"Size/count" is one or two parameters necessary to establish the number of array -elements and perhaps the length of elements within the array. - -Notes: -- The `_MESSAGE` variant convention still applies here to array assertions. The -`_MESSAGE` variants of the `_ARRAY` assertions have names ending with -`_ARRAY_MESSAGE`. -- Assertions for handling arrays of floating point values are grouped with float -and double assertions (see immediately following section). - - -### TEST_ASSERT_EACH_EQUAL_X Variants - -Unity provides a collection of assertions for arrays containing a variety of -types which can be compared to a single value as well. These are documented in -the Each Equal section below. these are almost on par with the `_MESSAGE` -variants of Unity's Asserts in that for pretty much any Unity type assertion you -can inject _EACH_EQUAL and run assertions on an entire block of memory. - - TEST_ASSERT_EACH_EQUAL_TYPEX( expected, actual, {size/count} ) - -"Expected" is a single value to compare to. -"Actual" is an array where each element will be compared to the expected value. -"Size/count" is one of two parameters necessary to establish the number of array -elements and perhaps the length of elements within the array. - -Notes: -- The `_MESSAGE` variant convention still applies here to Each Equal assertions. -- Assertions for handling Each Equal of floating point values are grouped with -float and double assertions (see immediately following section). - - -### Configuration - -#### Floating Point Support Is Optional - -Support for floating point types is configurable. That is, by defining the -appropriate preprocessor symbols, floats and doubles can be individually enabled -or disabled in Unity code. This is useful for embedded targets with no floating -point math support (i.e. Unity compiles free of errors for fixed point only -platforms). See Unity documentation for specifics. - - -#### Maximum Data Type Width Is Configurable - -Not all targets support 64 bit wide types or even 32 bit wide types. Define the -appropriate preprocessor symbols and Unity will omit all operations from -compilation that exceed the maximum width of your target. See Unity -documentation for specifics. - - -## The Assertions in All Their Blessed Glory - -### Basic Fail and Ignore - -##### `TEST_FAIL()` - -This fella is most often used in special conditions where your test code is -performing logic beyond a simple assertion. That is, in practice, `TEST_FAIL()` -will always be found inside a conditional code block. - -_Examples:_ -- Executing a state machine multiple times that increments a counter your test -code then verifies as a final step. -- Triggering an exception and verifying it (as in Try / Catch / Throw - see the -[CException](https://github.com/ThrowTheSwitch/CException) project). - -##### `TEST_IGNORE()` - -Marks a test case (i.e. function meant to contain test assertions) as ignored. -Usually this is employed as a breadcrumb to come back and implement a test case. -An ignored test case has effects if other assertions are in the enclosing test -case (see Unity documentation for more). - -### Boolean - -##### `TEST_ASSERT (condition)` - -##### `TEST_ASSERT_TRUE (condition)` - -##### `TEST_ASSERT_FALSE (condition)` - -##### `TEST_ASSERT_UNLESS (condition)` - -A simple wording variation on `TEST_ASSERT_FALSE`.The semantics of -`TEST_ASSERT_UNLESS` aid readability in certain test constructions or -conditional statements. - -##### `TEST_ASSERT_NULL (pointer)` - -##### `TEST_ASSERT_NOT_NULL (pointer)` - - -### Signed and Unsigned Integers (of all sizes) - -Large integer sizes can be disabled for build targets that do not support them. -For example, if your target only supports up to 16 bit types, by defining the -appropriate symbols Unity can be configured to omit 32 and 64 bit operations -that would break compilation (see Unity documentation for more). Refer to -Advanced Asserting later in this document for advice on dealing with other word -sizes. - -##### `TEST_ASSERT_EQUAL_INT (expected, actual)` - -##### `TEST_ASSERT_EQUAL_INT8 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_INT16 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_INT32 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_INT64 (expected, actual)` - -##### `TEST_ASSERT_EQUAL (expected, actual)` - -##### `TEST_ASSERT_NOT_EQUAL (expected, actual)` - -##### `TEST_ASSERT_EQUAL_UINT (expected, actual)` - -##### `TEST_ASSERT_EQUAL_UINT8 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_UINT16 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_UINT32 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_UINT64 (expected, actual)` - - -### Unsigned Integers (of all sizes) in Hexadecimal - -All `_HEX` assertions are identical in function to unsigned integer assertions -but produce failure messages with the `expected` and `actual` values formatted -in hexadecimal. Unity output is big endian. - -##### `TEST_ASSERT_EQUAL_HEX (expected, actual)` - -##### `TEST_ASSERT_EQUAL_HEX8 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_HEX16 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_HEX32 (expected, actual)` - -##### `TEST_ASSERT_EQUAL_HEX64 (expected, actual)` - - -### Masked and Bit-level Assertions - -Masked and bit-level assertions produce output formatted in hexadecimal. Unity -output is big endian. - - -##### `TEST_ASSERT_BITS (mask, expected, actual)` - -Only compares the masked (i.e. high) bits of `expected` and `actual` parameters. - - -##### `TEST_ASSERT_BITS_HIGH (mask, actual)` - -Asserts the masked bits of the `actual` parameter are high. - - -##### `TEST_ASSERT_BITS_LOW (mask, actual)` - -Asserts the masked bits of the `actual` parameter are low. - - -##### `TEST_ASSERT_BIT_HIGH (bit, actual)` - -Asserts the specified bit of the `actual` parameter is high. - - -##### `TEST_ASSERT_BIT_LOW (bit, actual)` - -Asserts the specified bit of the `actual` parameter is low. - -### Integer Less Than / Greater Than - -These assertions verify that the `actual` parameter is less than or greater -than `threshold` (exclusive). For example, if the threshold value is 0 for the -greater than assertion will fail if it is 0 or less. - -##### `TEST_ASSERT_GREATER_THAN (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_INT (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_INT8 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_INT16 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_INT32 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_UINT (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_UINT8 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_UINT16 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_UINT32 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_HEX8 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_HEX16 (threshold, actual)` - -##### `TEST_ASSERT_GREATER_THAN_HEX32 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_INT (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_INT8 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_INT16 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_INT32 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_UINT (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_UINT8 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_UINT16 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_UINT32 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_HEX8 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_HEX16 (threshold, actual)` - -##### `TEST_ASSERT_LESS_THAN_HEX32 (threshold, actual)` - - -### Integer Ranges (of all sizes) - -These assertions verify that the `expected` parameter is within +/- `delta` -(inclusive) of the `actual` parameter. For example, if the expected value is 10 -and the delta is 3 then the assertion will fail for any value outside the range -of 7 - 13. - -##### `TEST_ASSERT_INT_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_INT8_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_INT16_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_INT32_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_INT64_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_UINT_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_UINT8_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_UINT16_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_UINT32_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_UINT64_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_HEX_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_HEX8_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_HEX16_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_HEX32_WITHIN (delta, expected, actual)` - -##### `TEST_ASSERT_HEX64_WITHIN (delta, expected, actual)` - - -### Structs and Strings - -##### `TEST_ASSERT_EQUAL_PTR (expected, actual)` - -Asserts that the pointers point to the same memory location. - - -##### `TEST_ASSERT_EQUAL_STRING (expected, actual)` - -Asserts that the null terminated (`'\0'`)strings are identical. If strings are -of different lengths or any portion of the strings before their terminators -differ, the assertion fails. Two NULL strings (i.e. zero length) are considered -equivalent. - - -##### `TEST_ASSERT_EQUAL_MEMORY (expected, actual, len)` - -Asserts that the contents of the memory specified by the `expected` and `actual` -pointers is identical. The size of the memory blocks in bytes is specified by -the `len` parameter. - - -### Arrays - -`expected` and `actual` parameters are both arrays. `num_elements` specifies the -number of elements in the arrays to compare. - -`_HEX` assertions produce failure messages with expected and actual array -contents formatted in hexadecimal. - -For array of strings comparison behavior, see comments for -`TEST_ASSERT_EQUAL_STRING` in the preceding section. - -Assertions fail upon the first element in the compared arrays found not to -match. Failure messages specify the array index of the failed comparison. - -##### `TEST_ASSERT_EQUAL_INT_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_INT8_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_INT16_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_INT32_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_INT64_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_UINT_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_UINT16_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_UINT32_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_UINT64_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_HEX_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_HEX8_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_HEX16_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_HEX32_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_HEX64_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_PTR_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_STRING_ARRAY (expected, actual, num_elements)` - -##### `TEST_ASSERT_EQUAL_MEMORY_ARRAY (expected, actual, len, num_elements)` - -`len` is the memory in bytes to be compared at each array element. - - -### Each Equal (Arrays to Single Value) - -`expected` are single values and `actual` are arrays. `num_elements` specifies -the number of elements in the arrays to compare. - -`_HEX` assertions produce failure messages with expected and actual array -contents formatted in hexadecimal. - -Assertions fail upon the first element in the compared arrays found not to -match. Failure messages specify the array index of the failed comparison. - -#### `TEST_ASSERT_EACH_EQUAL_INT (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_INT8 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_INT16 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_INT32 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_INT64 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_UINT (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_UINT8 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_UINT16 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_UINT32 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_UINT64 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_HEX (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_HEX8 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_HEX16 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_HEX32 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_HEX64 (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_PTR (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_STRING (expected, actual, num_elements)` - -#### `TEST_ASSERT_EACH_EQUAL_MEMORY (expected, actual, len, num_elements)` - -`len` is the memory in bytes to be compared at each array element. - - -### Floating Point (If enabled) - -##### `TEST_ASSERT_FLOAT_WITHIN (delta, expected, actual)` - -Asserts that the `actual` value is within +/- `delta` of the `expected` value. -The nature of floating point representation is such that exact evaluations of -equality are not guaranteed. - - -##### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)` - -Asserts that the ?actual?value is "close enough to be considered equal" to the -`expected` value. If you are curious about the details, refer to the Advanced -Asserting section for more details on this. Omitting a user-specified delta in a -floating point assertion is both a shorthand convenience and a requirement of -code generation conventions for CMock. - - -##### `TEST_ASSERT_EQUAL_FLOAT_ARRAY (expected, actual, num_elements)` - -See Array assertion section for details. Note that individual array element -float comparisons are executed using T?EST_ASSERT_EQUAL_FLOAT?.That is, user -specified delta comparison values requires a custom-implemented floating point -array assertion. - - -##### `TEST_ASSERT_FLOAT_IS_INF (actual)` - -Asserts that `actual` parameter is equivalent to positive infinity floating -point representation. - - -##### `TEST_ASSERT_FLOAT_IS_NEG_INF (actual)` - -Asserts that `actual` parameter is equivalent to negative infinity floating -point representation. - - -##### `TEST_ASSERT_FLOAT_IS_NAN (actual)` - -Asserts that `actual` parameter is a Not A Number floating point representation. - - -##### `TEST_ASSERT_FLOAT_IS_DETERMINATE (actual)` - -Asserts that ?actual?parameter is a floating point representation usable for -mathematical operations. That is, the `actual` parameter is neither positive -infinity nor negative infinity nor Not A Number floating point representations. - - -##### `TEST_ASSERT_FLOAT_IS_NOT_INF (actual)` - -Asserts that `actual` parameter is a value other than positive infinity floating -point representation. - - -##### `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF (actual)` - -Asserts that `actual` parameter is a value other than negative infinity floating -point representation. - - -##### `TEST_ASSERT_FLOAT_IS_NOT_NAN (actual)` - -Asserts that `actual` parameter is a value other than Not A Number floating -point representation. - - -##### `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE (actual)` - -Asserts that `actual` parameter is not usable for mathematical operations. That -is, the `actual` parameter is either positive infinity or negative infinity or -Not A Number floating point representations. - - -### Double (If enabled) - -##### `TEST_ASSERT_DOUBLE_WITHIN (delta, expected, actual)` - -Asserts that the `actual` value is within +/- `delta` of the `expected` value. -The nature of floating point representation is such that exact evaluations of -equality are not guaranteed. - - -##### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)` - -Asserts that the `actual` value is "close enough to be considered equal" to the -`expected` value. If you are curious about the details, refer to the Advanced -Asserting section for more details. Omitting a user-specified delta in a -floating point assertion is both a shorthand convenience and a requirement of -code generation conventions for CMock. - - -##### `TEST_ASSERT_EQUAL_DOUBLE_ARRAY (expected, actual, num_elements)` - -See Array assertion section for details. Note that individual array element -double comparisons are executed using `TEST_ASSERT_EQUAL_DOUBLE`.That is, user -specified delta comparison values requires a custom implemented double array -assertion. - - -##### `TEST_ASSERT_DOUBLE_IS_INF (actual)` - -Asserts that `actual` parameter is equivalent to positive infinity floating -point representation. - - -##### `TEST_ASSERT_DOUBLE_IS_NEG_INF (actual)` - -Asserts that `actual` parameter is equivalent to negative infinity floating point -representation. - - -##### `TEST_ASSERT_DOUBLE_IS_NAN (actual)` - -Asserts that `actual` parameter is a Not A Number floating point representation. - - -##### `TEST_ASSERT_DOUBLE_IS_DETERMINATE (actual)` - -Asserts that `actual` parameter is a floating point representation usable for -mathematical operations. That is, the ?actual?parameter is neither positive -infinity nor negative infinity nor Not A Number floating point representations. - - -##### `TEST_ASSERT_DOUBLE_IS_NOT_INF (actual)` - -Asserts that `actual` parameter is a value other than positive infinity floating -point representation. - - -##### `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF (actual)` - -Asserts that `actual` parameter is a value other than negative infinity floating -point representation. - - -##### `TEST_ASSERT_DOUBLE_IS_NOT_NAN (actual)` - -Asserts that `actual` parameter is a value other than Not A Number floating -point representation. - - -##### `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE (actual)` - -Asserts that `actual` parameter is not usable for mathematical operations. That -is, the `actual` parameter is either positive infinity or negative infinity or -Not A Number floating point representations. - - -## Advanced Asserting: Details On Tricky Assertions - -This section helps you understand how to deal with some of the trickier -assertion situations you may run into. It will give you a glimpse into some of -the under-the-hood details of Unity's assertion mechanisms. If you're one of -those people who likes to know what is going on in the background, read on. If -not, feel free to ignore the rest of this document until you need it. - - -### How do the EQUAL assertions work for FLOAT and DOUBLE? - -As you may know, directly checking for equality between a pair of floats or a -pair of doubles is sloppy at best and an outright no-no at worst. Floating point -values can often be represented in multiple ways, particularly after a series of -operations on a value. Initializing a variable to the value of 2.0 is likely to -result in a floating point representation of 2 x 20,but a series of -mathematical operations might result in a representation of 8 x 2-2 -that also evaluates to a value of 2. At some point repeated operations cause -equality checks to fail. - -So Unity doesn't do direct floating point comparisons for equality. Instead, it -checks if two floating point values are "really close." If you leave Unity -running with defaults, "really close" means "within a significant bit or two." -Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN` -with the `delta` parameter calculated on the fly. For single precision, delta is -the expected value multiplied by 0.00001, producing a very small proportional -range around the expected value. - -If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So -any value between 19,999.8 and 20,000.2 will satisfy the equality check. This -works out to be roughly a single bit of range for a single-precision number, and -that's just about as tight a tolerance as you can reasonably get from a floating -point value. - -So what happens when it's zero? Zero - even more than other floating point -values - can be represented many different ways. It doesn't matter if you have -0 x 20or 0 x 263.It's still zero, right? Luckily, if you -subtract these values from each other, they will always produce a difference of -zero, which will still fall between 0 plus or minus a delta of 0. So it still -works! - -Double precision floating point numbers use a much smaller multiplier, again -approximating a single bit of error. - -If you don't like these ranges and you want to make your floating point equality -assertions less strict, you can change these multipliers to whatever you like by -defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity -documentation for more. - - -### How do we deal with targets with non-standard int sizes? - -It's "fun" that C is a standard where something as fundamental as an integer -varies by target. According to the C standard, an `int` is to be the target's -natural register size, and it should be at least 16-bits and a multiple of a -byte. It also guarantees an order of sizes: - -```C -char <= short <= int <= long <= long long -``` - -Most often, `int` is 32-bits. In many cases in the embedded world, `int` is -16-bits. There are rare microcontrollers out there that have 24-bit integers, -and this remains perfectly standard C. - -To make things even more interesting, there are compilers and targets out there -that have a hard choice to make. What if their natural register size is 10-bits -or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least -16-bits AND the requirement to match the natural register size. In these -situations, they often choose the natural register size, leaving us with -something like this: - -```C -char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit) -``` - -Um... yikes. It's obviously breaking a rule or two... but they had to break SOME -rules, so they made a choice. - -When the C99 standard rolled around, it introduced alternate standard-size types. -It also introduced macros for pulling in MIN/MAX values for your integer types. -It's glorious! Unfortunately, many embedded compilers can't be relied upon to -use the C99 types (Sometimes because they have weird register sizes as described -above. Sometimes because they don't feel like it?). - -A goal of Unity from the beginning was to support every combination of -microcontroller or microprocessor and C compiler. Over time, we've gotten really -close to this. There are a few tricks that you should be aware of, though, if -you're going to do this effectively on some of these more idiosyncratic targets. - -First, when setting up Unity for a new target, you're going to want to pay -special attention to the macros for automatically detecting types -(where available) or manually configuring them yourself. You can get information -on both of these in Unity's documentation. - -What about the times where you suddenly need to deal with something odd, like a -24-bit `int`? The simplest solution is to use the next size up. If you have a -24-bit `int`, configure Unity to use 32-bit integers. If you have a 12-bit -`int`, configure Unity to use 16 bits. There are two ways this is going to -affect you: - -1. When Unity displays errors for you, it's going to pad the upper unused bits -with zeros. -2. You're going to have to be careful of assertions that perform signed -operations, particularly `TEST_ASSERT_INT_WITHIN`.Such assertions might wrap -your `int` in the wrong place, and you could experience false failures. You can -always back down to a simple `TEST_ASSERT` and do the operations yourself. - - -*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/components/cjson/cJSON/tests/unity/docs/UnityConfigurationGuide.md b/components/cjson/cJSON/tests/unity/docs/UnityConfigurationGuide.md deleted file mode 100644 index 96e5358d4..000000000 --- a/components/cjson/cJSON/tests/unity/docs/UnityConfigurationGuide.md +++ /dev/null @@ -1,435 +0,0 @@ -# Unity Configuration Guide - -## C Standards, Compilers and Microcontrollers - -The embedded software world contains its challenges. Compilers support different -revisions of the C Standard. They ignore requirements in places, sometimes to -make the language more usable in some special regard. Sometimes it's to simplify -their support. Sometimes it's due to specific quirks of the microcontroller they -are targeting. Simulators add another dimension to this menagerie. - -Unity is designed to run on almost anything that is targeted by a C compiler. It -would be awesome if this could be done with zero configuration. While there are -some targets that come close to this dream, it is sadly not universal. It is -likely that you are going to need at least a couple of the configuration options -described in this document. - -All of Unity's configuration options are `#defines`. Most of these are simple -definitions. A couple are macros with arguments. They live inside the -unity_internals.h header file. We don't necessarily recommend opening that file -unless you really need to. That file is proof that a cross-platform library is -challenging to build. From a more positive perspective, it is also proof that a -great deal of complexity can be centralized primarily to one place in order to -provide a more consistent and simple experience elsewhere. - - -### Using These Options - -It doesn't matter if you're using a target-specific compiler and a simulator or -a native compiler. In either case, you've got a couple choices for configuring -these options: - -1. Because these options are specified via C defines, you can pass most of these -options to your compiler through command line compiler flags. Even if you're -using an embedded target that forces you to use their overbearing IDE for all -configuration, there will be a place somewhere in your project to configure -defines for your compiler. -2. You can create a custom `unity_config.h` configuration file (present in your -toolchain's search paths). In this file, you will list definitions and macros -specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and -Unity will rely on `unity_config.h` for any further definitions it may need. - - -## The Options - -### Integer Types - -If you've been a C developer for long, you probably already know that C's -concept of an integer varies from target to target. The C Standard has rules -about the `int` matching the register size of the target microprocessor. It has -rules about the `int` and how its size relates to other integer types. An `int` -on one target might be 16 bits while on another target it might be 64. There are -more specific types in compilers compliant with C99 or later, but that's -certainly not every compiler you are likely to encounter. Therefore, Unity has a -number of features for helping to adjust itself to match your required integer -sizes. It starts off by trying to do it automatically. - - -##### `UNITY_EXCLUDE_STDINT_H` - -The first thing that Unity does to guess your types is check `stdint.h`. -This file includes defines like `UINT_MAX` that Unity can make use of to -learn a lot about your system. It's possible you don't want it to do this -(um. why not?) or (more likely) it's possible that your system doesn't -support `stdint.h`. If that's the case, you're going to want to define this. -That way, Unity will know to skip the inclusion of this file and you won't -be left with a compiler error. - -_Example:_ - #define UNITY_EXCLUDE_STDINT_H - - -##### `UNITY_EXCLUDE_LIMITS_H` - -The second attempt to guess your types is to check `limits.h`. Some compilers -that don't support `stdint.h` could include `limits.h` instead. If you don't -want Unity to check this file either, define this to make it skip the inclusion. - -_Example:_ - #define UNITY_EXCLUDE_LIMITS_H - - -If you've disabled both of the automatic options above, you're going to have to -do the configuration yourself. Don't worry. Even this isn't too bad... there are -just a handful of defines that you are going to specify if you don't like the -defaults. - - -##### `UNITY_INT_WIDTH` - -Define this to be the number of bits an `int` takes up on your system. The -default, if not autodetected, is 32 bits. - -_Example:_ - #define UNITY_INT_WIDTH 16 - - -##### `UNITY_LONG_WIDTH` - -Define this to be the number of bits a `long` takes up on your system. The -default, if not autodetected, is 32 bits. This is used to figure out what kind -of 64-bit support your system can handle. Does it need to specify a `long` or a -`long long` to get a 64-bit value. On 16-bit systems, this option is going to be -ignored. - -_Example:_ - #define UNITY_LONG_WIDTH 16 - - -##### `UNITY_POINTER_WIDTH` - -Define this to be the number of bits a pointer takes up on your system. The -default, if not autodetected, is 32-bits. If you're getting ugly compiler -warnings about casting from pointers, this is the one to look at. - -_Example:_ - #define UNITY_POINTER_WIDTH 64 - - -##### `UNITY_SUPPORT_64` - -Unity will automatically include 64-bit support if it auto-detects it, or if -your `int`, `long`, or pointer widths are greater than 32-bits. Define this to -enable 64-bit support if none of the other options already did it for you. There -can be a significant size and speed impact to enabling 64-bit support on small -targets, so don't define it if you don't need it. - -_Example:_ - #define UNITY_SUPPORT_64 - - -### Floating Point Types - -In the embedded world, it's not uncommon for targets to have no support for -floating point operations at all or to have support that is limited to only -single precision. We are able to guess integer sizes on the fly because integers -are always available in at least one size. Floating point, on the other hand, is -sometimes not available at all. Trying to include `float.h` on these platforms -would result in an error. This leaves manual configuration as the only option. - - -##### `UNITY_INCLUDE_FLOAT` - -##### `UNITY_EXCLUDE_FLOAT` - -##### `UNITY_INCLUDE_DOUBLE` - -##### `UNITY_EXCLUDE_DOUBLE` - -By default, Unity guesses that you will want single precision floating point -support, but not double precision. It's easy to change either of these using the -include and exclude options here. You may include neither, either, or both, as -suits your needs. For features that are enabled, the following floating point -options also become available. - -_Example:_ - - //what manner of strange processor is this? - #define UNITY_EXCLUDE_FLOAT - #define UNITY_INCLUDE_DOUBLE - - -##### `UNITY_EXCLUDE_FLOAT_PRINT` - -Unity aims for as small of a footprint as possible and avoids most standard -library calls (some embedded platforms don’t have a standard library!). Because -of this, its routines for printing integer values are minimalist and hand-coded. -Therefore, the display of floating point values during a failure are optional. -By default, Unity will print the actual results of floating point assertion -failure (e.g. ”Expected 4.56 Was 4.68”). To not include this extra support, you -can use this define to instead respond to a failed assertion with a message like -”Values Not Within Delta”. If you would like verbose failure messages for floating -point assertions, use these options to give more explicit failure messages. - -_Example:_ - #define UNITY_EXCLUDE_FLOAT_PRINT - - -##### `UNITY_FLOAT_TYPE` - -If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C -floats. If your compiler supports a specialty floating point type, you can -always override this behavior by using this definition. - -_Example:_ - #define UNITY_FLOAT_TYPE float16_t - - -##### `UNITY_DOUBLE_TYPE` - -If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C -doubles. If you would like to change this, you can specify something else by -using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double` -could enable gargantuan floating point types on your 64-bit processor instead of -the standard `double`. - -_Example:_ - #define UNITY_DOUBLE_TYPE long double - - -##### `UNITY_FLOAT_PRECISION` - -##### `UNITY_DOUBLE_PRECISION` - -If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as -documented in the big daddy Unity Assertion Guide, you will learn that they are -not really asserting that two values are equal but rather that two values are -"close enough" to equal. "Close enough" is controlled by these precision -configuration options. If you are working with 32-bit floats and/or 64-bit -doubles (the normal on most processors), you should have no need to change these -options. They are both set to give you approximately 1 significant bit in either -direction. The float precision is 0.00001 while the double is 10-12. -For further details on how this works, see the appendix of the Unity Assertion -Guide. - -_Example:_ - #define UNITY_FLOAT_PRECISION 0.001f - - -### Toolset Customization - -In addition to the options listed above, there are a number of other options -which will come in handy to customize Unity's behavior for your specific -toolchain. It is possible that you may not need to touch any of these... but -certain platforms, particularly those running in simulators, may need to jump -through extra hoops to operate properly. These macros will help in those -situations. - - -##### `UNITY_OUTPUT_CHAR(a)` - -##### `UNITY_OUTPUT_FLUSH()` - -##### `UNITY_OUTPUT_START()` - -##### `UNITY_OUTPUT_COMPLETE()` - -By default, Unity prints its results to `stdout` as it runs. This works -perfectly fine in most situations where you are using a native compiler for -testing. It works on some simulators as well so long as they have `stdout` -routed back to the command line. There are times, however, where the simulator -will lack support for dumping results or you will want to route results -elsewhere for other reasons. In these cases, you should define the -`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as -an `int`, since this is the parameter type of the standard C `putchar` function -most commonly used). You may replace this with whatever function call you like. - -_Example:_ -Say you are forced to run your test suite on an embedded processor with no -`stdout` option. You decide to route your test result output to a custom serial -`RS232_putc()` function you wrote like thus: - - #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) - #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) - #define UNITY_OUTPUT_FLUSH() RS232_flush() - #define UNITY_OUTPUT_COMPLETE() RS232_close() - -_Note:_ -`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by -specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required. If you -specify a custom flush function instead with `UNITY_OUTPUT_FLUSH` directly, it -will declare an instance of your function by default. If you want to disable -this behavior, add `UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION`. - - -##### `UNITY_WEAK_ATTRIBUTE` - -##### `UNITY_WEAK_PRAGMA` - -##### `UNITY_NO_WEAK` - -For some targets, Unity can make the otherwise required setUp() and tearDown() -functions optional. This is a nice convenience for test writers since setUp and -tearDown don’t often actually do anything. If you’re using gcc or clang, this -option is automatically defined for you. Other compilers can also support this -behavior, if they support a C feature called weak functions. A weak function is -a function that is compiled into your executable unless a non-weak version of -the same function is defined elsewhere. If a non-weak version is found, the weak -version is ignored as if it never existed. If your compiler supports this feature, -you can let Unity know by defining UNITY_WEAK_ATTRIBUTE or UNITY_WEAK_PRAGMA as -the function attributes that would need to be applied to identify a function as -weak. If your compiler lacks support for weak functions, you will always need to -define setUp and tearDown functions (though they can be and often will be just -empty). You can also force Unity to NOT use weak functions by defining -UNITY_NO_WEAK. The most common options for this feature are: - -_Example:_ - #define UNITY_WEAK_ATTRIBUTE weak - #define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) - #define UNITY_WEAK_PRAGMA - #define UNITY_NO_WEAK - - -##### `UNITY_PTR_ATTRIBUTE` - -Some compilers require a custom attribute to be assigned to pointers, like -`near` or `far`. In these cases, you can give Unity a safe default for these by -defining this option with the attribute you would like. - -_Example:_ - #define UNITY_PTR_ATTRIBUTE __attribute__((far)) - #define UNITY_PTR_ATTRIBUTE near - - -##### `UNITY_PRINT_EOL` - -By default, Unity outputs \n at the end of each line of output. This is easy -to parse by the scripts, by Ceedling, etc, but it might not be ideal for YOUR -system. Feel free to override this and to make it whatever you wish. - -_Example:_ - #define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\r'); UNITY_OUTPUT_CHAR('\n') } - - - -##### `UNITY_EXCLUDE_DETAILS` - -This is an option for if you absolutely must squeeze every byte of memory out of -your system. Unity stores a set of internal scratchpads which are used to pass -extra detail information around. It's used by systems like CMock in order to -report which function or argument flagged an error. If you're not using CMock and -you're not using these details for other things, then you can exclude them. - -_Example:_ - #define UNITY_EXCLUDE_DETAILS - - - -##### `UNITY_EXCLUDE_SETJMP` - -If your embedded system doesn't support the standard library setjmp, you can -exclude Unity's reliance on this by using this define. This dropped dependence -comes at a price, though. You will be unable to use custom helper functions for -your tests, and you will be unable to use tools like CMock. Very likely, if your -compiler doesn't support setjmp, you wouldn't have had the memory space for those -things anyway, though... so this option exists for those situations. - -_Example:_ - #define UNITY_EXCLUDE_SETJMP - -##### `UNITY_OUTPUT_COLOR` - -If you want to add color using ANSI escape codes you can use this define. -t -_Example:_ - #define UNITY_OUTPUT_COLOR - - - -## Getting Into The Guts - -There will be cases where the options above aren't quite going to get everything -perfect. They are likely sufficient for any situation where you are compiling -and executing your tests with a native toolchain (e.g. clang on Mac). These -options may even get you through the majority of cases encountered in working -with a target simulator run from your local command line. But especially if you -must run your test suite on your target hardware, your Unity configuration will -require special help. This special help will usually reside in one of two -places: the `main()` function or the `RUN_TEST` macro. Let's look at how these -work. - - -##### `main()` - -Each test module is compiled and run on its own, separate from the other test -files in your project. Each test file, therefore, has a `main` function. This -`main` function will need to contain whatever code is necessary to initialize -your system to a workable state. This is particularly true for situations where -you must set up a memory map or initialize a communication channel for the -output of your test results. - -A simple main function looks something like this: - - int main(void) { - UNITY_BEGIN(); - RUN_TEST(test_TheFirst); - RUN_TEST(test_TheSecond); - RUN_TEST(test_TheThird); - return UNITY_END(); - } - -You can see that our main function doesn't bother taking any arguments. For our -most barebones case, we'll never have arguments because we just run all the -tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test -(in whatever order we wish). Finally, we call `UNITY_END`, returning its return -value (which is the total number of failures). - -It should be easy to see that you can add code before any test cases are run or -after all the test cases have completed. This allows you to do any needed -system-wide setup or teardown that might be required for your special -circumstances. - - -##### `RUN_TEST` - -The `RUN_TEST` macro is called with each test case function. Its job is to -perform whatever setup and teardown is necessary for executing a single test -case function. This includes catching failures, calling the test module's -`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If -using CMock or test coverage, there will be additional stubs in use here. A -simple minimalist RUN_TEST macro looks something like this: - - #define RUN_TEST(testfunc) \ - UNITY_NEW_TEST(#testfunc) \ - if (TEST_PROTECT()) { \ - setUp(); \ - testfunc(); \ - } \ - if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \ - tearDown(); \ - UnityConcludeTest(); - -So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity -has to deal with for every single test case. For each test case, we declare that -it is a new test. Then we run `setUp` and our test function. These are run -within a `TEST_PROTECT` block, the function of which is to handle failures that -occur during the test. Then, assuming our test is still running and hasn't been -ignored, we run `tearDown`. No matter what, our last step is to conclude this -test before moving on to the next. - -Let's say you need to add a call to `fsync` to force all of your output data to -flush to a file after each test. You could easily insert this after your -`UnityConcludeTest` call. Maybe you want to write an xml tag before and after -each result set. Again, you could do this by adding lines to this macro. Updates -to this macro are for the occasions when you need an action before or after -every single test case throughout your entire suite of tests. - - -## Happy Porting - -The defines and macros in this guide should help you port Unity to just about -any C target we can imagine. If you run into a snag or two, don't be afraid of -asking for help on the forums. We love a good challenge! - - -*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/components/cjson/cJSON/tests/unity/docs/UnityGettingStartedGuide.md b/components/cjson/cJSON/tests/unity/docs/UnityGettingStartedGuide.md deleted file mode 100644 index 50fc91c70..000000000 --- a/components/cjson/cJSON/tests/unity/docs/UnityGettingStartedGuide.md +++ /dev/null @@ -1,191 +0,0 @@ -# Unity - Getting Started - -## Welcome - -Congratulations. You're now the proud owner of your very own pile of bits! What -are you going to do with all these ones and zeros? This document should be able -to help you decide just that. - -Unity is a unit test framework. The goal has been to keep it small and -functional. The core Unity test framework is three files: a single C file and a -couple header files. These team up to provide functions and macros to make -testing easier. - -Unity was designed to be cross platform. It works hard to stick with C standards -while still providing support for the many embedded C compilers that bend the -rules. Unity has been used with many compilers, including GCC, IAR, Clang, -Green Hills, Microchip, and MS Visual Studio. It's not much work to get it to -work with a new target. - - -### Overview of the Documents - -#### Unity Assertions reference - -This document will guide you through all the assertion options provided by -Unity. This is going to be your unit testing bread and butter. You'll spend more -time with assertions than any other part of Unity. - - -#### Unity Assertions Cheat Sheet - -This document contains an abridged summary of the assertions described in the -previous document. It's perfect for printing and referencing while you -familiarize yourself with Unity's options. - - -#### Unity Configuration Guide - -This document is the one to reference when you are going to use Unity with a new -target or compiler. It'll guide you through the configuration options and will -help you customize your testing experience to meet your needs. - - -#### Unity Helper Scripts - -This document describes the helper scripts that are available for simplifying -your testing workflow. It describes the collection of optional Ruby scripts -included in the auto directory of your Unity installation. Neither Ruby nor -these scripts are necessary for using Unity. They are provided as a convenience -for those who wish to use them. - - -#### Unity License - -What's an open source project without a license file? This brief document -describes the terms you're agreeing to when you use this software. Basically, we -want it to be useful to you in whatever context you want to use it, but please -don't blame us if you run into problems. - - -### Overview of the Folders - -If you have obtained Unity through Github or something similar, you might be -surprised by just how much stuff you suddenly have staring you in the face. -Don't worry, Unity itself is very small. The rest of it is just there to make -your life easier. You can ignore it or use it at your convenience. Here's an -overview of everything in the project. - -- `src` - This is the code you care about! This folder contains a C file and two -header files. These three files _are_ Unity. -- `docs` - You're reading this document, so it's possible you have found your way -into this folder already. This is where all the handy documentation can be -found. -- `examples` - This contains a few examples of using Unity. -- `extras` - These are optional add ons to Unity that are not part of the core -project. If you've reached us through James Grenning's book, you're going to -want to look here. -- `test` - This is how Unity and its scripts are all tested. If you're just using -Unity, you'll likely never need to go in here. If you are the lucky team member -who gets to port Unity to a new toolchain, this is a good place to verify -everything is configured properly. -- `auto` - Here you will find helpful Ruby scripts for simplifying your test -workflow. They are purely optional and are not required to make use of Unity. - - -## How to Create A Test File - -Test files are C files. Most often you will create a single test file for each C -module that you want to test. The test file should include unity.h and the -header for your C module to be tested. - -Next, a test file will include a `setUp()` and `tearDown()` function. The setUp -function can contain anything you would like to run before each test. The -tearDown function can contain anything you would like to run after each test. -Both functions accept no arguments and return nothing. You may leave either or -both of these blank if you have no need for them. If you're using a compiler -that is configured to make these functions optional, you may leave them off -completely. Not sure? Give it a try. If you compiler complains that it can't -find setUp or tearDown when it links, you'll know you need to at least include -an empty function for these. - -The majority of the file will be a series of test functions. Test functions -follow the convention of starting with the word "test" or "spec". You don't HAVE -to name them this way, but it makes it clear what functions are tests for other -developers. Test functions take no arguments and return nothing. All test -accounting is handled internally in Unity. - -Finally, at the bottom of your test file, you will write a `main()` function. -This function will call `UNITY_BEGIN()`, then `RUN_TEST` for each test, and -finally `UNITY_END()`.This is what will actually trigger each of those test -functions to run, so it is important that each function gets its own `RUN_TEST` -call. - -Remembering to add each test to the main function can get to be tedious. If you -enjoy using helper scripts in your build process, you might consider making use -of our handy generate_test_runner.rb script. This will create the main function -and all the calls for you, assuming that you have followed the suggested naming -conventions. In this case, there is no need for you to include the main function -in your test file at all. - -When you're done, your test file will look something like this: - -```C -#include "unity.h" -#include "file_to_test.h" - -void setUp(void) { - // set stuff up here -} - -void tearDown(void) { - // clean stuff up here -} - -void test_function_should_doBlahAndBlah(void) { - //test stuff -} - -void test_function_should_doAlsoDoBlah(void) { - //more test stuff -} - -int main(void) { - UNITY_BEGIN(); - RUN_TEST(test_function_should_doBlahAndBlah); - RUN_TEST(test_function_should_doAlsoDoBlah); - return UNITY_END(); -} -``` - -It's possible that you will require more customization than this, eventually. -For that sort of thing, you're going to want to look at the configuration guide. -This should be enough to get you going, though. - - -## How to Build and Run A Test File - -This is the single biggest challenge to picking up a new unit testing framework, -at least in a language like C or C++. These languages are REALLY good at getting -you "close to the metal" (why is the phrase metal? Wouldn't it be more accurate -to say "close to the silicon"?). While this feature is usually a good thing, it -can make testing more challenging. - -You have two really good options for toolchains. Depending on where you're -coming from, it might surprise you that neither of these options is running the -unit tests on your hardware. -There are many reasons for this, but here's a short version: -- On hardware, you have too many constraints (processing power, memory, etc), -- On hardware, you don't have complete control over all registers, -- On hardware, unit testing is more challenging, -- Unit testing isn't System testing. Keep them separate. - -Instead of running your tests on your actual hardware, most developers choose to -develop them as native applications (using gcc or MSVC for example) or as -applications running on a simulator. Either is a good option. Native apps have -the advantages of being faster and easier to set up. Simulator apps have the -advantage of working with the same compiler as your target application. The -options for configuring these are discussed in the configuration guide. - -To get either to work, you might need to make a few changes to the file -containing your register set (discussed later). - -In either case, a test is built by linking unity, the test file, and the C -file(s) being tested. These files create an executable which can be run as the -test set for that module. Then, this process is repeated for the next test file. -This flexibility of separating tests into individual executables allows us to -much more thoroughly unit test our system and it keeps all the test code out of -our final release! - - -*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/components/cjson/cJSON/tests/unity/docs/UnityHelperScriptsGuide.md b/components/cjson/cJSON/tests/unity/docs/UnityHelperScriptsGuide.md deleted file mode 100644 index 424299008..000000000 --- a/components/cjson/cJSON/tests/unity/docs/UnityHelperScriptsGuide.md +++ /dev/null @@ -1,254 +0,0 @@ -# Unity Helper Scripts - -## With a Little Help From Our Friends - -Sometimes what it takes to be a really efficient C programmer is a little non-C. -The Unity project includes a couple Ruby scripts for making your life just a tad -easier. They are completely optional. If you choose to use them, you'll need a -copy of Ruby, of course. Just install whatever the latest version is, and it is -likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/). - - -### `generate_test_runner.rb` - -Are you tired of creating your own `main` function in your test file? Do you -keep forgetting to add a `RUN_TEST` call when you add a new test case to your -suite? Do you want to use CMock or other fancy add-ons but don't want to figure -out how to create your own `RUN_TEST` macro? - -Well then we have the perfect script for you! - -The `generate_test_runner` script processes a given test file and automatically -creates a separate test runner file that includes ?main?to execute the test -cases within the scanned test file. All you do then is add the generated runner -to your list of files to be compiled and linked, and presto you're done! - -This script searches your test file for void function signatures having a -function name beginning with "test" or "spec". It treats each of these -functions as a test case and builds up a test suite of them. For example, the -following includes three test cases: - -```C -void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void) -{ - ASSERT_TRUE(1); -} -void test_FunctionName_should_WorkProperlyAndReturn8(void) { - ASSERT_EQUAL_INT(8, FunctionName()); -} -void spec_Function_should_DoWhatItIsSupposedToDo(void) { - ASSERT_NOT_NULL(Function(5)); -} -``` - -You can run this script a couple of ways. The first is from the command line: - -```Shell -ruby generate_test_runner.rb TestFile.c NameOfRunner.c -``` - -Alternatively, if you include only the test file parameter, the script will copy -the name of the test file and automatically append "_Runner" to the name of the -generated file. The example immediately below will create TestFile_Runner.c. - -```Shell -ruby generate_test_runner.rb TestFile.c -``` - -You can also add a [YAML](http://www.yaml.org/) file to configure extra options. -Conveniently, this YAML file is of the same format as that used by Unity and -CMock. So if you are using YAML files already, you can simply pass the very same -file into the generator script. - -```Shell -ruby generate_test_runner.rb TestFile.c my_config.yml -``` - -The contents of the YAML file `my_config.yml` could look something like the -example below. If you're wondering what some of these options do, you're going -to love the next section of this document. - -```YAML -:unity: - :includes: - - stdio.h - - microdefs.h - :cexception: 1 - :suit_setup: "blah = malloc(1024);" - :suite_teardown: "free(blah);" -``` - -If you would like to force your generated test runner to include one or more -header files, you can just include those at the command line too. Just make sure -these are _after_ the YAML file, if you are using one: - -```Shell -ruby generate_test_runner.rb TestFile.c my_config.yml extras.h -``` - -Another option, particularly if you are already using Ruby to orchestrate your -builds - or more likely the Ruby-based build tool Rake - is requiring this -script directly. Anything that you would have specified in a YAML file can be -passed to the script as part of a hash. Let's push the exact same requirement -set as we did above but this time through Ruby code directly: - -```Ruby -require "generate_test_runner.rb" -options = { - :includes => ["stdio.h", "microdefs.h"], - :cexception => 1, - :suite_setup => "blah = malloc(1024);", - :suite_teardown => "free(blah);" -} -UnityTestRunnerGenerator.new.run(testfile, runner_name, options) -``` - -If you have multiple files to generate in a build script (such as a Rakefile), -you might want to instantiate a generator object with your options and call it -to generate each runner thereafter. Like thus: - -```Ruby -gen = UnityTestRunnerGenerator.new(options) -test_files.each do |f| - gen.run(f, File.basename(f,'.c')+"Runner.c" -end -``` - -#### Options accepted by generate_test_runner.rb: - -The following options are available when executing `generate_test_runner`. You -may pass these as a Ruby hash directly or specify them in a YAML file, both of -which are described above. In the `examples` directory, Example 3's Rakefile -demonstrates using a Ruby hash. - - -##### `:includes` - -This option specifies an array of file names to be `#include`'d at the top of -your runner C file. You might use it to reference custom types or anything else -universally needed in your generated runners. - - -##### `:suite_setup` - -Define this option with C code to be executed _before any_ test cases are run. - -Alternatively, if your C compiler supports weak symbols, you can leave this -option unset and instead provide a `void suiteSetUp(void)` function in your test -suite. The linker will look for this symbol and fall back to a Unity-provided -stub if it is not found. - - -##### `:suite_teardown` - -Define this option with C code to be executed _after all_ test cases have -finished. An integer variable `num_failures` is available for diagnostics. -The code should end with a `return` statement; the value returned will become -the exit code of `main`. You can normally just return `num_failures`. - -Alternatively, if your C compiler supports weak symbols, you can leave this -option unset and instead provide a `int suiteTearDown(int num_failures)` -function in your test suite. The linker will look for this symbol and fall -back to a Unity-provided stub if it is not found. - - -##### `:enforce_strict_ordering` - -This option should be defined if you have the strict order feature enabled in -CMock (see CMock documentation). This generates extra variables required for -everything to run smoothly. If you provide the same YAML to the generator as -used in CMock's configuration, you've already configured the generator properly. - - -##### `:plugins` - -This option specifies an array of plugins to be used (of course, the array can -contain only a single plugin). This is your opportunity to enable support for -CException support, which will add a check for unhandled exceptions in each -test, reporting a failure if one is detected. To enable this feature using Ruby: - -```Ruby -:plugins => [ :cexception ] -``` - -Or as a yaml file: - -```YAML -:plugins: - -:cexception -``` - -If you are using CMock, it is very likely that you are already passing an array -of plugins to CMock. You can just use the same array here. This script will just -ignore the plugins that don't require additional support. - - -### `unity_test_summary.rb` - -A Unity test file contains one or more test case functions. Each test case can -pass, fail, or be ignored. Each test file is run individually producing results -for its collection of test cases. A given project will almost certainly be -composed of multiple test files. Therefore, the suite of tests is comprised of -one or more test cases spread across one or more test files. This script -aggregates individual test file results to generate a summary of all executed -test cases. The output includes how many tests were run, how many were ignored, -and how many failed. In addition, the output includes a listing of which -specific tests were ignored and failed. A good example of the breadth and -details of these results can be found in the `examples` directory. Intentionally -ignored and failing tests in this project generate corresponding entries in the -summary report. - -If you're interested in other (prettier?) output formats, check into the -Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and -CMock and supports xunit-style xml as well as other goodies. - -This script assumes the existence of files ending with the extensions -`.testpass` and `.testfail`.The contents of these files includes the test -results summary corresponding to each test file executed with the extension set -according to the presence or absence of failures for that test file. The script -searches a specified path for these files, opens each one it finds, parses the -results, and aggregates and prints a summary. Calling it from the command line -looks like this: - -```Shell -ruby unity_test_summary.rb build/test/ -``` - -You can optionally specify a root path as well. This is really helpful when you -are using relative paths in your tools' setup, but you want to pull the summary -into an IDE like Eclipse for clickable shortcuts. - -```Shell -ruby unity_test_summary.rb build/test/ ~/projects/myproject/ -``` - -Or, if you're more of a Windows sort of person: - -```Shell -ruby unity_test_summary.rb build\teat\ C:\projects\myproject\ -``` - -When configured correctly, you'll see a final summary, like so: - -```Shell --------------------------- -UNITY IGNORED TEST SUMMARY --------------------------- -blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE - -------------------------- -UNITY FAILED TEST SUMMARY -------------------------- -blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0 -meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke" - --------------------------- -OVERALL UNITY TEST SUMMARY --------------------------- -45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED -``` - -How convenient is that? - - -*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/components/cjson/cJSON/tests/unity/docs/license.txt b/components/cjson/cJSON/tests/unity/docs/license.txt deleted file mode 100644 index d66fba53e..000000000 --- a/components/cjson/cJSON/tests/unity/docs/license.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/makefile b/components/cjson/cJSON/tests/unity/examples/example_1/makefile deleted file mode 100644 index cca79b42a..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/makefile +++ /dev/null @@ -1,71 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -#We try to detect the OS we are running on, and adjust commands as needed -ifeq ($(OS),Windows_NT) - ifeq ($(shell uname -s),) # not in a bash-like shell - CLEANUP = del /F /Q - MKDIR = mkdir - else # in a bash-like shell, like msys - CLEANUP = rm -f - MKDIR = mkdir -p - endif - TARGET_EXTENSION=.exe -else - CLEANUP = rm -f - MKDIR = mkdir -p - TARGET_EXTENSION=.out -endif - -C_COMPILER=gcc -ifeq ($(shell uname -s), Darwin) -C_COMPILER=clang -endif - -UNITY_ROOT=../.. - -CFLAGS=-std=c89 -CFLAGS += -Wall -CFLAGS += -Wextra -CFLAGS += -Wpointer-arith -CFLAGS += -Wcast-align -CFLAGS += -Wwrite-strings -CFLAGS += -Wswitch-default -CFLAGS += -Wunreachable-code -CFLAGS += -Winit-self -CFLAGS += -Wmissing-field-initializers -CFLAGS += -Wno-unknown-pragmas -CFLAGS += -Wstrict-prototypes -CFLAGS += -Wundef -CFLAGS += -Wold-style-definition - -TARGET_BASE1=test1 -TARGET_BASE2=test2 -TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) -TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION) -SRC_FILES1=$(UNITY_ROOT)/src/unity.c src/ProductionCode.c test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c -SRC_FILES2=$(UNITY_ROOT)/src/unity.c src/ProductionCode2.c test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c -INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -SYMBOLS= - -all: clean default - -default: $(SRC_FILES1) $(SRC_FILES2) - $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) - $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2) - - ./$(TARGET1) - ./$(TARGET2) - -test/test_runners/TestProductionCode_Runner.c: test/TestProductionCode.c - ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c -test/test_runners/TestProductionCode2_Runner.c: test/TestProductionCode2.c - ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c - -clean: - $(CLEANUP) $(TARGET1) $(TARGET2) - -ci: CFLAGS += -Werror -ci: default diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/readme.txt b/components/cjson/cJSON/tests/unity/examples/example_1/readme.txt deleted file mode 100644 index dfed81502..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -Example 1 -========= - -Close to the simplest possible example of Unity, using only basic features. -Run make to build & run the example tests. \ No newline at end of file diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.c deleted file mode 100644 index d039c3e89..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.c +++ /dev/null @@ -1,24 +0,0 @@ - -#include "ProductionCode.h" - -int Counter = 0; -int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ - -/* This function is supposed to search through NumbersToFind and find a particular number. - * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since - * NumbersToFind is indexed from 1. Unfortunately it's broken - * (and should therefore be caught by our tests) */ -int FindFunction_WhichIsBroken(int NumberToFind) -{ - int i = 0; - while (i <= 8) /* Notice I should have been in braces */ - i++; - if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ - return i; - return 0; -} - -int FunctionWhichReturnsLocalVariable(void) -{ - return Counter; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.h b/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.h deleted file mode 100644 index 250ca0dc6..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode.h +++ /dev/null @@ -1,3 +0,0 @@ - -int FindFunction_WhichIsBroken(int NumberToFind); -int FunctionWhichReturnsLocalVariable(void); diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.c deleted file mode 100644 index 98ee7eebc..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.c +++ /dev/null @@ -1,11 +0,0 @@ - -#include "ProductionCode2.h" - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) -{ - (void)Poor; - (void)LittleFunction; - /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know. - * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */ - return (char*)0; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.h b/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.h deleted file mode 100644 index 34ae980d1..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/src/ProductionCode2.h +++ /dev/null @@ -1,2 +0,0 @@ - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode.c deleted file mode 100644 index 806088625..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode.c +++ /dev/null @@ -1,62 +0,0 @@ - -#include "ProductionCode.h" -#include "unity.h" - -/* sometimes you may want to get at local data in a module. - * for example: If you plan to pass by reference, this could be useful - * however, it should often be avoided */ -extern int Counter; - -void setUp(void) -{ - /* This is run before EACH TEST */ - Counter = 0x5a5a; -} - -void tearDown(void) -{ -} - -void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) -{ - /* All of these should pass */ - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); -} - -void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) -{ - /* You should see this line fail in your test summary */ - TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); - - /* Notice the rest of these didn't get a chance to run because the line above failed. - * Unit tests abort each test function on the first sign of trouble. - * Then NEXT test function runs as normal. */ - TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) -{ - /* This should be true because setUp set this up for us before this test */ - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); - - /* This should be true because we can still change our answer */ - Counter = 0x1234; - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) -{ - /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */ - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) -{ - /* Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell - * you what actually happened...which in this case was a failure to setup the initial condition. */ - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode2.c deleted file mode 100644 index 7d940c171..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/test/TestProductionCode2.c +++ /dev/null @@ -1,31 +0,0 @@ - -#include "ProductionCode2.h" -#include "unity.h" - -/* These should be ignored because they are commented out in various ways: -#include "whatever.h" -#include "somethingelse.h" -*/ - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_IgnoredTest(void) -{ - TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); -} - -void test_AnotherIgnoredTest(void) -{ - TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); -} - -void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) -{ - TEST_IGNORE(); /* Like This */ -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c b/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c deleted file mode 100644 index cf72c219d..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c +++ /dev/null @@ -1,53 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT()) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "ProductionCode2.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_IgnoredTest(void); -extern void test_AnotherIgnoredTest(void); -extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("test/TestProductionCode2.c"); - RUN_TEST(test_IgnoredTest, 18); - RUN_TEST(test_AnotherIgnoredTest, 23); - RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c b/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c deleted file mode 100644 index 3b49af748..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c +++ /dev/null @@ -1,57 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT()) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "ProductionCode.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void); -extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void); -extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void); -extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void); -extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("test/TestProductionCode.c"); - RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20); - RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30); - RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41); - RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51); - RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/makefile b/components/cjson/cJSON/tests/unity/examples/example_2/makefile deleted file mode 100644 index 99d8d9681..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/makefile +++ /dev/null @@ -1,70 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -#We try to detect the OS we are running on, and adjust commands as needed -ifeq ($(OS),Windows_NT) - ifeq ($(shell uname -s),) # not in a bash-like shell - CLEANUP = del /F /Q - MKDIR = mkdir - else # in a bash-like shell, like msys - CLEANUP = rm -f - MKDIR = mkdir -p - endif - TARGET_EXTENSION=.exe -else - CLEANUP = rm -f - MKDIR = mkdir -p - TARGET_EXTENSION=.out -endif - -C_COMPILER=gcc -ifeq ($(shell uname -s), Darwin) -C_COMPILER=clang -endif - -UNITY_ROOT=../.. - -CFLAGS=-std=c99 -CFLAGS += -Wall -CFLAGS += -Wextra -CFLAGS += -Wpointer-arith -CFLAGS += -Wcast-align -CFLAGS += -Wwrite-strings -CFLAGS += -Wswitch-default -CFLAGS += -Wunreachable-code -CFLAGS += -Winit-self -CFLAGS += -Wmissing-field-initializers -CFLAGS += -Wno-unknown-pragmas -CFLAGS += -Wstrict-prototypes -CFLAGS += -Wundef -CFLAGS += -Wold-style-definition - -TARGET_BASE1=all_tests -TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) -SRC_FILES1=\ - $(UNITY_ROOT)/src/unity.c \ - $(UNITY_ROOT)/extras/fixture/src/unity_fixture.c \ - src/ProductionCode.c \ - src/ProductionCode2.c \ - test/TestProductionCode.c \ - test/TestProductionCode2.c \ - test/test_runners/TestProductionCode_Runner.c \ - test/test_runners/TestProductionCode2_Runner.c \ - test/test_runners/all_tests.c -INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -I$(UNITY_ROOT)/extras/fixture/src -SYMBOLS= - -all: clean default - -default: - $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) - - ./$(TARGET1) -v - -clean: - $(CLEANUP) $(TARGET1) - -ci: CFLAGS += -Werror -ci: default diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/readme.txt b/components/cjson/cJSON/tests/unity/examples/example_2/readme.txt deleted file mode 100644 index f0fce657c..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -Example 2 -========= - -Same as the first example, but now using Unity's test fixture to group tests -together. Using the test fixture also makes writing test runners much easier. \ No newline at end of file diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.c deleted file mode 100644 index 500b44b52..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.c +++ /dev/null @@ -1,24 +0,0 @@ - -#include "ProductionCode.h" - -int Counter = 0; -int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. - -// This function is supposed to search through NumbersToFind and find a particular number. -// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since -// NumbersToFind is indexed from 1. Unfortunately it's broken -// (and should therefore be caught by our tests) -int FindFunction_WhichIsBroken(int NumberToFind) -{ - int i = 0; - while (i <= 8) //Notice I should have been in braces - i++; - if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! - return i; - return 0; -} - -int FunctionWhichReturnsLocalVariable(void) -{ - return Counter; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.h b/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.h deleted file mode 100644 index 250ca0dc6..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode.h +++ /dev/null @@ -1,3 +0,0 @@ - -int FindFunction_WhichIsBroken(int NumberToFind); -int FunctionWhichReturnsLocalVariable(void); diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.c deleted file mode 100644 index 77c969f17..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.c +++ /dev/null @@ -1,11 +0,0 @@ - -#include "ProductionCode2.h" - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) -{ - (void)Poor; - (void)LittleFunction; - //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. - // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget - return (char*)0; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.h b/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.h deleted file mode 100644 index 34ae980d1..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/src/ProductionCode2.h +++ /dev/null @@ -1,2 +0,0 @@ - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode.c deleted file mode 100644 index ff318abbb..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "ProductionCode.h" -#include "unity.h" -#include "unity_fixture.h" - -TEST_GROUP(ProductionCode); - -//sometimes you may want to get at local data in a module. -//for example: If you plan to pass by reference, this could be useful -//however, it should often be avoided -extern int Counter; - -TEST_SETUP(ProductionCode) -{ - //This is run before EACH TEST - Counter = 0x5a5a; -} - -TEST_TEAR_DOWN(ProductionCode) -{ -} - -TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode) -{ - //All of these should pass - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); -} - -TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken) -{ - // You should see this line fail in your test summary - TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); - - // Notice the rest of these didn't get a chance to run because the line above failed. - // Unit tests abort each test function on the first sign of trouble. - // Then NEXT test function runs as normal. - TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); -} - -TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue) -{ - //This should be true because setUp set this up for us before this test - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); - - //This should be true because we can still change our answer - Counter = 0x1234; - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} - -TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain) -{ - //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); -} - -TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed) -{ - //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell - // you what actually happened...which in this case was a failure to setup the initial condition. - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode2.c deleted file mode 100644 index d9f4efe31..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/test/TestProductionCode2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "ProductionCode2.h" -#include "unity.h" -#include "unity_fixture.h" - -TEST_GROUP(ProductionCode2); - -/* These should be ignored because they are commented out in various ways: -#include "whatever.h" -*/ -//#include "somethingelse.h" - -TEST_SETUP(ProductionCode2) -{ -} - -TEST_TEAR_DOWN(ProductionCode2) -{ -} - -TEST(ProductionCode2, IgnoredTest) -{ - TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); -} - -TEST(ProductionCode2, AnotherIgnoredTest) -{ - TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); -} - -TEST(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented) -{ - TEST_IGNORE(); //Like This -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c b/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c deleted file mode 100644 index 6fcc3b120..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "unity.h" -#include "unity_fixture.h" - -TEST_GROUP_RUNNER(ProductionCode2) -{ - RUN_TEST_CASE(ProductionCode2, IgnoredTest); - RUN_TEST_CASE(ProductionCode2, AnotherIgnoredTest); - RUN_TEST_CASE(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented); -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c b/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c deleted file mode 100644 index 41a416a6e..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "unity.h" -#include "unity_fixture.h" - -TEST_GROUP_RUNNER(ProductionCode) -{ - RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode); - RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken); - RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue); - RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain); - RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed); -} \ No newline at end of file diff --git a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/all_tests.c b/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/all_tests.c deleted file mode 100644 index e706ece7d..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_2/test/test_runners/all_tests.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "unity_fixture.h" - -static void RunAllTests(void) -{ - RUN_TEST_GROUP(ProductionCode); - RUN_TEST_GROUP(ProductionCode2); -} - -int main(int argc, const char * argv[]) -{ - return UnityMain(argc, argv, RunAllTests); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.c b/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.c deleted file mode 100644 index 9cf42c678..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "unity.h" -#include "UnityHelper.h" -#include -#include - -void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line) -{ - UNITY_TEST_ASSERT_EQUAL_INT(expected.x, actual.x, line, "Example Struct Failed For Field x"); - UNITY_TEST_ASSERT_EQUAL_INT(expected.y, actual.y, line, "Example Struct Failed For Field y"); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.h b/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.h deleted file mode 100644 index 151611158..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/helper/UnityHelper.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _TESTHELPER_H -#define _TESTHELPER_H - -#include "Types.h" - -void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line); - -#define UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, line, message) AssertEqualExampleStruct(expected, actual, line); - -#define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, __LINE__, NULL); - -#endif // _TESTHELPER_H diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/rakefile.rb b/components/cjson/cJSON/tests/unity/examples/example_3/rakefile.rb deleted file mode 100644 index bf9f42be1..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/rakefile.rb +++ /dev/null @@ -1,43 +0,0 @@ -HERE = File.expand_path(File.dirname(__FILE__)) + '/' -UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..' - -require 'rake' -require 'rake/clean' -require HERE + 'rakefile_helper' - -TEMP_DIRS = [ - File.join(HERE, 'build') -].freeze - -TEMP_DIRS.each do |dir| - directory(dir) - CLOBBER.include(dir) -end - -task prepare_for_tests: TEMP_DIRS - -include RakefileHelpers - -# Load default configuration, for now -DEFAULT_CONFIG_FILE = 'target_gcc_32.yml'.freeze -configure_toolchain(DEFAULT_CONFIG_FILE) - -task unit: [:prepare_for_tests] do - run_tests unit_test_files -end - -desc 'Generate test summary' -task :summary do - report_summary -end - -desc 'Build and test Unity' -task all: %i(clean unit summary) -task default: %i(clobber all) -task ci: [:default] -task cruise: [:default] - -desc 'Load configuration' -task :config, :config_file do |_t, args| - configure_toolchain(args[:config_file]) -end diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/rakefile_helper.rb b/components/cjson/cJSON/tests/unity/examples/example_3/rakefile_helper.rb deleted file mode 100644 index a186cf0ff..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/rakefile_helper.rb +++ /dev/null @@ -1,249 +0,0 @@ -require 'yaml' -require 'fileutils' -require UNITY_ROOT + '/auto/unity_test_summary' -require UNITY_ROOT + '/auto/generate_test_runner' -require UNITY_ROOT + '/auto/colour_reporter' - -module RakefileHelpers - C_EXTENSION = '.c'.freeze - - def load_configuration(config_file) - $cfg_file = config_file - $cfg = YAML.load(File.read($cfg_file)) - end - - def configure_clean - CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? - end - - def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) - config_file += '.yml' unless config_file =~ /\.yml$/ - load_configuration(config_file) - configure_clean - end - - def unit_test_files - path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION - path.tr!('\\', '/') - FileList.new(path) - end - - def local_include_dirs - include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if { |dir| dir.is_a?(Array) } - include_dirs - end - - def extract_headers(filename) - includes = [] - lines = File.readlines(filename) - lines.each do |line| - m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) - includes << m[1] unless m.nil? - end - includes - end - - def find_source_file(header, paths) - paths.each do |dir| - src_file = dir + header.ext(C_EXTENSION) - return src_file if File.exist?(src_file) - end - nil - end - - def tackit(strings) - result = if strings.is_a?(Array) - "\"#{strings.join}\"" - else - strings - end - result - end - - def squash(prefix, items) - result = '' - items.each { |item| result += " #{prefix}#{tackit(item)}" } - result - end - - def build_compiler_fields - command = tackit($cfg['compiler']['path']) - defines = if $cfg['compiler']['defines']['items'].nil? - '' - else - squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items']) - end - options = squash('', $cfg['compiler']['options']) - includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) - includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { command: command, defines: defines, options: options, includes: includes } - end - - def compile(file, _defines = []) - compiler = build_compiler_fields - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \ - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" - obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" - execute(cmd_str + obj_file) - obj_file - end - - def build_linker_fields - command = tackit($cfg['linker']['path']) - options = if $cfg['linker']['options'].nil? - '' - else - squash('', $cfg['linker']['options']) - end - includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? - '' - else - squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) - end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { command: command, options: options, includes: includes } - end - - def link_it(exe_name, obj_list) - linker = build_linker_fields - cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + - (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] - execute(cmd_str) - end - - def build_simulator_fields - return nil if $cfg['simulator'].nil? - command = if $cfg['simulator']['path'].nil? - '' - else - (tackit($cfg['simulator']['path']) + ' ') - end - pre_support = if $cfg['simulator']['pre_support'].nil? - '' - else - squash('', $cfg['simulator']['pre_support']) - end - post_support = if $cfg['simulator']['post_support'].nil? - '' - else - squash('', $cfg['simulator']['post_support']) - end - - { command: command, pre_support: pre_support, post_support: post_support } - end - - def execute(command_string, verbose = true, raise_on_fail = true) - report command_string - output = `#{command_string}`.chomp - report(output) if verbose && !output.nil? && !output.empty? - if !$?.exitstatus.zero? && raise_on_fail - raise "Command failed. (Returned #{$?.exitstatus})" - end - output - end - - def report_summary - summary = UnityTestSummary.new - summary.root = HERE - results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.tr!('\\', '/') - results = Dir[results_glob] - summary.targets = results - summary.run - fail_out 'FAIL: There were failures' if summary.failures > 0 - end - - def run_tests(test_files) - report 'Running system tests...' - - # Tack on TEST define for compiling unit tests - load_configuration($cfg_file) - test_defines = ['TEST'] - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? - $cfg['compiler']['defines']['items'] << 'TEST' - - include_dirs = local_include_dirs - - # Build and execute each unit test - test_files.each do |test| - obj_list = [] - - # Detect dependencies and build required required modules - extract_headers(test).each do |header| - # Compile corresponding source file if it exists - src_file = find_source_file(header, include_dirs) - obj_list << compile(src_file, test_defines) unless src_file.nil? - end - - # Build the test runner (generate if configured to do so) - test_base = File.basename(test, C_EXTENSION) - runner_name = test_base + '_Runner.c' - if $cfg['compiler']['runner_path'].nil? - runner_path = $cfg['compiler']['build_path'] + runner_name - test_gen = UnityTestRunnerGenerator.new($cfg_file) - test_gen.run(test, runner_path) - else - runner_path = $cfg['compiler']['runner_path'] + runner_name - end - - obj_list << compile(runner_path, test_defines) - - # Build the test module - obj_list << compile(test, test_defines) - - # Link the test executable - link_it(test_base, obj_list) - - # Execute unit test and generate results file - simulator = build_simulator_fields - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] - cmd_str = if simulator.nil? - executable - else - "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end - output = execute(cmd_str, true, false) - test_results = $cfg['compiler']['build_path'] + test_base - test_results += if output.match(/OK$/m).nil? - '.testfail' - else - '.testpass' - end - File.open(test_results, 'w') { |f| f.print output } - end - end - - def build_application(main) - report 'Building application...' - - obj_list = [] - load_configuration($cfg_file) - main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION - - # Detect dependencies and build required required modules - include_dirs = get_local_include_dirs - extract_headers(main_path).each do |header| - src_file = find_source_file(header, include_dirs) - obj_list << compile(src_file) unless src_file.nil? - end - - # Build the main source file - main_base = File.basename(main_path, C_EXTENSION) - obj_list << compile(main_path) - - # Create the executable - link_it(main_base, obj_list) - end - - def fail_out(msg) - puts msg - puts 'Not returning exit code so continuous integration can pass' - # exit(-1) # Only removed to pass example_3, which has failing tests on purpose. - # Still fail if the build fails for any other reason. - end -end diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/readme.txt b/components/cjson/cJSON/tests/unity/examples/example_3/readme.txt deleted file mode 100644 index 7371fea05..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -Example 3 -========= - -This example project gives an example of some passing, ignored, and failing tests. -It's simple and meant for you to look over and get an idea for what all of this stuff does. - -You can build and test using rake. The rake version will let you test with gcc or a couple -versions of IAR. You can tweak the yaml files to get those versions running. - -Ruby is required if you're using the rake version (obviously). This version shows off most of -Unity's advanced features (automatically creating test runners, fancy summaries, etc.) -Without ruby, you have to maintain your own test runners. Do that for a while and you'll learn -why you really want to start using the Ruby tools. diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.c deleted file mode 100644 index 500b44b52..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.c +++ /dev/null @@ -1,24 +0,0 @@ - -#include "ProductionCode.h" - -int Counter = 0; -int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. - -// This function is supposed to search through NumbersToFind and find a particular number. -// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since -// NumbersToFind is indexed from 1. Unfortunately it's broken -// (and should therefore be caught by our tests) -int FindFunction_WhichIsBroken(int NumberToFind) -{ - int i = 0; - while (i <= 8) //Notice I should have been in braces - i++; - if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! - return i; - return 0; -} - -int FunctionWhichReturnsLocalVariable(void) -{ - return Counter; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.h b/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.h deleted file mode 100644 index 250ca0dc6..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode.h +++ /dev/null @@ -1,3 +0,0 @@ - -int FindFunction_WhichIsBroken(int NumberToFind); -int FunctionWhichReturnsLocalVariable(void); diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.c deleted file mode 100644 index 77c969f17..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.c +++ /dev/null @@ -1,11 +0,0 @@ - -#include "ProductionCode2.h" - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) -{ - (void)Poor; - (void)LittleFunction; - //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. - // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget - return (char*)0; -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.h b/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.h deleted file mode 100644 index 34ae980d1..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/src/ProductionCode2.h +++ /dev/null @@ -1,2 +0,0 @@ - -char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/target_gcc_32.yml b/components/cjson/cJSON/tests/unity/examples/example_3/target_gcc_32.yml deleted file mode 100644 index f155508c6..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/target_gcc_32.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Copied from ~Unity/targets/gcc_32.yml -unity_root: &unity_root '../..' -compiler: - path: gcc - source_path: 'src/' - unit_tests_path: &unit_tests_path 'test/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m32' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - items: - - 'src/' - - '../../src/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m32' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode.c b/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode.c deleted file mode 100644 index 28a55812c..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode.c +++ /dev/null @@ -1,62 +0,0 @@ - -#include "ProductionCode.h" -#include "unity.h" - -//sometimes you may want to get at local data in a module. -//for example: If you plan to pass by reference, this could be useful -//however, it should often be avoided -extern int Counter; - -void setUp(void) -{ - //This is run before EACH TEST - Counter = 0x5a5a; -} - -void tearDown(void) -{ -} - -void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) -{ - //All of these should pass - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); - TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); -} - -void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) -{ - // You should see this line fail in your test summary - TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); - - // Notice the rest of these didn't get a chance to run because the line above failed. - // Unit tests abort each test function on the first sign of trouble. - // Then NEXT test function runs as normal. - TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) -{ - //This should be true because setUp set this up for us before this test - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); - - //This should be true because we can still change our answer - Counter = 0x1234; - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) -{ - //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) - TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); -} - -void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) -{ - //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell - // you what actually happened...which in this case was a failure to setup the initial condition. - TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); -} diff --git a/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode2.c b/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode2.c deleted file mode 100644 index e2119cc38..000000000 --- a/components/cjson/cJSON/tests/unity/examples/example_3/test/TestProductionCode2.c +++ /dev/null @@ -1,31 +0,0 @@ - -#include "ProductionCode2.h" -#include "unity.h" - -/* These should be ignored because they are commented out in various ways: -#include "whatever.h" -*/ -//#include "somethingelse.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -void test_IgnoredTest(void) -{ - TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); -} - -void test_AnotherIgnoredTest(void) -{ - TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); -} - -void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) -{ - TEST_IGNORE(); //Like This -} diff --git a/components/cjson/cJSON/tests/unity/examples/unity_config.h b/components/cjson/cJSON/tests/unity/examples/unity_config.h deleted file mode 100644 index a2f161a7a..000000000 --- a/components/cjson/cJSON/tests/unity/examples/unity_config.h +++ /dev/null @@ -1,239 +0,0 @@ -/* Unity Configuration - * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529 - * Update: December 29th, 2016 - * See Also: Unity/docs/UnityConfigurationGuide.pdf - * - * Unity is designed to run on almost anything that is targeted by a C compiler. - * It would be awesome if this could be done with zero configuration. While - * there are some targets that come close to this dream, it is sadly not - * universal. It is likely that you are going to need at least a couple of the - * configuration options described in this document. - * - * All of Unity's configuration options are `#defines`. Most of these are simple - * definitions. A couple are macros with arguments. They live inside the - * unity_internals.h header file. We don't necessarily recommend opening that - * file unless you really need to. That file is proof that a cross-platform - * library is challenging to build. From a more positive perspective, it is also - * proof that a great deal of complexity can be centralized primarily to one - * place in order to provide a more consistent and simple experience elsewhere. - * - * Using These Options - * It doesn't matter if you're using a target-specific compiler and a simulator - * or a native compiler. In either case, you've got a couple choices for - * configuring these options: - * - * 1. Because these options are specified via C defines, you can pass most of - * these options to your compiler through command line compiler flags. Even - * if you're using an embedded target that forces you to use their - * overbearing IDE for all configuration, there will be a place somewhere in - * your project to configure defines for your compiler. - * 2. You can create a custom `unity_config.h` configuration file (present in - * your toolchain's search paths). In this file, you will list definitions - * and macros specific to your target. All you must do is define - * `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any - * further definitions it may need. - */ - -#ifndef UNITY_CONFIG_H -#define UNITY_CONFIG_H - -/* ************************* AUTOMATIC INTEGER TYPES *************************** - * C's concept of an integer varies from target to target. The C Standard has - * rules about the `int` matching the register size of the target - * microprocessor. It has rules about the `int` and how its size relates to - * other integer types. An `int` on one target might be 16 bits while on another - * target it might be 64. There are more specific types in compilers compliant - * with C99 or later, but that's certainly not every compiler you are likely to - * encounter. Therefore, Unity has a number of features for helping to adjust - * itself to match your required integer sizes. It starts off by trying to do it - * automatically. - **************************************************************************** */ - -/* The first attempt to guess your types is to check `limits.h`. Some compilers - * that don't support `stdint.h` could include `limits.h`. If you don't - * want Unity to check this file, define this to make it skip the inclusion. - * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89. - */ -/* #define UNITY_EXCLUDE_LIMITS_H */ - -/* The second thing that Unity does to guess your types is check `stdint.h`. - * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to - * learn about your system. It's possible you don't want it to do this or it's - * possible that your system doesn't support `stdint.h`. If that's the case, - * you're going to want to define this. That way, Unity will know to skip the - * inclusion of this file and you won't be left with a compiler error. - */ -/* #define UNITY_EXCLUDE_STDINT_H */ - -/* ********************** MANUAL INTEGER TYPE DEFINITION *********************** - * If you've disabled all of the automatic options above, you're going to have - * to do the configuration yourself. There are just a handful of defines that - * you are going to specify if you don't like the defaults. - **************************************************************************** */ - - /* Define this to be the number of bits an `int` takes up on your system. The - * default, if not auto-detected, is 32 bits. - * - * Example: - */ -/* #define UNITY_INT_WIDTH 16 */ - -/* Define this to be the number of bits a `long` takes up on your system. The - * default, if not autodetected, is 32 bits. This is used to figure out what - * kind of 64-bit support your system can handle. Does it need to specify a - * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option - * is going to be ignored. - * - * Example: - */ -/* #define UNITY_LONG_WIDTH 16 */ - -/* Define this to be the number of bits a pointer takes up on your system. The - * default, if not autodetected, is 32-bits. If you're getting ugly compiler - * warnings about casting from pointers, this is the one to look at. - * - * Example: - */ -/* #define UNITY_POINTER_WIDTH 64 */ - -/* Unity will automatically include 64-bit support if it auto-detects it, or if - * your `int`, `long`, or pointer widths are greater than 32-bits. Define this - * to enable 64-bit support if none of the other options already did it for you. - * There can be a significant size and speed impact to enabling 64-bit support - * on small targets, so don't define it if you don't need it. - */ -/* #define UNITY_INCLUDE_64 */ - - -/* *************************** FLOATING POINT TYPES **************************** - * In the embedded world, it's not uncommon for targets to have no support for - * floating point operations at all or to have support that is limited to only - * single precision. We are able to guess integer sizes on the fly because - * integers are always available in at least one size. Floating point, on the - * other hand, is sometimes not available at all. Trying to include `float.h` on - * these platforms would result in an error. This leaves manual configuration as - * the only option. - **************************************************************************** */ - - /* By default, Unity guesses that you will want single precision floating point - * support, but not double precision. It's easy to change either of these using - * the include and exclude options here. You may include neither, just float, - * or both, as suits your needs. - */ -/* #define UNITY_EXCLUDE_FLOAT */ -#define UNITY_INCLUDE_DOUBLE -/* #define UNITY_EXCLUDE_DOUBLE */ - -/* For features that are enabled, the following floating point options also - * become available. - */ - -/* Unity aims for as small of a footprint as possible and avoids most standard - * library calls (some embedded platforms don't have a standard library!). - * Because of this, its routines for printing integer values are minimalist and - * hand-coded. To keep Unity universal, though, we eventually chose to develop - * our own floating point print routines. Still, the display of floating point - * values during a failure are optional. By default, Unity will print the - * actual results of floating point assertion failures. So a failed assertion - * will produce a message like "Expected 4.0 Was 4.25". If you would like less - * verbose failure messages for floating point assertions, use this option to - * give a failure message `"Values Not Within Delta"` and trim the binary size. - */ -/* #define UNITY_EXCLUDE_FLOAT_PRINT */ - -/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C - * floats. If your compiler supports a specialty floating point type, you can - * always override this behavior by using this definition. - * - * Example: - */ -/* #define UNITY_FLOAT_TYPE float16_t */ - -/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard - * C doubles. If you would like to change this, you can specify something else - * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long - * double` could enable gargantuan floating point types on your 64-bit processor - * instead of the standard `double`. - * - * Example: - */ -/* #define UNITY_DOUBLE_TYPE long double */ - -/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as - * documented in the Unity Assertion Guide, you will learn that they are not - * really asserting that two values are equal but rather that two values are - * "close enough" to equal. "Close enough" is controlled by these precision - * configuration options. If you are working with 32-bit floats and/or 64-bit - * doubles (the normal on most processors), you should have no need to change - * these options. They are both set to give you approximately 1 significant bit - * in either direction. The float precision is 0.00001 while the double is - * 10^-12. For further details on how this works, see the appendix of the Unity - * Assertion Guide. - * - * Example: - */ -/* #define UNITY_FLOAT_PRECISION 0.001f */ -/* #define UNITY_DOUBLE_PRECISION 0.001f */ - - -/* *************************** TOOLSET CUSTOMIZATION *************************** - * In addition to the options listed above, there are a number of other options - * which will come in handy to customize Unity's behavior for your specific - * toolchain. It is possible that you may not need to touch any of these but - * certain platforms, particularly those running in simulators, may need to jump - * through extra hoops to operate properly. These macros will help in those - * situations. - **************************************************************************** */ - -/* By default, Unity prints its results to `stdout` as it runs. This works - * perfectly fine in most situations where you are using a native compiler for - * testing. It works on some simulators as well so long as they have `stdout` - * routed back to the command line. There are times, however, where the - * simulator will lack support for dumping results or you will want to route - * results elsewhere for other reasons. In these cases, you should define the - * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time - * (as an `int`, since this is the parameter type of the standard C `putchar` - * function most commonly used). You may replace this with whatever function - * call you like. - * - * Example: - * Say you are forced to run your test suite on an embedded processor with no - * `stdout` option. You decide to route your test result output to a custom - * serial `RS232_putc()` function you wrote like thus: - */ -/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */ -/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */ -/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */ -/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */ -/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */ -/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */ - -/* For some targets, Unity can make the otherwise required `setUp()` and - * `tearDown()` functions optional. This is a nice convenience for test writers - * since `setUp` and `tearDown` don't often actually _do_ anything. If you're - * using gcc or clang, this option is automatically defined for you. Other - * compilers can also support this behavior, if they support a C feature called - * weak functions. A weak function is a function that is compiled into your - * executable _unless_ a non-weak version of the same function is defined - * elsewhere. If a non-weak version is found, the weak version is ignored as if - * it never existed. If your compiler supports this feature, you can let Unity - * know by defining `UNITY_SUPPORT_WEAK` as the function attributes that would - * need to be applied to identify a function as weak. If your compiler lacks - * support for weak functions, you will always need to define `setUp` and - * `tearDown` functions (though they can be and often will be just empty). The - * most common options for this feature are: - */ -/* #define UNITY_SUPPORT_WEAK weak */ -/* #define UNITY_SUPPORT_WEAK __attribute__((weak)) */ -/* #define UNITY_NO_WEAK */ - -/* Some compilers require a custom attribute to be assigned to pointers, like - * `near` or `far`. In these cases, you can give Unity a safe default for these - * by defining this option with the attribute you would like. - * - * Example: - */ -/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */ -/* #define UNITY_PTR_ATTRIBUTE near */ - -#endif /* UNITY_CONFIG_H */ diff --git a/components/cjson/cJSON/tests/unity/extras/eclipse/error_parsers.txt b/components/cjson/cJSON/tests/unity/extras/eclipse/error_parsers.txt deleted file mode 100644 index 94e34ff38..000000000 --- a/components/cjson/cJSON/tests/unity/extras/eclipse/error_parsers.txt +++ /dev/null @@ -1,26 +0,0 @@ -Eclipse error parsers -===================== - -These are a godsend for extracting & quickly navigating to -warnings & error messages from console output. Unforunately -I don't know how to write an Eclipse plugin so you'll have -to add them manually. - -To add a console parser to Eclipse, go to Window --> Preferences ---> C/C++ --> Build --> Settings. Click on the 'Error Parsers' -tab and then click the 'Add...' button. See the table below for -the parser fields to add. - -Eclipse will only parse the console output during a build, so -running your unit tests must be part of your build process. -Either add this to your make/rakefile, or add it as a post- -build step in your Eclipse project settings. - - -Unity unit test error parsers ------------------------------ -Severity Pattern File Line Description -------------------------------------------------------------------------------- -Error (\.+)(.*?):(\d+):(.*?):FAIL: (.*) $2 $3 $5 -Warning (\.+)(.*?):(\d+):(.*?):IGNORE: (.*) $2 $3 $5 -Warning (\.+)(.*?):(\d+):(.*?):IGNORE\s*$ $2 $3 Ignored test diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/rakefile.rb b/components/cjson/cJSON/tests/unity/extras/fixture/rakefile.rb deleted file mode 100644 index 7603e5745..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/rakefile.rb +++ /dev/null @@ -1,48 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -HERE = File.expand_path(File.dirname(__FILE__)) + '/' - -require 'rake' -require 'rake/clean' -require 'rake/testtask' -require HERE + 'rakefile_helper' - -TEMP_DIRS = [ - File.join(HERE, 'build') -].freeze - -TEMP_DIRS.each do |dir| - directory(dir) - CLOBBER.include(dir) -end - -task prepare_for_tests: TEMP_DIRS - -include RakefileHelpers - -# Load default configuration, for now -DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'.freeze -configure_toolchain(DEFAULT_CONFIG_FILE) - -task unit: [:prepare_for_tests] do - run_tests -end - -desc 'Build and test Unity Framework' -task all: %i(clean unit) -task default: %i(clobber all) -task ci: %i(no_color default) -task cruise: %i(no_color default) - -desc 'Load configuration' -task :config, :config_file do |_t, args| - configure_toolchain(args[:config_file]) -end - -task :no_color do - $colour_output = false -end diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/rakefile_helper.rb b/components/cjson/cJSON/tests/unity/extras/fixture/rakefile_helper.rb deleted file mode 100644 index c45b2393d..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/rakefile_helper.rb +++ /dev/null @@ -1,178 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -require 'yaml' -require 'fileutils' -require HERE + '../../auto/unity_test_summary' -require HERE + '../../auto/generate_test_runner' -require HERE + '../../auto/colour_reporter' - -module RakefileHelpers - C_EXTENSION = '.c'.freeze - - def load_configuration(config_file) - return if $configured - - $cfg_file = HERE + "../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/ - $cfg = YAML.load(File.read($cfg_file)) - $colour_output = false unless $cfg['colour'] - $configured = true if config_file != DEFAULT_CONFIG_FILE - end - - def configure_clean - CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? - end - - def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) - config_file += '.yml' unless config_file =~ /\.yml$/ - config_file = config_file unless config_file =~ /[\\|\/]/ - load_configuration(config_file) - configure_clean - end - - def tackit(strings) - result = if strings.is_a?(Array) - "\"#{strings.join}\"" - else - strings - end - result - end - - def squash(prefix, items) - result = '' - items.each { |item| result += " #{prefix}#{tackit(item)}" } - result - end - - def build_compiler_fields - command = tackit($cfg['compiler']['path']) - defines = if $cfg['compiler']['defines']['items'].nil? - '' - else - squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)']) - end - options = squash('', $cfg['compiler']['options']) - includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) - includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { command: command, defines: defines, options: options, includes: includes } - end - - def compile(file, _defines = []) - compiler = build_compiler_fields - unity_include = $cfg['compiler']['includes']['prefix'] + '../../src' - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " \ - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" \ - "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" - - execute(cmd_str) - end - - def build_linker_fields - command = tackit($cfg['linker']['path']) - options = if $cfg['linker']['options'].nil? - '' - else - squash('', $cfg['linker']['options']) - end - includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? - '' - else - squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) - end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { command: command, options: options, includes: includes } - end - - def link_it(exe_name, obj_list) - linker = build_linker_fields - cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + - (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] - execute(cmd_str) - end - - def build_simulator_fields - return nil if $cfg['simulator'].nil? - command = if $cfg['simulator']['path'].nil? - '' - else - (tackit($cfg['simulator']['path']) + ' ') - end - pre_support = if $cfg['simulator']['pre_support'].nil? - '' - else - squash('', $cfg['simulator']['pre_support']) - end - post_support = if $cfg['simulator']['post_support'].nil? - '' - else - squash('', $cfg['simulator']['post_support']) - end - { command: command, pre_support: pre_support, post_support: post_support } - end - - def execute(command_string, verbose = true) - report command_string - output = `#{command_string}`.chomp - report(output) if verbose && !output.nil? && !output.empty? - raise "Command failed. (Returned #{$?.exitstatus})" if $?.exitstatus != 0 - output - end - - def report_summary - summary = UnityTestSummary.new - summary.root = HERE - results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.tr!('\\', '/') - results = Dir[results_glob] - summary.targets = results - summary.run - end - - def run_tests - report 'Running Unity system tests...' - - # Tack on TEST define for compiling unit tests - load_configuration($cfg_file) - test_defines = ['TEST'] - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? - - # Get a list of all source files needed - src_files = Dir[HERE + 'src/*.c'] - src_files += Dir[HERE + 'test/*.c'] - src_files += Dir[HERE + 'test/main/*.c'] - src_files << '../../src/unity.c' - - # Build object files - src_files.each { |f| compile(f, test_defines) } - obj_list = src_files.map { |f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) } - - # Link the test executable - test_base = 'framework_test' - link_it(test_base, obj_list) - - # Execute unit test and generate results file - simulator = build_simulator_fields - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] - cmd_str = if simulator.nil? - executable + ' -v -r' - else - "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end - output = execute(cmd_str) - test_results = $cfg['compiler']['build_path'] + test_base - test_results += if output.match(/OK$/m).nil? - '.testfail' - else - '.testpass' - end - File.open(test_results, 'w') { |f| f.print output } - end -end diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/readme.txt b/components/cjson/cJSON/tests/unity/extras/fixture/readme.txt deleted file mode 100644 index 6b9a78c17..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/readme.txt +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2010 James Grenning and Contributed to Unity Project - -Unity Project - A Test Framework for C -Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -[Released under MIT License. Please refer to license.txt for details] - -This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h, -you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of -test groups and gives finer control of your tests over the command line. \ No newline at end of file diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.c b/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.c deleted file mode 100644 index 3872bd8ff..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.c +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#include "unity_fixture.h" -#include "unity_internals.h" -#include - -struct UNITY_FIXTURE_T UnityFixture; - -/* If you decide to use the function pointer approach. - * Build with -D UNITY_OUTPUT_CHAR=outputChar and include - * int (*outputChar)(int) = putchar; */ - -#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) -void setUp(void) { /*does nothing*/ } -void tearDown(void) { /*does nothing*/ } -#endif - -static void announceTestRun(unsigned int runNumber) -{ - UnityPrint("Unity test run "); - UnityPrintNumberUnsigned(runNumber+1); - UnityPrint(" of "); - UnityPrintNumberUnsigned(UnityFixture.RepeatCount); - UNITY_PRINT_EOL(); -} - -int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)) -{ - int result = UnityGetCommandLineOptions(argc, argv); - unsigned int r; - if (result != 0) - return result; - - for (r = 0; r < UnityFixture.RepeatCount; r++) - { - UnityBegin(argv[0]); - announceTestRun(r); - runAllTests(); - if (!UnityFixture.Verbose) UNITY_PRINT_EOL(); - UnityEnd(); - } - - return (int)Unity.TestFailures; -} - -static int selected(const char* filter, const char* name) -{ - if (filter == 0) - return 1; - return strstr(name, filter) ? 1 : 0; -} - -static int testSelected(const char* test) -{ - return selected(UnityFixture.NameFilter, test); -} - -static int groupSelected(const char* group) -{ - return selected(UnityFixture.GroupFilter, group); -} - -void UnityTestRunner(unityfunction* setup, - unityfunction* testBody, - unityfunction* teardown, - const char* printableName, - const char* group, - const char* name, - const char* file, - unsigned int line) -{ - if (testSelected(name) && groupSelected(group)) - { - Unity.TestFile = file; - Unity.CurrentTestName = printableName; - Unity.CurrentTestLineNumber = line; - if (!UnityFixture.Verbose) - UNITY_OUTPUT_CHAR('.'); - else - { - UnityPrint(printableName); - #ifndef UNITY_REPEAT_TEST_NAME - Unity.CurrentTestName = NULL; - #endif - } - - Unity.NumberOfTests++; - UnityMalloc_StartTest(); - UnityPointer_Init(); - - if (TEST_PROTECT()) - { - setup(); - testBody(); - } - if (TEST_PROTECT()) - { - teardown(); - } - if (TEST_PROTECT()) - { - UnityPointer_UndoAllSets(); - if (!Unity.CurrentTestFailed) - UnityMalloc_EndTest(); - } - UnityConcludeFixtureTest(); - } -} - -void UnityIgnoreTest(const char* printableName, const char* group, const char* name) -{ - if (testSelected(name) && groupSelected(group)) - { - Unity.NumberOfTests++; - Unity.TestIgnores++; - if (!UnityFixture.Verbose) - UNITY_OUTPUT_CHAR('!'); - else - { - UnityPrint(printableName); - UNITY_PRINT_EOL(); - } - } -} - - -/*------------------------------------------------- */ -/* Malloc and free stuff */ -#define MALLOC_DONT_FAIL -1 -static int malloc_count; -static int malloc_fail_countdown = MALLOC_DONT_FAIL; - -void UnityMalloc_StartTest(void) -{ - malloc_count = 0; - malloc_fail_countdown = MALLOC_DONT_FAIL; -} - -void UnityMalloc_EndTest(void) -{ - malloc_fail_countdown = MALLOC_DONT_FAIL; - if (malloc_count != 0) - { - UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!"); - } -} - -void UnityMalloc_MakeMallocFailAfterCount(int countdown) -{ - malloc_fail_countdown = countdown; -} - -/* These definitions are always included from unity_fixture_malloc_overrides.h */ -/* We undef to use them or avoid conflict with per the C standard */ -#undef malloc -#undef free -#undef calloc -#undef realloc - -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC -static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES]; -static size_t heap_index; -#else -#include -#endif - -typedef struct GuardBytes -{ - size_t size; - size_t guard_space; -} Guard; - - -static const char end[] = "END"; - -void* unity_malloc(size_t size) -{ - char* mem; - Guard* guard; - size_t total_size = size + sizeof(Guard) + sizeof(end); - - if (malloc_fail_countdown != MALLOC_DONT_FAIL) - { - if (malloc_fail_countdown == 0) - return NULL; - malloc_fail_countdown--; - } - - if (size == 0) return NULL; -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES) - { - guard = NULL; - } - else - { - guard = (Guard*)&unity_heap[heap_index]; - heap_index += total_size; - } -#else - guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size); -#endif - if (guard == NULL) return NULL; - malloc_count++; - guard->size = size; - guard->guard_space = 0; - mem = (char*)&(guard[1]); - memcpy(&mem[size], end, sizeof(end)); - - return (void*)mem; -} - -static int isOverrun(void* mem) -{ - Guard* guard = (Guard*)mem; - char* memAsChar = (char*)mem; - guard--; - - return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0; -} - -static void release_memory(void* mem) -{ - Guard* guard = (Guard*)mem; - guard--; - - malloc_count--; -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - if (mem == unity_heap + heap_index - guard->size - sizeof(end)) - { - heap_index -= (guard->size + sizeof(Guard) + sizeof(end)); - } -#else - UNITY_FIXTURE_FREE(guard); -#endif -} - -void unity_free(void* mem) -{ - int overrun; - - if (mem == NULL) - { - return; - } - - overrun = isOverrun(mem); - release_memory(mem); - if (overrun) - { - UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()"); - } -} - -void* unity_calloc(size_t num, size_t size) -{ - void* mem = unity_malloc(num * size); - if (mem == NULL) return NULL; - memset(mem, 0, num * size); - return mem; -} - -void* unity_realloc(void* oldMem, size_t size) -{ - Guard* guard = (Guard*)oldMem; - void* newMem; - - if (oldMem == NULL) return unity_malloc(size); - - guard--; - if (isOverrun(oldMem)) - { - release_memory(oldMem); - UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()"); - } - - if (size == 0) - { - release_memory(oldMem); - return NULL; - } - - if (guard->size >= size) return oldMem; - -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */ - if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) && - heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES) - { - release_memory(oldMem); /* Not thread-safe, like unity_heap generally */ - return unity_malloc(size); /* No memcpy since data is in place */ - } -#endif - newMem = unity_malloc(size); - if (newMem == NULL) return NULL; /* Do not release old memory */ - memcpy(newMem, oldMem, guard->size); - release_memory(oldMem); - return newMem; -} - - -/*-------------------------------------------------------- */ -/*Automatic pointer restoration functions */ -struct PointerPair -{ - void** pointer; - void* old_value; -}; - -static struct PointerPair pointer_store[UNITY_MAX_POINTERS]; -static int pointer_index = 0; - -void UnityPointer_Init(void) -{ - pointer_index = 0; -} - -void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line) -{ - if (pointer_index >= UNITY_MAX_POINTERS) - { - UNITY_TEST_FAIL(line, "Too many pointers set"); - } - else - { - pointer_store[pointer_index].pointer = pointer; - pointer_store[pointer_index].old_value = *pointer; - *pointer = newValue; - pointer_index++; - } -} - -void UnityPointer_UndoAllSets(void) -{ - while (pointer_index > 0) - { - pointer_index--; - *(pointer_store[pointer_index].pointer) = - pointer_store[pointer_index].old_value; - } -} - -int UnityGetCommandLineOptions(int argc, const char* argv[]) -{ - int i; - UnityFixture.Verbose = 0; - UnityFixture.GroupFilter = 0; - UnityFixture.NameFilter = 0; - UnityFixture.RepeatCount = 1; - - if (argc == 1) - return 0; - - for (i = 1; i < argc; ) - { - if (strcmp(argv[i], "-v") == 0) - { - UnityFixture.Verbose = 1; - i++; - } - else if (strcmp(argv[i], "-g") == 0) - { - i++; - if (i >= argc) - return 1; - UnityFixture.GroupFilter = argv[i]; - i++; - } - else if (strcmp(argv[i], "-n") == 0) - { - i++; - if (i >= argc) - return 1; - UnityFixture.NameFilter = argv[i]; - i++; - } - else if (strcmp(argv[i], "-r") == 0) - { - UnityFixture.RepeatCount = 2; - i++; - if (i < argc) - { - if (*(argv[i]) >= '0' && *(argv[i]) <= '9') - { - unsigned int digit = 0; - UnityFixture.RepeatCount = 0; - while (argv[i][digit] >= '0' && argv[i][digit] <= '9') - { - UnityFixture.RepeatCount *= 10; - UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0'; - } - i++; - } - } - } - else - { - /* ignore unknown parameter */ - i++; - } - } - return 0; -} - -void UnityConcludeFixtureTest(void) -{ - if (Unity.CurrentTestIgnored) - { - Unity.TestIgnores++; - UNITY_PRINT_EOL(); - } - else if (!Unity.CurrentTestFailed) - { - if (UnityFixture.Verbose) - { - UnityPrint(" PASS"); - UNITY_PRINT_EOL(); - } - } - else /* Unity.CurrentTestFailed */ - { - Unity.TestFailures++; - UNITY_PRINT_EOL(); - } - - Unity.CurrentTestFailed = 0; - Unity.CurrentTestIgnored = 0; -} diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.h b/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.h deleted file mode 100644 index 6f8d6234b..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#ifndef UNITY_FIXTURE_H_ -#define UNITY_FIXTURE_H_ - -#include "unity.h" -#include "unity_internals.h" -#include "unity_fixture_malloc_overrides.h" -#include "unity_fixture_internals.h" - -int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)); - - -#define TEST_GROUP(group)\ - static const char* TEST_GROUP_##group = #group - -#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\ - void TEST_##group##_SETUP(void) - -#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\ - void TEST_##group##_TEAR_DOWN(void) - - -#define TEST(group, name) \ - void TEST_##group##_##name##_(void);\ - void TEST_##group##_##name##_run(void);\ - void TEST_##group##_##name##_run(void)\ - {\ - UnityTestRunner(TEST_##group##_SETUP,\ - TEST_##group##_##name##_,\ - TEST_##group##_TEAR_DOWN,\ - "TEST(" #group ", " #name ")",\ - TEST_GROUP_##group, #name,\ - __FILE__, __LINE__);\ - }\ - void TEST_##group##_##name##_(void) - -#define IGNORE_TEST(group, name) \ - void TEST_##group##_##name##_(void);\ - void TEST_##group##_##name##_run(void);\ - void TEST_##group##_##name##_run(void)\ - {\ - UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\ - }\ - void TEST_##group##_##name##_(void) - -/* Call this for each test, insider the group runner */ -#define RUN_TEST_CASE(group, name) \ - { void TEST_##group##_##name##_run(void);\ - TEST_##group##_##name##_run(); } - -/* This goes at the bottom of each test file or in a separate c file */ -#define TEST_GROUP_RUNNER(group)\ - void TEST_##group##_GROUP_RUNNER(void);\ - void TEST_##group##_GROUP_RUNNER(void) - -/* Call this from main */ -#define RUN_TEST_GROUP(group)\ - { void TEST_##group##_GROUP_RUNNER(void);\ - TEST_##group##_GROUP_RUNNER(); } - -/* CppUTest Compatibility Macros */ -#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS -/* Sets a pointer and automatically restores it to its old value after teardown */ -#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__) -#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual)) -#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual)) -#define FAIL(message) TEST_FAIL_MESSAGE((message)) -#define CHECK(condition) TEST_ASSERT_TRUE((condition)) -#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual)) -#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual)) -#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual)) -#endif - -/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */ -void UnityMalloc_MakeMallocFailAfterCount(int count); - -#endif /* UNITY_FIXTURE_H_ */ diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_internals.h b/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_internals.h deleted file mode 100644 index aa0d9e7c0..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_internals.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#ifndef UNITY_FIXTURE_INTERNALS_H_ -#define UNITY_FIXTURE_INTERNALS_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -struct UNITY_FIXTURE_T -{ - int Verbose; - unsigned int RepeatCount; - const char* NameFilter; - const char* GroupFilter; -}; -extern struct UNITY_FIXTURE_T UnityFixture; - -typedef void unityfunction(void); -void UnityTestRunner(unityfunction* setup, - unityfunction* body, - unityfunction* teardown, - const char* printableName, - const char* group, - const char* name, - const char* file, unsigned int line); - -void UnityIgnoreTest(const char* printableName, const char* group, const char* name); -void UnityMalloc_StartTest(void); -void UnityMalloc_EndTest(void); -int UnityGetCommandLineOptions(int argc, const char* argv[]); -void UnityConcludeFixtureTest(void); - -void UnityPointer_Set(void** ptr, void* newValue, UNITY_LINE_TYPE line); -void UnityPointer_UndoAllSets(void); -void UnityPointer_Init(void); -#ifndef UNITY_MAX_POINTERS -#define UNITY_MAX_POINTERS 5 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* UNITY_FIXTURE_INTERNALS_H_ */ diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h b/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h deleted file mode 100644 index 7daba50aa..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_ -#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_ - -#include - -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC -/* Define this macro to remove the use of stdlib.h, malloc, and free. - * Many embedded systems do not have a heap or malloc/free by default. - * This internal unity_malloc() provides allocated memory deterministically from - * the end of an array only, unity_free() only releases from end-of-array, - * blocks are not coalesced, and memory not freed in LIFO order is stranded. */ - #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES - #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256 - #endif -#endif - -/* These functions are used by the Unity Fixture to allocate and release memory - * on the heap and can be overridden with platform-specific implementations. - * For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc() - * and UNITY_FIXTURE_FREE becomes vPortFree(). */ -#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE) - #include - #define UNITY_FIXTURE_MALLOC(size) malloc(size) - #define UNITY_FIXTURE_FREE(ptr) free(ptr) -#else - extern void* UNITY_FIXTURE_MALLOC(size_t size); - extern void UNITY_FIXTURE_FREE(void* ptr); -#endif - -#define malloc unity_malloc -#define calloc unity_calloc -#define realloc unity_realloc -#define free unity_free - -void* unity_malloc(size_t size); -void* unity_calloc(size_t num, size_t size); -void* unity_realloc(void * oldMem, size_t size); -void unity_free(void * mem); - -#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */ diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/Makefile b/components/cjson/cJSON/tests/unity/extras/fixture/test/Makefile deleted file mode 100644 index e6c62552f..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -CC = gcc -ifeq ($(shell uname -s), Darwin) -CC = clang -endif -#DEBUG = -O0 -g -CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror -CFLAGS += $(DEBUG) -DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar -DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\) -SRC = ../src/unity_fixture.c \ - ../../../src/unity.c \ - unity_fixture_Test.c \ - unity_fixture_TestRunner.c \ - unity_output_Spy.c \ - main/AllTests.c - -INC_DIR = -I../src -I../../../src/ -BUILD_DIR = ../build -TARGET = ../build/fixture_tests.exe - -all: default noStdlibMalloc 32bits - -default: $(BUILD_DIR) - $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_SUPPORT_64 - @ echo "default build" - ./$(TARGET) - -32bits: $(BUILD_DIR) - $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m32 - @ echo "32bits build" - ./$(TARGET) - -noStdlibMalloc: $(BUILD_DIR) - $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC - @ echo "build with noStdlibMalloc" - ./$(TARGET) - -C89: CFLAGS += -D UNITY_EXCLUDE_STDINT_H # C89 did not have type 'long long', -C89: $(BUILD_DIR) - $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -std=c89 && ./$(TARGET) - $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC -std=c89 - ./$(TARGET) - -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) - -clean: - rm -f $(TARGET) $(BUILD_DIR)/*.gc* - -cov: $(BUILD_DIR) - cd $(BUILD_DIR) && \ - $(CC) $(DEFINES) $(foreach i, $(SRC), ../test/$(i)) $(INC_DIR) -o $(TARGET) -fprofile-arcs -ftest-coverage - rm -f $(BUILD_DIR)/*.gcda - ./$(TARGET) > /dev/null ; ./$(TARGET) -v > /dev/null - cd $(BUILD_DIR) && \ - gcov unity_fixture.c | head -3 - grep '###' $(BUILD_DIR)/unity_fixture.c.gcov -C2 || true # Show uncovered lines - -# These extended flags DO get included before any target build runs -CFLAGS += -Wbad-function-cast -CFLAGS += -Wcast-qual -CFLAGS += -Wconversion -CFLAGS += -Wformat=2 -CFLAGS += -Wmissing-prototypes -CFLAGS += -Wold-style-definition -CFLAGS += -Wpointer-arith -CFLAGS += -Wshadow -CFLAGS += -Wstrict-overflow=5 -CFLAGS += -Wstrict-prototypes -CFLAGS += -Wswitch-default -CFLAGS += -Wundef -CFLAGS += -Wno-error=undef # Warning only, this should not stop the build -CFLAGS += -Wunreachable-code -CFLAGS += -Wunused -CFLAGS += -fstrict-aliasing diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/main/AllTests.c b/components/cjson/cJSON/tests/unity/extras/fixture/test/main/AllTests.c deleted file mode 100644 index e30dd853d..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/main/AllTests.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#include "unity_fixture.h" - -static void runAllTests(void) -{ - RUN_TEST_GROUP(UnityFixture); - RUN_TEST_GROUP(UnityCommandOptions); - RUN_TEST_GROUP(LeakDetection); - RUN_TEST_GROUP(InternalMalloc); -} - -int main(int argc, const char* argv[]) -{ - return UnityMain(argc, argv, runAllTests); -} - diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/template_fixture_tests.c b/components/cjson/cJSON/tests/unity/extras/fixture/test/template_fixture_tests.c deleted file mode 100644 index 18bbb89e8..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/template_fixture_tests.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#include "unity_fixture.h" - -static int data = -1; - -TEST_GROUP(mygroup); - -TEST_SETUP(mygroup) -{ - data = 0; -} - -TEST_TEAR_DOWN(mygroup) -{ - data = -1; -} - -TEST(mygroup, test1) -{ - TEST_ASSERT_EQUAL_INT(0, data); -} - -TEST(mygroup, test2) -{ - TEST_ASSERT_EQUAL_INT(0, data); - data = 5; -} - -TEST(mygroup, test3) -{ - data = 7; - TEST_ASSERT_EQUAL_INT(7, data); -} diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_Test.c b/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_Test.c deleted file mode 100644 index a842b0853..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_Test.c +++ /dev/null @@ -1,543 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#include "unity_fixture.h" -#include "unity_output_Spy.h" -#include -#include - -TEST_GROUP(UnityFixture); - -TEST_SETUP(UnityFixture) -{ -} - -TEST_TEAR_DOWN(UnityFixture) -{ -} - -static int* pointer1 = 0; -static int* pointer2 = (int*)2; -static int* pointer3 = (int*)3; -static int int1; -static int int2; -static int int3; -static int int4; - -TEST(UnityFixture, PointerSetting) -{ - TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); - UT_PTR_SET(pointer1, &int1); - UT_PTR_SET(pointer2, &int2); - UT_PTR_SET(pointer3, &int3); - TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1); - TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2); - TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3); - UT_PTR_SET(pointer1, &int4); - UnityPointer_UndoAllSets(); - TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); - TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2); - TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3); -} - -TEST(UnityFixture, ForceMallocFail) -{ - void* m; - void* mfails; - UnityMalloc_MakeMallocFailAfterCount(1); - m = malloc(10); - CHECK(m); - mfails = malloc(10); - TEST_ASSERT_POINTERS_EQUAL(0, mfails); - free(m); -} - -TEST(UnityFixture, ReallocSmallerIsUnchanged) -{ - void* m1 = malloc(10); - void* m2 = realloc(m1, 5); - TEST_ASSERT_POINTERS_EQUAL(m1, m2); - free(m2); -} - -TEST(UnityFixture, ReallocSameIsUnchanged) -{ - void* m1 = malloc(10); - void* m2 = realloc(m1, 10); - TEST_ASSERT_POINTERS_EQUAL(m1, m2); - free(m2); -} - -TEST(UnityFixture, ReallocLargerNeeded) -{ - void* m1 = malloc(10); - void* m2; - CHECK(m1); - strcpy((char*)m1, "123456789"); - m2 = realloc(m1, 15); - /* CHECK(m1 != m2); //Depends on implementation */ - STRCMP_EQUAL("123456789", m2); - free(m2); -} - -TEST(UnityFixture, ReallocNullPointerIsLikeMalloc) -{ - void* m = realloc(0, 15); - CHECK(m != 0); - free(m); -} - -TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer) -{ - void* m1 = malloc(10); - void* m2 = realloc(m1, 0); - TEST_ASSERT_POINTERS_EQUAL(0, m2); -} - -TEST(UnityFixture, CallocFillsWithZero) -{ - void* m = calloc(3, sizeof(char)); - char* s = (char*)m; - CHECK(m); - TEST_ASSERT_BYTES_EQUAL(0, s[0]); - TEST_ASSERT_BYTES_EQUAL(0, s[1]); - TEST_ASSERT_BYTES_EQUAL(0, s[2]); - free(m); -} - -static char *p1; -static char *p2; - -TEST(UnityFixture, PointerSet) -{ - char c1; - char c2; - char newC1; - char newC2; - p1 = &c1; - p2 = &c2; - - UnityPointer_Init(); - UT_PTR_SET(p1, &newC1); - UT_PTR_SET(p2, &newC2); - TEST_ASSERT_POINTERS_EQUAL(&newC1, p1); - TEST_ASSERT_POINTERS_EQUAL(&newC2, p2); - UnityPointer_UndoAllSets(); - TEST_ASSERT_POINTERS_EQUAL(&c1, p1); - TEST_ASSERT_POINTERS_EQUAL(&c2, p2); -} - -TEST(UnityFixture, FreeNULLSafety) -{ - free(NULL); -} - -TEST(UnityFixture, ConcludeTestIncrementsFailCount) -{ - UNITY_UINT savedFails = Unity.TestFailures; - UNITY_UINT savedIgnores = Unity.TestIgnores; - UnityOutputCharSpy_Enable(1); - Unity.CurrentTestFailed = 1; - UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */ - Unity.CurrentTestIgnored = 1; - UnityConcludeFixtureTest(); /* Resets TestIgnored */ - UnityOutputCharSpy_Enable(0); - TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures); - TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores); - Unity.TestFailures = savedFails; - Unity.TestIgnores = savedIgnores; -} - -/*------------------------------------------------------------ */ - -TEST_GROUP(UnityCommandOptions); - -static int savedVerbose; -static unsigned int savedRepeat; -static const char* savedName; -static const char* savedGroup; - -TEST_SETUP(UnityCommandOptions) -{ - savedVerbose = UnityFixture.Verbose; - savedRepeat = UnityFixture.RepeatCount; - savedName = UnityFixture.NameFilter; - savedGroup = UnityFixture.GroupFilter; -} - -TEST_TEAR_DOWN(UnityCommandOptions) -{ - UnityFixture.Verbose = savedVerbose; - UnityFixture.RepeatCount= savedRepeat; - UnityFixture.NameFilter = savedName; - UnityFixture.GroupFilter = savedGroup; -} - - -static const char* noOptions[] = { - "testrunner.exe" -}; - -TEST(UnityCommandOptions, DefaultOptions) -{ - UnityGetCommandLineOptions(1, noOptions); - TEST_ASSERT_EQUAL(0, UnityFixture.Verbose); - TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter); - TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter); - TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount); -} - -static const char* verbose[] = { - "testrunner.exe", - "-v" -}; - -TEST(UnityCommandOptions, OptionVerbose) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose)); - TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); -} - -static const char* group[] = { - "testrunner.exe", - "-g", "groupname" -}; - -TEST(UnityCommandOptions, OptionSelectTestByGroup) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group)); - STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); -} - -static const char* name[] = { - "testrunner.exe", - "-n", "testname" -}; - -TEST(UnityCommandOptions, OptionSelectTestByName) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name)); - STRCMP_EQUAL("testname", UnityFixture.NameFilter); -} - -static const char* repeat[] = { - "testrunner.exe", - "-r", "99" -}; - -TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat)); - TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); -} - -TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat)); - TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount); -} - -static const char* multiple[] = { - "testrunner.exe", - "-v", - "-g", "groupname", - "-n", "testname", - "-r", "98" -}; - -TEST(UnityCommandOptions, MultipleOptions) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple)); - TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); - STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); - STRCMP_EQUAL("testname", UnityFixture.NameFilter); - TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); -} - -static const char* dashRNotLast[] = { - "testrunner.exe", - "-v", - "-g", "gggg", - "-r", - "-n", "tttt", -}; - -TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast)); - TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); - STRCMP_EQUAL("gggg", UnityFixture.GroupFilter); - STRCMP_EQUAL("tttt", UnityFixture.NameFilter); - TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); -} - -static const char* unknownCommand[] = { - "testrunner.exe", - "-v", - "-g", "groupname", - "-n", "testname", - "-r", "98", - "-z" -}; -TEST(UnityCommandOptions, UnknownCommandIsIgnored) -{ - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand)); - TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); - STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); - STRCMP_EQUAL("testname", UnityFixture.NameFilter); - TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); -} - -TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails) -{ - TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand)); - TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand)); - TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL)); -} - -TEST(UnityCommandOptions, GroupFilterReallyFilters) -{ - UNITY_UINT saved = Unity.NumberOfTests; - TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand)); - UnityIgnoreTest(NULL, "non-matching", NULL); - TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests); -} - -IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored) -{ - TEST_FAIL_MESSAGE("This test should not run!"); -} - -/*------------------------------------------------------------ */ - -TEST_GROUP(LeakDetection); - -TEST_SETUP(LeakDetection) -{ -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - UnityOutputCharSpy_Create(200); -#else - UnityOutputCharSpy_Create(1000); -#endif -} - -TEST_TEAR_DOWN(LeakDetection) -{ - UnityOutputCharSpy_Destroy(); -} - -#define EXPECT_ABORT_BEGIN \ - { \ - jmp_buf TestAbortFrame; \ - memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \ - if (TEST_PROTECT()) \ - { - -#define EXPECT_ABORT_END \ - } \ - memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \ - } - -/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */ -#ifdef __STDC_VERSION__ - -#if __STDC_VERSION__ >= 199901L -#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0) -#define ASSIGN_VALUE(a) VAL_##a -#define VAL_UnityOutputCharSpy_OutputChar 0, 1 -#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway) -#define SECOND_PARAM(a, b, ...) b -#if USING_SPY_AS(UNITY_OUTPUT_CHAR) - #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */ -#endif -#endif /* >= 199901 */ - -#else /* __STDC_VERSION__ else */ -#define UnityOutputCharSpy_OutputChar 42 -#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */ - #define USING_OUTPUT_SPY -#endif -#undef UnityOutputCharSpy_OutputChar -#endif /* __STDC_VERSION__ */ - -TEST(LeakDetection, DetectsLeak) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests"); -#else - void* m = malloc(10); - TEST_ASSERT_NOT_NULL(m); - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - UnityMalloc_EndTest(); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!")); - free(m); -#endif -} - -TEST(LeakDetection, BufferOverrunFoundDuringFree) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - void* m = malloc(10); - char* s = (char*)m; - TEST_ASSERT_NOT_NULL(m); - s[10] = (char)0xFF; - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - free(m); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); -#endif -} - -TEST(LeakDetection, BufferOverrunFoundDuringRealloc) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - void* m = malloc(10); - char* s = (char*)m; - TEST_ASSERT_NOT_NULL(m); - s[10] = (char)0xFF; - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - m = realloc(m, 100); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); -#endif -} - -TEST(LeakDetection, BufferGuardWriteFoundDuringFree) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - void* m = malloc(10); - char* s = (char*)m; - TEST_ASSERT_NOT_NULL(m); - s[-1] = (char)0x00; /* Will not detect 0 */ - s[-2] = (char)0x01; - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - free(m); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); -#endif -} - -TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - void* m = malloc(10); - char* s = (char*)m; - TEST_ASSERT_NOT_NULL(m); - s[-1] = (char)0x0A; - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - m = realloc(m, 100); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); -#endif -} - -TEST(LeakDetection, PointerSettingMax) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - int i; - for (i = 0; i < UNITY_MAX_POINTERS; i++) UT_PTR_SET(pointer1, &int1); - UnityOutputCharSpy_Enable(1); - EXPECT_ABORT_BEGIN - UT_PTR_SET(pointer1, &int1); - EXPECT_ABORT_END - UnityOutputCharSpy_Enable(0); - Unity.CurrentTestFailed = 0; - CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set")); -#endif -} - -/*------------------------------------------------------------ */ - -TEST_GROUP(InternalMalloc); -#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \ - ptr = malloc(10); free(ptr); \ - TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order"); - - -TEST_SETUP(InternalMalloc) { } -TEST_TEAR_DOWN(InternalMalloc) { } - -TEST(InternalMalloc, MallocPastBufferFails) -{ -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); - void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); - free(m); - TEST_ASSERT_NOT_NULL(m); - TEST_ASSERT_NULL(n); - TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); -#endif -} - -TEST(InternalMalloc, CallocPastBufferFails) -{ -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); - void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2); - free(m); - TEST_ASSERT_NOT_NULL(m); - TEST_ASSERT_NULL(n); - TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); -#endif -} - -TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace) -{ -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); - void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9); - free(n); - TEST_ASSERT_NOT_NULL(m); - TEST_ASSERT_EQUAL(m, n); - TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); -#endif -} - -TEST(InternalMalloc, ReallocFailDoesNotFreeMem) -{ -#ifdef UNITY_EXCLUDE_STDLIB_MALLOC - void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); - void* n1 = malloc(10); - void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); - void* n2 = malloc(10); - - free(n2); - if (out_of_mem == NULL) free(n1); - free(m); - - TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */ - TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */ - TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */ - TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2); -#endif -} diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_TestRunner.c b/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_TestRunner.c deleted file mode 100644 index e8713e1bc..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_fixture_TestRunner.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#include "unity_fixture.h" - -TEST_GROUP_RUNNER(UnityFixture) -{ - RUN_TEST_CASE(UnityFixture, PointerSetting); - RUN_TEST_CASE(UnityFixture, ForceMallocFail); - RUN_TEST_CASE(UnityFixture, ReallocSmallerIsUnchanged); - RUN_TEST_CASE(UnityFixture, ReallocSameIsUnchanged); - RUN_TEST_CASE(UnityFixture, ReallocLargerNeeded); - RUN_TEST_CASE(UnityFixture, ReallocNullPointerIsLikeMalloc); - RUN_TEST_CASE(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer); - RUN_TEST_CASE(UnityFixture, CallocFillsWithZero); - RUN_TEST_CASE(UnityFixture, PointerSet); - RUN_TEST_CASE(UnityFixture, FreeNULLSafety); - RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount); -} - -TEST_GROUP_RUNNER(UnityCommandOptions) -{ - RUN_TEST_CASE(UnityCommandOptions, DefaultOptions); - RUN_TEST_CASE(UnityCommandOptions, OptionVerbose); - RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByGroup); - RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByName); - RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount); - RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount); - RUN_TEST_CASE(UnityCommandOptions, MultipleOptions); - RUN_TEST_CASE(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified); - RUN_TEST_CASE(UnityCommandOptions, UnknownCommandIsIgnored); - RUN_TEST_CASE(UnityCommandOptions, GroupOrNameFilterWithoutStringFails); - RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters); - RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored); -} - -TEST_GROUP_RUNNER(LeakDetection) -{ - RUN_TEST_CASE(LeakDetection, DetectsLeak); - RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree); - RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc); - RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringFree); - RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringRealloc); - RUN_TEST_CASE(LeakDetection, PointerSettingMax); -} - -TEST_GROUP_RUNNER(InternalMalloc) -{ - RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails); - RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails); - RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace); - RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem); -} diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.c b/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.c deleted file mode 100644 index be87bd58f..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - - -#include "unity_output_Spy.h" -#include "unity_fixture.h" - -#include -#include - -static int size; -static int count; -static char* buffer; -static int spy_enable; - -void UnityOutputCharSpy_Create(int s) -{ - size = (s > 0) ? s : 0; - count = 0; - spy_enable = 0; - buffer = malloc((size_t)size); - TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__); - memset(buffer, 0, (size_t)size); -} - -void UnityOutputCharSpy_Destroy(void) -{ - size = 0; - free(buffer); -} - -void UnityOutputCharSpy_OutputChar(int c) -{ - if (spy_enable) - { - if (count < (size-1)) - buffer[count++] = (char)c; - } - else - { - putchar(c); - } -} - -const char * UnityOutputCharSpy_Get(void) -{ - return buffer; -} - -void UnityOutputCharSpy_Enable(int enable) -{ - spy_enable = enable; -} diff --git a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.h b/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.h deleted file mode 100644 index b30a7f13b..000000000 --- a/components/cjson/cJSON/tests/unity/extras/fixture/test/unity_output_Spy.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (c) 2010 James Grenning and Contributed to Unity Project - * ========================================== - * Unity Project - A Test Framework for C - * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - * [Released under MIT License. Please refer to license.txt for details] - * ========================================== */ - -#ifndef D_unity_output_Spy_H -#define D_unity_output_Spy_H - -void UnityOutputCharSpy_Create(int s); -void UnityOutputCharSpy_Destroy(void); -void UnityOutputCharSpy_OutputChar(int c); -const char * UnityOutputCharSpy_Get(void); -void UnityOutputCharSpy_Enable(int enable); - -#endif diff --git a/components/cjson/cJSON/tests/unity/release/build.info b/components/cjson/cJSON/tests/unity/release/build.info deleted file mode 100644 index 56d591286..000000000 --- a/components/cjson/cJSON/tests/unity/release/build.info +++ /dev/null @@ -1,2 +0,0 @@ -122 - diff --git a/components/cjson/cJSON/tests/unity/release/version.info b/components/cjson/cJSON/tests/unity/release/version.info deleted file mode 100644 index cf12b30d2..000000000 --- a/components/cjson/cJSON/tests/unity/release/version.info +++ /dev/null @@ -1,2 +0,0 @@ -2.4.3 - diff --git a/components/cjson/cJSON/tests/unity/src/unity.c b/components/cjson/cJSON/tests/unity/src/unity.c deleted file mode 100644 index 0f2d2dea3..000000000 --- a/components/cjson/cJSON/tests/unity/src/unity.c +++ /dev/null @@ -1,1570 +0,0 @@ -/* ========================================================================= - Unity Project - A Test Framework for C - Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -============================================================================ */ - -#define UNITY_INCLUDE_SETUP_STUBS -#include "unity.h" -#include - -/* If omitted from header, declare overrideable prototypes here so they're ready for use */ -#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION -void UNITY_OUTPUT_CHAR(int); -#endif - -/* Helpful macros for us to use here in Assert functions */ -#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; TEST_ABORT(); } -#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; TEST_ABORT(); } -#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return - -struct UNITY_STORAGE_T Unity; - -#ifdef UNITY_OUTPUT_COLOR -static const char UnityStrOk[] = "\033[42mOK\033[00m"; -static const char UnityStrPass[] = "\033[42mPASS\033[00m"; -static const char UnityStrFail[] = "\033[41mFAIL\033[00m"; -static const char UnityStrIgnore[] = "\033[43mIGNORE\033[00m"; -#else -static const char UnityStrOk[] = "OK"; -static const char UnityStrPass[] = "PASS"; -static const char UnityStrFail[] = "FAIL"; -static const char UnityStrIgnore[] = "IGNORE"; -#endif -static const char UnityStrNull[] = "NULL"; -static const char UnityStrSpacer[] = ". "; -static const char UnityStrExpected[] = " Expected "; -static const char UnityStrWas[] = " Was "; -static const char UnityStrGt[] = " to be greater than "; -static const char UnityStrLt[] = " to be less than "; -static const char UnityStrOrEqual[] = "or equal to "; -static const char UnityStrElement[] = " Element "; -static const char UnityStrByte[] = " Byte "; -static const char UnityStrMemory[] = " Memory Mismatch."; -static const char UnityStrDelta[] = " Values Not Within Delta "; -static const char UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; -static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; -static const char UnityStrNullPointerForActual[] = " Actual pointer was NULL"; -#ifndef UNITY_EXCLUDE_FLOAT -static const char UnityStrNot[] = "Not "; -static const char UnityStrInf[] = "Infinity"; -static const char UnityStrNegInf[] = "Negative Infinity"; -static const char UnityStrNaN[] = "NaN"; -static const char UnityStrDet[] = "Determinate"; -static const char UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; -#endif -const char UnityStrErrFloat[] = "Unity Floating Point Disabled"; -const char UnityStrErrDouble[] = "Unity Double Precision Disabled"; -const char UnityStrErr64[] = "Unity 64-bit Support Disabled"; -static const char UnityStrBreaker[] = "-----------------------"; -static const char UnityStrResultsTests[] = " Tests "; -static const char UnityStrResultsFailures[] = " Failures "; -static const char UnityStrResultsIgnored[] = " Ignored "; -static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; -static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; - -/*----------------------------------------------- - * Pretty Printers & Test Result Output Handlers - *-----------------------------------------------*/ - -void UnityPrint(const char* string) -{ - const char* pch = string; - - if (pch != NULL) - { - while (*pch) - { - /* printable characters plus CR & LF are printed */ - if ((*pch <= 126) && (*pch >= 32)) - { - UNITY_OUTPUT_CHAR(*pch); - } - /* write escaped carriage returns */ - else if (*pch == 13) - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('r'); - } - /* write escaped line feeds */ - else if (*pch == 10) - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('n'); - } -#ifdef UNITY_OUTPUT_COLOR - /* print ANSI escape code */ - else if (*pch == 27 && *(pch + 1) == '[') - { - while (*pch && *pch != 'm') - { - UNITY_OUTPUT_CHAR(*pch); - pch++; - } - UNITY_OUTPUT_CHAR('m'); - } -#endif - /* unprintable characters are shown as codes */ - else - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('x'); - UnityPrintNumberHex((UNITY_UINT)*pch, 2); - } - pch++; - } - } -} - -void UnityPrintLen(const char* string, const UNITY_UINT32 length) -{ - const char* pch = string; - - if (pch != NULL) - { - while (*pch && (UNITY_UINT32)(pch - string) < length) - { - /* printable characters plus CR & LF are printed */ - if ((*pch <= 126) && (*pch >= 32)) - { - UNITY_OUTPUT_CHAR(*pch); - } - /* write escaped carriage returns */ - else if (*pch == 13) - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('r'); - } - /* write escaped line feeds */ - else if (*pch == 10) - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('n'); - } - /* unprintable characters are shown as codes */ - else - { - UNITY_OUTPUT_CHAR('\\'); - UNITY_OUTPUT_CHAR('x'); - UnityPrintNumberHex((UNITY_UINT)*pch, 2); - } - pch++; - } - } -} - -/*-----------------------------------------------*/ -void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) -{ - if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) - { - UnityPrintNumber(number); - } - else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) - { - UnityPrintNumberUnsigned((UNITY_UINT)number); - } - else - { - UNITY_OUTPUT_CHAR('0'); - UNITY_OUTPUT_CHAR('x'); - UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); - } -} - -/*-----------------------------------------------*/ -void UnityPrintNumber(const UNITY_INT number_to_print) -{ - UNITY_UINT number = (UNITY_UINT)number_to_print; - - if (number_to_print < 0) - { - /* A negative number, including MIN negative */ - UNITY_OUTPUT_CHAR('-'); - number = (UNITY_UINT)(-number_to_print); - } - UnityPrintNumberUnsigned(number); -} - -/*----------------------------------------------- - * basically do an itoa using as little ram as possible */ -void UnityPrintNumberUnsigned(const UNITY_UINT number) -{ - UNITY_UINT divisor = 1; - - /* figure out initial divisor */ - while (number / divisor > 9) - { - divisor *= 10; - } - - /* now mod and print, then divide divisor */ - do - { - UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); - divisor /= 10; - } while (divisor > 0); -} - -/*-----------------------------------------------*/ -void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) -{ - int nibble; - char nibbles = nibbles_to_print; - if ((unsigned)nibbles > (2 * sizeof(number))) - nibbles = 2 * sizeof(number); - - while (nibbles > 0) - { - nibbles--; - nibble = (int)(number >> (nibbles * 4)) & 0x0F; - if (nibble <= 9) - { - UNITY_OUTPUT_CHAR((char)('0' + nibble)); - } - else - { - UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); - } - } -} - -/*-----------------------------------------------*/ -void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) -{ - UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); - UNITY_INT32 i; - - for (i = 0; i < UNITY_INT_WIDTH; i++) - { - if (current_bit & mask) - { - if (current_bit & number) - { - UNITY_OUTPUT_CHAR('1'); - } - else - { - UNITY_OUTPUT_CHAR('0'); - } - } - else - { - UNITY_OUTPUT_CHAR('X'); - } - current_bit = current_bit >> 1; - } -} - -/*-----------------------------------------------*/ -#ifndef UNITY_EXCLUDE_FLOAT_PRINT -/* This function prints a floating-point value in a format similar to - * printf("%.6g"). It can work with either single- or double-precision, - * but for simplicity, it prints only 6 significant digits in either case. - * Printing more than 6 digits accurately is hard (at least in the single- - * precision case) and isn't attempted here. */ -void UnityPrintFloat(const UNITY_DOUBLE input_number) -{ - UNITY_DOUBLE number = input_number; - - /* print minus sign (including for negative zero) */ - if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f)) - { - UNITY_OUTPUT_CHAR('-'); - number = -number; - } - - /* handle zero, NaN, and +/- infinity */ - if (number == 0.0f) UnityPrint("0"); - else if (isnan(number)) UnityPrint("nan"); - else if (isinf(number)) UnityPrint("inf"); - else - { - int exponent = 0; - int decimals, digits; - UNITY_INT32 n; - char buf[16]; - - /* scale up or down by powers of 10 */ - while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; } - while (number < 100000.0f) { number *= 10.0f; exponent--; } - while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; } - while (number > 1000000.0f) { number /= 10.0f; exponent++; } - - /* round to nearest integer */ - n = ((UNITY_INT32)(number + number) + 1) / 2; - if (n > 999999) - { - n = 100000; - exponent++; - } - - /* determine where to place decimal point */ - decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5; - exponent += decimals; - - /* truncate trailing zeroes after decimal point */ - while (decimals > 0 && n % 10 == 0) - { - n /= 10; - decimals--; - } - - /* build up buffer in reverse order */ - digits = 0; - while (n != 0 || digits < decimals + 1) - { - buf[digits++] = (char)('0' + n % 10); - n /= 10; - } - while (digits > 0) - { - if(digits == decimals) UNITY_OUTPUT_CHAR('.'); - UNITY_OUTPUT_CHAR(buf[--digits]); - } - - /* print exponent if needed */ - if (exponent != 0) - { - UNITY_OUTPUT_CHAR('e'); - - if(exponent < 0) - { - UNITY_OUTPUT_CHAR('-'); - exponent = -exponent; - } - else - { - UNITY_OUTPUT_CHAR('+'); - } - - digits = 0; - while (exponent != 0 || digits < 2) - { - buf[digits++] = (char)('0' + exponent % 10); - exponent /= 10; - } - while (digits > 0) - { - UNITY_OUTPUT_CHAR(buf[--digits]); - } - } - } -} -#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ - -/*-----------------------------------------------*/ -static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) -{ - UnityPrint(file); - UNITY_OUTPUT_CHAR(':'); - UnityPrintNumber((UNITY_INT)line); - UNITY_OUTPUT_CHAR(':'); - UnityPrint(Unity.CurrentTestName); - UNITY_OUTPUT_CHAR(':'); -} - -/*-----------------------------------------------*/ -static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) -{ - UnityTestResultsBegin(Unity.TestFile, line); - UnityPrint(UnityStrFail); - UNITY_OUTPUT_CHAR(':'); -} - -/*-----------------------------------------------*/ -void UnityConcludeTest(void) -{ - if (Unity.CurrentTestIgnored) - { - Unity.TestIgnores++; - } - else if (!Unity.CurrentTestFailed) - { - UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); - UnityPrint(UnityStrPass); - } - else - { - Unity.TestFailures++; - } - - Unity.CurrentTestFailed = 0; - Unity.CurrentTestIgnored = 0; - UNITY_PRINT_EOL(); - UNITY_FLUSH_CALL(); -} - -/*-----------------------------------------------*/ -static void UnityAddMsgIfSpecified(const char* msg) -{ - if (msg) - { - UnityPrint(UnityStrSpacer); -#ifndef UNITY_EXCLUDE_DETAILS - if (Unity.CurrentDetail1) - { - UnityPrint(UnityStrDetail1Name); - UnityPrint(Unity.CurrentDetail1); - if (Unity.CurrentDetail2) - { - UnityPrint(UnityStrDetail2Name); - UnityPrint(Unity.CurrentDetail2); - } - UnityPrint(UnityStrSpacer); - } -#endif - UnityPrint(msg); - } -} - -/*-----------------------------------------------*/ -static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) -{ - UnityPrint(UnityStrExpected); - if (expected != NULL) - { - UNITY_OUTPUT_CHAR('\''); - UnityPrint(expected); - UNITY_OUTPUT_CHAR('\''); - } - else - { - UnityPrint(UnityStrNull); - } - UnityPrint(UnityStrWas); - if (actual != NULL) - { - UNITY_OUTPUT_CHAR('\''); - UnityPrint(actual); - UNITY_OUTPUT_CHAR('\''); - } - else - { - UnityPrint(UnityStrNull); - } -} - -/*-----------------------------------------------*/ -static void UnityPrintExpectedAndActualStringsLen(const char* expected, - const char* actual, - const UNITY_UINT32 length) -{ - UnityPrint(UnityStrExpected); - if (expected != NULL) - { - UNITY_OUTPUT_CHAR('\''); - UnityPrintLen(expected, length); - UNITY_OUTPUT_CHAR('\''); - } - else - { - UnityPrint(UnityStrNull); - } - UnityPrint(UnityStrWas); - if (actual != NULL) - { - UNITY_OUTPUT_CHAR('\''); - UnityPrintLen(actual, length); - UNITY_OUTPUT_CHAR('\''); - } - else - { - UnityPrint(UnityStrNull); - } -} - -/*----------------------------------------------- - * Assertion & Control Helpers - *-----------------------------------------------*/ - -static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, - UNITY_INTERNAL_PTR actual, - const UNITY_LINE_TYPE lineNumber, - const char* msg) -{ - if (expected == actual) return 0; /* Both are NULL or same pointer */ - - /* print and return true if just expected is NULL */ - if (expected == NULL) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrNullPointerForExpected); - UnityAddMsgIfSpecified(msg); - return 1; - } - - /* print and return true if just actual is NULL */ - if (actual == NULL) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrNullPointerForActual); - UnityAddMsgIfSpecified(msg); - return 1; - } - - return 0; /* return false if neither is NULL */ -} - -/*----------------------------------------------- - * Assertion Functions - *-----------------------------------------------*/ - -void UnityAssertBits(const UNITY_INT mask, - const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - RETURN_IF_FAIL_OR_IGNORE; - - if ((mask & expected) != (mask & actual)) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); - UnityPrint(UnityStrWas); - UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertEqualNumber(const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style) -{ - RETURN_IF_FAIL_OR_IGNORE; - - if (expected != actual) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - UnityPrintNumberByStyle(expected, style); - UnityPrint(UnityStrWas); - UnityPrintNumberByStyle(actual, style); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, - const UNITY_INT actual, - const UNITY_COMPARISON_T compare, - const char *msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style) -{ - int failed = 0; - RETURN_IF_FAIL_OR_IGNORE; - - if (threshold == actual && compare & UNITY_EQUAL_TO) return; - if (threshold == actual) failed = 1; - - if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) - { - if (actual > threshold && compare & UNITY_SMALLER_THAN) failed = 1; - if (actual < threshold && compare & UNITY_GREATER_THAN) failed = 1; - } - else /* UINT or HEX */ - { - if ((UNITY_UINT)actual > (UNITY_UINT)threshold && compare & UNITY_SMALLER_THAN) failed = 1; - if ((UNITY_UINT)actual < (UNITY_UINT)threshold && compare & UNITY_GREATER_THAN) failed = 1; - } - - if (failed) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - UnityPrintNumberByStyle(actual, style); - if (compare & UNITY_GREATER_THAN) UnityPrint(UnityStrGt); - if (compare & UNITY_SMALLER_THAN) UnityPrint(UnityStrLt); - if (compare & UNITY_EQUAL_TO) UnityPrint(UnityStrOrEqual); - UnityPrintNumberByStyle(threshold, style); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -#define UnityPrintPointlessAndBail() \ -{ \ - UnityTestResultsFailBegin(lineNumber); \ - UnityPrint(UnityStrPointless); \ - UnityAddMsgIfSpecified(msg); \ - UNITY_FAIL_AND_BAIL; } - -/*-----------------------------------------------*/ -void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, - UNITY_INTERNAL_PTR actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style, - const UNITY_FLAGS_T flags) -{ - UNITY_UINT32 elements = num_elements; - unsigned int length = style & 0xF; - - RETURN_IF_FAIL_OR_IGNORE; - - if (num_elements == 0) - { - UnityPrintPointlessAndBail(); - } - - if (expected == actual) return; /* Both are NULL or same pointer */ - if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) - UNITY_FAIL_AND_BAIL; - - while (elements--) - { - UNITY_INT expect_val; - UNITY_INT actual_val; - switch (length) - { - case 1: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; - break; - case 2: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; - break; -#ifdef UNITY_SUPPORT_64 - case 8: - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; - break; -#endif - default: /* length 4 bytes */ - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; - length = 4; - break; - } - - if (expect_val != actual_val) - { - if (style & UNITY_DISPLAY_RANGE_UINT && length < sizeof(expect_val)) - { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ - UNITY_INT mask = 1; - mask = (mask << 8 * length) - 1; - expect_val &= mask; - actual_val &= mask; - } - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrElement); - UnityPrintNumberUnsigned(num_elements - elements - 1); - UnityPrint(UnityStrExpected); - UnityPrintNumberByStyle(expect_val, style); - UnityPrint(UnityStrWas); - UnityPrintNumberByStyle(actual_val, style); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } - if (flags == UNITY_ARRAY_TO_ARRAY) - { - expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected); - } - actual = (UNITY_INTERNAL_PTR)(length + (const char*)actual); - } -} - -/*-----------------------------------------------*/ -#ifndef UNITY_EXCLUDE_FLOAT -/* Wrap this define in a function with variable types as float or double */ -#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ - if (isinf(expected) && isinf(actual) && ((expected < 0) == (actual < 0))) return 1; \ - if (UNITY_NAN_CHECK) return 1; \ - diff = actual - expected; \ - if (diff < 0) diff = -diff; \ - if (delta < 0) delta = -delta; \ - return !(isnan(diff) || isinf(diff) || (diff > delta)) - /* This first part of this condition will catch any NaN or Infinite values */ -#ifndef UNITY_NAN_NOT_EQUAL_NAN - #define UNITY_NAN_CHECK isnan(expected) && isnan(actual) -#else - #define UNITY_NAN_CHECK 0 -#endif - -#ifndef UNITY_EXCLUDE_FLOAT_PRINT - #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ - { \ - UnityPrint(UnityStrExpected); \ - UnityPrintFloat(expected); \ - UnityPrint(UnityStrWas); \ - UnityPrintFloat(actual); } -#else - #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ - UnityPrint(UnityStrDelta) -#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ - -static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) -{ - UNITY_FLOAT diff; - UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); -} - -void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) -{ - UNITY_UINT32 elements = num_elements; - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; - - RETURN_IF_FAIL_OR_IGNORE; - - if (elements == 0) - { - UnityPrintPointlessAndBail(); - } - - if (expected == actual) return; /* Both are NULL or same pointer */ - if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) - UNITY_FAIL_AND_BAIL; - - while (elements--) - { - if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual)) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrElement); - UnityPrintNumberUnsigned(num_elements - elements - 1); - UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } - if (flags == UNITY_ARRAY_TO_ARRAY) - { - ptr_expected++; - } - ptr_actual++; - } -} - -/*-----------------------------------------------*/ -void UnityAssertFloatsWithin(const UNITY_FLOAT delta, - const UNITY_FLOAT expected, - const UNITY_FLOAT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - RETURN_IF_FAIL_OR_IGNORE; - - - if (!UnityFloatsWithin(delta, expected, actual)) - { - UnityTestResultsFailBegin(lineNumber); - UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertFloatSpecial(const UNITY_FLOAT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLOAT_TRAIT_T style) -{ - const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; - UNITY_INT should_be_trait = ((UNITY_INT)style & 1); - UNITY_INT is_trait = !should_be_trait; - UNITY_INT trait_index = (UNITY_INT)(style >> 1); - - RETURN_IF_FAIL_OR_IGNORE; - - switch (style) - { - case UNITY_FLOAT_IS_INF: - case UNITY_FLOAT_IS_NOT_INF: - is_trait = isinf(actual) && (actual > 0); - break; - case UNITY_FLOAT_IS_NEG_INF: - case UNITY_FLOAT_IS_NOT_NEG_INF: - is_trait = isinf(actual) && (actual < 0); - break; - - case UNITY_FLOAT_IS_NAN: - case UNITY_FLOAT_IS_NOT_NAN: - is_trait = isnan(actual) ? 1 : 0; - break; - - case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ - case UNITY_FLOAT_IS_NOT_DET: - is_trait = !isinf(actual) && !isnan(actual); - break; - - default: - trait_index = 0; - trait_names[0] = UnityStrInvalidFloatTrait; - break; - } - - if (is_trait != should_be_trait) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - if (!should_be_trait) - UnityPrint(UnityStrNot); - UnityPrint(trait_names[trait_index]); - UnityPrint(UnityStrWas); -#ifndef UNITY_EXCLUDE_FLOAT_PRINT - UnityPrintFloat((UNITY_DOUBLE)actual); -#else - if (should_be_trait) - UnityPrint(UnityStrNot); - UnityPrint(trait_names[trait_index]); -#endif - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -#endif /* not UNITY_EXCLUDE_FLOAT */ - -/*-----------------------------------------------*/ -#ifndef UNITY_EXCLUDE_DOUBLE -static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) -{ - UNITY_DOUBLE diff; - UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); -} - -void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) -{ - UNITY_UINT32 elements = num_elements; - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; - - RETURN_IF_FAIL_OR_IGNORE; - - if (elements == 0) - { - UnityPrintPointlessAndBail(); - } - - if (expected == actual) return; /* Both are NULL or same pointer */ - if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) - UNITY_FAIL_AND_BAIL; - - while (elements--) - { - if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual)) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrElement); - UnityPrintNumberUnsigned(num_elements - elements - 1); - UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } - if (flags == UNITY_ARRAY_TO_ARRAY) - { - ptr_expected++; - } - ptr_actual++; - } -} - -/*-----------------------------------------------*/ -void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, - const UNITY_DOUBLE expected, - const UNITY_DOUBLE actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - RETURN_IF_FAIL_OR_IGNORE; - - if (!UnityDoublesWithin(delta, expected, actual)) - { - UnityTestResultsFailBegin(lineNumber); - UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ - -void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLOAT_TRAIT_T style) -{ - const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; - UNITY_INT should_be_trait = ((UNITY_INT)style & 1); - UNITY_INT is_trait = !should_be_trait; - UNITY_INT trait_index = (UNITY_INT)(style >> 1); - - RETURN_IF_FAIL_OR_IGNORE; - - switch (style) - { - case UNITY_FLOAT_IS_INF: - case UNITY_FLOAT_IS_NOT_INF: - is_trait = isinf(actual) && (actual > 0); - break; - case UNITY_FLOAT_IS_NEG_INF: - case UNITY_FLOAT_IS_NOT_NEG_INF: - is_trait = isinf(actual) && (actual < 0); - break; - - case UNITY_FLOAT_IS_NAN: - case UNITY_FLOAT_IS_NOT_NAN: - is_trait = isnan(actual) ? 1 : 0; - break; - - case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ - case UNITY_FLOAT_IS_NOT_DET: - is_trait = !isinf(actual) && !isnan(actual); - break; - - default: - trait_index = 0; - trait_names[0] = UnityStrInvalidFloatTrait; - break; - } - - if (is_trait != should_be_trait) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrExpected); - if (!should_be_trait) - UnityPrint(UnityStrNot); - UnityPrint(trait_names[trait_index]); - UnityPrint(UnityStrWas); -#ifndef UNITY_EXCLUDE_FLOAT_PRINT - UnityPrintFloat(actual); -#else - if (should_be_trait) - UnityPrint(UnityStrNot); - UnityPrint(trait_names[trait_index]); -#endif - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -#endif /* not UNITY_EXCLUDE_DOUBLE */ - -/*-----------------------------------------------*/ -void UnityAssertNumbersWithin(const UNITY_UINT delta, - const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style) -{ - RETURN_IF_FAIL_OR_IGNORE; - - if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) - { - if (actual > expected) - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); - else - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); - } - else - { - if ((UNITY_UINT)actual > (UNITY_UINT)expected) - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); - else - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); - } - - if (Unity.CurrentTestFailed) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrDelta); - UnityPrintNumberByStyle((UNITY_INT)delta, style); - UnityPrint(UnityStrExpected); - UnityPrintNumberByStyle(expected, style); - UnityPrint(UnityStrWas); - UnityPrintNumberByStyle(actual, style); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertEqualString(const char* expected, - const char* actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - UNITY_UINT32 i; - - RETURN_IF_FAIL_OR_IGNORE; - - /* if both pointers not null compare the strings */ - if (expected && actual) - { - for (i = 0; expected[i] || actual[i]; i++) - { - if (expected[i] != actual[i]) - { - Unity.CurrentTestFailed = 1; - break; - } - } - } - else - { /* handle case of one pointers being null (if both null, test should pass) */ - if (expected != actual) - { - Unity.CurrentTestFailed = 1; - } - } - - if (Unity.CurrentTestFailed) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrintExpectedAndActualStrings(expected, actual); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertEqualStringLen(const char* expected, - const char* actual, - const UNITY_UINT32 length, - const char* msg, - const UNITY_LINE_TYPE lineNumber) -{ - UNITY_UINT32 i; - - RETURN_IF_FAIL_OR_IGNORE; - - /* if both pointers not null compare the strings */ - if (expected && actual) - { - for (i = 0; (i < length) && (expected[i] || actual[i]); i++) - { - if (expected[i] != actual[i]) - { - Unity.CurrentTestFailed = 1; - break; - } - } - } - else - { /* handle case of one pointers being null (if both null, test should pass) */ - if (expected != actual) - { - Unity.CurrentTestFailed = 1; - } - } - - if (Unity.CurrentTestFailed) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrintExpectedAndActualStringsLen(expected, actual, length); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } -} - -/*-----------------------------------------------*/ -void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, - const char** actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) -{ - UNITY_UINT32 i = 0; - UNITY_UINT32 j = 0; - const char* expd = NULL; - const char* act = NULL; - - RETURN_IF_FAIL_OR_IGNORE; - - /* if no elements, it's an error */ - if (num_elements == 0) - { - UnityPrintPointlessAndBail(); - } - - if ((const void*)expected == (const void*)actual) - { - return; /* Both are NULL or same pointer */ - } - - if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) - { - UNITY_FAIL_AND_BAIL; - } - - if (flags != UNITY_ARRAY_TO_ARRAY) - { - expd = (const char*)expected; - } - - do - { - act = actual[j]; - if (flags == UNITY_ARRAY_TO_ARRAY) - { - expd = ((const char* const*)expected)[j]; - } - - /* if both pointers not null compare the strings */ - if (expd && act) - { - for (i = 0; expd[i] || act[i]; i++) - { - if (expd[i] != act[i]) - { - Unity.CurrentTestFailed = 1; - break; - } - } - } - else - { /* handle case of one pointers being null (if both null, test should pass) */ - if (expd != act) - { - Unity.CurrentTestFailed = 1; - } - } - - if (Unity.CurrentTestFailed) - { - UnityTestResultsFailBegin(lineNumber); - if (num_elements > 1) - { - UnityPrint(UnityStrElement); - UnityPrintNumberUnsigned(j); - } - UnityPrintExpectedAndActualStrings(expd, act); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } - } while (++j < num_elements); -} - -/*-----------------------------------------------*/ -void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, - UNITY_INTERNAL_PTR actual, - const UNITY_UINT32 length, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags) -{ - UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; - UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; - UNITY_UINT32 elements = num_elements; - UNITY_UINT32 bytes; - - RETURN_IF_FAIL_OR_IGNORE; - - if ((elements == 0) || (length == 0)) - { - UnityPrintPointlessAndBail(); - } - - if (expected == actual) return; /* Both are NULL or same pointer */ - if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) - UNITY_FAIL_AND_BAIL; - - while (elements--) - { - bytes = length; - while (bytes--) - { - if (*ptr_exp != *ptr_act) - { - UnityTestResultsFailBegin(lineNumber); - UnityPrint(UnityStrMemory); - if (num_elements > 1) - { - UnityPrint(UnityStrElement); - UnityPrintNumberUnsigned(num_elements - elements - 1); - } - UnityPrint(UnityStrByte); - UnityPrintNumberUnsigned(length - bytes - 1); - UnityPrint(UnityStrExpected); - UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); - UnityPrint(UnityStrWas); - UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); - UnityAddMsgIfSpecified(msg); - UNITY_FAIL_AND_BAIL; - } - ptr_exp++; - ptr_act++; - } - if (flags == UNITY_ARRAY_TO_VAL) - { - ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; - } - } -} - -/*-----------------------------------------------*/ - -static union -{ - UNITY_INT8 i8; - UNITY_INT16 i16; - UNITY_INT32 i32; -#ifdef UNITY_SUPPORT_64 - UNITY_INT64 i64; -#endif -#ifndef UNITY_EXCLUDE_FLOAT - float f; -#endif -#ifndef UNITY_EXCLUDE_DOUBLE - double d; -#endif -} UnityQuickCompare; - -UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) -{ - switch(size) - { - case 1: - UnityQuickCompare.i8 = (UNITY_INT8)num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); - - case 2: - UnityQuickCompare.i16 = (UNITY_INT16)num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); - -#ifdef UNITY_SUPPORT_64 - case 8: - UnityQuickCompare.i64 = (UNITY_INT64)num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); -#endif - default: /* 4 bytes */ - UnityQuickCompare.i32 = (UNITY_INT32)num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); - } -} - -#ifndef UNITY_EXCLUDE_FLOAT -UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) -{ - UnityQuickCompare.f = num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); -} -#endif - -#ifndef UNITY_EXCLUDE_DOUBLE -UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) -{ - UnityQuickCompare.d = num; - return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); -} -#endif - -/*----------------------------------------------- - * Control Functions - *-----------------------------------------------*/ - -void UnityFail(const char* msg, const UNITY_LINE_TYPE line) -{ - RETURN_IF_FAIL_OR_IGNORE; - - UnityTestResultsBegin(Unity.TestFile, line); - UnityPrint(UnityStrFail); - if (msg != NULL) - { - UNITY_OUTPUT_CHAR(':'); - -#ifndef UNITY_EXCLUDE_DETAILS - if (Unity.CurrentDetail1) - { - UnityPrint(UnityStrDetail1Name); - UnityPrint(Unity.CurrentDetail1); - if (Unity.CurrentDetail2) - { - UnityPrint(UnityStrDetail2Name); - UnityPrint(Unity.CurrentDetail2); - } - UnityPrint(UnityStrSpacer); - } -#endif - if (msg[0] != ' ') - { - UNITY_OUTPUT_CHAR(' '); - } - UnityPrint(msg); - } - - UNITY_FAIL_AND_BAIL; -} - -/*-----------------------------------------------*/ -void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) -{ - RETURN_IF_FAIL_OR_IGNORE; - - UnityTestResultsBegin(Unity.TestFile, line); - UnityPrint(UnityStrIgnore); - if (msg != NULL) - { - UNITY_OUTPUT_CHAR(':'); - UNITY_OUTPUT_CHAR(' '); - UnityPrint(msg); - } - UNITY_IGNORE_AND_BAIL; -} - -/*-----------------------------------------------*/ -void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) -{ - Unity.CurrentTestName = FuncName; - Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; - Unity.NumberOfTests++; - UNITY_CLR_DETAILS(); - if (TEST_PROTECT()) - { - setUp(); - Func(); - } - if (TEST_PROTECT()) - { - tearDown(); - } - UnityConcludeTest(); -} - -/*-----------------------------------------------*/ -void UnityBegin(const char* filename) -{ - Unity.TestFile = filename; - Unity.CurrentTestName = NULL; - Unity.CurrentTestLineNumber = 0; - Unity.NumberOfTests = 0; - Unity.TestFailures = 0; - Unity.TestIgnores = 0; - Unity.CurrentTestFailed = 0; - Unity.CurrentTestIgnored = 0; - - UNITY_CLR_DETAILS(); - UNITY_OUTPUT_START(); -} - -/*-----------------------------------------------*/ -int UnityEnd(void) -{ - UNITY_PRINT_EOL(); - UnityPrint(UnityStrBreaker); - UNITY_PRINT_EOL(); - UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); - UnityPrint(UnityStrResultsTests); - UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); - UnityPrint(UnityStrResultsFailures); - UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); - UnityPrint(UnityStrResultsIgnored); - UNITY_PRINT_EOL(); - if (Unity.TestFailures == 0U) - { - UnityPrint(UnityStrOk); - } - else - { - UnityPrint(UnityStrFail); -#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL - UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); -#endif - } - UNITY_PRINT_EOL(); - UNITY_FLUSH_CALL(); - UNITY_OUTPUT_COMPLETE(); - return (int)(Unity.TestFailures); -} - -/*----------------------------------------------- - * Command Line Argument Support - *-----------------------------------------------*/ -#ifdef UNITY_USE_COMMAND_LINE_ARGS - -char* UnityOptionIncludeNamed = NULL; -char* UnityOptionExcludeNamed = NULL; -int UnityVerbosity = 1; - -int UnityParseOptions(int argc, char** argv) -{ - UnityOptionIncludeNamed = NULL; - UnityOptionExcludeNamed = NULL; - - for (int i = 1; i < argc; i++) - { - if (argv[i][0] == '-') - { - switch (argv[i][1]) - { - case 'l': /* list tests */ - return -1; - case 'n': /* include tests with name including this string */ - case 'f': /* an alias for -n */ - if (argv[i][2] == '=') - UnityOptionIncludeNamed = &argv[i][3]; - else if (++i < argc) - UnityOptionIncludeNamed = argv[i]; - else - { - UnityPrint("ERROR: No Test String to Include Matches For"); - UNITY_PRINT_EOL(); - return 1; - } - break; - case 'q': /* quiet */ - UnityVerbosity = 0; - break; - case 'v': /* verbose */ - UnityVerbosity = 2; - break; - case 'x': /* exclude tests with name including this string */ - if (argv[i][2] == '=') - UnityOptionExcludeNamed = &argv[i][3]; - else if (++i < argc) - UnityOptionExcludeNamed = argv[i]; - else - { - UnityPrint("ERROR: No Test String to Exclude Matches For"); - UNITY_PRINT_EOL(); - return 1; - } - break; - default: - UnityPrint("ERROR: Unknown Option "); - UNITY_OUTPUT_CHAR(argv[i][1]); - UNITY_PRINT_EOL(); - return 1; - } - } - } - - return 0; -} - -int IsStringInBiggerString(const char* longstring, const char* shortstring) -{ - const char* lptr = longstring; - const char* sptr = shortstring; - const char* lnext = lptr; - - if (*sptr == '*') - return 1; - - while (*lptr) - { - lnext = lptr + 1; - - /* If they current bytes match, go on to the next bytes */ - while (*lptr && *sptr && (*lptr == *sptr)) - { - lptr++; - sptr++; - - /* We're done if we match the entire string or up to a wildcard */ - if (*sptr == '*') - return 1; - if (*sptr == ',') - return 1; - if (*sptr == '"') - return 1; - if (*sptr == '\'') - return 1; - if (*sptr == ':') - return 2; - if (*sptr == 0) - return 1; - } - - /* Otherwise we start in the long pointer 1 character further and try again */ - lptr = lnext; - sptr = shortstring; - } - return 0; -} - -int UnityStringArgumentMatches(const char* str) -{ - int retval; - const char* ptr1; - const char* ptr2; - const char* ptrf; - - /* Go through the options and get the substrings for matching one at a time */ - ptr1 = str; - while (ptr1[0] != 0) - { - if ((ptr1[0] == '"') || (ptr1[0] == '\'')) - ptr1++; - - /* look for the start of the next partial */ - ptr2 = ptr1; - ptrf = 0; - do - { - ptr2++; - if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) - ptrf = &ptr2[1]; - } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); - while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) - ptr2++; - - /* done if complete filename match */ - retval = IsStringInBiggerString(Unity.TestFile, ptr1); - if (retval == 1) - return retval; - - /* done if testname match after filename partial match */ - if ((retval == 2) && (ptrf != 0)) - { - if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) - return 1; - } - - /* done if complete testname match */ - if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) - return 1; - - ptr1 = ptr2; - } - - /* we couldn't find a match for any substrings */ - return 0; -} - -int UnityTestMatches(void) -{ - /* Check if this test name matches the included test pattern */ - int retval; - if (UnityOptionIncludeNamed) - { - retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); - } - else - retval = 1; - - /* Check if this test name matches the excluded test pattern */ - if (UnityOptionExcludeNamed) - { - if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) - retval = 0; - } - return retval; -} - -#endif /* UNITY_USE_COMMAND_LINE_ARGS */ -/*-----------------------------------------------*/ diff --git a/components/cjson/cJSON/tests/unity/src/unity.h b/components/cjson/cJSON/tests/unity/src/unity.h deleted file mode 100644 index 32ff0e6df..000000000 --- a/components/cjson/cJSON/tests/unity/src/unity.h +++ /dev/null @@ -1,503 +0,0 @@ -/* ========================================== - Unity Project - A Test Framework for C - Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -========================================== */ - -#ifndef UNITY_FRAMEWORK_H -#define UNITY_FRAMEWORK_H -#define UNITY - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "unity_internals.h" - -/*------------------------------------------------------- - * Test Setup / Teardown - *-------------------------------------------------------*/ - -/* These functions are intended to be called before and after each test. */ -void setUp(void); -void tearDown(void); - -/* These functions are intended to be called at the beginning and end of an - * entire test suite. suiteTearDown() is passed the number of tests that - * failed, and its return value becomes the exit code of main(). */ -void suiteSetUp(void); -int suiteTearDown(int num_failures); - -/* If the compiler supports it, the following block provides stub - * implementations of the above functions as weak symbols. Note that on - * some platforms (MinGW for example), weak function implementations need - * to be in the same translation unit they are called from. This can be - * achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */ -#ifdef UNITY_INCLUDE_SETUP_STUBS - #ifdef UNITY_WEAK_ATTRIBUTE - UNITY_WEAK_ATTRIBUTE void setUp(void) { } - UNITY_WEAK_ATTRIBUTE void tearDown(void) { } - UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } - UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } - #elif defined(UNITY_WEAK_PRAGMA) - #pragma weak setUp - void setUp(void) { } - #pragma weak tearDown - void tearDown(void) { } - #pragma weak suiteSetUp - void suiteSetUp(void) { } - #pragma weak suiteTearDown - int suiteTearDown(int num_failures) { return num_failures; } - #endif -#endif - -/*------------------------------------------------------- - * Configuration Options - *------------------------------------------------------- - * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. - - * Integers/longs/pointers - * - Unity attempts to automatically discover your integer sizes - * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in - * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in - * - If you cannot use the automatic methods above, you can force Unity by using these options: - * - define UNITY_SUPPORT_64 - * - set UNITY_INT_WIDTH - * - set UNITY_LONG_WIDTH - * - set UNITY_POINTER_WIDTH - - * Floats - * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons - * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT - * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats - * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons - * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) - * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE - * - define UNITY_DOUBLE_TYPE to specify something other than double - * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors - - * Output - * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired - * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure - - * Optimization - * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge - * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. - - * Test Cases - * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script - - * Parameterized Tests - * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing - - * Tests with Arguments - * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity - - *------------------------------------------------------- - * Basic Fail and Ignore - *-------------------------------------------------------*/ - -#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) -#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) -#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) -#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) -#define TEST_ONLY() - -/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. - * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ -#define TEST_PASS() TEST_ABORT() - -/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out - * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ -#define TEST_FILE(a) - -/*------------------------------------------------------- - * Test Asserts (simple) - *-------------------------------------------------------*/ - -/* Boolean */ -#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") -#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") -#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") -#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") -#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") -#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") - -/* Integers (of all sizes) */ -#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") -#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) -#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL) -#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) -#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL) - -/* Integer Greater Than/ Less Than (of all sizes) */ -#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) - -#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) - -#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) - -#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) - -/* Integer Ranges (of all sizes) */ -#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) - -/* Structs and Strings */ -#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) - -/* Arrays */ -#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) - -/* Arrays Compared To Single Value */ -#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) - -/* Floating Point (If Enabled) */ -#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) -#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) - -/* Double (If Enabled) */ -#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) -#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) -#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) - -/*------------------------------------------------------- - * Test Asserts (with additional messages) - *-------------------------------------------------------*/ - -/* Boolean */ -#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) -#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) -#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) -#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) -#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) -#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) - -/* Integers (of all sizes) */ -#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) -#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) -#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) -#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) - -/* Integer Greater Than/ Less Than (of all sizes) */ -#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) - -#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) - -#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) - -#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) -#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) - -/* Integer Ranges (of all sizes) */ -#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) - -/* Structs and Strings */ -#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) - -/* Arrays */ -#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) - -/* Arrays Compared To Single Value*/ -#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) - -/* Floating Point (If Enabled) */ -#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) -#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) - -/* Double (If Enabled) */ -#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) -#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) -#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) - -/* end of UNITY_FRAMEWORK_H */ -#ifdef __cplusplus -} -#endif -#endif diff --git a/components/cjson/cJSON/tests/unity/src/unity_internals.h b/components/cjson/cJSON/tests/unity/src/unity_internals.h deleted file mode 100644 index f78cebace..000000000 --- a/components/cjson/cJSON/tests/unity/src/unity_internals.h +++ /dev/null @@ -1,870 +0,0 @@ -/* ========================================== - Unity Project - A Test Framework for C - Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -========================================== */ - -#ifndef UNITY_INTERNALS_H -#define UNITY_INTERNALS_H - -#include "../examples/unity_config.h" - -#ifndef UNITY_EXCLUDE_SETJMP_H -#include -#endif - -#ifndef UNITY_EXCLUDE_MATH_H -#include -#endif - -/* Unity Attempts to Auto-Detect Integer Types - * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits - * Attempt 2: UINTPTR_MAX in , or default to same size as long - * The user may override any of these derived constants: - * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ -#ifndef UNITY_EXCLUDE_STDINT_H -#include -#endif - -#ifndef UNITY_EXCLUDE_LIMITS_H -#include -#endif - -/*------------------------------------------------------- - * Guess Widths If Not Specified - *-------------------------------------------------------*/ - -/* Determine the size of an int, if not already specified. - * We cannot use sizeof(int), because it is not yet defined - * at this stage in the translation of the C program. - * Therefore, infer it from UINT_MAX if possible. */ -#ifndef UNITY_INT_WIDTH - #ifdef UINT_MAX - #if (UINT_MAX == 0xFFFF) - #define UNITY_INT_WIDTH (16) - #elif (UINT_MAX == 0xFFFFFFFF) - #define UNITY_INT_WIDTH (32) - #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) - #define UNITY_INT_WIDTH (64) - #endif - #else /* Set to default */ - #define UNITY_INT_WIDTH (32) - #endif /* UINT_MAX */ -#endif - -/* Determine the size of a long, if not already specified. */ -#ifndef UNITY_LONG_WIDTH - #ifdef ULONG_MAX - #if (ULONG_MAX == 0xFFFF) - #define UNITY_LONG_WIDTH (16) - #elif (ULONG_MAX == 0xFFFFFFFF) - #define UNITY_LONG_WIDTH (32) - #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) - #define UNITY_LONG_WIDTH (64) - #endif - #else /* Set to default */ - #define UNITY_LONG_WIDTH (32) - #endif /* ULONG_MAX */ -#endif - -/* Determine the size of a pointer, if not already specified. */ -#ifndef UNITY_POINTER_WIDTH - #ifdef UINTPTR_MAX - #if (UINTPTR_MAX <= 0xFFFF) - #define UNITY_POINTER_WIDTH (16) - #elif (UINTPTR_MAX <= 0xFFFFFFFF) - #define UNITY_POINTER_WIDTH (32) - #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) - #define UNITY_POINTER_WIDTH (64) - #endif - #else /* Set to default */ - #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH - #endif /* UINTPTR_MAX */ -#endif - -/*------------------------------------------------------- - * Int Support (Define types based on detected sizes) - *-------------------------------------------------------*/ - -#if (UNITY_INT_WIDTH == 32) - typedef unsigned char UNITY_UINT8; - typedef unsigned short UNITY_UINT16; - typedef unsigned int UNITY_UINT32; - typedef signed char UNITY_INT8; - typedef signed short UNITY_INT16; - typedef signed int UNITY_INT32; -#elif (UNITY_INT_WIDTH == 16) - typedef unsigned char UNITY_UINT8; - typedef unsigned int UNITY_UINT16; - typedef unsigned long UNITY_UINT32; - typedef signed char UNITY_INT8; - typedef signed int UNITY_INT16; - typedef signed long UNITY_INT32; -#else - #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) -#endif - -/*------------------------------------------------------- - * 64-bit Support - *-------------------------------------------------------*/ - -#ifndef UNITY_SUPPORT_64 - #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 - #define UNITY_SUPPORT_64 - #endif -#endif - -#ifndef UNITY_SUPPORT_64 - /* No 64-bit Support */ - typedef UNITY_UINT32 UNITY_UINT; - typedef UNITY_INT32 UNITY_INT; -#else - - /* 64-bit Support */ - #if (UNITY_LONG_WIDTH == 32) - typedef unsigned long long UNITY_UINT64; - typedef signed long long UNITY_INT64; - #elif (UNITY_LONG_WIDTH == 64) - typedef unsigned long UNITY_UINT64; - typedef signed long UNITY_INT64; - #else - #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) - #endif - typedef UNITY_UINT64 UNITY_UINT; - typedef UNITY_INT64 UNITY_INT; - -#endif - -/*------------------------------------------------------- - * Pointer Support - *-------------------------------------------------------*/ - -#if (UNITY_POINTER_WIDTH == 32) -#define UNITY_PTR_TO_INT UNITY_INT32 -#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 -#elif (UNITY_POINTER_WIDTH == 64) -#define UNITY_PTR_TO_INT UNITY_INT64 -#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 -#elif (UNITY_POINTER_WIDTH == 16) -#define UNITY_PTR_TO_INT UNITY_INT16 -#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 -#else - #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) -#endif - -#ifndef UNITY_PTR_ATTRIBUTE -#define UNITY_PTR_ATTRIBUTE -#endif - -#ifndef UNITY_INTERNAL_PTR -#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* -#endif - -/*------------------------------------------------------- - * Float Support - *-------------------------------------------------------*/ - -#ifdef UNITY_EXCLUDE_FLOAT - -/* No Floating Point Support */ -#ifndef UNITY_EXCLUDE_DOUBLE -#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ -#endif -#ifndef UNITY_EXCLUDE_FLOAT_PRINT -#define UNITY_EXCLUDE_FLOAT_PRINT -#endif - -#else - -/* Floating Point Support */ -#ifndef UNITY_FLOAT_PRECISION -#define UNITY_FLOAT_PRECISION (0.00001f) -#endif -#ifndef UNITY_FLOAT_TYPE -#define UNITY_FLOAT_TYPE float -#endif -typedef UNITY_FLOAT_TYPE UNITY_FLOAT; - -/* isinf & isnan macros should be provided by math.h */ -#ifndef isinf -/* The value of Inf - Inf is NaN */ -#define isinf(n) (isnan((n) - (n)) && !isnan(n)) -#endif - -#ifndef isnan -/* NaN is the only floating point value that does NOT equal itself. - * Therefore if n != n, then it is NaN. */ -#define isnan(n) ((n != n) ? 1 : 0) -#endif - -#endif - -/*------------------------------------------------------- - * Double Float Support - *-------------------------------------------------------*/ - -/* unlike float, we DON'T include by default */ -#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) - - /* No Floating Point Support */ - #ifndef UNITY_EXCLUDE_DOUBLE - #define UNITY_EXCLUDE_DOUBLE - #else - #undef UNITY_INCLUDE_DOUBLE - #endif - - #ifndef UNITY_EXCLUDE_FLOAT - #ifndef UNITY_DOUBLE_TYPE - #define UNITY_DOUBLE_TYPE double - #endif - typedef UNITY_FLOAT UNITY_DOUBLE; - /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ - #endif - -#else - - /* Double Floating Point Support */ - #ifndef UNITY_DOUBLE_PRECISION - #define UNITY_DOUBLE_PRECISION (1e-12) - #endif - - #ifndef UNITY_DOUBLE_TYPE - #define UNITY_DOUBLE_TYPE double - #endif - typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; - -#endif - -/*------------------------------------------------------- - * Output Method: stdout (DEFAULT) - *-------------------------------------------------------*/ -#ifndef UNITY_OUTPUT_CHAR -/* Default to using putchar, which is defined in stdio.h */ -#include -#define UNITY_OUTPUT_CHAR(a) (void)putchar(a) -#else - /* If defined as something else, make sure we declare it here so it's ready for use */ - #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION -extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; - #endif -#endif - -#ifndef UNITY_OUTPUT_FLUSH -#ifdef UNITY_USE_FLUSH_STDOUT -/* We want to use the stdout flush utility */ -#include -#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) -#else -/* We've specified nothing, therefore flush should just be ignored */ -#define UNITY_OUTPUT_FLUSH() -#endif -#else -/* We've defined flush as something else, so make sure we declare it here so it's ready for use */ -#ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION -extern void UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION; -#endif -#endif - -#ifndef UNITY_OUTPUT_FLUSH -#define UNITY_FLUSH_CALL() -#else -#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() -#endif - -#ifndef UNITY_PRINT_EOL -#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') -#endif - -#ifndef UNITY_OUTPUT_START -#define UNITY_OUTPUT_START() -#endif - -#ifndef UNITY_OUTPUT_COMPLETE -#define UNITY_OUTPUT_COMPLETE() -#endif - -/*------------------------------------------------------- - * Footprint - *-------------------------------------------------------*/ - -#ifndef UNITY_LINE_TYPE -#define UNITY_LINE_TYPE UNITY_UINT -#endif - -#ifndef UNITY_COUNTER_TYPE -#define UNITY_COUNTER_TYPE UNITY_UINT -#endif - -/*------------------------------------------------------- - * Language Features Available - *-------------------------------------------------------*/ -#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) -# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */ -# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__) -# define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) -# endif -# endif -#endif - -#ifdef UNITY_NO_WEAK -# undef UNITY_WEAK_ATTRIBUTE -# undef UNITY_WEAK_PRAGMA -#endif - - -/*------------------------------------------------------- - * Internal Structs Needed - *-------------------------------------------------------*/ - -typedef void (*UnityTestFunction)(void); - -#define UNITY_DISPLAY_RANGE_INT (0x10) -#define UNITY_DISPLAY_RANGE_UINT (0x20) -#define UNITY_DISPLAY_RANGE_HEX (0x40) - -typedef enum -{ -UNITY_DISPLAY_STYLE_INT = sizeof(int)+ UNITY_DISPLAY_RANGE_INT, - UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, - UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, - UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, -#ifdef UNITY_SUPPORT_64 - UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, -#endif - -UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT, - UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, - UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, - UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, -#ifdef UNITY_SUPPORT_64 - UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, -#endif - - UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, - UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, - UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, -#ifdef UNITY_SUPPORT_64 - UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, -#endif - - UNITY_DISPLAY_STYLE_UNKNOWN -} UNITY_DISPLAY_STYLE_T; - -typedef enum -{ - UNITY_EQUAL_TO = 1, - UNITY_GREATER_THAN = 2, - UNITY_GREATER_OR_EQUAL = 2 + UNITY_EQUAL_TO, - UNITY_SMALLER_THAN = 4, - UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO -} UNITY_COMPARISON_T; - -#ifndef UNITY_EXCLUDE_FLOAT -typedef enum UNITY_FLOAT_TRAIT -{ - UNITY_FLOAT_IS_NOT_INF = 0, - UNITY_FLOAT_IS_INF, - UNITY_FLOAT_IS_NOT_NEG_INF, - UNITY_FLOAT_IS_NEG_INF, - UNITY_FLOAT_IS_NOT_NAN, - UNITY_FLOAT_IS_NAN, - UNITY_FLOAT_IS_NOT_DET, - UNITY_FLOAT_IS_DET, - UNITY_FLOAT_INVALID_TRAIT -} UNITY_FLOAT_TRAIT_T; -#endif - -typedef enum -{ - UNITY_ARRAY_TO_VAL = 0, - UNITY_ARRAY_TO_ARRAY -} UNITY_FLAGS_T; - -struct UNITY_STORAGE_T -{ - const char* TestFile; - const char* CurrentTestName; -#ifndef UNITY_EXCLUDE_DETAILS - const char* CurrentDetail1; - const char* CurrentDetail2; -#endif - UNITY_LINE_TYPE CurrentTestLineNumber; - UNITY_COUNTER_TYPE NumberOfTests; - UNITY_COUNTER_TYPE TestFailures; - UNITY_COUNTER_TYPE TestIgnores; - UNITY_COUNTER_TYPE CurrentTestFailed; - UNITY_COUNTER_TYPE CurrentTestIgnored; -#ifndef UNITY_EXCLUDE_SETJMP_H - jmp_buf AbortFrame; -#endif -}; - -extern struct UNITY_STORAGE_T Unity; - -/*------------------------------------------------------- - * Test Suite Management - *-------------------------------------------------------*/ - -void UnityBegin(const char* filename); -int UnityEnd(void); -void UnityConcludeTest(void); -void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); - -/*------------------------------------------------------- - * Details Support - *-------------------------------------------------------*/ - -#ifdef UNITY_EXCLUDE_DETAILS -#define UNITY_CLR_DETAILS() -#define UNITY_SET_DETAIL(d1) -#define UNITY_SET_DETAILS(d1,d2) -#else -#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } -#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; } -#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; } - -#ifndef UNITY_DETAIL1_NAME -#define UNITY_DETAIL1_NAME "Function" -#endif - -#ifndef UNITY_DETAIL2_NAME -#define UNITY_DETAIL2_NAME "Argument" -#endif -#endif - -/*------------------------------------------------------- - * Test Output - *-------------------------------------------------------*/ - -void UnityPrint(const char* string); -void UnityPrintLen(const char* string, const UNITY_UINT32 length); -void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); -void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); -void UnityPrintNumber(const UNITY_INT number); -void UnityPrintNumberUnsigned(const UNITY_UINT number); -void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles); - -#ifndef UNITY_EXCLUDE_FLOAT_PRINT -void UnityPrintFloat(const UNITY_DOUBLE input_number); -#endif - -/*------------------------------------------------------- - * Test Assertion Functions - *------------------------------------------------------- - * Use the macros below this section instead of calling - * these directly. The macros have a consistent naming - * convention and will pull in file and line information - * for you. */ - -void UnityAssertEqualNumber(const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style); - -void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, - const UNITY_INT actual, - const UNITY_COMPARISON_T compare, - const char *msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style); - -void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, - UNITY_INTERNAL_PTR actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style, - const UNITY_FLAGS_T flags); - -void UnityAssertBits(const UNITY_INT mask, - const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber); - -void UnityAssertEqualString(const char* expected, - const char* actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber); - -void UnityAssertEqualStringLen(const char* expected, - const char* actual, - const UNITY_UINT32 length, - const char* msg, - const UNITY_LINE_TYPE lineNumber); - -void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, - const char** actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); - -void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, - UNITY_INTERNAL_PTR actual, - const UNITY_UINT32 length, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); - -void UnityAssertNumbersWithin(const UNITY_UINT delta, - const UNITY_INT expected, - const UNITY_INT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style); - -void UnityFail(const char* message, const UNITY_LINE_TYPE line); - -void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); - -#ifndef UNITY_EXCLUDE_FLOAT -void UnityAssertFloatsWithin(const UNITY_FLOAT delta, - const UNITY_FLOAT expected, - const UNITY_FLOAT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber); - -void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, - UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); - -void UnityAssertFloatSpecial(const UNITY_FLOAT actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLOAT_TRAIT_T style); -#endif - -#ifndef UNITY_EXCLUDE_DOUBLE -void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, - const UNITY_DOUBLE expected, - const UNITY_DOUBLE actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber); - -void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, - UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, - const UNITY_UINT32 num_elements, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLAGS_T flags); - -void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, - const char* msg, - const UNITY_LINE_TYPE lineNumber, - const UNITY_FLOAT_TRAIT_T style); -#endif - -/*------------------------------------------------------- - * Helpers - *-------------------------------------------------------*/ - -UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); -#ifndef UNITY_EXCLUDE_FLOAT -UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); -#endif -#ifndef UNITY_EXCLUDE_DOUBLE -UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); -#endif - -/*------------------------------------------------------- - * Error Strings We Might Need - *-------------------------------------------------------*/ - -extern const char UnityStrErrFloat[]; -extern const char UnityStrErrDouble[]; -extern const char UnityStrErr64[]; - -/*------------------------------------------------------- - * Test Running Macros - *-------------------------------------------------------*/ - -#ifndef UNITY_EXCLUDE_SETJMP_H -#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) -#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) -#else -#define TEST_PROTECT() 1 -#define TEST_ABORT() return -#endif - -/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ -#ifndef RUN_TEST -#ifdef __STDC_VERSION__ -#if __STDC_VERSION__ >= 199901L -#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__)) -#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway) -#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first -#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway) -#define RUN_TEST_SECOND_HELPER(first, second, ...) (second) -#endif -#endif -#endif - -/* If we can't do the tricky version, we'll just have to require them to always include the line number */ -#ifndef RUN_TEST -#ifdef CMOCK -#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) -#else -#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) -#endif -#endif - -#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) -#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) -#define UNITY_NEW_TEST(a) \ - Unity.CurrentTestName = (a); \ - Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ - Unity.NumberOfTests++; - -#ifndef UNITY_BEGIN -#define UNITY_BEGIN() UnityBegin(__FILE__) -#endif - -#ifndef UNITY_END -#define UNITY_END() UnityEnd() -#endif - -/*----------------------------------------------- - * Command Line Argument Support - *-----------------------------------------------*/ - -#ifdef UNITY_USE_COMMAND_LINE_ARGS -int UnityParseOptions(int argc, char** argv); -int UnityTestMatches(void); -#endif - -/*------------------------------------------------------- - * Basic Fail and Ignore - *-------------------------------------------------------*/ - -#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) - -/*------------------------------------------------------- - * Test Asserts - *-------------------------------------------------------*/ - -#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));} -#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) -#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) - -#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) -#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) - -#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) - -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) - -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) - -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) - -#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) - -#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) -#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) - -#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) - -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(unsigned int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) expected, sizeof(int*)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) - -#ifdef UNITY_SUPPORT_64 -#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#else -#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) -#endif - -#ifdef UNITY_EXCLUDE_FLOAT -#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) -#else -#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) -#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) -#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) -#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) -#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) -#endif - -#ifdef UNITY_EXCLUDE_DOUBLE -#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) -#else -#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual, (UNITY_LINE_TYPE)(line), message) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) -#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) -#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) -#endif - -/* End of UNITY_INTERNALS_H */ -#endif diff --git a/components/cjson/cJSON/tests/unity/test/.rubocop.yml b/components/cjson/cJSON/tests/unity/test/.rubocop.yml deleted file mode 100644 index c074ca9ac..000000000 --- a/components/cjson/cJSON/tests/unity/test/.rubocop.yml +++ /dev/null @@ -1,58 +0,0 @@ -# This is the configuration used to check the rubocop source code. - -#inherit_from: .rubocop_todo.yml - -AllCops: - TargetRubyVersion: 2.1 - -# These are areas where ThrowTheSwitch's coding style diverges from the Ruby standard -Style/SpecialGlobalVars: - EnforcedStyle: use_perl_names -Style/FormatString: - Enabled: false -Style/GlobalVars: - Enabled: false -Style/RegexpLiteral: - AllowInnerSlashes: true -Style/HashSyntax: - EnforcedStyle: no_mixed_keys - -# This is disabled because it seems to get confused over nested hashes -Style/AlignHash: - Enabled: false - EnforcedHashRocketStyle: table - EnforcedColonStyle: table - -# We purposefully use these insecure features because they're what makes Ruby awesome -Security/Eval: - Enabled: false -Security/YAMLLoad: - Enabled: false - -# At this point, we're not ready to enforce inline documentation requirements -Style/Documentation: - Enabled: false -Style/DocumentationMethod: - Enabled: false - -# At this point, we're not ready to enforce any metrics -Metrics/AbcSize: - Enabled: false -Metrics/BlockLength: - Enabled: false -Metrics/BlockNesting: - Enabled: false -Metrics/ClassLength: - Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false -Metrics/LineLength: - Enabled: false -Metrics/MethodLength: - Enabled: false -Metrics/ModuleLength: - Enabled: false -Metrics/ParameterLists: - Enabled: false -Metrics/PerceivedComplexity: - Enabled: false diff --git a/components/cjson/cJSON/tests/unity/test/Makefile b/components/cjson/cJSON/tests/unity/test/Makefile deleted file mode 100644 index c2710f1f1..000000000 --- a/components/cjson/cJSON/tests/unity/test/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -CC = gcc -ifeq ($(shell uname -s), Darwin) -CC = clang -endif -ifeq ($(findstring clang, $(CC)), clang) -E = -Weverything -CFLAGS += $E -Wno-unknown-warning-option -Wno-missing-prototypes -CFLAGS += -Wno-unused-macros -Wno-padded -Wno-missing-noreturn -endif -CFLAGS += -std=c99 -pedantic -Wall -Wextra -Wconversion -Werror -CFLAGS += -Wno-switch-enum -Wno-double-promotion -CFLAGS += -Wbad-function-cast -Wcast-qual -Wold-style-definition -Wshadow -Wstrict-overflow \ - -Wstrict-prototypes -Wswitch-default -Wundef -#DEBUG = -O0 -g -CFLAGS += $(DEBUG) -DEFINES = -D UNITY_OUTPUT_CHAR=putcharSpy -DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\) -DEFINES += $(UNITY_SUPPORT_64) $(UNITY_INCLUDE_DOUBLE) -UNITY_SUPPORT_64 = -D UNITY_SUPPORT_64 -UNITY_INCLUDE_DOUBLE = -D UNITY_INCLUDE_DOUBLE -SRC = ../src/unity.c tests/testunity.c build/testunityRunner.c -INC_DIR = -I ../src -COV_FLAGS = -fprofile-arcs -ftest-coverage -I ../../src -BUILD_DIR = build -TARGET = build/testunity-cov.exe - -# To generate coverage, call 'make -s', the default target runs. -# For verbose output of all the tests, run 'make test'. -default: coverage -.PHONY: default coverage test clean -coverage: DEFINES += -D UNITY_NO_WEAK -coverage: $(BUILD_DIR)/testunityRunner.c - cd $(BUILD_DIR) && \ - $(CC) $(CFLAGS) $(DEFINES) $(foreach i,$(SRC), ../$i) $(COV_FLAGS) -o ../$(TARGET) - rm -f $(BUILD_DIR)/*.gcda - ./$(TARGET) | grep 'Tests\|]]]' -A1 - cd $(BUILD_DIR) && \ - gcov unity.c | head -3 - grep '###' $(BUILD_DIR)/unity.c.gcov -C2 || true - -test: $(BUILD_DIR)/testunityRunner.c - $(CC) $(CFLAGS) $(DEFINES) $(INC_DIR) $(SRC) -o $(TARGET) - ./$(TARGET) - -# Compile only, for testing that preprocessor detection works -UNITY_C_ONLY =-c ../src/unity.c -o $(BUILD_DIR)/unity.o -intDetection: - $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_STDINT_H - $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_LIMITS_H - -$(BUILD_DIR)/testunityRunner.c: tests/testunity.c | $(BUILD_DIR) - awk $(AWK_SCRIPT) tests/testunity.c > $@ - -AWK_SCRIPT=\ - '/^void test/{ declarations[d++]=$$0; gsub(/\(?void\)? ?/,""); tests[t++]=$$0; line[u++]=NR } \ - END{ print "\#include \"unity.h\" /* Autogenerated by awk in Makefile */" ; \ - for (i=0; i -#include -#include "CException.h" -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_def.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_def.c deleted file mode 100644 index b8ad559f6..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_def.c +++ /dev/null @@ -1,57 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.c deleted file mode 100644 index 1d01551e8..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.c +++ /dev/null @@ -1,55 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "testsample_head1.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.h b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.h deleted file mode 100644 index da6b7ab26..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_head1.h +++ /dev/null @@ -1,15 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ -#ifndef _TESTSAMPLE_HEAD1_H -#define _TESTSAMPLE_HEAD1_H - -#include "unity.h" -#include "funky.h" -#include "stanky.h" -#include - -void test_TheFirstThingToTest(void); -void test_TheSecondThingToTest(void); -void test_TheThirdThingToTest(void); -void test_TheFourthThingToTest(void); -#endif - diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_cmd.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_cmd.c deleted file mode 100644 index 45a09af22..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_cmd.c +++ /dev/null @@ -1,80 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "CException.h" -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_def.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_def.c deleted file mode 100644 index a7a26078b..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_def.c +++ /dev/null @@ -1,76 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.c deleted file mode 100644 index 45829fe7e..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.c +++ /dev/null @@ -1,75 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "testsample_mock_head1.h" -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.h b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.h deleted file mode 100644 index 30c509ad0..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_head1.h +++ /dev/null @@ -1,13 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ -#ifndef _TESTSAMPLE_MOCK_HEAD1_H -#define _TESTSAMPLE_MOCK_HEAD1_H - -#include "unity.h" -#include "cmock.h" -#include "funky.h" -#include - -void test_TheFirstThingToTest(void); -void test_TheSecondThingToTest(void); -#endif - diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new1.c deleted file mode 100644 index 0061822e5..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new1.c +++ /dev/null @@ -1,89 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "CException.h" -#include "one.h" -#include "two.h" -#include "funky.h" -#include -#include "Mockstanky.h" - -int GlobalExpectCount; -int GlobalVerifyOrder; -char* GlobalOrderError; - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - GlobalExpectCount = 0; - GlobalVerifyOrder = 0; - GlobalOrderError = NULL; - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new2.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new2.c deleted file mode 100644 index ee63cdc0b..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_new2.c +++ /dev/null @@ -1,89 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_custom_setup(); -} - -/*=======Suite Teardown=====*/ -static int suite_teardown(int num_failures) -{ -a_custom_teardown(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return suite_teardown(UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_param.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_param.c deleted file mode 100644 index a42b7deae..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_param.c +++ /dev/null @@ -1,77 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST_NO_ARGS -#define RUN_TEST(TestFunc, TestLineNum, ...) \ -{ \ - Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(__VA_ARGS__); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); - RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run1.c deleted file mode 100644 index 0061822e5..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run1.c +++ /dev/null @@ -1,89 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "CException.h" -#include "one.h" -#include "two.h" -#include "funky.h" -#include -#include "Mockstanky.h" - -int GlobalExpectCount; -int GlobalVerifyOrder; -char* GlobalOrderError; - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - GlobalExpectCount = 0; - GlobalVerifyOrder = 0; - GlobalOrderError = NULL; - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run2.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run2.c deleted file mode 100644 index ee63cdc0b..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_run2.c +++ /dev/null @@ -1,89 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_custom_setup(); -} - -/*=======Suite Teardown=====*/ -static int suite_teardown(int num_failures) -{ -a_custom_teardown(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return suite_teardown(UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_yaml.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_yaml.c deleted file mode 100644 index a24bb5a57..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_mock_yaml.c +++ /dev/null @@ -1,90 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - CMock_Init(); \ - UNITY_CLR_DETAILS(); \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - CMock_Verify(); \ - } \ - CMock_Destroy(); \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include "cmock.h" -#include -#include -#include "CException.h" -#include "two.h" -#include "three.h" -#include -#include "funky.h" -#include -#include "Mockstanky.h" - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); - - -/*=======Mock Management=====*/ -static void CMock_Init(void) -{ - Mockstanky_Init(); -} -static void CMock_Verify(void) -{ - Mockstanky_Verify(); -} -static void CMock_Destroy(void) -{ - Mockstanky_Destroy(); -} - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_yaml_setup(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - CMock_Verify(); - CMock_Destroy(); - tearDown(); - CMock_Init(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/mocksample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - - CMock_Guts_MemFreeFinal(); - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new1.c deleted file mode 100644 index 7dcd3fdfe..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new1.c +++ /dev/null @@ -1,67 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "CException.h" -#include "one.h" -#include "two.h" -#include "funky.h" -#include "stanky.h" -#include - -int GlobalExpectCount; -int GlobalVerifyOrder; -char* GlobalOrderError; - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new2.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new2.c deleted file mode 100644 index c98c697f5..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_new2.c +++ /dev/null @@ -1,70 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_custom_setup(); -} - -/*=======Suite Teardown=====*/ -static int suite_teardown(int num_failures) -{ -a_custom_teardown(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return suite_teardown(UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_param.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_param.c deleted file mode 100644 index adf6c2626..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_param.c +++ /dev/null @@ -1,58 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST_NO_ARGS -#define RUN_TEST(TestFunc, TestLineNum, ...) \ -{ \ - Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(__VA_ARGS__); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); - RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); - RUN_TEST(test_TheThirdThingToTest, 53, RUN_TEST_NO_ARGS); - RUN_TEST(test_TheFourthThingToTest, 58, RUN_TEST_NO_ARGS); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run1.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run1.c deleted file mode 100644 index 7dcd3fdfe..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run1.c +++ /dev/null @@ -1,67 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "CException.h" -#include "one.h" -#include "two.h" -#include "funky.h" -#include "stanky.h" -#include - -int GlobalExpectCount; -int GlobalVerifyOrder; -char* GlobalOrderError; - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run2.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run2.c deleted file mode 100644 index c98c697f5..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_run2.c +++ /dev/null @@ -1,70 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - setUp(); \ - TestFunc(); \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_custom_setup(); -} - -/*=======Suite Teardown=====*/ -static int suite_teardown(int num_failures) -{ -a_custom_teardown(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return suite_teardown(UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_yaml.c b/components/cjson/cJSON/tests/unity/test/expectdata/testsample_yaml.c deleted file mode 100644 index 3316024df..000000000 --- a/components/cjson/cJSON/tests/unity/test/expectdata/testsample_yaml.c +++ /dev/null @@ -1,71 +0,0 @@ -/* AUTOGENERATED FILE. DO NOT EDIT. */ - -/*=======Test Runner Used To Run Each Test Below=====*/ -#define RUN_TEST(TestFunc, TestLineNum) \ -{ \ - Unity.CurrentTestName = #TestFunc; \ - Unity.CurrentTestLineNumber = TestLineNum; \ - Unity.NumberOfTests++; \ - if (TEST_PROTECT()) \ - { \ - CEXCEPTION_T e; \ - Try { \ - setUp(); \ - TestFunc(); \ - } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ - } \ - if (TEST_PROTECT() && !TEST_IS_IGNORED) \ - { \ - tearDown(); \ - } \ - UnityConcludeTest(); \ -} - -/*=======Automagically Detected Files To Include=====*/ -#include "unity.h" -#include -#include -#include "CException.h" -#include "two.h" -#include "three.h" -#include -#include "funky.h" -#include "stanky.h" -#include - -/*=======External Functions This Runner Calls=====*/ -extern void setUp(void); -extern void tearDown(void); -extern void test_TheFirstThingToTest(void); -extern void test_TheSecondThingToTest(void); -extern void test_TheThirdThingToTest(void); -extern void test_TheFourthThingToTest(void); - - -/*=======Suite Setup=====*/ -static int suite_setup(void) -{ -a_yaml_setup(); -} - -/*=======Test Reset Option=====*/ -void resetTest(void); -void resetTest(void) -{ - tearDown(); - setUp(); -} - - -/*=======MAIN=====*/ -int main(void) -{ - suite_setup(); - UnityBegin("testdata/testsample.c"); - RUN_TEST(test_TheFirstThingToTest, 21); - RUN_TEST(test_TheSecondThingToTest, 43); - RUN_TEST(test_TheThirdThingToTest, 53); - RUN_TEST(test_TheFourthThingToTest, 58); - - return (UnityEnd()); -} diff --git a/components/cjson/cJSON/tests/unity/test/rakefile b/components/cjson/cJSON/tests/unity/test/rakefile deleted file mode 100644 index 4a2f3d2c1..000000000 --- a/components/cjson/cJSON/tests/unity/test/rakefile +++ /dev/null @@ -1,125 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/' -$verbose = false - -require 'rake' -require 'rake/clean' -require UNITY_ROOT + 'rakefile_helper' -require 'rspec/core/rake_task' - -TEMP_DIRS = [ - File.join(UNITY_ROOT, 'build'), - File.join(UNITY_ROOT, 'sandbox') -] - -TEMP_DIRS.each do |dir| - directory(dir) - CLOBBER.include(dir) -end - -task :prepare_for_tests => TEMP_DIRS - -include RakefileHelpers - -# Load proper GCC as defult configuration -DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml' -configure_toolchain(DEFAULT_CONFIG_FILE) - -desc "Test unity with its own unit tests" -task :unit => [:prepare_for_tests] do - run_tests unit_test_files -end - -desc "Test unity's helper scripts" -task :scripts => [:prepare_for_tests] do - Dir['tests/test_*.rb'].each do |scriptfile| - require "./"+scriptfile - end -end - -desc "Run all rspecs" -RSpec::Core::RakeTask.new(:spec) do |t| - t.pattern = 'spec/**/*_spec.rb' -end - -desc "Generate test summary" -task :summary do - report_summary -end - -desc "Build and test Unity" -task :all => [:clean, :prepare_for_tests, :scripts, :unit, :style, :summary] -task :default => [:clobber, :all] -task :ci => [:no_color, :default] -task :cruise => [:no_color, :default] - -desc "Load configuration" -task :config, :config_file do |t, args| - configure_toolchain(args[:config_file]) -end - -task :no_color do - $colour_output = false -end - -task :verbose do - $verbose = true -end - -namespace :style do - desc "Check style" - task :check do - report "\nVERIFYING RUBY STYLE" - report execute("rubocop ../auto ../examples ../extras --config .rubocop.yml", true) - report "Styling Ruby:PASS" - end - - namespace :check do - Dir['../**/*.rb'].each do |f| - filename = File.basename(f, '.rb') - desc "Check Style of #{filename}" - task filename.to_sym => ['style:clean'] do - report execute("rubocop #{f} --color --config .rubocop.yml", true) - report "Style Checked for #{f}" - end - end - end - - desc "Fix Style of all C Code" - task :c do - run_astyle("../src/*.* ../extras/fixture/src/*.*") - end - - namespace :c do - Dir['../{src,extras/**}/*.{c,h}'].each do |f| - filename = File.basename(f)[0..-3] - desc "Check Style of #{filename}" - task filename.to_sym do - run_astyle f - end - end - end - - desc "Attempt to Autocorrect style" - task :auto => ['style:clean'] do - execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml") - report "Autocorrected What We Could." - end - - desc "Update style todo list" - task :todo => ['style:clean'] do - execute("rubocop ../auto ../examples ../extras --auto-gen-config --config .rubocop.yml") - report "Updated Style TODO List." - end - - task :clean do - File.delete(".rubocop_todo.yml") if File.exists?(".rubocop_todo.yml") - end -end - -task :style => ['style:check'] diff --git a/components/cjson/cJSON/tests/unity/test/rakefile_helper.rb b/components/cjson/cJSON/tests/unity/test/rakefile_helper.rb deleted file mode 100644 index 1fd60c5fd..000000000 --- a/components/cjson/cJSON/tests/unity/test/rakefile_helper.rb +++ /dev/null @@ -1,260 +0,0 @@ -# ========================================== -# Unity Project - A Test Framework for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -require 'yaml' -require 'fileutils' -require UNITY_ROOT + '../auto/unity_test_summary' -require UNITY_ROOT + '../auto/generate_test_runner' -require UNITY_ROOT + '../auto/colour_reporter' - -module RakefileHelpers - C_EXTENSION = '.c'.freeze - def load_configuration(config_file) - return if $configured - - $cfg_file = "targets/#{config_file}" unless config_file =~ /[\\|\/]/ - $cfg = YAML.load(File.read($cfg_file)) - $colour_output = false unless $cfg['colour'] - $configured = true if config_file != DEFAULT_CONFIG_FILE - end - - def configure_clean - CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? - end - - def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) - config_file += '.yml' unless config_file =~ /\.yml$/ - config_file = config_file unless config_file =~ /[\\|\/]/ - load_configuration(config_file) - configure_clean - end - - def unit_test_files - path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION - path.tr!('\\', '/') - FileList.new(path) - end - - def local_include_dirs - include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if { |dir| dir.is_a?(Array) } - include_dirs - end - - def extract_headers(filename) - includes = [] - lines = File.readlines(filename) - lines.each do |line| - m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) - includes << m[1] unless m.nil? - end - includes - end - - def find_source_file(header, paths) - paths.each do |dir| - src_file = dir + header.ext(C_EXTENSION) - return src_file if File.exist?(src_file) - end - nil - end - - def tackit(strings) - result = if strings.is_a?(Array) - "\"#{strings.join}\"" - else - strings - end - result - end - - def squash(prefix, items) - result = '' - items.each { |item| result += " #{prefix}#{tackit(item)}" } - result - end - - def should(behave, &block) - if block - puts 'Should ' + behave - yield block - else - puts "UNIMPLEMENTED CASE: Should #{behave}" - end - end - - def build_compiler_fields(inject_defines) - command = tackit($cfg['compiler']['path']) - defines = if $cfg['compiler']['defines']['items'].nil? - '' - else - squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)'] + inject_defines) - end - options = squash('', $cfg['compiler']['options']) - includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) - includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { :command => command, :defines => defines, :options => options, :includes => includes } - end - - def compile(file, defines = []) - compiler = build_compiler_fields(defines) - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \ - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" - obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" - execute(cmd_str + obj_file) - - obj_file - end - - def build_linker_fields - command = tackit($cfg['linker']['path']) - options = if $cfg['linker']['options'].nil? - '' - else - squash('', $cfg['linker']['options']) - end - includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? - '' - else - squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) - end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - - { :command => command, :options => options, :includes => includes } - end - - def link_it(exe_name, obj_list) - linker = build_linker_fields - cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + - (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] - execute(cmd_str) - end - - def build_simulator_fields - return nil if $cfg['simulator'].nil? - command = if $cfg['simulator']['path'].nil? - '' - else - (tackit($cfg['simulator']['path']) + ' ') - end - pre_support = if $cfg['simulator']['pre_support'].nil? - '' - else - squash('', $cfg['simulator']['pre_support']) - end - post_support = if $cfg['simulator']['post_support'].nil? - '' - else - squash('', $cfg['simulator']['post_support']) - end - - { :command => command, :pre_support => pre_support, :post_support => post_support } - end - - def run_astyle(style_what) - report "Styling C Code..." - command = "AStyle " \ - "--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \ - "--pad-oper --pad-comma --unpad-paren --pad-header " \ - "--align-pointer=type --align-reference=name " \ - "--add-brackets --mode=c --suffix=none " \ - "#{style_what}" - execute(command, false) - report "Styling C:PASS" - end - - def execute(command_string, ok_to_fail = false) - report command_string if $verbose - output = `#{command_string}`.chomp - report(output) if $verbose && !output.nil? && !output.empty? - raise "Command failed. (Returned #{$?.exitstatus})" if !$?.exitstatus.zero? && !ok_to_fail - output - end - - def report_summary - summary = UnityTestSummary.new - summary.root = UNITY_ROOT - results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.tr!('\\', '/') - results = Dir[results_glob] - summary.targets = results - report summary.run - end - - def run_tests(test_files) - report 'Running Unity system tests...' - - # Tack on TEST define for compiling unit tests - load_configuration($cfg_file) - test_defines = ['TEST'] - $cfg['compiler']['defines']['items'] ||= [] - $cfg['compiler']['defines']['items'] << 'TEST' - - include_dirs = local_include_dirs - - # Build and execute each unit test - test_files.each do |test| - obj_list = [] - - unless $cfg['compiler']['aux_sources'].nil? - $cfg['compiler']['aux_sources'].each do |aux| - obj_list << compile(aux, test_defines) - end - end - - # Detect dependencies and build required modules - extract_headers(test).each do |header| - # Compile corresponding source file if it exists - src_file = find_source_file(header, include_dirs) - - obj_list << compile(src_file, test_defines) unless src_file.nil? - end - - # Build the test runner (generate if configured to do so) - test_base = File.basename(test, C_EXTENSION) - - runner_name = test_base + '_Runner.c' - - runner_path = if $cfg['compiler']['runner_path'].nil? - $cfg['compiler']['build_path'] + runner_name - else - $cfg['compiler']['runner_path'] + runner_name - end - - options = $cfg[:unity] - options[:use_param_tests] = test =~ /parameterized/ ? true : false - UnityTestRunnerGenerator.new(options).run(test, runner_path) - obj_list << compile(runner_path, test_defines) - - # Build the test module - obj_list << compile(test, test_defines) - - # Link the test executable - link_it(test_base, obj_list) - - # Execute unit test and generate results file - simulator = build_simulator_fields - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] - cmd_str = if simulator.nil? - executable - else - "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end - output = execute(cmd_str) - test_results = $cfg['compiler']['build_path'] + test_base - if output.match(/OK$/m).nil? - test_results += '.testfail' - else - report output unless $verbose # Verbose already prints this line, as does a failure - test_results += '.testpass' - end - File.open(test_results, 'w') { |f| f.print output } - end - end -end diff --git a/components/cjson/cJSON/tests/unity/test/spec/generate_module_existing_file_spec.rb b/components/cjson/cJSON/tests/unity/test/spec/generate_module_existing_file_spec.rb deleted file mode 100644 index 74e7fc840..000000000 --- a/components/cjson/cJSON/tests/unity/test/spec/generate_module_existing_file_spec.rb +++ /dev/null @@ -1,158 +0,0 @@ - -require '../auto/generate_module.rb' -require 'fileutils' - -def touch_src(file) - FileUtils.touch "sandbox/src/#{file}" -end - -def touch_test(file) - FileUtils.touch "sandbox/test/#{file}" -end - -def create_src_with_known_content(file) - File.open("sandbox/src/#{file}", "w") {|f| f.write("the original #{file}")} -end - -def create_test_with_known_content(file) - File.open("sandbox/test/#{file}", "w") {|f| f.write("the original #{file}")} -end - -def expect_src_content_didnt_change(file) - expect(File.read("sandbox/src/#{file}")).to eq("the original #{file}") -end - -def expect_test_content_didnt_change(file) - expect(File.read("sandbox/test/#{file}")).to eq("the original #{file}") -end - -def expect_src_file_to_exist(file) - expect(File.exist?("sandbox/src/#{file}")).to be true -end - -def expect_test_file_to_exist(file) - expect(File.exist?("sandbox/test/#{file}")).to be true -end - -describe "UnityModuleGenerator" do - - before do - # clean sandbox and setup our "project" folders - FileUtils.rm_rf "sandbox" - FileUtils.mkdir_p "sandbox" - FileUtils.mkdir_p "sandbox/src" - FileUtils.mkdir_p "sandbox/test" - - @options = { - :path_src => "sandbox/src", - :path_tst => "sandbox/test", - } - end - - context "with src pattern" do - before do - @options[:pattern] = "src" - end - - it "fails when all files already exist" do - # create an existing triad of files - touch_src "meh.c" - touch_src "meh.h" - touch_test "Testmeh.c" - expect { - UnityModuleGenerator.new(@options).generate("meh") - }.to raise_error("ERROR: File meh already exists. Exiting.") - end - - it "creates the test file if the source and header files exist" do - # Create the existing files. - touch_src "meh.c" - touch_src "meh.h" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_test_file_to_exist "Testmeh.c" - end - - it "does not alter existing files" do - # Create some files with known content. - create_src_with_known_content "meh.c" - create_src_with_known_content "meh.h" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_src_content_didnt_change "meh.c" - expect_src_content_didnt_change "meh.c" - end - - it "does not alter existing test files" do - # Create some files with known content. - create_test_with_known_content "Testmeh.c" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_test_content_didnt_change "Testmeh.c" - end - - end - - context "with mch pattern" do - before do - @options[:pattern] = "mch" - end - - it "fails when all files exist" do - touch_src "meh_model.c" - touch_src "meh_conductor.c" - touch_src "meh_hardware.c" - touch_src "meh_model.h" - touch_src "meh_conductor.h" - touch_src "meh_hardware.h" - touch_test "Testmeh_model.c" - touch_test "Testmeh_conductor.c" - touch_test "Testmeh_hardware.c" - expect { - UnityModuleGenerator.new(@options).generate("meh") - }.to raise_error("ERROR: File meh_model already exists. Exiting.") - end - - it "creates files that don't exist" do - touch_src "meh_model.c" - touch_src "meh_conductor.c" - touch_src "meh_hardware.c" - touch_src "meh_model.h" - touch_src "meh_conductor.h" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_src_file_to_exist "meh_hardware.h" - expect_test_file_to_exist "Testmeh_model.c" - expect_test_file_to_exist "Testmeh_conductor.c" - expect_test_file_to_exist "Testmeh_hardware.c" - end - - it "does not alter existing source files" do - create_src_with_known_content "meh_model.c" - create_src_with_known_content "meh_model.c" - create_src_with_known_content "meh_model.c" - create_src_with_known_content "meh_model.h" - create_src_with_known_content "meh_model.c" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_src_content_didnt_change "meh_model.c" - expect_src_content_didnt_change "meh_model.c" - expect_src_content_didnt_change "meh_model.c" - expect_src_content_didnt_change "meh_model.c" - end - - it "does not alter existing test files" do - create_test_with_known_content "Testmeh_model.c" - - UnityModuleGenerator.new(@options).generate("meh") - - expect_test_content_didnt_change "Testmeh_model.c" - end - - end -end diff --git a/components/cjson/cJSON/tests/unity/test/targets/clang_file.yml b/components/cjson/cJSON/tests/unity/test/targets/clang_file.yml deleted file mode 100644 index df1bd24e3..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/clang_file.yml +++ /dev/null @@ -1,78 +0,0 @@ ---- -compiler: - path: clang - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-Wall' - - '-Wextra' - - '-Werror' - - '-Wcast-qual' - - '-Wconversion' - - '-Wdisabled-optimization' - - '-Wformat=2' - - '-Winit-self' - - '-Winline' - - '-Winvalid-pch' - - '-Wmissing-include-dirs' - - '-Wnonnull' - - '-Wpacked' - - '-Wpointer-arith' - - '-Wswitch-default' - - '-Wstrict-aliasing' - - '-Wstrict-overflow=5' - - '-Wuninitialized' - - '-Wunused' -# - '-Wunreachable-code' - - '-Wreturn-type' - - '-Wshadow' - - '-Wundef' - - '-Wwrite-strings' - - '-Wno-nested-externs' - - '-Wno-unused-parameter' - - '-Wno-variadic-macros' - - '-Wbad-function-cast' - - '-fms-extensions' - - '-fno-omit-frame-pointer' - - '-ffloat-store' - - '-fno-common' - - '-fstrict-aliasing' - - '-std=gnu99' - - '-pedantic' - - '-O0' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_64 - - UNITY_OUTPUT_RESULTS_FILE - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: clang - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/clang_strict.yml b/components/cjson/cJSON/tests/unity/test/targets/clang_strict.yml deleted file mode 100644 index ee05b2a99..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/clang_strict.yml +++ /dev/null @@ -1,78 +0,0 @@ ---- -compiler: - path: clang - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-Wall' - - '-Wextra' - - '-Werror' - - '-Wcast-qual' - - '-Wconversion' - - '-Wdisabled-optimization' - - '-Wformat=2' - - '-Winit-self' - - '-Winline' - - '-Winvalid-pch' - - '-Wmissing-include-dirs' - - '-Wnonnull' - - '-Wpacked' - - '-Wpointer-arith' - - '-Wswitch-default' - - '-Wstrict-aliasing' - - '-Wstrict-overflow=5' - - '-Wuninitialized' - - '-Wunused' -# - '-Wunreachable-code' - - '-Wreturn-type' - - '-Wshadow' - - '-Wundef' - - '-Wwrite-strings' - - '-Wno-nested-externs' - - '-Wno-unused-parameter' - - '-Wno-variadic-macros' - - '-Wbad-function-cast' - - '-fms-extensions' - - '-fno-omit-frame-pointer' - #- '-ffloat-store' - - '-fno-common' - - '-fstrict-aliasing' - - '-std=gnu99' - - '-pedantic' - - '-O0' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_SUPPORT_64 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: clang - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/gcc_32.yml b/components/cjson/cJSON/tests/unity/test/targets/gcc_32.yml deleted file mode 100644 index ec1165da0..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/gcc_32.yml +++ /dev/null @@ -1,49 +0,0 @@ -compiler: - path: gcc - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m32' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_EXCLUDE_STDINT_H - - UNITY_EXCLUDE_LIMITS_H - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_INT_WIDTH=32 - - UNITY_LONG_WIDTH=32 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m32' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/gcc_64.yml b/components/cjson/cJSON/tests/unity/test/targets/gcc_64.yml deleted file mode 100644 index 0e273de8f..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/gcc_64.yml +++ /dev/null @@ -1,50 +0,0 @@ -compiler: - path: gcc - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m64' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_EXCLUDE_STDINT_H - - UNITY_EXCLUDE_LIMITS_H - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_SUPPORT_64 - - UNITY_INT_WIDTH=32 - - UNITY_LONG_WIDTH=64 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_limits.yml b/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_limits.yml deleted file mode 100644 index 40088ac43..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_limits.yml +++ /dev/null @@ -1,47 +0,0 @@ -compiler: - path: gcc - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m64' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_EXCLUDE_STDINT_H - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_SUPPORT_64 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_stdint.yml b/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_stdint.yml deleted file mode 100644 index f12165cd1..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/gcc_auto_stdint.yml +++ /dev/null @@ -1,59 +0,0 @@ -compiler: - path: gcc - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m64' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - - '-Wextra' - - '-Werror' - - '-Wpointer-arith' - - '-Wcast-align' - - '-Wwrite-strings' - - '-Wswitch-default' - - '-Wunreachable-code' - - '-Winit-self' - - '-Wmissing-field-initializers' - - '-Wno-unknown-pragmas' - - '-Wstrict-prototypes' - - '-Wundef' - - '-Wold-style-definition' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_SUPPORT_64 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/gcc_manual_math.yml b/components/cjson/cJSON/tests/unity/test/targets/gcc_manual_math.yml deleted file mode 100644 index b379e3fc4..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/gcc_manual_math.yml +++ /dev/null @@ -1,47 +0,0 @@ -compiler: - path: gcc - source_path: '../src/' - unit_tests_path: &unit_tests_path 'tests/' - build_path: &build_path 'build/' - options: - - '-c' - - '-m64' - - '-Wall' - - '-Wno-address' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - items: - - 'src/' - - '../src/' - - 'testdata/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_EXCLUDE_MATH_H - - UNITY_INCLUDE_DOUBLE - - UNITY_SUPPORT_TEST_CASES - - UNITY_SUPPORT_64 - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: gcc - options: - - -lm - - '-m64' - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - destination: *build_path -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/hitech_picc18.yml b/components/cjson/cJSON/tests/unity/test/targets/hitech_picc18.yml deleted file mode 100644 index 2fd4aa366..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/hitech_picc18.yml +++ /dev/null @@ -1,101 +0,0 @@ -# rumor has it that this yaml file works for the standard edition of the -# hitech PICC18 compiler, but not the pro version. -# -compiler: - path: cd build && picc18 - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --chip=18F87J10 - - --ide=hitide - - --q #quiet please - - --asmlist - - --codeoffset=0 - - --emi=wordwrite # External memory interface protocol - - --warn=0 # allow all normal warning messages - - --errors=10 # Number of errors before aborting compile - - --char=unsigned - - -Bl # Large memory model - - -G # generate symbol file - - --cp=16 # 16-bit pointers - - --double=24 - - -N255 # 255-char symbol names - - --opt=none # Do not use any compiler optimziations - - -c # compile only - - -M - includes: - prefix: '-I' - items: - - 'c:/Projects/NexGen/Prototypes/CMockTest/src/' - - 'c:/Projects/NexGen/Prototypes/CMockTest/mocks/' - - 'c:/CMock/src/' - - 'c:/CMock/examples/src/' - - 'c:/CMock/vendor/unity/src/' - - 'c:/CMock/vendor/unity/examples/helper/' - - *unit_tests_path - defines: - prefix: '-D' - items: - - UNITY_INT_WIDTH=16 - - UNITY_POINTER_WIDTH=16 - - CMOCK_MEM_STATIC - - CMOCK_MEM_SIZE=3000 - - UNITY_SUPPORT_TEST_CASES - - _PICC18 - object_files: - # prefix: '-O' # Hi-Tech doesn't want a prefix. They key off of filename .extensions, instead - extension: '.obj' - destination: *build_path - -linker: - path: cd build && picc18 - options: - - --chip=18F87J10 - - --ide=hitide - - --cp=24 # 24-bit pointers. Is this needed for linker?? - - --double=24 # Is this needed for linker?? - - -Lw # Scan the pic87*w.lib in the lib/ of the compiler installation directory - - --summary=mem,file # info listing - - --summary=+psect - - --summary=+hex - - --output=+intel - - --output=+mcof - - --runtime=+init # Directs startup code to copy idata, ibigdata and ifardata psects from ROM to RAM. - - --runtime=+clear # Directs startup code to clear bss, bigbss, rbss and farbss psects - - --runtime=+clib # link in the c-runtime - - --runtime=+keep # Keep the generated startup src after its obj is linked - - -G # Generate src-level symbol file - - -MIWasTheLastToBuild.map - - --warn=0 # allow all normal warning messages - - -Bl # Large memory model (probably not needed for linking) - includes: - prefix: '-I' - object_files: - path: *build_path - extension: '.obj' - bin_files: - prefix: '-O' - extension: '.hex' - destination: *build_path - -simulator: - path: - pre_support: - - 'java -client -jar ' # note space - - ['C:\Program Files\HI-TECH Software\HI-TIDE\3.15\lib\', 'simpic18.jar'] - - 18F87J10 - post_support: - -:cmock: - :plugins: [] - :includes: - - Types.h - :suite_teardown: | - if (num_failures) - _FAILED_TEST(); - else - _PASSED_TESTS(); - return 0; - -colour: true diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v4.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v4.yml deleted file mode 100644 index 2f9f881ec..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v4.yml +++ /dev/null @@ -1,90 +0,0 @@ -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --dlib_config - - [*tools_root, 'arm\lib\dl4tptinl8n.h'] - - -z3 - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian little - - --cpu ARM7TDMI - - --stack_align 4 - - --interwork - - -e - - --silent - - --warnings_are_errors - - --fpu None - - --diag_suppress Pa050 - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - defines: - prefix: '-D' - items: - - UNITY_SUPPORT_64 - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.r79' - destination: *build_path -linker: - path: [*tools_root, 'common\bin\xlink.exe'] - options: - - -rt - - [*tools_root, 'arm\lib\dl4tptinl8n.r79'] - - -D_L_EXTMEM_START=0 - - -D_L_EXTMEM_SIZE=0 - - -D_L_HEAP_SIZE=120 - - -D_L_STACK_SIZE=32 - - -e_small_write=_formatted_write - - -s - - __program_start - - -f - - [*tools_root, '\arm\config\lnkarm.xcl'] - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\config\'] - - [*tools_root, 'arm\lib\'] - object_files: - path: *build_path - extension: '.r79' - bin_files: - prefix: '-o' - extension: '.d79' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --backend - - -B - - -p - - [*tools_root, 'arm\config\ioat91sam7X256.ddf'] - - -d - - sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5.yml deleted file mode 100644 index 223f1a65d..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5.yml +++ /dev/null @@ -1,80 +0,0 @@ -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --dlib_config - - [*tools_root, 'arm\inc\DLib_Config_Normal.h'] - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian=little - - --cpu=ARM7TDMI - - --interwork - - --warnings_are_errors - - --fpu=None - - --diag_suppress=Pa050 - - --diag_suppress=Pe111 - - -e - - -On - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - - 'iar\iar_v5\incIAR\' - defines: - prefix: '-D' - items: - - UNITY_SUPPORT_64 - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.r79' - destination: *build_path -linker: - path: [*tools_root, 'arm\bin\ilinkarm.exe'] - options: - - --redirect _Printf=_PrintfLarge - - --redirect _Scanf=_ScanfSmall - - --semihosting - - --entry __iar_program_start - - --config - - [*tools_root, 'arm\config\generic.icf'] - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --backend - - -B - - -p - - [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf'] - - -d - - sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5_3.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5_3.yml deleted file mode 100644 index 223f1a65d..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_arm_v5_3.yml +++ /dev/null @@ -1,80 +0,0 @@ -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --dlib_config - - [*tools_root, 'arm\inc\DLib_Config_Normal.h'] - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian=little - - --cpu=ARM7TDMI - - --interwork - - --warnings_are_errors - - --fpu=None - - --diag_suppress=Pa050 - - --diag_suppress=Pe111 - - -e - - -On - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - - 'iar\iar_v5\incIAR\' - defines: - prefix: '-D' - items: - - UNITY_SUPPORT_64 - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.r79' - destination: *build_path -linker: - path: [*tools_root, 'arm\bin\ilinkarm.exe'] - options: - - --redirect _Printf=_PrintfLarge - - --redirect _Scanf=_ScanfSmall - - --semihosting - - --entry __iar_program_start - - --config - - [*tools_root, 'arm\config\generic.icf'] - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --backend - - -B - - -p - - [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf'] - - -d - - sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml deleted file mode 100644 index c79bacf95..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml +++ /dev/null @@ -1,94 +0,0 @@ -#Default tool path for IAR 5.4 on Windows XP 64bit -tools_root: &tools_root 'C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --diag_suppress=Pa050 - #- --diag_suppress=Pe111 - - --debug - - --endian=little - - --cpu=Cortex-M3 - - --no_path_in_file_macros - - -e - - --fpu=None - - --dlib_config - - [*tools_root, 'arm\inc\DLib_Config_Normal.h'] - #- --preinclude --preinclude C:\Vss\T2 Working\common\system.h - - --interwork - - --warnings_are_errors -# - Ohz - - -Oh -# - --no_cse -# - --no_unroll -# - --no_inline -# - --no_code_motion -# - --no_tbaa -# - --no_clustering -# - --no_scheduling - - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - - 'iar\iar_v5\incIAR\' - defines: - prefix: '-D' - items: - - ewarm - - PART_LM3S9B92 - - TARGET_IS_TEMPEST_RB1 - - USE_ROM_DRIVERS - - UART_BUFFERED - - UNITY_SUPPORT_64 - object_files: - prefix: '-o' - extension: '.r79' - destination: *build_path -linker: - path: [*tools_root, 'arm\bin\ilinkarm.exe'] - options: - - --redirect _Printf=_PrintfLarge - - --redirect _Scanf=_ScanfSmall - - --semihosting - - --entry __iar_program_start - - --config - - [*tools_root, 'arm\config\generic.icf'] -# - ['C:\Temp\lm3s9b92.icf'] - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - #- --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim2.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --backend - - -B - - --endian=little - - --cpu=Cortex-M3 - - --fpu=None - - -p - - [*tools_root, 'arm\config\debugger\TexasInstruments\iolm3sxxxx.ddf'] - - --semihosting - - --device=LM3SxBxx - #- -d - #- sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_cortexm3_v5.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_cortexm3_v5.yml deleted file mode 100644 index 973de9475..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_cortexm3_v5.yml +++ /dev/null @@ -1,84 +0,0 @@ -# unit testing under iar compiler / simulator for STM32 Cortex-M3 - -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.4\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --dlib_config - - [*tools_root, 'arm\inc\DLib_Config_Normal.h'] - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian=little - - --cpu=Cortex-M3 - - --interwork - - --warnings_are_errors - - --fpu=None - - --diag_suppress=Pa050 - - --diag_suppress=Pe111 - - -e - - -On - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - - 'iar\iar_v5\incIAR\' - defines: - prefix: '-D' - items: - - 'IAR' - - 'UNITY_SUPPORT_64' - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.r79' - destination: *build_path -linker: - path: [*tools_root, 'arm\bin\ilinkarm.exe'] - options: - - --redirect _Printf=_PrintfLarge - - --redirect _Scanf=_ScanfSmall - - --semihosting - - --entry __iar_program_start - - --config - - [*tools_root, 'arm\config\generic_cortex.icf'] - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --backend - - -B - - -p - - [*tools_root, 'arm\config\debugger\ST\iostm32f107xx.ddf'] - - --cpu=Cortex-M3 - - -d - - sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_msp430.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_msp430.yml deleted file mode 100644 index 4563af927..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_msp430.yml +++ /dev/null @@ -1,95 +0,0 @@ -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3 MSP430\' -core_root: &core_root [*tools_root, '430\'] -core_bin: &core_bin [*core_root, 'bin\'] -core_config: &core_config [*core_root, 'config\'] -core_lib: &core_lib [*core_root, 'lib\'] -core_inc: &core_inc [*core_root, 'inc\'] -core_config: &core_config [*core_root, 'config\'] - -compiler: - path: [*core_bin, 'icc430.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - --dlib_config - - [*core_lib, 'dlib\dl430fn.h'] - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --debug - - -e - - -Ol - - --multiplier=16 - - --double=32 - - --diag_suppress Pa050 - - --diag_suppress Pe111 - includes: - prefix: '-I' - items: - - *core_inc - - [*core_inc, 'dlib'] - - [*core_lib, 'dlib'] - - 'src\' - - '../src/' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src' - defines: - prefix: '-D' - items: - - '__MSP430F149__' - - 'INT_WIDTH=16' - - 'UNITY_EXCLUDE_FLOAT' - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.r43' - destination: *build_path -linker: - path: [*core_bin, 'xlink.exe'] - options: - - -rt - - [*core_lib, 'dlib\dl430fn.r43'] - - -e_PrintfTiny=_Printf - - -e_ScanfSmall=_Scanf - - -s __program_start - - -D_STACK_SIZE=50 - - -D_DATA16_HEAP_SIZE=50 - - -D_DATA20_HEAP_SIZE=50 - - -f - - [*core_config, 'lnk430f5438.xcl'] - - -f - - [*core_config, 'multiplier.xcl'] - includes: - prefix: '-I' - items: - - *core_config - - *core_lib - - [*core_lib, 'dlib'] - object_files: - path: *build_path - extension: '.r79' - bin_files: - prefix: '-o' - extension: '.d79' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*core_bin, '430proc.dll'] - - [*core_bin, '430sim.dll'] - post_support: - - --plugin - - [*core_bin, '430bat.dll'] - - --backend -B - - --cpu MSP430F5438 - - -p - - [*core_config, 'MSP430F5438.ddf'] - - -d sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/targets/iar_sh2a_v6.yml b/components/cjson/cJSON/tests/unity/test/targets/iar_sh2a_v6.yml deleted file mode 100644 index 27e6bee42..000000000 --- a/components/cjson/cJSON/tests/unity/test/targets/iar_sh2a_v6.yml +++ /dev/null @@ -1,86 +0,0 @@ -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 6.0\' -compiler: - path: [*tools_root, 'sh\bin\iccsh.exe'] - source_path: '..\src\' - unit_tests_path: &unit_tests_path 'tests\' - build_path: &build_path 'build\' - options: - - -e - - --char_is_signed - - -Ol - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_scheduling - - --no_clustering - - --debug - - --dlib_config - - [*tools_root, 'sh\inc\DLib_Product.h'] - - --double=32 - - --code_model=huge - - --data_model=huge - - --core=sh2afpu - - --warnings_affect_exit_code - - --warnings_are_errors - - --mfc - - --use_unix_directory_separators - - --diag_suppress=Pe161 - includes: - prefix: '-I' - items: - - [*tools_root, 'sh\inc\'] - - [*tools_root, 'sh\inc\c'] - - 'src\' - - '..\src\' - - 'testdata/' - - *unit_tests_path - - 'vendor\unity\src\' - defines: - prefix: '-D' - items: - - UNITY_SUPPORT_64 - - 'UNITY_SUPPORT_TEST_CASES' - object_files: - prefix: '-o' - extension: '.o' - destination: *build_path -linker: - path: [*tools_root, 'sh\bin\ilinksh.exe'] - options: - - --redirect __Printf=__PrintfSmall - - --redirect __Scanf=__ScanfSmall - - --config - - [*tools_root, 'sh\config\generic.icf'] - - --config_def _CSTACK_SIZE=0x800 - - --config_def _HEAP_SIZE=0x800 - - --config_def _INT_TABLE=0x10 - - --entry __iar_program_start - - --debug_lib - object_files: - path: *build_path - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - destination: *build_path -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'sh\bin\shproc.dll'] - - [*tools_root, 'sh\bin\shsim.dll'] - post_support: - - --plugin - - [*tools_root, 'sh\bin\shbat.dll'] - - --backend - - -B - - --core sh2afpu - - -p - - [*tools_root, 'sh\config\debugger\io7264.ddf'] - - -d - - sim -colour: true -:unity: - :plugins: [] diff --git a/components/cjson/cJSON/tests/unity/test/testdata/CException.h b/components/cjson/cJSON/tests/unity/test/testdata/CException.h deleted file mode 100644 index 91ad3e1bf..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/CException.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef CEXCEPTION_H -#define CEXCEPTION_H - -#define CEXCEPTION_BEING_USED 1 - -#define CEXCEPTION_NONE 0 -#define CEXCEPTION_T int e = 1; (void) -#define Try if (e) -#define Catch(a) if (!a) - -#endif //CEXCEPTION_H diff --git a/components/cjson/cJSON/tests/unity/test/testdata/Defs.h b/components/cjson/cJSON/tests/unity/test/testdata/Defs.h deleted file mode 100644 index d3a90c0d5..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/Defs.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEF_H -#define DEF_H - -#define EXTERN_DECL - -extern int CounterSuiteSetup; - -#endif //DEF_H diff --git a/components/cjson/cJSON/tests/unity/test/testdata/cmock.h b/components/cjson/cJSON/tests/unity/test/testdata/cmock.h deleted file mode 100644 index c6149be1b..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/cmock.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef CMOCK_H -#define CMOCK_H - -int CMockMemFreeFinalCounter = 0; -int mockMock_Init_Counter = 0; -int mockMock_Verify_Counter = 0; -int mockMock_Destroy_Counter = 0; - -void CMock_Guts_MemFreeFinal(void) { CMockMemFreeFinalCounter++; } -void mockMock_Init(void) { mockMock_Init_Counter++; } -void mockMock_Verify(void) { mockMock_Verify_Counter++; } -void mockMock_Destroy(void) { mockMock_Destroy_Counter++; } - -#endif //CMOCK_H diff --git a/components/cjson/cJSON/tests/unity/test/testdata/mockMock.h b/components/cjson/cJSON/tests/unity/test/testdata/mockMock.h deleted file mode 100644 index 0a2c616f7..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/mockMock.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MOCK_MOCK_H -#define MOCK_MOCK_H - -extern int mockMock_Init_Counter; -extern int mockMock_Verify_Counter; -extern int mockMock_Destroy_Counter; -extern int CMockMemFreeFinalCounter; - -void mockMock_Init(void); -void mockMock_Verify(void); -void mockMock_Destroy(void); - -#endif //MOCK_MOCK_H diff --git a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGenerator.c b/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGenerator.c deleted file mode 100644 index e036dd967..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGenerator.c +++ /dev/null @@ -1,183 +0,0 @@ -/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ - -#include -#include "unity.h" -#include "Defs.h" - -#ifdef USE_CEXCEPTION -#include "CException.h" -#endif - -/* Notes about prefixes: - test - normal default prefix. these are "always run" tests for this procedure - spec - normal default prefix. required to run default setup/teardown calls. - should - normal default prefix. - qwiktest - custom prefix for when tests skip all setup/teardown calls. - custtest - custom prefix for when tests use custom setup/teardown calls. - paratest - custom prefix for when we want to verify parameterized tests. - extest - custom prefix only used during cexception - suitetest- custom prefix for when we want to use custom suite setup/teardown -*/ - -/* Support for Meta Test Rig */ -#define TEST_CASE(a) -void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests - -/* Global Variables Used During These Tests */ -int CounterSetup = 0; -int CounterTeardown = 0; -int CounterSuiteSetup = 0; - -void setUp(void) -{ - CounterSetup = 1; -} - -void tearDown(void) -{ - CounterTeardown = 1; -} - -void custom_setup(void) -{ - CounterSetup = 2; -} - -void custom_teardown(void) -{ - CounterTeardown = 2; -} - -/* -void test_OldSchoolCommentsShouldBeIgnored(void) -{ - TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored"); -} -*/ - -void test_ThisTestAlwaysPasses(void) -{ - TEST_PASS(); -} - -void test_ThisTestAlwaysFails(void) -{ - TEST_FAIL_MESSAGE("This Test Should Fail"); -} - -void test_ThisTestAlwaysIgnored(void) -{ - TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); -} - -void qwiktest_ThisTestPassesWhenNoSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run"); -} - -void qwiktest_ThisTestPassesWhenNoTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run"); -} - -void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run"); -} - -void spec_ThisTestPassesWhenNormalSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); -} - -void spec_ThisTestPassesWhenNormalTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); -} - -void custtest_ThisTestPassesWhenCustomSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run"); -} - -void custtest_ThisTestPassesWhenCustomTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run"); -} - -//void test_NewStyleCommentsShouldBeIgnored(void) -//{ -// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored"); -//} - -void test_NotBeConfusedByLongComplicatedStrings(void) -{ - const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; - - TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same"); -} - -void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void) -{ - TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); -} - -void test_StillNotBeConfusedByLongComplicatedStrings(void) -{ - const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; - - TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same"); -} - -void should_RunTestsStartingWithShouldByDefault(void) -{ - TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); -} - -TEST_CASE(25) -TEST_CASE(125) -TEST_CASE(5) -void paratest_ShouldHandleParameterizedTests(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5"); -} - -TEST_CASE(7) -void paratest_ShouldHandleParameterizedTests2(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes"); -} - -void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void) -{ - TEST_PASS(); -} - -TEST_CASE(17) -void paratest_ShouldHandleParameterizedTestsThatFail(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail"); -} - -#ifdef USE_CEXCEPTION -void extest_ShouldHandleCExceptionInTest(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException"); -} -#endif - -#ifdef USE_ANOTHER_MAIN -int custom_main(void); - -int main(void) -{ - return custom_main(); -} -#endif - -void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run"); -} - - diff --git a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorSmall.c b/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorSmall.c deleted file mode 100644 index c68374948..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorSmall.c +++ /dev/null @@ -1,67 +0,0 @@ -/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ - -#include -#include "unity.h" -#include "Defs.h" - -TEST_FILE("some_file.c") - -/* Notes about prefixes: - test - normal default prefix. these are "always run" tests for this procedure - spec - normal default prefix. required to run default setup/teardown calls. -*/ - -/* Support for Meta Test Rig */ -#define TEST_CASE(a) -void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests - -/* Global Variables Used During These Tests */ -int CounterSetup = 0; -int CounterTeardown = 0; -int CounterSuiteSetup = 0; - -void setUp(void) -{ - CounterSetup = 1; -} - -void tearDown(void) -{ - CounterTeardown = 1; -} - -void custom_setup(void) -{ - CounterSetup = 2; -} - -void custom_teardown(void) -{ - CounterTeardown = 2; -} - -void test_ThisTestAlwaysPasses(void) -{ - TEST_PASS(); -} - -void test_ThisTestAlwaysFails(void) -{ - TEST_FAIL_MESSAGE("This Test Should Fail"); -} - -void test_ThisTestAlwaysIgnored(void) -{ - TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); -} - -void spec_ThisTestPassesWhenNormalSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); -} - -void spec_ThisTestPassesWhenNormalTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); -} - diff --git a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorWithMocks.c b/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorWithMocks.c deleted file mode 100644 index 7eb0b671f..000000000 --- a/components/cjson/cJSON/tests/unity/test/testdata/testRunnerGeneratorWithMocks.c +++ /dev/null @@ -1,192 +0,0 @@ -/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ - -#include -#include "unity.h" -#include "Defs.h" -#include "mockMock.h" - -#ifdef USE_CEXCEPTION -#include "CException.h" -#endif - -/* Notes about prefixes: - test - normal default prefix. these are "always run" tests for this procedure - spec - normal default prefix. required to run default setup/teardown calls. - should - normal default prefix. - qwiktest - custom prefix for when tests skip all setup/teardown calls. - custtest - custom prefix for when tests use custom setup/teardown calls. - paratest - custom prefix for when we want to verify parameterized tests. - extest - custom prefix only used during cexception - suitetest- custom prefix for when we want to use custom suite setup/teardown -*/ - -/* Support for Meta Test Rig */ -#define TEST_CASE(a) -void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests - -/* Global Variables Used During These Tests */ -int CounterSetup = 0; -int CounterTeardown = 0; -int CounterSuiteSetup = 0; - -void setUp(void) -{ - CounterSetup = 1; -} - -void tearDown(void) -{ - CounterTeardown = 1; -} - -void custom_setup(void) -{ - CounterSetup = 2; -} - -void custom_teardown(void) -{ - CounterTeardown = 2; -} - -/* -void test_OldSchoolCommentsShouldBeIgnored(void) -{ - TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored"); -} -*/ - -void test_ThisTestAlwaysPasses(void) -{ - TEST_PASS(); -} - -void test_ThisTestAlwaysFails(void) -{ - TEST_FAIL_MESSAGE("This Test Should Fail"); -} - -void test_ThisTestAlwaysIgnored(void) -{ - TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); -} - -void qwiktest_ThisTestPassesWhenNoSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run"); -} - -void qwiktest_ThisTestPassesWhenNoTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run"); -} - -void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run"); -} - -void spec_ThisTestPassesWhenNormalSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); -} - -void spec_ThisTestPassesWhenNormalTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); -} - -void custtest_ThisTestPassesWhenCustomSetupRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run"); -} - -void custtest_ThisTestPassesWhenCustomTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run"); -} - -//void test_NewStyleCommentsShouldBeIgnored(void) -//{ -// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored"); -//} - -void test_NotBeConfusedByLongComplicatedStrings(void) -{ - const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; - - TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same"); -} - -void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void) -{ - TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); -} - -void test_StillNotBeConfusedByLongComplicatedStrings(void) -{ - const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; - - TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same"); -} - -void should_RunTestsStartingWithShouldByDefault(void) -{ - TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); -} - -TEST_CASE(25) -TEST_CASE(125) -TEST_CASE(5) -void paratest_ShouldHandleParameterizedTests(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5"); -} - -TEST_CASE(7) -void paratest_ShouldHandleParameterizedTests2(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes"); -} - -void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void) -{ - TEST_PASS(); -} - -TEST_CASE(17) -void paratest_ShouldHandleParameterizedTestsThatFail(int Num) -{ - TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail"); -} - -#ifdef USE_CEXCEPTION -void extest_ShouldHandleCExceptionInTest(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException"); -} -#endif - -#ifdef USE_ANOTHER_MAIN -int custom_main(void); - -int main(void) -{ - return custom_main(); -} -#endif - -void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void) -{ - TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run"); -} - -void test_ShouldCallMockInitAndVerifyFunctionsForEachTest(void) -{ - int passesOrIgnores = (int)(Unity.NumberOfTests - Unity.TestFailures); - TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests, mockMock_Init_Counter, "Mock Init Should Be Called Once Per Test Started"); - TEST_ASSERT_EQUAL_MESSAGE(passesOrIgnores, mockMock_Verify_Counter, "Mock Verify Should Be Called Once Per Test Passed"); - TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests - 1, mockMock_Destroy_Counter, "Mock Destroy Should Be Called Once Per Test Completed"); - TEST_ASSERT_EQUAL_MESSAGE(0, CMockMemFreeFinalCounter, "Mock MemFreeFinal Should Not Be Called Until End"); -} - diff --git a/components/cjson/cJSON/tests/unity/test/tests/test_generate_test_runner.rb b/components/cjson/cJSON/tests/unity/test/tests/test_generate_test_runner.rb deleted file mode 100644 index a3536d36d..000000000 --- a/components/cjson/cJSON/tests/unity/test/tests/test_generate_test_runner.rb +++ /dev/null @@ -1,1252 +0,0 @@ -# ========================================== -# CMock Project - Automatic Mock Generation for C -# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams -# [Released under MIT License. Please refer to license.txt for details] -# ========================================== - -require '../auto/generate_test_runner.rb' - -$generate_test_runner_tests = 0 -$generate_test_runner_failures = 0 - -OUT_FILE = 'build/testsample_' - -RUNNER_TESTS = [ - { :name => 'DefaultsThroughOptions', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => nil, #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'DefaultsThroughCommandLine', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => "", #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'DefaultsThroughYAMLFile', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => "", #defaults - :yaml => {}, #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ShorterFilterOfJustTest', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "test", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ShorterFilterOfJustShould', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "should", - }, - :expected => { - :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ShorterFilterOfJustSpec', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "spec", - }, - :expected => { - :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'InjectIncludes', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :includes => ['Defs.h'], - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ParameterizedThroughOptions', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "paratest", - :use_param_tests => true, - }, - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'ParameterizedThroughCommandLine', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1", - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'ParameterizedThroughCommandLineAndYaml', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => "--use_param_tests=1", - :yaml => { - :test_prefix => "paratest" - }, - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'CException', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'USE_CEXCEPTION'], - :options => { - :test_prefix => "extest", - :plugins => [ :cexception ], - }, - :expected => { - :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughOptions', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "custtest|test", - :setup_name => "custom_setup", - :teardown_name => "custom_teardown", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughCommandLine', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughYaml', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"custtest|test\"", - :yaml => { - :setup_name => "custom_setup", - :teardown_name => "custom_teardown", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomMain', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', "USE_ANOTHER_MAIN"], - :options => { - :main_name => "custom_main", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSuiteSetupAndTeardown', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :includes => ['Defs.h'], - :options => { - :test_prefix => "suitetest|test", - :suite_setup => " CounterSuiteSetup = 1;", - :suite_teardown => " return num_failures;", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'MainExternDeclaration', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST'], - :includes => ['Defs.h'], - :options => { - :main_export_decl => "EXTERN_DECL", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - - #### WITH MOCKS ########################################## - - { :name => 'DefaultsThroughOptions', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => nil, #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'DefaultsThroughCommandLine', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => "", #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'DefaultsThroughYAMLFile', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => "", #defaults - :yaml => {}, #defaults - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ShorterFilterOfJustTest', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "test", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ShorterFilterOfJustShould', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "should", - }, - :expected => { - :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ShorterFilterOfJustSpec', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "spec", - }, - :expected => { - :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'InjectIncludes', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :includes => ['Defs.h'], - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ParameterizedThroughOptions', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "paratest", - :use_param_tests => true, - }, - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'ParameterizedThroughCommandLine', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1", - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'ParameterizedThroughCommandLineAndYaml', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => "--use_param_tests=1", - :yaml => { - :test_prefix => "paratest" - }, - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'CException', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST', 'USE_CEXCEPTION'], - :options => { - :test_prefix => "extest", - :plugins => [ :cexception ], - }, - :expected => { - :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughOptions', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :options => { - :test_prefix => "custtest|test", - :setup_name => "custom_setup", - :teardown_name => "custom_teardown", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughCommandLine', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSetupAndTeardownThroughYaml', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :cmdline => " --test_prefix=\"custtest|test\"", - :yaml => { - :setup_name => "custom_setup", - :teardown_name => "custom_teardown", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'custtest_ThisTestPassesWhenCustomSetupRan', - 'custtest_ThisTestPassesWhenCustomTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomMain', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST', "USE_ANOTHER_MAIN"], - :options => { - :main_name => "custom_main", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'CustomSuiteSetupAndTeardown', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :includes => ['Defs.h'], - :options => { - :test_prefix => "suitetest|test", - :suite_setup => " CounterSuiteSetup = 1;", - :suite_teardown => " return num_failures;", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'MainExternDeclaration', - :testfile => 'testdata/testRunnerGeneratorWithMocks.c', - :testdefines => ['TEST'], - :includes => ['Defs.h'], - :options => { - :main_export_decl => "EXTERN_DECL", - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - - - #### WITH ARGS ########################################## - - { :name => 'ArgsThroughOptions', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsThroughCommandLine', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :cmdline => "--cmdline_args=1", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsThroughYAMLFile', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :cmdline => "", - :yaml => { - :cmdline_args => true, - }, - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterJustTest', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n test_", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterJustShould', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n should_", - :expected => { - :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsNameFilterTestAndShould', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n should_,test_", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterWithWildcardOnFile', - :testfile => 'testdata/testRunnerGeneratorSmall.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGeneratorSma*", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterWithWildcardAsName', - :testfile => 'testdata/testRunnerGeneratorSmall.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGeneratorSmall:*", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterWithWildcardOnName', - :testfile => 'testdata/testRunnerGeneratorSmall.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGeneratorSmall:test_*", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterWithWildcardAndShortName', - :testfile => 'testdata/testRunnerGeneratorSmall.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGeneratorSmall:te*", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsNameFilterWithWildcardOnBoth', - :testfile => 'testdata/testRunnerGeneratorSmall.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGeneratorSm*:*", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsExcludeFilterJustTest', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-x test_", - :expected => { - :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - 'should_RunTestsStartingWithShouldByDefault', - ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeAndExcludeFilter', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - :includes => ['Defs.h'], - }, - :cmdline_args => "-n test_ -x Ignored", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeSingleTest', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n ThisTestAlwaysPasses", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeSingleTestInSpecificFile', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGenerator:ThisTestAlwaysPasses", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeTestFileWithExtension', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGenerator.c:ThisTestAlwaysPasses", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeDoubleQuotes', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n \"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeSingleQuotes', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n 'testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails'", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeAValidTestForADifferentFile', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n AnotherFile:ThisTestDoesNotExist", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeNoTests', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n ThisTestDoesNotExist", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsExcludeAllTests', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-x _", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeFullFile', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n testRunnerGenerator", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses', - 'spec_ThisTestPassesWhenNormalSetupRan', - 'spec_ThisTestPassesWhenNormalTeardownRan', - 'test_NotBeConfusedByLongComplicatedStrings', - 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', - 'test_StillNotBeConfusedByLongComplicatedStrings', - 'should_RunTestsStartingWithShouldByDefault', - 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', - ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], - } - }, - - { :name => 'ArgsIncludeWithAlternateFlag', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-f=\"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"", - :expected => { - :to_pass => [ 'test_ThisTestAlwaysPasses' ], - :to_fail => [ 'test_ThisTestAlwaysFails' ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsIncludeWithParameterized', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :cmdline => "--use_param_tests=1", - :yaml => { - :cmdline_args => true, - :test_prefix => "paratest" - }, - :cmdline_args => "-n ShouldHandleParameterizedTests", - :expected => { - :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - ], - :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], - :to_ignore => [ ], - } - }, - - { :name => 'ArgsList', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-l", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - :text => [ "testRunnerGenerator", - "test_ThisTestAlwaysPasses", - "test_ThisTestAlwaysFails", - "test_ThisTestAlwaysIgnored", - "spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan", - "spec_ThisTestPassesWhenNormalSetupRan", - "spec_ThisTestPassesWhenNormalTeardownRan", - "test_NotBeConfusedByLongComplicatedStrings", - "test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings", - "test_StillNotBeConfusedByLongComplicatedStrings", - "should_RunTestsStartingWithShouldByDefault" - ] - } - }, - - { :name => 'ArgsListParameterized', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :test_prefix => "paratest", - :use_param_tests => true, - :cmdline_args => true, - }, - :cmdline_args => "-l", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - :text => [ "testRunnerGenerator", - 'paratest_ShouldHandleParameterizedTests\(25\)', - 'paratest_ShouldHandleParameterizedTests\(125\)', - 'paratest_ShouldHandleParameterizedTests\(5\)', - 'paratest_ShouldHandleParameterizedTests2\(7\)', - 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid\(RUN_TEST_NO_ARGS\)', - 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' - ], - } - }, - - { :name => 'ArgsIncompleteIncludeFlags', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-n", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - :text => [ "ERROR: No Test String to Include Matches For" ], - } - }, - - { :name => 'ArgsIncompleteExcludeFlags', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-x", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - :text => [ "ERROR: No Test String to Exclude Matches For" ], - } - }, - - { :name => 'ArgsIllegalFlags', - :testfile => 'testdata/testRunnerGenerator.c', - :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], - :options => { - :cmdline_args => true, - }, - :cmdline_args => "-z", - :expected => { - :to_pass => [ ], - :to_fail => [ ], - :to_ignore => [ ], - :text => [ "ERROR: Unknown Option z" ], - } - }, -] - -def runner_test(test, runner, expected, test_defines, cmdline_args) - # Tack on TEST define for compiling unit tests - load_configuration($cfg_file) - - #compile objects - obj_list = [ - compile(runner, test_defines), - compile(test, test_defines), - compile('../src/unity.c', test_defines), - ] - - # Link the test executable - test_base = File.basename(test, C_EXTENSION) - link_it(test_base, obj_list) - - # Execute unit test and generate results file - simulator = build_simulator_fields - cmdline_args ||= "" - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + " #{cmdline_args}" - cmd_str = if simulator.nil? - executable - else - "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end - output = execute(cmd_str, true) - - #compare to the expected pass/fail - allgood = expected[:to_pass].inject(true) {|s,v| s && verify_match(/#{v}:PASS/, output) } - allgood = expected[:to_fail].inject(allgood) {|s,v| s && verify_match(/#{v}:FAIL/, output) } - allgood = expected[:to_ignore].inject(allgood) {|s,v| s && verify_match(/#{v}:IGNORE/, output) } - - #verify there weren't more pass/fail/etc than expected - allgood &&= verify_number( expected[:to_pass], /(:PASS)/, output) - allgood &&= verify_number( expected[:to_fail], /(:FAIL)/, output) - allgood &&= verify_number( expected[:to_ignore], /(:IGNORE)/, output) - - #if we care about any other text, check that too - if (expected[:text]) - allgood = expected[:text].inject(allgood) {|s,v| s && verify_match(/#{v}/, output) } - allgood &&= verify_number( expected[:text], /.+/, output ) - end - - report output if (!allgood && !$verbose) #report failures if not already reporting everything - return allgood -end - -def verify_match(expression, output) - if (expression =~ output) - return true - else - report " FAIL: No Match For /#{expression.to_s}/" - return false - end -end - -def verify_number(expected, expression, output) - exp = expected.length - act = output.scan(expression).length - if (exp == act) - return true - else - report " FAIL: Expected #{exp} Matches For /#{expression.to_s}/. Was #{act}" - return false - end -end - -RUNNER_TESTS.each do |testset| - basename = File.basename(testset[:testfile], C_EXTENSION) - testset_name = "Runner_#{basename}_#{testset[:name]}" - should testset_name do - runner_name = OUT_FILE + testset[:name] + '_runner.c' - - #create a yaml file first if required - yaml_option = "" - if (testset[:yaml]) - File.open("build/runner_options.yml",'w') {|f| f << { :unity => testset[:yaml] }.to_yaml } - yaml_option = "build/runner_options.yml" - end - - #run script via command line or through hash function call, as requested - if (testset[:cmdline]) - cmdstr = "ruby ../auto/generate_test_runner.rb #{yaml_option} #{testset[:cmdline]} \"#{testset[:testfile]}\" \"#{runner_name}\"" - `#{cmdstr}` - else - UnityTestRunnerGenerator.new(testset[:options]).run(testset[:testfile], runner_name) - end - - #test the script against the specified test file and check results - if (runner_test(testset[:testfile], runner_name, testset[:expected], testset[:testdefines], testset[:cmdline_args])) - report "#{testset_name}:PASS" - else - report "#{testset_name}:FAIL" - $generate_test_runner_failures += 1 - end - $generate_test_runner_tests += 1 - end -end - -raise "There were #{$generate_test_runner_failures.to_s} failures while testing generate_test_runner.rb" if ($generate_test_runner_failures > 0) diff --git a/components/cjson/cJSON/tests/unity/test/tests/testparameterized.c b/components/cjson/cJSON/tests/unity/test/tests/testparameterized.c deleted file mode 100644 index aa6d1732c..000000000 --- a/components/cjson/cJSON/tests/unity/test/tests/testparameterized.c +++ /dev/null @@ -1,110 +0,0 @@ -/* ========================================== - Unity Project - A Test Framework for C - Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -========================================== */ - -#include -#include -#include "unity.h" - -void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests - -#define TEST_CASE(...) - -#define EXPECT_ABORT_BEGIN \ - if (TEST_PROTECT()) \ - { - -#define VERIFY_FAILS_END \ - } \ - Unity.CurrentTestFailed = (Unity.CurrentTestFailed != 0) ? 0 : 1; \ - if (Unity.CurrentTestFailed == 1) { \ - SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ - UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ - UNITY_OUTPUT_CHAR(':'); \ - UnityPrint(Unity.CurrentTestName); \ - UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \ - UNITY_OUTPUT_CHAR('\n'); \ - } - -#define VERIFY_IGNORES_END \ - } \ - Unity.CurrentTestFailed = (Unity.CurrentTestIgnored != 0) ? 0 : 1; \ - Unity.CurrentTestIgnored = 0; \ - if (Unity.CurrentTestFailed == 1) { \ - SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ - UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ - UNITY_OUTPUT_CHAR(':'); \ - UnityPrint(Unity.CurrentTestName); \ - UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \ - UNITY_OUTPUT_CHAR('\n'); \ - } - -int SetToOneToFailInTearDown; -int SetToOneMeanWeAlreadyCheckedThisGuy; - -void setUp(void) -{ - SetToOneToFailInTearDown = 0; - SetToOneMeanWeAlreadyCheckedThisGuy = 0; -} - -void tearDown(void) -{ - if (SetToOneToFailInTearDown == 1) - TEST_FAIL_MESSAGE("<= Failed in tearDown"); - if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) - { - UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); - UNITY_OUTPUT_CHAR('\n'); - } -} - -TEST_CASE(0) -TEST_CASE(44) -TEST_CASE((90)+9) -void test_TheseShouldAllPass(int Num) -{ - TEST_ASSERT_TRUE(Num < 100); -} - -TEST_CASE(3) -TEST_CASE(77) -TEST_CASE( (99) + 1 - (1)) -void test_TheseShouldAllFail(int Num) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_TRUE(Num > 100); - VERIFY_FAILS_END -} - -TEST_CASE(1) -TEST_CASE(44) -TEST_CASE(99) -TEST_CASE(98) -void test_TheseAreEveryOther(int Num) -{ - if (Num & 1) - { - EXPECT_ABORT_BEGIN - TEST_ASSERT_TRUE(Num > 100); - VERIFY_FAILS_END - } - else - { - TEST_ASSERT_TRUE(Num < 100); - } -} - -void test_NormalPassesStillWork(void) -{ - TEST_ASSERT_TRUE(1); -} - -void test_NormalFailsStillWork(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_TRUE(0); - VERIFY_FAILS_END -} diff --git a/components/cjson/cJSON/tests/unity/test/tests/testunity.c b/components/cjson/cJSON/tests/unity/test/tests/testunity.c deleted file mode 100644 index af06647f8..000000000 --- a/components/cjson/cJSON/tests/unity/test/tests/testunity.c +++ /dev/null @@ -1,5337 +0,0 @@ -/* ========================================== - Unity Project - A Test Framework for C - Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -========================================== */ - -#include "unity.h" -#include -#include - -// Dividing by these constants produces +/- infinity. -// The rationale is given in UnityAssertFloatIsInf's body. -#ifndef UNITY_EXCLUDE_FLOAT -static const UNITY_FLOAT f_zero = 0.0f; -#endif - -#ifndef UNITY_EXCLUDE_DOUBLE -static const UNITY_DOUBLE d_zero = 0.0; -#endif - -#define EXPECT_ABORT_BEGIN \ - startPutcharSpy(); \ - if (TEST_PROTECT()) \ - { - -#define VERIFY_FAILS_END \ - } \ - endPutcharSpy(); /* start/end Spy to suppress output of failure message */ \ - Unity.CurrentTestFailed = (Unity.CurrentTestFailed == 1) ? 0 : 1; \ - if (Unity.CurrentTestFailed == 1) { \ - SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ - UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ - UNITY_OUTPUT_CHAR(':'); \ - UnityPrint(Unity.CurrentTestName); \ - UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \ - UNITY_OUTPUT_CHAR('\n'); \ - } - -#define VERIFY_IGNORES_END \ - } \ - endPutcharSpy(); /* start/end Spy to suppress output of ignore message */ \ - Unity.CurrentTestFailed = (Unity.CurrentTestIgnored == 1) ? 0 : 1; \ - Unity.CurrentTestIgnored = 0; \ - if (Unity.CurrentTestFailed == 1) { \ - SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ - UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ - UNITY_OUTPUT_CHAR(':'); \ - UnityPrint(Unity.CurrentTestName); \ - UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \ - UNITY_OUTPUT_CHAR('\n'); \ - } - -void startPutcharSpy(void); -void endPutcharSpy(void); -char* getBufferPutcharSpy(void); - -static int SetToOneToFailInTearDown; -static int SetToOneMeanWeAlreadyCheckedThisGuy; - -void setUp(void) -{ - SetToOneToFailInTearDown = 0; - SetToOneMeanWeAlreadyCheckedThisGuy = 0; -} - -void tearDown(void) -{ - endPutcharSpy(); /* Stop suppressing test output */ - if (SetToOneToFailInTearDown == 1) - { - /* These will be skipped internally if already failed/ignored */ - TEST_FAIL_MESSAGE("<= Failed in tearDown"); - TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); - } - if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) - { - UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); - UNITY_OUTPUT_CHAR('\n'); - } -} - -void testUnitySizeInitializationReminder(void) -{ - /* This test ensures that sizeof(struct UNITY_STORAGE_T) doesn't change. If this - * test breaks, go look at the initialization of the Unity global variable - * in unity.c and make sure we're filling in the proper fields. */ - const char* message = "Unexpected size for UNITY_STORAGE_T struct. Please check that " - "the initialization of the Unity symbol in unity.c is " - "still correct."; - - /* Define a structure with all the same fields as `struct UNITY_STORAGE_T`. */ -#ifdef UNITY_EXCLUDE_DETAILS - struct { - const char* TestFile; - const char* CurrentTestName; - UNITY_LINE_TYPE CurrentTestLineNumber; - UNITY_COUNTER_TYPE NumberOfTests; - UNITY_COUNTER_TYPE TestFailures; - UNITY_COUNTER_TYPE TestIgnores; - UNITY_COUNTER_TYPE CurrentTestFailed; - UNITY_COUNTER_TYPE CurrentTestIgnored; -#ifndef UNITY_EXCLUDE_SETJMP_H - jmp_buf AbortFrame; -#endif - } _Expected_Unity; -#else - struct { - const char* TestFile; - const char* CurrentTestName; - const char* CurrentDetails1; - const char* CurrentDetails2; - UNITY_LINE_TYPE CurrentTestLineNumber; - UNITY_COUNTER_TYPE NumberOfTests; - UNITY_COUNTER_TYPE TestFailures; - UNITY_COUNTER_TYPE TestIgnores; - UNITY_COUNTER_TYPE CurrentTestFailed; - UNITY_COUNTER_TYPE CurrentTestIgnored; -#ifndef UNITY_EXCLUDE_SETJMP_H - jmp_buf AbortFrame; -#endif - } _Expected_Unity; -#endif - - /* Compare our fake structure's size to the actual structure's size. They - * should be the same. - * - * This accounts for alignment, padding, and packing issues that might come - * up between different architectures. */ - TEST_ASSERT_EQUAL_MESSAGE(sizeof(_Expected_Unity), sizeof(Unity), message); -} - -void testPassShouldEndImmediatelyWithPass(void) -{ - TEST_PASS(); - TEST_FAIL_MESSAGE("We should have passed already and finished this test"); -} - -void testTrue(void) -{ - TEST_ASSERT(1); - - TEST_ASSERT_TRUE(1); -} - -void testFalse(void) -{ - TEST_ASSERT_FALSE(0); - - TEST_ASSERT_UNLESS(0); -} - -void testPreviousPass(void) -{ - TEST_ASSERT_EQUAL_INT(0U, Unity.TestFailures); -} - -void testNotVanilla(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT(0); - VERIFY_FAILS_END -} - -void testNotTrue(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_TRUE(0); - VERIFY_FAILS_END -} - -void testNotFalse(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_FALSE(1); - VERIFY_FAILS_END -} - -void testNotUnless(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UNLESS(1); - VERIFY_FAILS_END -} - -void testNotNotEqual(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_NOT_EQUAL(10, 10); - VERIFY_FAILS_END -} - -void testFail(void) -{ - EXPECT_ABORT_BEGIN - TEST_FAIL_MESSAGE("Expected for testing"); - VERIFY_FAILS_END -} - -void testIsNull(void) -{ - char* ptr1 = NULL; - const char* ptr2 = "hello"; - - TEST_ASSERT_NULL(ptr1); - TEST_ASSERT_NOT_NULL(ptr2); -} - -void testIsNullShouldFailIfNot(void) -{ - const char* ptr1 = "hello"; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_NULL(ptr1); - VERIFY_FAILS_END -} - -void testNotNullShouldFailIfNULL(void) -{ - char* ptr1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_NOT_NULL(ptr1); - VERIFY_FAILS_END -} - -void testIgnore(void) -{ - EXPECT_ABORT_BEGIN - TEST_IGNORE(); - TEST_FAIL_MESSAGE("This should not be reached"); - VERIFY_IGNORES_END -} - -void testIgnoreMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_IGNORE_MESSAGE("This is an expected TEST_IGNORE_MESSAGE string!"); - TEST_FAIL_MESSAGE("This should not be reached"); - VERIFY_IGNORES_END -} - -void testNotEqualInts(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT(3982, 3983); - VERIFY_FAILS_END -} - -void testNotEqualInt8s(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT8(-127, -126); - VERIFY_FAILS_END -} - -void testNotEqualInt16s(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT16(-16383, -16382); - VERIFY_FAILS_END -} - -void testNotEqualInt32s(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT32(-2147483647, -2147483648); //use largest 32 bit negative to test printability - VERIFY_FAILS_END -} - -void testNotEqualBits(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_BITS(0xFF00, 0x5555, 0x5A55); - VERIFY_FAILS_END -} - -void testNotEqualUInts(void) -{ - UNITY_UINT16 v0, v1; - - v0 = 9000; - v1 = 9001; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualUInt8s(void) -{ - UNITY_UINT8 v0, v1; - - v0 = 254; - v1 = 255; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT8(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualUInt16s(void) -{ - UNITY_UINT16 v0, v1; - - v0 = 65535; - v1 = 65534; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT16(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualUInt32s(void) -{ - UNITY_UINT32 v0, v1; - - v0 = 4294967295; - v1 = 4294967294; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT32(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex8s(void) -{ - UNITY_UINT8 v0, v1; - - v0 = 0x23; - v1 = 0x22; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex8sIfSigned(void) -{ - UNITY_INT8 v0, v1; - - v0 = -2; - v1 = 2; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex16s(void) -{ - UNITY_UINT16 v0, v1; - - v0 = 0x1234; - v1 = 0x1235; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX16(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex16sIfSigned(void) -{ - UNITY_INT16 v0, v1; - - v0 = -1024; - v1 = -1028; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX16(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex32s(void) -{ - UNITY_UINT32 v0, v1; - - v0 = 900000; - v1 = 900001; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32(v0, v1); - VERIFY_FAILS_END -} - -void testNotEqualHex32sIfSigned(void) -{ - UNITY_INT32 v0, v1; - - v0 = -900000; - v1 = 900001; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32(v0, v1); - VERIFY_FAILS_END -} - -void testEqualInts(void) -{ - int v0, v1; - int *p0, *p1; - - v0 = 19467; - v1 = 19467; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT(1837, 1837); - TEST_ASSERT_EQUAL_INT(-27365, -27365); - TEST_ASSERT_EQUAL_INT(v0, v1); - TEST_ASSERT_EQUAL_INT(19467, v1); - TEST_ASSERT_EQUAL_INT(v0, 19467); - TEST_ASSERT_EQUAL_INT(*p0, v1); - TEST_ASSERT_EQUAL_INT(*p0, *p1); - TEST_ASSERT_EQUAL_INT(*p0, 19467); -} - -void testEqualInt8s(void) -{ - UNITY_INT8 v0, v1; - UNITY_INT8 *p0, *p1; - - v0 = 0x22; - v1 = 0x22; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT8(0x22, 0x22); - TEST_ASSERT_EQUAL_INT8(v0, v1); - TEST_ASSERT_EQUAL_INT8(0x22, v1); - TEST_ASSERT_EQUAL_INT8(v0, 0x22); - TEST_ASSERT_EQUAL_INT8(*p0, v1); - TEST_ASSERT_EQUAL_INT8(*p0, *p1); - TEST_ASSERT_EQUAL_INT8(*p0, 0x22); -} - -void testEqualInt8sWhenThereAreDifferencesOutside8Bits(void) -{ - TEST_ASSERT_EQUAL_INT8(0x321,0x421); - TEST_ASSERT_EQUAL_INT8(0xFF21,0x0021); -} - -void testEqualInt16s(void) -{ - UNITY_INT16 v0, v1; - UNITY_INT16 *p0, *p1; - - v0 = 0x7876; - v1 = 0x7876; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT16(0x7876, 0x7876); - TEST_ASSERT_EQUAL_INT16(v0, v1); - TEST_ASSERT_EQUAL_INT16(0x7876, v1); - TEST_ASSERT_EQUAL_INT16(v0, 0x7876); - TEST_ASSERT_EQUAL_INT16(*p0, v1); - TEST_ASSERT_EQUAL_INT16(*p0, *p1); - TEST_ASSERT_EQUAL_INT16(*p0, 0x7876); -} - -void testEqualInt16sNegatives(void) -{ - UNITY_INT16 v0, v1; - UNITY_INT16 *p0, *p1; - - v0 = -7876; - v1 = -7876; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT16(-7876, -7876); - TEST_ASSERT_EQUAL_INT16(v0, v1); - TEST_ASSERT_EQUAL_INT16(-7876, v1); - TEST_ASSERT_EQUAL_INT16(v0, -7876); - TEST_ASSERT_EQUAL_INT16(*p0, v1); - TEST_ASSERT_EQUAL_INT16(*p0, *p1); - TEST_ASSERT_EQUAL_INT16(*p0, -7876); -} - -void testEqualInt16sWhenThereAreDifferencesOutside16Bits(void) -{ - TEST_ASSERT_EQUAL_INT16(0x54321,0x64321); - TEST_ASSERT_EQUAL_INT16(0xFFFF4321,0x00004321); -} - -void testEqualInt32s(void) -{ - UNITY_INT32 v0, v1; - UNITY_INT32 *p0, *p1; - - v0 = 0x78760000; - v1 = 0x78760000; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT32(0x78760000, 0x78760000); - TEST_ASSERT_EQUAL_INT32(v0, v1); - TEST_ASSERT_EQUAL_INT32(0x78760000, v1); - TEST_ASSERT_EQUAL_INT32(v0, 0x78760000); - TEST_ASSERT_EQUAL_INT32(*p0, v1); - TEST_ASSERT_EQUAL_INT32(*p0, *p1); - TEST_ASSERT_EQUAL_INT32(*p0, 0x78760000); -} - -void testEqualInt32sNegatives(void) -{ - UNITY_INT32 v0, v1; - UNITY_INT32 *p0, *p1; - - v0 = -123456789; - v1 = -123456789; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT32(-123456789, -123456789); - TEST_ASSERT_EQUAL_INT32(v0, v1); - TEST_ASSERT_EQUAL_INT32(-123456789, v1); - TEST_ASSERT_EQUAL_INT32(v0, -123456789); - TEST_ASSERT_EQUAL_INT32(*p0, v1); - TEST_ASSERT_EQUAL_INT32(*p0, *p1); - TEST_ASSERT_EQUAL_INT32(*p0, -123456789); -} - - -void testEqualUints(void) -{ - unsigned int v0, v1; - unsigned int *p0, *p1; - - v0 = 19467; - v1 = 19467; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT(1837, 1837); - TEST_ASSERT_EQUAL_UINT(v0, v1); - TEST_ASSERT_EQUAL_UINT(19467, v1); - TEST_ASSERT_EQUAL_UINT(v0, 19467); - TEST_ASSERT_EQUAL_UINT(*p0, v1); - TEST_ASSERT_EQUAL_UINT(*p0, *p1); - TEST_ASSERT_EQUAL_UINT(*p0, 19467); - TEST_ASSERT_EQUAL_UINT(60872u, 60872u); -} - - -void testEqualUint8s(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0x22; - v1 = 0x22; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT8(0x22, 0x22); - TEST_ASSERT_EQUAL_UINT8(v0, v1); - TEST_ASSERT_EQUAL_UINT8(0x22, v1); - TEST_ASSERT_EQUAL_UINT8(v0, 0x22); - TEST_ASSERT_EQUAL_UINT8(*p0, v1); - TEST_ASSERT_EQUAL_UINT8(*p0, *p1); - TEST_ASSERT_EQUAL_UINT8(*p0, 0x22); -} - -void testEqualUint8sWhenThereAreDifferencesOutside8Bits(void) -{ - TEST_ASSERT_EQUAL_UINT8(0x321,0x421); - TEST_ASSERT_EQUAL_UINT8(0xFF21,0x0021); -} - -void testEqualUint16s(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 0x9876; - v1 = 0x9876; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT16(0x9876, 0x9876); - TEST_ASSERT_EQUAL_UINT16(v0, v1); - TEST_ASSERT_EQUAL_UINT16(0x9876, v1); - TEST_ASSERT_EQUAL_UINT16(v0, 0x9876); - TEST_ASSERT_EQUAL_UINT16(*p0, v1); - TEST_ASSERT_EQUAL_UINT16(*p0, *p1); - TEST_ASSERT_EQUAL_UINT16(*p0, 0x9876); -} - -void testEqualUint16sWhenThereAreDifferencesOutside16Bits(void) -{ - TEST_ASSERT_EQUAL_UINT16(0x54321,0x64321); - TEST_ASSERT_EQUAL_UINT16(0xFFFF4321,0x00004321); -} - -void testEqualUint32s(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 0x98760000; - v1 = 0x98760000; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT32(0x98760000, 0x98760000); - TEST_ASSERT_EQUAL_UINT32(v0, v1); - TEST_ASSERT_EQUAL_UINT32(0x98760000, v1); - TEST_ASSERT_EQUAL_UINT32(v0, 0x98760000); - TEST_ASSERT_EQUAL_UINT32(*p0, v1); - TEST_ASSERT_EQUAL_UINT32(*p0, *p1); - TEST_ASSERT_EQUAL_UINT32(*p0, 0x98760000); -} - -void testNotEqual(void) -{ - TEST_ASSERT_NOT_EQUAL(0, 1); - TEST_ASSERT_NOT_EQUAL(1, 0); - TEST_ASSERT_NOT_EQUAL(100, 101); - TEST_ASSERT_NOT_EQUAL(0, -1); - TEST_ASSERT_NOT_EQUAL(65535, -65535); - TEST_ASSERT_NOT_EQUAL(75, 900); - TEST_ASSERT_NOT_EQUAL(-100, -101); -} - -void testEqualHex8s(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0x22; - v1 = 0x22; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_HEX8(0x22, 0x22); - TEST_ASSERT_EQUAL_HEX8(v0, v1); - TEST_ASSERT_EQUAL_HEX8(0x22, v1); - TEST_ASSERT_EQUAL_HEX8(v0, 0x22); - TEST_ASSERT_EQUAL_HEX8(*p0, v1); - TEST_ASSERT_EQUAL_HEX8(*p0, *p1); - TEST_ASSERT_EQUAL_HEX8(*p0, 0x22); -} - -void testEqualHex8sWhenThereAreDifferencesOutside8Bits(void) -{ - TEST_ASSERT_EQUAL_HEX8(0x321,0x421); - TEST_ASSERT_EQUAL_HEX8(0xFF21,0x0021); -} - -void testEqualHex8sNegatives(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0xDD; - v1 = 0xDD; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_HEX8(0xDD, 0xDD); - TEST_ASSERT_EQUAL_HEX8(v0, v1); - TEST_ASSERT_EQUAL_HEX8(0xDD, v1); - TEST_ASSERT_EQUAL_HEX8(v0, 0xDD); - TEST_ASSERT_EQUAL_HEX8(*p0, v1); - TEST_ASSERT_EQUAL_HEX8(*p0, *p1); - TEST_ASSERT_EQUAL_HEX8(*p0, 0xDD); -} - -void testEqualHex16s(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 0x9876; - v1 = 0x9876; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_HEX16(0x9876, 0x9876); - TEST_ASSERT_EQUAL_HEX16(v0, v1); - TEST_ASSERT_EQUAL_HEX16(0x9876, v1); - TEST_ASSERT_EQUAL_HEX16(v0, 0x9876); - TEST_ASSERT_EQUAL_HEX16(*p0, v1); - TEST_ASSERT_EQUAL_HEX16(*p0, *p1); - TEST_ASSERT_EQUAL_HEX16(*p0, 0x9876); -} - -void testEqualHex16sWhenThereAreDifferencesOutside16Bits(void) -{ - TEST_ASSERT_EQUAL_HEX16(0x54321,0x64321); - TEST_ASSERT_EQUAL_HEX16(0xFFFF4321,0x00004321); -} - -void testEqualHex32s(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 0x98765432ul; - v1 = 0x98765432ul; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_HEX32(0x98765432ul, 0x98765432ul); - TEST_ASSERT_EQUAL_HEX32(v0, v1); - TEST_ASSERT_EQUAL_HEX32(0x98765432ul, v1); - TEST_ASSERT_EQUAL_HEX32(v0, 0x98765432ul); - TEST_ASSERT_EQUAL_HEX32(*p0, v1); - TEST_ASSERT_EQUAL_HEX32(*p0, *p1); - TEST_ASSERT_EQUAL_HEX32(*p0, 0x98765432ul); -} - -void testEqualBits(void) -{ - UNITY_UINT32 v0 = 0xFF55AA00; - UNITY_UINT32 v1 = 0x55550000; - - TEST_ASSERT_BITS(v1, v0, 0x55550000); - TEST_ASSERT_BITS(v1, v0, 0xFF55CC00); - TEST_ASSERT_BITS(0xFFFFFFFF, v0, 0xFF55AA00); - TEST_ASSERT_BITS(0xFFFFFFFF, v0, v0); - TEST_ASSERT_BITS(0xF0F0F0F0, v0, 0xFC5DAE0F); - TEST_ASSERT_BITS_HIGH(v1, v0); - TEST_ASSERT_BITS_LOW(0x000055FF, v0); - TEST_ASSERT_BIT_HIGH(30, v0); - TEST_ASSERT_BIT_LOW(5, v0); -} - -void testNotEqualBitHigh(void) -{ - UNITY_UINT32 v0 = 0x7F55AA00; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_BIT_HIGH(31, v0); - VERIFY_FAILS_END -} - -void testNotEqualBitLow(void) -{ - UNITY_UINT32 v0 = 0xFF55AA00; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_BIT_LOW(30, v0); - VERIFY_FAILS_END -} - -void testNotEqualBitsHigh(void) -{ - UNITY_UINT32 v0 = 0xFF55AA00; - UNITY_UINT32 v1 = 0x55550000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_BITS_HIGH(v0, v1); - VERIFY_FAILS_END - -} - -void testNotEqualBitsLow(void) -{ - UNITY_UINT32 v0 = 0xFF55AA00; - UNITY_UINT32 v1 = 0x55550000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_BITS_LOW(v0, v1); - VERIFY_FAILS_END -} - - -void testEqualShorts(void) -{ - short v0, v1; - short *p0, *p1; - - v0 = 19467; - v1 = 19467; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT(1837, 1837); - TEST_ASSERT_EQUAL_INT(-2987, -2987); - TEST_ASSERT_EQUAL_INT(v0, v1); - TEST_ASSERT_EQUAL_INT(19467, v1); - TEST_ASSERT_EQUAL_INT(v0, 19467); - TEST_ASSERT_EQUAL_INT(*p0, v1); - TEST_ASSERT_EQUAL_INT(*p0, *p1); - TEST_ASSERT_EQUAL_INT(*p0, 19467); -} - -void testEqualUShorts(void) -{ - unsigned short v0, v1; - unsigned short *p0, *p1; - - v0 = 19467; - v1 = 19467; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT(1837, 1837); - TEST_ASSERT_EQUAL_UINT(2987, 2987); - TEST_ASSERT_EQUAL_UINT(v0, v1); - TEST_ASSERT_EQUAL_UINT(19467, v1); - TEST_ASSERT_EQUAL_UINT(v0, 19467); - TEST_ASSERT_EQUAL_UINT(*p0, v1); - TEST_ASSERT_EQUAL_UINT(*p0, *p1); - TEST_ASSERT_EQUAL_UINT(*p0, 19467); -} - -void testEqualChars(void) -{ - signed char v0, v1; - signed char *p0, *p1; - - v0 = 109; - v1 = 109; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT(42, 42); - TEST_ASSERT_EQUAL_INT(-116, -116); - TEST_ASSERT_EQUAL_INT(v0, v1); - TEST_ASSERT_EQUAL_INT(109, v1); - TEST_ASSERT_EQUAL_INT(v0, 109); - TEST_ASSERT_EQUAL_INT(*p0, v1); - TEST_ASSERT_EQUAL_INT(*p0, *p1); - TEST_ASSERT_EQUAL_INT(*p0, 109); -} - -void testEqualUChars(void) -{ - unsigned char v0, v1; - unsigned char *p0, *p1; - - v0 = 251; - v1 = 251; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT(42, 42); - TEST_ASSERT_EQUAL_INT(v0, v1); - TEST_ASSERT_EQUAL_INT(251, v1); - TEST_ASSERT_EQUAL_INT(v0, 251); - TEST_ASSERT_EQUAL_INT(*p0, v1); - TEST_ASSERT_EQUAL_INT(*p0, *p1); - TEST_ASSERT_EQUAL_INT(*p0, 251); -} - -void testEqualPointers(void) -{ - int v0, v1; - int *p0, *p1, *p2; - - v0 = 19467; - v1 = 18271; - p0 = &v0; - p1 = &v1; - p2 = &v1; - - TEST_ASSERT_EQUAL_PTR(p0, &v0); - TEST_ASSERT_EQUAL_PTR(&v1, p1); - TEST_ASSERT_EQUAL_PTR(p2, p1); - TEST_ASSERT_EQUAL_PTR(&v0, &v0); -} - -void testNotEqualPointers(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR(0x12345678, 0x12345677); - VERIFY_FAILS_END -} - -void testIntsWithinDelta(void) -{ - TEST_ASSERT_INT_WITHIN(1, 5000, 5001); - TEST_ASSERT_INT_WITHIN(5, 5000, 4996); - TEST_ASSERT_INT_WITHIN(5, 5000, 5005); - TEST_ASSERT_INT_WITHIN(500, 50, -440); - - TEST_ASSERT_INT_WITHIN(2, -1, -1); - TEST_ASSERT_INT_WITHIN(5, 1, -1); - TEST_ASSERT_INT_WITHIN(5, -1, 1); -} - -void testIntsWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_INT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); - TEST_ASSERT_INT_WITHIN_MESSAGE(500, 50, -440, "Custom Message."); - - TEST_ASSERT_INT_WITHIN_MESSAGE(2, -1, -1, "Custom Message."); - TEST_ASSERT_INT_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); - TEST_ASSERT_INT_WITHIN_MESSAGE(5, -1, 1, "Custom Message."); -} - -void testIntsNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT_WITHIN(5, 5000, 5006); - VERIFY_FAILS_END -} - -void testIntsNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5006, "Custom Message."); - VERIFY_FAILS_END -} - -void testUIntsWithinDelta(void) -{ - TEST_ASSERT_UINT_WITHIN(1, 5000, 5001); - TEST_ASSERT_UINT_WITHIN(5, 5000, 4996); - TEST_ASSERT_UINT_WITHIN(5, 5000, 5005); -} - -void testUIntsWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); -} - -void testUIntsNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN(1, 2147483647u, 2147483649u); - VERIFY_FAILS_END -} - -void testUIntsNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); - VERIFY_FAILS_END -} - -void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirst(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN(5, 1, -1); - VERIFY_FAILS_END -} - -void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirstAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); - VERIFY_FAILS_END -} - -void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirst(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN(5, -1, 1); - VERIFY_FAILS_END -} - -void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirstAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT_WITHIN_MESSAGE(5, -1, 1, "Custom Message."); - VERIFY_FAILS_END -} - -void testHEX32sWithinDelta(void) -{ - TEST_ASSERT_HEX32_WITHIN(1, 5000, 5001); - TEST_ASSERT_HEX32_WITHIN(5, 5000, 4996); - TEST_ASSERT_HEX32_WITHIN(5, 5000, 5005); -} - -void testHEX32sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); -} - -void testHEX32sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX32_WITHIN(1, 2147483647u, 2147483649u); - VERIFY_FAILS_END -} - -void testHEX32sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); - VERIFY_FAILS_END -} - -void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPass(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX32_WITHIN(5, 1, -1); - VERIFY_FAILS_END -} - -void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); - VERIFY_FAILS_END -} - -void testHEX16sWithinDelta(void) -{ - TEST_ASSERT_HEX16_WITHIN(1, 5000, 5001); - TEST_ASSERT_HEX16_WITHIN(5, 5000, 4996); - TEST_ASSERT_HEX16_WITHIN(5, 5000, 5005); -} - -void testHEX16sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_HEX16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); -} - -void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) -{ - TEST_ASSERT_HEX16_WITHIN(5, 0x54321, 0x44321); -} - -void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) -{ - TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); -} - -void testHEX16sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX16_WITHIN(2, 65535, 0); - VERIFY_FAILS_END -} - -void testHEX16sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message."); - VERIFY_FAILS_END -} - -void testHEX8sWithinDelta(void) -{ - TEST_ASSERT_HEX8_WITHIN(1, 254, 255); - TEST_ASSERT_HEX8_WITHIN(5, 251, 255); - TEST_ASSERT_HEX8_WITHIN(5, 1, 4); -} - -void testHEX8sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_HEX8_WITHIN_MESSAGE(1, 254, 255, "Custom Message."); - TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 251, 255, "Custom Message."); - TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); -} - -void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) -{ - TEST_ASSERT_HEX8_WITHIN(5, 0x123, 0xF23); -} - -void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) -{ - TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); -} - -void testHEX8sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX8_WITHIN(2, 255, 0); - VERIFY_FAILS_END -} - -void testHEX8sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX8_WITHIN_MESSAGE(2, 255, 0, "Custom Message."); - VERIFY_FAILS_END -} - -//----------------- - -void testUINT32sWithinDelta(void) -{ - TEST_ASSERT_UINT32_WITHIN(1, 5000, 5001); - TEST_ASSERT_UINT32_WITHIN(5, 5000, 4996); - TEST_ASSERT_UINT32_WITHIN(5, 5000, 5005); -} - -void testUINT32sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); -} - -void testUINT32sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT32_WITHIN(1, 2147483647u, 2147483649u); - VERIFY_FAILS_END -} - -void testUINT32sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); - VERIFY_FAILS_END -} - -void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPass(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT32_WITHIN(5, 1, -1); - VERIFY_FAILS_END -} - -void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); - VERIFY_FAILS_END -} - -void testUINT16sWithinDelta(void) -{ - TEST_ASSERT_UINT16_WITHIN(1, 5000, 5001); - TEST_ASSERT_UINT16_WITHIN(5, 5000, 4996); - TEST_ASSERT_UINT16_WITHIN(5, 5000, 5005); -} - -void testUINT16sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_UINT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); - TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); - TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); -} - -void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) -{ - TEST_ASSERT_UINT16_WITHIN(5, 0x54321, 0x44321); -} - -void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) -{ - TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); -} - -void testUINT16sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT16_WITHIN(2, 65535, 0); - VERIFY_FAILS_END -} - -void testUINT16sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message."); - VERIFY_FAILS_END -} - -void testUINT8sWithinDelta(void) -{ - TEST_ASSERT_UINT8_WITHIN(1, 254, 255); - TEST_ASSERT_UINT8_WITHIN(5, 251, 255); - TEST_ASSERT_UINT8_WITHIN(5, 1, 4); -} - -void testUINT8sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_UINT8_WITHIN_MESSAGE(1, 254, 255, "Custom Message."); - TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 251, 255, "Custom Message."); - TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); -} - -void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) -{ - TEST_ASSERT_UINT8_WITHIN(5, 0x123, 0xF23); -} - -void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) -{ - TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); -} - -void testUINT8sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT8_WITHIN(2, 255, 0); - VERIFY_FAILS_END -} - -void testUINT8sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT8_WITHIN_MESSAGE(2, 255, 0, "Custom Message."); - VERIFY_FAILS_END -} - -void testINT32sWithinDelta(void) -{ - TEST_ASSERT_INT32_WITHIN(1, 5000, 5001); - TEST_ASSERT_INT32_WITHIN(5, 1, -2); - TEST_ASSERT_INT32_WITHIN(5, -2, 1); -} - -void testINT32sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_INT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); -} - -void testINT32sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT32_WITHIN(1, -3, 1); - VERIFY_FAILS_END -} - -void testINT32sNotWithinDeltaAndDifferenceOverflows(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT32_WITHIN(1, -1, 0x7FFFFFFF); - VERIFY_FAILS_END -} -void testINT32sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT32_WITHIN_MESSAGE(1, -2, 1, "Custom Message."); - VERIFY_FAILS_END -} - -void testINT16sWithinDelta(void) -{ - TEST_ASSERT_INT16_WITHIN(1, 5000, 5001); - TEST_ASSERT_INT16_WITHIN(5, 2, -2); - TEST_ASSERT_INT16_WITHIN(5, -2, 2); -} - -void testINT16sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_INT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); -} - -void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) -{ - TEST_ASSERT_INT16_WITHIN(5, 0x54321, 0x44321); -} - -void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) -{ - TEST_ASSERT_INT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); -} - -void testINT16sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT16_WITHIN(2, 4, -2); - VERIFY_FAILS_END -} - -void testINT16sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT16_WITHIN_MESSAGE(2, 3, 0, "Custom Message."); - VERIFY_FAILS_END -} - -void testINT8sWithinDelta(void) -{ - TEST_ASSERT_INT8_WITHIN(1, 127, 126); - TEST_ASSERT_INT8_WITHIN(5, -2, 2); - TEST_ASSERT_INT8_WITHIN(5, 2, -2); -} - -void testINT8sWithinDeltaAndCustomMessage(void) -{ - TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); -} - -void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) -{ - TEST_ASSERT_INT8_WITHIN(5, 0x123, 0xF23); -} - -void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) -{ - TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); -} - -void testINT8sNotWithinDelta(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT8_WITHIN(2, -3, 0); - VERIFY_FAILS_END -} - -void testINT8sNotWithinDeltaAndCustomMessage(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT8_WITHIN_MESSAGE(2, -4, 0, "Custom Message."); - VERIFY_FAILS_END -} - - -//----------------- -void testGreaterThan(void) -{ - UNITY_INT v0, v1; - UNITY_INT *p0, *p1; - - v0 = 0; - v1 = 1; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN(v0, v1); - TEST_ASSERT_GREATER_THAN(*p0, v1); - TEST_ASSERT_GREATER_THAN(v0, *p1); - TEST_ASSERT_GREATER_THAN(*p0, *p1); -} - -void testGreaterThanINT(void) -{ - UNITY_INT v0, v1; - UNITY_INT *p0, *p1; - - v0 = 302; - v1 = 3334; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_INT(v0, v1); - TEST_ASSERT_GREATER_THAN_INT(*p0, v1); - TEST_ASSERT_GREATER_THAN_INT(v0, *p1); - TEST_ASSERT_GREATER_THAN_INT(*p0, *p1); -} - - -void testGreaterThanINT8(void) -{ - UNITY_INT8 v0, v1; - UNITY_INT8 *p0, *p1; - - v0 = -128; - v1 = 127; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_INT8(v0, v1); - TEST_ASSERT_GREATER_THAN_INT8(*p0, v1); - TEST_ASSERT_GREATER_THAN_INT8(v0, *p1); - TEST_ASSERT_GREATER_THAN_INT8(*p0, *p1); -} - -void testGreaterThanINT16(void) -{ - UNITY_INT16 v0, v1; - UNITY_INT16 *p0, *p1; - - v0 = -32768; - v1 = 32767; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_INT16(v0, v1); - TEST_ASSERT_GREATER_THAN_INT16(*p0, v1); - TEST_ASSERT_GREATER_THAN_INT16(v0, *p1); - TEST_ASSERT_GREATER_THAN_INT16(*p0, *p1); -} - -void testGreaterThanINT32(void) -{ - UNITY_INT32 v0, v1; - UNITY_INT32 *p0, *p1; - - v0 = -214783648; - v1 = 214783647; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_INT32(v0, v1); - TEST_ASSERT_GREATER_THAN_INT32(*p0, v1); - TEST_ASSERT_GREATER_THAN_INT32(v0, *p1); - TEST_ASSERT_GREATER_THAN_INT32(*p0, *p1); -} - -void testGreaterThanUINT(void) -{ - UNITY_UINT v0, v1; - UNITY_UINT *p0, *p1; - - v0 = 0; - v1 = 1; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_UINT(v0, v1); - TEST_ASSERT_GREATER_THAN_UINT(*p0, v1); - TEST_ASSERT_GREATER_THAN_UINT(v0, *p1); - TEST_ASSERT_GREATER_THAN_UINT(*p0, *p1); -} - - -void testGreaterThanUINT8(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0; - v1 = 255; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_UINT8(v0, v1); - TEST_ASSERT_GREATER_THAN_UINT8(*p0, v1); - TEST_ASSERT_GREATER_THAN_UINT8(v0, *p1); - TEST_ASSERT_GREATER_THAN_UINT8(*p0, *p1); -} - -void testGreaterThanUINT16(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 0; - v1 = 65535; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_UINT16(v0, v1); - TEST_ASSERT_GREATER_THAN_UINT16(*p0, v1); - TEST_ASSERT_GREATER_THAN_UINT16(v0, *p1); - TEST_ASSERT_GREATER_THAN_UINT16(*p0, *p1); -} - -void testGreaterThanUINT32(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 0; - v1 = 4294967295; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_UINT32(v0, v1); - TEST_ASSERT_GREATER_THAN_UINT32(*p0, v1); - TEST_ASSERT_GREATER_THAN_UINT32(v0, *p1); - TEST_ASSERT_GREATER_THAN_UINT32(*p0, *p1); -} - -void testGreaterThanHEX8(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0x00; - v1 = 0xFF; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_HEX8(v0, v1); - TEST_ASSERT_GREATER_THAN_HEX8(*p0, v1); - TEST_ASSERT_GREATER_THAN_HEX8(v0, *p1); - TEST_ASSERT_GREATER_THAN_HEX8(*p0, *p1); -} - -void testGreaterThanHEX16(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 0x0000; - v1 = 0xFFFF; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_HEX16(v0, v1); - TEST_ASSERT_GREATER_THAN_HEX16(*p0, v1); - TEST_ASSERT_GREATER_THAN_HEX16(v0, *p1); - TEST_ASSERT_GREATER_THAN_HEX16(*p0, *p1); -} - -void testGreaterThanHEX32(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 0x00000000; - v1 = 0xFFFFFFFF; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_GREATER_THAN_HEX32(v0, v1); - TEST_ASSERT_GREATER_THAN_HEX32(*p0, v1); - TEST_ASSERT_GREATER_THAN_HEX32(v0, *p1); - TEST_ASSERT_GREATER_THAN_HEX32(*p0, *p1); -} - - -void testNotGreaterThan(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_GREATER_THAN(0, -1); - VERIFY_FAILS_END -} - -void testLessThan(void) -{ - UNITY_INT v0, v1; - UNITY_INT *p0, *p1; - - v0 = 0; - v1 = -1; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN(v0, v1); - TEST_ASSERT_LESS_THAN(*p0, v1); - TEST_ASSERT_LESS_THAN(v0, *p1); - TEST_ASSERT_LESS_THAN(*p0, *p1); -} - -void testLessThanINT(void) -{ - UNITY_INT v0, v1; - UNITY_INT *p0, *p1; - - v0 = 3334; - v1 = 302; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_INT(v0, v1); - TEST_ASSERT_LESS_THAN_INT(*p0, v1); - TEST_ASSERT_LESS_THAN_INT(v0, *p1); - TEST_ASSERT_LESS_THAN_INT(*p0, *p1); -} - - -void testLessThanINT8(void) -{ - UNITY_INT8 v0, v1; - UNITY_INT8 *p0, *p1; - - v0 = 127; - v1 = -128; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_INT8(v0, v1); - TEST_ASSERT_LESS_THAN_INT8(*p0, v1); - TEST_ASSERT_LESS_THAN_INT8(v0, *p1); - TEST_ASSERT_LESS_THAN_INT8(*p0, *p1); -} - -void testLessThanINT16(void) -{ - UNITY_INT16 v0, v1; - UNITY_INT16 *p0, *p1; - - v0 = 32767; - v1 = -32768; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_INT16(v0, v1); - TEST_ASSERT_LESS_THAN_INT16(*p0, v1); - TEST_ASSERT_LESS_THAN_INT16(v0, *p1); - TEST_ASSERT_LESS_THAN_INT16(*p0, *p1); -} - -void testLessThanINT32(void) -{ - UNITY_INT32 v0, v1; - UNITY_INT32 *p0, *p1; - - v0 = 214783647; - v1 = -214783648; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_INT32(v0, v1); - TEST_ASSERT_LESS_THAN_INT32(*p0, v1); - TEST_ASSERT_LESS_THAN_INT32(v0, *p1); - TEST_ASSERT_LESS_THAN_INT32(*p0, *p1); -} - -void testLessThanUINT(void) -{ - UNITY_UINT v0, v1; - UNITY_UINT *p0, *p1; - - v0 = 1; - v1 = 0; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_UINT(v0, v1); - TEST_ASSERT_LESS_THAN_UINT(*p0, v1); - TEST_ASSERT_LESS_THAN_UINT(v0, *p1); - TEST_ASSERT_LESS_THAN_UINT(*p0, *p1); -} - - -void testLessThanUINT8(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 255; - v1 = 0; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_UINT8(v0, v1); - TEST_ASSERT_LESS_THAN_UINT8(*p0, v1); - TEST_ASSERT_LESS_THAN_UINT8(v0, *p1); - TEST_ASSERT_LESS_THAN_UINT8(*p0, *p1); -} - -void testLessThanUINT16(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 65535; - v1 = 0; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_UINT16(v0, v1); - TEST_ASSERT_LESS_THAN_UINT16(*p0, v1); - TEST_ASSERT_LESS_THAN_UINT16(v0, *p1); - TEST_ASSERT_LESS_THAN_UINT16(*p0, *p1); -} - -void testLessThanUINT32(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 4294967295; - v1 = 0; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_UINT32(v0, v1); - TEST_ASSERT_LESS_THAN_UINT32(*p0, v1); - TEST_ASSERT_LESS_THAN_UINT32(v0, *p1); - TEST_ASSERT_LESS_THAN_UINT32(*p0, *p1); -} - -void testLessThanHEX8(void) -{ - UNITY_UINT8 v0, v1; - UNITY_UINT8 *p0, *p1; - - v0 = 0xFF; - v1 = 0x00; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_HEX8(v0, v1); - TEST_ASSERT_LESS_THAN_HEX8(*p0, v1); - TEST_ASSERT_LESS_THAN_HEX8(v0, *p1); - TEST_ASSERT_LESS_THAN_HEX8(*p0, *p1); -} - -void testLessThanHEX16(void) -{ - UNITY_UINT16 v0, v1; - UNITY_UINT16 *p0, *p1; - - v0 = 0xFFFF; - v1 = 0x0000; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_HEX16(v0, v1); - TEST_ASSERT_LESS_THAN_HEX16(*p0, v1); - TEST_ASSERT_LESS_THAN_HEX16(v0, *p1); - TEST_ASSERT_LESS_THAN_HEX16(*p0, *p1); -} - -void testLessThanHEX32(void) -{ - UNITY_UINT32 v0, v1; - UNITY_UINT32 *p0, *p1; - - v0 = 0xFFFFFFFF; - v1 = 0x00000000; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_LESS_THAN_HEX32(v0, v1); - TEST_ASSERT_LESS_THAN_HEX32(*p0, v1); - TEST_ASSERT_LESS_THAN_HEX32(v0, *p1); - TEST_ASSERT_LESS_THAN_HEX32(*p0, *p1); -} - - -void testNotLessThan(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_LESS_THAN(0, 1); - VERIFY_FAILS_END -} - - - -//----------------- -void testEqualStrings(void) -{ - const char *testString = "foo"; - - TEST_ASSERT_EQUAL_STRING(testString, testString); - TEST_ASSERT_EQUAL_STRING_MESSAGE("foo", "foo", "foo isn't foo"); - TEST_ASSERT_EQUAL_STRING("foo", testString); - TEST_ASSERT_EQUAL_STRING(testString, "foo"); - TEST_ASSERT_EQUAL_STRING("", ""); -} - -void testEqualStringsLen(void) -{ - const char *testString = "foobar"; - TEST_ASSERT_EQUAL_STRING_LEN(testString, testString, strlen(testString)); - TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE("foobar", "foobaz", 5, "fooba isn't fooba"); - TEST_ASSERT_EQUAL_STRING_LEN("foo", testString, 3); - TEST_ASSERT_EQUAL_STRING_LEN(testString, "foo", 3); - TEST_ASSERT_EQUAL_STRING_LEN("", "", 3); -} - -void testEqualStringsWithCarriageReturnsAndLineFeeds(void) -{ - const char *testString = "foo\r\nbar"; - - TEST_ASSERT_EQUAL_STRING(testString, testString); - TEST_ASSERT_EQUAL_STRING("foo\r\nbar", "foo\r\nbar"); - TEST_ASSERT_EQUAL_STRING("foo\r\nbar", testString); - TEST_ASSERT_EQUAL_STRING(testString, "foo\r\nbar"); - TEST_ASSERT_EQUAL_STRING("", ""); -} - -void testNotEqualString1(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING("foo", "bar"); - VERIFY_FAILS_END -} - -void testNotEqualStringLen1(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN("foobar", "foobaz", 6); - VERIFY_FAILS_END -} - -void testNotEqualString2(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING("foo", ""); - VERIFY_FAILS_END -} - -void testNotEqualStringLen2(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN("foo", "", 3); - VERIFY_FAILS_END -} - -void testNotEqualString3(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING("", "bar"); - VERIFY_FAILS_END -} - -void testNotEqualStringLen3(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN("", "bar", 3); - VERIFY_FAILS_END -} - -void testNotEqualString4(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING("bar\r", "bar\n"); - VERIFY_FAILS_END -} - -void testNotEqualStringLen4(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN("ba\r\x16", "ba\r\n", 4); - VERIFY_FAILS_END -} - -void testNotEqualString5(void) -{ - const char str1[] = { 0x41, 0x42, 0x03, 0x00 }; - const char str2[] = { 0x41, 0x42, 0x04, 0x00 }; - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING(str1, str2); - VERIFY_FAILS_END -} - -void testNotEqualString_ExpectedStringIsNull(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING(NULL, "bar"); - VERIFY_FAILS_END -} - -void testNotEqualStringLen_ExpectedStringIsNull(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN(NULL, "bar", 1); - VERIFY_FAILS_END -} - -void testNotEqualString_ActualStringIsNull(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING("foo", NULL); - VERIFY_FAILS_END -} - -void testNotEqualStringLen_ActualStringIsNull(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_LEN("foo", NULL, 1); - VERIFY_FAILS_END -} - -void testEqualStringArrays(void) -{ - const char *testStrings[] = { "foo", "boo", "woo", "moo" }; - const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; - - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, expStrings, 3); - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 3); - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 2); - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 1); -} - -void testNotEqualStringArray1(void) -{ - const char *testStrings[] = { "foo", "boo", "woo", "moo" }; - const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringArray2(void) -{ - const char *testStrings[] = { "zoo", "boo", "woo", "moo" }; - const char *expStrings[] = { "foo", "boo", "woo", "moo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringArray3(void) -{ - const char *testStrings[] = { "foo", "boo", "woo", NULL }; - const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringArray4(void) -{ - const char *testStrings[] = { "foo", "boo", "woo", "moo" }; - const char *expStrings[] = { "foo", NULL, "woo", "moo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringArray5(void) -{ - const char **testStrings = NULL; - const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringArray6(void) -{ - const char *testStrings[] = { "foo", "boo", "woo", "zoo" }; - const char **expStrings = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); - VERIFY_FAILS_END -} - -void testEqualStringArrayIfBothNulls(void) -{ - const char **testStrings = NULL; - const char **expStrings = NULL; - - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); -} - -void testNotEqualStringArrayLengthZero(void) -{ - const char *testStrings[] = {NULL}; - const char **expStrings = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 0); - VERIFY_FAILS_END -} - -void testEqualStringEachEqual(void) -{ - const char *testStrings1[] = { "foo", "foo", "foo", "foo" }; - const char *testStrings2[] = { "boo", "boo", "boo", "zoo" }; - const char *testStrings3[] = { "", "", "", "" }; - - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 4); - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 1); - TEST_ASSERT_EACH_EQUAL_STRING("boo", testStrings2, 3); - TEST_ASSERT_EACH_EQUAL_STRING("", testStrings3, 4); -} - -void testNotEqualStringEachEqual1(void) -{ - const char *testStrings[] = { "foo", "foo", "foo", "moo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringEachEqual2(void) -{ - const char *testStrings[] = { "boo", "foo", "foo", "foo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringEachEqual3(void) -{ - const char *testStrings[] = { "foo", "foo", "foo", NULL }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringEachEqual4(void) -{ - const char *testStrings[] = { "foo", "foo", "woo", "foo" }; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); - VERIFY_FAILS_END -} - -void testNotEqualStringEachEqual5(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_STRING("foo", NULL, 1); - VERIFY_FAILS_END -} - -void testEqualMemory(void) -{ - const char *testString = "whatever"; - - TEST_ASSERT_EQUAL_MEMORY(testString, testString, 8); - TEST_ASSERT_EQUAL_MEMORY("whatever", "whatever", 8); - TEST_ASSERT_EQUAL_MEMORY("whatever", testString, 8); - TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 8); - TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 2); - TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 1); -} - -void testNotEqualMemory1(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY("foo", "bar", 3); - VERIFY_FAILS_END -} - -void testNotEqualMemory2(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY("fool", "food", 4); - VERIFY_FAILS_END -} - -void testNotEqualMemory3(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY(NULL, "food", 4); - VERIFY_FAILS_END -} - -void testNotEqualMemory4(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY("fool", NULL, 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryLengthZero(void) -{ - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 0); - VERIFY_FAILS_END -} - -void testEqualIntArrays(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, -2}; - int p2[] = {1, 8, 987, 2}; - int p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p3, 1); - TEST_ASSERT_EQUAL_INT_ARRAY(NULL, NULL, 1); -} - -void testNotEqualIntArraysNullExpected(void) -{ - int* p0 = NULL; - int p1[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntArraysNullActual(void) -{ - int* p1 = NULL; - int p0[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntArrays1(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntArrays2(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {2, 8, 987, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntArrays3(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 986, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntArraysLengthZero(void) -{ - UNITY_UINT32 p0[1] = {1}; - UNITY_UINT32 p1[1] = {1}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 0); - VERIFY_FAILS_END -} - -void testEqualIntEachEqual(void) -{ - int p0[] = {1, 1, 1, 1}; - int p1[] = {987, 987, 987, 987}; - int p2[] = {-2, -2, -2, -3}; - int p3[] = {1, 5, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_INT(1, p0, 1); - TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); - TEST_ASSERT_EACH_EQUAL_INT(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_INT(-2, p2, 3); - TEST_ASSERT_EACH_EQUAL_INT(1, p3, 1); -} - -void testNotEqualIntEachEqualNullActual(void) -{ - int* p1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT(1, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntEachEqual1(void) -{ - int p0[] = {1, 1, 1, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntEachEqual2(void) -{ - int p0[] = {-5, -5, -1, -5}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT(-5, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualIntEachEqual3(void) -{ - int p0[] = {1, 88, 88, 88}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT(88, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualEachEqualLengthZero(void) -{ - UNITY_UINT32 p0[1] = {1}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT(0, p0, 0); - VERIFY_FAILS_END -} - -void testEqualPtrArrays(void) -{ - char A = 1; - char B = 2; - char C = 3; - char* p0[] = {&A, &B, &C}; - char* p1[] = {&A, &B, &C, &A}; - char* p2[] = {&A, &B}; - char* p3[] = {&A}; - - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 3); - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 3); - TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p2, 2); - TEST_ASSERT_EQUAL_PTR_ARRAY(p3, p0, 1); -} - -void testNotEqualPtrArraysNullExpected(void) -{ - char A = 1; - char B = 2; - char** p0 = NULL; - char* p1[] = {&A, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 2); - VERIFY_FAILS_END -} - -void testNotEqualPtrArraysNullActual(void) -{ - char A = 1; - char B = 2; - char** p0 = NULL; - char* p1[] = {&A, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p0, 2); - VERIFY_FAILS_END -} - -void testNotEqualPtrArrays1(void) -{ - char A = 1; - char B = 2; - char C = 3; - char* p0[] = {&A, &B, &C, &B}; - char* p1[] = {&A, &B, &C, &A}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualPtrArrays2(void) -{ - char A = 1; - char B = 2; - char C = 3; - char* p0[] = {&B, &B, &C, &A}; - char* p1[] = {&A, &B, &C, &A}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualPtrArrays3(void) -{ - char A = 1; - char B = 2; - char C = 3; - char* p0[] = {&A, &B, &B, &A}; - char* p1[] = {&A, &B, &C, &A}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualPtrEachEqual(void) -{ - char A = 1; - char B = 2; - char C = 3; - char* p0[] = {&A, &A, &A}; - char* p1[] = {&A, &B, &C, &A}; - char* p2[] = {&B, &B}; - char* p3[] = {&C}; - - TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 1); - TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 3); - TEST_ASSERT_EACH_EQUAL_PTR(&A, p1, 1); - TEST_ASSERT_EACH_EQUAL_PTR(&B, p2, 2); - TEST_ASSERT_EACH_EQUAL_PTR(&C, p3, 1); -} - -void testNotEqualPtrEachEqualNullExpected(void) -{ - char A = 1; - char B = 1; - char* p0[] = {&A, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); - VERIFY_FAILS_END -} - -void testNotEqualPtrEachEqualNullActual(void) -{ - char A = 1; - char** p0 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); - VERIFY_FAILS_END -} - -void testNotEqualPtrEachEqual1(void) -{ - char A = 1; - char B = 1; - char* p0[] = {&A, &A, &A, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualPtrEachEqual2(void) -{ - char A = 1; - char B = 1; - char* p0[] = {&B, &B, &A, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualPtrEachEqual3(void) -{ - char A = 1; - char B = 1; - char* p0[] = {&A, &B, &B, &B}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); - VERIFY_FAILS_END -} - -void testEqualInt8Arrays(void) -{ - UNITY_INT8 p0[] = {1, 8, 117, -2}; - UNITY_INT8 p1[] = {1, 8, 117, -2}; - UNITY_INT8 p2[] = {1, 8, 117, 2}; - UNITY_INT8 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p3, 1); -} - -void testNotEqualInt8Arrays(void) -{ - UNITY_INT8 p0[] = {1, 8, 36, -2}; - UNITY_INT8 p1[] = {1, 8, 36, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualInt8EachEqual(void) -{ - UNITY_INT8 p0[] = {1, 1, 1, 1}; - UNITY_INT8 p1[] = {117, 117, 117, -2}; - UNITY_INT8 p2[] = {-1, -1, 117, 2}; - UNITY_INT8 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 1); - TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 4); - TEST_ASSERT_EACH_EQUAL_INT8(117, p1, 3); - TEST_ASSERT_EACH_EQUAL_INT8(-1, p2, 2); - TEST_ASSERT_EACH_EQUAL_INT8(1, p3, 1); -} - -void testNotEqualInt8EachEqual(void) -{ - UNITY_INT8 p0[] = {1, 8, 36, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 2); - VERIFY_FAILS_END -} - -void testEqualUIntArrays(void) -{ - unsigned int p0[] = {1, 8, 987, 65132u}; - unsigned int p1[] = {1, 8, 987, 65132u}; - unsigned int p2[] = {1, 8, 987, 2}; - unsigned int p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p3, 1); -} - -void testNotEqualUIntArrays1(void) -{ - unsigned int p0[] = {1, 8, 987, 65132u}; - unsigned int p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUIntArrays2(void) -{ - unsigned int p0[] = {1, 8, 987, 65132u}; - unsigned int p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUIntArrays3(void) -{ - unsigned int p0[] = {1, 8, 987, 65132u}; - unsigned int p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualUIntEachEqual(void) -{ - unsigned int p0[] = {1, 1, 1, 1}; - unsigned int p1[] = {65132u, 65132u, 65132u, 65132u}; - unsigned int p2[] = {8, 8, 987, 2}; - unsigned int p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 1); - TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); - TEST_ASSERT_EACH_EQUAL_UINT(65132u, p1, 4); - TEST_ASSERT_EACH_EQUAL_UINT(8, p2, 2); - TEST_ASSERT_EACH_EQUAL_UINT(1, p3, 1); -} - -void testNotEqualUIntEachEqual1(void) -{ - unsigned int p0[] = {1, 65132u, 65132u, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUIntEachEqual2(void) -{ - unsigned int p0[] = {987, 8, 987, 987}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT(987, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUIntEachEqual3(void) -{ - unsigned int p0[] = {1, 1, 1, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); - VERIFY_FAILS_END -} - -void testEqualInt16Arrays(void) -{ - UNITY_INT16 p0[] = {1, 8, 117, 3}; - UNITY_INT16 p1[] = {1, 8, 117, 3}; - UNITY_INT16 p2[] = {1, 8, 117, 2}; - UNITY_INT16 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p3, 1); -} - -void testNotEqualInt16Arrays(void) -{ - UNITY_INT16 p0[] = {1, 8, 127, 3}; - UNITY_INT16 p1[] = {1, 8, 127, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualInt16EachEqual(void) -{ - UNITY_INT16 p0[] = {1, 1, 1, 1}; - UNITY_INT16 p1[] = {32111, 32111, 32111, 3}; - UNITY_INT16 p2[] = {-1, -1, -1, 2}; - UNITY_INT16 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 1); - TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 4); - TEST_ASSERT_EACH_EQUAL_INT16(32111, p1, 3); - TEST_ASSERT_EACH_EQUAL_INT16(-1, p2, 3); - TEST_ASSERT_EACH_EQUAL_INT16(1, p3, 1); -} - -void testNotEqualInt16EachEqual(void) -{ - UNITY_INT16 p0[] = {127, 127, 127, 3}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT16(127, p0, 4); - VERIFY_FAILS_END -} - -void testEqualInt32Arrays(void) -{ - UNITY_INT32 p0[] = {1, 8, 117, 3}; - UNITY_INT32 p1[] = {1, 8, 117, 3}; - UNITY_INT32 p2[] = {1, 8, 117, 2}; - UNITY_INT32 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p3, 1); -} - -void testNotEqualInt32Arrays(void) -{ - UNITY_INT32 p0[] = {1, 8, 127, 3}; - UNITY_INT32 p1[] = {1, 8, 127, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualInt32EachEqual(void) -{ - UNITY_INT32 p0[] = {8, 8, 8, 8}; - UNITY_INT32 p1[] = {65537, 65537, 65537, 65537}; - UNITY_INT32 p2[] = {-3, -3, -3, 2}; - UNITY_INT32 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 1); - TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 4); - TEST_ASSERT_EACH_EQUAL_INT32(65537, p1, 4); - TEST_ASSERT_EACH_EQUAL_INT32(-3, p2, 3); - TEST_ASSERT_EACH_EQUAL_INT32(1, p3, 1); -} - -void testNotEqualInt32EachEqual(void) -{ - UNITY_INT32 p0[] = {127, 8, 127, 127}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_INT32(127, p0, 4); - VERIFY_FAILS_END -} - -void testEqualUINT8Arrays(void) -{ - UNITY_UINT8 p0[] = {1, 8, 100, 127}; - UNITY_UINT8 p1[] = {1, 8, 100, 127}; - UNITY_UINT8 p2[] = {1, 8, 100, 2}; - UNITY_UINT8 p3[] = {1, 50, 60, 70}; - - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p3, 1); -} - -void testNotEqualUINT8Arrays1(void) -{ - unsigned char p0[] = {1, 8, 100, 127u}; - unsigned char p1[] = {1, 8, 100, 255u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT8Arrays2(void) -{ - unsigned char p0[] = {1, 8, 100, 127u}; - unsigned char p1[] = {1, 8, 100, 255u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT8Arrays3(void) -{ - unsigned char p0[] = {1, 8, 100, 127u}; - unsigned char p1[] = {1, 8, 100, 255u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - - -void testEqualUINT16Arrays(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 987, 65132u}; - unsigned short p2[] = {1, 8, 987, 2}; - unsigned short p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p3, 1); -} - -void testNotEqualUINT16Arrays1(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT16Arrays2(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT16Arrays3(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualUINT32Arrays(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p2[] = {1, 8, 987, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p3, 1); -} - -void testNotEqualUINT32Arrays1(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT32Arrays2(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT32Arrays3(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualHEXArrays(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p2[] = {1, 8, 987, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1); -} - -void testNotEqualHEXArrays1(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEXArrays2(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEXArrays3(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualHEX32Arrays(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p2[] = {1, 8, 987, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1); -} - -void testNotEqualHEX32Arrays1(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX32Arrays2(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX32Arrays3(void) -{ - UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualHEX16Arrays(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 987, 65132u}; - unsigned short p2[] = {1, 8, 987, 2}; - unsigned short p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p3, 1); -} - -void testNotEqualHEX16Arrays1(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX16Arrays2(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX16Arrays3(void) -{ - unsigned short p0[] = {1, 8, 987, 65132u}; - unsigned short p1[] = {1, 8, 986, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualHEX8Arrays(void) -{ - unsigned char p0[] = {1, 8, 254u, 123}; - unsigned char p1[] = {1, 8, 254u, 123}; - unsigned char p2[] = {1, 8, 254u, 2}; - unsigned char p3[] = {1, 23, 25, 26}; - - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p3, 1); -} - -void testNotEqualHEX8Arrays1(void) -{ - unsigned char p0[] = {1, 8, 254u, 253u}; - unsigned char p1[] = {1, 8, 254u, 252u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX8Arrays2(void) -{ - unsigned char p0[] = {1, 8, 254u, 253u}; - unsigned char p1[] = {2, 8, 254u, 253u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX8Arrays3(void) -{ - unsigned char p0[] = {1, 8, 254u, 253u}; - unsigned char p1[] = {1, 8, 255u, 253u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -} - -void testEqualUINT8EachEqual(void) -{ - UNITY_UINT8 p0[] = {127u, 127u, 127u, 127u}; - UNITY_UINT8 p1[] = {1u, 1u, 1u, 1u}; - UNITY_UINT8 p2[] = {128u, 128u, 128u, 2u}; - UNITY_UINT8 p3[] = {1u, 50u, 60u, 70u}; - - TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 1); - TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); - TEST_ASSERT_EACH_EQUAL_UINT8(1u, p1, 4); - TEST_ASSERT_EACH_EQUAL_UINT8(128u, p2, 3); - TEST_ASSERT_EACH_EQUAL_UINT8(1u, p3, 1); -} - -void testNotEqualUINT8EachEqual1(void) -{ - unsigned char p0[] = {127u, 127u, 128u, 127u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT8EachEqual2(void) -{ - unsigned char p0[] = {1, 1, 1, 127u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT8(1, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT8EachEqual3(void) -{ - unsigned char p0[] = {54u, 55u, 55u, 55u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT8(55u, p0, 4); - VERIFY_FAILS_END -} - -void testEqualUINT16EachEqual(void) -{ - unsigned short p0[] = {65132u, 65132u, 65132u, 65132u}; - unsigned short p1[] = {987, 987, 987, 987}; - unsigned short p2[] = {1, 1, 1, 2}; - unsigned short p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 1); - TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); - TEST_ASSERT_EACH_EQUAL_UINT16(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_UINT16(1, p2, 3); - TEST_ASSERT_EACH_EQUAL_UINT16(1, p3, 1); -} - -void testNotEqualUINT16EachEqual1(void) -{ - unsigned short p0[] = {1, 65132u, 65132u, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT16EachEqual2(void) -{ - unsigned short p0[] = {65132u, 65132u, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT16EachEqual3(void) -{ - unsigned short p0[] = {65132u, 65132u, 65132u, 65133u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testEqualUINT32EachEqual(void) -{ - UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; - UNITY_UINT32 p1[] = {987, 987, 987, 987}; - UNITY_UINT32 p2[] = {8, 8, 8, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 1); - TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); - TEST_ASSERT_EACH_EQUAL_UINT32(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_UINT32(8, p2, 3); - TEST_ASSERT_EACH_EQUAL_UINT32(1, p3, 1); -} - -void testNotEqualUINT32EachEqual1(void) -{ - UNITY_UINT32 p0[] = {65132u, 65132u, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT32EachEqual2(void) -{ - UNITY_UINT32 p0[] = {1, 987, 987, 987}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT32(987, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualUINT32EachEqual3(void) -{ - UNITY_UINT32 p0[] = {1, 1, 1, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_UINT32(1, p0, 4); - VERIFY_FAILS_END -} - -void testEqualHEXEachEqual(void) -{ - UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; - UNITY_UINT32 p1[] = {987, 987, 987, 987}; - UNITY_UINT32 p2[] = {8, 8, 8, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 1); - TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 4); - TEST_ASSERT_EACH_EQUAL_HEX(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_HEX(8, p2, 3); - TEST_ASSERT_EACH_EQUAL_HEX(1, p3, 1); -} - -void testNotEqualHEXEachEqual1(void) -{ - UNITY_UINT32 p0[] = {1, 65132u, 65132u, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEXEachEqual2(void) -{ - UNITY_UINT32 p0[] = {987, 987, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEXEachEqual3(void) -{ - UNITY_UINT32 p0[] = {8, 8, 987, 8}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX(8, p0, 4); - VERIFY_FAILS_END -} - -void testEqualHEX32EachEqual(void) -{ - UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; - UNITY_UINT32 p1[] = {987, 987, 987, 987}; - UNITY_UINT32 p2[] = {8, 8, 8, 2}; - UNITY_UINT32 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 1); - TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); - TEST_ASSERT_EACH_EQUAL_HEX32(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_HEX32(8, p2, 3); - TEST_ASSERT_EACH_EQUAL_HEX32(1, p3, 1); -} - -void testNotEqualHEX32EachEqual1(void) -{ - UNITY_UINT32 p0[] = {65132u, 8, 65132u, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX32EachEqual2(void) -{ - UNITY_UINT32 p0[] = {1, 987, 987, 987}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX32EachEqual3(void) -{ - UNITY_UINT32 p0[] = {8, 8, 8, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX32(8, p0, 4); - VERIFY_FAILS_END -} - -void testEqualHEX16EachEqual(void) -{ - UNITY_UINT16 p0[] = {65132u, 65132u, 65132u, 65132u}; - UNITY_UINT16 p1[] = {987, 987, 987, 987}; - UNITY_UINT16 p2[] = {8, 8, 8, 2}; - UNITY_UINT16 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 1); - TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); - TEST_ASSERT_EACH_EQUAL_HEX16(987, p1, 4); - TEST_ASSERT_EACH_EQUAL_HEX16(8, p2, 3); - TEST_ASSERT_EACH_EQUAL_HEX16(1, p3, 1); -} - -void testNotEqualHEX16EachEqual1(void) -{ - unsigned short p0[] = {65132u, 65132u, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX16EachEqual2(void) -{ - unsigned short p0[] = {1, 987, 987, 987}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX16(987, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX16EachEqual3(void) -{ - unsigned short p0[] = {8, 8, 8, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX16(8, p0, 4); - VERIFY_FAILS_END -} - -void testEqualHEX8EachEqual(void) -{ - unsigned char p0[] = {254u, 254u, 254u, 254u}; - unsigned char p1[] = {123, 123, 123, 123}; - unsigned char p2[] = {8, 8, 8, 2}; - unsigned char p3[] = {1, 23, 25, 26}; - - TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 1); - TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); - TEST_ASSERT_EACH_EQUAL_HEX8(123, p1, 4); - TEST_ASSERT_EACH_EQUAL_HEX8(8, p2, 3); - TEST_ASSERT_EACH_EQUAL_HEX8(1, p3, 1); -} - -void testNotEqualHEX8EachEqual1(void) -{ - unsigned char p0[] = {253u, 253u, 254u, 253u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX8(253u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX8EachEqual2(void) -{ - unsigned char p0[] = {254u, 254u, 254u, 253u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); - VERIFY_FAILS_END -} - -void testNotEqualHEX8EachEqual3(void) -{ - unsigned char p0[] = {1, 8, 8, 8}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_HEX8(8, p0, 4); - VERIFY_FAILS_END -} - -void testEqualMemoryArrays(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, -2}; - int p2[] = {1, 8, 987, 2}; - int p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 1); - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 4); - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p2, sizeof(int), 3); - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p3, sizeof(int), 1); -} - -void testNotEqualMemoryArraysExpectedNull(void) -{ - int* p0 = NULL; - int p1[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryArraysActualNull(void) -{ - int p0[] = {1, 8, 987, -2}; - int* p1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryArrays1(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryArrays2(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {2, 8, 987, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryArrays3(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 986, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testEqualMemoryEachEqual(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, -2, 1, 8, 987, -2}; - int p2[] = {8, 8, 8, 2}; - int p3[] = {8, 500, 600, 700}; - int v = 8; - - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p0, sizeof(int)*4, 1); - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 2); - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 1); - TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p2, sizeof(int), 3); - TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p3, sizeof(int), 1); -} - -void testNotEqualMemoryEachEqualExpectedNull(void) -{ - int* p0 = NULL; - int p1[] = {1, 8, 987, 2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryEachEqualActualNull(void) -{ - int p0[] = {1, 8, 987, -2}; - int* p1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4); - VERIFY_FAILS_END -} - -void testNotEqualMemoryEachEqual1(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {9, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); - VERIFY_FAILS_END -} - -void testNotEqualMemoryEachEqual2(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, 9}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); - VERIFY_FAILS_END -} - -void testNotEqualMemoryEachEqual3(void) -{ - int p0[] = {1, 8, 987, -2}; - int p1[] = {1, 8, 987, -2, 1, 9, 987, -2, 1, 8, 987, -2}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); - VERIFY_FAILS_END -} - -void testProtection(void) -{ - volatile int mask = 0; - - if (TEST_PROTECT()) - { - mask |= 1; - TEST_ABORT(); - } - else - { - Unity.CurrentTestFailed = 0; - mask |= 2; - } - - TEST_ASSERT_EQUAL(3, mask); -} - -void testIgnoredAndThenFailInTearDown(void) -{ - SetToOneToFailInTearDown = 1; - TEST_IGNORE(); -} - -// Tricky series of macros to set USING_OUTPUT_SPY -#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0) -#define ASSIGN_VALUE(a) VAL_##a -#define VAL_putcharSpy 0, 1 -#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway) -#define SECOND_PARAM(a, b, ...) b -#if USING_SPY_AS(UNITY_OUTPUT_CHAR) - #define USING_OUTPUT_SPY // true only if UNITY_OUTPUT_CHAR = putcharSpy -#endif - -#ifdef USING_OUTPUT_SPY -#include -#define SPY_BUFFER_MAX 40 -static char putcharSpyBuffer[SPY_BUFFER_MAX]; -#endif -static int indexSpyBuffer; -static int putcharSpyEnabled; - -void startPutcharSpy(void) {indexSpyBuffer = 0; putcharSpyEnabled = 1;} - -void endPutcharSpy(void) {putcharSpyEnabled = 0;} - -char* getBufferPutcharSpy(void) -{ -#ifdef USING_OUTPUT_SPY - putcharSpyBuffer[indexSpyBuffer] = '\0'; - return putcharSpyBuffer; -#else - return NULL; -#endif -} - -void putcharSpy(int c) -{ -#ifdef USING_OUTPUT_SPY - if (putcharSpyEnabled) - { - if (indexSpyBuffer < SPY_BUFFER_MAX - 1) - putcharSpyBuffer[indexSpyBuffer++] = (char)c; - } else - putchar((char)c); -#endif -} - -void testFailureCountIncrementsAndIsReturnedAtEnd(void) -{ - UNITY_UINT savedFailures = Unity.TestFailures; - Unity.CurrentTestFailed = 1; - startPutcharSpy(); // Suppress output - UnityConcludeTest(); - endPutcharSpy(); - TEST_ASSERT_EQUAL(savedFailures + 1, Unity.TestFailures); - - startPutcharSpy(); // Suppress output - int failures = UnityEnd(); - Unity.TestFailures--; - endPutcharSpy(); - TEST_ASSERT_EQUAL(savedFailures + 1, failures); -} - -void testCstringsEscapeSequence(void) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - startPutcharSpy(); - UnityPrint("\x16\x10"); - endPutcharSpy(); - TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy()); -#endif -} - -void testHexPrintsUpToMaxNumberOfNibbles(void) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - startPutcharSpy(); - UnityPrintNumberHex(0xBEE, 21); - endPutcharSpy(); - TEST_ASSERT_EQUAL_INT(sizeof(UNITY_INT)*2, strlen(getBufferPutcharSpy())); -#endif -} - -#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \ - startPutcharSpy(); UnityPrintNumber((actual)); endPutcharSpy(); \ - TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ - } - -#define TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS(expected, actual) { \ - startPutcharSpy(); UnityPrintNumberUnsigned((actual)); endPutcharSpy(); \ - TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ - } - -void testPrintNumbers32(void) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE_MESSAGE("Compile with '-D UNITY_OUTPUT_CHAR=putcharSpy' to enable print testing"); -#else - TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("1", 1); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", -1); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("2000000000", 2000000000); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("-2147483648", (UNITY_INT32)0x80000000); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT32)0xFFFFFFFF); -#endif -} - -void testPrintNumbersUnsigned32(void) -{ -#ifndef USING_OUTPUT_SPY - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1", 1); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1500000000", 1500000000); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("2147483648", (UNITY_UINT32)0x80000000); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("4294967295", (UNITY_UINT32)0xFFFFFFFF); -#endif -} - -// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES 64 BIT SUPPORT ================== - -void testPrintNumbersInt64(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - #ifndef USING_OUTPUT_SPY - TEST_IGNORE(); - #else - TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("10000000000", 10000000000); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("-9223372036854775808", (UNITY_INT)0x8000000000000000); - TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT)0xFFFFFFFFFFFFFFFF); - #endif -#endif -} - -void testPrintNumbersUInt64(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - #ifndef USING_OUTPUT_SPY - TEST_IGNORE(); - #else - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("70000000000", 70000000000); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("9223372036854775808", (UNITY_UINT)0x8000000000000000); - TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("18446744073709551615", (UNITY_UINT)0xFFFFFFFFFFFFFFFF); - #endif -#endif -} - -void testEqualHex64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 v0, v1; - UNITY_UINT64 *p0, *p1; - - v0 = 0x9876543201234567; - v1 = 0x9876543201234567; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, 0x9876543201234567); - TEST_ASSERT_EQUAL_HEX64(v0, v1); - TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, v1); - TEST_ASSERT_EQUAL_HEX64(v0, 0x9876543201234567); - TEST_ASSERT_EQUAL_HEX64(*p0, v1); - TEST_ASSERT_EQUAL_HEX64(*p0, *p1); - TEST_ASSERT_EQUAL_HEX64(*p0, 0x9876543201234567); -#endif -} - -void testEqualUint64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 v0, v1; - UNITY_UINT64 *p0, *p1; - - v0 = 0x9876543201234567; - v1 = 0x9876543201234567; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, 0x9876543201234567); - TEST_ASSERT_EQUAL_UINT64(v0, v1); - TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, v1); - TEST_ASSERT_EQUAL_UINT64(v0, 0x9876543201234567); - TEST_ASSERT_EQUAL_UINT64(*p0, v1); - TEST_ASSERT_EQUAL_UINT64(*p0, *p1); - TEST_ASSERT_EQUAL_UINT64(*p0, 0x9876543201234567); -#endif -} - -void testEqualInt64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_INT64 v0, v1; - UNITY_INT64 *p0, *p1; - - v0 = (UNITY_INT64)0x9876543201234567; - v1 = (UNITY_INT64)0x9876543201234567; - p0 = &v0; - p1 = &v1; - - TEST_ASSERT_EQUAL_INT64(0x9876543201234567, 0x9876543201234567); - TEST_ASSERT_EQUAL_INT64(v0, v1); - TEST_ASSERT_EQUAL_INT64(0x9876543201234567, v1); - TEST_ASSERT_EQUAL_INT64(v0, 0x9876543201234567); - TEST_ASSERT_EQUAL_INT64(*p0, v1); - TEST_ASSERT_EQUAL_INT64(*p0, *p1); - TEST_ASSERT_EQUAL_INT64(*p0, 0x9876543201234567); -#endif -} - - -void testNotEqualHex64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 v0, v1; - - v0 = 9000000000; - v1 = 9100000000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX64(v0, v1); - VERIFY_FAILS_END -#endif -} - -void testNotEqualUint64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 v0, v1; - - v0 = 9000000000; - v1 = 9100000000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT64(v0, v1); - VERIFY_FAILS_END -#endif -} - -void testNotEqualInt64s(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_INT64 v0, v1; - - v0 = -9000000000; - v1 = 9100000000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT64(v0, v1); - VERIFY_FAILS_END -#endif -} - -void testNotEqualHex64sIfSigned(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_INT64 v0, v1; - - v0 = -9000000000; - v1 = 9000000000; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX64(v0, v1); - VERIFY_FAILS_END -#endif -} - -void testHEX64sWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); - TEST_ASSERT_HEX64_WITHIN(5, 5000, 4996); - TEST_ASSERT_HEX64_WITHIN(5, 5000, 5005); -#endif -} - -void testHEX64sNotWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); - VERIFY_FAILS_END -#endif -} - -void testHEX64sNotWithinDeltaEvenThoughASignedIntWouldPass(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_HEX64_WITHIN(5, 1, -1); - VERIFY_FAILS_END -#endif -} - -void testUINT64sWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); - TEST_ASSERT_UINT64_WITHIN(5, 5000, 4996); - TEST_ASSERT_UINT64_WITHIN(5, 5000, 5005); -#endif -} - -void testUINT64sNotWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); - VERIFY_FAILS_END -#endif -} - -void testUINT64sNotWithinDeltaEvenThoughASignedIntWouldPass(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_UINT64_WITHIN(5, 1, -1); - VERIFY_FAILS_END -#endif -} - -void testINT64sWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); - TEST_ASSERT_INT64_WITHIN(5, 5000, 4996); - TEST_ASSERT_INT64_WITHIN(5, 5000, 5005); -#endif -} - -void testINT64sNotWithinDelta(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); - VERIFY_FAILS_END -#endif -} - -void testINT64sNotWithinDeltaAndDifferenceOverflows(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_INT64_WITHIN(1, 0x8000000000000000, 0x7FFFFFFFFFFFFFFF); - VERIFY_FAILS_END -#endif -} - -void testEqualHEX64Arrays(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p1[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p2[] = {1, 8, 987, 2}; - UNITY_UINT64 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p3, 1); -#endif -} - -void testEqualUint64Arrays(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p1[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p2[] = {1, 8, 987, 2}; - UNITY_UINT64 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p3, 1); -#endif -} - -void testEqualInt64Arrays(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_INT64 p0[] = {1, 8, 987, -65132}; - UNITY_INT64 p1[] = {1, 8, 987, -65132}; - UNITY_INT64 p2[] = {1, 8, 987, -2}; - UNITY_INT64 p3[] = {1, 500, 600, 700}; - - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p3, 1); -#endif -} - - -void testNotEqualHEX64Arrays1(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualHEX64Arrays2(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p1[] = {2, 8, 987, 65132u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualUint64Arrays(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; - UNITY_UINT64 p1[] = {1, 8, 987, 65131u}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualInt64Arrays(void) -{ -#ifndef UNITY_SUPPORT_64 - TEST_IGNORE(); -#else - UNITY_INT64 p0[] = {1, 8, 987, -65132}; - UNITY_INT64 p1[] = {1, 8, 987, -65131}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} -// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES FLOAT SUPPORT ================== - -void testFloatsWithinDelta(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_WITHIN(0.00003f, 187245.03485f, 187245.03488f); - TEST_ASSERT_FLOAT_WITHIN(1.0f, 187245.0f, 187246.0f); - TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2549f, 9273.2049f); - TEST_ASSERT_FLOAT_WITHIN(0.007f, -726.93724f, -726.94424f); -#endif -} - -void testFloatsNotWithinDelta(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2649f, 9273.2049f); - VERIFY_FAILS_END -#endif -} - -void testFloatsEqual(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_FLOAT(187245.0f, 187246.0f); - TEST_ASSERT_EQUAL_FLOAT(18724.5f, 18724.6f); - TEST_ASSERT_EQUAL_FLOAT(9273.2549f, 9273.2599f); - TEST_ASSERT_EQUAL_FLOAT(-726.93724f, -726.9374f); -#endif -} - -void testFloatsNotEqual(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(9273.9649f, 9273.0049f); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualNegative1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(-9273.9649f, -9273.0049f); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualNegative2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(-9273.0049f, -9273.9649f); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualActualNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(85.963f, 0.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualExpectedNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 85.963f); - VERIFY_FAILS_END -#endif -} - -void testFloatsEqualBothNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero); -#endif -} - -void testFloatsNotEqualInfNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 0.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualNaNInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 1.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualActualInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(321.642f, 1.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatsNotEqualExpectedInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 321.642f); - VERIFY_FAILS_END -#endif -} - -void testFloatsEqualBothInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); -#endif -} - -void testFloatsNotEqualPlusMinusInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatIsPosInf1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_INF(2.0f / f_zero); -#endif -} - -void testFloatIsPosInf2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNegInf1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_NEG_INF(-3.0f / f_zero); -#endif -} - -void testFloatIsNegInf2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(-3.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNotPosInf1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_INF(2.0f); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNotPosInf2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f); -#endif -} - -void testFloatIsNotNegInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NEG_INF(-999.876f); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNan1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_NAN(0.0f / f_zero); -#endif -} - -void testFloatIsNan2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NOT_NAN(0.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNotNan1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NAN(234.9f); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNotNan2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_NOT_NAN(234.9f); -#endif -} - -void testFloatInfIsNotNan(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NAN(1.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatNanIsNotInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_INF(0.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatIsDeterminate1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_DETERMINATE(0.0f); - TEST_ASSERT_FLOAT_IS_DETERMINATE(123.3f); - TEST_ASSERT_FLOAT_IS_DETERMINATE(-88.3f); -#endif -} - -void testFloatIsDeterminate2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-88.3f); - VERIFY_FAILS_END -#endif -} - -void testFloatIsNotDeterminate1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(1.0f / f_zero); - TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-1.0f / f_zero); - TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(0.0f / f_zero); -#endif -} - -void testFloatIsNotDeterminate2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_FLOAT_IS_DETERMINATE(-1.0f / f_zero); - VERIFY_FAILS_END -#endif -} - -void testFloatTraitFailsOnInvalidTrait(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - UnityAssertFloatSpecial(1.0f, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT); - VERIFY_FAILS_END -#endif -} - - -void testEqualFloatArrays(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, -8.0f, 25.4f, -0.123f}; - float p1[] = {1.0f, -8.0f, 25.4f, -0.123f}; - float p2[] = {1.0f, -8.0f, 25.4f, -0.2f}; - float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; - - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p3, 1); - TEST_ASSERT_EQUAL_FLOAT_ARRAY(NULL, NULL, 1); -#endif -} - -void testNotEqualFloatArraysExpectedNull(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float* p0 = NULL; - float p1[] = {1.0f, 8.0f, 25.4f, 0.252f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArraysActualNull(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; - float* p1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArrays1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; - float p1[] = {1.0f, 8.0f, 25.4f, 0.252f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArrays2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; - float p1[] = {2.0f, 8.0f, 25.4f, 0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArrays3(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; - float p1[] = {1.0f, 8.0f, 25.5f, 0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArraysNegative1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; - float p1[] = {-1.0f, -8.0f, -25.4f, -0.252f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArraysNegative2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; - float p1[] = {-2.0f, -8.0f, -25.4f, -0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatArraysNegative3(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; - float p1[] = {-1.0f, -8.0f, -25.5f, -0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testEqualFloatArraysNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f}; - float p1[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f}; - - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); -#endif -} - -void testEqualFloatArraysInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; - float p1[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; - - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); -#endif -} - -void testNotEqualFloatArraysLengthZero(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[1] = {0.0f}; - float p1[1] = {0.0f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 0); - VERIFY_FAILS_END -#endif -} - -void testEqualFloatEachEqual(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 1.0f, 1.0f, 1.0f}; - float p1[] = {-0.123f, -0.123f, -0.123f, -0.123f}; - float p2[] = {25.4f, 25.4f, 25.4f, -0.2f}; - float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; - - TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 1); - TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); - TEST_ASSERT_EACH_EQUAL_FLOAT(-0.123f, p1, 4); - TEST_ASSERT_EACH_EQUAL_FLOAT(25.4f, p2, 3); - TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p3, 1); -#endif -} - -void testNotEqualFloatEachEqualActualNull(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float* p0 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(5, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqual1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {0.253f, 8.0f, 0.253f, 0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(0.253f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqual2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {8.0f, 8.0f, 8.0f, 0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(8.0f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqual3(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f, 1.0f, 1.0f, 0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqualNegative1(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-1.0f, -0.253f, -0.253f, -0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(-0.253f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqualNegative2(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-25.4f, -8.0f, -25.4f, -25.4f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(-25.4f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualFloatEachEqualNegative3(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {-8.0f, -8.0f, -8.0f, -0.253f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(-8.0f, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testEqualFloatEachEqualNaN(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero}; - - TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f / f_zero, p0, 4); -#endif -} - -void testEqualFloatEachEqualInf(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[] = {1.0f / f_zero, 1.0f / f_zero, 25.4f, 0.253f}; - - TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f / f_zero, p0, 2); -#endif -} - -void testNotEqualFloatEachEqualLengthZero(void) -{ -#ifdef UNITY_EXCLUDE_FLOAT - TEST_IGNORE(); -#else - float p0[1] = {0.0f}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f, p0, 0); - VERIFY_FAILS_END -#endif -} - -#define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \ - startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \ - TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ - } - -void testFloatPrinting(void) -{ -#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999995f); /*Rounding to int place*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999", 7.99999f); /*Not rounding*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0002", 16.0002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0004", 16.0004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0006", 16.0006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("999999", 999999.0f); /*Last full print integer*/ - - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999995f); /*Rounding to int place*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999", -7.99999f); /*Not rounding*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0002", -16.0002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0004", -16.0004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0006", -16.0006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999", -999999.0f); /*Last full print integer*/ - - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("8.31e+09", 8309999104.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f); - /* Some compilers have trouble with inexact float constants, a float cast works generally */ - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005e+10", (float)1.000054e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.6353e+10", 1.63529943e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282e+38", 3.40282346638e38f); - - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282e+38", -3.40282346638e38f); -#endif -} - -void testFloatPrintingInfinityAndNaN(void) -{ -#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0f / f_zero); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0f / f_zero); - - TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0f / f_zero); -#endif -} - -#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) -static void printFloatValue(float f) -{ - char expected[18]; - char expected_lower[18]; - char expected_higher[18]; - - startPutcharSpy(); - - UnityPrintFloat(f); - - sprintf(expected, "%.6g", f); - - /* We print all NaN's as "nan", not "-nan" */ - if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - - /* Allow for rounding differences in last digit */ - double lower = (double)f * 0.9999995; - double higher = (double)f * 1.0000005; - - if (isfinite(lower)) sprintf(expected_lower, "%.6g", lower); else strcpy(expected_lower, expected); - if (isfinite(higher)) sprintf(expected_higher, "%.6g", higher); else strcpy(expected_higher, expected); - - if (strcmp(expected, getBufferPutcharSpy()) != 0 && - strcmp(expected_lower, getBufferPutcharSpy()) != 0 && - strcmp(expected_higher, getBufferPutcharSpy()) != 0) - { - /* Fail with diagnostic printing */ - TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); - } -} -#endif - -void testFloatPrintingRandomSamples(void) -{ -#if !defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) || !defined(USING_OUTPUT_SPY) - TEST_IGNORE(); -#else - union { float f_value; uint32_t int_value; } u; - - /* These values are not covered by the MINSTD generator */ - u.int_value = 0x00000000; printFloatValue(u.f_value); - u.int_value = 0x80000000; printFloatValue(u.f_value); - u.int_value = 0x7fffffff; printFloatValue(u.f_value); - u.int_value = 0xffffffff; printFloatValue(u.f_value); - - uint32_t a = 1; - for(int num_tested = 0; num_tested < 1000000; num_tested++) - { - /* MINSTD pseudo-random number generator */ - a = (uint32_t)(((uint64_t)a * 48271u) % 2147483647u); - - /* MINSTD does not set the highest bit; test both possibilities */ - u.int_value = a; printFloatValue(u.f_value); - u.int_value = a | 0x80000000; printFloatValue(u.f_value); - } -#endif -} - -// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ================== - -void testDoublesWithinDelta(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_WITHIN(0.00003, 187245.03485, 187245.03488); - TEST_ASSERT_DOUBLE_WITHIN(1.0, 187245.0, 187246.0); - TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2549, 9273.2049); - TEST_ASSERT_DOUBLE_WITHIN(0.007, -726.93725, -726.94424); -#endif -} - -void testDoublesNotWithinDelta(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2649, 9273.2049); - VERIFY_FAILS_END -#endif -} - - -void testDoublesEqual(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_DOUBLE(187245123456.0, 187245123456.0); - TEST_ASSERT_EQUAL_DOUBLE(187241234567.5, 187241234567.6); - TEST_ASSERT_EQUAL_DOUBLE(9273.2512345649, 9273.25123455699); - TEST_ASSERT_EQUAL_DOUBLE(-726.12345693724, -726.1234569374); -#endif -} - -void testDoublesNotEqual(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(9273.9649, 9273.0049); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualNegative1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(-9273.9649, -9273.0049); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualNegative2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(-9273.0049, -9273.9649); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualActualNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(85.963, 0.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualExpectedNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 85.963); - VERIFY_FAILS_END -#endif -} - -void testDoublesEqualBothNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero); -#endif -} - -void testDoublesNotEqualInfNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 0.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualNaNInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 1.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualActualInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(321.642, 1.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoublesNotEqualExpectedInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 321.642); - VERIFY_FAILS_END -#endif -} - -void testDoublesEqualBothInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); -#endif -} - -void testDoublesNotEqualPlusMinusInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsPosInf1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_INF(2.0 / d_zero); -#endif -} - -void testDoubleIsPosInf2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNegInf1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_NEG_INF(-3.0 / d_zero); -#endif -} - -void testDoubleIsNegInf2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(-3.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNotPosInf1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_INF(2.0); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNotPosInf2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0); -#endif -} - -void testDoubleIsNotNegInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NEG_INF(-999.876); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNan1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_NAN(0.0 / d_zero); -#endif -} - -void testDoubleIsNan2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NOT_NAN(0.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNotNan1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NAN(234.9); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNotNan2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_NOT_NAN(234.9); -#endif -} - -void testDoubleInfIsNotNan(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NAN(1.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleNanIsNotInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_INF(0.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsDeterminate1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_DETERMINATE(0.0); - TEST_ASSERT_DOUBLE_IS_DETERMINATE(123.3); - TEST_ASSERT_DOUBLE_IS_DETERMINATE(-88.3); -#endif -} - -void testDoubleIsDeterminate2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-88.3); - VERIFY_FAILS_END -#endif -} - -void testDoubleIsNotDeterminate1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(1.0 / d_zero); - TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-1.0 / d_zero); - TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(0.0 / d_zero); -#endif -} - -void testDoubleIsNotDeterminate2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - TEST_ASSERT_DOUBLE_IS_DETERMINATE(-1.0 / d_zero); - VERIFY_FAILS_END -#endif -} - -void testDoubleTraitFailsOnInvalidTrait(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - EXPECT_ABORT_BEGIN - UnityAssertDoubleSpecial(1.0, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT); - VERIFY_FAILS_END -#endif -} - -void testEqualDoubleArrays(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, -8.0, 25.4, -0.123}; - double p1[] = {1.0, -8.0, 25.4, -0.123}; - double p2[] = {1.0, -8.0, 25.4, -0.2}; - double p3[] = {1.0, -23.0, 25.0, -0.26}; - - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 1); - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 4); - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p2, 3); - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p3, 1); - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(NULL, NULL, 1); -#endif -} - -void testNotEqualDoubleArraysExpectedNull(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double* p0 = NULL; - double p1[] = {1.0, 8.0, 25.4, 0.252}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArraysActualNull(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 8.0, 25.4, 0.253}; - double* p1 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArrays1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 8.0, 25.4, 0.25666666667}; - double p1[] = {1.0, 8.0, 25.4, 0.25666666666}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArrays2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 8.0, 25.4, 0.253}; - double p1[] = {2.0, 8.0, 25.4, 0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArrays3(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 8.0, 25.4, 0.253}; - double p1[] = {1.0, 8.0, 25.5, 0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArraysNegative1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-1.0, -8.0, -25.4, -0.2566666667}; - double p1[] = {-1.0, -8.0, -25.4, -0.2566666666}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArraysNegative2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-1.0, -8.0, -25.4, -0.253}; - double p1[] = {-2.0, -8.0, -25.4, -0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleArraysNegative3(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-1.0, -8.0, -25.4, -0.253}; - double p1[] = {-1.0, -8.0, -25.5, -0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); - VERIFY_FAILS_END -#endif -} - -void testEqualDoubleArraysNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 0.0 / d_zero, 25.4, 0.253}; - double p1[] = {1.0, 0.0 / d_zero, 25.4, 0.253}; - - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); -#endif -} - -void testEqualDoubleArraysInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; - double p1[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; - - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); -#endif -} - -void testNotEqualDoubleArraysLengthZero(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[1] = {0.0}; - double p1[1] = {0.0}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 0); - VERIFY_FAILS_END -#endif -} - -void testEqualDoubleEachEqual(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 1.0, 1.0, 1.0}; - double p1[] = {-0.123, -0.123, -0.123, -0.123}; - double p2[] = {25.4, 25.4, 25.4, -0.2}; - double p3[] = {1.0, -23.0, 25.0, -0.26}; - - TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 1); - TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); - TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.123, p1, 4); - TEST_ASSERT_EACH_EQUAL_DOUBLE(25.4, p2, 3); - TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p3, 1); -#endif -} - -void testNotEqualDoubleEachEqualActualNull(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double* p0 = NULL; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(5, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqual1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {0.253, 8.0, 0.253, 0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(0.253, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqual2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {8.0, 8.0, 8.0, 0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(8.0, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqual3(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0, 1.0, 1.0, 0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqualNegative1(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-1.0, -0.253, -0.253, -0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.253, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqualNegative2(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-25.4, -8.0, -25.4, -25.4}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(-25.4, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testNotEqualDoubleEachEqualNegative3(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {-8.0, -8.0, -8.0, -0.253}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(-8.0, p0, 4); - VERIFY_FAILS_END -#endif -} - -void testEqualDoubleEachEqualNaN(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero}; - - TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0 / d_zero, p0, 4); -#endif -} - -void testEqualDoubleEachEqualInf(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[] = {1.0 / d_zero, 1.0 / d_zero, 25.4, 0.253}; - - TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0 / d_zero, p0, 2); -#endif -} - -void testNotEqualDoubleEachEqualLengthZero(void) -{ -#ifdef UNITY_EXCLUDE_DOUBLE - TEST_IGNORE(); -#else - double p0[1] = {0.0}; - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0, p0, 0); - VERIFY_FAILS_END -#endif -} - -void testDoublePrinting(void) -{ -#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.0072e+15", 9007199254740990.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23457e+300", 9.23456789e+300); - - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); -#endif -} - -void testDoublePrintingInfinityAndNaN(void) -{ -#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) - TEST_IGNORE(); -#else - TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0 / d_zero); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0 / d_zero); - - TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0 / d_zero); -#endif -} - -// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ================== - -void testThatDetailsCanBeHandleOneDetail(void) -{ -#ifdef UNITY_EXCLUDE_DETAILS - TEST_IGNORE(); -#else - UNITY_SET_DETAIL("Detail1"); - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_INT_MESSAGE(5, 6, "Should Fail And Say Detail1"); - VERIFY_FAILS_END -#endif -} - -void testThatDetailsCanHandleTestFail(void) -{ -#ifdef UNITY_EXCLUDE_DETAILS - TEST_IGNORE(); -#else - UNITY_SET_DETAILS("Detail1","Detail2"); - - EXPECT_ABORT_BEGIN - TEST_FAIL_MESSAGE("Should Fail And Say Detail1 and Detail2"); - VERIFY_FAILS_END -#endif -} - -void testThatDetailsCanBeHandleTwoDetails(void) -{ -#ifdef UNITY_EXCLUDE_DETAILS - TEST_IGNORE(); -#else - UNITY_SET_DETAILS("Detail1","Detail2"); - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_HEX8_MESSAGE(7, 8, "Should Fail And Say Detail1 and Detail2"); - VERIFY_FAILS_END -#endif -} - -void testThatDetailsCanBeHandleSingleDetailClearingTwoDetails(void) -{ -#ifdef UNITY_EXCLUDE_DETAILS - TEST_IGNORE(); -#else - UNITY_SET_DETAILS("Detail1","Detail2"); - UNITY_SET_DETAIL("DetailNew"); - - EXPECT_ABORT_BEGIN - TEST_ASSERT_EQUAL_STRING_MESSAGE("MEH", "GUH", "Should Fail And Say DetailNew"); - VERIFY_FAILS_END -#endif -} diff --git a/components/cjson/cJSON/valgrind.supp b/components/cjson/cJSON/valgrind.supp deleted file mode 100644 index 79b55c674..000000000 --- a/components/cjson/cJSON/valgrind.supp +++ /dev/null @@ -1,6 +0,0 @@ -{ - suppress_ld_on_armv7 - Memcheck:Cond - ... - obj:*/ld-*.so -} diff --git a/components/cjson/component.mk b/components/cjson/component.mk deleted file mode 100644 index 9b2da22aa..000000000 --- a/components/cjson/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -COMPONENT_ADD_INCLUDEDIRS += cJSON - -COMPONENT_SRCDIRS := cJSON - -ifdef CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL -CFLAGS += -DCJSON_SPRINTF_FLOAT=1 -endif diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index 90b0c26e6..925ed75e2 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -1,42 +1,41 @@ -set(COMPONENT_ADD_INCLUDEDIRS port/include port/include/coap libcoap/include libcoap/include/coap) +if(CONFIG_ENABLE_COAP) + set(include_dirs port/include port/include/coap libcoap/include libcoap/include/coap2) -set(COMPONENT_SRCS - libcoap/src/address.c - libcoap/src/async.c - libcoap/src/block.c - libcoap/src/coap_time.c - libcoap/src/debug.c - libcoap/src/encode.c - libcoap/src/hashkey.c - libcoap/src/mem.c - libcoap/src/net.c - libcoap/src/option.c - libcoap/src/pdu.c - libcoap/src/resource.c - libcoap/src/str.c - libcoap/src/subscribe.c - libcoap/src/uri.c - port/coap_io_socket.c - ) + set(srcs + "libcoap/src/address.c" + "libcoap/src/async.c" + "libcoap/src/block.c" + "libcoap/src/coap_event.c" + "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_session.c" + "libcoap/src/coap_time.c" + "libcoap/src/coap_debug.c" + "libcoap/src/encode.c" + "libcoap/src/mem.c" + "libcoap/src/net.c" + "libcoap/src/option.c" + "libcoap/src/pdu.c" + "libcoap/src/resource.c" + "libcoap/src/str.c" + "libcoap/src/subscribe.c" + "libcoap/src/uri.c" + "libcoap/src/coap_notls.c" + "port/coap_io.c") -set(COMPONENT_REQUIRES lwip) + set(COMPONENT_REQUIRES lwip) -register_component() + idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + REQUIRES lwip) -# Needed for coap headers in public builds, also. -# -# TODO: find a way to move this to a port header -target_compile_definitions(coap PUBLIC WITH_POSIX) + # Silence format truncation warning, until it is fixed upstream + set_source_files_properties(libcoap/src/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) -set_source_files_properties( - libcoap/src/debug.c - libcoap/src/pdu.c - PROPERTIES COMPILE_FLAGS - -Wno-write-strings) - -# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo -set_source_files_properties( - libcoap/src/option.c - PROPERTIES COMPILE_FLAGS - -Wno-implicit-fallthrough) + # Needed for coap headers in public builds, also. + # + # TODO: find a way to move this to a port header + target_compile_definitions(${COMPONENT_LIB} PUBLIC WITH_POSIX) +else() + register_component() +endif() diff --git a/components/coap/Kconfig b/components/coap/Kconfig new file mode 100644 index 000000000..825b8deab --- /dev/null +++ b/components/coap/Kconfig @@ -0,0 +1,10 @@ +menu "COAP" + +config ENABLE_COAP + bool "Enable coap" + default n + select LWIP_IPV6 + help + Enable this option and coap is to be used, IPv6 is to be Enable. +endmenu + diff --git a/components/coap/Makefile.projbuild b/components/coap/Makefile.projbuild deleted file mode 100644 index e900b0f9a..000000000 --- a/components/coap/Makefile.projbuild +++ /dev/null @@ -1 +0,0 @@ -CPPFLAGS += -DWITH_POSIX diff --git a/components/coap/component.mk b/components/coap/component.mk index 4b3d56f56..a656dbc28 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -2,15 +2,15 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap +ifdef CONFIG_ENABLE_COAP +COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2 -COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_time.o libcoap/src/debug.o libcoap/src/encode.o libcoap/src/hashkey.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_io_socket.o +COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_session.o libcoap/src/coap_time.o libcoap/src/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o libcoap/src/coap_notls.o port/coap_io.o COMPONENT_SRCDIRS := libcoap/src libcoap port COMPONENT_SUBMODULES += libcoap -libcoap/src/debug.o: CFLAGS += -Wno-write-strings -libcoap/src/pdu.o: CFLAGS += -Wno-write-strings -# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo -libcoap/src/option.o: CFLAGS += -Wno-implicit-fallthrough +# Silence format truncation warning, until it is fixed upstream +libcoap/src/coap_debug.o: CFLAGS += -Wno-format-truncation +endif diff --git a/components/coap/libcoap b/components/coap/libcoap new file mode 160000 index 000000000..0dbccca06 --- /dev/null +++ b/components/coap/libcoap @@ -0,0 +1 @@ +Subproject commit 0dbccca06c3ea75a20ef0a51633eb424a35b5e2a diff --git a/components/coap/libcoap/.gitignore b/components/coap/libcoap/.gitignore deleted file mode 100644 index 3b1d4b234..000000000 --- a/components/coap/libcoap/.gitignore +++ /dev/null @@ -1,64 +0,0 @@ -# .gitignore for libcoap - -# ignoring autogenerated files and directories by autoreconf -INSTALL -Makefile -Makefile.in -aclocal.m4 -ar-lib -autom4te.cache/ -coap_config.h* -compile -config.* -configure -debian/ -depcomp -install-sh -libcoap-*.tar.bz2 -libtool -ltmain.sh -m4/libtool.m4 -m4/ltoptions.m4 -m4/ltsugar.m4 -m4/ltversion.m4 -m4/lt~obsolete.m4 -missing -stamp-h1 - -# ignoring more files generated by the configure script or the make actions -.libs/ -libcoap*.la -libcoap*.pc -src/.deps/ -src/.dirstamp -src/.libs/ -src/*.o -src/*.lo - -# the doc/ folder -doc/Doxyfile -doc/Makefile.in -doc/doxyfile.stamp -doc/doxygen_sqlite3.db -doc/html/ - -# the examples/ folder -examples/.deps/ -examples/*.o -examples/coap-client -examples/coap-rd -examples/coap-server -examples/coap-client.5 -examples/coap-client.txt -examples/coap-rd.5 -examples/coap-rd.txt -examples/coap-server.5 -examples/coap-server.txt - -# the include/ folder -include/coap/coap.h - -# the tests/ folder -tests/.deps -tests/testdriver -tests/*.o diff --git a/components/coap/libcoap/.travis.yml b/components/coap/libcoap/.travis.yml deleted file mode 100644 index d574e1d29..000000000 --- a/components/coap/libcoap/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -sudo: required -dist: trusty - -language: c -compiler: - - gcc - - clang - -env: - - PLATFORM=posix TESTS=yes - - PLATFORM=contiki - - PLATFORM=lwip - -addons: - apt_packages: - - pkg-config - - graphviz - - libcunit1-dev - - doxygen - - libxml2-utils - - xsltproc - - docbook-xml - - docbook-xsl - - asciidoc - -branches: - only: - - master - - develop - - /^release-.*$/ - -before_script: ./autogen.sh --clean && ./autogen.sh - -script: scripts/build.sh diff --git a/components/coap/libcoap/AUTHORS b/components/coap/libcoap/AUTHORS deleted file mode 100644 index d747a4e74..000000000 --- a/components/coap/libcoap/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -libcoap authors - -Olaf Bergmann, Universit�t Bremen diff --git a/components/coap/libcoap/CONTRIBUTE b/components/coap/libcoap/CONTRIBUTE deleted file mode 100644 index 9e6d3ee2c..000000000 --- a/components/coap/libcoap/CONTRIBUTE +++ /dev/null @@ -1,219 +0,0 @@ - ####################################################### - # Developer information for contributing to libcoap # - ####################################################### - -1. The basics -~~~~~~~~~~~~~ -The libcoap project is a FOSS project that is dual licensed. The maintainer -for the libcoap is Olaf Bergmann . -Any contributions have to be made dual licensed under the terms of the -license - - * BSD 2-Clause (The BSD 2-Clause License) - -and - - * GPL v2+ (The GNU General Public License 2.0 or later) - -The used VCS for libcoap is Git, the main repository is living on GitHub. -You can clone (or fork directly on GitHub) on the repository site: - - https://github.com/obgm/libcoap - -Please refer also to the libcoap website for additional information - - https://libcoap.net/ - -The build environment is grounded on the classical autotools, the GNU GCC and -the LLVM C-compiler (CLang) are supported. The Windows systems are not -currently supported (until someone is creating support for it). - -Doxygen is used for creating a HTML based online documentation of the -libcoap library. - -2. Communications -~~~~~~~~~~~~~~~~~ -The main discussion and development platform for libcoap is the mailing list -on Sourceforge. -No matter if you just have a simple question, some specific problem or -want to discuss some patches, please write it to the mailing list. Please -avoid personal mailings to the maintainer (or some other contributor) if -your questions will probably be in the interest of other users too. -You can subscribe to the list here: - - https://lists.sourceforge.net/lists/listinfo/libcoap-developers - -The archive of the list can be found on: - - https://sourceforge.net/p/libcoap/mailman/libcoap-developers - -3. Starting contributing -~~~~~~~~~~~~~~~~~~~~~~~~ -As written above libcoap is maintained with the Git tools so you should be -familiar with the various git commands. -The libcoap project is using just two main branches, the 'master' branch is -holding the point releases, all the development process is going on in the -'develop' branch. -To start any contributing you first have to clone the git tree from the main -repository on GitHub: - - git clone https://github.com/obgm/libcoap.git - -4. Working on the source -~~~~~~~~~~~~~~~~~~~~~~~~ -As one golden rule you should work on improvements within *your* own local -development branch! To do so you have to first checkout the 'develop' branch -as local branch and then start on top on this branch your own branch. So -create (or better say checkout) the local 'develop' branch: - - cd libcoap - git checkout develop origin/develop - -Now you can simply start your own local branch (for example 'my-develop') -with the 'origin/develop' as parent so you can later create the patches -against the the upstream development branch: - - git checkout -b my-develop - -At this point you can now work as known with git, modify the source, commit -the changes, amend if needed and test your work. -At some point you will have to generate patches to post them on the mailing -list (and/or push your changes into your public Git tree). It's a good idea to -post your patch series on the mailing list so other contributors will see your -work and give further suggestions or discuss your work. - -To be able to send a patch series you will now create the series itself as -single patches, this will be going easy with the 'git format-patch' command -against the 'develop' branch, remind this is the upstream main development -branch. -To not mix up your series with probably unrelated patches let git place the -patches within a defined directory. Also, while create the patches, tell git to -create a cover letter patch so you can append some introducing words that will -hold probably explanations why you create the patches in the way you have done. - - git format-patch --cover-letter -o ../patches4libcoap - -This command will create a patch series in ../patches4libcoap where you find a -patch named '0000-cover-letter.patch'. Please modify this patch with some -useful information's for the mailing list. After finish this you now can send -your patches to libcoap-developers@lists.sourceforge.net - - git send-email ../patches4libcoap/* --to=libcoap-developers@lists.sourceforge.net - -5. Coding rules -~~~~~~~~~~~~~~~ -As every FOSS project the libcoap project needs also some rules for coding. -There are loss but the main of them are important! - -5.1 License and Copyright -------------------------- -Every new file must contain a license and the copyright holder(s). Please -take a look into existing files and adopt the needed changes to your new -file(s). - -5.2 Source Code Indentation ---------------------------- -* For better reading the indentation is set to 2 characters as spaces, this - is depended on the often used nested functions like 'if-else'. Don't use - TABs any there! Avoid trailing white spaces at the end of a line. - It's appropriate to set up a modline like this one at first line within - the source file: - ---8<---- -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ ---->8-- - -* Single lines within the source code should not be longer then 78 - characters. - -* If there a functions with a lot of parameters that do not fit into the above - rule split the declaration (in the *.h) and the implementation (in the *.c) - into single lines per parameter. For example like this (from src/block.c): - ---8<---- -int -coap_add_block(coap_pdu_t *pdu, - unsigned int len, - const unsigned char *data, - unsigned int block_num, - unsigned char block_szx); ---->8-- - -5.3 Source Code Documentation ------------------------------ -* A useful source code documentation is mandatory. Mostly to be done within the - source code files, but more complex description should be done in extra - README files. - -* Please set up/adjust the doxygen documentation if you create new functions or - change existing functions. The doxygen documentation has to be done in the - header files as they are the public part of the libcoap and only use the - @-syntax for doxygen commands (akin to javadoc). - -5.4 API Changes ---------------- -* Never break the API! - Don't remove old functions and if there some changes are needed in some kind - always provide a wrapper for the old call to let the library be backward - compatible and mark the old function as @deprecated in the doxygen comment. - Please discuss needed changes on the mailing list. - -5.5 Patches and Commits ------------------------ -* Git commits must be atomic and contain a declarative subject line (max 50 - characters if possible) and a body for a statement if needed. - Use the possibility to write a good explanation why your patch/commit is - handle the changes in the way you have done. Remind that other user can - read your code but not necessary understand why the code is written this - way. Don't use something to generic like "bugfix commit". - -* A patch/commit or a series of patches/commits have to ensure that the - whole project is able to build up every thing, in short: Do not break - any make target and test your work. - -* Every patch/commit should handle one single logical change. If more than - one patch/commit is needed for a change explain it, respect the point - above. If your subject line become much larger than 50 characters then - typically your patch is to big for one single commit. - -* Commit message should begin with a submodule or unit the commit is for. By - this your commit message helps to find thematic other changes. If you have - to search and find something with 'git log | grep [foo]' you will see why - this is useful. Examples: - - rd.c: Fixed type-specifier warning - Makefile.am: Added missing src/address.c - address.[hc]: make coap_address_equals() not inline on POSIX - -6. Where to start contributing? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are various things you could starting on to contribute, the best -is you simply pick up an issue you blindly see and just improve the -situation. Please take also a look into the file TODO and choose a point -from there or point the maintainer to add other things here too. - -* Documentation -We are always lacking on a better documentation on the source code, so -maybe you can improve the doxygen documentation. -Also a good documentation on the usage of the libcoap and the example -binaries is always improvable. So we appreciate any help on this. - -* Man Pages -The source is providing some example binaries which originally just should show -how the libcoap can be used. Right now these binaries are fully usable and -quite more than simple examples on a system. There are man pages for these -binaries available, if you found there is a improvement needed please do so and -write to the mailing list explained in section 2. -Maybe you can write up some good HowTo's on the usage for these binaries. A man -page for the library itself would be also a improvement. - -* HowTo's -The libcoap library has now a lot of functions you can use. -Unfortunately there is no good user guide on how to use the libcoap in -any external project. This means there is no HowTo or CheatSheet for a -programming person available. You want to write up something? - -* missed Functionality -There are some features that are still missing inside the libcoap. For -example some DTLS implementations and proxy functionality. - diff --git a/components/coap/libcoap/COPYING b/components/coap/libcoap/COPYING deleted file mode 100644 index 6f0c0fd23..000000000 --- a/components/coap/libcoap/COPYING +++ /dev/null @@ -1,6 +0,0 @@ -libcoap is published as open-source software without any warranty of any kind. - -Use is permitted under the terms of the GNU General Public License (GPL), -Version 2 or higher, OR the simplified BSD license. - -The respective license file are shipped as LICENSE.BSD and LICENSE.GPL. diff --git a/components/coap/libcoap/ChangeLog b/components/coap/libcoap/ChangeLog deleted file mode 100644 index 477be8df1..000000000 --- a/components/coap/libcoap/ChangeLog +++ /dev/null @@ -1,220 +0,0 @@ -2016-02-16 Olaf Bergmann - - * Fixed build for Contiki3 and LwIP - * .travis.yml: Enabled continuous integration for platforms - POSIX and Contiki - -2015-03-11 Olaf Bergmann - - * include/coap/resource.h: Replaced custom list structures by - utlist macros. - -2015-03-09 Olaf Bergmann - - * src/uri.c (coap_split_path): Fixed URI parser bug and - removed broken parse iterator. - -2015-03-05 Olaf Bergmann - - * src/coap_time.c (coap_ticks): Changed POSIX implementation - to fixed point arithmetic and removed clock_offset. - -2015-02-21 Olaf Bergmann - - * net.c (coap_send_confirmed): Use fixed point arithmetic - to calculate retransmission timeout. - -2015-02-20 Olaf Bergmann - - * coap_list.[hc]: Moved old list implementation into - sub-directory examples and replaced by linked lists - from utlist.h. As a result, the list must be sorted - explicitly with LL_SORT). - -2015-02-19 Olaf Bergmann - - * net.c (coap_send_confirmed): Fixed retransmission timeout - calculation and renamed transmission parameters according to - Section 4.8 of RFC 7252. - -2015-02-17 Olaf Bergmann - - * major rework to get Contiki and lwip running - * many fixed bugs and warnings - -2014-06-18 Olaf Bergmann - - * mem.c (coap_malloc_type): New functions for allocating memory. - On POSIX systems, coap_malloc_type() and coap_free_type() are just - wrapper functions for malloc() and free(), while on Contiki and - LWIP distinct arrays are used for each type. - -2014-03-09 Olaf Bergmann - - * net.c (coap_cancel): Removed 7.31 again and implemented new - method for cancelling observe relationships. - -2014-02-25 Olaf Bergmann - - * net.c (coap_cancel): Handling of 7.31 responses to cancel - notifications (see Section 4.6 of draft-ietf-core-observe-12) - -2014-02-04 Olaf Bergmann - - * resource.c (coap_print_link): This function now takes an offset - where printing starts. This is used for generating blocks on the - fly. - - * net.c (wellknown_response): Added support for Block2 options - when generating a response for .well-known/core. - - * block.h (coap_opt_block_num): Fixed handling of zero-length - options. COAP_OPT_BLOCK_LAST now returns NULL when the option - value's length is zero. - -2014-01-07 Olaf Bergmann - - * resource.c (coap_print_link): Output partial resource - descriptions. The function now provides a sliding window over the - textual representation of the resource. Output starts at the given - offset and ends at the buffer's upper bound. The meaning of the - return value has changed to allow distinguishing whether or not - the resource description has been truncated at the buffer's upper - bound. - (print_wellknown): Support for the new coap_print_link(). An - additional parameter now is used to provide the offset into the - resource description. The meaning of the return value has been - adjusted accordingly. - -2013-12-23 Olaf Bergmann - - * configure.in: merged with LWIP port from chrysn - . This - introduces new compiler flags WITH_POSIX and WITH_LWIP to - distinguish target platforms. - -2013-09-03 Olaf Bergmann - - * option.h (coap_option_setb): increased size of option type - argument - - * tests/test_error_response.c (t_init_error_response_tests): new - tests for error response generation - - * tests/test_pdu.c (t_encode_pdu5): fixed number for option Accept - - * net.c (coap_new_error_response): fixed option size calculation - -2013-07-04 Olaf Bergmann - - * net.c (coap_new_context): register critical Accept option - - * pdu.c: option codes for Accept and Size1 according to coap-18 - -2013-02-01 Olaf Bergmann - - * coap_time.h (coap_clock_init_impl): fix invalid preprocessor - directive. #warning is now only used for gcc only (close sf bug #15) - - * net.c (wellknown_response): applied patch from chrysn to - fix bug in generation of .well-known/core representation - -2013-01-21 Olaf Bergmann - - * option.h: renamed option field in coap_opt_iterator_t to - next_option to detect erroneous use in old code - -2013-01-18 Olaf Bergmann - - * configure.in: new option --with-tests to enable unit tests - - * tests/testdriver.c: unit tests for parser functions - - * pdu.c (coap_pdu_parse): new PDU parser for Klaus-encoding - according to coap-13 - - * net.c (coap_read): call coap_pdu_parse() to check PDU integrity - - * option.c: Klaus-encoding for coap-13, including new option - iterator interface - -2012-11-20 Olaf Bergmann - - * net.c (next_option_safe): made option parsing more robust in - presence of option jumps - - * pdu.h: new option codes from draft-ietf-core-coap-12 - - * option.c (coap_opt_setlength): new function to set option length - - * uri.c (make_decoded_option): use coap_opt_setlength() instead of - obsolete macro COAP_OPT_SETLENGTH. - -2012-11-19 Olaf Bergmann - - * uri.c (make_decoded_option): use coap_opt_encode() instead of writing - -2012-11-03 Olaf Bergmann - - * net.c (coap_read): read new option encoding - -2012-11-01 Olaf Bergmann - - * option.c (coap_opt_size, coap_opt_value, coap_opt_length): - several functions to access fields of options (possibly preceeded - by option jump) - -2012-10-25 Olaf Bergmann - - * option.c (coap_opt_encode): new function for option encoding - with option jumps - -2012-03-23 Olaf Bergmann - - * examples/client.c (clear_obs): clear observation relationship after - user-specified duration - -2012-03-21 Olaf Bergmann - - * resource.c (print_wellknown): filtering by attributes - -2012-03-19 Olaf Bergmann - - * pdu.c (coap_add_option): allow more than 15 options. - -2012-03-15 Olaf Bergmann - - * examples/client.c (cmdline_uri): split path and query here to - make it easier to include these options in subsequent requests for - block transfer. - -2012-03-14 Olaf Bergmann - - * examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test - -2012-03-13 Olaf Bergmann - - * encode.c (coap_encode_var_bytes): more efficient coding for 0 - -2012-03-11 Olaf Bergmann - - * examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest, - March 24/25, 2012 in Paris, France. - -2012-03-10 Olaf Bergmann - - * block.c: support for block transfer. - -2012-03-07 Olaf Bergmann - - * examples/client.c (usage): new command line options - -B to set timeout after which the main loop is left. - -e to specify a payload (incompatible with -f) - (message_handler): bugfixes - - * resource.h: (coap_method_handler_t): new API for method handlers. - - -Copyright 2012 Olaf Bergmann, TZI -Copying and distribution of this file, with or without modification, are -permitted provided the copyright notice and this notice are preserved. diff --git a/components/coap/libcoap/LICENSE.BSD b/components/coap/libcoap/LICENSE.BSD deleted file mode 100644 index b3d19496a..000000000 --- a/components/coap/libcoap/LICENSE.BSD +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2010--2015, Olaf Bergmann -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - o Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - o 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. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/coap/libcoap/LICENSE.GPL b/components/coap/libcoap/LICENSE.GPL deleted file mode 100644 index d8cf7d463..000000000 --- a/components/coap/libcoap/LICENSE.GPL +++ /dev/null @@ -1,280 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/components/coap/libcoap/Makefile.am b/components/coap/libcoap/Makefile.am deleted file mode 100644 index 15e4881a1..000000000 --- a/components/coap/libcoap/Makefile.am +++ /dev/null @@ -1,180 +0,0 @@ -# Makefile.am for libcoap -# -# Copyright (C) 2010-2015 Olaf Bergmann -# (C) 2015-2016 Carsten Schoenert -# -# This file is part of the CoAP C library libcoap. Please see README and -# COPYING for terms of use. - -## Place generated object files (.o) into the same directory as their source -## files, in order to avoid collisions when non-recursive make is used. -AUTOMAKE_OPTIONS = subdir-objects - -ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 - -## Additional files for the distribution archive -EXTRA_DIST = \ - CONTRIBUTE \ - TODO \ - $(pkgconfig_DATA).in \ - libcoap-$(LIBCOAP_API_VERSION).map \ - libcoap-$(LIBCOAP_API_VERSION).sym \ - examples/coap_list.h \ - tests/test_options.h \ - tests/test_pdu.h \ - tests/test_error_response.h \ - tests/test_sendqueue.h \ - tests/test_uri.h \ - tests/test_wellknown.h - -AM_CFLAGS = -I$(top_builddir)/include/coap -I$(top_srcdir)/include/coap $(WARNING_CFLAGS) -std=c99 - -SUBDIRS = . $(DOC_DIR) tests examples - -## Define a libtool archive target "libcoap-@LIBCOAP_API_VERSION@.la", with -## @LIBCOAP_API_VERSION@ substituted into the generated Makefile at configure -## time. -## The libtool archive file (.la) will be installed into the directory named -## by the predefined variable $(bindir), along with the actual shared library -## file (.so). -lib_LTLIBRARIES = libcoap-@LIBCOAP_API_VERSION@.la - -libcoap_@LIBCOAP_API_VERSION@_la_CFLAGS = \ - -fPIC \ - -fPIE \ - $(AM_CFLAGS) - -## Define the source file list for the "libcoap.la" target. -## Note that it is not necessary to list header files which are already listed -## elsewhere in a _HEADERS variable assignment. -libcoap_@LIBCOAP_API_VERSION@_la_SOURCES = \ - src/address.c \ - src/async.c \ - src/block.c \ - src/coap_io.c \ - src/coap_time.c \ - src/debug.c \ - src/encode.c \ - src/hashkey.c \ - src/mem.c \ - src/net.c \ - src/option.c \ - src/pdu.c \ - src/resource.c \ - src/str.c \ - src/subscribe.c \ - src/uri.c - -## Define the list of public header files and their install location. -## The list defined here will be used within the include/Makefile.am -## and is only a variable because the content is needed also for the -## generating of the symbol mapping file. -libcoap_includedir = $(includedir)/coap/ -libcoap_include_HEADERS = \ - $(top_srcdir)/include/coap/address.h \ - $(top_srcdir)/include/coap/async.h \ - $(top_srcdir)/include/coap/bits.h \ - $(top_srcdir)/include/coap/block.h \ - $(top_builddir)/include/coap/coap.h \ - $(top_srcdir)/include/coap/coap_io.h \ - $(top_srcdir)/include/coap/coap_time.h \ - $(top_srcdir)/include/coap/debug.h \ - $(top_srcdir)/include/coap/encode.h \ - $(top_srcdir)/include/coap/hashkey.h \ - $(top_srcdir)/include/coap/libcoap.h \ - $(top_srcdir)/include/coap/mem.h \ - $(top_srcdir)/include/coap/net.h \ - $(top_srcdir)/include/coap/option.h \ - $(top_srcdir)/include/coap/pdu.h \ - $(top_srcdir)/include/coap/prng.h \ - $(top_srcdir)/include/coap/resource.h \ - $(top_srcdir)/include/coap/str.h \ - $(top_srcdir)/include/coap/subscribe.h \ - $(top_srcdir)/include/coap/uri.h \ - $(top_srcdir)/include/coap/uthash.h \ - $(top_srcdir)/include/coap/utlist.h - -# If there is a API change to something $(LIBCOAP_API_VERSION) > 1 the install -# prefix for the header files has to change to not conflict the older version -# if the user want's to install both versions. There will be something used like -# libcoap_include_HEADERS = \ -# $(top_srcdir)/include/coap-$(LIBCOAP_API_VERSION)/* - - -## Instruct libtool to include API version information in the generated shared -## library file (.so). The library ABI version will later defined in configure.ac, -## so that all version information is kept in one place. -libcoap_@LIBCOAP_API_VERSION@_la_LDFLAGS = \ - -version-info $(LT_LIBCOAP_CURRENT):$(LT_LIBCOAP_REVISION):$(LT_LIBCOAP_AGE) \ - @libcoap_SYMBOLS@ \ - -pie - -## Collect symbols here we want to ignore while building the helper files -## libcoap-$(LIBCOAP_API_VERSION).{map,sym} for the linker. -CTAGS_IGNORE=-I "coap_packet_extract_pbuf coap_pdu_from_pbuf" - -# This helper is called by libcoap-$(LIBCOAP_API_VERSION).{map,sym} to see if -# configure has detected a usable version of the ctags program and aborts if not. -check_ctags: - @if [ "$(CTAGS_PROG)" = "" ]; then \ - echo ;\ - echo "There was no ctags program found by the configure script!" ;\ - echo "ctags is needed for running this target! Please note the warning about the missed ctags program of the configure script." ;\ - echo ;\ - exit 1;\ - fi - -## Helper target to generate the symbol table needed by libtool. -## The .map format is used when ld supports linker scripts, otherwise -## it must fall back to a plain symbol file. -update-map-file: libcoap-$(LIBCOAP_API_VERSION).map libcoap-$(LIBCOAP_API_VERSION).sym - -libcoap-$(LIBCOAP_API_VERSION).map: check_ctags $(libcoap_include_HEADERS) - ( echo "VER_$(LIBCOAP_API_VERSION) {" ; \ - echo "global:" ; \ - $(CTAGS_PROG) $(CTAGS_IGNORE) -f - --c-kinds=p $(libcoap_include_HEADERS) | awk '/^coap_/ { print " " $$1 ";" }' | sort ; \ - echo "local:" ; \ - echo " *;" ; \ - echo "};" ) > $@.new - mv $@.new $@ - -libcoap-$(LIBCOAP_API_VERSION).sym: check_ctags $(libcoap_include_HEADERS) - ( $(CTAGS_PROG) $(CTAGS_IGNORE) -f - --c-kinds=p $(libcoap_include_HEADERS) | awk '/^coap_/ { print $$1 }' | sort ) \ - > $@.new - mv $@.new $@ - -## Install the generated pkg-config file (.pc) into the expected location for -## architecture-dependent package configuration information. Occasionally, -## pkg-config files are also used for architecture-independent data packages, -## in which case the correct install location would be $(datadir)/pkgconfig. -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libcoap-$(LIBCOAP_API_VERSION).pc - -## Define an independent executable script for inclusion in the distribution -## archive. However, it will not be installed on an end user's system due to -## the noinst_ prefix. -dist_noinst_SCRIPTS = autogen.sh - -## various *-local targets -## Remove the helper files for the linker and the pkg-config file if there -## is 'make distclean' called. NOTE: To re create the *.{map,sym} files you -## need to call the target update-map-file after the configure script was -## running! -distclean-local: - rm -f libcoap-$(LIBCOAP_API_VERSION).map - rm -f libcoap-$(LIBCOAP_API_VERSION).sym - rm -f libcoap-$(LIBCOAP_API_VERSION).pc - @echo - @echo " ---> Please note the following important advice! <---" - @echo " The files libcoap-$(LIBCOAP_API_VERSION).{map,sym} are removed by the distclean target!" - @echo " To regenerate this two files you need to call 'make update-map-file' first before any" - @echo " other Make target. Otherwise the build of libcoap will fail!" - @echo - -## Ensure we have actual *.{map,sym} files if we create a release tarball. -dist-local: update-map-file - -## Finaly some phony targets, just to ensure those targets are always buildable -## no matter if the user has created same called files. -.PHONY: update-map-file check_ctags - diff --git a/components/coap/libcoap/Makefile.libcoap b/components/coap/libcoap/Makefile.libcoap deleted file mode 100644 index 122e0faac..000000000 --- a/components/coap/libcoap/Makefile.libcoap +++ /dev/null @@ -1,7 +0,0 @@ -libcoap_src = pdu.c net.c debug.c encode.c uri.c subscribe.c resource.c hashkey.c str.c option.c async.c block.c mem.c coap_io.c - -libcoap_dir := $(filter %libcoap,$(APPDS)) -vpath %c $(libcoap_dir)/src - -# set include path for coap sources -CFLAGS += -I$(libcoap_dir)/include/coap -DCOAP_RESOURCES_NOHASH diff --git a/components/coap/libcoap/README b/components/coap/libcoap/README deleted file mode 100644 index a582dbfe9..000000000 --- a/components/coap/libcoap/README +++ /dev/null @@ -1,30 +0,0 @@ -libcoap: A C implementation of IETF Constrained Application Protocol (RFC 7252) - -Copyright (C) 2010--2015 by Olaf Bergmann - -ABOUT LIBCOAP -============= - -libcoap is a C implementation of a lightweight application-protocol -for devices that are constrained their resources such as computing -power, RF range, memory, bandwith, or network packet sizes. This -protocol, CoAP, is standardized by the IETF as RFC 7252. For further -information related to CoAP, see . - -PACKAGE CONTENTS -================ - -This directory contains a protocol parser and basic networking -functions for platform with support for malloc() and BSD-style -sockets. The examples directory contains a client and a server to -demonstrate the use of this library. - -LICENSE INFORMATION -=================== - -This library is published as open-source software without any warranty -of any kind. Use is permitted under the terms of the GNU General -Public License (GPL), Version 2 or higher, OR the simplified BSD -license. Please refer to LICENSE.GPL oder LICENSE.BSD for further -details. - diff --git a/components/coap/libcoap/README.md b/components/coap/libcoap/README.md deleted file mode 100644 index a582dbfe9..000000000 --- a/components/coap/libcoap/README.md +++ /dev/null @@ -1,30 +0,0 @@ -libcoap: A C implementation of IETF Constrained Application Protocol (RFC 7252) - -Copyright (C) 2010--2015 by Olaf Bergmann - -ABOUT LIBCOAP -============= - -libcoap is a C implementation of a lightweight application-protocol -for devices that are constrained their resources such as computing -power, RF range, memory, bandwith, or network packet sizes. This -protocol, CoAP, is standardized by the IETF as RFC 7252. For further -information related to CoAP, see . - -PACKAGE CONTENTS -================ - -This directory contains a protocol parser and basic networking -functions for platform with support for malloc() and BSD-style -sockets. The examples directory contains a client and a server to -demonstrate the use of this library. - -LICENSE INFORMATION -=================== - -This library is published as open-source software without any warranty -of any kind. Use is permitted under the terms of the GNU General -Public License (GPL), Version 2 or higher, OR the simplified BSD -license. Please refer to LICENSE.GPL oder LICENSE.BSD for further -details. - diff --git a/components/coap/libcoap/TODO b/components/coap/libcoap/TODO deleted file mode 100644 index 503ea7a03..000000000 --- a/components/coap/libcoap/TODO +++ /dev/null @@ -1,61 +0,0 @@ -This is a simple file for all kinds of stuff related on devlopment for -libcoap. Please append (and remove) any issue you think its worthy. - -Classification of issues: - Critical -> Break the library in some kind or a missing feature, maybe not - directly but later - Serious -> No regression on the user side, more likly on the libcoap - development - Minor -> Things that are nice to have, but they are not time critical - -================= -* CRITICAL ISSUES -================= --> Remove the #include "coap_config.h" directive from the public header files. --> Remove #ifdef HAVE_ASSERT_H and so on from the public headers. --> Use coap.h as the only header to include from the public view. --> DTLS functionality - -> Adding DTLS functions based on openssl - -> Bill Benett has starting some improvements here, please contact him - first before starting something --> Proxy functionality - -> A coap-server should be able to act as proxy server - -================ -* SERIOUS ISSUES -================ --> Create some development rules like: - --> How to submit patches? What about pull requests? - --> How to implement/change platform related code? --> Adding some documentation for classical users on how to use the libcoap --> Clean up the various inclusion for #ifdef __cplusplus #extern "C" {} --> Adding additional config options (like --with-pdu-size) --> Split of the platform related code into [foo]_platform.c files --> In general, improving the online doxygen documentation like creating some - additional information for doxygen (startpage, development information, - ...) --> In special, improving ... - Adding prams and return explanation in: - include/coap/coap_io.h - include/coap/option.h - include/coap/net.h - include/coap/resource.h - include/coap/str.h - include/coap/subscribe.h - include/coap/uri.h - Adding @brief directive - include/coap/block.h - include/coap/coap_io.h - include/coap/debug.h - include/coap/encode.h - include/coap/net.h - include/coap/str.h - include/coap/subscribe.h - include/coap/uri.h - -============== -* MINOR ISSUES -============== --> Remove the not needed Makefile.in.old files --> Adding a logo for libcoap - diff --git a/components/coap/libcoap/autogen.sh b/components/coap/libcoap/autogen.sh deleted file mode 100755 index 0b8694e94..000000000 --- a/components/coap/libcoap/autogen.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/sh -e - -# uncomment the set command for debugging -#set -x - -# function to check for needed helper tools -check_helper() { -#echo "Checking for $1 ..." -TOOL=`which "$1" || echo none` - -if [ "$TOOL" = "none" ]; then - echo - echo "Couldn't find '$1'!" - RET=1 -else - RET=0 -fi -} - -PROJECT="libcoap" - -AUTOGEN_FILES=" -INSTALL -aclocal.m4 ar-lib -coap_config.h coap_config.h.in* compile config.guess config.h* config.log config.status config.sub configure -depcomp -doc/Doxyfile doc/doxyfile.stamp doc/doxygen_sqlite3.db doc/Makefile doc/Makefile.in -examples/*.o examples/coap-client examples/coap-server examples/coap-rd -examples/coap-*.5 examples/coap-*.txt examples/Makefile.in -include/coap/coap.h -install-sh -libcoap-1.pc libtool ltmain.sh -missing -Makefile Makefile.in -stamp-h1 src/.dirstamp libcoap*.la* src/*.*o -tests/*.o tests/Makefile tests/testdriver -m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 -" - -AUTOGEN_DIRS=" -.deps -.libs autom4te.cache/ -doc/html/ -examples/.deps/ examples/.libs -src/.deps/ src/.libs/ -tests/.deps/ -" - -# checking for cleaner argument -echo -if [ "$1" = "--clean" ]; then - echo "removing autogerated files ..." - rm -rf $AUTOGEN_FILES $AUTOGEN_DIRS - echo "done" - exit -else - echo "[HINT] You can run 'autogen.sh --clean' to remove all generated files by the autotools." - echo -fi - -# checking for autoreconf -check_helper autoconf -if [ "$RET" = "1" ]; then - echo "You probably need to install the package 'autoconf'." - ERROR=1 -else - echo "Found 'autoconf'." -fi - -# checking for aclocal -check_helper aclocal -if [ "$RET" = "1" ]; then - echo "You probably need to install the package 'automake'." - ERROR=1 -else - echo "Found 'aclocal'." -fi - -# checking for pkg-config -check_helper pkg-config -if [ "$RET" = "1" ]; then - echo "You probably need to install the package 'pkg-config|pkgconf'." - ERROR=1 -else - echo "Found 'pkg-config'." -fi - -# checking for libtool -# The libtool helper maybe installed as 'libtoolize', checking for 'libtool' first. -check_helper libtool -if [ "$RET" = "1" ]; then - # O.k. libtool not found, searching for libtoolize. - check_helper libtoolize - if [ "$RET" = "1" ]; then - echo "You probably need to install the package 'libtool'." - # That's bad, we found nothing! - ERROR=1 - else - echo "Found 'libtoolize'." - break - fi -else - echo "Found 'libtool'." -fi - -# exit if one tool isn't available -if [ "$ERROR" = "1" ]; then - echo - echo "One or more needed tools are missing, exiting ..." - echo "Please install the needed software packages and restart 'autogen.sh' again." - echo - exit 1 -fi - -echo -echo " ---> Found all needed tools! That's fine." -echo - -# countinue otherwise -test -n "$srcdir" || srcdir=`dirname "$0"` -test -n "$srcdir" || srcdir=. - -# Creating the directory m4 before calling autoreconf to -# not struggle with old versions of aclocal. -mkdir -p $srcdir/m4 - -echo "Generating needed autotools files for $PROJECT by running autoreconf ..." -autoreconf --force --install --verbose "$srcdir" - -echo -echo "You can now run 'configure --help' to see possible configuration options." -echo "Otherwise process the configure script to create the makefiles and generated helper files." -echo diff --git a/components/coap/libcoap/configure.ac b/components/coap/libcoap/configure.ac deleted file mode 100644 index 8ae8840e5..000000000 --- a/components/coap/libcoap/configure.ac +++ /dev/null @@ -1,423 +0,0 @@ -# configure.ac for the libcoap package -# -# Copyright (C) 2010-2015 Olaf Bergmann -# (C) 2015-2016 Carsten Schoenert -# -# Please run 'autogen.sh' to let autoconf produce a configure script. - -# Define the libcoap software version here. Note! The libtool versions are -# defined later. -m4_define([libcoap_major_version], [4]) -m4_define([libcoap_minor_version], [1]) -m4_define([libcoap_micro_version], [2]) - -m4_define([libcoap_version],[libcoap_major_version.libcoap_minor_version.libcoap_micro_version]) - -AC_INIT([libcoap], [libcoap_version], [libcoap-developers@lists.sourceforge.net], [libcoap], [https://libcoap.net/]) -AC_PREREQ([2.64]) -AM_INIT_AUTOMAKE([1.10 -Wall no-define no-dist-gzip dist-bzip2]) -PKG_PROG_PKG_CONFIG([0.20]) - -# Generate one configuration header file for building the library itself with -# an autogenerated template. We need later a second one (include/libcoap.h) -# that will be installed alongside the library. -AC_CONFIG_HEADERS([coap_config.h]) - -AC_PROG_CC -AM_PROG_CC_C_O -AC_PROG_SED -AC_CONFIG_MACRO_DIR([m4]) -m4_pattern_allow([AM_PROG_AR]) -AM_PROG_AR - -AC_C_BIGENDIAN - -# enable the automatically build of shared and static libraries, the unit -# tests needs the static library -LT_INIT([shared static]) - -# Setting the libtool versioning -################################################################################### -# # -# To set the version of the library, libtool provides the -version-info # -# parameter, which accepts three numbers, separated by colons, that are called # -# respectively, current, revision and age. Both their name and their behaviour, # -# nowadays, have to be considered fully arbitrary, as the explanation provided # -# in the official documentation is confusing to say the least, and can be, in # -# some cases, considered completely wrong. # -# https://autotools.io/libtool/version.html # -# # -################################################################################### -# -# How to work with the libtool versioning? -# -# Follow the followings steps from top to bottom. This means allways start at point 1 -# if you plan to make a release and change the values. -# Every new library starts with a version 'current' (short 'c') = 0 -# 'revision' (short 'r') = 0 -# 'age' (short 'a') = 0 -# -# Update the libtool versioning only immediately before a public release of libcoap. -# -# 1. If the library source code has changed at all since the last update, then -# increment revision (c:r:a becomes c:r+1:a). -# --> Increase the 'LT_LIBCOAP_REVISION' value with *everey* new software release. -# -# 2. If any interfaces [exported functions or data] have been added, removed, or -# changed since the last update, increment current, and set revision to 0 -# (c:r:a becomes c+1:r=0:a). -# --> Increase the 'LT_LIBCOAP_CURRENT' value whenever as an interface has been added, -# removed or changed. This implies also a API change! You mostly have to change -# the 'libcoap_major_version' then too! -# --> Set 'LT_LIBCOAP_REVISION' to 0. -# -# 3. If any interfaces have been added since the last public release, then increment -# age (c:r:a becomes c:r:a+1). Adding new interfaces will make the library allways -# backwards compatable. -# --> Increase the 'LT_LIBCOAP_AGE' value only if the changes made to the ABI are -# backward compatible. -# -# 4. If any interfaces whitin the library have been removed since the last public -# release, then set age to 0. -# --> Set 'LT_LIBCOAP_AGE' to 0. - -LT_LIBCOAP_CURRENT=0 -LT_LIBCOAP_REVISION=0 -LT_LIBCOAP_AGE=0 -LIBCOAP_SO_VERSION=$LT_LIBCOAP_CURRENT.$LT_LIBCOAP_REVISION.$LT_LIBCOAP_AGE - -# Announce the libtool version -AC_SUBST(LT_LIBCOAP_CURRENT) -AC_SUBST(LT_LIBCOAP_REVISION) -AC_SUBST(LT_LIBCOAP_AGE) -AC_SUBST(LIBCOAP_SO_VERSION) - -# Defining the API Version -LIBCOAP_API_VERSION=1 -AC_SUBST(LIBCOAP_API_VERSION) - -# Adding some default warning options for code QS -# see https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html -# and http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html -WARNING_CFLAGS="\ --pedantic \ --Wall \ --Wextra \ --Wformat-security \ --Winline \ --Wmissing-declarations \ --Wmissing-prototypes \ --Wnested-externs \ --Wpointer-arith \ --Wshadow \ --Wstrict-prototypes \ --Wswitch-default \ --Wswitch-enum \ --Wunused \ -" - -# check whether or not the compiler supports -Wlogical-op (clang does not...) -AX_CHECK_COMPILE_FLAG([-Wlogical-op], [WARNING_CFLAGS="$WARNING_CFLAGS -Wlogical-op"],,[-Werror]) -AX_CHECK_COMPILE_FLAG([-fdiagnostics-color], [CFLAGS="$CFLAGS -fdiagnostics-color"],,[-Werror]) -AX_CHECK_COMPILE_FLAG([-Wunused-result], [WARNING_CFLAGS="$WARNING_CFLAGS -Wunused-result"]) - -AC_SUBST([WARNING_CFLAGS]) - -AX_CHECK_LINK_FLAG([-Wl,--version-script=./libcoap-${LIBCOAP_API_VERSION}.map], - [libcoap_SYMBOLS="-Wl,--version-script=\$(srcdir)/libcoap-\$(LIBCOAP_API_VERSION).map"], - [libcoap_SYMBOLS="-export-symbols \$(srcdir)/libcoap-\$(LIBCOAP_API_VERSION).sym"]) - -AC_SUBST(libcoap_SYMBOLS) - -# configure options -# __documentation__ -AC_ARG_ENABLE([documentation], - [AC_HELP_STRING([--enable-documentation], - [Enable building the documentation [default=yes]])], - [build_documentation="$enableval"], - [build_documentation="yes"]) - -if test "x$build_documentation" = "xyes"; then - # Check for doxygen - AC_PATH_PROGS([DOXYGEN], [doxygen]) - if test -z "$DOXYGEN"; then - if test "x$build_documentation" = "xyes"; then - AC_MSG_WARN([==> Doxygen not found - continuing without Doxygen support]) - AC_MSG_WARN([==> The libcoap html documentation will not be build!]) - doxygen_version="not found" - fi - else - AC_MSG_CHECKING([for compatible doxygen version (>= 1.7.0)]) - doxygen_version=`$DOXYGEN --version` - AS_VERSION_COMPARE([$doxygen_version], [1.7.0], - [AC_MSG_RESULT([no]) - DOXYGEN=""], - [AC_MSG_RESULT([yes $doxygen_version])], - [AC_MSG_RESULT([yes $doxygen_version])]) - if test "x$DOXYGEN" = "x" -a "x$build_documentation" = "xyes"; then - AC_MSG_ERROR([==> Doxygen $doxygen_version too old. Doxygen 1.7+ required for documentation build.]) - AC_MSG_ERROR([==> Install required doxygen version or disable the documentation using --disable-documentation]) - else - # we found doxygen and the version is valid - DOC_DIR=doc - AC_SUBST(DOC_DIR) - # now checking dot (needed for graphics) - AC_PATH_PROG([DOT], [dot]) - if test "x$DOT" = "x"; then - AC_MSG_WARN([==> dot not found - continuing without DOT support]) - AC_MSG_WARN([==> The libcoap html documentation will be build without DOT graphics!]) - HAVE_DOT="NO" - USE_CALL_GRAPH="NO" - else - AC_MSG_CHECKING([for compatible dot version (>= 2.26.0)]) - case $host in - *-freebsd1*) - # csh and tcsh have a different output redirection than more recent shells - # cmd >& file # Redirect both stdout and stderr to file. - # cmd >>& file # Append both stdout and stderr to file. - # cmd1 | cmd2 # pipe stdout to cmd2 - # cmd1 |& cmd2 # pipe stdout and stderr to cmd2 - # Using a explicit call with the default always available C-shell on FreeBSD, - # the user may have installed another shell from a port which we don't know here - dot_version=`export DOT=$DOT && csh -c '$DOT -V |& cut -f5 -d" "'` - ;; - - *) - dot_version=`$DOT -V 2>&1 | cut -f5 -d" "` - ;; - - esac - AS_VERSION_COMPARE([$dot_version], [2.26.0], - [AC_MSG_RESULT([no]) - DOT=""], - [AC_MSG_RESULT([yes $dot_version])], - [AC_MSG_RESULT([yes $dot_version])]) - if test "x$DOT" = "x" -a "x$build_documentation" = "xyes"; then - AC_MSG_WARN([==> Graphviz dot $dot_version too old. Graphviz 2.26+ required for documentation build.]) - AC_MSG_ERROR([==> Install required graphviz version or disable the documentation using --disable-documentation]) - fi - # we found dot and the version is valid - HAVE_DOT="YES" - # let doxygen create caller graphics - # see http://www.stack.nl/~dimitri/doxygen/manual/config.html#cfg_call_graph - USE_CALL_GRAPH="YES" - # exporting the tests to doc/Doxygen(.in) - AC_SUBST(HAVE_DOT) - AC_SUBST(USE_CALL_GRAPH) - fi - fi - fi -fi -AM_CONDITIONAL(BUILD_DOCUMENTATION, [test "x$build_documentation" = "xyes"]) - -AM_CONDITIONAL([HAVE_DOXYGEN], - [test -n "$DOXYGEN"])AM_COND_IF([HAVE_DOXYGEN], - [AC_CONFIG_FILES([doc/Doxyfile])]) - -# configure options -# __tests__ -AC_ARG_ENABLE([tests], - [AC_HELP_STRING([--enable-tests], - [Enable building the binary testsuite [default=no]])], - [build_tests="$enableval"], - [build_tests="no"]) - -if test "x$build_tests" = "xyes"; then - PKG_CHECK_MODULES([CUNIT], - [cunit], - [have_cunit=yes - AC_DEFINE(HAVE_LIBCUNIT, [1], [Define if the system has libcunit])], - [have_cunit=no - AC_MSG_WARN([==> You want to build the testing binary but the pkg-config file cunit.pc could not be found or installed CUnit version is too old!]) - AC_MSG_ERROR([==> Install the package(s) containing the development files for CUnit or disable the testing binary using --disable-tests.]) - ]) -fi -AM_CONDITIONAL(HAVE_CUNIT, [test "x$CUNIT_LIBS" != "x"]) - -# configure options -# __examples__ -AC_ARG_ENABLE([examples], - [AC_HELP_STRING([--enable-examples], - [Enable building the example binaries [default=yes]])], - [build_examples="$enableval"], - [build_examples="yes"]) - -if test "x$build_examples" = "xyes" -a "x$build_documentation" = "xyes"; then - AC_ARG_VAR([A2X], [a2x command]) - AC_PATH_PROG([A2X], [a2x]) - if test "x$A2X" = "x"; then - AC_MSG_WARN([==> You want to build the examples binaries, that is also including the respective manpages but a2x was not found!]) - AC_MSG_ERROR([==> Install the package containg a2x (mostly asciidoc) or disable the build of the examples using --disable-examples.]) - fi - build_examples="yes" -fi -AM_CONDITIONAL(BUILD_EXAMPLES, [test "x$build_examples" = "xyes"]) - -# end configure options -####################### - -########################################## -# from configure options independed checks - -# Check for (ex)ctags binary -# The needed ctags binary name differs on FreeBSD and Linux, on Linux -# systems we search for 'ctags', on FreeBSD for 'exctags' -case $host in - # FreeBSD has exctags from the ctags port - *-freebsd1*) - AC_ARG_VAR([CTAGS_PROG],[the 'exctags' program to use for make target 'update-map-file']) - AC_PATH_PROG([CTAGS_PROG],[exctags],[HAVE_CTAGS=no]) - ;; - - *) - # Linux distributions have exuberant-ctags - AC_ARG_VAR([CTAGS_PROG],[the 'ctags' program to use for make target 'update-map-file']) - AC_PATH_PROG([CTAGS_PROG],[ctags],[HAVE_CTAGS=no]) - ;; - -esac - -if test "x$HAVE_CTAGS" = "xno"; then - AC_MSG_NOTICE([==> Note: '(ex)ctags' command not found!]) - AC_MSG_WARN([==> Without ctags you will be unable to run the target 'update-map-file'!]) - AC_MSG_WARN([==> This is no problem if you just want to build the library libcoap.]) -else - if test "`$CTAGS_PROG --help | grep '\---kinds'`" = ""; then - AC_MSG_NOTICE([==> Note: Your ctags binary does not support '--c-kinds'!]) - AC_MSG_NOTICE([==> Most likely, you are using the GNU Emacs ctag and not exuberant ctag.]) - AC_MSG_WARN([==> This option is required for the target 'update-map-file'.]) - AC_MSG_WARN([==> which is not a problem if you just want to build the library libcoap.]) - fi -fi - -# Checks for header files. -AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h \ - stdlib.h string.h strings.h sys/socket.h sys/time.h \ - time.h unistd.h sys/unistd.h syslog.h]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_TYPE_SIZE_T -AC_TYPE_SSIZE_T - -# Checks for library functions. -AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo \ - strnlen malloc]) - -# Check if -lsocket -lnsl is required (specifically Solaris) -AC_SEARCH_LIBS([socket], [socket]) -AC_SEARCH_LIBS([inet_ntop], [nsl]) - -# Check if clock_gettime() requires librt, when available -AC_SEARCH_LIBS([clock_gettime], [rt]) - -AC_MSG_CHECKING([operating system]) - -# Set up here some extra platform depended defines and variables. -# The "ADDITIONAL_CFLAGS" is need as this stand-alone definition -# for the doxygen part. -case $host in - *-linux* | *-uclinux*) - AC_MSG_RESULT([Linux]) - ADDITIONAL_CFLAGS="-D_GNU_SOURCE -DWITH_POSIX" - - # Not yet needed but if some code definitions have to depend on the platform. - #AC_DEFINE(OS_LINUX, 1, [Linux backend]) - #AC_SUBST(OS_LINUX) - ;; - - *-solaris*) - AC_MSG_RESULT([Solaris]) - # set _XOPEN_SOURCE and _XOPEN_SOURCE_EXTENDED to enable XPG4v2 (POSIX 2004) - # set __EXTENSION__ to shut up feature test macros that restrict -std=c99 - # to only C99 (and nothing newer) - ADDITIONAL_CFLAGS="-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=600 -D__EXTENSIONS__=1 -DWITH_POSIX" - ;; - - *-darwin*) - AC_MSG_RESULT([Darwin]) - ADDITIONAL_CFLAGS="-D_GNU_SOURCE -DWITH_POSIX" - - AC_DEFINE(__APPLE_USE_RFC_3542, 1, [Define this to 1 for ancillary data on MacOS]) - - # Not yet needed but if some code definitions have to depend on the platform. - #AC_DEFINE(OS_MACOS, 1, [MacOS backend]) - #AC_SUBST(OS_MACOS) - ;; - - *-freebsd1*) - AC_MSG_RESULT([FreeBSD-1x]) - ADDITIONAL_CFLAGS="-D_GNU_SOURCE -DWITH_POSIX" - ;; - - *kfreebsd*) - AC_MSG_RESULT([kFreeBSD]) - ADDITIONAL_CFLAGS="-D_GNU_SOURCE -DWITH_POSIX" - ;; - - *) - AC_MSG_WARN([==> Currently unsupported operating system '${host}' !]) - AC_MSG_ERROR([==> If you can provide patches to support your operating system please write to 'libcoap-developers@lists.sourceforge.net'.]) -esac - -# Exporting the PREDEFINED_CFLAGS definition -PREDEFINED_CFLAGS=`echo $ADDITIONAL_CFLAGS | $SED -e 's/-D//g'` -AC_SUBST(PREDEFINED_CFLAGS) - -# And finaly combining the CFLAGS together ... -CFLAGS="$CFLAGS $ADDITIONAL_CFLAGS" - -# Override the various template files, currently just makefiles and the -# pkgconfig *.pc file. -# Later if the API version is changing dont forget to change the -# libcoap-$LIBCOAP_API_VERSION.pc.in file too!! You will have to change -# the 'Cflags' variable to something like -# Cflags: -I${includedir}/coap-@LIBCOAP_API_VERSION@ -# -AC_CONFIG_FILES([ -Makefile -doc/Makefile -examples/Makefile -examples/coap-client.txt -examples/coap-server.txt -examples/coap-rd.txt -include/coap/coap.h -tests/Makefile -libcoap-$LIBCOAP_API_VERSION.pc:libcoap-$LIBCOAP_API_VERSION.pc.in -]) - -AC_OUTPUT - -AC_MSG_RESULT([ -libcoap configuration summary: - libcoap package version : "$PACKAGE_VERSION" - libcoap library version : "$LIBCOAP_SO_VERSION" - libcoap API version : "$LIBCOAP_API_VERSION" - host system : "$host"]); -if test "x$build_documentation" = "xyes" -a "x$DOXYGEN" != "x"; then - AC_MSG_RESULT([ build documentation : "yes"]) - AC_MSG_RESULT([ --> Doxygen around : "yes" ($DOXYGEN $doxygen_version)]) - if test "x$DOT" = "x"; then - AC_MSG_RESULT([ --> dot around : "no" (DOT not found!)]) - else - AC_MSG_RESULT([ --> dot around : "yes" ($DOT $dot_version)]) - fi -else - if test "x$build_documentation" = "xno"; then - AC_MSG_RESULT([ build documentation : "no"]) - fi -fi -if test "x$build_tests" = "xyes"; then - AC_MSG_RESULT([ build unit test binary : "yes"]) -else - AC_MSG_RESULT([ build unit test binary : "no"]) -fi -if test "x$build_examples" = "xyes"; then - AC_MSG_RESULT([ build examples : "yes"]) - if test "x$A2X" != "x"; then - AC_MSG_RESULT([ --> use a2x : "yes" ($A2X)]) - else - AC_MSG_RESULT([ --> use a2x : "no"]) - fi -else - AC_MSG_RESULT([ build examples : "no"]) -fi diff --git a/components/coap/libcoap/doc/Makefile.am b/components/coap/libcoap/doc/Makefile.am deleted file mode 100644 index 27cb237ab..000000000 --- a/components/coap/libcoap/doc/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# doc/Makefile.am -# -# Copyright (C) 2015 Carsten Schoenert -# -# This file is part of the CoAP C library libcoap. Please see README and -# COPYING for terms of use. - - -# We can only perfom the targets in this directory if doxygen is present. - -if HAVE_DOXYGEN - -CLEANFILES = \ - doxygen_sqlite3.db - - -# This target has no check for automated install data! It's simply assumed that -# that the 'all' target is running before, in short: the user has to run first -# 'make' before running 'make install'! -install-data-am: - @if [ ! -d $(top_builddir)/doc/html ]; then \ - echo ;\ - echo " No install data in '$(top_builddir)/doc/html'found! Please run 'make all' first." ;\ - echo ;\ - exit 1 ;\ - fi - $(MKDIR_P) $(DESTDIR)$(htmldir)/html || exit 1 - cp -a $(top_builddir)/doc/html $(DESTDIR)$(htmldir) - find $(DESTDIR)$(htmldir) -type f -name "*.md5" -exec rm {} \; - -uninstall-am: - -rm -rf $(DESTDIR)$(htmldir)/html - -all: - $(DOXYGEN) Doxyfile - -clean-local: - rm -rf $(top_builddir)/doc/html - -distclean-local: clean-local - -endif # HAVE_DOXYGEN diff --git a/components/coap/libcoap/examples/Makefile.am b/components/coap/libcoap/examples/Makefile.am deleted file mode 100644 index 087aef4b4..000000000 --- a/components/coap/libcoap/examples/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -# examples/Makefile.am -# -# Copyright (C) 2015 Carsten Schoenert -# -# This file is part of the CoAP C library libcoap. Please see README and -# COPYING for terms of use. - -# just do nothing if 'BUILD_EXAMPLES' isn't defined -if BUILD_EXAMPLES - -# picking up the default warning CFLAGS into AM_CFLAGS -AM_CFLAGS = -isystem$(top_builddir)/include/coap -I$(top_srcdir)/include/coap $(WARNING_CFLAGS) -std=c99 - -# etsi_iot_01 and tiny are missing -bin_PROGRAMS = coap-client coap-server coap-rd - -coap_client_SOURCES = client.c coap_list.c -coap_client_LDADD = $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la - -coap_server_SOURCES = coap-server.c -coap_server_LDADD = $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la - -coap_rd_SOURCES = coap-rd.c -coap_rd_LDADD = $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la - -# build manuals only if 'BUILD_DOCUMENTATION' is defined -if BUILD_DOCUMENTATION - -# building the manpages -TXT5 = coap-client.txt \ - coap-rd.txt \ - coap-server.txt - -MAN5 = $(TXT5:%.txt=%.5) - -man5_MANS = $(MAN5) - -.txt.5: - $(A2X) --doctype manpage --format manpage $< - -CLEANFILES = *.5 -endif # BUILD_DOCUMENTATION - -endif # BUILD_EXAMPLES diff --git a/components/coap/libcoap/examples/README.etsi_iot b/components/coap/libcoap/examples/README.etsi_iot deleted file mode 100644 index 9a5a58f49..000000000 --- a/components/coap/libcoap/examples/README.etsi_iot +++ /dev/null @@ -1,43 +0,0 @@ -This README documents the test cases supported for the 1st ETSI CoAP -plugtest on March 24/25 in Paris, France. - - -Legend: - [+] full support - [o] partial support - [-] no support - [?] needs check - [ ] has open issues - -Mandatory Tests - -[+] TD_COAP_CORE_01 Perform GET transaction (CON mode) -[+] TD_COAP_CORE_02 Perform POST transaction (CON mode) -[+] TD_COAP_CORE_03 Perform PUT transaction (CON mode) -[+] TD_COAP_CORE_04 Perform DELETE transaction (CON mode) -[+] TD_COAP_CORE_05 Perform GET transaction (NON mode) -[+] TD_COAP_CORE_06 Perform POST transaction (NON mode) -[+] TD_COAP_CORE_07 Perform PUT transaction (NON mode) -[+] TD_COAP_CORE_08 Perform DELETE transaction (NON mode) -[+] TD_COAP_CORE_09 Perform GET transaction with delayed response (CON mode, no piggyback) -[+] TD_COAP_CORE_10 Handle request containing Token option -[+] TD_COAP_CORE_11 Handle request not containing Token option -[+] TD_COAP_CORE_12 Handle request containing several Uri-Path options -[+] TD_COAP_CORE_13 Handle request containing several Uri-Query options -[?] TD_COAP_CORE_14 Interoperate in lossy context (CON mode, piggybacked response) -[?] TD_COAP_CORE_15 Interoperate in lossy context (CON mode, delayed response) - -Optional Tests - -[ ] TD_COAP_LINK_01 Access to well-known interface for resource discovery -[-] TD_COAP_LINK_02 Use filtered requests for limiting discovery results -[+] TD_COAP_BLOCK_01 Handle GET blockwise transfer for large resource (early negotiation) -[+] TD_COAP_BLOCK_02 Handle GET blockwise transfer for large resource (late negotiation) -[-] TD_COAP_BLOCK_03 Handle PUT blockwise transfer for large resource -[-] TD_COAP_BLOCK_04 Handle POST blockwise transfer for large resource -[-] TD_COAP_OBS_01 Handle resource observation -[-] TD_COAP_OBS_02 Stop resource observation -[-] TD_COAP_OBS_03 Client detection of deregistration (Max-Age) -[-] TD_COAP_OBS_04 Server detection of deregistration (client OFF) -[-] TD_COAP_OBS_05 Server detection of deregistration (explicit RST) - diff --git a/components/coap/libcoap/examples/client.c b/components/coap/libcoap/examples/client.c deleted file mode 100644 index c5457a7ae..000000000 --- a/components/coap/libcoap/examples/client.c +++ /dev/null @@ -1,1305 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - -/* coap-client -- simple CoAP client - * - * Copyright (C) 2010--2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms of - * use. - */ - -#include "coap_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "coap.h" -#include "coap_list.h" - -int flags = 0; - -static unsigned char _token_data[8]; -str the_token = { 0, _token_data }; - -#define FLAGS_BLOCK 0x01 - -static coap_list_t *optlist = NULL; -/* Request URI. - * TODO: associate the resources with transaction id and make it expireable */ -static coap_uri_t uri; -static str proxy = { 0, NULL }; -static unsigned short proxy_port = COAP_DEFAULT_PORT; - -/* reading is done when this flag is set */ -static int ready = 0; - -static str output_file = { 0, NULL }; /* output file name */ -static FILE *file = NULL; /* output file stream */ - -static str payload = { 0, NULL }; /* optional payload to send */ - -unsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ - -typedef unsigned char method_t; -method_t method = 1; /* the method we are using in our requests */ - -coap_block_t block = { .num = 0, .m = 0, .szx = 6 }; - -unsigned int wait_seconds = 90; /* default timeout in seconds */ -coap_tick_t max_wait; /* global timeout (changed by set_timeout()) */ - -unsigned int obs_seconds = 30; /* default observe time */ -coap_tick_t obs_wait = 0; /* timeout for current subscription */ - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -static inline void -set_timeout(coap_tick_t *timer, const unsigned int seconds) { - coap_ticks(timer); - *timer += seconds * COAP_TICKS_PER_SECOND; -} - -static int -append_to_output(const unsigned char *data, size_t len) { - size_t written; - - if (!file) { - if (!output_file.s || (output_file.length && output_file.s[0] == '-')) - file = stdout; - else { - if (!(file = fopen((char *)output_file.s, "w"))) { - perror("fopen"); - return -1; - } - } - } - - do { - written = fwrite(data, 1, len, file); - len -= written; - data += written; - } while ( written && len ); - fflush(file); - - return 0; -} - -static void -close_output(void) { - if (file) { - - /* add a newline before closing in case were writing to stdout */ - if (!output_file.s || (output_file.length && output_file.s[0] == '-')) - fwrite("\n", 1, 1, file); - - fflush(file); - fclose(file); - } -} - -static int -order_opts(void *a, void *b) { - coap_option *o1, *o2; - - if (!a || !b) - return a < b ? -1 : 1; - - o1 = (coap_option *)(((coap_list_t *)a)->data); - o2 = (coap_option *)(((coap_list_t *)b)->data); - - return (COAP_OPTION_KEY(*o1) < COAP_OPTION_KEY(*o2)) - ? -1 - : (COAP_OPTION_KEY(*o1) != COAP_OPTION_KEY(*o2)); -} - -static coap_pdu_t * -coap_new_request(coap_context_t *ctx, - method_t m, - coap_list_t **options, - unsigned char *data, - size_t length) { - coap_pdu_t *pdu; - coap_list_t *opt; - - if ( ! ( pdu = coap_new_pdu() ) ) - return NULL; - - pdu->hdr->type = msgtype; - pdu->hdr->id = coap_new_message_id(ctx); - pdu->hdr->code = m; - - pdu->hdr->token_length = the_token.length; - if ( !coap_add_token(pdu, the_token.length, the_token.s)) { - debug("cannot add token to request\n"); - } - - coap_show_pdu(pdu); - - if (options) { - /* sort options for delta encoding */ - LL_SORT((*options), order_opts); - - LL_FOREACH((*options), opt) { - coap_option *o = (coap_option *)(opt->data); - coap_add_option(pdu, - COAP_OPTION_KEY(*o), - COAP_OPTION_LENGTH(*o), - COAP_OPTION_DATA(*o)); - } - } - - if (length) { - if ((flags & FLAGS_BLOCK) == 0) - coap_add_data(pdu, length, data); - else - coap_add_block(pdu, length, data, block.num, block.szx); - } - - return pdu; -} - -static coap_tid_t -clear_obs(coap_context_t *ctx, - const coap_endpoint_t *local_interface, - const coap_address_t *remote) { - coap_pdu_t *pdu; - coap_list_t *option; - coap_tid_t tid = COAP_INVALID_TID; - unsigned char buf[2]; - - /* create bare PDU w/o any option */ - pdu = coap_pdu_init(msgtype, - COAP_REQUEST_GET, - coap_new_message_id(ctx), - COAP_MAX_PDU_SIZE); - - if (!pdu) { - return tid; - } - - if (!coap_add_token(pdu, the_token.length, the_token.s)) { - coap_log(LOG_CRIT, "cannot add token"); - goto error; - } - - for (option = optlist; option; option = option->next ) { - coap_option *o = (coap_option *)(option->data); - if (COAP_OPTION_KEY(*o) == COAP_OPTION_URI_HOST) { - if (!coap_add_option(pdu, - COAP_OPTION_KEY(*o), - COAP_OPTION_LENGTH(*o), - COAP_OPTION_DATA(*o))) { - goto error; - } - break; - } - } - - if (!coap_add_option(pdu, - COAP_OPTION_OBSERVE, - coap_encode_var_bytes(buf, COAP_OBSERVE_CANCEL), - buf)) { - coap_log(LOG_CRIT, "cannot add option Observe: %u", COAP_OBSERVE_CANCEL); - goto error; - } - - for (option = optlist; option; option = option->next ) { - coap_option *o = (coap_option *)(option->data); - switch (COAP_OPTION_KEY(*o)) { - case COAP_OPTION_URI_PORT : - case COAP_OPTION_URI_PATH : - case COAP_OPTION_URI_QUERY : - if (!coap_add_option (pdu, - COAP_OPTION_KEY(*o), - COAP_OPTION_LENGTH(*o), - COAP_OPTION_DATA(*o))) { - goto error; - } - break; - default: - ; - } - } - - coap_show_pdu(pdu); - - if (pdu->hdr->type == COAP_MESSAGE_CON) - tid = coap_send_confirmed(ctx, local_interface, remote, pdu); - else - tid = coap_send(ctx, local_interface, remote, pdu); - - if (tid == COAP_INVALID_TID) { - debug("clear_obs: error sending new request"); - coap_delete_pdu(pdu); - } else if (pdu->hdr->type != COAP_MESSAGE_CON) - coap_delete_pdu(pdu); - - return tid; - error: - - coap_delete_pdu(pdu); - return tid; -} - -static int -resolve_address(const str *server, struct sockaddr *dst) { - - struct addrinfo *res, *ainfo; - struct addrinfo hints; - static char addrstr[256]; - int error, len=-1; - - memset(addrstr, 0, sizeof(addrstr)); - if (server->length) - memcpy(addrstr, server->s, server->length); - else - memcpy(addrstr, "localhost", 9); - - memset ((char *)&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_DGRAM; - hints.ai_family = AF_UNSPEC; - - error = getaddrinfo(addrstr, NULL, &hints, &res); - - if (error != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); - return error; - } - - for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { - switch (ainfo->ai_family) { - case AF_INET6: - case AF_INET: - len = ainfo->ai_addrlen; - memcpy(dst, ainfo->ai_addr, len); - goto finish; - default: - ; - } - } - - finish: - freeaddrinfo(res); - return len; -} - -#define HANDLE_BLOCK1(Pdu) \ - ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \ - ((flags & FLAGS_BLOCK) == 0) && \ - ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \ - (Pdu)->hdr->code == COAP_RESPONSE_CODE(204))) - -static inline int -check_token(coap_pdu_t *received) { - return received->hdr->token_length == the_token.length && - memcmp(received->hdr->token, the_token.s, the_token.length) == 0; -} - -static void -message_handler(struct coap_context_t *ctx, - const coap_endpoint_t *local_interface, - const coap_address_t *remote, - coap_pdu_t *sent, - coap_pdu_t *received, - const coap_tid_t id UNUSED_PARAM) { - - coap_pdu_t *pdu = NULL; - coap_opt_t *block_opt; - coap_opt_iterator_t opt_iter; - unsigned char buf[4]; - coap_list_t *option; - size_t len; - unsigned char *databuf; - coap_tid_t tid; - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { - debug("** process incoming %d.%02d response:\n", - (received->hdr->code >> 5), received->hdr->code & 0x1F); - coap_show_pdu(received); - } -#endif - - /* check if this is a response to our original request */ - if (!check_token(received)) { - /* drop if this was just some message, or send RST in case of notification */ - if (!sent && (received->hdr->type == COAP_MESSAGE_CON || - received->hdr->type == COAP_MESSAGE_NON)) - coap_send_rst(ctx, local_interface, remote, received); - return; - } - - if (received->hdr->type == COAP_MESSAGE_RST) { - info("got RST\n"); - return; - } - - /* output the received data, if any */ - if (COAP_RESPONSE_CLASS(received->hdr->code) == 2) { - - /* set obs timer if we have successfully subscribed a resource */ - if (sent && coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter)) { - debug("observation relationship established, set timeout to %d\n", obs_seconds); - set_timeout(&obs_wait, obs_seconds); - } - - /* Got some data, check if block option is set. Behavior is undefined if - * both, Block1 and Block2 are present. */ - block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter); - if (block_opt) { /* handle Block2 */ - unsigned short blktype = opt_iter.type; - - /* TODO: check if we are looking at the correct block number */ - if (coap_get_data(received, &len, &databuf)) - append_to_output(databuf, len); - - if(COAP_OPT_BLOCK_MORE(block_opt)) { - /* more bit is set */ - debug("found the M bit, block size is %u, block nr. %u\n", - COAP_OPT_BLOCK_SZX(block_opt), - coap_opt_block_num(block_opt)); - - /* create pdu with request for next block */ - pdu = coap_new_request(ctx, method, NULL, NULL, 0); /* first, create bare PDU w/o any option */ - if ( pdu ) { - /* add URI components from optlist */ - for (option = optlist; option; option = option->next ) { - coap_option *o = (coap_option *)(option->data); - switch (COAP_OPTION_KEY(*o)) { - case COAP_OPTION_URI_HOST : - case COAP_OPTION_URI_PORT : - case COAP_OPTION_URI_PATH : - case COAP_OPTION_URI_QUERY : - coap_add_option (pdu, - COAP_OPTION_KEY(*o), - COAP_OPTION_LENGTH(*o), - COAP_OPTION_DATA(*o)); - break; - default: - ; /* skip other options */ - } - } - - /* finally add updated block option from response, clear M bit */ - /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ - debug("query block %d\n", (coap_opt_block_num(block_opt) + 1)); - coap_add_option(pdu, - blktype, - coap_encode_var_bytes(buf, - ((coap_opt_block_num(block_opt) + 1) << 4) | - COAP_OPT_BLOCK_SZX(block_opt)), buf); - - if (pdu->hdr->type == COAP_MESSAGE_CON) - tid = coap_send_confirmed(ctx, local_interface, remote, pdu); - else - tid = coap_send(ctx, local_interface, remote, pdu); - - if (tid == COAP_INVALID_TID) { - debug("message_handler: error sending new request"); - coap_delete_pdu(pdu); - } else { - set_timeout(&max_wait, wait_seconds); - if (pdu->hdr->type != COAP_MESSAGE_CON) - coap_delete_pdu(pdu); - } - - return; - } - } - } else { /* no Block2 option */ - block_opt = coap_check_option(received, COAP_OPTION_BLOCK1, &opt_iter); - - if (block_opt) { /* handle Block1 */ - unsigned int szx = COAP_OPT_BLOCK_SZX(block_opt); - unsigned int num = coap_opt_block_num(block_opt); - debug("found Block1 option, block size is %u, block nr. %u\n", szx, num); - if (szx != block.szx) { - unsigned int bytes_sent = ((block.num + 1) << (block.szx + 4)); - if (bytes_sent % (1 << (szx + 4)) == 0) { - /* Recompute the block number of the previous packet given the new block size */ - block.num = (bytes_sent >> (szx + 4)) - 1; - block.szx = szx; - debug("new Block1 size is %u, block number %u completed\n", (1 << (block.szx + 4)), block.num); - } else { - debug("ignoring request to increase Block1 size, " - "next block is not aligned on requested block size boundary. " - "(%u x %u mod %u = %u != 0)\n", - block.num + 1, (1 << (block.szx + 4)), (1 << (szx + 4)), - bytes_sent % (1 << (szx + 4))); - } - } - - if (payload.length <= (block.num+1) * (1 << (block.szx + 4))) { - debug("upload ready\n"); - ready = 1; - return; - } - - /* create pdu with request for next block */ - pdu = coap_new_request(ctx, method, NULL, NULL, 0); /* first, create bare PDU w/o any option */ - if (pdu) { - - /* add URI components from optlist */ - for (option = optlist; option; option = option->next ) { - coap_option *o = (coap_option *)(option->data); - switch (COAP_OPTION_KEY(*o)) { - case COAP_OPTION_URI_HOST : - case COAP_OPTION_URI_PORT : - case COAP_OPTION_URI_PATH : - case COAP_OPTION_CONTENT_FORMAT : - case COAP_OPTION_URI_QUERY : - coap_add_option (pdu, - COAP_OPTION_KEY(*o), - COAP_OPTION_LENGTH(*o), - COAP_OPTION_DATA(*o)); - break; - default: - ; /* skip other options */ - } - } - - /* finally add updated block option from response, clear M bit */ - /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ - block.num++; - block.m = ((block.num+1) * (1 << (block.szx + 4)) < payload.length); - - debug("send block %d\n", block.num); - coap_add_option(pdu, - COAP_OPTION_BLOCK1, - coap_encode_var_bytes(buf, - (block.num << 4) | (block.m << 3) | block.szx), buf); - - coap_add_block(pdu, - payload.length, - payload.s, - block.num, - block.szx); - coap_show_pdu(pdu); - if (pdu->hdr->type == COAP_MESSAGE_CON) - tid = coap_send_confirmed(ctx, local_interface, remote, pdu); - else - tid = coap_send(ctx, local_interface, remote, pdu); - - if (tid == COAP_INVALID_TID) { - debug("message_handler: error sending new request"); - coap_delete_pdu(pdu); - } else { - set_timeout(&max_wait, wait_seconds); - if (pdu->hdr->type != COAP_MESSAGE_CON) - coap_delete_pdu(pdu); - } - - return; - } - } else { - /* There is no block option set, just read the data and we are done. */ - if (coap_get_data(received, &len, &databuf)) - append_to_output(databuf, len); - } - } - } else { /* no 2.05 */ - - /* check if an error was signaled and output payload if so */ - if (COAP_RESPONSE_CLASS(received->hdr->code) >= 4) { - fprintf(stderr, "%d.%02d", - (received->hdr->code >> 5), received->hdr->code & 0x1F); - if (coap_get_data(received, &len, &databuf)) { - fprintf(stderr, " "); - while(len--) - fprintf(stderr, "%c", *databuf++); - } - fprintf(stderr, "\n"); - } - - } - - /* finally send new request, if needed */ - if (pdu && coap_send(ctx, local_interface, remote, pdu) == COAP_INVALID_TID) { - debug("message_handler: error sending response"); - } - coap_delete_pdu(pdu); - - /* our job is done, we can exit at any time */ - ready = coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter) == NULL; -} - -static void -usage( const char *program, const char *version) { - const char *p; - - p = strrchr( program, '/' ); - if ( p ) - program = ++p; - - fprintf( stderr, "%s v%s -- a small CoAP implementation\n" - "(c) 2010-2015 Olaf Bergmann \n\n" - "usage: %s [-A type...] [-t type] [-b [num,]size] [-B seconds] [-e text]\n" - "\t\t[-m method] [-N] [-o file] [-P addr[:port]] [-p port]\n" - "\t\t[-s duration] [-O num,text] [-T string] [-v num] [-a addr] [-U] URI\n\n" - "\tURI can be an absolute or relative coap URI,\n" - "\t-a addr\tthe local interface address to use\n" - "\t-A type...\taccepted media types as comma-separated list of\n" - "\t\t\tsymbolic or numeric values\n" - "\t-t type\t\tcontent format for given resource for PUT/POST\n" - "\t-b [num,]size\tblock size to be used in GET/PUT/POST requests\n" - "\t \t\t(value must be a multiple of 16 not larger than 1024)\n" - "\t \t\tIf num is present, the request chain will start at\n" - "\t \t\tblock num\n" - "\t-B seconds\tbreak operation after waiting given seconds\n" - "\t\t\t(default is %d)\n" - "\t-e text\t\tinclude text as payload (use percent-encoding for\n" - "\t\t\tnon-ASCII characters)\n" - "\t-f file\t\tfile to send with PUT/POST (use '-' for STDIN)\n" - "\t-m method\trequest method (get|put|post|delete), default is 'get'\n" - "\t-N\t\tsend NON-confirmable message\n" - "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n" - "\t-p port\t\tlisten on specified port\n" - "\t-s duration\tsubscribe for given duration [s]\n" - "\t-v num\t\tverbosity level (default: 3)\n" - "\t-O num,text\tadd option num with contents text to request\n" - "\t-P addr[:port]\tuse proxy (automatically adds Proxy-Uri option to\n" - "\t\t\trequest)\n" - "\t-T token\tinclude specified token\n" - "\t-U\t\tnever include Uri-Host or Uri-Port options\n" - "\n" - "examples:\n" - "\tcoap-client -m get coap://[::1]/\n" - "\tcoap-client -m get coap://[::1]/.well-known/core\n" - "\tcoap-client -m get -T cafe coap://[::1]/time\n" - "\techo 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n" - ,program, version, program, wait_seconds); -} - -static coap_list_t * -new_option_node(unsigned short key, unsigned int length, unsigned char *data) { - coap_list_t *node; - - node = coap_malloc(sizeof(coap_list_t) + sizeof(coap_option) + length); - - if (node) { - coap_option *option; - option = (coap_option *)(node->data); - COAP_OPTION_KEY(*option) = key; - COAP_OPTION_LENGTH(*option) = length; - memcpy(COAP_OPTION_DATA(*option), data, length); - } else { - coap_log(LOG_DEBUG, "new_option_node: malloc\n"); - } - - return node; -} - -typedef struct { - unsigned char code; - char *media_type; -} content_type_t; - -static void -cmdline_content_type(char *arg, unsigned short key) { - static content_type_t content_types[] = { - { 0, "plain" }, - { 0, "text/plain" }, - { 40, "link" }, - { 40, "link-format" }, - { 40, "application/link-format" }, - { 41, "xml" }, - { 41, "application/xml" }, - { 42, "binary" }, - { 42, "octet-stream" }, - { 42, "application/octet-stream" }, - { 47, "exi" }, - { 47, "application/exi" }, - { 50, "json" }, - { 50, "application/json" }, - { 60, "cbor" }, - { 60, "application/cbor" }, - { 255, NULL } - }; - coap_list_t *node; - unsigned char i, value[10]; - int valcnt = 0; - unsigned char buf[2]; - char *p, *q = arg; - - while (q && *q) { - p = strchr(q, ','); - - if (isdigit(*q)) { - if (p) - *p = '\0'; - value[valcnt++] = atoi(q); - } else { - for (i=0; - content_types[i].media_type && - strncmp(q, content_types[i].media_type, p ? (size_t)(p-q) : strlen(q)) != 0 ; - ++i) - ; - - if (content_types[i].media_type) { - value[valcnt] = content_types[i].code; - valcnt++; - } else { - warn("W: unknown content-format '%s'\n",arg); - } - } - - if (!p || key == COAP_OPTION_CONTENT_TYPE) - break; - - q = p+1; - } - - for (i = 0; i < valcnt; ++i) { - node = new_option_node(key, coap_encode_var_bytes(buf, value[i]), buf); - if (node) { - LL_PREPEND(optlist, node); - } - } -} - -/** - * Sets global URI options according to the URI passed as @p arg. - * This function returns 0 on success or -1 on error. - * - * @param arg The URI string. - * @param create_uri_opts Flags that indicate whether Uri-Host and - * Uri-Port should be suppressed. - * @return 0 on success, -1 otherwise - */ -static int -cmdline_uri(char *arg, int create_uri_opts) { - unsigned char portbuf[2]; -#define BUFSIZE 40 - unsigned char _buf[BUFSIZE]; - unsigned char *buf = _buf; - size_t buflen; - int res; - - if (proxy.length) { /* create Proxy-Uri from argument */ - size_t len = strlen(arg); - while (len > 270) { - coap_insert(&optlist, - new_option_node(COAP_OPTION_PROXY_URI, - 270, - (unsigned char *)arg)); - - len -= 270; - arg += 270; - } - - coap_insert(&optlist, - new_option_node(COAP_OPTION_PROXY_URI, - len, - (unsigned char *)arg)); - - } else { /* split arg into Uri-* options */ - if (coap_split_uri((unsigned char *)arg, strlen(arg), &uri) < 0) { - return -1; - } - - if (uri.port != COAP_DEFAULT_PORT && create_uri_opts) { - coap_insert(&optlist, - new_option_node(COAP_OPTION_URI_PORT, - coap_encode_var_bytes(portbuf, uri.port), - portbuf)); - } - - if (uri.path.length) { - buflen = BUFSIZE; - res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - - while (res--) { - coap_insert(&optlist, - new_option_node(COAP_OPTION_URI_PATH, - COAP_OPT_LENGTH(buf), - COAP_OPT_VALUE(buf))); - - buf += COAP_OPT_SIZE(buf); - } - } - - if (uri.query.length) { - buflen = BUFSIZE; - buf = _buf; - res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); - - while (res--) { - coap_insert(&optlist, - new_option_node(COAP_OPTION_URI_QUERY, - COAP_OPT_LENGTH(buf), - COAP_OPT_VALUE(buf))); - - buf += COAP_OPT_SIZE(buf); - } - } - } - - return 0; -} - -static int -cmdline_blocksize(char *arg) { - unsigned short size; - - again: - size = 0; - while(*arg && *arg != ',') - size = size * 10 + (*arg++ - '0'); - - if (*arg == ',') { - arg++; - block.num = size; - goto again; - } - - if (size) - block.szx = (coap_fls(size >> 4) - 1) & 0x07; - - flags |= FLAGS_BLOCK; - return 1; -} - -/* Called after processing the options from the commandline to set - * Block1 or Block2 depending on method. */ -static void -set_blocksize(void) { - static unsigned char buf[4]; /* hack: temporarily take encoded bytes */ - unsigned short opt; - unsigned int opt_length; - - if (method != COAP_REQUEST_DELETE) { - opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 : COAP_OPTION_BLOCK1; - - block.m = (opt == COAP_OPTION_BLOCK1) && - ((1u << (block.szx + 4)) < payload.length); - - opt_length = coap_encode_var_bytes(buf, - (block.num << 4 | block.m << 3 | block.szx)); - - coap_insert(&optlist, new_option_node(opt, opt_length, buf)); - } -} - -static void -cmdline_subscribe(char *arg) { - obs_seconds = atoi(arg); - coap_insert(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL)); -} - -static int -cmdline_proxy(char *arg) { - char *proxy_port_str = strrchr((const char *)arg, ':'); /* explicit port ? */ - if (proxy_port_str) { - char *ipv6_delimiter = strrchr((const char *)arg, ']'); - if (!ipv6_delimiter) { - if (proxy_port_str == strchr((const char *)arg, ':')) { - /* host:port format - host not in ipv6 hexadecimal string format */ - *proxy_port_str++ = '\0'; /* split */ - proxy_port = atoi(proxy_port_str); - } - } else { - arg = strchr((const char *)arg, '['); - if (!arg) return 0; - arg++; - *ipv6_delimiter = '\0'; /* split */ - if (ipv6_delimiter + 1 == proxy_port_str++) { - /* [ipv6 address]:port */ - proxy_port = atoi(proxy_port_str); - } - } - } - - proxy.length = strlen(arg); - if ( (proxy.s = coap_malloc(proxy.length + 1)) == NULL) { - proxy.length = 0; - return 0; - } - - memcpy(proxy.s, arg, proxy.length+1); - return 1; -} - -static inline void -cmdline_token(char *arg) { - strncpy((char *)the_token.s, arg, min(sizeof(_token_data), strlen(arg))); - the_token.length = strlen(arg); -} - -static void -cmdline_option(char *arg) { - unsigned int num = 0; - - while (*arg && *arg != ',') { - num = num * 10 + (*arg - '0'); - ++arg; - } - if (*arg == ',') - ++arg; - - coap_insert(&optlist, - new_option_node(num, strlen(arg), (unsigned char *)arg)); -} - -/** - * Calculates decimal value from hexadecimal ASCII character given in - * @p c. The caller must ensure that @p c actually represents a valid - * heaxdecimal character, e.g. with isxdigit(3). - * - * @hideinitializer - */ -#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) - -/** - * Decodes percent-encoded characters while copying the string @p seg - * of size @p length to @p buf. The caller of this function must - * ensure that the percent-encodings are correct (i.e. the character - * '%' is always followed by two hex digits. and that @p buf provides - * sufficient space to hold the result. This function is supposed to - * be called by make_decoded_option() only. - * - * @param seg The segment to decode and copy. - * @param length Length of @p seg. - * @param buf The result buffer. - */ -static void -decode_segment(const unsigned char *seg, size_t length, unsigned char *buf) { - - while (length--) { - - if (*seg == '%') { - *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); - - seg += 2; length -= 2; - } else { - *buf = *seg; - } - - ++buf; ++seg; - } -} - -/** - * Runs through the given path (or query) segment and checks if - * percent-encodings are correct. This function returns @c -1 on error - * or the length of @p s when decoded. - */ -static int -check_segment(const unsigned char *s, size_t length) { - - size_t n = 0; - - while (length) { - if (*s == '%') { - if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) - return -1; - - s += 2; - length -= 2; - } - - ++s; ++n; --length; - } - - return n; -} - -static int -cmdline_input(char *text, str *buf) { - int len; - len = check_segment((unsigned char *)text, strlen(text)); - - if (len < 0) - return 0; - - buf->s = (unsigned char *)coap_malloc(len); - if (!buf->s) - return 0; - - buf->length = len; - decode_segment((unsigned char *)text, strlen(text), buf->s); - return 1; -} - -static int -cmdline_input_from_file(char *filename, str *buf) { - FILE *inputfile = NULL; - ssize_t len; - int result = 1; - struct stat statbuf; - - if (!filename || !buf) - return 0; - - if (filename[0] == '-' && !filename[1]) { /* read from stdin */ - buf->length = 20000; - buf->s = (unsigned char *)coap_malloc(buf->length); - if (!buf->s) - return 0; - - inputfile = stdin; - } else { - /* read from specified input file */ - inputfile = fopen(filename, "r"); - if ( !inputfile ) { - perror("cmdline_input_from_file: fopen"); - return 0; - } - - if (fstat(fileno(inputfile), &statbuf) < 0) { - perror("cmdline_input_from_file: stat"); - fclose(inputfile); - return 0; - } - - buf->length = statbuf.st_size; - buf->s = (unsigned char *)coap_malloc(buf->length); - if (!buf->s) { - fclose(inputfile); - return 0; - } - } - - len = fread(buf->s, 1, buf->length, inputfile); - - if (len < 0 || ((size_t)len < buf->length)) { - if (ferror(inputfile) != 0) { - perror("cmdline_input_from_file: fread"); - coap_free(buf->s); - buf->length = 0; - buf->s = NULL; - result = 0; - } else { - buf->length = len; - } - } - - if (inputfile != stdin) - fclose(inputfile); - - return result; -} - -static method_t -cmdline_method(char *arg) { - static char *methods[] = - { 0, "get", "post", "put", "delete", 0}; - unsigned char i; - - for (i=1; methods[i] && strcasecmp(arg,methods[i]) != 0 ; ++i) - ; - - return i; /* note that we do not prevent illegal methods */ -} - -static coap_context_t * -get_context(const char *node, const char *port) { - coap_context_t *ctx = NULL; - int s; - struct addrinfo hints; - struct addrinfo *result, *rp; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; - - s = getaddrinfo(node, port, &hints, &result); - if ( s != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); - return NULL; - } - - /* iterate through results until success */ - for (rp = result; rp != NULL; rp = rp->ai_next) { - coap_address_t addr; - - if (rp->ai_addrlen <= sizeof(addr.addr)) { - coap_address_init(&addr); - addr.size = rp->ai_addrlen; - memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); - - ctx = coap_new_context(&addr); - if (ctx) { - /* TODO: output address:port for successful binding */ - goto finish; - } - } - } - - fprintf(stderr, "no context available for interface '%s'\n", node); - - finish: - freeaddrinfo(result); - return ctx; -} - -int -main(int argc, char **argv) { - coap_context_t *ctx = NULL; - coap_address_t dst; - static char addr[INET6_ADDRSTRLEN]; - void *addrptr = NULL; - fd_set readfds; - struct timeval tv; - int result; - coap_tick_t now; - coap_queue_t *nextpdu; - coap_pdu_t *pdu; - static str server; - unsigned short port = COAP_DEFAULT_PORT; - char port_str[NI_MAXSERV] = "0"; - char node_str[NI_MAXHOST] = ""; - int opt, res; - coap_log_t log_level = LOG_WARNING; - coap_tid_t tid = COAP_INVALID_TID; - int create_uri_opts = 1; - - while ((opt = getopt(argc, argv, "Na:b:e:f:g:m:p:s:t:o:v:A:B:O:P:T:U")) != -1) { - switch (opt) { - case 'a' : - strncpy(node_str, optarg, NI_MAXHOST-1); - node_str[NI_MAXHOST - 1] = '\0'; - break; - case 'b' : - cmdline_blocksize(optarg); - break; - case 'B' : - wait_seconds = atoi(optarg); - break; - case 'e' : - if (!cmdline_input(optarg,&payload)) - payload.length = 0; - break; - case 'f' : - if (!cmdline_input_from_file(optarg,&payload)) - payload.length = 0; - break; - case 'p' : - strncpy(port_str, optarg, NI_MAXSERV-1); - port_str[NI_MAXSERV - 1] = '\0'; - break; - case 'm' : - method = cmdline_method(optarg); - break; - case 'N' : - msgtype = COAP_MESSAGE_NON; - break; - case 's' : - cmdline_subscribe(optarg); - break; - case 'o' : - output_file.length = strlen(optarg); - output_file.s = (unsigned char *)coap_malloc(output_file.length + 1); - - if (!output_file.s) { - fprintf(stderr, "cannot set output file: insufficient memory\n"); - exit(-1); - } else { - /* copy filename including trailing zero */ - memcpy(output_file.s, optarg, output_file.length + 1); - } - break; - case 'A' : - cmdline_content_type(optarg,COAP_OPTION_ACCEPT); - break; - case 't' : - cmdline_content_type(optarg,COAP_OPTION_CONTENT_TYPE); - break; - case 'O' : - cmdline_option(optarg); - break; - case 'P' : - if (!cmdline_proxy(optarg)) { - fprintf(stderr, "error specifying proxy address\n"); - exit(-1); - } - break; - case 'T' : - cmdline_token(optarg); - break; - case 'U' : - create_uri_opts = 0; - break; - case 'v' : - log_level = strtol(optarg, NULL, 10); - break; - default: - usage( argv[0], PACKAGE_VERSION ); - exit( 1 ); - } - } - - coap_set_log_level(log_level); - - if (optind < argc) { - if (cmdline_uri(argv[optind], create_uri_opts) < 0) { - coap_log(LOG_ERR, "invalid CoAP URI\n"); - exit(1); - } - } else { - usage( argv[0], PACKAGE_VERSION ); - exit( 1 ); - } - - if (proxy.length) { - server = proxy; - port = proxy_port; - } else { - server = uri.host; - port = uri.port; - } - - /* resolve destination address where server should be sent */ - res = resolve_address(&server, &dst.addr.sa); - - if (res < 0) { - fprintf(stderr, "failed to resolve address\n"); - exit(-1); - } - - dst.size = res; - dst.addr.sin.sin_port = htons(port); - - /* add Uri-Host if server address differs from uri.host */ - - switch (dst.addr.sa.sa_family) { - case AF_INET: - addrptr = &dst.addr.sin.sin_addr; - - /* create context for IPv4 */ - ctx = get_context(node_str[0] == 0 ? "0.0.0.0" : node_str, port_str); - break; - case AF_INET6: - addrptr = &dst.addr.sin6.sin6_addr; - - /* create context for IPv6 */ - ctx = get_context(node_str[0] == 0 ? "::" : node_str, port_str); - break; - default: - ; - } - - if (!ctx) { - coap_log(LOG_EMERG, "cannot create context\n"); - return -1; - } - - coap_register_option(ctx, COAP_OPTION_BLOCK2); - coap_register_response_handler(ctx, message_handler); - - /* construct CoAP message */ - - if (!proxy.length && addrptr - && (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0) - && (strlen(addr) != uri.host.length - || memcmp(addr, uri.host.s, uri.host.length) != 0) - && create_uri_opts) { - /* add Uri-Host */ - - coap_insert(&optlist, - new_option_node(COAP_OPTION_URI_HOST, - uri.host.length, - uri.host.s)); - } - - /* set block option if requested at commandline */ - if (flags & FLAGS_BLOCK) - set_blocksize(); - - if (! (pdu = coap_new_request(ctx, method, &optlist, payload.s, payload.length))) - return -1; - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { - debug("sending CoAP request:\n"); - coap_show_pdu(pdu); - } -#endif - - if (pdu->hdr->type == COAP_MESSAGE_CON) - tid = coap_send_confirmed(ctx, ctx->endpoint, &dst, pdu); - else - tid = coap_send(ctx, ctx->endpoint, &dst, pdu); - - if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID) - coap_delete_pdu(pdu); - - set_timeout(&max_wait, wait_seconds); - debug("timeout is set to %d seconds\n", wait_seconds); - - while ( !(ready && coap_can_exit(ctx)) ) { - FD_ZERO(&readfds); - FD_SET( ctx->sockfd, &readfds ); - - nextpdu = coap_peek_next( ctx ); - - coap_ticks(&now); - while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { - coap_retransmit( ctx, coap_pop_next( ctx )); - nextpdu = coap_peek_next( ctx ); - } - - if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait, max_wait) - now) { - /* set timeout if there is a pdu to send */ - tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; - } else { - /* check if obs_wait fires before max_wait */ - if (obs_wait && obs_wait < max_wait) { - tv.tv_usec = ((obs_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (obs_wait - now) / COAP_TICKS_PER_SECOND; - } else { - tv.tv_usec = ((max_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (max_wait - now) / COAP_TICKS_PER_SECOND; - } - } - - result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv); - - if ( result < 0 ) { /* error */ - perror("select"); - } else if ( result > 0 ) { /* read from socket */ - if ( FD_ISSET( ctx->sockfd, &readfds ) ) { - coap_read( ctx ); /* read received data */ - /* coap_dispatch( ctx ); /\* and dispatch PDUs from receivequeue *\/ */ - } - } else { /* timeout */ - coap_ticks(&now); - if (max_wait <= now) { - info("timeout\n"); - break; - } - if (obs_wait && obs_wait <= now) { - debug("clear observation relationship\n"); - clear_obs(ctx, ctx->endpoint, &dst); /* FIXME: handle error case COAP_TID_INVALID */ - - /* make sure that the obs timer does not fire again */ - obs_wait = 0; - obs_seconds = 0; - } - } - } - - close_output(); - - coap_delete_list(optlist); - coap_free_context( ctx ); - - return 0; -} diff --git a/components/coap/libcoap/examples/coap-client.txt.in b/components/coap/libcoap/examples/coap-client.txt.in deleted file mode 100644 index ee0f7ac57..000000000 --- a/components/coap/libcoap/examples/coap-client.txt.in +++ /dev/null @@ -1,168 +0,0 @@ -// -*- mode:doc; -*- -// vim: set syntax=asciidoc,tw=0: - -coap-client(5) -============== -:doctype: manpage -:man source: coap-client -:man version: @PACKAGE_VERSION@ -:man manual: coap-client Manual - -NAME ------ -coap-client - CoAP Client based on libcoap - -SYNOPSIS --------- -*coap-client* [*-A* type1, _type2_ ,...] [*-t* type] [*-b* [num,]size] - [*-B* seconds] [*-e* text] [*-f* file] [*-m* method] [*-N*] - [*-o* file] [*-P* addr[:port]] [*-p* port] [*-s* duration] - [*-O* num,text] [*-T* token] [*-v* num] [*-a* addr] [*-U*] URI - -DESCRIPTION ------------ -*coap-client* is a CoAP client to communicate with 6LoWPAN devices via -the protocol CoAP (RFC 7252) using the URI given as argument on the -command line. The URI must have the scheme 'coap' (or 'coaps' when -coap-client was built with support for secure communication). The URI's -host part may be a DNS name or a literal IP address. Note that, for -IPv6 address references, angle brackets are required (c.f. EXAMPLES). - - -OPTIONS -------- -*-a* addr:: - The local address of the interface that has to be used. - -*-b* [num,]size:: - The block size to be used in GET/PUT/POST requests (value must be a - multiple of 16 not larger than 1024 as libcoap uses a fixed maximum - PDU size of 1400 bytes). If 'num' is present, the request - chain will start at block 'num'. When the server includes a Block2 - option in its response to a GET request, coap-client will automatically - retrieve the subsequent block from the server until there are no more - outstanding blocks for the requested content. - -*-e* text:: - Include text as payload (use percent-encoding for non-ASCII characters). - -*-f* file:: - File to send with PUT/POST (use '-' for STDIN). - -*-m* method:: - The request method for action (get|put|post|delete), default is 'get'. - (Note that the string passed to *-m* is compared case-insensitive.) - -*-o* file:: - A filename to store data retrieved with GET. - -*-p* port:: - The port to listen on. - -*-s* duration:: - Subscribe to the resource specified by URI for the given 'duration' in - seconds. - -*-t* type:: - Content format for given resource for PUT/POST. 'type' must be either - a numeric value reflecting a valid CoAP content format or a string - describing a registered format. The following registered content format - descriptors are supported, with alternative shortcuts given in - parentheses: - - text/plain (plain) - application/link-format (link, link-format) - application/xml (xml) - application/octet-stream (binary, octet-stream) - application/exi (exi) - application/json (json) - application/cbor (cbor) - -*-v* num:: - The verbosity level to use (default: 3, maximum is 9). - -*-A* type:: - Accepted media types as comma-separated list of symbolic or numeric - values, there are multiple arguments as comma separated list - possible. 'type' must be either a numeric value reflecting a valid - CoAP content format or a string that specifies a registered format as - described for option *-t*. - -*-B* seconds:: - Break operation after waiting given seconds (default is 90). - -*-N* :: - Send NON-confirmable message. If option *-N* is not specified, a - confirmable message will be sent. - -*-O* num,text:: - Add option 'num' with contents of 'text' to the request. - -*-P* addr[:port]:: - Address (and port) for proxy to use (automatically adds Proxy-Uri option - to request). - -*-T* token:: - Include the 'token' to the request. - -*-U* :: - Never include Uri-Host or Uri-Port options. - -EXAMPLES --------- -* Example ----- -coap-client coap://coap.me ----- -Query resource '/' from server 'coap.me' (via the GET method). - -* Example ----- -coap-client -m get coap://[::1]/ ----- -Query on localhost via the 'GET' method. - -* Example ----- -coap-client -m get coap://[::1]/.well-known/core ----- -Quite the same, except on the resource '.well-known/core' on localhost. - -* Example ----- -echo -n "mode=on" | coap-client -m put \ -coap://[2001:db8:c001:f00d:221:2eff:ff00:2704]:5683/actuators/leds?color=r -f- ----- -Send text 'mode=on' to resource 'actuators/leds?color=r' on the endpoint with -address '2001:db8:c001:f00d:221:2eff:ff00:2704' and port '5683'. Note that the -port '5683' is the default port and isn't really needed to append. - -* Example ----- -coap-client -m put coap://[fec0::3]/ck -T 3a -t binary -f to_upload ----- -Put the contents of file 'to_upload' with content type 'binary' (i.e. -application/octet-stream) into resource 'ck' on 'fec0::3' by usage of a token -'3a' via the 'PUT' method. - -FILES ------- -There are no configuration files. - -EXIT STATUS ------------ -*0*:: - Success - -*1*:: - Failure (syntax or usage error; configuration error; document - processing failure; unexpected error) - -BUGS ------ -Please report bugs on the mailing list for libcoap: -libcoap-developers@lists.sourceforge.net - -AUTHORS -------- -The libcoap project diff --git a/components/coap/libcoap/examples/coap-rd.c b/components/coap/libcoap/examples/coap-rd.c deleted file mode 100644 index 64f156f2d..000000000 --- a/components/coap/libcoap/examples/coap-rd.c +++ /dev/null @@ -1,763 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ - -/* coap -- simple implementation of the Constrained Application Protocol (CoAP) - * as defined in RFC 7252 - * - * Copyright (C) 2010--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms of - * use. - */ - - -/** - * @file rd.c - * @brief CoRE resource directory - * - * @see http://tools.ietf.org/id/draft-shelby-core-resource-directory - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "coap_config.h" -#include "utlist.h" -#include "resource.h" -#include "coap.h" - -#define COAP_RESOURCE_CHECK_TIME 2 - -#define RD_ROOT_STR ((unsigned char *)"rd") -#define RD_ROOT_SIZE 2 - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -typedef struct rd_t { - UT_hash_handle hh; /**< hash handle (for internal use only) */ - coap_key_t key; /**< the actual key bytes for this resource */ - - size_t etag_len; /**< actual length of @c etag */ - unsigned char etag[8]; /**< ETag for current description */ - - str data; /**< points to the resource description */ -} rd_t; - -rd_t *resources = NULL; - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -static inline rd_t * -rd_new(void) { - rd_t *rd; - rd = (rd_t *)coap_malloc(sizeof(rd_t)); - if (rd) - memset(rd, 0, sizeof(rd_t)); - - return rd; -} - -static inline void -rd_delete(rd_t *rd) { - if (rd) { - coap_free(rd->data.s); - coap_free(rd); - } -} - -/* temporary storage for dynamic resource representations */ -static int quit = 0; - -/* SIGINT handler: set quit to 1 for graceful termination */ -static void -handle_sigint(int signum UNUSED_PARAM) { - quit = 1; -} - -static void -hnd_get_resource(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - rd_t *rd = NULL; - unsigned char buf[3]; - - HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, - COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, - COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), - buf); - - if (rd && rd->etag_len) - coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); - - if (rd && rd->data.s) - coap_add_data(response, rd->data.length, rd->data.s); -} - -static void -hnd_put_resource(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response) { -#if 1 - response->hdr->code = COAP_RESPONSE_CODE(501); -#else /* FIXME */ - coap_opt_iterator_t opt_iter; - coap_opt_t *token, *etag; - coap_pdu_t *response; - size_t size = sizeof(coap_hdr_t); - int type = (request->hdr->type == COAP_MESSAGE_CON) - ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; - rd_t *rd = NULL; - unsigned char code; /* result code */ - unsigned char *data; - str tmp; - - HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); - if (rd) { - /* found resource object, now check Etag */ - etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); - if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) - || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) { - - if (coap_get_data(request, &tmp.length, &data)) { - - tmp.s = (unsigned char *)coap_malloc(tmp.length); - if (!tmp.s) { - debug("hnd_put_rd: cannot allocate storage for new rd\n"); - code = COAP_RESPONSE_CODE(503); - goto finish; - } - - coap_free(rd->data.s); - rd->data.s = tmp.s; - rd->data.length = tmp.length; - memcpy(rd->data.s, data, rd->data.length); - } - } - - if (etag) { - rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); - memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); - } - - code = COAP_RESPONSE_CODE(204); - /* FIXME: update lifetime */ - - } else { - - code = COAP_RESPONSE_CODE(503); - } - - finish: - /* FIXME: do not create a new response but use the old one instead */ - response = coap_pdu_init(type, code, request->hdr->id, size); - - if (!response) { - debug("cannot create response for message %d\n", request->hdr->id); - return; - } - - if (request->hdr->token_length) - coap_add_token(response, request->hdr->token_length, request->hdr->token); - - if (coap_send(ctx, peer, response) == COAP_INVALID_TID) { - debug("hnd_get_rd: cannot send response for message %d\n", - request->hdr->id); - } - coap_delete_pdu(response); -#endif -} - -static void -hnd_delete_resource(coap_context_t *ctx, - struct coap_resource_t *resource, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - rd_t *rd = NULL; - - HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); - if (rd) { - HASH_DELETE(hh, resources, rd); - rd_delete(rd); - } - /* FIXME: link attributes for resource have been created dynamically - * using coap_malloc() and must be released. */ - coap_delete_resource(ctx, resource->key); - - response->hdr->code = COAP_RESPONSE_CODE(202); -} - -static void -hnd_get_rd(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - unsigned char buf[3]; - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, - COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, - COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), - buf); - - coap_add_option(response, - COAP_OPTION_MAXAGE, - coap_encode_var_bytes(buf, 0x2ffff), buf); -} - -static int -parse_param(unsigned char *search, - size_t search_len, - unsigned char *data, - size_t data_len, - str *result) { - - if (result) - memset(result, 0, sizeof(str)); - - if (!search_len) - return 0; - - while (search_len <= data_len) { - - /* handle parameter if found */ - if (memcmp(search, data, search_len) == 0) { - data += search_len; - data_len -= search_len; - - /* key is only valid if we are at end of string or delimiter follows */ - if (!data_len || *data == '=' || *data == '&') { - while (data_len && *data != '=') { - ++data; --data_len; - } - - if (data_len > 1 && result) { - /* value begins after '=' */ - - result->s = ++data; - while (--data_len && *data != '&') { - ++data; result->length++; - } - } - - return 1; - } - } - - /* otherwise proceed to next */ - while (--data_len && *data++ != '&') - ; - } - - return 0; -} - -static void -add_source_address(struct coap_resource_t *resource, - coap_address_t *peer) { -#define BUFSIZE 64 - char *buf; - size_t n = 1; - - buf = (char *)coap_malloc(BUFSIZE); - if (!buf) - return; - - buf[0] = '"'; - - switch(peer->addr.sa.sa_family) { - - case AF_INET: - /* FIXME */ - break; - - case AF_INET6: - n += snprintf(buf + n, BUFSIZE - n, - "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" \ - ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]", - peer->addr.sin6.sin6_addr.s6_addr[0], - peer->addr.sin6.sin6_addr.s6_addr[1], - peer->addr.sin6.sin6_addr.s6_addr[2], - peer->addr.sin6.sin6_addr.s6_addr[3], - peer->addr.sin6.sin6_addr.s6_addr[4], - peer->addr.sin6.sin6_addr.s6_addr[5], - peer->addr.sin6.sin6_addr.s6_addr[6], - peer->addr.sin6.sin6_addr.s6_addr[7], - peer->addr.sin6.sin6_addr.s6_addr[8], - peer->addr.sin6.sin6_addr.s6_addr[9], - peer->addr.sin6.sin6_addr.s6_addr[10], - peer->addr.sin6.sin6_addr.s6_addr[11], - peer->addr.sin6.sin6_addr.s6_addr[12], - peer->addr.sin6.sin6_addr.s6_addr[13], - peer->addr.sin6.sin6_addr.s6_addr[14], - peer->addr.sin6.sin6_addr.s6_addr[15]); - - if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) { - n += - snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port); - } - break; - default: - ; - } - - if (n < BUFSIZE) - buf[n++] = '"'; - - coap_add_attr(resource, - (unsigned char *)"A", - 1, - (unsigned char *)buf, - n, - COAP_ATTR_FLAGS_RELEASE_VALUE); -#undef BUFSIZE -} - -static rd_t * -make_rd(coap_address_t *peer UNUSED_PARAM, coap_pdu_t *pdu) { - rd_t *rd; - unsigned char *data; - coap_opt_iterator_t opt_iter; - coap_opt_t *etag; - - rd = rd_new(); - - if (!rd) { - debug("hnd_get_rd: cannot allocate storage for rd\n"); - return NULL; - } - - if (coap_get_data(pdu, &rd->data.length, &data)) { - rd->data.s = (unsigned char *)coap_malloc(rd->data.length); - if (!rd->data.s) { - debug("hnd_get_rd: cannot allocate storage for rd->data\n"); - rd_delete(rd); - return NULL; - } - memcpy(rd->data.s, data, rd->data.length); - } - - etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); - if (etag) { - rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); - memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); - } - - return rd; -} - -static void -hnd_post_rd(coap_context_t *ctx, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer, - coap_pdu_t *request, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - coap_resource_t *r; - coap_opt_iterator_t opt_iter; - coap_opt_t *query; -#define LOCSIZE 68 - unsigned char *loc; - size_t loc_size; - str h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ - unsigned char *buf; - - loc = (unsigned char *)coap_malloc(LOCSIZE); - if (!loc) { - response->hdr->code = COAP_RESPONSE_CODE(500); - return; - } - memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); - - loc_size = RD_ROOT_SIZE; - loc[loc_size++] = '/'; - - /* store query parameters for later use */ - query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); - if (query) { - parse_param((unsigned char *)"h", 1, - COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h); - parse_param((unsigned char *)"ins", 3, - COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &ins); - parse_param((unsigned char *)"lt", 2, - COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <); - parse_param((unsigned char *)"rt", 2, - COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt); - } - - if (h.length) { /* client has specified a node name */ - memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); - loc_size += min(h.length, LOCSIZE - loc_size - 1); - - if (ins.length && loc_size > 1) { - loc[loc_size++] = '-'; - memcpy((char *)(loc + loc_size), - ins.s, min(ins.length, LOCSIZE - loc_size - 1)); - loc_size += min(ins.length, LOCSIZE - loc_size - 1); - } - - } else { /* generate node identifier */ - loc_size += - snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, - "%x", request->hdr->id); - - if (loc_size > 1) { - if (ins.length) { - loc[loc_size++] = '-'; - memcpy((char *)(loc + loc_size), - ins.s, - min(ins.length, LOCSIZE - loc_size - 1)); - loc_size += min(ins.length, LOCSIZE - loc_size - 1); - } else { - coap_tick_t now; - coap_ticks(&now); - - loc_size += snprintf((char *)(loc + loc_size), - LOCSIZE - loc_size - 1, - "-%x", - (unsigned int)(now & (unsigned int)-1)); - } - } - } - - /* TODO: - * - use lt to check expiration - */ - - r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); - coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource); - coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); - - if (ins.s) { - buf = (unsigned char *)coap_malloc(ins.length + 2); - if (buf) { - /* add missing quotes */ - buf[0] = '"'; - memcpy(buf + 1, ins.s, ins.length); - buf[ins.length + 1] = '"'; - coap_add_attr(r, - (unsigned char *)"ins", - 3, - buf, - ins.length + 2, - COAP_ATTR_FLAGS_RELEASE_VALUE); - } - } - - if (rt.s) { - buf = (unsigned char *)coap_malloc(rt.length + 2); - if (buf) { - /* add missing quotes */ - buf[0] = '"'; - memcpy(buf + 1, rt.s, rt.length); - buf[rt.length + 1] = '"'; - coap_add_attr(r, - (unsigned char *)"rt", - 2, - buf, - rt.length + 2,COAP_ATTR_FLAGS_RELEASE_VALUE); - } - } - - add_source_address(r, peer); - - { - rd_t *rd; - rd = make_rd(peer, request); - if (rd) { - coap_hash_path(loc, loc_size, rd->key); - HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd); - } else { - /* FIXME: send error response and delete r */ - } - } - - coap_add_resource(ctx, r); - - - /* create response */ - - response->hdr->code = COAP_RESPONSE_CODE(201); - - { /* split path into segments and add Location-Path options */ - unsigned char _b[LOCSIZE]; - unsigned char *b = _b; - size_t buflen = sizeof(_b); - int nseg; - - nseg = coap_split_path(loc, loc_size, b, &buflen); - while (nseg--) { - coap_add_option(response, - COAP_OPTION_LOCATION_PATH, - COAP_OPT_LENGTH(b), - COAP_OPT_VALUE(b)); - b += COAP_OPT_SIZE(b); - } - } -} - -static void -init_resources(coap_context_t *ctx) { - coap_resource_t *r; - - r = coap_resource_init(RD_ROOT_STR, RD_ROOT_SIZE, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_rd); - coap_register_handler(r, COAP_REQUEST_POST, hnd_post_rd); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"40", 2, 0); - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"core.rd\"", 9, 0); - coap_add_attr(r, (unsigned char *)"ins", 2, (unsigned char *)"\"default\"", 9, 0); - - coap_add_resource(ctx, r); - -} - -static void -usage( const char *program, const char *version) { - const char *p; - - p = strrchr( program, '/' ); - if ( p ) - program = ++p; - - fprintf( stderr, "%s v%s -- CoRE Resource Directory implementation\n" - "(c) 2011-2012 Olaf Bergmann \n\n" - "usage: %s [-A address] [-p port]\n\n" - "\t-A address\tinterface address to bind to\n" - "\t-p port\t\tlisten on specified port\n" - "\t-v num\t\tverbosity level (default: 3)\n", - program, version, program ); -} - -static coap_context_t * -get_context(const char *node, const char *port) { - coap_context_t *ctx = NULL; - int s; - struct addrinfo hints; - struct addrinfo *result, *rp; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - - s = getaddrinfo(node, port, &hints, &result); - if ( s != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); - return NULL; - } - - /* iterate through results until success */ - for (rp = result; rp != NULL; rp = rp->ai_next) { - coap_address_t addr; - - if (rp->ai_addrlen <= sizeof(addr.addr)) { - coap_address_init(&addr); - addr.size = rp->ai_addrlen; - memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); - - ctx = coap_new_context(&addr); - if (ctx) { - /* TODO: output address:port for successful binding */ - goto finish; - } - } - } - - fprintf(stderr, "no context available for interface '%s'\n", node); - - finish: - freeaddrinfo(result); - return ctx; -} - -static int -join(coap_context_t *ctx, char *group_name) { - struct ipv6_mreq mreq; - struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; - int result = -1; - - /* we have to resolve the link-local interface to get the interface id */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - - result = getaddrinfo("::", NULL, &hints, &reslocal); - if ( result < 0 ) { - perror("join: cannot resolve link-local interface"); - goto finish; - } - - /* get the first suitable interface identifier */ - for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) { - if ( ainfo->ai_family == AF_INET6 ) { - mreq.ipv6mr_interface = - ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id; - break; - } - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - - /* resolve the multicast group address */ - result = getaddrinfo(group_name, NULL, &hints, &resmulti); - - if ( result < 0 ) { - perror("join: cannot resolve multicast address"); - goto finish; - } - - for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) { - if ( ainfo->ai_family == AF_INET6 ) { - mreq.ipv6mr_multiaddr = - ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr; - break; - } - } - - result = setsockopt(ctx->sockfd, - IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *)&mreq, sizeof(mreq) ); - if ( result < 0 ) - perror("join: setsockopt"); - - finish: - freeaddrinfo(resmulti); - freeaddrinfo(reslocal); - - return result; -} - -int -main(int argc, char **argv) { - coap_context_t *ctx; - fd_set readfds; - struct timeval tv, *timeout; - int result; - coap_tick_t now; - coap_queue_t *nextpdu; - char addr_str[NI_MAXHOST] = "::"; - char port_str[NI_MAXSERV] = "5683"; - char *group = NULL; - int opt; - coap_log_t log_level = LOG_WARNING; - - while ((opt = getopt(argc, argv, "A:g:p:v:")) != -1) { - switch (opt) { - case 'A' : - strncpy(addr_str, optarg, NI_MAXHOST-1); - addr_str[NI_MAXHOST - 1] = '\0'; - break; - case 'g' : - group = optarg; - break; - case 'p' : - strncpy(port_str, optarg, NI_MAXSERV-1); - port_str[NI_MAXSERV - 1] = '\0'; - break; - case 'v' : - log_level = strtol(optarg, NULL, 10); - break; - default: - usage( argv[0], PACKAGE_VERSION ); - exit( 1 ); - } - } - - coap_set_log_level(log_level); - - ctx = get_context(addr_str, port_str); - if (!ctx) - return -1; - - if (group) - join(ctx, group); - - init_resources(ctx); - - signal(SIGINT, handle_sigint); - - while ( !quit ) { - FD_ZERO(&readfds); - FD_SET( ctx->sockfd, &readfds ); - - nextpdu = coap_peek_next( ctx ); - - coap_ticks(&now); - while ( nextpdu && nextpdu->t <= now ) { - coap_retransmit( ctx, coap_pop_next( ctx ) ); - nextpdu = coap_peek_next( ctx ); - } - - if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME ) { - /* set timeout if there is a pdu to send before our automatic - timeout occurs */ - tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; - timeout = &tv; - } else { - tv.tv_usec = 0; - tv.tv_sec = COAP_RESOURCE_CHECK_TIME; - timeout = &tv; - } - result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); - - if ( result < 0 ) { /* error */ - if (errno != EINTR) - perror("select"); - } else if ( result > 0 ) { /* read from socket */ - if ( FD_ISSET( ctx->sockfd, &readfds ) ) { - coap_read( ctx ); /* read received data */ - /* coap_dispatch( ctx ); /\* and dispatch PDUs from receivequeue *\/ */ - } - } else { /* timeout */ - /* coap_check_resource_list( ctx ); */ - } - } - - coap_free_context( ctx ); - - return 0; -} diff --git a/components/coap/libcoap/examples/coap-rd.txt.in b/components/coap/libcoap/examples/coap-rd.txt.in deleted file mode 100644 index 762609cf0..000000000 --- a/components/coap/libcoap/examples/coap-rd.txt.in +++ /dev/null @@ -1,88 +0,0 @@ -// -*- mode:doc; -*- -// vim: set syntax=asciidoc,tw=0: - -coap-rd(5) -========== -:doctype: manpage -:man source: coap-rd -:man version: @PACKAGE_VERSION@ -:man manual: coap-rd Manual - -NAME ------ -coap-rd - A CoAP Resource Directory based on libcoap - -SYNOPSIS --------- -*coap-rd* [*-A* addr] [*-g* group] [*-p* port] [*-v* num] - -DESCRIPTION ------------ -*coap-rd* is a simple CoAP Resource Directory server that can handle resource -registrations using the protocol CoAP (RFC 7252). - -OPTIONS -------- -*-A* addr:: - The local address of the interface which the server has to listen. - -*-g* group:: - Join specified multicast 'group' on startup. - -*-p* port:: - The 'port' on the given address the server will be waitung for connections. - The default port is 5683 if not given any other value. - -*-v* num:: - The verbosity level to use (default: 3, maximum is 9). - -EXAMPLES --------- -* Example ----- -coap-rd -A ::1 ----- -Let the server listen on localhost (port 5683). - -* Example ----- -coap-rd -A ::1 -p 13011 ----- -Quite the same, except listening port is '13011' (and not the default port -5683). - -* Example ----- -coap-rd -A 2001:db8:81a8:0:6ef0:dead:feed:beef -v 5 ----- -The listening address is set to '2001:db8:81a8:0:6ef0:dead:feed:beef' and the -verbosity level is set to '5'. - -* Example ----- -coap-rd -A 2001:db8:81a8:0:6ef0:dead:feed:beef -g FF02:FD ----- -Set listening address to '2001:db8:81a8:0:6ef0:dead:feed:beef' and join the -All CoAP Nodes multicast group 'FF02:FD'. - -FILES ------- -There are no configuration files. - -EXIT STATUS ------------ -*0*:: - Success - -*1*:: - Failure (syntax or usage error; configuration error; document - processing failure; unexpected error) - -BUGS ------ -Please report bugs on the mailing list for libcoap: -libcoap-developers@lists.sourceforge.net - -AUTHORS -------- -The libcoap project diff --git a/components/coap/libcoap/examples/coap-server.c b/components/coap/libcoap/examples/coap-server.c deleted file mode 100644 index aa29db31a..000000000 --- a/components/coap/libcoap/examples/coap-server.c +++ /dev/null @@ -1,550 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ - -/* coap -- simple implementation of the Constrained Application Protocol (CoAP) - * as defined in RFC 7252 - * - * Copyright (C) 2010--2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "coap_config.h" -#include "resource.h" -#include "coap.h" - -#define COAP_RESOURCE_CHECK_TIME 2 - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -/* temporary storage for dynamic resource representations */ -static int quit = 0; - -/* changeable clock base (see handle_put_time()) */ -static time_t clock_offset; -static time_t my_clock_base = 0; - -struct coap_resource_t *time_resource = NULL; - -#ifndef WITHOUT_ASYNC -/* This variable is used to mimic long-running tasks that require - * asynchronous responses. */ -static coap_async_state_t *async = NULL; -#endif /* WITHOUT_ASYNC */ - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -/* SIGINT handler: set quit to 1 for graceful termination */ -static void -handle_sigint(int signum UNUSED_PARAM) { - quit = 1; -} - -#define INDEX "This is a test server made with libcoap (see https://libcoap.net)\n" \ - "Copyright (C) 2010--2016 Olaf Bergmann \n\n" - -static void -hnd_get_index(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - unsigned char buf[3]; - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, - COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_add_option(response, - COAP_OPTION_MAXAGE, - coap_encode_var_bytes(buf, 0x2ffff), buf); - - coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX); -} - -static void -hnd_get_time(coap_context_t *ctx, - struct coap_resource_t *resource, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer, - coap_pdu_t *request, - str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - unsigned char buf[40]; - size_t len; - time_t now; - coap_tick_t t; - - /* FIXME: return time, e.g. in human-readable by default and ticks - * when query ?ticks is given. */ - - /* if my_clock_base was deleted, we pretend to have no such resource */ - response->hdr->code = - my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); - - if (coap_find_observer(resource, peer, token)) { - /* FIXME: need to check for resource->dirty? */ - coap_add_option(response, - COAP_OPTION_OBSERVE, - coap_encode_var_bytes(buf, ctx->observe), buf); - } - - if (my_clock_base) - coap_add_option(response, - COAP_OPTION_CONTENT_FORMAT, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_add_option(response, - COAP_OPTION_MAXAGE, - coap_encode_var_bytes(buf, 0x01), buf); - - if (my_clock_base) { - - /* calculate current time */ - coap_ticks(&t); - now = my_clock_base + (t / COAP_TICKS_PER_SECOND); - - if (request != NULL - && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter)) - && memcmp(COAP_OPT_VALUE(option), "ticks", - min(5, COAP_OPT_LENGTH(option))) == 0) { - /* output ticks */ - len = snprintf((char *)buf, - min(sizeof(buf), - response->max_size - response->length), - "%u", (unsigned int)now); - coap_add_data(response, len, buf); - - } else { /* output human-readable time */ - struct tm *tmp; - tmp = gmtime(&now); - len = strftime((char *)buf, - min(sizeof(buf), - response->max_size - response->length), - "%b %d %H:%M:%S", tmp); - coap_add_data(response, len, buf); - } - } -} - -static void -hnd_put_time(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - coap_tick_t t; - size_t size; - unsigned char *data; - - /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 - * and request is empty. When not empty, set to value in request payload - * (insist on query ?ticks). Return Created or Ok. - */ - - /* if my_clock_base was deleted, we pretend to have no such resource */ - response->hdr->code = - my_clock_base ? COAP_RESPONSE_CODE(204) : COAP_RESPONSE_CODE(201); - - resource->dirty = 1; - - /* coap_get_data() sets size to 0 on error */ - (void)coap_get_data(request, &size, &data); - - if (size == 0) /* re-init */ - my_clock_base = clock_offset; - else { - my_clock_base = 0; - coap_ticks(&t); - while(size--) - my_clock_base = my_clock_base * 10 + *data++; - my_clock_base -= t / COAP_TICKS_PER_SECOND; - } -} - -static void -hnd_delete_time(coap_context_t *ctx UNUSED_PARAM, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer UNUSED_PARAM, - coap_pdu_t *request UNUSED_PARAM, - str *token UNUSED_PARAM, - coap_pdu_t *response UNUSED_PARAM) { - my_clock_base = 0; /* mark clock as "deleted" */ - - /* type = request->hdr->type == COAP_MESSAGE_CON */ - /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */ -} - -#ifndef WITHOUT_ASYNC -static void -hnd_get_async(coap_context_t *ctx, - struct coap_resource_t *resource UNUSED_PARAM, - const coap_endpoint_t *local_interface UNUSED_PARAM, - coap_address_t *peer, - coap_pdu_t *request, - str *token UNUSED_PARAM, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - unsigned long delay = 5; - size_t size; - - if (async) { - if (async->id != request->hdr->id) { - coap_opt_filter_t f; - coap_option_filter_clear(f); - response->hdr->code = COAP_RESPONSE_CODE(503); - } - return; - } - - option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); - if (option) { - unsigned char *p = COAP_OPT_VALUE(option); - - delay = 0; - for (size = COAP_OPT_LENGTH(option); size; --size, ++p) - delay = delay * 10 + (*p - '0'); - } - - async = coap_register_async(ctx, - peer, - request, - COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, - (void *)(COAP_TICKS_PER_SECOND * delay)); -} - -static void -check_async(coap_context_t *ctx, - const coap_endpoint_t *local_if, - coap_tick_t now) { - coap_pdu_t *response; - coap_async_state_t *tmp; - - size_t size = sizeof(coap_hdr_t) + 13; - - if (!async || now < async->created + (unsigned long)async->appdata) - return; - - response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM - ? COAP_MESSAGE_CON - : COAP_MESSAGE_NON, - COAP_RESPONSE_CODE(205), 0, size); - if (!response) { - debug("check_async: insufficient memory, we'll try later\n"); - async->appdata = - (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND); - return; - } - - response->hdr->id = coap_new_message_id(ctx); - - if (async->tokenlen) - coap_add_token(response, async->tokenlen, async->token); - - coap_add_data(response, 4, (unsigned char *)"done"); - - if (coap_send(ctx, local_if, &async->peer, response) == COAP_INVALID_TID) { - debug("check_async: cannot send response for message %d\n", - response->hdr->id); - } - coap_delete_pdu(response); - coap_remove_async(ctx, async->id, &tmp); - coap_free_async(async); - async = NULL; -} -#endif /* WITHOUT_ASYNC */ - -static void -init_resources(coap_context_t *ctx) { - coap_resource_t *r; - - r = coap_resource_init(NULL, 0, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0); - coap_add_resource(ctx, r); - - /* store clock base to use in /time */ - my_clock_base = clock_offset; - - r = coap_resource_init((unsigned char *)"time", 4, COAP_RESOURCE_FLAGS_NOTIFY_CON); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); - coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); - coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"Internal Clock\"", 16, 0); - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"Ticks\"", 7, 0); - r->observable = 1; - coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"clock\"", 7, 0); - - coap_add_resource(ctx, r); - time_resource = r; - -#ifndef WITHOUT_ASYNC - r = coap_resource_init((unsigned char *)"async", 5, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_resource(ctx, r); -#endif /* WITHOUT_ASYNC */ -} - -static void -usage( const char *program, const char *version) { - const char *p; - - p = strrchr( program, '/' ); - if ( p ) - program = ++p; - - fprintf( stderr, "%s v%s -- a small CoAP implementation\n" - "(c) 2010,2011,2015 Olaf Bergmann \n\n" - "usage: %s [-A address] [-p port]\n\n" - "\t-A address\tinterface address to bind to\n" - "\t-g group\tjoin the given multicast group\n" - "\t-p port\t\tlisten on specified port\n" - "\t-v num\t\tverbosity level (default: 3)\n", - program, version, program ); -} - -static coap_context_t * -get_context(const char *node, const char *port) { - coap_context_t *ctx = NULL; - int s; - struct addrinfo hints; - struct addrinfo *result, *rp; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - - s = getaddrinfo(node, port, &hints, &result); - if ( s != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); - return NULL; - } - - /* iterate through results until success */ - for (rp = result; rp != NULL; rp = rp->ai_next) { - coap_address_t addr; - - if (rp->ai_addrlen <= sizeof(addr.addr)) { - coap_address_init(&addr); - addr.size = rp->ai_addrlen; - memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); - - ctx = coap_new_context(&addr); - if (ctx) { - /* TODO: output address:port for successful binding */ - goto finish; - } - } - } - - fprintf(stderr, "no context available for interface '%s'\n", node); - - finish: - freeaddrinfo(result); - return ctx; -} - -static int -join(coap_context_t *ctx, char *group_name){ - struct ipv6_mreq mreq; - struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; - int result = -1; - - /* we have to resolve the link-local interface to get the interface id */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - - result = getaddrinfo("::", NULL, &hints, &reslocal); - if (result < 0) { - fprintf(stderr, "join: cannot resolve link-local interface: %s\n", - gai_strerror(result)); - goto finish; - } - - /* get the first suitable interface identifier */ - for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) { - if (ainfo->ai_family == AF_INET6) { - mreq.ipv6mr_interface = - ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id; - break; - } - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - - /* resolve the multicast group address */ - result = getaddrinfo(group_name, NULL, &hints, &resmulti); - - if (result < 0) { - fprintf(stderr, "join: cannot resolve multicast address: %s\n", - gai_strerror(result)); - goto finish; - } - - for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) { - if (ainfo->ai_family == AF_INET6) { - mreq.ipv6mr_multiaddr = - ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr; - break; - } - } - - result = setsockopt(ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *)&mreq, sizeof(mreq)); - if (result < 0) - perror("join: setsockopt"); - - finish: - freeaddrinfo(resmulti); - freeaddrinfo(reslocal); - - return result; -} - -int -main(int argc, char **argv) { - coap_context_t *ctx; - char *group = NULL; - fd_set readfds; - struct timeval tv, *timeout; - int result; - coap_tick_t now; - coap_queue_t *nextpdu; - char addr_str[NI_MAXHOST] = "::"; - char port_str[NI_MAXSERV] = "5683"; - int opt; - coap_log_t log_level = LOG_WARNING; - - clock_offset = time(NULL); - - while ((opt = getopt(argc, argv, "A:g:p:v:")) != -1) { - switch (opt) { - case 'A' : - strncpy(addr_str, optarg, NI_MAXHOST-1); - addr_str[NI_MAXHOST - 1] = '\0'; - break; - case 'g' : - group = optarg; - break; - case 'p' : - strncpy(port_str, optarg, NI_MAXSERV-1); - port_str[NI_MAXSERV - 1] = '\0'; - break; - case 'v' : - log_level = strtol(optarg, NULL, 10); - break; - default: - usage( argv[0], PACKAGE_VERSION ); - exit( 1 ); - } - } - - coap_set_log_level(log_level); - - ctx = get_context(addr_str, port_str); - if (!ctx) - return -1; - - init_resources(ctx); - - /* join multicast group if requested at command line */ - if (group) - join(ctx, group); - - signal(SIGINT, handle_sigint); - - while ( !quit ) { - FD_ZERO(&readfds); - FD_SET( ctx->sockfd, &readfds ); - - nextpdu = coap_peek_next( ctx ); - - coap_ticks(&now); - while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { - coap_retransmit( ctx, coap_pop_next( ctx ) ); - nextpdu = coap_peek_next( ctx ); - } - - if ( nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME ) { - /* set timeout if there is a pdu to send before our automatic timeout occurs */ - tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; - timeout = &tv; - } else { - tv.tv_usec = 0; - tv.tv_sec = COAP_RESOURCE_CHECK_TIME; - timeout = &tv; - } - result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); - - if ( result < 0 ) { /* error */ - if (errno != EINTR) - perror("select"); - } else if ( result > 0 ) { /* read from socket */ - if ( FD_ISSET( ctx->sockfd, &readfds ) ) { - coap_read( ctx ); /* read received data */ - /* coap_dispatch( ctx ); /\* and dispatch PDUs from receivequeue *\/ */ - } - } else { /* timeout */ - if (time_resource) { - time_resource->dirty = 1; - } - } - -#ifndef WITHOUT_ASYNC - /* check if we have to send asynchronous responses */ - check_async(ctx, ctx->endpoint, now); -#endif /* WITHOUT_ASYNC */ - -#ifndef WITHOUT_OBSERVE - /* check if we have to send observe notifications */ - coap_check_notify(ctx); -#endif /* WITHOUT_OBSERVE */ - } - - coap_free_context(ctx); - - return 0; -} diff --git a/components/coap/libcoap/examples/coap-server.txt.in b/components/coap/libcoap/examples/coap-server.txt.in deleted file mode 100644 index c15741ef8..000000000 --- a/components/coap/libcoap/examples/coap-server.txt.in +++ /dev/null @@ -1,88 +0,0 @@ -// -*- mode:doc; -*- -// vim: set syntax=asciidoc,tw=0: - -coap-server(5) -============== -:doctype: manpage -:man source: coap-server -:man version: @PACKAGE_VERSION@ -:man manual: coap-server Manual - -NAME ------ -coap-server - CoAP Server based on libcoap - -SYNOPSIS --------- -*coap-server* [*-A* addr] [*-g* group] [*-p* port] [*-v* num] - -DESCRIPTION ------------ -*coap-server* is a CoAP server which simulate 6LoWPAN devices which can be -addressed via the CoAP protocol. - -OPTIONS -------- -*-A* addr:: - The local address of the interface which the server has to listen. - -*-g* group:: - Join specified multicast 'group' on startup. - -*-p* port:: - The 'port' on the given address the server will be waitung for connections. - The default port is 5683 if not given any other value. - -*-v* num:: - The verbosity level to use (default: 3, maximum is 9). - -EXAMPLES --------- -* Example ----- -coap-server -A ::1 ----- -Let the server listen on localhost (port 5683). - -* Example ----- -coap-server -A ::1 -p 13011 ----- -Quite the same, except listening port is '13011' (and not the default port -5683). - -* Example ----- -coap-server -A 2001:db8:81a8:0:6ef0:dead:feed:beef -v 5 ----- -The listening address is set to '2001:db8:81a8:0:6ef0:dead:feed:beef' and the -verbosity level is set to '5'. - -* Example ----- -coap-server -A 2001:db8:81a8:0:6ef0:dead:feed:beef -g FF02:FD ----- -Set listening address to '2001:db8:81a8:0:6ef0:dead:feed:beef' and join the -All CoAP Nodes multicast group 'FF02:FD'. - -FILES ------- -There are no configuration files. - -EXIT STATUS ------------ -*0*:: - Success - -*1*:: - Failure (syntax or usage error; configuration error; document - processing failure; unexpected error) - -BUGS ------ -Please report bugs on the mailing list for libcoap: -libcoap-developers@lists.sourceforge.net - -AUTHORS -------- -The libcoap project diff --git a/components/coap/libcoap/examples/coap_list.c b/components/coap/libcoap/examples/coap_list.c deleted file mode 100644 index 06e59168d..000000000 --- a/components/coap/libcoap/examples/coap_list.c +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ - -/* coap_list.c -- CoAP list structures - * - * Copyright (C) 2010,2011,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms of - * use. - */ - -/* #include "coap_config.h" */ - -#include -#include - -#include "debug.h" -#include "mem.h" -#include "coap_list.h" - - -int -coap_insert(coap_list_t **head, coap_list_t *node) { - if (!node) { - coap_log(LOG_WARNING, "cannot create option Proxy-Uri\n"); - } else { - /* must append at the list end to avoid re-ordering of - * options during sort */ - LL_APPEND((*head), node); - } - - return node != NULL; -} - -int -coap_delete(coap_list_t *node) { - if (node) { - coap_free(node); - } - return 1; -} - -void -coap_delete_list(coap_list_t *queue) { - coap_list_t *elt, *tmp; - - if (!queue) - return; - - LL_FOREACH_SAFE(queue, elt, tmp) { - coap_delete(elt); - } -} - diff --git a/components/coap/libcoap/examples/coap_list.h b/components/coap/libcoap/examples/coap_list.h deleted file mode 100644 index 14a68a300..000000000 --- a/components/coap/libcoap/examples/coap_list.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ - -/* coap_list.h -- CoAP list structures - * - * Copyright (C) 2010,2011,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms of - * use. - */ - -#ifndef _COAP_LIST_H_ -#define _COAP_LIST_H_ - -#include "utlist.h" - -typedef struct coap_list_t { - struct coap_list_t *next; - char data[]; -} coap_list_t; - -/** - * Adds node to given queue, ordered by specified order function. Returns 1 - * when insert was successful, 0 otherwise. - */ -int coap_insert(coap_list_t **queue, coap_list_t *node); - -/* destroys specified node */ -int coap_delete(coap_list_t *node); - -/* removes all items from given queue and frees the allocated storage */ -void coap_delete_list(coap_list_t *queue); - -#endif /* _COAP_LIST_H_ */ diff --git a/components/coap/libcoap/examples/contiki/Makefile.contiki b/components/coap/libcoap/examples/contiki/Makefile.contiki deleted file mode 100644 index 9df292a28..000000000 --- a/components/coap/libcoap/examples/contiki/Makefile.contiki +++ /dev/null @@ -1,33 +0,0 @@ -######################################################################## -# platform-specific options - -ifeq ($(TARGET), econotag) -CONTIKI_WITH_RPL=0 -CFLAGS += -DUIP_CONF_TCP=0 -DCOAP_MAX_BLOCK_SZX=1 -endif - -ifeq ($(TARGET), mbxxx) -CFLAGS += -DUIP_CONF_TCP=0 -DCOAP_MAX_BLOCK_SZX=1 -DHAVE_ASSERT_H -DHAVE_LIMITS_H -STM32W_CPUREV=CC -#STM32W_CPUREV=xB -endif - -# usually, you should not need changing anything beyond this line -######################################################################## - -CONTIKI?=../../../.. - -ifneq ($(NODE_ADDR),) - CFLAGS += -DNODE_ADDR=$(NODE_ADDR) -endif - -all: server - -CFLAGS += -Os -ffunction-sections -LDFLAGS += -Wl,--gc-sections,--undefined=_reset_vector__,--undefined=InterruptVectors,--undefined=_copy_data_init__,--undefined=_clear_bss_init__,--undefined=_end_of_init__ - -CFLAGS += #-DSHORT_ERROR_RESPONSE -DNDEBUG - -APPS += libcoap - -include $(CONTIKI)/Makefile.include diff --git a/components/coap/libcoap/examples/contiki/coap-observer.c b/components/coap/libcoap/examples/contiki/coap-observer.c deleted file mode 100644 index 6e30d3290..000000000 --- a/components/coap/libcoap/examples/contiki/coap-observer.c +++ /dev/null @@ -1,185 +0,0 @@ -/* coap-server.c -- Example CoAP server using Contiki and libcoap - * - * Copyright (C) 2011 Olaf Bergmann - * - * 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -#include "coap_config.h" -#include "net/uip-debug.h" - -#include - -#include "debug.h" -#include "coap.h" - -static coap_context_t *coap_context; - -/* Where the resource to subscribe is hosted */ -static coap_address_t dst; - -/* The resource to observe */ -static char resource[] = "/s/light"; - -/* when did the last notify arrive? (0 == never) */ -static coap_tick_t last_seen = 0; - -PROCESS(coap_server_process, "CoAP server process"); -AUTOSTART_PROCESSES(&coap_server_process); -/*---------------------------------------------------------------------------*/ -void -init_coap() { - coap_address_t listen_addr; - - coap_address_init(&listen_addr); - listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT); - -#ifdef WITH_CONTIKI - /* initialize uIP address for SLAAC */ - uip_ip6addr(&listen_addr.addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); - uip_ds6_set_addr_iid(&listen_addr.addr, &uip_lladdr); - uip_ds6_addr_add(&listen_addr.addr, 0, ADDR_AUTOCONF); - - uip_debug_lladdr_print(&uip_lladdr); - printf("\r\n"); - uip_debug_ipaddr_print(&listen_addr.addr); - printf("\r\n"); -#endif /* WITH_CONTIKI */ - -#ifdef WITH_CONTIKI - printf("tentative address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", - listen_addr.addr.u8[0], listen_addr.addr.u8[1], - listen_addr.addr.u8[2], listen_addr.addr.u8[3], - listen_addr.addr.u8[4], listen_addr.addr.u8[5], - listen_addr.addr.u8[6], listen_addr.addr.u8[7], - listen_addr.addr.u8[8], listen_addr.addr.u8[9], - listen_addr.addr.u8[10], listen_addr.addr.u8[11], - listen_addr.addr.u8[12], listen_addr.addr.u8[13], - listen_addr.addr.u8[14], listen_addr.addr.u8[15] , - uip_ntohs(listen_addr.port)); -#endif - - coap_context = coap_new_context(&listen_addr); - - coap_set_log_level(LOG_DEBUG); - - if (!coap_context) - coap_log(LOG_CRIT, "cannot create CoAP context\r\n"); -} - -void -message_handler(struct coap_context_t *ctx, - const coap_address_t *remote, - coap_pdu_t *sent, - coap_pdu_t *received, - const coap_tid_t id) { - /* send ACK if received message is confirmable (i.e. a separate response) */ - coap_send_ack(ctx, remote, received); - - debug("** process incoming %d.%02d response:\n", - (received->hdr->code >> 5), received->hdr->code & 0x1F); - coap_show_pdu(received); - - coap_ticks(&last_seen); -} - -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_server_process, ev, data) -{ - coap_pdu_t *request; - coap_uri_t uri; - PROCESS_BEGIN(); - - init_coap(); - - if (!coap_context) { - coap_log(LOG_EMERG, "cannot create context\n"); - PROCESS_EXIT(); - } - - coap_register_response_handler(coap_context, message_handler); - - /* setup subscription request */ - - coap_address_init(&dst); - dst.port = uip_htons(COAP_DEFAULT_PORT); - uip_ip6addr(&dst.addr, 0xaaaa, 0, 0, 0, 0x206, 0x98ff, 0xfe00, 0x232); - /* uip_ip6addr(&dst.addr, 0xfe80, 0, 0, 0, 0x206, 0x98ff, 0xfe00, 0x232); */ - - request = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_GET, - coap_new_message_id(coap_context), - COAP_MAX_PDU_SIZE); - - coap_split_uri((unsigned char *)resource, strlen(resource), &uri); - - if (uri.port != COAP_DEFAULT_PORT) { - unsigned char portbuf[2]; - coap_add_option(request, COAP_OPTION_URI_PORT, - coap_encode_var_bytes(portbuf, uri.port), portbuf); - } - - if (uri.path.length) { -#define BUFSIZE 20 - unsigned char _buf[BUFSIZE]; - unsigned char *buf = _buf; - size_t buflen; - int res; - - buflen = BUFSIZE; -#undef BUFSIZE - res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - - while (res--) { - coap_add_option(request, COAP_OPTION_URI_PATH, - COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)); - - buf += COAP_OPT_SIZE(buf); - } - } - - coap_add_option(request, COAP_OPTION_SUBSCRIPTION, 0, NULL); - { - unsigned char buf[2]; - prng(buf, 2); - coap_add_option(request, COAP_OPTION_TOKEN, 2, buf); - } - - if (COAP_INVALID_TID == coap_send_confirmed(coap_context, &dst, request)) - coap_delete_pdu(request); - - while(1) { - PROCESS_YIELD(); - if(ev == tcpip_event) { - coap_read(coap_context); /* read received data */ - coap_dispatch(coap_context); /* and dispatch PDUs from receivequeue */ - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/components/coap/libcoap/examples/contiki/radvd.conf.sample b/components/coap/libcoap/examples/contiki/radvd.conf.sample deleted file mode 100644 index 26c218ba4..000000000 --- a/components/coap/libcoap/examples/contiki/radvd.conf.sample +++ /dev/null @@ -1,14 +0,0 @@ -interface tap0 -{ - AdvSendAdvert on; - MinRtrAdvInterval 3; - MaxRtrAdvInterval 20; - - prefix aaaa::/64 - { - AdvOnLink on; - AdvAutonomous on; - AdvRouterAddr on; - - }; -}; diff --git a/components/coap/libcoap/examples/contiki/server.c b/components/coap/libcoap/examples/contiki/server.c deleted file mode 100644 index 7d33235be..000000000 --- a/components/coap/libcoap/examples/contiki/server.c +++ /dev/null @@ -1,231 +0,0 @@ -/* coap-server.c -- Example CoAP server using Contiki and libcoap - * - * Copyright (C) 2011 Olaf Bergmann - * - * 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -#include "coap_config.h" - -#define DEBUG DEBUG_PRINT -#include "net/ip/uip-debug.h" -#include "net/net-debug.h" - -#include - -#include "debug.h" -#include "coap.h" - -static coap_context_t *coap_context; - -static clock_time_t clock_offset; -/* changeable clock base (see handle_put_time()) */ -static clock_time_t my_clock_base = 0; -static coap_resource_t *time_resource = NULL; /* just for testing */ - -PROCESS(coap_server_process, "CoAP server process"); -AUTOSTART_PROCESSES(&coap_server_process); -/*---------------------------------------------------------------------------*/ -void -init_coap_server(coap_context_t **ctx) { - coap_address_t listen_addr; - uip_ipaddr_t gw_addr; - - assert(ctx); - - coap_set_log_level(LOG_DEBUG); - - coap_address_init(&listen_addr); - listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT); - - uip_ip6addr(&listen_addr.addr, 0xaaaa, 0, 0, 0, 0, 0, 0, NODE_ADDR); -#ifndef CONTIKI_TARGET_MINIMAL_NET - uip_ds6_prefix_add(&listen_addr.addr, 64, 0, 0, 0, 0); -#endif /* not CONTIKI_TARGET_MINIMAL_NET */ - - uip_ds6_addr_add(&listen_addr.addr, 0, ADDR_MANUAL); - - /* set default route to gateway aaaa::1 */ - uip_ip6addr(&gw_addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0x0001); - uip_ds6_defrt_add(&gw_addr, 0); - - PRINTLLADDR(&uip_lladdr); - printf("\r\n"); - PRINT6ADDR(&listen_addr.addr); - printf("\r\n"); - - *ctx = coap_new_context(&listen_addr); - - if (!*ctx) { - coap_log(LOG_CRIT, "cannot create CoAP context\r\n"); - } -} - -/*---------------------------------------------------------------------------*/ -#ifndef min -# define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -void -hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, - const coap_endpoint_t *local_interface, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - unsigned char buf[40]; - size_t len; - coap_tick_t now; - coap_tick_t t; - - /* FIXME: return time, e.g. in human-readable by default and ticks - * when query ?ticks is given. */ - - /* if my_clock_base was deleted, we pretend to have no such resource */ - response->hdr->code = - my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); - - if (coap_find_observer(resource, peer, token)) { - /* FIXME: need to check for resource->dirty? */ - coap_add_option(response, COAP_OPTION_OBSERVE, - coap_encode_var_bytes(buf, ctx->observe), buf); - } - - if (my_clock_base) - coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_add_option(response, COAP_OPTION_MAXAGE, - coap_encode_var_bytes(buf, 0x01), buf); - - if (my_clock_base) { - - /* calculate current time */ - coap_ticks(&t); - now = my_clock_base + (t / COAP_TICKS_PER_SECOND); - - if (request != NULL - && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter)) - && memcmp(COAP_OPT_VALUE(option), "ticks", - min(5, COAP_OPT_LENGTH(option))) == 0) { - /* output ticks */ - len = snprintf((char *)buf, - min(sizeof(buf), response->max_size - response->length), - "%u", (unsigned int)now); - coap_add_data(response, len, buf); - - } - } -} - -void -init_coap_resources(coap_context_t *ctx) { - coap_resource_t *r; -#if 0 - r = coap_resource_init(NULL, 0, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0); - coap_add_resource(ctx, r); -#endif - /* store clock base to use in /time */ - my_clock_base = clock_offset; - - r = coap_resource_init((unsigned char *)"time", 4, 0); - if (!r) - goto error; - - r->observable = 1; - time_resource = r; - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); -#if 0 - coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); - coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); -#endif - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - /* coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"Internal Clock\"", 16, 0); */ - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"Ticks\"", 7, 0); - coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"clock\"", 7, 0); - - coap_add_resource(ctx, r); -#if 0 -#ifndef WITHOUT_ASYNC - r = coap_resource_init((unsigned char *)"async", 5, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_resource(ctx, r); -#endif /* WITHOUT_ASYNC */ -#endif - - return; - error: - coap_log(LOG_CRIT, "cannot create resource\n"); -} - -/* struct etimer notify_timer; */ -struct etimer dirty_timer; - -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_server_process, ev, data) -{ - PROCESS_BEGIN(); - - clock_offset = clock_time(); - init_coap_server(&coap_context); - - if (!coap_context) { - coap_log(LOG_EMERG, "cannot create context\n"); - PROCESS_EXIT(); - } - - init_coap_resources(coap_context); - - if (!coap_context) { - coap_log(LOG_EMERG, "cannot create context\n"); - PROCESS_EXIT(); - } - - /* etimer_set(¬ify_timer, 5 * CLOCK_SECOND); */ - etimer_set(&dirty_timer, 30 * CLOCK_SECOND); - - while(1) { - PROCESS_YIELD(); - if(ev == tcpip_event) { - coap_read(coap_context); /* read received data */ - /* coap_dispatch(coap_context); /\* and dispatch PDUs from receivequeue *\/ */ - } else if (ev == PROCESS_EVENT_TIMER && etimer_expired(&dirty_timer)) { - time_resource->dirty = 1; - etimer_reset(&dirty_timer); - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/components/coap/libcoap/examples/etsi_coaptest.sh b/components/coap/libcoap/examples/etsi_coaptest.sh deleted file mode 100755 index 3226a2540..000000000 --- a/components/coap/libcoap/examples/etsi_coaptest.sh +++ /dev/null @@ -1,210 +0,0 @@ -#!/bin/bash - -# test coap implementation for the ETSI CoAP Plugtest in March 2012 -# with test cases described in Plugtests Guide First Draft V0.0.16 - -COAP_CLIENT=./coap-client -tcpdump=/usr/sbin/tcpdump -DEFAULTPORT=5683 -CLIENTPORT=61701 -# directory for logging -LOGDIR=logs -# set client's verbose level -callopts=" -v 5" -longtimeout=180 -clienttimeout=$longtimeout -timeoutcmd=/usr/bin/timeout - -#URIREGEX=.*\/.* -# resembles approximately an ip address -IPADDRREGEX="^[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}" -# FIXME IPV6 address -IP6REGEX=".*:.*:.*" - -# Testcase groups -CORE=( TD_COAP_CORE_01 TD_COAP_CORE_02 TD_COAP_CORE_03 -TD_COAP_CORE_04 TD_COAP_CORE_05 TD_COAP_CORE_06 TD_COAP_CORE_07 -TD_COAP_CORE_08 TD_COAP_CORE_09 TD_COAP_CORE_10 TD_COAP_CORE_11 -TD_COAP_CORE_12 TD_COAP_CORE_13 TD_COAP_CORE_14 TD_COAP_CORE_15 ) -LINK=( TD_COAP_LINK_01 TD_COAP_LINK_02 ) -BLOCK=( TD_COAP_BLOCK_01 TD_COAP_BLOCK_02 TD_COAP_BLOCK_03 TD_COAP_BLOCK_04 ) -OBS=( TD_COAP_OBS_01 TD_COAP_OBS_02 TD_COAP_OBS_03 TD_COAP_OBS_04 TD_COAP_OBS_05 ) - -testgroups=( CORE LINK BLOCK OBS ) - -# if no test cases are specified, we want to run all tests -testnumber=-1 -group='' - -source etsi_testcases.sh - -function usage { -echo "Usage: `basename $0` [-n testnumber] [-g groupname] [-t timeout] [-P server_port] [-p client port] [-d logdir] [-v] -i interface server_address" 1>&2 -echo "-n test case to be accomplished" 1>&2 -echo "-g group to be tested" 1>&2 -echo "-t time in seconds until timout for single test" 1>&2 -echo "-i interface to use for tcpdump" 1>&2 -echo "-P port of server" 1>&2 -echo "-p port client listens on" 1>&2 -echo "-d directory for logfiles" 1>&2 -echo "-v verbose level" 1>&2 -} - -function run_test { - tn=$1 - clientopts='' - if [ -z $1 ]; then - echo "missing argument for run_test" - exit 1 - fi - echo -e "running test: $tn" - if [ $(type -t $tn) ] ; then - $tn $tn - echo - else - echo "not implemented" - echo - fi -} - -while getopts "n:g:t:i:P:p:d:v" OPTION; -do -# A missing argument for an option leads getopts to take the next -# option as the parameter. We want to prevent that. -case $OPTARG in --*) echo "Missing argument for option \"-$OPTION\"." -echo $USAGE -exit 1 -;; -esac - -case $OPTION in -n) # number of test case -testnumber=$((OPTARG-1)) -;; - -g) # name of test group -# is there a group with that name? -for i in "${testgroups[@]}" - do - # group doesn't have to be case sensitive - tmpgroup=$(echo $OPTARG | tr '[:lower:]' '[:upper:]') - if [ $i == $tmpgroup ] ; then - group=$tmpgroup - break - fi -done -if [ -z $group ] ; then - echo "No such group:" $OPTARG". Available groups are: ${testgroups[@]}" - exit 1 -fi -;; - -t) -# add timeout to client parameters -clienttimeout=$((OPTARG)) -callopts="$callopts -B $clienttimeout" -;; - -i) -# interface tcpdump listens on -INTERFACE=$OPTARG -;; - -P) -# port the server listens on -SERVERPORT=$((OPTARG)) -;; - -p) -# port the client listens on -CLIENTPORT=$((OPTARG)) -;; - -d) -# directory tcpdump writes the logfiles into -LOGDIR=$OPTARG -;; - -v) -verbose=1 -;; - -?) -# any other option is invalid -echo -e $USAGE 1>&2 -exit 1 -;; -esac -done - -# catch last argument: server address -ARGS=$(($#+1)) -SERVERADDRESS=${@: -1} - -if [[ ! $((ARGS-OPTIND)) -eq 1 ]]; then - echo -e "\nno server address specified" - usage - exit 1 -fi - -# if no port number was specified by user, the server address for the -# coap-client is $SERVERADDRESS - -if [ -z $SERVERPORT ]; then - SERVERPORT=$DEFAULTPORT - if [[ $SERVERADDRESS =~ $IP6REGEX ]]; then - SERVERTUP=\[$SERVERADDRESS\] - else - SERVERTUP=$SERVERADDRESS - fi -else - if [[ $SERVERADDRESS =~ $IP6REGEX ]]; then - SERVERTUP=\[$SERVERADDRESS\]:$SERVERPORT - else - SERVERTUP=$SERVERADDRESS:$SERVERPORT - fi -fi - -# create directory for logging, if it's not already there -if [[ ! -e $LOGDIR ]]; then - mkdir -p $LOGDIR - if [ $? ]; then - echo created directory \""$LOGDIR"\" for logging - fi -fi - -# the interface for tcpdump is mandatory -if [ -z $INTERFACE ]; then - echo -e "\nno interface given" - exit 1 -fi - -# determine which tests to run -if [ -n "$group" ] ; then - echo group: $group - if [[ ! $testnumber -eq -1 ]] ; then - groupsize=$(eval "echo \${#$(echo $group)[@]}") - # is there a testcase with number $testnumber in group $group - if [ $testnumber -ge $groupsize -o $testnumber -lt 0 ] ; then - echo "No such testcase number: $OPTARG. Test cases numbers are 1 to" $groupsize - exit 1 - else - # run test with group $group and number $testnumber - run_test $(eval "echo \${$(echo $group)[$testnumber]}") - fi - else - # if no testnumber was specified, we want to run all tests in that group - for i in $(eval "echo \${$(echo $group)[@]}") ; do - run_test $i - done - fi -else - # run all tests of all groups - for j in ${testgroups[@]} ; do - echo "group: $j" - for k in $(eval "echo \${$(echo $j)[@]}") ; do - run_test $k - done - done -fi diff --git a/components/coap/libcoap/examples/etsi_iot_01.c b/components/coap/libcoap/examples/etsi_iot_01.c deleted file mode 100644 index 0edc8a936..000000000 --- a/components/coap/libcoap/examples/etsi_iot_01.c +++ /dev/null @@ -1,759 +0,0 @@ -/* CoAP server for first ETSI CoAP plugtest, March 2012 - * - * Copyright (C) 2012--2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "uthash.h" -#include "coap.h" - -#define COAP_RESOURCE_CHECK_TIME_SEC 1 - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -/* temporary storage for dynamic resource representations */ -static int quit = 0; - -#define COAP_OPT_BLOCK_SZX_MAX 6 /**< allowed maximum for block szx value */ - -#define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */ -typedef struct { - UT_hash_handle hh; - coap_key_t resource_key; /* foreign key that points into resource space */ - unsigned int flags; /* some flags to control behavior */ - size_t max_data; /* maximum size allocated for @p data */ - uint16_t media_type; /* media type for this object */ - size_t length; /* length of data */ - unsigned char data[]; /* the actual contents */ -} coap_payload_t; - -coap_payload_t *test_resources = NULL; - -/** - * This structure is used to store URIs for dynamically allocated - * resources, usually by POST or PUT. - */ -typedef struct { - UT_hash_handle hh; - coap_key_t resource_key; /* foreign key that points into resource space */ - size_t length; /* length of data */ - unsigned char data[]; /* the actual contents */ -} coap_dynamic_uri_t; - -coap_dynamic_uri_t *test_dynamic_uris = NULL; - -/* This variable is used to mimic long-running tasks that require - * asynchronous responses. */ -static coap_async_state_t *async = NULL; - -/* SIGINT handler: set quit to 1 for graceful termination */ -void -handle_sigint(int signum) { - quit = 1; -} - -#define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \ - "Copyright (C) 2012 Olaf Bergmann \n\n" - -coap_payload_t * -coap_new_payload(size_t size) { - coap_payload_t *p; - p = (coap_payload_t *)coap_malloc(sizeof(coap_payload_t) + size); - if (p) { - memset(p, 0, sizeof(coap_payload_t)); - p->max_data = size; - } - - return p; -} - -static inline coap_payload_t * -coap_find_payload(const coap_key_t key) { - coap_payload_t *p; - HASH_FIND(hh, test_resources, key, sizeof(coap_key_t), p); - return p; -} - -static inline void -coap_add_payload(const coap_key_t key, coap_payload_t *payload, - coap_dynamic_uri_t *uri) { - assert(payload); - - memcpy(payload->resource_key, key, sizeof(coap_key_t)); - HASH_ADD(hh, test_resources, resource_key, sizeof(coap_key_t), payload); - - if (uri) { - memcpy(uri->resource_key, key, sizeof(coap_key_t)); - HASH_ADD(hh, test_dynamic_uris, resource_key, sizeof(coap_key_t), uri); - } -} - -static inline void -coap_delete_payload(coap_payload_t *payload) { - if (payload) { - coap_dynamic_uri_t *uri; - HASH_FIND(hh, test_dynamic_uris, - payload->resource_key, sizeof(coap_key_t), uri); - if (uri) { - HASH_DELETE(hh, test_dynamic_uris, uri); - coap_free(uri); - } - } - - HASH_DELETE(hh, test_resources, payload); - coap_free(payload); -} - -void -hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - unsigned char buf[3]; - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_add_option(response, COAP_OPTION_MAXAGE, - coap_encode_var_bytes(buf, 0x2ffff), buf); - - coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX); -} - - -void -hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_key_t etag; - unsigned char buf[2]; - coap_payload_t *test_payload; - coap_block_t block; - - test_payload = coap_find_payload(resource->key); - if (!test_payload) { - response->hdr->code = COAP_RESPONSE_CODE(500); - - return; - } - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, test_payload->media_type), buf); - - /* add etag for the resource */ - if (test_payload->flags & REQUIRE_ETAG) { - memset(etag, 0, sizeof(etag)); - coap_hash(test_payload->data, test_payload->length, etag); - coap_add_option(response, COAP_OPTION_ETAG, sizeof(etag), etag); - } - - if (request) { - int res; - - if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) { - res = coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, - test_payload->length); - - switch (res) { - case -2: /* illegal block */ - response->hdr->code = COAP_RESPONSE_CODE(400); - goto error; - case -1: /* should really not happen */ - assert(0); - /* fall through if assert is a no-op */ - case -3: /* cannot handle request */ - response->hdr->code = COAP_RESPONSE_CODE(500); - goto error; - default: /* everything is good */ - ; - } - - coap_add_block(response, test_payload->length, test_payload->data, - block.num, block.szx); - } else { - if (!coap_add_data(response, test_payload->length, test_payload->data)) { - /* set initial block size, will be lowered by - * coap_write_block_opt) automatically */ - block.szx = 6; - coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, - test_payload->length); - - coap_add_block(response, test_payload->length, test_payload->data, - block.num, block.szx); - } - } - } else { /* this is a notification, block is 0 */ - /* FIXME: need to store block size with subscription */ - } - - return; - - error: - coap_add_data(response, - strlen(coap_response_phrase(response->hdr->code)), - (unsigned char *)coap_response_phrase(response->hdr->code)); -} - -/* DELETE handler for dynamic resources created by POST /test */ -void -hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_payload_t *payload; - - payload = coap_find_payload(resource->key); - - if (payload) - coap_delete_payload(payload); - - coap_delete_resource(ctx, resource->key); - - response->hdr->code = COAP_RESPONSE_CODE(202); -} - -void -hnd_post_test(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - coap_payload_t *test_payload; - size_t len; - size_t l = 6 + sizeof(void *); - coap_dynamic_uri_t *uri; - unsigned char *data; - -#define BUFSIZE 20 - int res; - unsigned char _buf[BUFSIZE]; - unsigned char *buf = _buf; - size_t buflen = BUFSIZE; - - coap_get_data(request, &len, &data); - - /* allocate storage for resource and to hold URI */ - test_payload = coap_new_payload(len); - uri = (coap_dynamic_uri_t *)coap_malloc(sizeof(coap_dynamic_uri_t) + l); - if (!(test_payload && uri)) { - coap_log(LOG_CRIT, "cannot allocate new resource under /test"); - response->hdr->code = COAP_RESPONSE_CODE(500); - coap_free(test_payload); - coap_free(uri); - } else { - coap_resource_t *r; - - memset(uri, 0, sizeof(coap_dynamic_uri_t)); - uri->length = min(l, snprintf((char *)uri->data, l, "test/%p", test_payload)); - test_payload->length = len; - - memcpy(test_payload->data, data, len); - - r = coap_resource_init(uri->data, uri->length, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); - coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); - - /* set media_type if available */ - option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); - if (option) { - test_payload->media_type = - coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); - } - - coap_add_resource(ctx, r); - coap_add_payload(r->key, test_payload, uri); - - /* add Location-Path */ - res = coap_split_path(uri->data, uri->length, buf, &buflen); - - while (res--) { - coap_add_option(response, COAP_OPTION_LOCATION_PATH, - COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)); - - buf += COAP_OPT_SIZE(buf); - } - - response->hdr->code = COAP_RESPONSE_CODE(201); - } - -} - -void -hnd_put_test(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - coap_payload_t *payload; - size_t len; - unsigned char *data; - - response->hdr->code = COAP_RESPONSE_CODE(204); - - coap_get_data(request, &len, &data); - - payload = coap_find_payload(resource->key); - if (payload && payload->max_data < len) { /* need more storage */ - coap_delete_payload(payload); - payload = NULL; - /* bug: when subsequent coap_new_payload() fails, our old contents - is gone */ - } - - if (!payload) { /* create new payload */ - payload = coap_new_payload(len); - if (!payload) - goto error; - - coap_add_payload(resource->key, payload, NULL); - } - payload->length = len; - memcpy(payload->data, data, len); - - option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); - if (option) { - /* set media type given in request */ - payload->media_type = - coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); - } else { - /* set default value */ - payload->media_type = COAP_MEDIATYPE_TEXT_PLAIN; - } - /* FIXME: need to change attribute ct of resource. - To do so, we need dynamic management of the attribute value - */ - - return; - error: - warn("cannot modify resource\n"); - response->hdr->code = COAP_RESPONSE_CODE(500); -} - -void -hnd_delete_test(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - /* the ETSI validation tool does not like empty resources... */ -#if 0 - coap_payload_t *payload; - payload = coap_find_payload(resource->key); - - if (payload) - payload->length = 0; -#endif - - response->hdr->code = COAP_RESPONSE_CODE(202); -} - -void -hnd_get_query(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_filter_t f; - coap_opt_t *q; - size_t len, L; - unsigned char buf[70]; - - response->hdr->code = COAP_RESPONSE_CODE(205); - - coap_add_option(response, COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_option_filter_clear(f); - coap_option_setb(f, COAP_OPTION_URI_QUERY); - - coap_option_iterator_init(request, &opt_iter, f); - - len = 0; - while ((len < sizeof(buf)) && (q = coap_option_next(&opt_iter))) { - L = min(sizeof(buf) - len, 11); - memcpy(buf + len, "Uri-Query: ", L); - len += L; - - L = min(sizeof(buf) - len, COAP_OPT_LENGTH(q)); - memcpy(buf + len, COAP_OPT_VALUE(q), L); - len += L; - - if (len < sizeof(buf)) - buf[len++] = '\n'; - } - - coap_add_data(response, len, buf); -} - -/* handler for TD_COAP_CORE_16 */ -void -hnd_get_separate(coap_context_t *ctx, struct coap_resource_t *resource, - coap_address_t *peer, coap_pdu_t *request, str *token, - coap_pdu_t *response) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - coap_opt_filter_t f; - unsigned long delay = 5; - - if (async) { - if (async->id != request->hdr->id) { - coap_opt_filter_t f; - coap_option_filter_clear(f); - response->hdr->code = COAP_RESPONSE_CODE(503); - } - return; - } - - /* search for option delay in query list */ - coap_option_filter_clear(f); - coap_option_setb(f, COAP_OPTION_URI_QUERY); - - coap_option_iterator_init(request, &opt_iter, f); - - while ((option = coap_option_next(&opt_iter))) { - if (strncmp("delay=", (char *)COAP_OPT_VALUE(option), 6) == 0) { - int i; - unsigned long d = 0; - - for (i = 6; i < COAP_OPT_LENGTH(option); ++i) - d = d * 10 + COAP_OPT_VALUE(option)[i] - '0'; - - /* don't allow delay to be less than COAP_RESOURCE_CHECK_TIME*/ - delay = d < COAP_RESOURCE_CHECK_TIME_SEC - ? COAP_RESOURCE_CHECK_TIME_SEC - : d; - debug("set delay to %lu\n", delay); - break; - } - } - - async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE, - (void *)(COAP_TICKS_PER_SECOND * delay)); -} - -void -check_async(coap_context_t *ctx, coap_tick_t now) { - coap_pdu_t *response; - coap_async_state_t *tmp; - unsigned char buf[2]; - size_t size = sizeof(coap_hdr_t) + 8; - - if (!async || now < async->created + (unsigned long)async->appdata) - return; - - size += async->tokenlen; - - response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM - ? COAP_MESSAGE_CON - : COAP_MESSAGE_NON, - COAP_RESPONSE_CODE(205), 0, size); - if (!response) { - debug("check_async: insufficient memory, we'll try later\n"); - async->appdata = - (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND); - return; - } - - response->hdr->id = coap_new_message_id(ctx); - - if (async->tokenlen) - coap_add_token(response, async->tokenlen, async->token); - - coap_add_option(response, COAP_OPTION_CONTENT_TYPE, - coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - - coap_add_data(response, 4, (unsigned char *)"done"); - - if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) { - debug("check_async: cannot send response for message %d\n", - response->hdr->id); - } - coap_delete_pdu(response); - - coap_remove_async(ctx, async->id, &tmp); - coap_free_async(async); - async = NULL; -} - -coap_payload_t * -make_large(char *filename) { - coap_payload_t *payload; - FILE *inputfile = NULL; - struct stat statbuf; - - if (!filename) - return NULL; - - /* read from specified input file */ - if (stat(filename, &statbuf) < 0) { - warn("cannot stat file %s\n", filename); - return NULL; - } - - payload = coap_new_payload(statbuf.st_size); - if (!payload) - return NULL; - - inputfile = fopen(filename, "r"); - if ( !inputfile ) { - warn("cannot read file %s\n", filename); - coap_free(payload); - return NULL; - } - - payload->length = fread(payload->data, 1, statbuf.st_size, inputfile); - payload->media_type = 41; - - fclose(inputfile); - - return payload; -} - -void -init_resources(coap_context_t *ctx) { - coap_resource_t *r; - coap_payload_t *test_payload; - - test_payload = coap_new_payload(200); - if (!test_payload) - coap_log(LOG_CRIT, "cannot allocate resource /test"); - else { - test_payload->length = 13; - memcpy(test_payload->data, "put data here", test_payload->length); - /* test_payload->media_type is 0 anyway */ - - r = coap_resource_init((unsigned char *)"test", 4, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); - coap_register_handler(r, COAP_REQUEST_POST, hnd_post_test); - coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_test); - coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_test); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"test", 4, 0); - coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"core#b", 6, 0); -#if 0 - coap_add_attr(r, (unsigned char *)"obs", 3, NULL, 0, 0); -#endif - coap_add_resource(ctx, r); - coap_add_payload(r->key, test_payload, NULL); - } - - /* TD_COAP_BLOCK_01 - * TD_COAP_BLOCK_02 */ - test_payload = make_large("etsi_iot_01_largedata.txt"); - if (!test_payload) - coap_log(LOG_CRIT, "cannot allocate resource /large\n"); - else { - r = coap_resource_init((unsigned char *)"large", 5, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"41", 2, 0); - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"large", 5, 0); - coap_add_resource(ctx, r); - - test_payload->flags |= REQUIRE_ETAG; - - coap_add_payload(r->key, test_payload, NULL); - } - - /* For TD_COAP_CORE_12 */ - test_payload = coap_new_payload(20); - if (!test_payload) - coap_log(LOG_CRIT, "cannot allocate resource /seg1/seg2/seg3\n"); - else { - test_payload->length = 10; - memcpy(test_payload->data, "segsegseg!", test_payload->length); - /* test_payload->media_type is 0 anyway */ - - r = coap_resource_init((unsigned char *)"seg1/seg2/seg3", 14, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_resource(ctx, r); - - coap_add_payload(r->key, test_payload, NULL); - } - - /* For TD_COAP_CORE_13 */ - r = coap_resource_init((unsigned char *)"query", 5, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_query); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_resource(ctx, r); - - /* For TD_COAP_CORE_16 */ - r = coap_resource_init((unsigned char *)"separate", 8, 0); - coap_register_handler(r, COAP_REQUEST_GET, hnd_get_separate); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"separate", 8, 0); - coap_add_resource(ctx, r); -} - -void -usage( const char *program, const char *version) { - const char *p; - - p = strrchr( program, '/' ); - if ( p ) - program = ++p; - - fprintf( stderr, "%s v%s -- ETSI CoAP plugtest server\n" - "(c) 2012 Olaf Bergmann \n\n" - "usage: %s [-A address] [-p port]\n\n" - "\t-A address\tinterface address to bind to\n" - "\t-p port\t\tlisten on specified port\n" - "\t-v num\t\tverbosity level (default: 3)\n", - program, version, program ); -} - -coap_context_t * -get_context(const char *node, const char *port) { - coap_context_t *ctx = NULL; - int s; - struct addrinfo hints; - struct addrinfo *result, *rp; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - - s = getaddrinfo(node, port, &hints, &result); - if ( s != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); - return NULL; - } - - /* iterate through results until success */ - for (rp = result; rp != NULL; rp = rp->ai_next) { - coap_address_t addr; - - if (rp->ai_addrlen <= sizeof(addr.addr)) { - coap_address_init(&addr); - addr.size = rp->ai_addrlen; - memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); - - ctx = coap_new_context(&addr); - if (ctx) { - /* TODO: output address:port for successful binding */ - goto finish; - } - } - } - - fprintf(stderr, "no context available for interface '%s'\n", node); - - finish: - freeaddrinfo(result); - return ctx; -} - -int -main(int argc, char **argv) { - coap_context_t *ctx; - fd_set readfds; - struct timeval tv, *timeout; - int result; - coap_tick_t now; - coap_queue_t *nextpdu; - char addr_str[NI_MAXHOST] = "::"; - char port_str[NI_MAXSERV] = "5683"; - int opt; - coap_log_t log_level = LOG_WARNING; - - while ((opt = getopt(argc, argv, "A:p:v:")) != -1) { - switch (opt) { - case 'A' : - strncpy(addr_str, optarg, NI_MAXHOST-1); - addr_str[NI_MAXHOST - 1] = '\0'; - break; - case 'p' : - strncpy(port_str, optarg, NI_MAXSERV-1); - port_str[NI_MAXSERV - 1] = '\0'; - break; - case 'v' : - log_level = strtol(optarg, NULL, 10); - break; - default: - usage( argv[0], PACKAGE_VERSION ); - exit( 1 ); - } - } - - coap_set_log_level(log_level); - - ctx = get_context(addr_str, port_str); - if (!ctx) - return -1; - - coap_register_option(ctx, COAP_OPTION_BLOCK2); - - init_resources(ctx); - - signal(SIGINT, handle_sigint); - - while ( !quit ) { - FD_ZERO(&readfds); - FD_SET( ctx->sockfd, &readfds ); - - nextpdu = coap_peek_next( ctx ); - - coap_ticks(&now); - while ( nextpdu && nextpdu->t <= now ) { - coap_retransmit( ctx, coap_pop_next( ctx ) ); - nextpdu = coap_peek_next( ctx ); - } - - if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME_SEC ) { - /* set timeout if there is a pdu to send before our automatic timeout occurs */ - tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; - timeout = &tv; - } else { - tv.tv_usec = 0; - tv.tv_sec = COAP_RESOURCE_CHECK_TIME_SEC; - timeout = &tv; - } - result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); - - if ( result < 0 ) { /* error */ - if (errno != EINTR) - perror("select"); - } else if ( result > 0 ) { /* read from socket */ - if ( FD_ISSET( ctx->sockfd, &readfds ) ) { - coap_read( ctx ); /* read received data */ - coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ - } - } else { /* timeout */ - /* coap_check_resource_list( ctx ); */ - } - - /* check if we have to send asynchronous responses */ - check_async(ctx, now); - } - - coap_free_context( ctx ); - - return 0; -} diff --git a/components/coap/libcoap/examples/etsi_iot_01_largedata.txt b/components/coap/libcoap/examples/etsi_iot_01_largedata.txt deleted file mode 100644 index 9f808f391..000000000 --- a/components/coap/libcoap/examples/etsi_iot_01_largedata.txt +++ /dev/null @@ -1,7 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet sapien ac leo bibendum suscipit at sed ipsum. Aliquam in mauris nec felis dictum lobortis a et erat. Pellentesque tempus urna vulputate purus faucibus ac pretium massa volutpat. Maecenas at tellus neque, quis elementum ante. Morbi molestie, elit placerat rhoncus faucibus, urna nunc accumsan diam, vel porta eros sem vel augue. Proin metus dolor, tristique a accumsan eget, suscipit vel ante. Suspendisse feugiat, nisl non viverra convallis, ante nibh congue lectus, sodales ultrices turpis massa sed elit. - -Praesent posuere laoreet nulla eu accumsan. Vestibulum consequat molestie erat, ut laoreet arcu mattis non. Maecenas viverra elementum mauris, vitae pretium elit ultrices sit amet. Sed sit amet elit sit amet dui imperdiet consequat. Donec viverra leo mollis lorem varius lacinia mollis nulla posuere. Phasellus felis odio, tempor et sodales non, facilisis fermentum eros. Duis dignissim massa at ante euismod vel laoreet mi tristique. Nulla libero dolor, pretium vitae vulputate eget, luctus at sapien. Praesent aliquam nisl ut urna pretium eu rhoncus ipsum eleifend. Sed lobortis vestibulum est eu eleifend. Sed vitae luctus erat. Sed vel dolor quam, tempor venenatis dolor. - -Vivamus a est a neque condimentum fermentum sed quis dui. Maecenas rhoncus imperdiet tortor, vitae viverra lectus ornare vulputate. Nam congue pulvinar faucibus. Vivamus id mauris at tortor porta volutpat. Donec non velit a tellus placerat iaculis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse at felis ligula, vel euismod velit. Aliquam in odio urna. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ac risus ipsum. Donec vel purus risus, eu molestie nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse consequat libero eu augue ornare volutpat mollis sed dui. Ut sed. diff --git a/components/coap/libcoap/examples/etsi_testcases.sh b/components/coap/libcoap/examples/etsi_testcases.sh deleted file mode 100644 index 693a8c705..000000000 --- a/components/coap/libcoap/examples/etsi_testcases.sh +++ /dev/null @@ -1,765 +0,0 @@ -#!/bin/bash - -function start_tcpdump { - testfunc=$1 - logfile=$LOGDIR/"$testfunc"_$(date +%s).dump - tcpdumpcmd="$tcpdump -i $INTERFACE host $SERVERADDRESS and (udp port $SERVERPORT or icmp) -s0 -n -w $logfile" - if [ $verbose ]; then - echo "$tcpdumpcmd" - $tcpdumpcmd& - else - $tcpdumpcmd 2>/dev/null& - fi - tcpdumppid=$! - # wait until tcpdump is ready to write - for t in {0..20} ; do - if [ ! -e $logfile ] ; then - sleep 0.1 - else - sleep 1 - if [ $verbose ]; then - echo "tcpdump started" - fi - break - fi - done -} - -function kill_tcpdump { - kill $tcpdumppid 2>/dev/null || ERROR=1 - if [ $ERROR ]; then - echo "tcpdump failed." - exit 1 - fi -} - -function start_coap_test { - if [ -z $1 ]; then - echo "missing argument for start_coap_test" - exit 1 - fi - start_tcpdump $1 - if [ $verbose ]; then - echo "client command: $COAP_CLIENT $clientopts $testaddress" - fi - echo -e "\nOutput of client:" - # for OBS - if [[ ! -z $2 ]]; then - testfifo=/tmp/tmpfifo$(date +%s) - mkfifo $testfifo - $COAP_CLIENT $clientopts "$testaddress" &> $testfifo & - clientpid=$! - ($timeoutcmd $clienttimeout cat $testfifo | if read -n 1 char; then echo "output: $char" ; fi) 2>/dev/null - # when client has written an output to fifo, kill client - kill $clientpid - rm $testfifo - if [[ $2 == "wait" ]] ; then - echo "Client killed. Waiting.." - sleep $longtimeout - fi - else - $COAP_CLIENT $clientopts "$testaddress" - fi - kill_tcpdump -} - - -## -# Perform GET (CON mode) on resource /test -# -# pre: resource /test exists and can handle GET with arbitrary payload -# -# client sends GET request with Type=0(CON) and Code=1(GET) -# -# check if sent request contains Type value indicating 0 and Code -# value indicating 1 -# -# check if server sends response containing Code = 69(2.05 Content), -# the same Message ID as that of previous request, content type option -# -# verify that server displays received information -# -function TD_COAP_CORE_01 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/test - echo "perform GET (CON mode) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform POST transaction (CON mode) on resource /test: create -# resource /test -# -# pre: resource /test doesn't exist but can be created on /test -# -# client sends POST with Type=0(CON), Code=2(POST), arbitrary payload, -# Content type option -# -# check: client sends request containing Type value indicating 0 and -# Code value indicating 2 -# -# verify: Server displays received information -# -# check: server sends response containing Code=69(2.01 Created), same -# message ID as that of the previous request, Content type option -# -# verify: client displays received information -# -function TD_COAP_CORE_02 { - # -t 0: content type text/plain - clientopts="$callopts -m post -t 0 -e sometext" - testaddress=coap://$SERVERTUP/test - echo "perform POST (CON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform PUT transaction (CON mode) on resource /test -# -# pre: resource /test exists which can handle PUT -# -# Client sends a PUT request with Type=0(CON), Code=3(PUT), arbitrary -# payload, content type option -# -# check: sent request contains Type value indicating 0 and Code value -# indicating 3 -# -# verify: server displays received information -# -# check: Server sends response containing Code=68(2.04 Changed), same -# Message ID as that of the previous request -# -# verify: client displays received response -# -function TD_COAP_CORE_03 { - clientopts="$callopts -m put -t 0 -e sometext" - testaddress=coap://$SERVERTUP/test - echo "perform PUT (CON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform DELETE transaction (CON mode) on resource /test -# -# pre: resource /test exists which can handle DELETE -# -# Client sends a DELETE request with Type=0(CON), Code=4(DELETE) -# -# check: sent request contains Type value indicating 0 and Code value -# indicating 4 -# -# check: Server sends response containing Code=66(2.02 Deleted), same -# Message ID as that of the previous request -# -# verify: client displays received response -# -function TD_COAP_CORE_04 { - clientopts="$callopts -m delete" - testaddress=coap://$SERVERTUP/test - echo "perform DELETE (CON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform GET transaction (NON mode) on resource /test -# -# pre: resource /test exits which can handle GET -# -# Client sends a GET request with Type=1(NON), Code=1(GET) -# -# check: sent request contains Type value indicating 1 and Code value -# indicating 1 -# -# check: Server sends response containing Type=1(NON), Code=69(2.05 -# Content), content type option -# -# verify: client displays received response -# -function TD_COAP_CORE_05 { - # -N: send non-confirmable message - clientopts="$callopts -m get -N" - testaddress=coap://$SERVERTUP/test - echo "perform GET (NON mode) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform POST transaction (NON mode), create resource on /test -# -# pre: resource on /test doesn't exist but can be created -# -# Client sends a POST request with Type=1(NON), Code=2(POST), -# arbitrary payload, content type option -# -# check: sent request contains Type value indicating 1 and Code value -# indicating 2 -# -# verify: Server displays the received information -# -# check: Server sends response containing Type=1(NON), Code=65(2.01 -# Created) -# -# verify: client displays received response -# -function TD_COAP_CORE_06 { - clientopts="$callopts -m post -t 0 -e sometext -N" - testaddress=coap://$SERVERTUP/test - echo "perform POST (NON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform PUT transaction (NON mode) on resource /test -# -# pre: /test exists and can handle PUT -# -# Client sends a PUT request with Type=1(NON), Code=3(PUT), -# arbitrary payload, content type option -# -# check: sent request contains Type value indicating 1 and Code value -# indicating 3 -# -# verify: Server displays the received information -# -# check: Server sends response containing Type=1(NON), Code=68(2.04 -# Changed) -# -# verify: client displays received response -# -function TD_COAP_CORE_07 { - clientopts="$callopts -m put -t 0 -e sometext -N" - testaddress=coap://$SERVERTUP/test - echo "perform PUT (NON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform DELETE transaction (NON mode) on resource /test -# -# pre: /test exists and can handle DELETE -# -# Client sends a DELETE request with Type=1(NON), Code=4(DELETE) -# -# check: sent request contains Type value indicating 1 and Code value -# indicating 4 -# -# check: Server sends response containing Type=1(NON), Code=66(2.02 -# Deleted) -# -# verify: client displays received response -# -function TD_COAP_CORE_08 { - clientopts="$callopts -m delete -N" - testaddress=coap://$SERVERTUP/test - echo "perform DELETE (NON) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform GET transaction with a separate response on resource /separate -# -# pre: resource /separate exists which cannot be served immediately and which -# cannot be acknowledged in a piggy-backed way -# -# Client sends a confirmable GET request to server's resource -# -# check: sent request contains Type=0(CON), Code=1(GET), client -# generated Message ID -# -# check: Server sends response containing Type=2(ACK), message ID same -# as the request, empty Payload -# -# check: Server sends response containing Type=0(CON), Code=69(2.05 -# content), Payload=Content of the requested resource, Content type option -# -# check: Client sends response containing Type=2(ACK), message ID same -# as the response, empty Payload -# -# verify: client displays received response -# -function TD_COAP_CORE_09 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/separate - echo "perform GET (CON) on resource $testaddress which cannot be served immediately" - start_coap_test $1 -} - -## -# Perform GET transaction with Token on resource /test -# -# pre: resource /test exists which can handle GET requests -# -# Client sends a confirmable GET request to server's resource -# including Token option -# -# check: sent request contains Type=0(CON) and Code=1(GET), client -# generated Token value, length of the token which should be between 1 -# to 8 B, Option Type=Token -# -# check: Server sends response containing Code=69(2.05 content), -# length of the token should be between 1 to 8 B, Token value same as -# the requested, Payload=Content of the requested resource, Content -# type option -# -# verify: client displays received response -# -function TD_COAP_CORE_10 { - clientopts="$callopts -m get -T sometok" - testaddress=coap://$SERVERTUP/test - echo "perform GET (CON) on resource $testaddress with Token" - start_coap_test $1 -} - -## -# Perform GET transaction without Token on resource /test -# -# pre: resource /test exists which can handle GET requests -# -# Client sends a confirmable GET request to server's resource -# not containing Token option -# -# check: sent request contains Type=0(CON) and Code=1(GET), no Token -# option -# -# check: Server sends response containing Code=69(2.05 content), no -# Token option, Payload=Content of the requested resource, Content -# type option -# -# verify: client displays received response -# -function TD_COAP_CORE_11 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/test - echo "perform GET (CON mode) without Token on resource $testaddress" - start_coap_test $1 -} - -## -# Perform GET transaction to resource /seg1/seg2/seg3 -# -# pre: resource /seg1/seg2/seg3 exists on server -# -# Client sends a confirmable GET request to server's resource -# -# check: sent request contains Type=0(CON) and Code=1(GET), Option -# type=URI-Path (one for each path segment) -# -# check: Server sends response containing Code=69(2.05 content), -# Payload=Content of the requested resource, Content type option -# -# verify: client displays received response -# -function TD_COAP_CORE_12 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/seg1/seg2/seg3 - echo "perform GET (CON mode) on resource $testaddress" - start_coap_test $1 -} - -## -# Perform GET transaction to resource /query -# -# pre: resource /query exists on server -# -# Client sends a confirmable GET request with three Query parameters -# (e.g. ?first=1&second=2&third=3) to server's resource -# -# check: sent request contains Type=0(CON) and Code=1(GET), Option -# type=URI-Query (More than one query parameter) -# -# check: Server sends response containing Type=0/2(Con/ACK), -# Code=69(2.05 content), Payload=Content of the requested resource, -# Content type option -# -# verify: client displays received response -# -function TD_COAP_CORE_13 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/query - query="?first=1&second=2&third=3" - echo -e "perform GET (CON mode) on resource $testaddress with query $query" - testaddress=$testaddress$query - start_coap_test $1 -} - -## -# Perform GET transaction to resource /test in lossy context -# -# pre: gateway is introduced and configured to produce packet loss, -# resource /test exists on server -# -# Configuration=CoAP_CFG_02 -# -# observe: One dropped request, one dropped request ACK, one dropped -# response, one dropped response ACK and its retransmission, test -# sequence should be executed several times -# -# Client sends a confirmable GET request to server's resource -# -# check: sent request contains Type=0(CON) and Code=1(GET), Client -# generated Message ID -# -# check: Server sends response containing Type=2(ACK), Code=69(2.05 -# content), Payload=Content of the requested resource, Content type -# option -# -# verify: client displays received response -# -function TD_COAP_CORE_14 { - clientopts="$callopts -m get" - #FIXME: address for lossy context? - testaddress=coap://$SERVERTUP/test - echo "perform GET (CON mode) on resource $testaddress in lossy context" - start_coap_test $1 -} - -## -# Perform GET transaction to resource /separate in lossy context -# -# pre: gateway is introduced and configured to produce packet loss, -# resource /separate exists which cannot be served immediately and -# which cannot be acknowledged in a piggy-backed way -# -# Configuration=CoAP_CFG_02 -# -# observe: One dropped request, one dropped request ACK, one dropped -# response, one dropped response ACK and its retransmission, test -# sequence should be executed several times -# -# Client sends a confirmable GET request to server's resource -# -# check: sent request contains Type=0(CON) and Code=1(GET), Client -# generated Message ID -# -# check: server sends response containing Type=2(ACK), Message ID same -# as the request, empty Payload -# -# check: Server sends response containing Type=0(CON), Code=69(2.05 -# content), Payload=Content of the requested resource, Content type -# option -# -# check: Client sends response containing Type=2(ACK), message ID same -# as the response, empty Payload -# -# verify: client displays received response -# -function TD_COAP_CORE_15 { - clientopts="$callopts -m get" - #FIXME: address for lossy context? - testaddress=coap://$SERVERTUP/separate - echo "perform GET (CON mode) on resource $testaddress in lossy context" - start_coap_test $1 -} - -### LINK ### - -## -# Access to well-known interface for resource discovery -# -# Pre: client supports CoRE Link Format, server supports -# /.well-known/core resource and the CoRE Link Format -# -# Client retrieves Server's list of resource -# -# check: client sends GET request for /.well-known/core resource -# -# check: server sends response containing content-type option -# indicating 40 (application/link-format), payload indicating all the -# links available on Server -# -# client displays the list of resources available on Server -# -function TD_COAP_LINK_01 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/.well-known/core - echo "retrieve server's list of resource" - start_tcpdump $1 - if [ $verbose ]; then - echo "client command: $COAP_CLIENT $clientopts $testaddress" - fi - clientoutput=$($COAP_CLIENT $clientopts "$testaddress") - if [[ ! $(echo $clientoutput | grep rt) ]] ; then - echo "no resource with attribute rt found on server" - else - rt="${clientoutput##*rt=\"}" - rt="${rt%%\";*}" - fi - echo -e "\nOutput of client:" - echo -e $clientoutput - echo - kill_tcpdump -} - -## -# Use filtered requests for limiting discovery results -# -# Pre: client supports CoRE Link Format, server supports CoRE Link -# Format and offers different types of resources (Type 1, Type 2 -# (extracted from /.well-knwon/core resource -# -# Client retrieves Server's list of resource of a specific Type 1 -# -# check: client sends GET request for /.well-known/core resource -# containing URI-Query indicating "rt=Type1" -# -# check: server sends response containing content-type option -# indicating 40 (application/link-format), payload indicating only the -# links of type Type1 available on server -# -# client displays the list of resources of type Type1 available on Server -# -function TD_COAP_LINK_02 { - clientopts="$callopts -m get" - echo "retrieve server's list of resource for appropriate type" - if [[ ! -z $rt ]]; then - testaddress="coap://$SERVERTUP/.well-known/core?rt=$rt" - else - echo "no appropriate resource found. Skipping test" - return - fi - start_coap_test $1 -} - -### BLOCK ### - -## -# Perform GET blockwise transfer for large resource (early negotiation) -# -# pre: Client supports Block transfers, Server supports Block -# transfers, Server offers a large resource /large, client knows -# /large requires block transfer -# -# Client is requested to retrieve resource /large -# -# check: client sends a GET request containing Block2 option indicating block -# number 0 and desired block size -# -# check: Each request contains Block2 option indicating block number -# of the next block and size of the last received block -# -# check: server sends further responses containing Block2 option -# indicating block number and size -# -# verify: client displays received response -# -function TD_COAP_BLOCK_01 { - clientopts="$callopts -m get -b 1024" - testaddress=coap://$SERVERTUP/large - echo "perform GET on large resource $testaddress (early negotiation)" - start_coap_test $1 -} - -## -# Perform GET blockwise transfer for large resource (late negotiation) -# -# pre: Client supports Block transfers, Server supports Block -# transfers, Server offers a large resource /large, client does not -# know /large requires block transfer -# -# Client is requested to retrieve resource /large -# -# check: client sends a GET request not containing Block2 option -# -# check: server sends response containing Block2 option indicating -# block number and size -# -# check: Each request contains Block2 option indicating block number -# of the next block and size of the last received block or the desired -# size of the next block -# -# check: server sends further responses containing Block2 option -# indicating block number and size -# -# verify: client displays received response -# -function TD_COAP_BLOCK_02 { - clientopts="$callopts -m get" - testaddress=coap://$SERVERTUP/large - echo "perform GET blockwise transfer for large resource (late negotiation) on resource $testaddress" - start_coap_test $1 stop -} - -## -# Perform PUT blockwise transfer for large resource -# -# pre: Client supports Block transfers, Server supports Block -# transfers, Server offers a large updatable resource /large-update -# -# Client is requested to retrieve resource /large-update on server -# -# check: client sends a PUT request containing Block1 option -# indicating block number 0 and block size -# -# check: client sends further request containing Block1 option -# indicating block number and size -# -# verify: server indicates presence of the complete updated resource -# /large-update -# -function TD_COAP_BLOCK_03 { - clientopts="$callopts -m put -b 1024" - testaddress=coap://$SERVERTUP/large-update - echo "perform PUT on large resource $testaddress" - start_coap_test $1 -} - -## -# Perform POST blockwise transfer for large resource -# -# pre: Client supports Block transfers, Server supports Block -# transfers, Server accepts creation of new resources on /large-create -# -# Client is requested to create a new resource on server -# -# check: client sends a POST request containing Block1 option -# indicating block number 0 and block size -# -# check: client sends further requests containing Block1 option -# indicating block number and size -# -# verify: server indicates presence of the complete new resource -# -function TD_COAP_BLOCK_04 { - clientopts="$callopts -m post -b 1024" - testaddress=coap://$SERVERTUP/large-create - echo "perform POST on large resource $testaddress" - start_coap_test $1 -} - -# # OBS - -## -# Handle observe option -# -# pre: client supports Observe option, server supports observe option, -# server offers an observable resource /obs which changes periodically -# (e.g. every 5s.) -# -# client is requested to observe resource /obs on server -# -# check: client sends a GET request containing observe option -# -# verify: client displays the received information -# -# check: server sends response containing observe option indicating -# increasing values, as resource changes -# -# verify: client displays the updated information -# -function TD_COAP_OBS_01 { - # we need some time to verify the correct behavior - clientopts="$callopts -s 0" #"-v 5 -B $longtimeout -s 0" - testaddress=coap://$SERVERTUP/obs - echo "observe resource $testaddress" - start_coap_test $1 -} - -## -# Stop resource observation -# -# pre: client supports Observe option, server supports observe option, -# server offers an observable resource /obs which changes periodically -# (e.g. every 5s.), client is observing /obs on server -# -# client is requested to stop observing resource /obs on server -# -# check: client sends a GET request not containing observe option -# -# verify: client displays the received information -# -# check: server does not send further response -# -# verify: client does not display the updated information -# -# function TD_COAP_OBS_02 { -# #FIXME: client does not support stopping yet - # we need some time to verify the correct behavior -# clientopts="-v 5 -B $longtimeout -s 1" -# testaddress=coap://$SERVERTUP/obs -# echo "stop observing resource $testaddress" -# start_coap_test $1 -# } - -## -# client detection of deregistration (Max-Age) -# -# pre: client supports Observe option, server supports observe option, -# server offers an observable resource /obs which changes periodically -# (e.g. every 5s.), client is observing /obs on server -# -# Server is rebooted -# -# check: Server does not send notifications -# -# verify: Client does not display updated information -# -# verify: After Max-Age expiration, client sends a new GET with observe -# option for Server's observable resource -# -# check: Sent request contains Observe option indicating 0 -# -# check: Server sends response containing Observe option -# -# verify: client displays the received information -# -# check: Server sends response containing Observe option indicating -# increasing values, as resource changes -# -# verify: Client displays the updated information -# -function TD_COAP_OBS_03 { - clientopts="$callopts -s 0"#"-v5 -B $longtimeout -s 0" - testaddress=coap://$SERVERTUP/obs - echo "client detection of deregistration (Max-Age)" - start_coap_test $1 -} - -## -# Server detection of deregistration (client OFF) -# -# pre: client supports Observe option, server supports observe option, -# server offers an observable resource /obs which changes periodically -# (e.g. every 5s.), client is observing /obs on server -# -# Client is switched off -# -# check: Server’s confirmable responses are not acknowledged -# -# verify: After some delay, Server does not send further responses -# -function TD_COAP_OBS_04 { - clientopts="$callopts -s 0" -#"-v 5 -B $longtimeout -s 0" - testaddress=coap://$SERVERTUP/obs - echo "server detection of deregistration (client off)" - start_coap_test $1 wait -} - -## -# Server detection of deregistration (explicit RST) -# -# pre: client supports Observe option, server supports observe option, -# server offers an observable resource /obs which changes periodically -# (e.g. every 5s.), client is observing /obs on server -# -# Client is rebooted -# -# check: Server sends response containing Observe option -# -# verify: Client discards response and does not display information -# -# check: Client sends RST to Server -# -# check: Server does not send further response -# -function TD_COAP_OBS_05 { - clientopts="$callopts -s 0 -p $CLIENTPORT" -#"-v 5 -B $longtimeout -p $CLIENTPORT -s 0" - testaddress=coap://$SERVERTUP/obs - echo "server detection of deregistration (explicit RST)" - start_coap_test $1 stop - clientopts="$callopts -p $CLIENTPORT -s 0 -N" -#"-v 5 -B $clienttimeout -p $CLIENTPORT -s 0 -N" - testaddress=coap://[::1]/obs - start_coap_test $1 -} \ No newline at end of file diff --git a/components/coap/libcoap/examples/lwip/.gitignore b/components/coap/libcoap/examples/lwip/.gitignore deleted file mode 100644 index 7905765c5..000000000 --- a/components/coap/libcoap/examples/lwip/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# not going for submodules here to keep things easy -lwip -lwip-contrib - -# never objects, and not the resulting binary -*.o -server diff --git a/components/coap/libcoap/examples/lwip/README b/components/coap/libcoap/examples/lwip/README deleted file mode 100644 index 776cd36b7..000000000 --- a/components/coap/libcoap/examples/lwip/README +++ /dev/null @@ -1,27 +0,0 @@ -Example of libcoap running on lwIP -================================== - -To run the example, do - - $ make - $ sudo ./server - -(and in a second terminal) - - $ sudo ip a a dev tap0 192.168.0.1/24 - -and query `coap://192.168.0.2/` with any coap tool. - -This will - -* download lwip and lwip-contrib from the upstream git sources -* apply a required patch to lwip -* build the server application -* run the server application, creating a virtual network device tap0 (unless - that exists) -* configure your network interface to make the server accessible. - -The server does not create any resources (it exposes an empty -`.well-known/core`), but the work flow for adding more resources does not -differ from regular libcoap usage. If you seem to run out of memory creating -the resources, tweak the number of pre-allocated resources in `lwippools.h`. diff --git a/components/coap/libcoap/examples/lwip/lwipopts.h b/components/coap/libcoap/examples/lwip/lwipopts.h deleted file mode 100644 index 0182c5980..000000000 --- a/components/coap/libcoap/examples/lwip/lwipopts.h +++ /dev/null @@ -1,11 +0,0 @@ -#define NO_SYS 1 - -/* they'd require NO_SYS=0, but are enabled by default */ -#define LWIP_SOCKET 0 -#define LWIP_NETCONN 0 - -#define LWIP_IPV6 1 -#define LWIP_IPV6_REASS 0 - - -#define MEMP_USE_CUSTOM_POOLS 1 diff --git a/components/coap/libcoap/examples/lwip/server-coap.c b/components/coap/libcoap/examples/lwip/server-coap.c deleted file mode 100644 index 978648f5a..000000000 --- a/components/coap/libcoap/examples/lwip/server-coap.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "coap_config.h" -#include - -coap_context_t *main_coap_context; - -void server_coap_init(void) -{ - coap_address_t listenaddress; - - coap_address_init(&listenaddress); - - /* looks like a server address, but is used as end point for clients too */ - listenaddress.addr = *(IP_ANY_TYPE); - listenaddress.port = COAP_DEFAULT_PORT; - - main_coap_context = coap_new_context(&listenaddress); - - LWIP_ASSERT("Failed to initialize context", main_coap_context != NULL); -} - -void server_coap_poll(void) -{ - coap_check_notify(main_coap_context); -} diff --git a/components/coap/libcoap/examples/lwip/server-coap.h b/components/coap/libcoap/examples/lwip/server-coap.h deleted file mode 100644 index e45e263b1..000000000 --- a/components/coap/libcoap/examples/lwip/server-coap.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "coap_config.h" -#include - -void server_coap_init(void); -/* call this when you think that resources could be dirty */ -void server_coap_poll(void); diff --git a/components/coap/libcoap/examples/lwip/server.c b/components/coap/libcoap/examples/lwip/server.c deleted file mode 100644 index 9f8067822..000000000 --- a/components/coap/libcoap/examples/lwip/server.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Demo for libcoap on lwIP - * - * partially copied from lwip-contrib/ports/unix/proj/minimal/main.c - * - * - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * Author: Adam Dunkels - * RT timer modifications by Christiaan Simons - * lwip adaptions: chrysn - * also, https://savannah.nongnu.org/bugs/?40245 was applied */ - -#include "server-coap.h" - -#include -#include - -#include -#include - -#include - -static ip4_addr_t ipaddr, netmask, gw; - -int -main(int argc, char **argv) -{ - struct netif netif; - - /* startup defaults (may be overridden by one or more opts). this is - * hard-coded v4 even in presence of v6, which does auto-discovery and - * should thus wind up with an address of fe80::12:34ff:fe56:78ab%tap0 - * */ - IP4_ADDR(&gw, 192,168,0,1); - IP4_ADDR(&ipaddr, 192,168,0,2); - IP4_ADDR(&netmask, 255,255,255,0); - - lwip_init(); - - printf("TCP/IP initialized.\n"); - - netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); - netif.flags |= NETIF_FLAG_ETHARP; - netif_set_default(&netif); - netif_set_up(&netif); -#if LWIP_IPV6 - netif_create_ip6_linklocal_address(&netif, 1); -#endif - - /* start applications here */ - - server_coap_init(); - - printf("Applications started.\n"); - - - while (1) { - /* poll netif, pass packet to lwIP */ - tapif_select(&netif); - - sys_check_timeouts(); - - server_coap_poll(); - } - - return 0; -} diff --git a/components/coap/libcoap/examples/tiny.c b/components/coap/libcoap/examples/tiny.c deleted file mode 100644 index 86cef8419..000000000 --- a/components/coap/libcoap/examples/tiny.c +++ /dev/null @@ -1,149 +0,0 @@ -/* tiny -- tiny sender - * - * Copyright (C) 2010,2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../coap.h" - -static coap_tid_t id; - -coap_pdu_t * -make_pdu( unsigned int value ) { - coap_pdu_t *pdu; - unsigned char enc; - static unsigned char buf[20]; - int len, ls; - - if ( ! ( pdu = coap_new_pdu() ) ) - return NULL; - - pdu->hdr->type = COAP_MESSAGE_NON; - pdu->hdr->code = COAP_REQUEST_POST; - pdu->hdr->id = htons(id++); - - enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value,ls); - coap_add_data( pdu, 1, &enc); - - len = sprintf((char *)buf, "%u", COAP_PSEUDOFP_DECODE_8_4(enc)); - if ( len > 0 ) { - coap_add_data( pdu, len, buf ); - } - - return pdu; -} - -void -usage( const char *program ) { - const char *p; - - p = strrchr( program, '/' ); - if ( p ) - program = ++p; - - fprintf( stderr, "%s -- tiny fake sensor\n" - "(c) 2010 Olaf Bergmann \n\n" - "usage: %s [group address]\n" - "\n\nSends some fake sensor values to specified multicast group\n", - program, program ); -} - -coap_context_t * -get_context(const char *node, const char *port) { - coap_context_t *ctx = NULL; - int s; - struct addrinfo hints; - struct addrinfo *result, *rp; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; - - s = getaddrinfo(node, port, &hints, &result); - if ( s != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); - return NULL; - } - - /* iterate through results until success */ - for (rp = result; rp != NULL; rp = rp->ai_next) { - ctx = coap_new_context(rp->ai_addr, rp->ai_addrlen); - if (ctx) { - /* TODO: output address:port for successful binding */ - goto finish; - } - } - - fprintf(stderr, "no context available for interface '%s'\n", node); - - finish: - freeaddrinfo(result); - return ctx; -} - -int -main(int argc, char **argv) { - coap_context_t *ctx; - struct timeval tv; - coap_pdu_t *pdu; - struct sockaddr_in6 dst; - int hops = 16; - - if ( argc > 1 && strncmp(argv[1], "-h", 2) == 0 ) { - usage( argv[0] ); - exit( 1 ); - } - - ctx = get_context("::", NULL); - if ( !ctx ) - return -1; - - id = rand() & INT_MAX; - - memset(&dst, 0, sizeof(struct sockaddr_in6 )); - dst.sin6_family = AF_INET6; - inet_pton( AF_INET6, argc > 1 ? argv[1] : "::1", &dst.sin6_addr ); - dst.sin6_port = htons( COAP_DEFAULT_PORT ); - - if ( IN6_IS_ADDR_MULTICAST(&dst.sin6_addr) ) { - /* set socket options for multicast */ - - if ( setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, - (char *)&hops, sizeof(hops) ) < 0 ) - perror("setsockopt: IPV6_MULTICAST_HOPS"); - - } - - while ( 1 ) { - - if (! (pdu = make_pdu( rand() & 0xfff ) ) ) - return -1; - - coap_send( ctx, (struct sockaddr *)&dst, sizeof(dst), pdu ); - coap_delete_pdu(pdu); - - tv.tv_sec = 5; tv.tv_usec = 0; - - select( 0, 0, 0, 0, &tv ); - - } - - coap_free_context( ctx ); - - return 0; -} diff --git a/components/coap/libcoap/include/coap/address.h b/components/coap/libcoap/include/coap/address.h deleted file mode 100644 index b45e81e63..000000000 --- a/components/coap/libcoap/include/coap/address.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * address.h -- representation of network addresses - * - * Copyright (C) 2010-2011,2015-2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file address.h - * @brief Representation of network addresses - */ - -#ifndef _COAP_ADDRESS_H_ -#define _COAP_ADDRESS_H_ - -#include -#include -#include -#include -#include "libcoap.h" - -#ifdef WITH_LWIP -#include - -typedef struct coap_address_t { - uint16_t port; - ip_addr_t addr; -} coap_address_t; - -#define _coap_address_equals_impl(A, B) (!!ip_addr_cmp(&(A)->addr,&(B)->addr)) - -#define _coap_address_isany_impl(A) ip_addr_isany(&(A)->addr) - -#define _coap_is_mcast_impl(Address) ip_addr_ismulticast(&(Address)->addr) -#endif /* WITH_LWIP */ - -#ifdef WITH_CONTIKI -#include "uip.h" - -typedef struct coap_address_t { - uip_ipaddr_t addr; - unsigned short port; -} coap_address_t; - -#define _coap_address_equals_impl(A,B) \ - ((A)->port == (B)->port \ - && uip_ipaddr_cmp(&((A)->addr),&((B)->addr))) - -/** @todo implementation of _coap_address_isany_impl() for Contiki */ -#define _coap_address_isany_impl(A) 0 - -#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) -#endif /* WITH_CONTIKI */ - -#ifdef WITH_POSIX -/** multi-purpose address abstraction */ -typedef struct coap_address_t { - socklen_t size; /**< size of addr */ - union { - struct sockaddr sa; - struct sockaddr_storage st; - struct sockaddr_in sin; -#if COAP_IPV6 - struct sockaddr_in6 sin6; -#endif - } addr; -} coap_address_t; - -/** - * Compares given address objects @p a and @p b. This function returns @c 1 if - * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be - * @c NULL; - */ -int coap_address_equals(const coap_address_t *a, const coap_address_t *b); - -static inline int -_coap_address_isany_impl(const coap_address_t *a) { - /* need to compare only relevant parts of sockaddr_in6 */ - switch (a->addr.sa.sa_family) { - case AF_INET: - return a->addr.sin.sin_addr.s_addr == INADDR_ANY; -#if COAP_IPV6 - case AF_INET6: - return memcmp(&in6addr_any, - &a->addr.sin6.sin6_addr, - sizeof(in6addr_any)) == 0; -#endif - default: - ; - } - - return 0; -} -#endif /* WITH_POSIX */ - -/** - * Resets the given coap_address_t object @p addr to its default values. In - * particular, the member size must be initialized to the available size for - * storing addresses. - * - * @param addr The coap_address_t object to initialize. - */ -static inline void -coap_address_init(coap_address_t *addr) { - assert(addr); - memset(addr, 0, sizeof(coap_address_t)); -#ifdef WITH_POSIX - /* lwip and Contiki have constant address sizes and doesn't need the .size part */ - addr->size = sizeof(addr->addr); -#endif -} - -#ifndef WITH_POSIX -/** - * Compares given address objects @p a and @p b. This function returns @c 1 if - * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be - * @c NULL; - */ -static inline int -coap_address_equals(const coap_address_t *a, const coap_address_t *b) { - assert(a); assert(b); - return _coap_address_equals_impl(a, b); -} -#endif - -/** - * Checks if given address object @p a denotes the wildcard address. This - * function returns @c 1 if this is the case, @c 0 otherwise. The parameters @p - * a must not be @c NULL; - */ -static inline int -coap_address_isany(const coap_address_t *a) { - assert(a); - return _coap_address_isany_impl(a); -} - -#ifdef WITH_POSIX -/** - * Checks if given address @p a denotes a multicast address. This function - * returns @c 1 if @p a is multicast, @c 0 otherwise. - */ -int coap_is_mcast(const coap_address_t *a); -#else /* WITH_POSIX */ -/** - * Checks if given address @p a denotes a multicast address. This function - * returns @c 1 if @p a is multicast, @c 0 otherwise. - */ -static inline int -coap_is_mcast(const coap_address_t *a) { - return a && _coap_is_mcast_impl(a); -} -#endif /* WITH_POSIX */ - -#endif /* _COAP_ADDRESS_H_ */ diff --git a/components/coap/libcoap/include/coap/async.h b/components/coap/libcoap/include/coap/async.h deleted file mode 100644 index 0c36defac..000000000 --- a/components/coap/libcoap/include/coap/async.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * async.h -- state management for asynchronous messages - * - * Copyright (C) 2010-2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file async.h - * @brief State management for asynchronous messages - */ - -#ifndef _COAP_ASYNC_H_ -#define _COAP_ASYNC_H_ - -#include "net.h" - -#ifndef WITHOUT_ASYNC - -/** - * @defgroup coap_async Asynchronous Messaging - * @{ - * Structure for managing asynchronous state of CoAP resources. A - * coap_resource_t object holds a list of coap_async_state_t objects that can be - * used to generate a separate response in case a result of an operation cannot - * be delivered in time, or the resource has been explicitly subscribed to with - * the option @c observe. - */ -typedef struct coap_async_state_t { - unsigned char flags; /**< holds the flags to control behaviour */ - - /** - * Holds the internal time when the object was registered with a - * resource. This field will be updated whenever - * coap_register_async() is called for a specific resource. - */ - coap_tick_t created; - - /** - * This field can be used to register opaque application data with the - * asynchronous state object. - */ - void *appdata; - unsigned short message_id; /**< id of last message seen */ - coap_tid_t id; /**< transaction id */ - struct coap_async_state_t *next; /**< internally used for linking */ - coap_address_t peer; /**< the peer to notify */ - size_t tokenlen; /**< length of the token */ - unsigned char token[]; /**< the token to use in a response */ -} coap_async_state_t; - -/* Definitions for Async Status Flags These flags can be used to control the - * behaviour of asynchronous response generation. - */ -#define COAP_ASYNC_CONFIRM 0x01 /**< send confirmable response */ -#define COAP_ASYNC_SEPARATE 0x02 /**< send separate response */ -#define COAP_ASYNC_OBSERVED 0x04 /**< the resource is being observed */ - -/** release application data on destruction */ -#define COAP_ASYNC_RELEASE_DATA 0x08 - -/** - * Allocates a new coap_async_state_t object and fills its fields according to - * the given @p request. The @p flags are used to control generation of empty - * ACK responses to stop retransmissions and to release registered @p data when - * the resource is deleted by coap_free_async(). This function returns a pointer - * to the registered coap_async_t object or @c NULL on error. Note that this - * function will return @c NULL in case that an object with the same identifier - * is already registered. - * - * @param context The context to use. - * @param peer The remote peer that is to be asynchronously notified. - * @param request The request that is handled asynchronously. - * @param flags Flags to control state management. - * @param data Opaque application data to register. Note that the - * storage occupied by @p data is released on destruction - * only if flag COAP_ASYNC_RELEASE_DATA is set. - * - * @return A pointer to the registered coap_async_state_t object or @c - * NULL in case of an error. - */ -coap_async_state_t * -coap_register_async(coap_context_t *context, - coap_address_t *peer, - coap_pdu_t *request, - unsigned char flags, - void *data); - -/** - * Removes the state object identified by @p id from @p context. The removed - * object is returned in @p s, if found. Otherwise, @p s is undefined. This - * function returns @c 1 if the object was removed, @c 0 otherwise. Note that - * the storage allocated for the stored object is not released by this - * functions. You will have to call coap_free_async() to do so. - * - * @param context The context where the async object is registered. - * @param id The identifier of the asynchronous transaction. - * @param s Will be set to the object identified by @p id after removal. - * - * @return @c 1 if object was removed and @p s updated, or @c 0 if no - * object was found with the given id. @p s is valid only if the - * return value is @c 1. - */ -int coap_remove_async(coap_context_t *context, - coap_tid_t id, - coap_async_state_t **s); - -/** - * Releases the memory that was allocated by coap_async_state_init() for the - * object @p s. The registered application data will be released automatically - * if COAP_ASYNC_RELEASE_DATA is set. - * - * @param state The object to delete. - */ -void -coap_free_async(coap_async_state_t *state); - -/** - * Retrieves the object identified by @p id from the list of asynchronous - * transactions that are registered with @p context. This function returns a - * pointer to that object or @c NULL if not found. - * - * @param context The context where the asynchronous objects are registered - * with. - * @param id The id of the object to retrieve. - * - * @return A pointer to the object identified by @p id or @c NULL if - * not found. - */ -coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id); - -/** - * Updates the time stamp of @p s. - * - * @param s The state object to update. - */ -static inline void -coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); } - -/** @} */ - -#endif /* WITHOUT_ASYNC */ - -#endif /* _COAP_ASYNC_H_ */ diff --git a/components/coap/libcoap/include/coap/bits.h b/components/coap/libcoap/include/coap/bits.h deleted file mode 100644 index 0b269166d..000000000 --- a/components/coap/libcoap/include/coap/bits.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * bits.h -- bit vector manipulation - * - * Copyright (C) 2010-2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file bits.h - * @brief Bit vector manipulation - */ - -#ifndef _COAP_BITS_H_ -#define _COAP_BITS_H_ - -#include - -/** - * Sets the bit @p bit in bit-vector @p vec. This function returns @c 1 if bit - * was set or @c -1 on error (i.e. when the given bit does not fit in the - * vector). - * - * @param vec The bit-vector to change. - * @param size The size of @p vec in bytes. - * @param bit The bit to set in @p vec. - * - * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. - */ -inline static int -bits_setb(uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) - return -1; - - *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07)); - return 1; -} - -/** - * Clears the bit @p bit from bit-vector @p vec. This function returns @c 1 if - * bit was cleared or @c -1 on error (i.e. when the given bit does not fit in - * the vector). - * - * @param vec The bit-vector to change. - * @param size The size of @p vec in bytes. - * @param bit The bit to clear from @p vec. - * - * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. - */ -inline static int -bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) - return -1; - - *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07))); - return 1; -} - -/** - * Gets the status of bit @p bit from bit-vector @p vec. This function returns - * @c 1 if the bit is set, @c 0 otherwise (even in case of an error). - * - * @param vec The bit-vector to read from. - * @param size The size of @p vec in bytes. - * @param bit The bit to get from @p vec. - * - * @return @c 1 if the bit is set, @c 0 otherwise. - */ -inline static int -bits_getb(const uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) - return -1; - - return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0; -} - -#endif /* _COAP_BITS_H_ */ diff --git a/components/coap/libcoap/include/coap/block.h b/components/coap/libcoap/include/coap/block.h deleted file mode 100644 index 9ce00311c..000000000 --- a/components/coap/libcoap/include/coap/block.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * block.h -- block transfer - * - * Copyright (C) 2010-2012,2014-2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_BLOCK_H_ -#define _COAP_BLOCK_H_ - -#include "encode.h" -#include "option.h" -#include "pdu.h" - -/** - * @defgroup block Block Transfer - * @{ - */ - -#ifndef COAP_MAX_BLOCK_SZX -/** - * The largest value for the SZX component in a Block option. Note that - * 1 << (COAP_MAX_BLOCK_SZX + 4) should not exceed COAP_MAX_PDU_SIZE. - */ -#define COAP_MAX_BLOCK_SZX 4 -#endif /* COAP_MAX_BLOCK_SZX */ - -/** - * Structure of Block options. - */ -typedef struct { - unsigned int num; /**< block number */ - unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */ - unsigned int szx:3; /**< block size */ -} coap_block_t; - -/** - * Returns the value of the least significant byte of a Block option @p opt. - * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST - * returns @c NULL. - */ -#define COAP_OPT_BLOCK_LAST(opt) \ - (COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0) - -/** Returns the value of the More-bit of a Block option @p opt. */ -#define COAP_OPT_BLOCK_MORE(opt) \ - (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0) - -/** Returns the value of the SZX-field of a Block option @p opt. */ -#define COAP_OPT_BLOCK_SZX(opt) \ - (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0) - -/** - * Returns the value of field @c num in the given block option @p block_opt. - */ -unsigned int coap_opt_block_num(const coap_opt_t *block_opt); - -/** - * Checks if more than @p num blocks are required to deliver @p data_len - * bytes of data for a block size of 1 << (@p szx + 4). - */ -static inline int -coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) { - return ((num+1) << (szx + 4)) < data_len; -} - -/** Sets the More-bit in @p block_opt */ -static inline void -coap_opt_block_set_m(coap_opt_t *block_opt, int m) { - if (m) - *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08; - else - *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) &= ~0x08; -} - -/** - * Initializes @p block from @p pdu. @p type must be either COAP_OPTION_BLOCK1 - * or COAP_OPTION_BLOCK2. When option @p type was found in @p pdu, @p block is - * initialized with values from this option and the function returns the value - * @c 1. Otherwise, @c 0 is returned. - * - * @param pdu The pdu to search for option @p type. - * @param type The option to search for (must be COAP_OPTION_BLOCK1 or - * COAP_OPTION_BLOCK2). - * @param block The block structure to initilize. - * - * @return @c 1 on success, @c 0 otherwise. - */ -int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block); - -/** - * Writes a block option of type @p type to message @p pdu. If the requested - * block size is too large to fit in @p pdu, it is reduced accordingly. An - * exception is made for the final block when less space is required. The actual - * length of the resource is specified in @p data_length. - * - * This function may change *block to reflect the values written to @p pdu. As - * the function takes into consideration the remaining space @p pdu, no more - * options should be added after coap_write_block_opt() has returned. - * - * @param block The block structure to use. On return, this object is - * updated according to the values that have been written to - * @p pdu. - * @param type COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2. - * @param pdu The message where the block option should be written. - * @param data_length The length of the actual data that will be added the @p - * pdu by calling coap_add_block(). - * - * @return @c 1 on success, or a negative value on error. - */ -int coap_write_block_opt(coap_block_t *block, - unsigned short type, - coap_pdu_t *pdu, - size_t data_length); - -/** - * Adds the @p block_num block of size 1 << (@p block_szx + 4) from source @p - * data to @p pdu. - * - * @param pdu The message to add the block. - * @param len The length of @p data. - * @param data The source data to fill the block with. - * @param block_num The actual block number. - * @param block_szx Encoded size of block @p block_number. - * - * @return @c 1 on success, @c 0 otherwise. - */ -int coap_add_block(coap_pdu_t *pdu, - unsigned int len, - const unsigned char *data, - unsigned int block_num, - unsigned char block_szx); -/**@}*/ - -#endif /* _COAP_BLOCK_H_ */ diff --git a/components/coap/libcoap/include/coap/coap.h.in b/components/coap/libcoap/include/coap/coap.h.in deleted file mode 100644 index 76ebc5eb0..000000000 --- a/components/coap/libcoap/include/coap/coap.h.in +++ /dev/null @@ -1,59 +0,0 @@ -/* - * coap.h -- main header file for CoAP stack of libcoap - * - * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann - * 2015 Carsten Schoenert - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_H_ -#define _COAP_H_ - -#include "libcoap.h" - -/* Define the address where bug reports for libcoap should be sent. */ -#define LIBCOAP_PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ - -/* Define the full name of libcoap. */ -#define LIBCOAP_PACKAGE_NAME @PACKAGE_NAME@ - -/* Define the full name and version of libcoap. */ -#define LIBCOAP_PACKAGE_STRING @PACKAGE_STRING@ - -/* Define the home page for libcoap. */ -#define LIBCOAP_PACKAGE_URL @PACKAGE_URL@ - -/* Define the version of libcoap this file belongs to. */ -#define LIBCOAP_PACKAGE_VERSION @PACKAGE_VERSION@ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "address.h" -#include "async.h" -#include "bits.h" -#include "block.h" -#include "coap_io.h" -#include "coap_time.h" -#include "debug.h" -#include "encode.h" -#include "mem.h" -#include "net.h" -#include "option.h" -#include "pdu.h" -#include "prng.h" -#include "resource.h" -#include "str.h" -#include "subscribe.h" -#include "uri.h" -#include "uthash.h" -#include "utlist.h" - -#ifdef __cplusplus -} -#endif - -#endif /* _COAP_H_ */ diff --git a/components/coap/libcoap/include/coap/coap_io.h b/components/coap/libcoap/include/coap/coap_io.h deleted file mode 100644 index 7a48b319a..000000000 --- a/components/coap/libcoap/include/coap/coap_io.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * coap_io.h -- Default network I/O functions for libcoap - * - * Copyright (C) 2012-2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_IO_H_ -#define _COAP_IO_H_ - -#include -#include - -#include "address.h" - -/** - * Abstract handle that is used to identify a local network interface. - */ -typedef int coap_if_handle_t; - -/** Invalid interface handle */ -#define COAP_IF_INVALID -1 - -struct coap_packet_t; -typedef struct coap_packet_t coap_packet_t; - -struct coap_context_t; - -/** - * Abstraction of virtual endpoint that can be attached to coap_context_t. The - * tuple (handle, addr) must uniquely identify this endpoint. - */ -typedef struct coap_endpoint_t { -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) - union { - int fd; /**< on POSIX systems */ - void *conn; /**< opaque connection (e.g. uip_conn in Contiki) */ - } handle; /**< opaque handle to identify this endpoint */ -#endif /* WITH_POSIX or WITH_CONTIKI */ - -#ifdef WITH_LWIP - struct udp_pcb *pcb; - /**< @FIXME --chrysn - * this was added in a hurry, not sure it confirms to the overall model */ - struct coap_context_t *context; -#endif /* WITH_LWIP */ - - coap_address_t addr; /**< local interface address */ - int ifindex; - int flags; -} coap_endpoint_t; - -#define COAP_ENDPOINT_NOSEC 0x00 -#define COAP_ENDPOINT_DTLS 0x01 - -coap_endpoint_t *coap_new_endpoint(const coap_address_t *addr, int flags); - -void coap_free_endpoint(coap_endpoint_t *ep); - -/** - * Function interface for data transmission. This function returns the number of - * bytes that have been transmitted, or a value less than zero on error. - * - * @param context The calling CoAP context. - * @param local_interface The local interface to send the data. - * @param dst The address of the receiver. - * @param data The data to send. - * @param datalen The actual length of @p data. - * - * @return The number of bytes written on success, or a value - * less than zero on error. - */ -ssize_t coap_network_send(struct coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char *data, size_t datalen); - -/** - * Function interface for reading data. This function returns the number of - * bytes that have been read, or a value less than zero on error. In case of an - * error, @p *packet is set to NULL. - * - * @param ep The endpoint that is used for reading data from the network. - * @param packet A result parameter where a pointer to the received packet - * structure is stored. The caller must call coap_free_packet to - * release the storage used by this packet. - * - * @return The number of bytes received on success, or a value less than - * zero on error. - */ -ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet); - -#ifndef coap_mcast_interface -# define coap_mcast_interface(Local) 0 -#endif - -/** - * Releases the storage allocated for @p packet. - */ -void coap_free_packet(coap_packet_t *packet); - -/** - * Populate the coap_endpoint_t *target from the incoming packet's destination - * data. - * - * This is usually used to copy a packet's data into a node's local_if member. - */ -void coap_packet_populate_endpoint(coap_packet_t *packet, - coap_endpoint_t *target); - -/** - * Given an incoming packet, copy its source address into an address struct. - */ -void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target); - -/** - * Given a packet, set msg and msg_len to an address and length of the packet's - * data in memory. - * */ -void coap_packet_get_memmapped(coap_packet_t *packet, - unsigned char **address, - size_t *length); - -#ifdef WITH_LWIP -/** - * Get the pbuf of a packet. The caller takes over responsibility for freeing - * the pbuf. - */ -struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet); -#endif - -#ifdef WITH_CONTIKI -/* - * This is only included in coap_io.h instead of .c in order to be available for - * sizeof in mem.c. - */ -struct coap_packet_t { - coap_if_handle_t hnd; /**< the interface handle */ - coap_address_t src; /**< the packet's source address */ - coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; - int ifindex; - void *session; /**< opaque session data */ - size_t length; /**< length of payload */ - unsigned char payload[]; /**< payload */ -}; -#endif - -#ifdef WITH_LWIP -/* - * This is only included in coap_io.h instead of .c in order to be available for - * sizeof in lwippools.h. - * Simple carry-over of the incoming pbuf that is later turned into a node. - * - * Source address data is currently side-banded via ip_current_dest_addr & co - * as the packets have limited lifetime anyway. - */ -struct coap_packet_t { - struct pbuf *pbuf; - const coap_endpoint_t *local_interface; - uint16_t srcport; -}; -#endif - -#endif /* _COAP_IO_H_ */ diff --git a/components/coap/libcoap/include/coap/coap_time.h b/components/coap/libcoap/include/coap/coap_time.h deleted file mode 100644 index 9357e5ff7..000000000 --- a/components/coap/libcoap/include/coap/coap_time.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * coap_time.h -- Clock Handling - * - * Copyright (C) 2010-2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file coap_time.h - * @brief Clock Handling - */ - -#ifndef _COAP_TIME_H_ -#define _COAP_TIME_H_ - -/** - * @defgroup clock Clock Handling - * Default implementation of internal clock. - * @{ - */ - -#ifdef WITH_LWIP - -#include -#include - -/* lwIP provides ms in sys_now */ -#define COAP_TICKS_PER_SECOND 1000 - -typedef uint32_t coap_tick_t; -typedef uint32_t coap_time_t; -typedef int32_t coap_tick_diff_t; - -static inline void coap_ticks_impl(coap_tick_t *t) { - *t = sys_now(); -} - -static inline void coap_clock_init_impl(void) { -} - -#define coap_clock_init coap_clock_init_impl -#define coap_ticks coap_ticks_impl - -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { - return t / COAP_TICKS_PER_SECOND; -} -#endif - -#ifdef WITH_CONTIKI -#include "clock.h" - -typedef clock_time_t coap_tick_t; -typedef clock_time_t coap_time_t; - -/** - * This data type is used to represent the difference between two clock_tick_t - * values. This data type must have the same size in memory as coap_tick_t to - * allow wrapping. - */ -typedef int coap_tick_diff_t; - -#define COAP_TICKS_PER_SECOND CLOCK_SECOND - -static inline void coap_clock_init(void) { - clock_init(); -} - -static inline void coap_ticks(coap_tick_t *t) { - *t = clock_time(); -} - -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { - return t / COAP_TICKS_PER_SECOND; -} -#endif /* WITH_CONTIKI */ - -#ifdef WITH_POSIX -/** - * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND - * resolution. - */ -typedef unsigned long coap_tick_t; - -/** - * CoAP time in seconds since epoch. - */ -typedef time_t coap_time_t; - -/** - * This data type is used to represent the difference between two clock_tick_t - * values. This data type must have the same size in memory as coap_tick_t to - * allow wrapping. - */ -typedef long coap_tick_diff_t; - -/** Use ms resolution on POSIX systems */ -#define COAP_TICKS_PER_SECOND 1000 - -/** - * Initializes the internal clock. - */ -void coap_clock_init(void); - -/** - * Sets @p t to the internal time with COAP_TICKS_PER_SECOND resolution. - */ -void coap_ticks(coap_tick_t *t); - -/** - * Helper function that converts coap ticks to wallclock time. On POSIX, this - * function returns the number of seconds since the epoch. On other systems, it - * may be the calculated number of seconds since last reboot or so. - * - * @param t Internal system ticks. - * - * @return The number of seconds that has passed since a specific reference - * point (seconds since epoch on POSIX). - */ -coap_time_t coap_ticks_to_rt(coap_tick_t t); -#endif /* WITH_POSIX */ - -/** - * Returns @c 1 if and only if @p a is less than @p b where less is defined on a - * signed data type. - */ -static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { - return ((coap_tick_diff_t)(a - b)) < 0; -} - -/** - * Returns @c 1 if and only if @p a is less than or equal @p b where less is - * defined on a signed data type. - */ -static inline int coap_time_le(coap_tick_t a, coap_tick_t b) { - return a == b || coap_time_lt(a,b); -} - -/** @} */ - -#endif /* _COAP_TIME_H_ */ diff --git a/components/coap/libcoap/include/coap/debug.h b/components/coap/libcoap/include/coap/debug.h deleted file mode 100644 index e7c86aff5..000000000 --- a/components/coap/libcoap/include/coap/debug.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * debug.h -- debug utilities - * - * Copyright (C) 2010-2011,2014 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_DEBUG_H_ -#define _COAP_DEBUG_H_ - -#ifndef COAP_DEBUG_FD -#define COAP_DEBUG_FD stdout -#endif - -#ifndef COAP_ERR_FD -#define COAP_ERR_FD stderr -#endif - -#ifdef HAVE_SYSLOG_H -#include -typedef short coap_log_t; -#else -/** Pre-defined log levels akin to what is used in \b syslog. */ -typedef enum { - LOG_EMERG=0, - LOG_ALERT, - LOG_CRIT, - LOG_ERR, - LOG_WARNING, - LOG_NOTICE, - LOG_INFO, - LOG_DEBUG -} coap_log_t; -#endif - -/** Returns the current log level. */ -coap_log_t coap_get_log_level(void); - -/** Sets the log level to the specified value. */ -void coap_set_log_level(coap_log_t level); - -/** Returns a zero-terminated string with the name of this library. */ -const char *coap_package_name(void); - -/** Returns a zero-terminated string with the library version. */ -const char *coap_package_version(void); - -/** - * Writes the given text to @c COAP_ERR_FD (for @p level <= @c LOG_CRIT) or @c - * COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The text is output only when - * @p level is below or equal to the log level that set by coap_set_log_level(). - */ -void coap_log_impl(coap_log_t level, const char *format, ...); - -#ifndef coap_log -#define coap_log(...) coap_log_impl(__VA_ARGS__) -#endif - -#ifndef NDEBUG - -/* A set of convenience macros for common log levels. */ -#define info(...) coap_log(LOG_INFO, __VA_ARGS__) -#define warn(...) coap_log(LOG_WARNING, __VA_ARGS__) -#define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__) - -#include "pdu.h" -void coap_show_pdu(const coap_pdu_t *); - -struct coap_address_t; -size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t); - -#else - -#define debug(...) -#define info(...) -#define warn(...) - -#define coap_show_pdu(x) -#define coap_print_addr(...) - -#endif /* NDEBUG */ - -#endif /* _COAP_DEBUG_H_ */ diff --git a/components/coap/libcoap/include/coap/encode.h b/components/coap/libcoap/include/coap/encode.h deleted file mode 100644 index a5d290c4e..000000000 --- a/components/coap/libcoap/include/coap/encode.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * encode.h -- encoding and decoding of CoAP data types - * - * Copyright (C) 2010-2012 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_ENCODE_H_ -#define _COAP_ENCODE_H_ - -#if (BSD >= 199103) || defined(WITH_CONTIKI) -# include -#else -# include -#endif - -#define Nn 8 /* duplicate definition of N if built on sky motes */ -#define ENCODE_HEADER_SIZE 4 -#define HIBIT (1 << (Nn - 1)) -#define EMASK ((1 << ENCODE_HEADER_SIZE) - 1) -#define MMASK ((1 << Nn) - 1 - EMASK) -#define MAX_VALUE ( (1 << Nn) - (1 << ENCODE_HEADER_SIZE) ) * (1 << ((1 << ENCODE_HEADER_SIZE) - 1)) - -#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) - -#ifndef HAVE_FLS -/* include this only if fls() is not available */ -extern int coap_fls(unsigned int i); -#else -#define coap_fls(i) fls(i) -#endif - -/* ls and s must be integer variables */ -#define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) -#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) - -/** - * Decodes multiple-length byte sequences. buf points to an input byte sequence - * of length len. Returns the decoded value. - */ -unsigned int coap_decode_var_bytes(unsigned char *buf,unsigned int len); - -/** - * Encodes multiple-length byte sequences. buf points to an output buffer of - * sufficient length to store the encoded bytes. val is the value to encode. - * Returns the number of bytes used to encode val or 0 on error. - */ -unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val); - -#endif /* _COAP_ENCODE_H_ */ diff --git a/components/coap/libcoap/include/coap/hashkey.h b/components/coap/libcoap/include/coap/hashkey.h deleted file mode 100644 index 5cff67d2d..000000000 --- a/components/coap/libcoap/include/coap/hashkey.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * hashkey.h -- definition of hash key type and helper functions - * - * Copyright (C) 2010-2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file hashkey.h - * @brief definition of hash key type and helper functions - */ - -#ifndef _COAP_HASHKEY_H_ -#define _COAP_HASHKEY_H_ - -#include "str.h" - -typedef unsigned char coap_key_t[4]; - -#ifndef coap_hash -/** - * Calculates a fast hash over the given string @p s of length @p len and stores - * the result into @p h. Depending on the exact implementation, this function - * cannot be used as one-way function to check message integrity or simlar. - * - * @param s The string used for hash calculation. - * @param len The length of @p s. - * @param h The result buffer to store the calculated hash key. - */ -void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h); - -#define coap_hash(String,Length,Result) \ - coap_hash_impl((String),(Length),(Result)) - -/* This is used to control the pre-set hash-keys for resources. */ -#define __COAP_DEFAULT_HASH -#else -#undef __COAP_DEFAULT_HASH -#endif /* coap_hash */ - -/** - * Calls coap_hash() with given @c str object as parameter. - * - * @param Str Must contain a pointer to a coap string object. - * @param H A coap_key_t object to store the result. - * - * @hideinitializer - */ -#define coap_str_hash(Str,H) { \ - assert(Str); \ - memset((H), 0, sizeof(coap_key_t)); \ - coap_hash((Str)->s, (Str)->length, (H)); \ - } - -#endif /* _COAP_HASHKEY_H_ */ diff --git a/components/coap/libcoap/include/coap/libcoap.h b/components/coap/libcoap/include/coap/libcoap.h deleted file mode 100644 index 214b9e235..000000000 --- a/components/coap/libcoap/include/coap/libcoap.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * libcoap.h -- platform specific header file for CoAP stack - * - * Copyright (C) 2015 Carsten Schoenert - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _LIBCOAP_H_ -#define _LIBCOAP_H_ - -/* The non posix embedded platforms like Contiki, TinyOS, RIOT, ... doesn't have - * a POSIX compatible header structure so we have to slightly do some platform - * related things. Currently there is only Contiki available so we check for a - * CONTIKI environment and do *not* include the POSIX related network stuff. If - * there are other platforms in future there need to be analogous environments. - * - * The CONTIKI variable is within the Contiki build environment! */ - -#if !defined (CONTIKI) -#include -#include -#endif /* CONTIKI */ - -#endif /* _LIBCOAP_H_ */ diff --git a/components/coap/libcoap/include/coap/lwippools.h b/components/coap/libcoap/include/coap/lwippools.h deleted file mode 100644 index 0bfb3f527..000000000 --- a/components/coap/libcoap/include/coap/lwippools.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** Memory pool definitions for the libcoap when used with lwIP (which has its - * own mechanism for quickly allocating chunks of data with known sizes). Has - * to be findable by lwIP (ie. an #include must either directly - * include this or include something more generic which includes this), and - * MEMP_USE_CUSTOM_POOLS has to be set in lwipopts.h. */ - -#include "coap_config.h" -#include -#include -#include - -#ifndef MEMP_NUM_COAPCONTEXT -#define MEMP_NUM_COAPCONTEXT 1 -#endif - -#ifndef MEMP_NUM_COAPENDPOINT -#define MEMP_NUM_COAPENDPOINT 1 -#endif - -/* 1 is sufficient as this is very short-lived */ -#ifndef MEMP_NUM_COAPPACKET -#define MEMP_NUM_COAPPACKET 1 -#endif - -#ifndef MEMP_NUM_COAPNODE -#define MEMP_NUM_COAPNODE 4 -#endif - -#ifndef MEMP_NUM_COAPPDU -#define MEMP_NUM_COAPPDU MEMP_NUM_COAPNODE -#endif - -#ifndef MEMP_NUM_COAP_SUBSCRIPTION -#define MEMP_NUM_COAP_SUBSCRIPTION 4 -#endif - -#ifndef MEMP_NUM_COAPRESOURCE -#define MEMP_NUM_COAPRESOURCE 10 -#endif - -#ifndef MEMP_NUM_COAPRESOURCEATTR -#define MEMP_NUM_COAPRESOURCEATTR 20 -#endif - -LWIP_MEMPOOL(COAP_CONTEXT, MEMP_NUM_COAPCONTEXT, sizeof(coap_context_t), "COAP_CONTEXT") -LWIP_MEMPOOL(COAP_ENDPOINT, MEMP_NUM_COAPENDPOINT, sizeof(coap_endpoint_t), "COAP_ENDPOINT") -LWIP_MEMPOOL(COAP_PACKET, MEMP_NUM_COAPPACKET, sizeof(coap_packet_t), "COAP_PACKET") -LWIP_MEMPOOL(COAP_NODE, MEMP_NUM_COAPNODE, sizeof(coap_queue_t), "COAP_NODE") -LWIP_MEMPOOL(COAP_PDU, MEMP_NUM_COAPPDU, sizeof(coap_pdu_t), "COAP_PDU") -LWIP_MEMPOOL(COAP_subscription, MEMP_NUM_COAP_SUBSCRIPTION, sizeof(coap_subscription_t), "COAP_subscription") -LWIP_MEMPOOL(COAP_RESOURCE, MEMP_NUM_COAPRESOURCE, sizeof(coap_resource_t), "COAP_RESOURCE") -LWIP_MEMPOOL(COAP_RESOURCEATTR, MEMP_NUM_COAPRESOURCEATTR, sizeof(coap_attr_t), "COAP_RESOURCEATTR") diff --git a/components/coap/libcoap/include/coap/mem.h b/components/coap/libcoap/include/coap/mem.h deleted file mode 100644 index fd3c69aaf..000000000 --- a/components/coap/libcoap/include/coap/mem.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * mem.h -- CoAP memory handling - * - * Copyright (C) 2010-2011,2014-2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_MEM_H_ -#define _COAP_MEM_H_ - -#include - -#ifndef WITH_LWIP -/** - * Initializes libcoap's memory management. - * This function must be called once before coap_malloc() can be used on - * constrained devices. - */ -void coap_memory_init(void); -#endif /* WITH_LWIP */ - -/** - * Type specifiers for coap_malloc_type(). Memory objects can be typed to - * facilitate arrays of type objects to be used instead of dynamic memory - * management on constrained devices. - */ -typedef enum { - COAP_STRING, - COAP_ATTRIBUTE_NAME, - COAP_ATTRIBUTE_VALUE, - COAP_PACKET, - COAP_NODE, - COAP_CONTEXT, - COAP_ENDPOINT, - COAP_PDU, - COAP_PDU_BUF, - COAP_RESOURCE, - COAP_RESOURCEATTR -} coap_memory_tag_t; - -#ifndef WITH_LWIP - -/** - * Allocates a chunk of @p size bytes and returns a pointer to the newly - * allocated memory. The @p type is used to select the appropriate storage - * container on constrained devices. The storage allocated by coap_malloc_type() - * must be released with coap_free_type(). - * - * @param type The type of object to be stored. - * @param size The number of bytes requested. - * @return A pointer to the allocated storage or @c NULL on error. - */ -void *coap_malloc_type(coap_memory_tag_t type, size_t size); - -/** - * Releases the memory that was allocated by coap_malloc_type(). The type tag @p - * type must be the same that was used for allocating the object pointed to by - * @p . - * - * @param type The type of the object to release. - * @param p A pointer to memory that was allocated by coap_malloc_type(). - */ -void coap_free_type(coap_memory_tag_t type, void *p); - -/** - * Wrapper function to coap_malloc_type() for backwards compatibility. - */ -static inline void *coap_malloc(size_t size) { - return coap_malloc_type(COAP_STRING, size); -} - -/** - * Wrapper function to coap_free_type() for backwards compatibility. - */ -static inline void coap_free(void *object) { - coap_free_type(COAP_STRING, object); -} - -#endif /* not WITH_LWIP */ - -#ifdef WITH_LWIP - -#include - -/* no initialization needed with lwip (or, more precisely: lwip must be - * completely initialized anyway by the time coap gets active) */ -static inline void coap_memory_init(void) {} - -/* It would be nice to check that size equals the size given at the memp - * declaration, but i currently don't see a standard way to check that without - * sourcing the custom memp pools and becoming dependent of its syntax - */ -#define coap_malloc_type(type, size) memp_malloc(MEMP_ ## type) -#define coap_free_type(type, p) memp_free(MEMP_ ## type, p) - -/* Those are just here to make uri.c happy where string allocation has not been - * made conditional. - */ -static inline void *coap_malloc(size_t size) { - LWIP_ASSERT("coap_malloc must not be used in lwIP", 0); -} - -static inline void coap_free(void *pointer) { - LWIP_ASSERT("coap_free must not be used in lwIP", 0); -} - -#endif /* WITH_LWIP */ - -#endif /* _COAP_MEM_H_ */ diff --git a/components/coap/libcoap/include/coap/net.h b/components/coap/libcoap/include/coap/net.h deleted file mode 100644 index 014b4903a..000000000 --- a/components/coap/libcoap/include/coap/net.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * net.h -- CoAP network interface - * - * Copyright (C) 2010-2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_NET_H_ -#define _COAP_NET_H_ - -#include -#include -#include -#include -#include - -#ifdef WITH_LWIP -#include -#endif - -#include "coap_io.h" -#include "coap_time.h" -#include "option.h" -#include "pdu.h" -#include "prng.h" - -struct coap_queue_t; - -typedef struct coap_queue_t { - struct coap_queue_t *next; - coap_tick_t t; /**< when to send PDU for the next time */ - unsigned char retransmit_cnt; /**< retransmission counter, will be removed - * when zero */ - unsigned int timeout; /**< the randomized timeout value */ - coap_endpoint_t local_if; /**< the local address interface */ - coap_address_t remote; /**< remote address */ - coap_tid_t id; /**< unique transaction id */ - coap_pdu_t *pdu; /**< the CoAP PDU to send */ -} coap_queue_t; - -/** Adds node to given queue, ordered by node->t. */ -int coap_insert_node(coap_queue_t **queue, coap_queue_t *node); - -/** Destroys specified node. */ -int coap_delete_node(coap_queue_t *node); - -/** Removes all items from given queue and frees the allocated storage. */ -void coap_delete_all(coap_queue_t *queue); - -/** Creates a new node suitable for adding to the CoAP sendqueue. */ -coap_queue_t *coap_new_node(void); - -struct coap_resource_t; -struct coap_context_t; -#ifndef WITHOUT_ASYNC -struct coap_async_state_t; -#endif - -/** Message handler that is used as call-back in coap_context_t */ -typedef void (*coap_response_handler_t)(struct coap_context_t *, - const coap_endpoint_t *local_interface, - const coap_address_t *remote, - coap_pdu_t *sent, - coap_pdu_t *received, - const coap_tid_t id); - -#define COAP_MID_CACHE_SIZE 3 -typedef struct { - unsigned char flags[COAP_MID_CACHE_SIZE]; - coap_key_t item[COAP_MID_CACHE_SIZE]; -} coap_mid_cache_t; - -/** The CoAP stack's global state is stored in a coap_context_t object */ -typedef struct coap_context_t { - coap_opt_filter_t known_options; - struct coap_resource_t *resources; /**< hash table or list of known resources */ - -#ifndef WITHOUT_ASYNC - /** - * list of asynchronous transactions */ - struct coap_async_state_t *async_state; -#endif /* WITHOUT_ASYNC */ - - /** - * The time stamp in the first element of the sendqeue is relative - * to sendqueue_basetime. */ - coap_tick_t sendqueue_basetime; - coap_queue_t *sendqueue; - coap_endpoint_t *endpoint; /**< the endpoint used for listening */ - -#ifdef WITH_POSIX - int sockfd; /**< send/receive socket */ -#endif /* WITH_POSIX */ - -#ifdef WITH_CONTIKI - struct uip_udp_conn *conn; /**< uIP connection object */ - struct etimer retransmit_timer; /**< fires when the next packet must be sent */ - struct etimer notify_timer; /**< used to check resources periodically */ -#endif /* WITH_CONTIKI */ - -#ifdef WITH_LWIP - uint8_t timer_configured; /**< Set to 1 when a retransmission is - * scheduled using lwIP timers for this - * context, otherwise 0. */ -#endif /* WITH_LWIP */ - - /** - * The last message id that was used is stored in this field. The initial - * value is set by coap_new_context() and is usually a random value. A new - * message id can be created with coap_new_message_id(). - */ - unsigned short message_id; - - /** - * The next value to be used for Observe. This field is global for all - * resources and will be updated when notifications are created. - */ - unsigned int observe; - - coap_response_handler_t response_handler; - - ssize_t (*network_send)(struct coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char *data, size_t datalen); - - ssize_t (*network_read)(coap_endpoint_t *ep, coap_packet_t **packet); - -} coap_context_t; - -/** - * Registers a new message handler that is called whenever a response was - * received that matches an ongoing transaction. - * - * @param context The context to register the handler for. - * @param handler The response handler to register. - */ -static inline void -coap_register_response_handler(coap_context_t *context, - coap_response_handler_t handler) { - context->response_handler = handler; -} - -/** - * Registers the option type @p type with the given context object @p ctx. - * - * @param ctx The context to use. - * @param type The option type to register. - */ -inline static void -coap_register_option(coap_context_t *ctx, unsigned char type) { - coap_option_setb(ctx->known_options, type); -} - -/** - * Set sendqueue_basetime in the given context object @p ctx to @p now. This - * function returns the number of elements in the queue head that have timed - * out. - */ -unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now); - -/** - * Returns the next pdu to send without removing from sendqeue. - */ -coap_queue_t *coap_peek_next( coap_context_t *context ); - -/** - * Returns the next pdu to send and removes it from the sendqeue. - */ -coap_queue_t *coap_pop_next( coap_context_t *context ); - -/** - * Creates a new coap_context_t object that will hold the CoAP stack status. - */ -coap_context_t *coap_new_context(const coap_address_t *listen_addr); - -/** - * Returns a new message id and updates @p context->message_id accordingly. The - * message id is returned in network byte order to make it easier to read in - * tracing tools. - * - * @param context The current coap_context_t object. - * - * @return Incremented message id in network byte order. - */ -static inline unsigned short -coap_new_message_id(coap_context_t *context) { - context->message_id++; -#ifndef WITH_CONTIKI - return htons(context->message_id); -#else /* WITH_CONTIKI */ - return uip_htons(context->message_id); -#endif -} - -/** - * CoAP stack context must be released with coap_free_context(). This function - * clears all entries from the receive queue and send queue and deletes the - * resources that have been registered with @p context, and frees the attached - * endpoints. - */ -void coap_free_context(coap_context_t *context); - - -/** - * Sends a confirmed CoAP message to given destination. The memory that is - * allocated by pdu will not be released by coap_send_confirmed(). The caller - * must release the memory. - * - * @param context The CoAP context to use. - * @param local_interface The local network interface where the outbound - * packet is sent. - * @param dst The address to send to. - * @param pdu The CoAP PDU to send. - * - * @return The message id of the sent message or @c - * COAP_INVALID_TID on error. - */ -coap_tid_t coap_send_confirmed(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu); - -/** - * Creates a new ACK PDU with specified error @p code. The options specified by - * the filter expression @p opts will be copied from the original request - * contained in @p request. Unless @c SHORT_ERROR_RESPONSE was defined at build - * time, the textual reason phrase for @p code will be added as payload, with - * Content-Type @c 0. - * This function returns a pointer to the new response message, or @c NULL on - * error. The storage allocated for the new message must be relased with - * coap_free(). - * - * @param request Specification of the received (confirmable) request. - * @param code The error code to set. - * @param opts An option filter that specifies which options to copy from - * the original request in @p node. - * - * @return A pointer to the new message or @c NULL on error. - */ -coap_pdu_t *coap_new_error_response(coap_pdu_t *request, - unsigned char code, - coap_opt_filter_t opts); - -/** - * Sends a non-confirmed CoAP message to given destination. The memory that is - * allocated by pdu will not be released by coap_send(). - * The caller must release the memory. - * - * @param context The CoAP context to use. - * @param local_interface The local network interface where the outbound packet - * is sent. - * @param dst The address to send to. - * @param pdu The CoAP PDU to send. - * - * @return The message id of the sent message or @c - * COAP_INVALID_TID on error. - */ -coap_tid_t coap_send(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu); - -/** - * Sends an error response with code @p code for request @p request to @p dst. - * @p opts will be passed to coap_new_error_response() to copy marked options - * from the request. This function returns the transaction id if the message was - * sent, or @c COAP_INVALID_TID otherwise. - * - * @param context The context to use. - * @param request The original request to respond to. - * @param local_interface The local network interface where the outbound packet - * is sent. - * @param dst The remote peer that sent the request. - * @param code The response code. - * @param opts A filter that specifies the options to copy from the - * @p request. - * - * @return The transaction id if the message was sent, or @c - * COAP_INVALID_TID otherwise. - */ -coap_tid_t coap_send_error(coap_context_t *context, - coap_pdu_t *request, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char code, - coap_opt_filter_t opts); - -/** - * Helper funktion to create and send a message with @p type (usually ACK or - * RST). This function returns @c COAP_INVALID_TID when the message was not - * sent, a valid transaction id otherwise. - * - * @param context The CoAP context. - * @param local_interface The local network interface where the outbound packet - * is sent. - * @param dst Where to send the context. - * @param request The request that should be responded to. - * @param type Which type to set. - * @return transaction id on success or @c COAP_INVALID_TID - * otherwise. - */ -coap_tid_t -coap_send_message_type(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *request, - unsigned char type); - -/** - * Sends an ACK message with code @c 0 for the specified @p request to @p dst. - * This function returns the corresponding transaction id if the message was - * sent or @c COAP_INVALID_TID on error. - * - * @param context The context to use. - * @param local_interface The local network interface where the outbound packet - * is sent. - * @param dst The destination address. - * @param request The request to be acknowledged. - * - * @return The transaction id if ACK was sent or @c - * COAP_INVALID_TID on error. - */ -coap_tid_t coap_send_ack(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *request); - -/** - * Sends an RST message with code @c 0 for the specified @p request to @p dst. - * This function returns the corresponding transaction id if the message was - * sent or @c COAP_INVALID_TID on error. - * - * @param context The context to use. - * @param local_interface The local network interface where the outbound packet - * is sent. - * @param dst The destination address. - * @param request The request to be reset. - * - * @return The transaction id if RST was sent or @c - * COAP_INVALID_TID on error. - */ -static inline coap_tid_t -coap_send_rst(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *request) { - return coap_send_message_type(context, - local_interface, - dst, request, - COAP_MESSAGE_RST); -} - -/** - * Handles retransmissions of confirmable messages - */ -coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node); - -/** - * Reads data from the network and tries to parse as CoAP PDU. On success, 0 is - * returned and a new node with the parsed PDU is added to the receive queue in - * the specified context object. - */ -int coap_read(coap_context_t *context); - -/** - * Parses and interprets a CoAP message with context @p ctx. This function - * returns @c 0 if the message was handled, or a value less than zero on - * error. - * - * @param ctx The current CoAP context. - * @param packet The received packet. - * - * @return @c 0 if message was handled successfully, or less than zero on - * error. - */ -int coap_handle_message(coap_context_t *ctx, - coap_packet_t *packet); - -/** - * Calculates a unique transaction id from given arguments @p peer and @p pdu. - * The id is returned in @p id. - * - * @param peer The remote party who sent @p pdu. - * @param pdu The message that initiated the transaction. - * @param id Set to the new id. - */ -void coap_transaction_id(const coap_address_t *peer, - const coap_pdu_t *pdu, - coap_tid_t *id); - -/** - * This function removes the element with given @p id from the list given list. - * If @p id was found, @p node is updated to point to the removed element. Note - * that the storage allocated by @p node is @b not released. The caller must do - * this manually using coap_delete_node(). This function returns @c 1 if the - * element with id @p id was found, @c 0 otherwise. For a return value of @c 0, - * the contents of @p node is undefined. - * - * @param queue The queue to search for @p id. - * @param id The node id to look for. - * @param node If found, @p node is updated to point to the removed node. You - * must release the storage pointed to by @p node manually. - * - * @return @c 1 if @p id was found, @c 0 otherwise. - */ -int coap_remove_from_queue(coap_queue_t **queue, - coap_tid_t id, - coap_queue_t **node); - -/** - * Removes the transaction identified by @p id from given @p queue. This is a - * convenience function for coap_remove_from_queue() with automatic deletion of - * the removed node. - * - * @param queue The queue to search for @p id. - * @param id The transaction id. - * - * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise. - */ -inline static int -coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) { - coap_queue_t *node; - if (!coap_remove_from_queue(queue, id, &node)) - return 0; - - coap_delete_node(node); - return 1; -} - -/** - * Retrieves transaction from the queue. - * - * @param queue The transaction queue to be searched. - * @param id Unique key of the transaction to find. - * - * @return A pointer to the transaction object or NULL if not found. - */ -coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id); - -/** - * Cancels all outstanding messages for peer @p dst that have the specified - * token. - * - * @param context The context in use. - * @param dst Destination address of the messages to remove. - * @param token Message token. - * @param token_length Actual length of @p token. - */ -void coap_cancel_all_messages(coap_context_t *context, - const coap_address_t *dst, - const unsigned char *token, - size_t token_length); - -/** - * Dispatches the PDUs from the receive queue in given context. - */ -void coap_dispatch(coap_context_t *context, coap_queue_t *rcvd); - -/** - * Returns 1 if there are no messages to send or to dispatch in the context's - * queues. */ -int coap_can_exit(coap_context_t *context); - -/** - * Returns the current value of an internal tick counter. The counter counts \c - * COAP_TICKS_PER_SECOND ticks every second. - */ -void coap_ticks(coap_tick_t *); - -/** - * Verifies that @p pdu contains no unknown critical options. Options must be - * registered at @p ctx, using the function coap_register_option(). A basic set - * of options is registered automatically by coap_new_context(). This function - * returns @c 1 if @p pdu is ok, @c 0 otherwise. The given filter object @p - * unknown will be updated with the unknown options. As only @c COAP_MAX_OPT - * options can be signalled this way, remaining options must be examined - * manually. - * - * @code - coap_opt_filter_t f = COAP_OPT_NONE; - coap_opt_iterator_t opt_iter; - - if (coap_option_check_critical(ctx, pdu, f) == 0) { - coap_option_iterator_init(pdu, &opt_iter, f); - - while (coap_option_next(&opt_iter)) { - if (opt_iter.type & 0x01) { - ... handle unknown critical option in opt_iter ... - } - } - } - * @endcode - * - * @param ctx The context where all known options are registered. - * @param pdu The PDU to check. - * @param unknown The output filter that will be updated to indicate the - * unknown critical options found in @p pdu. - * - * @return @c 1 if everything was ok, @c 0 otherwise. - */ -int coap_option_check_critical(coap_context_t *ctx, - coap_pdu_t *pdu, - coap_opt_filter_t unknown); - -/** - * Creates a new response for given @p request with the contents of @c - * .well-known/core. The result is NULL on error or a newly allocated PDU that - * must be released by coap_delete_pdu(). - * - * @param context The current coap context to use. - * @param request The request for @c .well-known/core . - * - * @return A new 2.05 response for @c .well-known/core or NULL on error. - */ -coap_pdu_t *coap_wellknown_response(coap_context_t *context, - coap_pdu_t *request); - -#endif /* _COAP_NET_H_ */ diff --git a/components/coap/libcoap/include/coap/option.h b/components/coap/libcoap/include/coap/option.h deleted file mode 100644 index ace2b81c7..000000000 --- a/components/coap/libcoap/include/coap/option.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * option.h -- helpers for handling options in CoAP PDUs - * - * Copyright (C) 2010-2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file option.h - * @brief Helpers for handling options in CoAP PDUs - */ - -#ifndef _COAP_OPTION_H_ -#define _COAP_OPTION_H_ - -#include "bits.h" -#include "pdu.h" - -/** - * Use byte-oriented access methods here because sliding a complex struct - * coap_opt_t over the data buffer may cause bus error on certain platforms. - */ -typedef unsigned char coap_opt_t; -#define PCHAR(p) ((coap_opt_t *)(p)) - -/** Representation of CoAP options. */ -typedef struct { - unsigned short delta; - size_t length; - unsigned char *value; -} coap_option_t; - -/** - * Parses the option pointed to by @p opt into @p result. This function returns - * the number of bytes that have been parsed, or @c 0 on error. An error is - * signaled when illegal delta or length values are encountered or when option - * parsing would result in reading past the option (i.e. beyond opt + length). - * - * @param opt The beginning of the option to parse. - * @param length The maximum length of @p opt. - * @param result A pointer to the coap_option_t structure that is filled with - * actual values iff coap_opt_parse() > 0. - * @return The number of bytes parsed or @c 0 on error. - */ -size_t coap_opt_parse(const coap_opt_t *opt, - size_t length, - coap_option_t *result); - -/** - * Returns the size of the given option, taking into account a possible option - * jump. - * - * @param opt An option jump or the beginning of the option. - * @return The number of bytes between @p opt and the end of the option - * starting at @p opt. In case of an error, this function returns - * @c 0 as options need at least one byte storage space. - */ -size_t coap_opt_size(const coap_opt_t *opt); - -/** @deprecated { Use coap_opt_size() instead. } */ -#define COAP_OPT_SIZE(opt) coap_opt_size(opt) - -/** - * Calculates the beginning of the PDU's option section. - * - * @param pdu The PDU containing the options. - * @return A pointer to the first option if available, or @c NULL otherwise. - */ -coap_opt_t *options_start(coap_pdu_t *pdu); - -/** - * Interprets @p opt as pointer to a CoAP option and advances to - * the next byte past this option. - * @hideinitializer - */ -#define options_next(opt) \ - ((coap_opt_t *)((unsigned char *)(opt) + COAP_OPT_SIZE(opt))) - -/** - * @defgroup opt_filter Option Filters - * @{ - */ - -/** - * The number of option types below 256 that can be stored in an - * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be - * at most 16. Each coap_option_filter_t object reserves - * ((COAP_OPT_FILTER_SHORT + 1) / 2) * 2 bytes for short options. - */ -#define COAP_OPT_FILTER_SHORT 6 - -/** - * The number of option types above 255 that can be stored in an - * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be - * at most 16. Each coap_option_filter_t object reserves - * COAP_OPT_FILTER_LONG * 2 bytes for short options. - */ -#define COAP_OPT_FILTER_LONG 2 - -/* Ensure that COAP_OPT_FILTER_SHORT and COAP_OPT_FILTER_LONG are set - * correctly. */ -#if (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) -#error COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be less or equal 16 -#endif /* (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) */ - -/** The number of elements in coap_opt_filter_t. */ -#define COAP_OPT_FILTER_SIZE \ - (((COAP_OPT_FILTER_SHORT + 1) >> 1) + COAP_OPT_FILTER_LONG) +1 - -/** - * Fixed-size vector we use for option filtering. It is large enough - * to hold COAP_OPT_FILTER_SHORT entries with an option number between - * 0 and 255, and COAP_OPT_FILTER_LONG entries with an option number - * between 256 and 65535. Its internal structure is - * - * @code -struct { - uint16_t mask; - uint16_t long_opts[COAP_OPT_FILTER_LONG]; - uint8_t short_opts[COAP_OPT_FILTER_SHORT]; -} - * @endcode - * - * The first element contains a bit vector that indicates which fields - * in the remaining array are used. The first COAP_OPT_FILTER_LONG - * bits correspond to the long option types that are stored in the - * elements from index 1 to COAP_OPT_FILTER_LONG. The next - * COAP_OPT_FILTER_SHORT bits correspond to the short option types - * that are stored in the elements from index COAP_OPT_FILTER_LONG + 1 - * to COAP_OPT_FILTER_LONG + COAP_OPT_FILTER_SHORT. The latter - * elements are treated as bytes. - */ -typedef uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE]; - -/** Pre-defined filter that includes all options. */ -#define COAP_OPT_ALL NULL - -/** - * Clears filter @p f. - * - * @param f The filter to clear. - */ -static inline void -coap_option_filter_clear(coap_opt_filter_t f) { - memset(f, 0, sizeof(coap_opt_filter_t)); -} - -/** - * Sets the corresponding entry for @p type in @p filter. This - * function returns @c 1 if bit was set or @c 0 on error (i.e. when - * the given type does not fit in the filter). - * - * @param filter The filter object to change. - * @param type The type for which the bit should be set. - * - * @return @c 1 if bit was set, @c 0 otherwise. - */ -int coap_option_filter_set(coap_opt_filter_t filter, unsigned short type); - -/** - * Clears the corresponding entry for @p type in @p filter. This - * function returns @c 1 if bit was set or @c 0 on error (i.e. when - * the given type does not fit in the filter). - * - * @param filter The filter object to change. - * @param type The type that should be cleared from the filter. - * - * @return @c 1 if bit was set, @c 0 otherwise. - */ -int coap_option_filter_unset(coap_opt_filter_t filter, unsigned short type); - -/** - * Checks if @p type is contained in @p filter. This function returns - * @c 1 if found, @c 0 if not, or @c -1 on error (i.e. when the given - * type does not fit in the filter). - * - * @param filter The filter object to search. - * @param type The type to search for. - * - * @return @c 1 if @p type was found, @c 0 otherwise, or @c -1 on error. - */ -int coap_option_filter_get(const coap_opt_filter_t filter, unsigned short type); - -/** - * Sets the corresponding bit for @p type in @p filter. This function returns @c - * 1 if bit was set or @c -1 on error (i.e. when the given type does not fit in - * the filter). - * - * @deprecated Use coap_option_filter_set() instead. - * - * @param filter The filter object to change. - * @param type The type for which the bit should be set. - * - * @return @c 1 if bit was set, @c -1 otherwise. - */ -inline static int -coap_option_setb(coap_opt_filter_t filter, unsigned short type) { - return coap_option_filter_set(filter, type) ? 1 : -1; -} - -/** - * Clears the corresponding bit for @p type in @p filter. This function returns - * @c 1 if bit was cleared or @c -1 on error (i.e. when the given type does not - * fit in the filter). - * - * @deprecated Use coap_option_filter_unset() instead. - * - * @param filter The filter object to change. - * @param type The type for which the bit should be cleared. - * - * @return @c 1 if bit was set, @c -1 otherwise. - */ -inline static int -coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { - return coap_option_filter_unset(filter, type) ? 1 : -1; -} - -/** - * Gets the corresponding bit for @p type in @p filter. This function returns @c - * 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. when the given type - * does not fit in the filter). - * - * @deprecated Use coap_option_filter_get() instead. - * - * @param filter The filter object to read bit from. - * @param type The type for which the bit should be read. - * - * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. - */ -inline static int -coap_option_getb(const coap_opt_filter_t filter, unsigned short type) { - return coap_option_filter_get(filter, type); -} - -/** - * Iterator to run through PDU options. This object must be - * initialized with coap_option_iterator_init(). Call - * coap_option_next() to walk through the list of options until - * coap_option_next() returns @c NULL. - * - * @code - * coap_opt_t *option; - * coap_opt_iterator_t opt_iter; - * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); - * - * while ((option = coap_option_next(&opt_iter))) { - * ... do something with option ... - * } - * @endcode - */ -typedef struct { - size_t length; /**< remaining length of PDU */ - unsigned short type; /**< decoded option type */ - unsigned int bad:1; /**< iterator object is ok if not set */ - unsigned int filtered:1; /**< denotes whether or not filter is used */ - coap_opt_t *next_option; /**< pointer to the unparsed next option */ - coap_opt_filter_t filter; /**< option filter */ -} coap_opt_iterator_t; - -/** - * Initializes the given option iterator @p oi to point to the beginning of the - * @p pdu's option list. This function returns @p oi on success, @c NULL - * otherwise (i.e. when no options exist). Note that a length check on the - * option list must be performed before coap_option_iterator_init() is called. - * - * @param pdu The PDU the options of which should be walked through. - * @param oi An iterator object that will be initilized. - * @param filter An optional option type filter. - * With @p type != @c COAP_OPT_ALL, coap_option_next() - * will return only options matching this bitmask. - * Fence-post options @c 14, @c 28, @c 42, ... are always - * skipped. - * - * @return The iterator object @p oi on success, @c NULL otherwise. - */ -coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu, - coap_opt_iterator_t *oi, - const coap_opt_filter_t filter); - -/** - * Updates the iterator @p oi to point to the next option. This function returns - * a pointer to that option or @c NULL if no more options exist. The contents of - * @p oi will be updated. In particular, @c oi->n specifies the current option's - * ordinal number (counted from @c 1), @c oi->type is the option's type code, - * and @c oi->option points to the beginning of the current option itself. When - * advanced past the last option, @c oi->option will be @c NULL. - * - * Note that options are skipped whose corresponding bits in the filter - * specified with coap_option_iterator_init() are @c 0. Options with type codes - * that do not fit in this filter hence will always be returned. - * - * @param oi The option iterator to update. - * - * @return The next option or @c NULL if no more options exist. - */ -coap_opt_t *coap_option_next(coap_opt_iterator_t *oi); - -/** - * Retrieves the first option of type @p type from @p pdu. @p oi must point to a - * coap_opt_iterator_t object that will be initialized by this function to - * filter only options with code @p type. This function returns the first option - * with this type, or @c NULL if not found. - * - * @param pdu The PDU to parse for options. - * @param type The option type code to search for. - * @param oi An iterator object to use. - * - * @return A pointer to the first option of type @p type, or @c NULL if - * not found. - */ -coap_opt_t *coap_check_option(coap_pdu_t *pdu, - unsigned short type, - coap_opt_iterator_t *oi); - -/** - * Encodes the given delta and length values into @p opt. This function returns - * the number of bytes that were required to encode @p delta and @p length or @c - * 0 on error. Note that the result indicates by how many bytes @p opt must be - * advanced to encode the option value. - * - * @param opt The option buffer space where @p delta and @p length are - * written. - * @param maxlen The maximum length of @p opt. - * @param delta The actual delta value to encode. - * @param length The actual length value to encode. - * - * @return The number of bytes used or @c 0 on error. - */ -size_t coap_opt_setheader(coap_opt_t *opt, - size_t maxlen, - unsigned short delta, - size_t length); - -/** - * Encodes option with given @p delta into @p opt. This function returns the - * number of bytes written to @p opt or @c 0 on error. This happens especially - * when @p opt does not provide sufficient space to store the option value, - * delta, and option jumps when required. - * - * @param opt The option buffer space where @p val is written. - * @param n Maximum length of @p opt. - * @param delta The option delta. - * @param val The option value to copy into @p opt. - * @param length The actual length of @p val. - * - * @return The number of bytes that have been written to @p opt or @c 0 on - * error. The return value will always be less than @p n. - */ -size_t coap_opt_encode(coap_opt_t *opt, - size_t n, - unsigned short delta, - const unsigned char *val, - size_t length); - -/** - * Decodes the delta value of the next option. This function returns the number - * of bytes read or @c 0 on error. The caller of this function must ensure that - * it does not read over the boundaries of @p opt (e.g. by calling - * coap_opt_check_delta(). - * - * @param opt The option to examine. - * - * @return The number of bytes read or @c 0 on error. - */ -unsigned short coap_opt_delta(const coap_opt_t *opt); - -/** @deprecated { Use coap_opt_delta() instead. } */ -#define COAP_OPT_DELTA(opt) coap_opt_delta(opt) - -/** @deprecated { Use coap_opt_encode() instead. } */ -#define COAP_OPT_SETDELTA(opt,val) \ - coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0) - -/** - * Returns the length of the given option. @p opt must point to an option jump - * or the beginning of the option. This function returns @c 0 when @p opt is not - * an option or the actual length of @p opt (which can be @c 0 as well). - * - * @note {The rationale for using @c 0 in case of an error is that in most - * contexts, the result of this function is used to skip the next - * coap_opt_length() bytes.} - * - * @param opt The option whose length should be returned. - * - * @return The option's length or @c 0 when undefined. - */ -unsigned short coap_opt_length(const coap_opt_t *opt); - -/** @deprecated { Use coap_opt_length() instead. } */ -#define COAP_OPT_LENGTH(opt) coap_opt_length(opt) - -/** - * Returns a pointer to the value of the given option. @p opt must point to an - * option jump or the beginning of the option. This function returns @c NULL if - * @p opt is not a valid option. - * - * @param opt The option whose value should be returned. - * - * @return A pointer to the option value or @c NULL on error. - */ -unsigned char *coap_opt_value(coap_opt_t *opt); - -/** @deprecated { Use coap_opt_value() instead. } */ -#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt) - -/** @} */ - -#endif /* _OPTION_H_ */ diff --git a/components/coap/libcoap/include/coap/pdu.h b/components/coap/libcoap/include/coap/pdu.h deleted file mode 100644 index 7ed482dee..000000000 --- a/components/coap/libcoap/include/coap/pdu.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * pdu.h -- CoAP message structure - * - * Copyright (C) 2010-2014 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file pdu.h - * @brief Pre-defined constants that reflect defaults for CoAP - */ - -#ifndef _COAP_PDU_H_ -#define _COAP_PDU_H_ - -#include "uri.h" - -#ifdef WITH_LWIP -#include -#endif - -#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ -#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ -#ifndef COAP_MAX_PDU_SIZE -#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU */ -#endif /* COAP_MAX_PDU_SIZE */ - -#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */ -#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */ - -/** well-known resources URI */ -#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core" - -#ifdef __COAP_DEFAULT_HASH -/* pre-calculated hash key for the default well-known URI */ -#define COAP_DEFAULT_WKC_HASHKEY "\345\130\144\245" -#endif - -/* CoAP message types */ - -#define COAP_MESSAGE_CON 0 /* confirmable message (requires ACK/RST) */ -#define COAP_MESSAGE_NON 1 /* non-confirmable message (one-shot message) */ -#define COAP_MESSAGE_ACK 2 /* used to acknowledge confirmable messages */ -#define COAP_MESSAGE_RST 3 /* indicates error in received messages */ - -/* CoAP request methods */ - -#define COAP_REQUEST_GET 1 -#define COAP_REQUEST_POST 2 -#define COAP_REQUEST_PUT 3 -#define COAP_REQUEST_DELETE 4 - -/* CoAP option types (be sure to update check_critical when adding options */ - -#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */ -#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */ -#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */ -#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */ -#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */ -#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */ -#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */ -#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */ -#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT -#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */ -#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */ -#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */ -#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */ -#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */ -#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */ -#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */ - -/* option types from RFC 7641 */ - -#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ -#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE - -/* selected option types from RFC 7959 */ - -#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */ -#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */ - -/* selected option types from RFC 7967 */ - -#define COAP_OPTION_NORESPONSE 258 /* N, uint, 0--1 B, 0 */ - -#define COAP_MAX_OPT 65535 /**< the highest option number we know */ - -/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */ - -/* As of draft-ietf-core-coap-04, response codes are encoded to base - * 32, i.e. the three upper bits determine the response class while - * the remaining five fine-grained information specific to that class. - */ -#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100) - -/* Determines the class of response code C */ -#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF) - -#ifndef SHORT_ERROR_RESPONSE -/** - * Returns a human-readable response phrase for the specified CoAP response @p - * code. This function returns @c NULL if not found. - * - * @param code The response code for which the literal phrase should be - * retrieved. - * - * @return A zero-terminated string describing the error, or @c NULL if not - * found. - */ -char *coap_response_phrase(unsigned char code); - -#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */ - -#else -#define coap_response_phrase(x) ((char *)NULL) - -#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */ -#endif /* SHORT_ERROR_RESPONSE */ - -/* The following definitions exist for backwards compatibility */ -#if 0 /* this does not exist any more */ -#define COAP_RESPONSE_100 40 /* 100 Continue */ -#endif -#define COAP_RESPONSE_200 COAP_RESPONSE_CODE(200) /* 2.00 OK */ -#define COAP_RESPONSE_201 COAP_RESPONSE_CODE(201) /* 2.01 Created */ -#define COAP_RESPONSE_304 COAP_RESPONSE_CODE(203) /* 2.03 Valid */ -#define COAP_RESPONSE_400 COAP_RESPONSE_CODE(400) /* 4.00 Bad Request */ -#define COAP_RESPONSE_404 COAP_RESPONSE_CODE(404) /* 4.04 Not Found */ -#define COAP_RESPONSE_405 COAP_RESPONSE_CODE(405) /* 4.05 Method Not Allowed */ -#define COAP_RESPONSE_415 COAP_RESPONSE_CODE(415) /* 4.15 Unsupported Media Type */ -#define COAP_RESPONSE_500 COAP_RESPONSE_CODE(500) /* 5.00 Internal Server Error */ -#define COAP_RESPONSE_501 COAP_RESPONSE_CODE(501) /* 5.01 Not Implemented */ -#define COAP_RESPONSE_503 COAP_RESPONSE_CODE(503) /* 5.03 Service Unavailable */ -#define COAP_RESPONSE_504 COAP_RESPONSE_CODE(504) /* 5.04 Gateway Timeout */ -#if 0 /* these response codes do not have a valid code any more */ -# define COAP_RESPONSE_X_240 240 /* Token Option required by server */ -# define COAP_RESPONSE_X_241 241 /* Uri-Authority Option required by server */ -#endif -#define COAP_RESPONSE_X_242 COAP_RESPONSE_CODE(402) /* Critical Option not supported */ - -/* CoAP media type encoding */ - -#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */ -#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */ -#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */ -#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */ -#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */ -#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */ -#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */ -#define COAP_MEDIATYPE_APPLICATION_CBOR 60 /* application/cbor */ - -/* Note that identifiers for registered media types are in the range 0-65535. We - * use an unallocated type here and hope for the best. */ -#define COAP_MEDIATYPE_ANY 0xff /* any media type */ - -/** - * coap_tid_t is used to store CoAP transaction id, i.e. a hash value - * built from the remote transport address and the message id of a - * CoAP PDU. Valid transaction ids are greater or equal zero. - */ -typedef int coap_tid_t; - -/** Indicates an invalid transaction id. */ -#define COAP_INVALID_TID -1 - -/** - * Indicates that a response is suppressed. This will occur for error - * responses if the request was received via IP multicast. - */ -#define COAP_DROPPED_RESPONSE -2 - -#ifdef WORDS_BIGENDIAN -typedef struct { - unsigned int version:2; /* protocol version */ - unsigned int type:2; /* type flag */ - unsigned int token_length:4; /* length of Token */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* message id */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; -#else -typedef struct { - unsigned int token_length:4; /* length of Token */ - unsigned int type:2; /* type flag */ - unsigned int version:2; /* protocol version */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* transaction id (network byte order!) */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; -#endif - -#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0) -#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \ - && ((MSG)->code < 32)) -#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64) - -#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list - * in a CoAP message is limited by 0b11110000 - * marker */ - -#define COAP_OPT_END 0xF0 /* end marker */ - -#define COAP_PAYLOAD_START 0xFF /* payload marker */ - -/** - * Structures for more convenient handling of options. (To be used with ordered - * coap_list_t.) The option's data will be added to the end of the coap_option - * structure (see macro COAP_OPTION_DATA). - */ -typedef struct { - unsigned short key; /* the option key (no delta coding) */ - unsigned int length; -} coap_option; - -#define COAP_OPTION_KEY(option) (option).key -#define COAP_OPTION_LENGTH(option) (option).length -#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option)) - -/** - * Header structure for CoAP PDUs - */ - -typedef struct { - size_t max_size; /**< allocated storage for options and data */ - coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. - * This may or may not equal (coap_hdr_t*)(pdu+1) - * depending on the memory management - * implementation. */ - unsigned short max_delta; /**< highest option number */ - unsigned short length; /**< PDU length (including header, options, data) */ - unsigned char *data; /**< payload */ - -#ifdef WITH_LWIP - struct pbuf *pbuf; /**< lwIP PBUF. The package data will always reside - * inside the pbuf's payload, but this pointer - * has to be kept because no exact offset can be - * given. This field must not be accessed from - * outside, because the pbuf's reference count - * is checked to be 1 when the pbuf is assigned - * to the pdu, and the pbuf stays exclusive to - * this pdu. */ -#endif -} coap_pdu_t; - -/** - * Options in coap_pdu_t are accessed with the macro COAP_OPTION. - */ -#define COAP_OPTION(node) ((coap_option *)(node)->options) - -#ifdef WITH_LWIP -/** - * Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to this - * function. - * - * The pbuf is checked for being contiguous, and for having only one reference. - * The reference is stored in the PDU and will be freed when the PDU is freed. - * - * (For now, these are fatal errors; in future, a new pbuf might be allocated, - * the data copied and the passed pbuf freed). - * - * This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards - * copying the contents of the pbuf to the pdu. - * - * @return A pointer to the new PDU object or @c NULL on error. - */ -coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf); -#endif - -/** - * Creates a new CoAP PDU of given @p size (must be large enough to hold the - * basic CoAP message header (coap_hdr_t). The function returns a pointer to the - * node coap_pdu_t object on success, or @c NULL on error. The storage allocated - * for the result must be released with coap_delete_pdu(). - * - * @param type The type of the PDU (one of COAP_MESSAGE_CON, COAP_MESSAGE_NON, - * COAP_MESSAGE_ACK, COAP_MESSAGE_RST). - * @param code The message code. - * @param id The message id to set or COAP_INVALID_TID if unknown. - * @param size The number of bytes to allocate for the actual message. - * - * @return A pointer to the new PDU object or @c NULL on error. - */ -coap_pdu_t * -coap_pdu_init(unsigned char type, - unsigned char code, - unsigned short id, - size_t size); - -/** - * Clears any contents from @p pdu and resets @c version field, @c - * length and @c data pointers. @c max_size is set to @p size, any - * other field is set to @c 0. Note that @p pdu must be a valid - * pointer to a coap_pdu_t object created e.g. by coap_pdu_init(). - */ -void coap_pdu_clear(coap_pdu_t *pdu, size_t size); - -/** - * Creates a new CoAP PDU. - * The object is created on the heap and must be released using - * coap_delete_pdu(); - * - * @deprecated This function allocates the maximum storage for each - * PDU. Use coap_pdu_init() instead. - */ -coap_pdu_t *coap_new_pdu(void); - -void coap_delete_pdu(coap_pdu_t *); - -/** - * Parses @p data into the CoAP PDU structure given in @p result. - * This function returns @c 0 on error or a number greater than zero on success. - * - * @param data The raw data to parse as CoAP PDU. - * @param length The actual size of @p data. - * @param result The PDU structure to fill. Note that the structure must - * provide space for at least @p length bytes to hold the - * entire CoAP PDU. - * - * @return A value greater than zero on success or @c 0 on error. - */ -int coap_pdu_parse(unsigned char *data, - size_t length, - coap_pdu_t *result); - -/** - * Adds token of length @p len to @p pdu. - * Adding the token destroys any following contents of the pdu. Hence options - * and data must be added after coap_add_token() has been called. In @p pdu, - * length is set to @p len + @c 4, and max_delta is set to @c 0. This funtion - * returns @c 0 on error or a value greater than zero on success. - * - * @param pdu The PDU where the token is to be added. - * @param len The length of the new token. - * @param data The token to add. - * - * @return A value greater than zero on success, or @c 0 on error. - */ -int coap_add_token(coap_pdu_t *pdu, - size_t len, - const unsigned char *data); - -/** - * Adds option of given type to pdu that is passed as first - * parameter. - * coap_add_option() destroys the PDU's data, so coap_add_data() must be called - * after all options have been added. As coap_add_token() destroys the options - * following the token, the token must be added before coap_add_option() is - * called. This function returns the number of bytes written or @c 0 on error. - */ -size_t coap_add_option(coap_pdu_t *pdu, - unsigned short type, - unsigned int len, - const unsigned char *data); - -/** - * Adds option of given type to pdu that is passed as first parameter, but does - * not write a value. It works like coap_add_option with respect to calling - * sequence (i.e. after token and before data). This function returns a memory - * address to which the option data has to be written before the PDU can be - * sent, or @c NULL on error. - */ -unsigned char *coap_add_option_later(coap_pdu_t *pdu, - unsigned short type, - unsigned int len); - -/** - * Adds given data to the pdu that is passed as first parameter. Note that the - * PDU's data is destroyed by coap_add_option(). coap_add_data() must be called - * only once per PDU, otherwise the result is undefined. - */ -int coap_add_data(coap_pdu_t *pdu, - unsigned int len, - const unsigned char *data); - -/** - * Retrieves the length and data pointer of specified PDU. Returns 0 on error or - * 1 if *len and *data have correct values. Note that these values are destroyed - * with the pdu. - */ -int coap_get_data(coap_pdu_t *pdu, - size_t *len, - unsigned char **data); - -#endif /* _COAP_PDU_H_ */ diff --git a/components/coap/libcoap/include/coap/prng.h b/components/coap/libcoap/include/coap/prng.h deleted file mode 100644 index da6d95344..000000000 --- a/components/coap/libcoap/include/coap/prng.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * prng.h -- Pseudo Random Numbers - * - * Copyright (C) 2010-2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file prng.h - * @brief Pseudo Random Numbers - */ - -#ifndef _COAP_PRNG_H_ -#define _COAP_PRNG_H_ - -/** - * @defgroup prng Pseudo Random Numbers - * @{ - */ - -#if defined(WITH_POSIX) || (defined(WITH_LWIP) && !defined(LWIP_RAND)) -#include - -/** - * Fills \p buf with \p len random bytes. This is the default implementation for - * prng(). You might want to change prng() to use a better PRNG on your specific - * platform. - */ -static inline int -coap_prng_impl(unsigned char *buf, size_t len) { - while (len--) - *buf++ = rand() & 0xFF; - return 1; -} -#endif /* WITH_POSIX */ - -#ifdef WITH_CONTIKI -#include - -/** - * Fills \p buf with \p len random bytes. This is the default implementation for - * prng(). You might want to change prng() to use a better PRNG on your specific - * platform. - */ -static inline int -contiki_prng_impl(unsigned char *buf, size_t len) { - unsigned short v = random_rand(); - while (len > sizeof(v)) { - memcpy(buf, &v, sizeof(v)); - len -= sizeof(v); - buf += sizeof(v); - v = random_rand(); - } - - memcpy(buf, &v, len); - return 1; -} - -#define prng(Buf,Length) contiki_prng_impl((Buf), (Length)) -#define prng_init(Value) random_init((unsigned short)(Value)) -#endif /* WITH_CONTIKI */ - -#if defined(WITH_LWIP) && defined(LWIP_RAND) -static inline int -lwip_prng_impl(unsigned char *buf, size_t len) { - u32_t v = LWIP_RAND(); - while (len > sizeof(v)) { - memcpy(buf, &v, sizeof(v)); - len -= sizeof(v); - buf += sizeof(v); - v = LWIP_RAND(); - } - - memcpy(buf, &v, len); - return 1; -} - -#define prng(Buf,Length) lwip_prng_impl((Buf), (Length)) -#define prng_init(Value) - -#endif /* WITH_LWIP */ - -#ifndef prng -/** - * Fills \p Buf with \p Length bytes of random data. - * - * @hideinitializer - */ -#define prng(Buf,Length) coap_prng_impl((Buf), (Length)) -#endif - -#ifndef prng_init -/** - * Called to set the PRNG seed. You may want to re-define this to allow for a - * better PRNG. - * - * @hideinitializer - */ -#define prng_init(Value) srand((unsigned long)(Value)) -#endif - -/** @} */ - -#endif /* _COAP_PRNG_H_ */ diff --git a/components/coap/libcoap/include/coap/resource.h b/components/coap/libcoap/include/coap/resource.h deleted file mode 100644 index dbb19a8d1..000000000 --- a/components/coap/libcoap/include/coap/resource.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * resource.h -- generic resource handling - * - * Copyright (C) 2010,2011,2014,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -/** - * @file resource.h - * @brief Generic resource handling - */ - -#ifndef _COAP_RESOURCE_H_ -#define _COAP_RESOURCE_H_ - -# include - -#ifndef COAP_RESOURCE_CHECK_TIME -/** The interval in seconds to check if resources have changed. */ -#define COAP_RESOURCE_CHECK_TIME 2 -#endif /* COAP_RESOURCE_CHECK_TIME */ - -#ifdef COAP_RESOURCES_NOHASH -# include "utlist.h" -#else -# include "uthash.h" -#endif - -#include "hashkey.h" -#include "async.h" -#include "str.h" -#include "pdu.h" -#include "net.h" -#include "subscribe.h" - -/** - * Definition of message handler function (@sa coap_resource_t). - */ -typedef void (*coap_method_handler_t) - (coap_context_t *, - struct coap_resource_t *, - const coap_endpoint_t *, - coap_address_t *, - coap_pdu_t *, - str * /* token */, - coap_pdu_t * /* response */); - -#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1 -#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2 - -typedef struct coap_attr_t { - struct coap_attr_t *next; - str name; - str value; - int flags; -} coap_attr_t; - -/** The URI passed to coap_resource_init() is free'd by coap_delete_resource(). */ -#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1 - -/** - * Notifications will be sent non-confirmable by default. RFC 7641 Section 4.5 - * https://tools.ietf.org/html/rfc7641#section-4.5 - */ -#define COAP_RESOURCE_FLAGS_NOTIFY_NON 0x0 - -/** - * Notifications will be sent confirmable by default. RFC 7641 Section 4.5 - * https://tools.ietf.org/html/rfc7641#section-4.5 - */ -#define COAP_RESOURCE_FLAGS_NOTIFY_CON 0x2 - -typedef struct coap_resource_t { - unsigned int dirty:1; /**< set to 1 if resource has changed */ - unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet - * been notified of the last change */ - unsigned int observable:1; /**< can be observed */ - unsigned int cacheable:1; /**< can be cached */ - - /** - * Used to store handlers for the four coap methods @c GET, @c POST, @c PUT, - * and @c DELETE. coap_dispatch() will pass incoming requests to the handler - * that corresponds to its request method or generate a 4.05 response if no - * handler is available. - */ - coap_method_handler_t handler[4]; - - coap_key_t key; /**< the actual key bytes for this resource */ - -#ifdef COAP_RESOURCES_NOHASH - struct coap_resource_t *next; -#else - UT_hash_handle hh; -#endif - - coap_attr_t *link_attr; /**< attributes to be included with the link format */ - coap_subscription_t *subscribers; /**< list of observers for this resource */ - - /** - * Request URI for this resource. This field will point into the static - * memory. - */ - str uri; - int flags; - -} coap_resource_t; - -/** - * Creates a new resource object and initializes the link field to the string - * of length @p len. This function returns the new coap_resource_t object. - * - * @param uri The URI path of the new resource. - * @param len The length of @p uri. - * @param flags Flags for memory management (in particular release of memory). - * - * @return A pointer to the new object or @c NULL on error. - */ -coap_resource_t *coap_resource_init(const unsigned char *uri, - size_t len, int flags); - - -/** - * Sets the notification message type of resource @p r to given - * @p mode which must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON - * or @c COAP_RESOURCE_FLAGS_NOTIFY_CON. - */ -static inline void -coap_resource_set_mode(coap_resource_t *r, int mode) { - r->flags = (r->flags & !COAP_RESOURCE_FLAGS_NOTIFY_CON) | mode; -} - -/** - * Registers the given @p resource for @p context. The resource must have been - * created by coap_resource_init(), the storage allocated for the resource will - * be released by coap_delete_resource(). - * - * @param context The context to use. - * @param resource The resource to store. - */ -void coap_add_resource(coap_context_t *context, coap_resource_t *resource); - -/** - * Deletes a resource identified by @p key. The storage allocated for that - * resource is freed. - * - * @param context The context where the resources are stored. - * @param key The unique key for the resource to delete. - * - * @return @c 1 if the resource was found (and destroyed), - * @c 0 otherwise. - */ -int coap_delete_resource(coap_context_t *context, coap_key_t key); - -/** - * Deletes all resources from given @p context and frees their storage. - * - * @param context The CoAP context with the resources to be deleted. - */ -void coap_delete_all_resources(coap_context_t *context); - -/** - * Registers a new attribute with the given @p resource. As the - * attributes str fields will point to @p name and @p val the - * caller must ensure that these pointers are valid during the - * attribute's lifetime. - * - * @param resource The resource to register the attribute with. - * @param name The attribute's name. - * @param nlen Length of @p name. - * @param val The attribute's value or @c NULL if none. - * @param vlen Length of @p val if specified. - * @param flags Flags for memory management (in particular release of - * memory). - * - * @return A pointer to the new attribute or @c NULL on error. - */ -coap_attr_t *coap_add_attr(coap_resource_t *resource, - const unsigned char *name, - size_t nlen, - const unsigned char *val, - size_t vlen, - int flags); - -/** - * Returns @p resource's coap_attr_t object with given @p name if found, @c NULL - * otherwise. - * - * @param resource The resource to search for attribute @p name. - * @param name Name of the requested attribute. - * @param nlen Actual length of @p name. - * @return The first attribute with specified @p name or @c NULL if none - * was found. - */ -coap_attr_t *coap_find_attr(coap_resource_t *resource, - const unsigned char *name, - size_t nlen); - -/** - * Deletes an attribute. - * - * @param attr Pointer to a previously created attribute. - * - */ -void coap_delete_attr(coap_attr_t *attr); - -/** - * Status word to encode the result of conditional print or copy operations such - * as coap_print_link(). The lower 28 bits of coap_print_status_t are used to - * encode the number of characters that has actually been printed, bits 28 to 31 - * encode the status. When COAP_PRINT_STATUS_ERROR is set, an error occurred - * during output. In this case, the other bits are undefined. - * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, i.e. the - * printing would have exceeded the current buffer. - */ -typedef unsigned int coap_print_status_t; - -#define COAP_PRINT_STATUS_MASK 0xF0000000u -#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK) -#define COAP_PRINT_STATUS_ERROR 0x80000000u -#define COAP_PRINT_STATUS_TRUNC 0x40000000u - -/** - * Writes a description of this resource in link-format to given text buffer. @p - * len must be initialized to the maximum length of @p buf and will be set to - * the number of characters actually written if successful. This function - * returns @c 1 on success or @c 0 on error. - * - * @param resource The resource to describe. - * @param buf The output buffer to write the description to. - * @param len Must be initialized to the length of @p buf and - * will be set to the length of the printed link description. - * @param offset The offset within the resource description where to - * start writing into @p buf. This is useful for dealing - * with the Block2 option. @p offset is updated during - * output as it is consumed. - * - * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise, - * the lower 28 bits will indicate the number of characters that - * have actually been output into @p buffer. The flag - * COAP_PRINT_STATUS_TRUNC indicates that the output has been - * truncated. - */ -coap_print_status_t coap_print_link(const coap_resource_t *resource, - unsigned char *buf, - size_t *len, - size_t *offset); - -/** - * Registers the specified @p handler as message handler for the request type @p - * method - * - * @param resource The resource for which the handler shall be registered. - * @param method The CoAP request method to handle. - * @param handler The handler to register with @p resource. - */ -static inline void -coap_register_handler(coap_resource_t *resource, - unsigned char method, - coap_method_handler_t handler) { - assert(resource); - assert(method > 0 && (size_t)(method-1) < sizeof(resource->handler)/sizeof(coap_method_handler_t)); - resource->handler[method-1] = handler; -} - -/** - * Returns the resource identified by the unique string @p key. If no resource - * was found, this function returns @c NULL. - * - * @param context The context to look for this resource. - * @param key The unique key of the resource. - * - * @return A pointer to the resource or @c NULL if not found. - */ -coap_resource_t *coap_get_resource_from_key(coap_context_t *context, - coap_key_t key); - -/** - * Calculates the hash key for the resource requested by the Uri-Options of @p - * request. This function calls coap_hash() for every path segment. - * - * @param request The requesting pdu. - * @param key The resulting hash is stored in @p key. - */ -void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key); - -/** - * @addtogroup observe - */ - -/** - * Adds the specified peer as observer for @p resource. The subscription is - * identified by the given @p token. This function returns the registered - * subscription information if the @p observer has been added, or @c NULL on - * error. - * - * @param resource The observed resource. - * @param local_interface The local network interface where the observer is - * attached to. - * @param observer The remote peer that wants to received status updates. - * @param token The token that identifies this subscription. - * @return A pointer to the added/updated subscription - * information or @c NULL on error. - */ -coap_subscription_t *coap_add_observer(coap_resource_t *resource, - const coap_endpoint_t *local_interface, - const coap_address_t *observer, - const str *token); - -/** - * Returns a subscription object for given @p peer. - * - * @param resource The observed resource. - * @param peer The address to search for. - * @param token The token that identifies this subscription or @c NULL for - * any token. - * @return A valid subscription if exists or @c NULL otherwise. - */ -coap_subscription_t *coap_find_observer(coap_resource_t *resource, - const coap_address_t *peer, - const str *token); - -/** - * Marks an observer as alive. - * - * @param context The CoAP context to use. - * @param observer The transport address of the observer. - * @param token The corresponding token that has been used for the - * subscription. - */ -void coap_touch_observer(coap_context_t *context, - const coap_address_t *observer, - const str *token); - -/** - * Removes any subscription for @p observer from @p resource and releases the - * allocated storage. The result is @c 1 if an observation relationship with @p - * observer and @p token existed, @c 0 otherwise. - * - * @param resource The observed resource. - * @param observer The observer's address. - * @param token The token that identifies this subscription or @c NULL for - * any token. - * @return @c 1 if the observer has been deleted, @c 0 otherwise. - */ -int coap_delete_observer(coap_resource_t *resource, - const coap_address_t *observer, - const str *token); - -/** - * Checks for all known resources, if they are dirty and notifies subscribed - * observers. - */ -void coap_check_notify(coap_context_t *context); - -#ifdef COAP_RESOURCES_NOHASH - -#define RESOURCES_ADD(r, obj) \ - LL_PREPEND((r), (obj)) - -#define RESOURCES_DELETE(r, obj) \ - LL_DELETE((r), (obj)) - -#define RESOURCES_ITER(r,tmp) \ - coap_resource_t *tmp; \ - LL_FOREACH((r), tmp) - -#define RESOURCES_FIND(r, k, res) { \ - coap_resource_t *tmp; \ - (res) = tmp = NULL; \ - LL_FOREACH((r), tmp) { \ - if (memcmp((k), tmp->key, sizeof(coap_key_t)) == 0) { \ - (res) = tmp; \ - break; \ - } \ - } \ - } -#else /* COAP_RESOURCES_NOHASH */ - -#define RESOURCES_ADD(r, obj) \ - HASH_ADD(hh, (r), key, sizeof(coap_key_t), (obj)) - -#define RESOURCES_DELETE(r, obj) \ - HASH_DELETE(hh, (r), (obj)) - -#define RESOURCES_ITER(r,tmp) \ - coap_resource_t *tmp, *rtmp; \ - HASH_ITER(hh, (r), tmp, rtmp) - -#define RESOURCES_FIND(r, k, res) { \ - HASH_FIND(hh, (r), (k), sizeof(coap_key_t), (res)); \ - } - -#endif /* COAP_RESOURCES_NOHASH */ - -/** @} */ - -coap_print_status_t coap_print_wellknown(coap_context_t *, - unsigned char *, - size_t *, size_t, - coap_opt_t *); - -void coap_handle_failed_notify(coap_context_t *, - const coap_address_t *, - const str *); - -#endif /* _COAP_RESOURCE_H_ */ diff --git a/components/coap/libcoap/include/coap/str.h b/components/coap/libcoap/include/coap/str.h deleted file mode 100644 index 3dfa67315..000000000 --- a/components/coap/libcoap/include/coap/str.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * str.h -- strings to be used in the CoAP library - * - * Copyright (C) 2010-2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_STR_H_ -#define _COAP_STR_H_ - -#include - -typedef struct { - size_t length; /* length of string */ - unsigned char *s; /* string data */ -} str; - -#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); } - -/** - * Returns a new string object with at least size bytes storage allocated. The - * string must be released using coap_delete_string(); - */ -str *coap_new_string(size_t size); - -/** - * Deletes the given string and releases any memory allocated. - */ -void coap_delete_string(str *); - -#endif /* _COAP_STR_H_ */ diff --git a/components/coap/libcoap/include/coap/subscribe.h b/components/coap/libcoap/include/coap/subscribe.h deleted file mode 100644 index 52068642d..000000000 --- a/components/coap/libcoap/include/coap/subscribe.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * subscribe.h -- subscription handling for CoAP - * see draft-ietf-core-observe-16 - * - * Copyright (C) 2010-2012,2014-2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - - -#ifndef _COAP_SUBSCRIBE_H_ -#define _COAP_SUBSCRIBE_H_ - -#include "address.h" -#include "coap_io.h" - -/** - * @defgroup observe Resource observation - * @{ - */ - -/** - * The value COAP_OBSERVE_ESTABLISH in a GET request indicates a new observe - * relationship for (sender address, token) is requested. - */ -#define COAP_OBSERVE_ESTABLISH 0 - -/** - * The value COAP_OBSERVE_CANCEL in a GET request indicates that the observe - * relationship for (sender address, token) must be cancelled. - */ -#define COAP_OBSERVE_CANCEL 1 - -#ifndef COAP_OBS_MAX_NON -/** - * Number of notifications that may be sent non-confirmable before a confirmable - * message is sent to detect if observers are alive. The maximum allowed value - * here is @c 15. - */ -#define COAP_OBS_MAX_NON 5 -#endif /* COAP_OBS_MAX_NON */ - -#ifndef COAP_OBS_MAX_FAIL -/** - * Number of confirmable notifications that may fail (i.e. time out without - * being ACKed) before an observer is removed. The maximum value for - * COAP_OBS_MAX_FAIL is @c 3. - */ -#define COAP_OBS_MAX_FAIL 3 -#endif /* COAP_OBS_MAX_FAIL */ - -/** Subscriber information */ -typedef struct coap_subscription_t { - struct coap_subscription_t *next; /**< next element in linked list */ - coap_endpoint_t local_if; /**< local communication interface */ - coap_address_t subscriber; /**< address and port of subscriber */ - - unsigned int non_cnt:4; /**< up to 15 non-confirmable notifies allowed */ - unsigned int fail_cnt:2; /**< up to 3 confirmable notifies can fail */ - unsigned int dirty:1; /**< set if the notification temporarily could not be - * sent (in that case, the resource's partially - * dirty flag is set too) */ - size_t token_length; /**< actual length of token */ - unsigned char token[8]; /**< token used for subscription */ -} coap_subscription_t; - -void coap_subscription_init(coap_subscription_t *); - -/** @} */ - -#endif /* _COAP_SUBSCRIBE_H_ */ diff --git a/components/coap/libcoap/include/coap/uri.h b/components/coap/libcoap/include/coap/uri.h deleted file mode 100644 index 2340a7a6c..000000000 --- a/components/coap/libcoap/include/coap/uri.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * uri.h -- helper functions for URI treatment - * - * Copyright (C) 2010-2011,2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef _COAP_URI_H_ -#define _COAP_URI_H_ - -#include "hashkey.h" -#include "str.h" - -/** - * Representation of parsed URI. Components may be filled from a string with - * coap_split_uri() and can be used as input for option-creation functions. - */ -typedef struct { - str host; /**< host part of the URI */ - unsigned short port; /**< The port in host byte order */ - str path; /**< Beginning of the first path segment. - Use coap_split_path() to create Uri-Path options */ - str query; /**< The query part if present */ -} coap_uri_t; - -/** - * Creates a new coap_uri_t object from the specified URI. Returns the new - * object or NULL on error. The memory allocated by the new coap_uri_t - * must be released using coap_free(). - * - * @param uri The URI path to copy. - * @param length The length of uri. - * - * @return New URI object or NULL on error. - */ -coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length); - -/** - * Clones the specified coap_uri_t object. Thie function allocates sufficient - * memory to hold the coap_uri_t structure and its contents. The object must - * be released with coap_free(). */ -coap_uri_t *coap_clone_uri(const coap_uri_t *uri); - -/** - * Calculates a hash over the given path and stores the result in - * @p key. This function returns @c 0 on error or @c 1 on success. - * - * @param path The URI path to generate hash for. - * @param len The length of @p path. - * @param key The output buffer. - * - * @return @c 1 if @p key was set, @c 0 otherwise. - */ -int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key); - -/** - * @defgroup uri_parse URI Parsing Functions - * - * CoAP PDUs contain normalized URIs with their path and query split into - * multiple segments. The functions in this module help splitting strings. - * @{ - */ - -/** - * Parses a given string into URI components. The identified syntactic - * components are stored in the result parameter @p uri. Optional URI - * components that are not specified will be set to { 0, 0 }, except for the - * port which is set to @c COAP_DEFAULT_PORT. This function returns @p 0 if - * parsing succeeded, a value less than zero otherwise. - * - * @param str_var The string to split up. - * @param len The actual length of @p str_var - * @param uri The coap_uri_t object to store the result. - * @return @c 0 on success, or < 0 on error. - * - */ -int coap_split_uri(const unsigned char *str_var, size_t len, coap_uri_t *uri); - -/** - * Splits the given URI path into segments. Each segment is preceded - * by an option pseudo-header with delta-value 0 and the actual length - * of the respective segment after percent-decoding. - * - * @param s The path string to split. - * @param length The actual length of @p s. - * @param buf Result buffer for parsed segments. - * @param buflen Maximum length of @p buf. Will be set to the actual number - * of bytes written into buf on success. - * - * @return The number of segments created or @c -1 on error. - */ -int coap_split_path(const unsigned char *s, - size_t length, - unsigned char *buf, - size_t *buflen); - -/** - * Splits the given URI query into segments. Each segment is preceded - * by an option pseudo-header with delta-value 0 and the actual length - * of the respective query term. - * - * @param s The query string to split. - * @param length The actual length of @p s. - * @param buf Result buffer for parsed segments. - * @param buflen Maximum length of @p buf. Will be set to the actual number - * of bytes written into buf on success. - * - * @return The number of segments created or @c -1 on error. - * - * @bug This function does not reserve additional space for delta > 12. - */ -int coap_split_query(const unsigned char *s, - size_t length, - unsigned char *buf, - size_t *buflen); - -/** @} */ - -#endif /* _COAP_URI_H_ */ diff --git a/components/coap/libcoap/include/coap/uthash.h b/components/coap/libcoap/include/coap/uthash.h deleted file mode 100644 index 32b7a81cf..000000000 --- a/components/coap/libcoap/include/coap/uthash.h +++ /dev/null @@ -1,963 +0,0 @@ -/* -Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#include /* memcmp,strlen */ -#include /* ptrdiff_t */ -#include /* exit() */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define DECLTYPE(x) -#endif -#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) -#define NO_DECLTYPE -#define DECLTYPE(x) -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while(0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while(0) -#endif - -/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ -#if defined (_WIN32) -#if defined(_MSC_VER) && _MSC_VER >= 1600 -#include -#elif defined(__WATCOMC__) -#include -#else -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#endif -#else -#include -#endif - -#define UTHASH_VERSION 1.9.9 - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#endif -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhe */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - out=NULL; \ - if (head) { \ - unsigned _hf_bkt,_hf_hashv; \ - HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ - keyptr,keylen,out); \ - } \ - } \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0 -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while(0) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - replaced=NULL; \ - HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ - if (replaced!=NULL) { \ - HASH_DELETE(hh,head,replaced); \ - }; \ - HASH_ADD(hh,head,fieldname,keylen_in,add); \ -} while(0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.next = NULL; \ - (add)->hh.key = (char*)(keyptr); \ - (add)->hh.keylen = (unsigned)(keylen_in); \ - if (!(head)) { \ - head = (add); \ - (head)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh,head); \ - } else { \ - (head)->hh.tbl->tail->next = (add); \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail = &((add)->hh); \ - } \ - (head)->hh.tbl->num_items++; \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ - (add)->hh.hashv, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ - HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ - HASH_FSCK(hh,head); \ -} while(0) - -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - head = NULL; \ - } else { \ - unsigned _hd_bkt; \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ - } \ - if (_hd_hh_del->next) { \ - ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield[0],strlen(add->strfield),add) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - struct UT_hash_handle *_thh; \ - if (head) { \ - unsigned _bkt_i; \ - unsigned _count; \ - char *_prev; \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - unsigned _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %u, actual %u\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %u, actual %u\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %u, actual %u\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#ifdef HASH_FUNCTION -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _sx_i; \ - char *_hs_key=(char*)(key); \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - bkt = hashv & (num_bkts-1); \ -} while (0) -/* FNV-1a variation */ -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _fn_i; \ - char *_hf_key=(char*)(key); \ - hashv = 2166136261UL; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ - hashv = hashv ^ _hf_key[_fn_i]; \ - hashv = hashv * 16777619; \ - } \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _ho_i; \ - char *_ho_key=(char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned char *_hj_key=(unsigned char*)(key); \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12; \ - } \ - hashv += keylen; \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - case 5: _hj_j += _hj_key[4]; \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - case 1: _hj_i += _hj_key[0]; \ - /* case 0: nothing left to add */ \ - default: /* make gcc -Wswitch-default happy */ \ - ; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned char *_sfh_key=(unsigned char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ - \ - int _sfh_rem = _sfh_len & 3; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6b; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35l; \ - _h ^= _h >> 16; \ -} while(0) - -#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353; \ - uint32_t _mur_c1 = 0xcc9e2d51; \ - uint32_t _mur_c2 = 0x1b873593; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ - int _mur_i; \ - for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = _mur_h1*5+0xe6546b64; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ - _mur_k1=0; \ - switch((keylen) & 3) { \ - case 3: _mur_k1 ^= _mur_tail[2] << 16; \ - case 2: _mur_k1 ^= _mur_tail[1] << 8; \ - case 1: _mur_k1 ^= _mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ - bkt = hashv & (num_bkts-1); \ -} while(0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* key comparison function; return 0 if keys equal */ -#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ -do { \ - if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ - else out=NULL; \ - while (out) { \ - if ((out)->hh.keylen == keylen_in) { \ - if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ - } \ - if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ - else out = NULL; \ - } \ -} while(0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ - && (addhh)->tbl->noexpand != 1) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while(0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ - ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ - _he_thh; \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - tbl->num_buckets *= 2; \ - tbl->log2_num_buckets++; \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1) : 0; \ - if (tbl->ineff_expands > 1) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while(0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) break; \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ - if (_hs_psize == 0) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else if (( \ - cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail ) { \ - _hs_tail->next = ((_hs_e) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e) { \ - _hs_e->prev = ((_hs_tail) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail){ \ - _hs_tail->next = NULL; \ - } \ - if ( _hs_nmerges <= 1 ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ - if (!dst) { \ - DECLTYPE_ASSIGN(dst,_elt); \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)=NULL; \ - } \ -} while(0) - -#define HASH_OVERHEAD(hh,head) \ - ((head) ? ( \ - (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - (sizeof(UT_hash_table)) + \ - (HASH_BLOOM_BYTELEN)))) : 0) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1 -#define HASH_BLOOM_SIGNATURE 0xb12220f2 - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - char bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ diff --git a/components/coap/libcoap/include/coap/utlist.h b/components/coap/libcoap/include/coap/utlist.h deleted file mode 100644 index b5f3f04c1..000000000 --- a/components/coap/libcoap/include/coap/utlist.h +++ /dev/null @@ -1,757 +0,0 @@ -/* -Copyright (c) 2007-2014, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTLIST_H -#define UTLIST_H - -#define UTLIST_VERSION 1.9.9 - -#include - -/* - * This file contains macros to manipulate singly and doubly-linked lists. - * - * 1. LL_ macros: singly-linked lists. - * 2. DL_ macros: doubly-linked lists. - * 3. CDL_ macros: circular doubly-linked lists. - * - * To use singly-linked lists, your structure must have a "next" pointer. - * To use doubly-linked lists, your structure must "prev" and "next" pointers. - * Either way, the pointer to the head of the list must be initialized to NULL. - * - * ----------------.EXAMPLE ------------------------- - * struct item { - * int id; - * struct item *prev, *next; - * } - * - * struct item *list = NULL: - * - * int main() { - * struct item *item; - * ... allocate and populate item ... - * DL_APPEND(list, item); - * } - * -------------------------------------------------- - * - * For doubly-linked lists, the append and delete macros are O(1) - * For singly-linked lists, append and delete are O(n) but prepend is O(1) - * The sort macro is O(n log(n)) for all types of single/double/circular lists. - */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ code), this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define LDECLTYPE(x) decltype(x) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define LDECLTYPE(x) char* -#endif -#elif defined(__ICCARM__) -#define NO_DECLTYPE -#define LDECLTYPE(x) char* -#else /* GNU, Sun and other compilers */ -#define LDECLTYPE(x) __typeof(x) -#endif - -/* for VS2008 we use some workarounds to get around the lack of decltype, - * namely, we always reassign our tmp variable to the list head if we need - * to dereference its prev/next pointers, and save/restore the real head.*/ -#ifdef NO_DECLTYPE -#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } -#define _NEXT(elt,list,next) ((char*)((list)->next)) -#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } -/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */ -#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } -#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } -#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } -#else -#define _SV(elt,list) -#define _NEXT(elt,list,next) ((elt)->next) -#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to) -/* #define _PREV(elt,list,prev) ((elt)->prev) */ -#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) -#define _RS(list) -#define _CASTASGN(a,b) (a)=(b) -#endif - -/****************************************************************************** - * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * - * Unwieldy variable names used here to avoid shadowing passed-in variables. * - *****************************************************************************/ -#define LL_SORT(list, cmp) \ - LL_SORT2(list, cmp, next) - -#define LL_SORT2(list, cmp, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - _CASTASGN(_ls_p,list); \ - list = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ - } else { \ - _CASTASGN(list,_ls_e); \ - } \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ - } \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - - -#define DL_SORT(list, cmp) \ - DL_SORT2(list, cmp, prev, next) - -#define DL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - _CASTASGN(_ls_p,list); \ - list = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ - } else { \ - _CASTASGN(list,_ls_e); \ - } \ - _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - _CASTASGN(list->prev, _ls_tail); \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -#define CDL_SORT(list, cmp) \ - CDL_SORT2(list, cmp, prev, next) - -#define CDL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - LDECLTYPE(list) _ls_oldhead; \ - LDECLTYPE(list) _tmp; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - _CASTASGN(_ls_p,list); \ - _CASTASGN(_ls_oldhead,list); \ - list = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - _SV(_ls_q,list); \ - if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \ - _ls_q = NULL; \ - } else { \ - _ls_q = _NEXT(_ls_q,list,next); \ - } \ - _RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ - _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } \ - if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ - } else { \ - _CASTASGN(list,_ls_e); \ - } \ - _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - _CASTASGN(list->prev,_ls_tail); \ - _CASTASGN(_tmp,list); \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -/****************************************************************************** - * singly linked list macros (non-circular) * - *****************************************************************************/ -#define LL_PREPEND(head,add) \ - LL_PREPEND2(head,add,next) - -#define LL_PREPEND2(head,add,next) \ -do { \ - (add)->next = head; \ - head = add; \ -} while (0) - -#define LL_CONCAT(head1,head2) \ - LL_CONCAT2(head1,head2,next) - -#define LL_CONCAT2(head1,head2,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head1) { \ - _tmp = head1; \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(head2); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) - -#define LL_APPEND(head,add) \ - LL_APPEND2(head,add,next) - -#define LL_APPEND2(head,add,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - (add)->next=NULL; \ - if (head) { \ - _tmp = head; \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(add); \ - } else { \ - (head)=(add); \ - } \ -} while (0) - -#define LL_DELETE(head,del) \ - LL_DELETE2(head,del,next) - -#define LL_DELETE2(head,del,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - _tmp = head; \ - while (_tmp->next && (_tmp->next != (del))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = ((del)->next); \ - } \ - } \ -} while (0) - -/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ -#define LL_APPEND_VS2008(head,add) \ - LL_APPEND2_VS2008(head,add,next) - -#define LL_APPEND2_VS2008(head,add,next) \ -do { \ - if (head) { \ - (add)->next = head; /* use add->next as a temp variable */ \ - while ((add)->next->next) { (add)->next = (add)->next->next; } \ - (add)->next->next=(add); \ - } else { \ - (head)=(add); \ - } \ - (add)->next=NULL; \ -} while (0) - -#define LL_DELETE_VS2008(head,del) \ - LL_DELETE2_VS2008(head,del,next) - -#define LL_DELETE2_VS2008(head,del,next) \ -do { \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && ((head)->next != (del))) { \ - head = (head)->next; \ - } \ - if ((head)->next) { \ - (head)->next = ((del)->next); \ - } \ - { \ - char **_head_alias = (char**)&(head); \ - *_head_alias = _tmp; \ - } \ - } \ -} while (0) -#ifdef NO_DECLTYPE -#undef LL_APPEND -#define LL_APPEND LL_APPEND_VS2008 -#undef LL_DELETE -#define LL_DELETE LL_DELETE_VS2008 -#undef LL_DELETE2 -#define LL_DELETE2 LL_DELETE2_VS2008 -#undef LL_APPEND2 -#define LL_APPEND2 LL_APPEND2_VS2008 -#undef LL_CONCAT /* no LL_CONCAT_VS2008 */ -#undef DL_CONCAT /* no DL_CONCAT_VS2008 */ -#endif -/* end VS2008 replacements */ - -#define LL_COUNT(head,el,counter) \ - LL_COUNT2(head,el,counter,next) \ - -#define LL_COUNT2(head,el,counter,next) \ -{ \ - counter = 0; \ - LL_FOREACH2(head,el,next){ ++counter; } \ -} - -#define LL_FOREACH(head,el) \ - LL_FOREACH2(head,el,next) - -#define LL_FOREACH2(head,el,next) \ - for(el=head;el;el=(el)->next) - -#define LL_FOREACH_SAFE(head,el,tmp) \ - LL_FOREACH_SAFE2(head,el,tmp,next) - -#define LL_FOREACH_SAFE2(head,el,tmp,next) \ - for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) - -#define LL_SEARCH_SCALAR(head,out,field,val) \ - LL_SEARCH_SCALAR2(head,out,field,val,next) - -#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while(0) - -#define LL_SEARCH(head,out,elt,cmp) \ - LL_SEARCH2(head,out,elt,cmp,next) - -#define LL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while(0) - -#define LL_REPLACE_ELEM(head, el, add) \ -do { \ - LDECLTYPE(head) _tmp; \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el)->next; \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = head; \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ -} while (0) - -#define LL_PREPEND_ELEM(head, el, add) \ -do { \ - LDECLTYPE(head) _tmp; \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = head; \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ -} while (0) \ - - -/****************************************************************************** - * doubly linked list macros (non-circular) * - *****************************************************************************/ -#define DL_PREPEND(head,add) \ - DL_PREPEND2(head,add,prev,next) - -#define DL_PREPEND2(head,add,prev,next) \ -do { \ - (add)->next = head; \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev = (add); \ - } else { \ - (add)->prev = (add); \ - } \ - (head) = (add); \ -} while (0) - -#define DL_APPEND(head,add) \ - DL_APPEND2(head,add,prev,next) - -#define DL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev->next = (add); \ - (head)->prev = (add); \ - (add)->next = NULL; \ - } else { \ - (head)=(add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define DL_CONCAT(head1,head2) \ - DL_CONCAT2(head1,head2,prev,next) - -#define DL_CONCAT2(head1,head2,prev,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head2) { \ - if (head1) { \ - _tmp = (head2)->prev; \ - (head2)->prev = (head1)->prev; \ - (head1)->prev->next = (head2); \ - (head1)->prev = _tmp; \ - } else { \ - (head1)=(head2); \ - } \ - } \ -} while (0) - -#define DL_DELETE(head,del) \ - DL_DELETE2(head,del,prev,next) - -#define DL_DELETE2(head,del,prev,next) \ -do { \ - assert((del)->prev != NULL); \ - if ((del)->prev == (del)) { \ - (head)=NULL; \ - } else if ((del)==(head)) { \ - (del)->next->prev = (del)->prev; \ - (head) = (del)->next; \ - } else { \ - (del)->prev->next = (del)->next; \ - if ((del)->next) { \ - (del)->next->prev = (del)->prev; \ - } else { \ - (head)->prev = (del)->prev; \ - } \ - } \ -} while (0) - -#define DL_COUNT(head,el,counter) \ - DL_COUNT2(head,el,counter,next) \ - -#define DL_COUNT2(head,el,counter,next) \ -{ \ - counter = 0; \ - DL_FOREACH2(head,el,next){ ++counter; } \ -} - -#define DL_FOREACH(head,el) \ - DL_FOREACH2(head,el,next) - -#define DL_FOREACH2(head,el,next) \ - for(el=head;el;el=(el)->next) - -/* this version is safe for deleting the elements during iteration */ -#define DL_FOREACH_SAFE(head,el,tmp) \ - DL_FOREACH_SAFE2(head,el,tmp,next) - -#define DL_FOREACH_SAFE2(head,el,tmp,next) \ - for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) - -/* these are identical to their singly-linked list counterparts */ -#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR -#define DL_SEARCH LL_SEARCH -#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 -#define DL_SEARCH2 LL_SEARCH2 - -#define DL_REPLACE_ELEM(head, el, add) \ -do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - (add)->next = (el)->next; \ - if ((el)->next == NULL) { \ - (add)->prev = (add); \ - } else { \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - } \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->prev->next = (add); \ - if ((el)->next == NULL) { \ - (head)->prev = (add); \ - } else { \ - (add)->next->prev = (add); \ - } \ - } \ -} while (0) - -#define DL_PREPEND_ELEM(head, el, add) \ -do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->prev->next = (add); \ - } \ -} while (0) \ - - -/****************************************************************************** - * circular doubly linked list macros * - *****************************************************************************/ -#define CDL_PREPEND(head,add) \ - CDL_PREPEND2(head,add,prev,next) - -#define CDL_PREPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - } \ -(head)=(add); \ -} while (0) - -#define CDL_DELETE(head,del) \ - CDL_DELETE2(head,del,prev,next) - -#define CDL_DELETE2(head,del,prev,next) \ -do { \ - if ( ((head)==(del)) && ((head)->next == (head))) { \ - (head) = 0L; \ - } else { \ - (del)->next->prev = (del)->prev; \ - (del)->prev->next = (del)->next; \ - if ((del) == (head)) (head)=(del)->next; \ - } \ -} while (0) - -#define CDL_COUNT(head,el,counter) \ - CDL_COUNT2(head,el,counter,next) \ - -#define CDL_COUNT2(head, el, counter,next) \ -{ \ - counter = 0; \ - CDL_FOREACH2(head,el,next){ ++counter; } \ -} - -#define CDL_FOREACH(head,el) \ - CDL_FOREACH2(head,el,next) - -#define CDL_FOREACH2(head,el,next) \ - for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) - -#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ - CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) - -#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ - for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ - (el) && ((tmp2)=(el)->next, 1); \ - ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) - -#define CDL_SEARCH_SCALAR(head,out,field,val) \ - CDL_SEARCH_SCALAR2(head,out,field,val,next) - -#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while(0) - -#define CDL_SEARCH(head,out,elt,cmp) \ - CDL_SEARCH2(head,out,elt,cmp,next) - -#define CDL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while(0) - -#define CDL_REPLACE_ELEM(head, el, add) \ -do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - if ((el)->next == (el)) { \ - (add)->next = (add); \ - (add)->prev = (add); \ - (head) = (add); \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } \ -} while (0) - -#define CDL_PREPEND_ELEM(head, el, add) \ -do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ -} while (0) \ - -#endif /* UTLIST_H */ - diff --git a/components/coap/libcoap/libcoap-1.map b/components/coap/libcoap/libcoap-1.map deleted file mode 100644 index b065371d9..000000000 --- a/components/coap/libcoap/libcoap-1.map +++ /dev/null @@ -1,116 +0,0 @@ -VER_1 { -global: - coap_add_attr; - coap_add_block; - coap_add_data; - coap_add_observer; - coap_add_option; - coap_add_option_later; - coap_add_resource; - coap_address_equals; - coap_add_token; - coap_adjust_basetime; - coap_cancel_all_messages; - coap_can_exit; - coap_check_notify; - coap_check_option; - coap_clock_init; - coap_clone_uri; - coap_decode_var_bytes; - coap_delete_all; - coap_delete_all_resources; - coap_delete_attr; - coap_delete_node; - coap_delete_observer; - coap_delete_pdu; - coap_delete_resource; - coap_delete_string; - coap_dispatch; - coap_encode_var_bytes; - coap_find_async; - coap_find_attr; - coap_find_observer; - coap_find_transaction; - coap_fls; - coap_free_async; - coap_free_context; - coap_free_endpoint; - coap_free_packet; - coap_free_type; - coap_get_block; - coap_get_data; - coap_get_log_level; - coap_get_resource_from_key; - coap_handle_failed_notify; - coap_handle_message; - coap_hash_impl; - coap_hash_path; - coap_hash_request_uri; - coap_insert_node; - coap_log_impl; - coap_malloc_type; - coap_memory_init; - coap_network_read; - coap_network_send; - coap_new_context; - coap_new_endpoint; - coap_new_error_response; - coap_new_node; - coap_new_pdu; - coap_new_string; - coap_new_uri; - coap_opt_block_num; - coap_opt_delta; - coap_opt_encode; - coap_option_check_critical; - coap_option_filter_get; - coap_option_filter_set; - coap_option_filter_unset; - coap_option_iterator_init; - coap_option_next; - coap_opt_length; - coap_opt_parse; - coap_opt_setheader; - coap_opt_size; - coap_opt_value; - coap_package_name; - coap_package_version; - coap_packet_copy_source; - coap_packet_get_memmapped; - coap_packet_populate_endpoint; - coap_pdu_clear; - coap_pdu_init; - coap_pdu_parse; - coap_peek_next; - coap_pop_next; - coap_print_addr; - coap_print_link; - coap_print_wellknown; - coap_read; - coap_register_async; - coap_remove_async; - coap_remove_from_queue; - coap_resource_init; - coap_response_phrase; - coap_retransmit; - coap_send; - coap_send_ack; - coap_send_confirmed; - coap_send_error; - coap_send_message_type; - coap_set_log_level; - coap_show_pdu; - coap_split_path; - coap_split_query; - coap_split_uri; - coap_subscription_init; - coap_ticks; - coap_ticks; - coap_ticks_to_rt; - coap_touch_observer; - coap_transaction_id; - coap_wellknown_response; - coap_write_block_opt; -local: - *; -}; diff --git a/components/coap/libcoap/libcoap-1.pc.in b/components/coap/libcoap/libcoap-1.pc.in deleted file mode 100644 index 8d1f3134c..000000000 --- a/components/coap/libcoap/libcoap-1.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: @PACKAGE_NAME@ -Description: C-Implementation of CoAP. -Version: @PACKAGE_VERSION@ -URL: @PACKAGE_URL@ -Libs: -L${libdir} -lcoap-@LIBCOAP_API_VERSION@ -Cflags: -I${includedir}/coap diff --git a/components/coap/libcoap/libcoap-1.sym b/components/coap/libcoap/libcoap-1.sym deleted file mode 100644 index 7f465feb2..000000000 --- a/components/coap/libcoap/libcoap-1.sym +++ /dev/null @@ -1,111 +0,0 @@ -coap_add_attr -coap_add_block -coap_add_data -coap_add_observer -coap_add_option -coap_add_option_later -coap_add_resource -coap_address_equals -coap_add_token -coap_adjust_basetime -coap_cancel_all_messages -coap_can_exit -coap_check_notify -coap_check_option -coap_clock_init -coap_clone_uri -coap_decode_var_bytes -coap_delete_all -coap_delete_all_resources -coap_delete_attr -coap_delete_node -coap_delete_observer -coap_delete_pdu -coap_delete_resource -coap_delete_string -coap_dispatch -coap_encode_var_bytes -coap_find_async -coap_find_attr -coap_find_observer -coap_find_transaction -coap_fls -coap_free_async -coap_free_context -coap_free_endpoint -coap_free_packet -coap_free_type -coap_get_block -coap_get_data -coap_get_log_level -coap_get_resource_from_key -coap_handle_failed_notify -coap_handle_message -coap_hash_impl -coap_hash_path -coap_hash_request_uri -coap_insert_node -coap_log_impl -coap_malloc_type -coap_memory_init -coap_network_read -coap_network_send -coap_new_context -coap_new_endpoint -coap_new_error_response -coap_new_node -coap_new_pdu -coap_new_string -coap_new_uri -coap_opt_block_num -coap_opt_delta -coap_opt_encode -coap_option_check_critical -coap_option_filter_get -coap_option_filter_set -coap_option_filter_unset -coap_option_iterator_init -coap_option_next -coap_opt_length -coap_opt_parse -coap_opt_setheader -coap_opt_size -coap_opt_value -coap_package_name -coap_package_version -coap_packet_copy_source -coap_packet_get_memmapped -coap_packet_populate_endpoint -coap_pdu_clear -coap_pdu_init -coap_pdu_parse -coap_peek_next -coap_pop_next -coap_print_addr -coap_print_link -coap_print_wellknown -coap_read -coap_register_async -coap_remove_async -coap_remove_from_queue -coap_resource_init -coap_response_phrase -coap_retransmit -coap_send -coap_send_ack -coap_send_confirmed -coap_send_error -coap_send_message_type -coap_set_log_level -coap_show_pdu -coap_split_path -coap_split_query -coap_split_uri -coap_subscription_init -coap_ticks -coap_ticks -coap_ticks_to_rt -coap_touch_observer -coap_transaction_id -coap_wellknown_response -coap_write_block_opt diff --git a/components/coap/libcoap/m4/ax_check_link_flag.m4 b/components/coap/libcoap/m4/ax_check_link_flag.m4 deleted file mode 100644 index eb01a6ce1..000000000 --- a/components/coap/libcoap/m4/ax_check_link_flag.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the linker or gives an error. -# (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the linker's default flags -# when the check is done. The check is thus made with the flags: "LDFLAGS -# EXTRA-FLAGS FLAG". This can for example be used to force the linker to -# issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_LINK_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 4 - -AC_DEFUN([AX_CHECK_LINK_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl -AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ - ax_check_save_flags=$LDFLAGS - LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - LDFLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_LINK_FLAGS diff --git a/components/coap/libcoap/scripts/build.sh b/components/coap/libcoap/scripts/build.sh deleted file mode 100755 index 8bc0e3905..000000000 --- a/components/coap/libcoap/scripts/build.sh +++ /dev/null @@ -1,32 +0,0 @@ -#! /bin/sh - -if test "x$TESTS" = "xyes" -o "x$TESTS" = "xtrue" ; then - WITH_TESTS="`scripts/fix-cunit.sh` --enable-tests" - test -f `pwd`/cunit.pc && echo cat `pwd`/cunit.pc -fi - -config() { - echo "./configure $*" - ./configure $* || cat config.log -} - -case "${PLATFORM}" in - contiki) config "--disable-tests --disable-documentation --disable-examples" && \ - make -C examples/contiki - ;; - lwip) config "--disable-tests --disable-documentation --disable-examples" && \ - make -C examples/lwip lwip lwip-contrib - make -C examples/lwip LDLIBS=`grep ac_cv_search_clock_gettime=- config.log|cut -d= -f2` - ;; - posix|*) config "$WITH_TESTS --enable-documentation --enable-examples" && \ - make - ;; -esac - -err=$? -if test $err = 0 -a -n "$WITH_TESTS" ; then - tests/testdriver - err=$? -fi - -exit $err diff --git a/components/coap/libcoap/scripts/fix-cunit.sh b/components/coap/libcoap/scripts/fix-cunit.sh deleted file mode 100755 index 05ab658eb..000000000 --- a/components/coap/libcoap/scripts/fix-cunit.sh +++ /dev/null @@ -1,15 +0,0 @@ -#! /bin/sh - -# only continue if `pkgconfig cunit` fails -pkg-config cunit 2>/dev/null && exit 0 - -# Check if the system has a cunit.pc. -# If not, exit with success (the configure script will raise -# a more descriptive error). -CUNIT_PC=`dpkg -L libcunit1-dev 2>/dev/null|grep cunit.pc` -if test "x$CUNIT_PC" != "x"; then - grep -q Version: $CUNIT_PC || (dpkg -l|sed -ne 's/^ii\s\+libcunit1-dev\s\+\([0-9]\+.[0-9]\+-[0-9]\+\).*$/Version: \1/p; T; q'|cat - $CUNIT_PC |sed -e 's/={exec_prefix/=${exec_prefix/' >`pwd`/cunit.pc) -fi - -# output location of generated cunit.pc -echo PKG_CONFIG_PATH=`pwd` diff --git a/components/coap/libcoap/src/address.c b/components/coap/libcoap/src/address.c deleted file mode 100644 index acb9ba3c6..000000000 --- a/components/coap/libcoap/src/address.c +++ /dev/null @@ -1,67 +0,0 @@ -/* address.c -- representation of network addresses - * - * Copyright (C) 2015-2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#ifdef WITH_POSIX -#include -#include -#include -#include - -#include "address.h" - -int -coap_address_equals(const coap_address_t *a, const coap_address_t *b) { - assert(a); assert(b); - - if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family) - return 0; - - /* need to compare only relevant parts of sockaddr_in6 */ - switch (a->addr.sa.sa_family) { - case AF_INET: - return - a->addr.sin.sin_port == b->addr.sin.sin_port && - memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, - sizeof(struct in_addr)) == 0; -#if COAP_IPV6 - case AF_INET6: - return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port && - memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr, - sizeof(struct in6_addr)) == 0; -#endif - default: /* fall through and signal error */ - ; - } - return 0; -} - -int coap_is_mcast(const coap_address_t *a) { - if (!a) - return 0; - - switch (a->addr.sa.sa_family) { - case AF_INET: - return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr)); -#if COAP_IPV6 - case AF_INET6: - return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr); -#endif - default: /* fall through and signal error */ - ; - } - return 0; -} -#else /* WITH_POSIX */ - -/* make compilers happy that do not like empty modules */ -static inline void dummy() -{ -} - -#endif /* not WITH_POSIX */ - diff --git a/components/coap/libcoap/src/async.c b/components/coap/libcoap/src/async.c deleted file mode 100644 index b311bf8ef..000000000 --- a/components/coap/libcoap/src/async.c +++ /dev/null @@ -1,100 +0,0 @@ -/* async.c -- state management for asynchronous messages - * - * Copyright (C) 2010,2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -/** - * @file async.c - * @brief state management for asynchronous messages - */ - -#ifndef WITHOUT_ASYNC - -#include "coap_config.h" -#include "coap.h" -#include "async.h" -#include "debug.h" -#include "mem.h" -#include "utlist.h" - -coap_async_state_t * -coap_register_async(coap_context_t *context, coap_address_t *peer, - coap_pdu_t *request, unsigned char flags, void *data) { - coap_async_state_t *s; - coap_tid_t id; - - coap_transaction_id(peer, request, &id); - LL_SEARCH_SCALAR(context->async_state,s,id,id); - - if (s != NULL) { - /* We must return NULL here as the caller must know that he is - * responsible for releasing @p data. */ - debug("asynchronous state for transaction %d already registered\n", id); - return NULL; - } - - /* store information for handling the asynchronous task */ - s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) + - request->hdr->token_length); - if (!s) { - coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n"); - return NULL; - } - - memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length); - - /* set COAP_ASYNC_CONFIRM according to request's type */ - s->flags = flags & ~COAP_ASYNC_CONFIRM; - if (request->hdr->type == COAP_MESSAGE_CON) - s->flags |= COAP_ASYNC_CONFIRM; - - s->appdata = data; - - memcpy(&s->peer, peer, sizeof(coap_address_t)); - - if (request->hdr->token_length) { - s->tokenlen = request->hdr->token_length; - memcpy(s->token, request->hdr->token, request->hdr->token_length); - } - - memcpy(&s->id, &id, sizeof(coap_tid_t)); - - coap_touch_async(s); - - LL_PREPEND(context->async_state, s); - - return s; -} - -coap_async_state_t * -coap_find_async(coap_context_t *context, coap_tid_t id) { - coap_async_state_t *tmp; - LL_SEARCH_SCALAR(context->async_state,tmp,id,id); - return tmp; -} - -int -coap_remove_async(coap_context_t *context, coap_tid_t id, - coap_async_state_t **s) { - coap_async_state_t *tmp = coap_find_async(context, id); - - if (tmp) - LL_DELETE(context->async_state,tmp); - - *s = tmp; - return tmp != NULL; -} - -void -coap_free_async(coap_async_state_t *s) { - if (s && (s->flags & COAP_ASYNC_RELEASE_DATA) != 0) - coap_free(s->appdata); - coap_free(s); -} - -#else -void does_not_exist(); /* make some compilers happy */ -#endif /* WITHOUT_ASYNC */ diff --git a/components/coap/libcoap/src/block.c b/components/coap/libcoap/src/block.c deleted file mode 100644 index 0e2cf4825..000000000 --- a/components/coap/libcoap/src/block.c +++ /dev/null @@ -1,140 +0,0 @@ -/* block.c -- block transfer - * - * Copyright (C) 2010--2012,2015-2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include "debug.h" -#include "block.h" - -#if (COAP_MAX_PDU_SIZE - 6) < (1 << (COAP_MAX_BLOCK_SZX + 4)) -#error "COAP_MAX_BLOCK_SZX too large" -#endif - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -#ifndef WITHOUT_BLOCK -unsigned int -coap_opt_block_num(const coap_opt_t *block_opt) { - unsigned int num = 0; - unsigned short len; - - len = coap_opt_length(block_opt); - - if (len == 0) { - return 0; - } - - if (len > 1) { - num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), - COAP_OPT_LENGTH(block_opt) - 1); - } - - return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); -} - -int -coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - - assert(block); - memset(block, 0, sizeof(coap_block_t)); - - if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) { - unsigned int num; - - block->szx = COAP_OPT_BLOCK_SZX(option); - if (COAP_OPT_BLOCK_MORE(option)) - block->m = 1; - - /* The block number is at most 20 bits, so values above 2^20 - 1 - * are illegal. */ - num = coap_opt_block_num(option); - if (num > 0xFFFFF) { - return 0; - } - block->num = num; - return 1; - } - - return 0; -} - -int -coap_write_block_opt(coap_block_t *block, unsigned short type, - coap_pdu_t *pdu, size_t data_length) { - size_t start, want, avail; - unsigned char buf[4]; - - assert(pdu); - - start = block->num << (block->szx + 4); - if (data_length <= start) { - debug("illegal block requested\n"); - return -2; - } - - avail = pdu->max_size - pdu->length - 4; - want = 1 << (block->szx + 4); - - /* check if entire block fits in message */ - if (want <= avail) { - block->m = want < data_length - start; - } else { - /* Sender has requested a block that is larger than the remaining - * space in pdu. This is ok if the remaining data fits into the pdu - * anyway. The block size needs to be adjusted only if there is more - * data left that cannot be delivered in this message. */ - - if (data_length - start <= avail) { - - /* it's the final block and everything fits in the message */ - block->m = 0; - } else { - unsigned char szx; - - /* we need to decrease the block size */ - if (avail < 16) { /* bad luck, this is the smallest block size */ - debug("not enough space, even the smallest block does not fit"); - return -3; - } - debug("decrease block size for %zu to %d\n", avail, coap_fls(avail) - 5); - szx = block->szx; - block->szx = coap_fls(avail) - 5; - block->m = 1; - block->num <<= szx - block->szx; - } - } - - /* to re-encode the block option */ - coap_add_option(pdu, type, coap_encode_var_bytes(buf, ((block->num << 4) | - (block->m << 3) | - block->szx)), - buf); - - return 1; -} - -int -coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, - unsigned int block_num, unsigned char block_szx) { - size_t start; - start = block_num << (block_szx + 4); - - if (len <= start) - return 0; - - return coap_add_data(pdu, - min(len - start, (unsigned int)(1 << (block_szx + 4))), - data + start); -} -#endif /* WITHOUT_BLOCK */ diff --git a/components/coap/libcoap/src/coap_io.c b/components/coap/libcoap/src/coap_io.c deleted file mode 100644 index a91ec54e2..000000000 --- a/components/coap/libcoap/src/coap_io.c +++ /dev/null @@ -1,621 +0,0 @@ -/* coap_io.h -- Default network I/O functions for libcoap - * - * Copyright (C) 2012,2014 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#ifdef HAVE_STDIO_H -# include -#endif - -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_SYS_UIO_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#include - -#ifdef WITH_CONTIKI -# include "uip.h" -#endif - -#include "debug.h" -#include "mem.h" -#include "coap_io.h" - -#ifdef WITH_POSIX -/* define generic PKTINFO for IPv4 */ -#if defined(IP_PKTINFO) -# define GEN_IP_PKTINFO IP_PKTINFO -#elif defined(IP_RECVDSTADDR) -# define GEN_IP_PKTINFO IP_RECVDSTADDR -#else -# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." -#endif /* IP_PKTINFO */ - -/* define generic KTINFO for IPv6 */ -#ifdef IPV6_RECVPKTINFO -# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO -#elif defined(IPV6_PKTINFO) -# define GEN_IPV6_PKTINFO IPV6_PKTINFO -#else -# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." -#endif /* IPV6_RECVPKTINFO */ - -struct coap_packet_t { - coap_if_handle_t hnd; /**< the interface handle */ - coap_address_t src; /**< the packet's source address */ - coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; - - int ifindex; - void *session; /**< opaque session data */ - - size_t length; /**< length of payload */ - unsigned char payload[]; /**< payload */ -}; -#endif - -#ifndef CUSTOM_COAP_NETWORK_ENDPOINT - -#ifdef WITH_CONTIKI -static int ep_initialized = 0; - -static inline struct coap_endpoint_t * -coap_malloc_contiki_endpoint() { - static struct coap_endpoint_t ep; - - if (ep_initialized) { - return NULL; - } else { - ep_initialized = 1; - return &ep; - } -} - -static inline void -coap_free_contiki_endpoint(struct coap_endpoint_t *ep) { - ep_initialized = 0; -} - -coap_endpoint_t * -coap_new_endpoint(const coap_address_t *addr, int flags) { - struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint(); - - if (ep) { - memset(ep, 0, sizeof(struct coap_endpoint_t)); - ep->handle.conn = udp_new(NULL, 0, NULL); - - if (!ep->handle.conn) { - coap_free_endpoint(ep); - return NULL; - } - - coap_address_init(&ep->addr); - uip_ipaddr_copy(&ep->addr.addr, &addr->addr); - ep->addr.port = addr->port; - udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port); - } - return ep; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if (ep) { - if (ep->handle.conn) { - uip_udp_remove((struct uip_udp_conn *)ep->handle.conn); - } - coap_free_contiki_endpoint(ep); - } -} - -#else /* WITH_CONTIKI */ -static inline struct coap_endpoint_t * -coap_malloc_posix_endpoint(void) { - return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t)); -} - -static inline void -coap_free_posix_endpoint(struct coap_endpoint_t *ep) { - coap_free(ep); -} - -coap_endpoint_t * -coap_new_endpoint(const coap_address_t *addr, int flags) { - int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); - int on = 1; - struct coap_endpoint_t *ep; - - if (sockfd < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: socket"); - return NULL; - } - - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR"); - - on = 1; - switch(addr->addr.sa.sa_family) { - case AF_INET: - if (setsockopt(sockfd, IPPROTO_IP, GEN_IP_PKTINFO, &on, sizeof(on)) < 0) - coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IP_PKTINFO\n"); - break; - case AF_INET6: - if (setsockopt(sockfd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, &on, sizeof(on)) < 0) - coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_PKTINFO\n"); - break; - default: - coap_log(LOG_ALERT, "coap_new_endpoint: unsupported sa_family\n"); - } - - if (bind(sockfd, &addr->addr.sa, addr->size) < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: bind"); - close (sockfd); - return NULL; - } - - ep = coap_malloc_posix_endpoint(); - if (!ep) { - coap_log(LOG_WARNING, "coap_new_endpoint: malloc"); - close(sockfd); - return NULL; - } - - memset(ep, 0, sizeof(struct coap_endpoint_t)); - ep->handle.fd = sockfd; - ep->flags = flags; - - ep->addr.size = addr->size; - if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address"); - close (sockfd); - return NULL; - } - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr_str[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) { - debug("created %sendpoint %s\n", - ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "", - addr_str); - } - } -#endif /* NDEBUG */ - - return (coap_endpoint_t *)ep; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if(ep) { - if (ep->handle.fd >= 0) - close(ep->handle.fd); - coap_free_posix_endpoint((struct coap_endpoint_t *)ep); - } -} - -#endif /* WITH_CONTIKI */ -#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */ - -#ifndef CUSTOM_COAP_NETWORK_SEND - -#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H) -/* define struct in6_pktinfo and struct in_pktinfo if not available - FIXME: check with configure -*/ -struct in6_pktinfo { - struct in6_addr ipi6_addr; /* src/dst IPv6 address */ - unsigned int ipi6_ifindex; /* send/recv interface index */ -}; - -struct in_pktinfo { - int ipi_ifindex; - struct in_addr ipi_spec_dst; - struct in_addr ipi_addr; -}; -#endif - -#if defined(WITH_POSIX) && !defined(SOL_IP) -/* Solaris expects level IPPROTO_IP for ancillary data. */ -#define SOL_IP IPPROTO_IP -#endif - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -ssize_t -coap_network_send(struct coap_context_t *context UNUSED_PARAM, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char *data, - size_t datalen) { - - struct coap_endpoint_t *ep = - (struct coap_endpoint_t *)local_interface; - -#ifndef WITH_CONTIKI - /* a buffer large enough to hold all protocol address types */ - char buf[CMSG_LEN(sizeof(struct sockaddr_storage))]; - struct msghdr mhdr; - struct iovec iov[1]; - - assert(local_interface); - - iov[0].iov_base = data; - iov[0].iov_len = datalen; - - memset(&mhdr, 0, sizeof(struct msghdr)); - mhdr.msg_name = (void *)&dst->addr; - mhdr.msg_namelen = dst->size; - - mhdr.msg_iov = iov; - mhdr.msg_iovlen = 1; - - switch (dst->addr.sa.sa_family) { - case AF_INET6: { - struct cmsghdr *cmsg; - struct in6_pktinfo *pktinfo; - - mhdr.msg_control = buf; - mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - - cmsg = CMSG_FIRSTHDR(&mhdr); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - - pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); - memset(pktinfo, 0, sizeof(struct in6_pktinfo)); - - pktinfo->ipi6_ifindex = ep->ifindex; - if (coap_is_mcast(&local_interface->addr)) { - /* We cannot send with multicast address as source address - * and hence let the kernel pick the outgoing interface. */ - pktinfo->ipi6_ifindex = 0; - memset(&pktinfo->ipi6_addr, 0, sizeof(pktinfo->ipi6_addr)); - } else { - pktinfo->ipi6_ifindex = ep->ifindex; - memcpy(&pktinfo->ipi6_addr, - &local_interface->addr.addr.sin6.sin6_addr, - local_interface->addr.size); - } - break; - } - case AF_INET: { -#if defined(IP_PKTINFO) - struct cmsghdr *cmsg; - struct in_pktinfo *pktinfo; - - mhdr.msg_control = buf; - mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); - - cmsg = CMSG_FIRSTHDR(&mhdr); - cmsg->cmsg_level = SOL_IP; - cmsg->cmsg_type = IP_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - - pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); - memset(pktinfo, 0, sizeof(struct in_pktinfo)); - - if (coap_is_mcast(&local_interface->addr)) { - /* We cannot send with multicast address as source address - * and hence let the kernel pick the outgoing interface. */ - pktinfo->ipi_ifindex = 0; - memset(&pktinfo->ipi_spec_dst, 0, sizeof(pktinfo->ipi_spec_dst)); - } else { - pktinfo->ipi_ifindex = ep->ifindex; - memcpy(&pktinfo->ipi_spec_dst, - &local_interface->addr.addr.sin.sin_addr, - local_interface->addr.size); - } -#endif /* IP_PKTINFO */ - break; - } - default: - /* error */ - coap_log(LOG_WARNING, "protocol not supported\n"); - return -1; - } - - return sendmsg(ep->handle.fd, &mhdr, 0); -#else /* WITH_CONTIKI */ - /* FIXME: untested */ - /* FIXME: is there a way to check if send was successful? */ - uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen, - &dst->addr, dst->port); - return datalen; -#endif /* WITH_CONTIKI */ -} - -#endif /* CUSTOM_COAP_NETWORK_SEND */ - -#ifndef CUSTOM_COAP_NETWORK_READ - -#define SIN6(A) ((struct sockaddr_in6 *)(A)) - -#ifdef WITH_POSIX -static coap_packet_t * -coap_malloc_packet(void) { - coap_packet_t *packet; - const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE; - - packet = (coap_packet_t *)coap_malloc(need); - if (packet) { - memset(packet, 0, need); - } - return packet; -} - -void -coap_free_packet(coap_packet_t *packet) { - coap_free(packet); -} -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI -static inline coap_packet_t * -coap_malloc_packet(void) { - return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0); -} - -void -coap_free_packet(coap_packet_t *packet) { - coap_free_type(COAP_PACKET, packet); -} -#endif /* WITH_CONTIKI */ - -static inline size_t -coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { - return COAP_MAX_PDU_SIZE; -} - -void -coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) -{ - target->handle = packet->interface->handle; - memcpy(&target->addr, &packet->dst, sizeof(target->addr)); - target->ifindex = packet->ifindex; - target->flags = 0; /* FIXME */ -} -void -coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) -{ - memcpy(target, &packet->src, sizeof(coap_address_t)); -} -void -coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) -{ - *address = packet->payload; - *length = packet->length; -} - -/** - * Checks if a message with destination address @p dst matches the - * local interface with address @p local. This function returns @c 1 - * if @p dst is a valid match, and @c 0 otherwise. - */ -static inline int -is_local_if(const coap_address_t *local, const coap_address_t *dst) { - return coap_address_isany(local) || coap_address_equals(dst, local) || - coap_is_mcast(dst); -} - -ssize_t -coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { - ssize_t len = -1; - -#ifdef WITH_POSIX - char msg_control[CMSG_LEN(sizeof(struct sockaddr_storage))]; - struct msghdr mhdr; - struct iovec iov[1]; -#endif /* WITH_POSIX */ - - assert(ep); - assert(packet); - - *packet = coap_malloc_packet(); - - if (!*packet) { - warn("coap_network_read: insufficient memory, drop packet\n"); - return -1; - } - - coap_address_init(&(*packet)->dst); /* the local interface address */ - coap_address_init(&(*packet)->src); /* the remote peer */ - -#ifdef WITH_POSIX - iov[0].iov_base = (*packet)->payload; - iov[0].iov_len = coap_get_max_packetlength(*packet); - - memset(&mhdr, 0, sizeof(struct msghdr)); - - mhdr.msg_name = &(*packet)->src.addr.st; - mhdr.msg_namelen = sizeof((*packet)->src.addr.st); - - mhdr.msg_iov = iov; - mhdr.msg_iovlen = 1; - - mhdr.msg_control = msg_control; - mhdr.msg_controllen = sizeof(msg_control); - assert(sizeof(msg_control) == CMSG_LEN(sizeof(struct sockaddr_storage))); - - len = recvmsg(ep->handle.fd, &mhdr, 0); - - if (len < 0) { - coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno)); - goto error; - } else { - struct cmsghdr *cmsg; - - coap_log(LOG_DEBUG, "received %d bytes on fd %d\n", (int)len, ep->handle.fd); - - /* use getsockname() to get the local port */ - (*packet)->dst.size = sizeof((*packet)->dst.addr); - if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) { - coap_log(LOG_DEBUG, "cannot determine local port\n"); - goto error; - } - - (*packet)->length = len; - - /* Walk through ancillary data records until the local interface - * is found where the data was received. */ - for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { - - /* get the local interface for IPv6 */ - if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { - union { - unsigned char *c; - struct in6_pktinfo *p; - } u; - u.c = CMSG_DATA(cmsg); - (*packet)->ifindex = (int)(u.p->ipi6_ifindex); - - memcpy(&(*packet)->dst.addr.sin6.sin6_addr, - &u.p->ipi6_addr, sizeof(struct in6_addr)); - - (*packet)->src.size = sizeof(struct sockaddr_in6); - if ((*packet)->src.size != mhdr.msg_namelen) { - coap_log(LOG_DEBUG, "wrong IPv6 address length detected, dropped packet\n"); - goto error; - } - - (*packet)->src.addr.sin6.sin6_family = SIN6(mhdr.msg_name)->sin6_family; - (*packet)->src.addr.sin6.sin6_addr = SIN6(mhdr.msg_name)->sin6_addr; - (*packet)->src.addr.sin6.sin6_port = SIN6(mhdr.msg_name)->sin6_port; - - break; - } - - /* local interface for IPv4 */ -#if defined(IP_PKTINFO) - if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { - union { - unsigned char *c; - struct in_pktinfo *p; - } u; - - u.c = CMSG_DATA(cmsg); - (*packet)->ifindex = u.p->ipi_ifindex; - - memcpy(&(*packet)->dst.addr.sin.sin_addr, - &u.p->ipi_addr, sizeof(struct in_addr)); - - (*packet)->src.size = sizeof(struct sockaddr_in); - if ((*packet)->src.size != mhdr.msg_namelen) { - coap_log(LOG_DEBUG, "wrong IPv4 address length detected, dropped packet\n"); - goto error; - } - - assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0); - - break; - } -#elif defined(IP_RECVDSTADDR) - if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { - (*packet)->ifindex = 0; - - memcpy(&(*packet)->dst.addr.sin.sin_addr, - CMSG_DATA(cmsg), sizeof(struct in_addr)); - - (*packet)->src.size = sizeof(struct sockaddr_in); - if ((*packet)->src.size != mhdr.msg_namelen) { - coap_log(LOG_DEBUG, "wrong IPv4 address length detected, dropped packet\n"); - goto error; - } - - assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0); - - break; - } -#endif /* IP_PKTINFO */ - } - - if (!is_local_if(&ep->addr, &(*packet)->dst)) { - coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n"); - goto error; - } - } -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI - /* FIXME: untested, make this work */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) - - if(uip_newdata()) { - uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr); - (*packet)->src.port = UIP_UDP_BUF->srcport; - uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr); - (*packet)->dst.port = UIP_UDP_BUF->destport; - - if (!is_local_if(&ep->addr, &(*packet)->dst)) { - coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n"); - goto error; - } - - len = uip_datalen(); - - if (len > coap_get_max_packetlength(*packet)) { - /* FIXME: we might want to send back a response */ - warn("discarded oversized packet\n"); - return -1; - } - - ((char *)uip_appdata)[len] = 0; -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr_str[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) { - debug("received %zd bytes from %s\n", len, addr_str); - } - } -#endif /* NDEBUG */ - - (*packet)->length = len; - memcpy(&(*packet)->payload, uip_appdata, len); - } - -#undef UIP_IP_BUF -#undef UIP_UDP_BUF -#endif /* WITH_CONTIKI */ -#ifdef WITH_LWIP -#error "coap_network_read() not implemented on this platform" -#endif - - (*packet)->interface = ep; - - return len; - error: - coap_free_packet(*packet); - *packet = NULL; - return -1; -} - -#undef SIN6 - -#endif /* CUSTOM_COAP_NETWORK_READ */ diff --git a/components/coap/libcoap/src/coap_io_lwip.c b/components/coap/libcoap/src/coap_io_lwip.c deleted file mode 100644 index 8ae3b57e0..000000000 --- a/components/coap/libcoap/src/coap_io_lwip.c +++ /dev/null @@ -1,98 +0,0 @@ -/* coap_io_lwip.h -- Network I/O functions for libcoap on lwIP - * - * Copyright (C) 2012,2014 Olaf Bergmann - * 2014 chrysn - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "mem.h" -#include "coap_io.h" -#include - -void coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) -{ - printf("FIXME no endpoint populated\n"); -} -void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) -{ - target->port = packet->srcport; - memcpy(&target->addr, ip_current_src_addr(), sizeof(ip_addr_t)); -} -void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) -{ - LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", packet->pbuf->tot_len == packet->pbuf->len); - *address = packet->pbuf->payload; - *length = packet->pbuf->tot_len; -} -void coap_free_packet(coap_packet_t *packet) -{ - if (packet->pbuf) - pbuf_free(packet->pbuf); - coap_free_type(COAP_PACKET, packet); -} - -struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet) -{ - struct pbuf *ret = packet->pbuf; - packet->pbuf = NULL; - return ret; -} - - -/** Callback from lwIP when a package was received. - * - * The current implemntation deals this to coap_handle_message immedately, but - * other mechanisms (as storing the package in a queue and later fetching it - * when coap_read is called) can be envisioned. - * - * It handles everything coap_read does on other implementations. - */ -static void coap_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - coap_endpoint_t *ep = (coap_endpoint_t*)arg; - coap_packet_t *packet = coap_malloc_type(COAP_PACKET, sizeof(coap_packet_t)); - /* this is fatal because due to the short life of the packet, never should there be more than one coap_packet_t required */ - LWIP_ASSERT("Insufficient coap_packet_t resources.", packet != NULL); - packet->pbuf = p; - packet->srcport = port; - - /** FIXME derive the context without changing endopint definition */ - coap_handle_message(ep->context, packet); - - coap_free_packet(packet); -} - -coap_endpoint_t *coap_new_endpoint(const coap_address_t *addr, int flags) { - coap_endpoint_t *result; - err_t err; - - LWIP_ASSERT("Flags not supported for LWIP endpoints", flags == COAP_ENDPOINT_NOSEC); - - result = coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t)); - if (!result) return NULL; - - result->pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (result->pcb == NULL) goto error; - - udp_recv(result->pcb, coap_recv, (void*)result); - err = udp_bind(result->pcb, &addr->addr, addr->port); - if (err) { - udp_remove(result->pcb); - goto error; - } - - return result; - -error: - coap_free_type(COAP_ENDPOINT, result); - return NULL; -} - -void coap_free_endpoint(coap_endpoint_t *ep) -{ - udp_remove(ep->pcb); - coap_free_type(COAP_ENDPOINT, ep); -} diff --git a/components/coap/libcoap/src/coap_time.c b/components/coap/libcoap/src/coap_time.c deleted file mode 100644 index 1f991755e..000000000 --- a/components/coap/libcoap/src/coap_time.c +++ /dev/null @@ -1,98 +0,0 @@ -/* coap_time.c -- Clock Handling - * - * Copyright (C) 2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#ifdef WITH_POSIX -#include -#include -#include /* _POSIX_TIMERS */ - -#include "coap_config.h" -#include "coap_time.h" - -static coap_time_t coap_clock_offset = 0; - -#if _POSIX_TIMERS && !defined(__APPLE__) - /* _POSIX_TIMERS is > 0 when clock_gettime() is available */ - - /* Use real-time clock for correct timestamps in coap_log(). */ -#define COAP_CLOCK CLOCK_REALTIME -#endif - -void -coap_clock_init(void) { -#ifdef COAP_CLOCK - struct timespec tv; - clock_gettime(COAP_CLOCK, &tv); -#else /* _POSIX_TIMERS */ - struct timeval tv; - gettimeofday(&tv, NULL); -#endif /* not _POSIX_TIMERS */ - - coap_clock_offset = tv.tv_sec; -} - -/* creates a Qx.frac from fval */ -#define Q(frac,fval) ((coap_tick_t)(((1 << (frac)) * (fval)))) - -/* number of frac bits for sub-seconds */ -#define FRAC 10 - -/* rounds val up and right shifts by frac positions */ -#define SHR_FP(val,frac) (((val) + (1 << ((frac) - 1))) >> (frac)) - -void -coap_ticks(coap_tick_t *t) { - unsigned long tmp; - -#ifdef COAP_CLOCK - struct timespec tv; - clock_gettime(COAP_CLOCK, &tv); - /* Possible errors are (see clock_gettime(2)): - * EFAULT tp points outside the accessible address space. - * EINVAL The clk_id specified is not supported on this system. - * Both cases should not be possible here. - */ - - tmp = SHR_FP(tv.tv_nsec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000000.0)), FRAC); -#else /* _POSIX_TIMERS */ - /* Fall back to gettimeofday() */ - - struct timeval tv; - gettimeofday(&tv, NULL); - /* Possible errors are (see gettimeofday(2)): - * EFAULT One of tv or tz pointed outside the accessible address space. - * EINVAL Timezone (or something else) is invalid. - * Both cases should not be possible here. - */ - - tmp = SHR_FP(tv.tv_usec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000.0)), FRAC); -#endif /* not _POSIX_TIMERS */ - - /* Finally, convert temporary FP representation to multiple of - * COAP_TICKS_PER_SECOND */ - *t = tmp + (tv.tv_sec - coap_clock_offset) * COAP_TICKS_PER_SECOND; -} - -coap_time_t -coap_ticks_to_rt(coap_tick_t t) { - return coap_clock_offset + (t / COAP_TICKS_PER_SECOND); -} - -#undef Q -#undef FRAC -#undef SHR_FP - -#else /* WITH_POSIX */ - -/* make compilers happy that do not like empty modules */ -static inline void dummy() -{ -} - -#endif /* not WITH_POSIX */ - diff --git a/components/coap/libcoap/src/debug.c b/components/coap/libcoap/src/debug.c deleted file mode 100644 index e1afda606..000000000 --- a/components/coap/libcoap/src/debug.c +++ /dev/null @@ -1,508 +0,0 @@ -/* debug.c -- debug utilities - * - * Copyright (C) 2010--2012,2014--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif - -#include "block.h" -#include "debug.h" -#include "encode.h" -#include "net.h" - -#ifdef WITH_LWIP -# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__)) -# define fflush(...) -#endif - -#ifdef WITH_CONTIKI -# ifndef DEBUG -# define DEBUG DEBUG_PRINT -# endif /* DEBUG */ -#include "net/ip/uip-debug.h" -#endif - -static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ - -const char *coap_package_name(void) { - return PACKAGE_NAME; -} - -const char *coap_package_version(void) { - return PACKAGE_STRING; -} - -coap_log_t -coap_get_log_level(void) { - return maxlog; -} - -void -coap_set_log_level(coap_log_t level) { - maxlog = level; -} - -/* this array has the same order as the type log_t */ -static char *loglevels[] = { - "EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTE", "INFO", "DEBG" -}; - -#ifdef HAVE_TIME_H - -static inline size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { - struct tm *tmp; - time_t now = coap_ticks_to_rt(t); - tmp = localtime(&now); - return strftime(s, len, "%b %d %H:%M:%S", tmp); -} - -#else /* alternative implementation: just print the timestamp */ - -static inline size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { -#ifdef HAVE_SNPRINTF - return snprintf(s, len, "%u.%03u", - (unsigned int)coap_ticks_to_rt(t), - (unsigned int)(t % COAP_TICKS_PER_SECOND)); -#else /* HAVE_SNPRINTF */ - /* @todo do manual conversion of timestamp */ - return 0; -#endif /* HAVE_SNPRINTF */ -} - -#endif /* HAVE_TIME_H */ - -#ifndef NDEBUG - -#ifndef HAVE_STRNLEN -/** - * A length-safe strlen() fake. - * - * @param s The string to count characters != 0. - * @param maxlen The maximum length of @p s. - * - * @return The length of @p s. - */ -static inline size_t -strnlen(const char *s, size_t maxlen) { - size_t n = 0; - while(*s++ && n < maxlen) - ++n; - return n; -} -#endif /* HAVE_STRNLEN */ - -static unsigned int -print_readable( const unsigned char *data, unsigned int len, - unsigned char *result, unsigned int buflen, int encode_always ) { - const unsigned char hex[] = "0123456789ABCDEF"; - unsigned int cnt = 0; - assert(data || len == 0); - - if (buflen == 0) { /* there is nothing we can do here but return */ - return 0; - } - - while (len) { - if (!encode_always && isprint(*data)) { - if (cnt+1 < buflen) { /* keep one byte for terminating zero */ - *result++ = *data; - ++cnt; - } else { - break; - } - } else { - if (cnt+4 < buflen) { /* keep one byte for terminating zero */ - *result++ = '\\'; - *result++ = 'x'; - *result++ = hex[(*data & 0xf0) >> 4]; - *result++ = hex[*data & 0x0f]; - cnt += 4; - } else - break; - } - - ++data; --len; - } - - *result = '\0'; /* add a terminating zero */ - return cnt; -} - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -size_t -coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#ifdef HAVE_ARPA_INET_H - const void *addrptr = NULL; - in_port_t port; - unsigned char *p = buf; - - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - port = ntohs(addr->addr.sin.sin_port); - break; -#if COAP_IPV6 - case AF_INET6: - if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ - return 0; - - *p++ = '['; - - addrptr = &addr->addr.sin6.sin6_addr; - port = ntohs(addr->addr.sin6.sin6_port); - - break; -#endif - default: - memcpy(buf, "(unknown address type)", min(22, len)); - return min(22, len); - } - - if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, len) == 0) { - perror("coap_print_addr"); - return 0; - } - - p += strnlen((char *)p, len); - - if (addr->addr.sa.sa_family == AF_INET6) { - if (p < buf + len) { - *p++ = ']'; - } else - return 0; - } - - p += snprintf((char *)p, buf + len - p + 1, ":%d", port); - - return buf + len - p; -#else /* HAVE_ARPA_INET_H */ -# if WITH_CONTIKI - unsigned char *p = buf; - uint8_t i; -# if NETSTACK_CONF_WITH_IPV6 - const unsigned char hex[] = "0123456789ABCDEF"; - - if (len < 41) - return 0; - - *p++ = '['; - - for (i=0; i < 16; i += 2) { - if (i) { - *p++ = ':'; - } - *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i] & 0x0f)]; - *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; - } - *p++ = ']'; -# else /* WITH_UIP6 */ -# warning "IPv4 network addresses will not be included in debug output" - - if (len < 21) - return 0; -# endif /* WITH_UIP6 */ - if (buf + len - p < 6) - return 0; - -#ifdef HAVE_SNPRINTF - p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); -#else /* HAVE_SNPRINTF */ - /* @todo manual conversion of port number */ -#endif /* HAVE_SNPRINTF */ - - return p - buf; -# else /* WITH_CONTIKI */ - /* TODO: output addresses manually */ -# warning "inet_ntop() not available, network addresses will not be included in debug output" -# endif /* WITH_CONTIKI */ - return 0; -#endif -} - -#ifdef WITH_CONTIKI -# define fprintf(fd, ...) PRINTF(__VA_ARGS__) -# define fflush(...) - -# ifdef HAVE_VPRINTF -# define vfprintf(fd, ...) vprintf(__VA_ARGS__) -# else /* HAVE_VPRINTF */ -# define vfprintf(fd, ...) PRINTF(__VA_ARGS__) -# endif /* HAVE_VPRINTF */ -#endif /* WITH_CONTIKI */ - -/** Returns a textual description of the message type @p t. */ -static const char * -msg_type_string(uint8_t t) { - static char *types[] = { "CON", "NON", "ACK", "RST", "???" }; - - return types[min(t, sizeof(types)/sizeof(char *) - 1)]; -} - -/** Returns a textual description of the method or response code. */ -static const char * -msg_code_string(uint8_t c) { - static char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE", "PATCH" }; - static char buf[5]; - - if (c < sizeof(methods)/sizeof(char *)) { - return methods[c]; - } else { - snprintf(buf, sizeof(buf), "%u.%02u", c >> 5, c & 0x1f); - return buf; - } -} - -/** Returns a textual description of the option name. */ -static const char * -msg_option_string(uint16_t option_type) { - struct option_desc_t { - uint16_t type; - const char *name; - }; - - static struct option_desc_t options[] = { - { COAP_OPTION_IF_MATCH, "If-Match" }, - { COAP_OPTION_URI_HOST, "Uri-Host" }, - { COAP_OPTION_ETAG, "ETag" }, - { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" }, - { COAP_OPTION_OBSERVE, "Observe" }, - { COAP_OPTION_URI_PORT, "Uri-Port" }, - { COAP_OPTION_LOCATION_PATH, "Location-Path" }, - { COAP_OPTION_URI_PATH, "Uri-Path" }, - { COAP_OPTION_CONTENT_FORMAT, "Content-Format" }, - { COAP_OPTION_MAXAGE, "Max-Age" }, - { COAP_OPTION_URI_QUERY, "Uri-Query" }, - { COAP_OPTION_ACCEPT, "Accept" }, - { COAP_OPTION_LOCATION_QUERY, "Location-Query" }, - { COAP_OPTION_BLOCK2, "Block2" }, - { COAP_OPTION_BLOCK1, "Block1" }, - { COAP_OPTION_PROXY_URI, "Proxy-Uri" }, - { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" }, - { COAP_OPTION_SIZE1, "Size1" }, - { COAP_OPTION_NORESPONSE, "No-Response" } - }; - - static char buf[6]; - size_t i; - - /* search option_type in list of known options */ - for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) { - if (option_type == options[i].type) { - return options[i].name; - } - } - - /* unknown option type, just print to buf */ - snprintf(buf, sizeof(buf), "%u", option_type); - return buf; -} - -static unsigned int -print_content_format(unsigned int format_type, - unsigned char *result, unsigned int buflen) { - struct desc_t { - unsigned int type; - const char *name; - }; - - static struct desc_t formats[] = { - { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" }, - { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" }, - { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" }, - { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" }, - { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" }, - { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" }, - { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" } - }; - - size_t i; - - /* search format_type in list of known content formats */ - for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) { - if (format_type == formats[i].type) { - return snprintf((char *)result, buflen, "%s", formats[i].name); - } - } - - /* unknown content format, just print numeric value to buf */ - return snprintf((char *)result, buflen, "%d", format_type); -} - -/** - * Returns 1 if the given @p content_format is either unknown or known - * to carry binary data. The return value @c 0 hence indicates - * printable data which is also assumed if @p content_format is @c 01. - */ -static inline int -is_binary(int content_format) { - return !(content_format == -1 || - content_format == COAP_MEDIATYPE_TEXT_PLAIN || - content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT || - content_format == COAP_MEDIATYPE_APPLICATION_XML || - content_format == COAP_MEDIATYPE_APPLICATION_JSON); -} - -void -coap_show_pdu(const coap_pdu_t *pdu) { - unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ - size_t buf_len = 0; /* takes the number of bytes written to buf */ - int encode = 0, have_options = 0, i; - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - int content_format = -1; - size_t data_len; - unsigned char *data; - - fprintf(COAP_DEBUG_FD, "v:%d t:%s c:%s i:%04x {", - pdu->hdr->version, msg_type_string(pdu->hdr->type), - msg_code_string(pdu->hdr->code), ntohs(pdu->hdr->id)); - - for (i = 0; i < pdu->hdr->token_length; i++) { - fprintf(COAP_DEBUG_FD, "%02x", pdu->hdr->token[i]); - } - fprintf(COAP_DEBUG_FD, "}"); - - /* show options, if any */ - coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL); - - fprintf(COAP_DEBUG_FD, " ["); - while ((option = coap_option_next(&opt_iter))) { - if (!have_options) { - have_options = 1; - } else { - fprintf(COAP_DEBUG_FD, ","); - } - - switch (opt_iter.type) { - case COAP_OPTION_CONTENT_FORMAT: - content_format = (int)coap_decode_var_bytes(COAP_OPT_VALUE(option), - COAP_OPT_LENGTH(option)); - - buf_len = print_content_format(content_format, buf, sizeof(buf)); - break; - - case COAP_OPTION_BLOCK1: - case COAP_OPTION_BLOCK2: - /* split block option into number/more/size where more is the - * letter M if set, the _ otherwise */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u", - coap_opt_block_num(option), /* block number */ - COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ - (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */ - - break; - - case COAP_OPTION_URI_PORT: - case COAP_OPTION_MAXAGE: - case COAP_OPTION_OBSERVE: - case COAP_OPTION_SIZE1: - /* show values as unsigned decimal value */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(COAP_OPT_VALUE(option), - COAP_OPT_LENGTH(option))); - break; - - default: - /* generic output function for all other option types */ - if (opt_iter.type == COAP_OPTION_URI_PATH || - opt_iter.type == COAP_OPTION_PROXY_URI || - opt_iter.type == COAP_OPTION_URI_HOST || - opt_iter.type == COAP_OPTION_LOCATION_PATH || - opt_iter.type == COAP_OPTION_LOCATION_QUERY || - opt_iter.type == COAP_OPTION_URI_QUERY) { - encode = 0; - } else { - encode = 1; - } - - buf_len = print_readable(COAP_OPT_VALUE(option), - COAP_OPT_LENGTH(option), - buf, sizeof(buf), encode); - } - - fprintf(COAP_DEBUG_FD, " %s:%.*s", msg_option_string(opt_iter.type), - (int)buf_len, buf); - } - - fprintf(COAP_DEBUG_FD, " ]"); - - if (coap_get_data((coap_pdu_t *)pdu, &data_len, &data)) { - - fprintf(COAP_DEBUG_FD, " :: "); - - if (is_binary(content_format)) { - fprintf(COAP_DEBUG_FD, "<<"); - while (data_len--) { - fprintf(COAP_DEBUG_FD, "%02x", *data++); - } - fprintf(COAP_DEBUG_FD, ">>"); - } else { - if (print_readable(data, data_len, buf, sizeof(buf), 0)) { - fprintf(COAP_DEBUG_FD, "'%s'", buf); - } - } - } - - fprintf(COAP_DEBUG_FD, "\n"); - fflush(COAP_DEBUG_FD); -} - - -#endif /* NDEBUG */ - -void -coap_log_impl(coap_log_t level, const char *format, ...) { - char timebuf[32]; - coap_tick_t now; - va_list ap; - FILE *log_fd; - - if (maxlog < level) - return; - - log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; - - coap_ticks(&now); - if (print_timestamp(timebuf,sizeof(timebuf), now)) - fprintf(log_fd, "%s ", timebuf); - - if (level <= LOG_DEBUG) - fprintf(log_fd, "%s ", loglevels[level]); - - va_start(ap, format); - vfprintf(log_fd, format, ap); - va_end(ap); - fflush(log_fd); -} - diff --git a/components/coap/libcoap/src/encode.c b/components/coap/libcoap/src/encode.c deleted file mode 100644 index 10c0c6c93..000000000 --- a/components/coap/libcoap/src/encode.c +++ /dev/null @@ -1,48 +0,0 @@ -/* encode.c -- encoding and decoding of CoAP data types - * - * Copyright (C) 2010,2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#ifndef NDEBUG -# include -#endif - -#include "coap_config.h" -#include "encode.h" - -/* Carsten suggested this when fls() is not available: */ -int coap_fls(unsigned int i) { - int n; - for (n = 0; i; n++) - i >>= 1; - return n; -} - -unsigned int -coap_decode_var_bytes(unsigned char *buf,unsigned int len) { - unsigned int i, n = 0; - for (i = 0; i < len; ++i) - n = (n << 8) + buf[i]; - - return n; -} - -unsigned int -coap_encode_var_bytes(unsigned char *buf, unsigned int val) { - unsigned int n, i; - - for (n = 0, i = val; i && n < sizeof(val); ++n) - i >>= 8; - - i = n; - while (i--) { - buf[i] = val & 0xff; - val >>= 8; - } - - return n; -} - diff --git a/components/coap/libcoap/src/hashkey.c b/components/coap/libcoap/src/hashkey.c deleted file mode 100644 index 828b5194d..000000000 --- a/components/coap/libcoap/src/hashkey.c +++ /dev/null @@ -1,29 +0,0 @@ -/* hashkey.c -- definition of hash key type and helper functions - * - * Copyright (C) 2010,2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "hashkey.h" - -/* Caution: When changing this, update COAP_DEFAULT_WKC_HASHKEY - * accordingly (see int coap_hash_path()); - */ -void -coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h) { - size_t j; - - while (len--) { - j = sizeof(coap_key_t)-1; - - while (j) { - h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j]; - --j; - } - - h[0] = (h[0] << 7) + h[0] + *s++; - } -} - diff --git a/components/coap/libcoap/src/mem.c b/components/coap/libcoap/src/mem.c deleted file mode 100644 index 95950c92e..000000000 --- a/components/coap/libcoap/src/mem.c +++ /dev/null @@ -1,121 +0,0 @@ -/* mem.c -- CoAP memory handling - * - * Copyright (C) 2014--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - - -#include "coap_config.h" -#include "mem.h" -#include "debug.h" - -#ifdef HAVE_ASSERT_H -#include -#else /* HAVE_ASSERT_H */ -#define assert(...) -#endif /* HAVE_ASSERT_H */ - -#ifdef HAVE_MALLOC -#include - -void -coap_memory_init(void) { -} - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__((unused)) -#else -#define UNUSED_PARAM -#endif /* __GNUC__ */ - -void * -coap_malloc_type(coap_memory_tag_t type UNUSED_PARAM, size_t size) { - return malloc(size); -} - -void -coap_free_type(coap_memory_tag_t type UNUSED_PARAM, void *p) { - free(p); -} - -#else /* HAVE_MALLOC */ - -#ifdef WITH_CONTIKI - -#define COAP_MAX_STRING_SIZE 12 -#define COAP_MAX_STRINGS 8 - -struct coap_string_t { - char data[COAP_MAX_STRING_SIZE]; -}; - -#include "coap_config.h" -#include "net.h" -#include "pdu.h" -#include "coap_io.h" -#include "resource.h" - -#define COAP_MAX_PACKET_SIZE (sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE) -#define COAP_MAX_PACKETS 2 - -typedef union { - coap_pdu_t packet; /* try to convince the compiler to word-align this structure */ - char buf[COAP_MAX_PACKET_SIZE]; -} coap_packetbuf_t; - -MEMB(string_storage, struct coap_string_t, COAP_MAX_STRINGS); -MEMB(packet_storage, coap_packetbuf_t, COAP_MAX_PACKETS); -MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT); -MEMB(pdu_storage, coap_pdu_t, COAP_PDU_MAXCNT); -MEMB(pdu_buf_storage, coap_packetbuf_t, COAP_PDU_MAXCNT); -MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES); -MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES); - -static struct memb * -get_container(coap_memory_tag_t type) { - switch(type) { - case COAP_PACKET: return &packet_storage; - case COAP_NODE: return &node_storage; - case COAP_PDU: return &pdu_storage; - case COAP_PDU_BUF: return &pdu_buf_storage; - case COAP_RESOURCE: return &resource_storage; - case COAP_RESOURCEATTR: return &attribute_storage; - default: - return &string_storage; - } -} - -void -coap_memory_init(void) { - memb_init(&string_storage); - memb_init(&packet_storage); - memb_init(&node_storage); - memb_init(&pdu_storage); - memb_init(&pdu_buf_storage); - memb_init(&resource_storage); - memb_init(&attribute_storage); -} - -void * -coap_malloc_type(coap_memory_tag_t type, size_t size) { - struct memb *container = get_container(type); - - assert(container); - - if (size > container->size) { - debug("coap_malloc_type: Requested memory exceeds maximum object size\n"); - return NULL; - } - - return memb_alloc(container); -} - -void -coap_free_type(coap_memory_tag_t type, void *object) { - memb_free(get_container(type), object); -} -#endif /* WITH_CONTIKI */ - -#endif /* HAVE_MALLOC */ diff --git a/components/coap/libcoap/src/net.c b/components/coap/libcoap/src/net.c deleted file mode 100644 index 7ebe48ad8..000000000 --- a/components/coap/libcoap/src/net.c +++ /dev/null @@ -1,1804 +0,0 @@ -/* net.c -- CoAP network interface - * - * Copyright (C) 2010--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#include -#include -#include -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#elif HAVE_SYS_UNISTD_H -#include -#endif -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef WITH_LWIP -#include -#include -#include -#endif - -#include "debug.h" -#include "mem.h" -#include "str.h" -#include "async.h" -#include "resource.h" -#include "option.h" -#include "encode.h" -#include "block.h" -#include "net.h" - -/** - * @defgroup cc Rate Control - * The transmission parameters for CoAP rate control ("Congestion - * Control" in stream-oriented protocols) are defined in - * https://tools.ietf.org/html/rfc7252#section-4.8 - * @{ - */ - -#ifndef COAP_DEFAULT_ACK_TIMEOUT -/** - * Number of seconds when to expect an ACK or a response to an - * outstanding CON message. - */ -#define COAP_DEFAULT_ACK_TIMEOUT 2 /* see RFC 7252, Section 4.8 */ -#endif - -#ifndef COAP_DEFAULT_ACK_RANDOM_FACTOR -/** - * A factor that is used to randomize the wait time before a message - * is retransmitted to prevent synchronization effects. - */ -#define COAP_DEFAULT_ACK_RANDOM_FACTOR 1.5 /* see RFC 7252, Section 4.8 */ -#endif - -#ifndef COAP_DEFAULT_MAX_RETRANSMIT -/** - * Number of message retransmissions before message sending is stopped - */ -#define COAP_DEFAULT_MAX_RETRANSMIT 4 /* see RFC 7252, Section 4.8 */ -#endif - -#ifndef COAP_DEFAULT_NSTART -/** - * The number of simultaneous outstanding interactions that a client - * maintains to a given server. - */ -#define COAP_DEFAULT_NSTART 1 /* see RFC 7252, Section 4.8 */ -#endif - -/** @} */ - -/** - * The number of bits for the fractional part of ACK_TIMEOUT and - * ACK_RANDOM_FACTOR. Must be less or equal 8. - */ -#define FRAC_BITS 6 - -/** - * The maximum number of bits for fixed point integers that are used - * for retransmission time calculation. Currently this must be @c 8. - */ -#define MAX_BITS 8 - -#if FRAC_BITS > 8 -#error FRAC_BITS must be less or equal 8 -#endif - -/** creates a Qx.frac from fval */ -#define Q(frac,fval) ((unsigned short)(((1 << (frac)) * (fval)))) - -/** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_RANDOM_FACTOR */ -#define ACK_RANDOM_FACTOR \ - Q(FRAC_BITS, COAP_DEFAULT_ACK_RANDOM_FACTOR) - -/** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_TIMEOUT */ -#define ACK_TIMEOUT Q(FRAC_BITS, COAP_DEFAULT_ACK_TIMEOUT) - -#if defined(WITH_POSIX) - -time_t clock_offset; - -static inline coap_queue_t * -coap_malloc_node(void) { - return (coap_queue_t *)coap_malloc_type(COAP_NODE, sizeof(coap_queue_t)); -} - -static inline void -coap_free_node(coap_queue_t *node) { - coap_free_type(COAP_NODE, node); -} -#endif /* WITH_POSIX */ -#ifdef WITH_LWIP - -#include - -static void coap_retransmittimer_execute(void *arg); -static void coap_retransmittimer_restart(coap_context_t *ctx); - -static inline coap_queue_t * -coap_malloc_node() { - return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); -} - -static inline void -coap_free_node(coap_queue_t *node) { - memp_free(MEMP_COAP_NODE, node); -} - -#endif /* WITH_LWIP */ -#ifdef WITH_CONTIKI -# ifndef DEBUG -# define DEBUG DEBUG_PRINT -# endif /* DEBUG */ - -#include "mem.h" -#include "net/ip/uip-debug.h" - -clock_time_t clock_offset; - -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) - -void coap_resources_init(); - -unsigned char initialized = 0; -coap_context_t the_coap_context; - -PROCESS(coap_retransmit_process, "message retransmit process"); - -static inline coap_queue_t * -coap_malloc_node() { - return (coap_queue_t *)coap_malloc_type(COAP_NODE, 0); -} - -static inline void -coap_free_node(coap_queue_t *node) { - coap_free_type(COAP_NODE, node); -} -#endif /* WITH_CONTIKI */ - -unsigned int -coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now) { - unsigned int result = 0; - coap_tick_diff_t delta = now - ctx->sendqueue_basetime; - - if (ctx->sendqueue) { - /* delta < 0 means that the new time stamp is before the old. */ - if (delta <= 0) { - ctx->sendqueue->t -= delta; - } else { - /* This case is more complex: The time must be advanced forward, - * thus possibly leading to timed out elements at the queue's - * start. For every element that has timed out, its relative - * time is set to zero and the result counter is increased. */ - - coap_queue_t *q = ctx->sendqueue; - coap_tick_t t = 0; - while (q && (t + q->t < (coap_tick_t)delta)) { - t += q->t; - q->t = 0; - result++; - q = q->next; - } - - /* finally adjust the first element that has not expired */ - if (q) { - q->t = (coap_tick_t)delta - t; - } - } - } - - /* adjust basetime */ - ctx->sendqueue_basetime += delta; - - return result; -} - -int -coap_insert_node(coap_queue_t **queue, coap_queue_t *node) { - coap_queue_t *p, *q; - if ( !queue || !node ) - return 0; - - /* set queue head if empty */ - if ( !*queue ) { - *queue = node; - return 1; - } - - /* replace queue head if PDU's time is less than head's time */ - q = *queue; - if (node->t < q->t) { - node->next = q; - *queue = node; - q->t -= node->t; /* make q->t relative to node->t */ - return 1; - } - - /* search for right place to insert */ - do { - node->t -= q->t; /* make node-> relative to q->t */ - p = q; - q = q->next; - } while (q && q->t <= node->t); - - /* insert new item */ - if (q) { - q->t -= node->t; /* make q->t relative to node->t */ - } - node->next = q; - p->next = node; - return 1; -} - -int -coap_delete_node(coap_queue_t *node) { - if ( !node ) - return 0; - - coap_delete_pdu(node->pdu); - coap_free_node(node); - - return 1; -} - -void -coap_delete_all(coap_queue_t *queue) { - if ( !queue ) - return; - - coap_delete_all( queue->next ); - coap_delete_node( queue ); -} - -coap_queue_t * -coap_new_node(void) { - coap_queue_t *node; - node = coap_malloc_node(); - - if ( ! node ) { -#ifndef NDEBUG - coap_log(LOG_WARNING, "coap_new_node: malloc\n"); -#endif - return NULL; - } - - memset(node, 0, sizeof(*node)); - return node; -} - -coap_queue_t * -coap_peek_next( coap_context_t *context ) { - if ( !context || !context->sendqueue ) - return NULL; - - return context->sendqueue; -} - -coap_queue_t * -coap_pop_next( coap_context_t *context ) { - coap_queue_t *next; - - if ( !context || !context->sendqueue ) - return NULL; - - next = context->sendqueue; - context->sendqueue = context->sendqueue->next; - if (context->sendqueue) { - context->sendqueue->t += next->t; - } - next->next = NULL; - return next; -} - -#ifdef COAP_DEFAULT_WKC_HASHKEY -/** Checks if @p Key is equal to the pre-defined hash key for.well-known/core. */ -#define is_wkc(Key) \ - (memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0) -#else -/* Implements a singleton to store a hash key for the .wellknown/core - * resources. */ -int -is_wkc(coap_key_t k) { - static coap_key_t wkc; - static unsigned char _initialized = 0; - if (!_initialized) { - _initialized = coap_hash_path((unsigned char *)COAP_DEFAULT_URI_WELLKNOWN, - sizeof(COAP_DEFAULT_URI_WELLKNOWN) - 1, wkc); - } - return memcmp(k, wkc, sizeof(coap_key_t)) == 0; -} -#endif - -coap_context_t * -coap_new_context( - const coap_address_t *listen_addr) { - coap_context_t *c; - - if (!listen_addr) { - coap_log(LOG_EMERG, "no listen address specified\n"); - return NULL; - } -#ifdef WITH_CONTIKI - if (initialized) - return NULL; -#endif /* WITH_CONTIKI */ -#ifndef WITH_CONTIKI - c = coap_malloc_type(COAP_CONTEXT, sizeof(coap_context_t)); -#endif /* not WITH_CONTIKI */ - - coap_clock_init(); -#ifdef WITH_LWIP - prng_init(LWIP_RAND()); -#endif /* WITH_LWIP */ -#ifdef WITH_CONTIKI - prng_init((ptrdiff_t)listen_addr ^ clock_offset); -#endif /* WITH_LWIP */ -#ifdef WITH_POSIX - prng_init((unsigned long)listen_addr ^ clock_offset); -#endif /* WITH_POSIX */ - -#ifndef WITH_CONTIKI - if (!c) { -#ifndef NDEBUG - coap_log(LOG_EMERG, "coap_init: malloc:\n"); -#endif - return NULL; - } -#endif /* not WITH_CONTIKI */ -#ifdef WITH_CONTIKI - coap_resources_init(); - coap_memory_init(); - - c = &the_coap_context; - initialized = 1; -#endif /* WITH_CONTIKI */ - - memset(c, 0, sizeof( coap_context_t ) ); - - /* initialize message id */ - prng((unsigned char *)&c->message_id, sizeof(unsigned short)); - - c->endpoint = coap_new_endpoint(listen_addr, COAP_ENDPOINT_NOSEC); - if (c->endpoint == NULL) { - goto onerror; - } -#ifdef WITH_LWIP - c->endpoint->context = c; -#endif - -#ifdef WITH_POSIX - c->sockfd = c->endpoint->handle.fd; -#endif /* WITH_POSIX */ - -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) - c->network_send = coap_network_send; - c->network_read = coap_network_read; -#endif /* WITH_POSIX or WITH_CONTIKI */ - -#ifdef WITH_CONTIKI - process_start(&coap_retransmit_process, (char *)c); - - PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); -#ifndef WITHOUT_OBSERVE - etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND); -#endif /* WITHOUT_OBSERVE */ - /* the retransmit timer must be initialized to some large value */ - etimer_set(&the_coap_context.retransmit_timer, 0xFFFF); - PROCESS_CONTEXT_END(&coap_retransmit_process); -#endif /* WITH_CONTIKI */ - - return c; - - onerror: - coap_free_type(COAP_CONTEXT, c); - return NULL; -} - -void -coap_free_context(coap_context_t *context) { - - if (!context) - return; - - coap_delete_all(context->sendqueue); - -#ifdef WITH_LWIP - context->sendqueue = NULL; - coap_retransmittimer_restart(context); -#endif - - coap_delete_all_resources(context); - - coap_free_endpoint(context->endpoint); -#ifndef WITH_CONTIKI - coap_free_type(COAP_CONTEXT, context); -#endif/* not WITH_CONTIKI */ -#ifdef WITH_CONTIKI - memset(&the_coap_context, 0, sizeof(coap_context_t)); - initialized = 0; -#endif /* WITH_CONTIKI */ -} - -int -coap_option_check_critical(coap_context_t *ctx, - coap_pdu_t *pdu, - coap_opt_filter_t unknown) { - - coap_opt_iterator_t opt_iter; - int ok = 1; - - coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); - - while (coap_option_next(&opt_iter)) { - - /* The following condition makes use of the fact that - * coap_option_getb() returns -1 if type exceeds the bit-vector - * filter. As the vector is supposed to be large enough to hold - * the largest known option, we know that everything beyond is - * bad. - */ - if (opt_iter.type & 0x01) { - /* first check the built-in critical options */ - switch (opt_iter.type) { - case COAP_OPTION_IF_MATCH: - case COAP_OPTION_URI_HOST: - case COAP_OPTION_IF_NONE_MATCH: - case COAP_OPTION_URI_PORT: - case COAP_OPTION_URI_PATH: - case COAP_OPTION_URI_QUERY: - case COAP_OPTION_ACCEPT: - case COAP_OPTION_PROXY_URI: - case COAP_OPTION_PROXY_SCHEME: - case COAP_OPTION_BLOCK2: - case COAP_OPTION_BLOCK1: - break; - default: - if (coap_option_filter_get(ctx->known_options, opt_iter.type) <= 0) { - debug("unknown critical option %d\n", opt_iter.type); - ok = 0; - - /* When opt_iter.type is beyond our known option range, - * coap_option_filter_set() will return -1 and we are safe to leave - * this loop. */ - if (coap_option_filter_set(unknown, opt_iter.type) == -1) { - break; - } - } - } - } - } - - return ok; -} - -void -coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, - coap_tid_t *id) { - coap_key_t h; - - memset(h, 0, sizeof(coap_key_t)); - - /* Compare the transport address. */ - -#ifdef WITH_POSIX - switch (peer->addr.sa.sa_family) { - case AF_INET: - coap_hash((const unsigned char *)&peer->addr.sin.sin_port, - sizeof(peer->addr.sin.sin_port), h); - coap_hash((const unsigned char *)&peer->addr.sin.sin_addr, - sizeof(peer->addr.sin.sin_addr), h); - break; -#if COAP_IPV6 - case AF_INET6: - coap_hash((const unsigned char *)&peer->addr.sin6.sin6_port, - sizeof(peer->addr.sin6.sin6_port), h); - coap_hash((const unsigned char *)&peer->addr.sin6.sin6_addr, - sizeof(peer->addr.sin6.sin6_addr), h); - break; -#endif - default: - return; - } -#endif -#if defined(WITH_LWIP) || defined(WITH_CONTIKI) - /* FIXME: with lwip, we can do better */ - coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h); - coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h); -#endif /* WITH_LWIP || WITH_CONTIKI */ - - coap_hash((const unsigned char *)&pdu->hdr->id, sizeof(unsigned short), h); - - *id = (((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3])) & INT_MAX; -} - -coap_tid_t -coap_send_ack(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *request) { - coap_pdu_t *response; - coap_tid_t result = COAP_INVALID_TID; - - if (request && request->hdr->type == COAP_MESSAGE_CON) { - response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id, - sizeof(coap_pdu_t)); - if (response) { - result = coap_send(context, local_interface, dst, response); - coap_delete_pdu(response); - } - } - return result; -} - -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) -static coap_tid_t -coap_send_impl(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu) { - ssize_t bytes_written; - coap_tid_t id = COAP_INVALID_TID; - - if ( !context || !dst || !pdu ) - return id; - - /* Do not send error responses for requests that were received via - * IP multicast. - * FIXME: If No-Response option indicates interest, these responses - * must not be dropped. */ - if (coap_is_mcast(&local_interface->addr) && - COAP_RESPONSE_CLASS(pdu->hdr->code) > 2) { - return COAP_DROPPED_RESPONSE; - } - - bytes_written = context->network_send(context, local_interface, dst, - (unsigned char *)pdu->hdr, pdu->length); - - if (bytes_written >= 0) { - coap_transaction_id(dst, pdu, &id); - } else { - coap_log(LOG_CRIT, "coap_send_impl: %s\n", strerror(errno)); - } - - return id; -} -#endif /* WITH_POSIX */ -#ifdef WITH_LWIP -coap_tid_t -coap_send_impl(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu) { - coap_tid_t id = COAP_INVALID_TID; - - if ( !context || !dst || !pdu ) - { - return id; - } - - /* FIXME: we can't check this here with the existing infrastructure, but we - * should actually check that the pdu is not held by anyone but us. the - * respective pbuf is already exclusively owned by the pdu. */ - - pbuf_realloc(pdu->pbuf, pdu->length); - - coap_transaction_id(dst, pdu, &id); - - udp_sendto(context->endpoint->pcb, pdu->pbuf, - &dst->addr, dst->port); - - return id; -} -#endif /* WITH_LWIP */ - -coap_tid_t -coap_send(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu) { - return coap_send_impl(context, local_interface, dst, pdu); -} - -coap_tid_t -coap_send_error(coap_context_t *context, - coap_pdu_t *request, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char code, - coap_opt_filter_t opts) { - coap_pdu_t *response; - coap_tid_t result = COAP_INVALID_TID; - - assert(request); - assert(dst); - - response = coap_new_error_response(request, code, opts); - if (response) { - result = coap_send(context, local_interface, dst, response); - coap_delete_pdu(response); - } - - return result; -} - -coap_tid_t -coap_send_message_type(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *request, - unsigned char type) { - coap_pdu_t *response; - coap_tid_t result = COAP_INVALID_TID; - - if (request) { - response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t)); - if (response) { - result = coap_send(context, local_interface, dst, response); - coap_delete_pdu(response); - } - } - return result; -} - -/** - * Calculates the initial timeout based on the global CoAP transmission - * parameters ACK_TIMEOUT, ACK_RANDOM_FACTOR, and COAP_TICKS_PER_SECOND. - * The calculation requires ACK_TIMEOUT and ACK_RANDOM_FACTOR to be in - * Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r - * is interpreted as the fractional part of a Q0.MAX_BITS random value. - * - * @param r random value as fractional part of a Q0.MAX_BITS fixed point - * value - * @return COAP_TICKS_PER_SECOND * ACK_TIMEOUT * (1 + (ACK_RANDOM_FACTOR - 1) * r) - */ -static inline unsigned int -calc_timeout(unsigned char r) { - unsigned int result; - - /* The integer 1.0 as a Qx.FRAC_BITS */ -#define FP1 Q(FRAC_BITS, 1) - - /* rounds val up and right shifts by frac positions */ -#define SHR_FP(val,frac) (((val) + (1 << ((frac) - 1))) >> (frac)) - - /* Inner term: multiply ACK_RANDOM_FACTOR by Q0.MAX_BITS[r] and - * make the result a rounded Qx.FRAC_BITS */ - result = SHR_FP((ACK_RANDOM_FACTOR - FP1) * r, MAX_BITS); - - /* Add 1 to the inner term and multiply with ACK_TIMEOUT, then - * make the result a rounded Qx.FRAC_BITS */ - result = SHR_FP(((result + FP1) * ACK_TIMEOUT), FRAC_BITS); - - /* Multiply with COAP_TICKS_PER_SECOND to yield system ticks - * (yields a Qx.FRAC_BITS) and shift to get an integer */ - return SHR_FP((COAP_TICKS_PER_SECOND * result), FRAC_BITS); - -#undef FP1 -#undef SHR_FP -} - -coap_tid_t -coap_send_confirmed(coap_context_t *context, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - coap_pdu_t *pdu) { - coap_queue_t *node; - coap_tick_t now; - unsigned char r; - - node = coap_new_node(); - if (!node) { - debug("coap_send_confirmed: insufficient memory\n"); - return COAP_INVALID_TID; - } - - node->id = coap_send_impl(context, local_interface, dst, pdu); - if (COAP_INVALID_TID == node->id) { - debug("coap_send_confirmed: error sending pdu\n"); - coap_free_node(node); - return COAP_INVALID_TID; - } - - prng((unsigned char *)&r,sizeof(r)); - - /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */ - node->timeout = calc_timeout(r); - - node->local_if = *local_interface; - memcpy(&node->remote, dst, sizeof(coap_address_t)); - node->pdu = pdu; - - /* Set timer for pdu retransmission. If this is the first element in - * the retransmission queue, the base time is set to the current - * time and the retransmission time is node->timeout. If there is - * already an entry in the sendqueue, we must check if this node is - * to be retransmitted earlier. Therefore, node->timeout is first - * normalized to the base time and then inserted into the queue with - * an adjusted relative time. - */ - coap_ticks(&now); - if (context->sendqueue == NULL) { - node->t = node->timeout; - context->sendqueue_basetime = now; - } else { - /* make node->t relative to context->sendqueue_basetime */ - node->t = (now - context->sendqueue_basetime) + node->timeout; - } - - coap_insert_node(&context->sendqueue, node); - -#ifdef WITH_LWIP - if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ - coap_retransmittimer_restart(context); -#endif - -#ifdef WITH_CONTIKI - { /* (re-)initialize retransmission timer */ - coap_queue_t *nextpdu; - - nextpdu = coap_peek_next(context); - assert(nextpdu); /* we have just inserted a node */ - - /* must set timer within the context of the retransmit process */ - PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); - etimer_set(&context->retransmit_timer, nextpdu->t); - PROCESS_CONTEXT_END(&coap_retransmit_process); - } -#endif /* WITH_CONTIKI */ - - return node->id; -} - -coap_tid_t -coap_retransmit(coap_context_t *context, coap_queue_t *node) { - if (!context || !node) - return COAP_INVALID_TID; - - /* re-initialize timeout when maximum number of retransmissions are not reached yet */ - if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) { - node->retransmit_cnt++; - node->t = node->timeout << node->retransmit_cnt; - coap_insert_node(&context->sendqueue, node); -#ifdef WITH_LWIP - if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ - coap_retransmittimer_restart(context); -#endif - - debug("** retransmission #%d of transaction %d\n", - node->retransmit_cnt, ntohs(node->pdu->hdr->id)); - - node->id = coap_send_impl(context, &node->local_if, - &node->remote, node->pdu); - return node->id; - } - - /* no more retransmissions, remove node from system */ - -#ifndef WITH_CONTIKI - debug("** removed transaction %d\n", ntohs(node->id)); -#endif - -#ifndef WITHOUT_OBSERVE - /* Check if subscriptions exist that should be canceled after - COAP_MAX_NOTIFY_FAILURES */ - if (node->pdu->hdr->code >= 64) { - str token = { 0, NULL }; - - token.length = node->pdu->hdr->token_length; - token.s = node->pdu->hdr->token; - - coap_handle_failed_notify(context, &node->remote, &token); - } -#endif /* WITHOUT_OBSERVE */ - - /* And finally delete the node */ - coap_delete_node( node ); - return COAP_INVALID_TID; -} - -void coap_dispatch(coap_context_t *context, coap_queue_t *rcvd); - -#ifndef WITH_LWIP -/* WITH_LWIP, this is handled by coap_recv in a different way */ -int -coap_read( coap_context_t *ctx ) { - ssize_t bytes_read = -1; - coap_packet_t *packet; - coap_address_t src; - int result = -1; /* the value to be returned */ - - coap_address_init(&src); - - bytes_read = ctx->network_read(ctx->endpoint, &packet); - - if ( bytes_read < 0 ) { - warn("coap_read: recvfrom"); - } else { - result = coap_handle_message(ctx, packet); - } - - coap_free_packet(packet); - - return result; -} -#endif /* not WITH_LWIP */ - -int -coap_handle_message(coap_context_t *ctx, - coap_packet_t *packet) { - /* const coap_address_t *remote, */ - /* unsigned char *msg, size_t msg_len) { */ - unsigned char *msg; - size_t msg_len; - coap_queue_t *node; - - /* the negated result code */ - enum result_t { RESULT_OK, RESULT_ERR_EARLY, RESULT_ERR }; - int result = RESULT_ERR_EARLY; - - coap_packet_get_memmapped(packet, &msg, &msg_len); - - if (msg_len < sizeof(coap_hdr_t)) { - debug("coap_handle_message: discarded invalid frame\n" ); - goto error_early; - } - - /* check version identifier */ - if (((*msg >> 6) & 0x03) != COAP_DEFAULT_VERSION) { - debug("coap_handle_message: unknown protocol version %d\n", (*msg >> 6) & 0x03); - goto error_early; - } - - node = coap_new_node(); - if (!node) { - goto error_early; - } - - /* from this point, the result code indicates that */ - result = RESULT_ERR; - -#ifdef WITH_LWIP - node->pdu = coap_pdu_from_pbuf(coap_packet_extract_pbuf(packet)); -#else - node->pdu = coap_pdu_init(0, 0, 0, msg_len); -#endif - if (!node->pdu) { - goto error; - } - - if (!coap_pdu_parse(msg, msg_len, node->pdu)) { - warn("discard malformed PDU\n"); - goto error; - } - - coap_ticks(&node->t); - - coap_packet_populate_endpoint(packet, &node->local_if); - coap_packet_copy_source(packet, &node->remote); - - /* and add new node to receive queue */ - coap_transaction_id(&node->remote, node->pdu, &node->id); - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - /** @FIXME get debug to work again ** - unsigned char addr[INET6_ADDRSTRLEN+8], localaddr[INET6_ADDRSTRLEN+8]; - if (coap_print_addr(remote, addr, INET6_ADDRSTRLEN+8) && - coap_print_addr(&packet->dst, localaddr, INET6_ADDRSTRLEN+8) ) - debug("** received %d bytes from %s on interface %s:\n", - (int)msg_len, addr, localaddr); - - */ - coap_show_pdu(node->pdu); - } -#endif - - coap_dispatch(ctx, node); - return -RESULT_OK; - - error: - /* FIXME: send back RST? */ - coap_delete_node(node); - return -result; - - error_early: - return -result; -} - -int -coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node) { - coap_queue_t *p, *q; - - if ( !queue || !*queue) - return 0; - - /* replace queue head if PDU's time is less than head's time */ - - if ( id == (*queue)->id ) { /* found transaction */ - *node = *queue; - *queue = (*queue)->next; - if (*queue) { /* adjust relative time of new queue head */ - (*queue)->t += (*node)->t; - } - (*node)->next = NULL; - /* coap_delete_node( q ); */ - debug("*** removed transaction %u\n", id); - return 1; - } - - /* search transaction to remove (only first occurence will be removed) */ - q = *queue; - do { - p = q; - q = q->next; - } while ( q && id != q->id ); - - if ( q ) { /* found transaction */ - p->next = q->next; - if (p->next) { /* must update relative time of p->next */ - p->next->t += q->t; - } - q->next = NULL; - *node = q; - /* coap_delete_node( q ); */ - debug("*** removed transaction %u\n", id); - return 1; - } - - return 0; - -} - -static inline int -token_match(const unsigned char *a, size_t alen, - const unsigned char *b, size_t blen) { - return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); -} - -void -coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst, - const unsigned char *token, size_t token_length) { - /* cancel all messages in sendqueue that are for dst - * and use the specified token */ - coap_queue_t *p, *q; - - while (context->sendqueue && - coap_address_equals(dst, &context->sendqueue->remote) && - token_match(token, token_length, - context->sendqueue->pdu->hdr->token, - context->sendqueue->pdu->hdr->token_length)) { - q = context->sendqueue; - context->sendqueue = q->next; - debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); - coap_delete_node(q); - } - - if (!context->sendqueue) - return; - - p = context->sendqueue; - q = p->next; - - /* when q is not NULL, it does not match (dst, token), so we can skip it */ - while (q) { - if (coap_address_equals(dst, &q->remote) && - token_match(token, token_length, - q->pdu->hdr->token, q->pdu->hdr->token_length)) { - p->next = q->next; - debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); - coap_delete_node(q); - q = p->next; - } else { - p = q; - q = q->next; - } - } -} - -coap_queue_t * -coap_find_transaction(coap_queue_t *queue, coap_tid_t id) { - while (queue && queue->id != id) - queue = queue->next; - - return queue; -} - -coap_pdu_t * -coap_new_error_response(coap_pdu_t *request, unsigned char code, - coap_opt_filter_t opts) { - coap_opt_iterator_t opt_iter; - coap_pdu_t *response; - size_t size = sizeof(coap_hdr_t) + request->hdr->token_length; - int type; - coap_opt_t *option; - unsigned short opt_type = 0; /* used for calculating delta-storage */ - -#if COAP_ERROR_PHRASE_LENGTH > 0 - char *phrase = coap_response_phrase(code); - - /* Need some more space for the error phrase and payload start marker */ - if (phrase) - size += strlen(phrase) + 1; -#endif - - assert(request); - - /* cannot send ACK if original request was not confirmable */ - type = request->hdr->type == COAP_MESSAGE_CON - ? COAP_MESSAGE_ACK - : COAP_MESSAGE_NON; - - /* Estimate how much space we need for options to copy from - * request. We always need the Token, for 4.02 the unknown critical - * options must be included as well. */ - coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */ - - coap_option_iterator_init(request, &opt_iter, opts); - - /* Add size of each unknown critical option. As known critical - options as well as elective options are not copied, the delta - value might grow. - */ - while((option = coap_option_next(&opt_iter))) { - unsigned short delta = opt_iter.type - opt_type; - /* calculate space required to encode (opt_iter.type - opt_type) */ - if (delta < 13) { - size++; - } else if (delta < 269) { - size += 2; - } else { - size += 3; - } - - /* add coap_opt_length(option) and the number of additional bytes - * required to encode the option length */ - - size += coap_opt_length(option); - switch (*option & 0x0f) { - case 0x0e: - size++; - /* fall through */ - case 0x0d: - size++; - break; - default: - ; - } - - opt_type = opt_iter.type; - } - - /* Now create the response and fill with options and payload data. */ - response = coap_pdu_init(type, code, request->hdr->id, size); - if (response) { - /* copy token */ - if (!coap_add_token(response, request->hdr->token_length, - request->hdr->token)) { - debug("cannot add token to error response\n"); - coap_delete_pdu(response); - return NULL; - } - - /* copy all options */ - coap_option_iterator_init(request, &opt_iter, opts); - while((option = coap_option_next(&opt_iter))) - coap_add_option(response, opt_iter.type, - COAP_OPT_LENGTH(option), - COAP_OPT_VALUE(option)); - -#if COAP_ERROR_PHRASE_LENGTH > 0 - /* note that diagnostic messages do not need a Content-Format option. */ - if (phrase) - coap_add_data(response, strlen(phrase), (unsigned char *)phrase); -#endif - } - - return response; -} - -/** - * Quick hack to determine the size of the resource description for - * .well-known/core. - */ -static inline size_t -get_wkc_len(coap_context_t *context, coap_opt_t *query_filter) { - unsigned char buf[1]; - size_t len = 0; - - if (coap_print_wellknown(context, buf, &len, UINT_MAX, query_filter) - & COAP_PRINT_STATUS_ERROR) { - warn("cannot determine length of /.well-known/core\n"); - return 0; - } - - debug("get_wkc_len: coap_print_wellknown() returned %zu\n", len); - - return len; -} - -#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4))) - -coap_pdu_t * -coap_wellknown_response(coap_context_t *context, coap_pdu_t *request) { - coap_pdu_t *resp; - coap_opt_iterator_t opt_iter; - size_t len, wkc_len; - unsigned char buf[2]; - int result = 0; - int need_block2 = 0; /* set to 1 if Block2 option is required */ - coap_block_t block; - coap_opt_t *query_filter; - size_t offset = 0; - - resp = coap_pdu_init(request->hdr->type == COAP_MESSAGE_CON - ? COAP_MESSAGE_ACK - : COAP_MESSAGE_NON, - COAP_RESPONSE_CODE(205), - request->hdr->id, COAP_MAX_PDU_SIZE); - if (!resp) { - debug("coap_wellknown_response: cannot create PDU\n"); - return NULL; - } - - if (!coap_add_token(resp, request->hdr->token_length, request->hdr->token)) { - debug("coap_wellknown_response: cannot add token\n"); - goto error; - } - - query_filter = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); - wkc_len = get_wkc_len(context, query_filter); - - /* The value of some resources is undefined and get_wkc_len will return 0.*/ - if (wkc_len == 0){ - debug("coap_wellknown_response: undefined resource\n"); - /* set error code 4.00 Bad Request*/ - resp->hdr->code = COAP_RESPONSE_CODE(400); - resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length; - return resp; - } - - /* check whether the request contains the Block2 option */ - if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) { - debug("create block\n"); - offset = block.num << (block.szx + 4); - if (block.szx > 6) { /* invalid, MUST lead to 4.00 Bad Request */ - resp->hdr->code = COAP_RESPONSE_CODE(400); - return resp; - } else if (block.szx > COAP_MAX_BLOCK_SZX) { - block.szx = COAP_MAX_BLOCK_SZX; - block.num = offset >> (block.szx + 4); - } - - need_block2 = 1; - } - - /* Check if there is sufficient space to add Content-Format option - * and data. We do this before adding the Content-Format option to - * avoid sending error responses with that option but no actual - * content. */ - if (resp->max_size <= (size_t)resp->length + 3) { - debug("coap_wellknown_response: insufficient storage space\n"); - goto error; - } - - /* Add Content-Format. As we have checked for available storage, - * nothing should go wrong here. */ - assert(coap_encode_var_bytes(buf, - COAP_MEDIATYPE_APPLICATION_LINK_FORMAT) == 1); - coap_add_option(resp, COAP_OPTION_CONTENT_FORMAT, - coap_encode_var_bytes(buf, - COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); - - /* check if Block2 option is required even if not requested */ - if (!need_block2 && (resp->max_size - (size_t)resp->length < wkc_len)) { - assert(resp->length <= resp->max_size); - const size_t payloadlen = resp->max_size - resp->length; - /* yes, need block-wise transfer */ - block.num = 0; - block.m = 0; /* the M bit is set by coap_write_block_opt() */ - block.szx = COAP_MAX_BLOCK_SZX; - while (payloadlen < SZX_TO_BYTES(block.szx)) { - if (block.szx == 0) { - debug("coap_wellknown_response: message to small even for szx == 0\n"); - goto error; - } else { - block.szx--; - } - } - - need_block2 = 1; - } - - /* write Block2 option if necessary */ - if (need_block2) { - if (coap_write_block_opt(&block, COAP_OPTION_BLOCK2, resp, wkc_len) < 0) { - debug("coap_wellknown_response: cannot add Block2 option\n"); - goto error; - } - } - - /* Manually set payload of response to let print_wellknown() write, - * into our buffer without copying data. */ - - resp->data = (unsigned char *)resp->hdr + resp->length; - *resp->data = COAP_PAYLOAD_START; - resp->data++; - resp->length++; - len = need_block2 ? SZX_TO_BYTES(block.szx) : resp->max_size - resp->length; - - result = coap_print_wellknown(context, resp->data, &len, offset, query_filter); - if ((result & COAP_PRINT_STATUS_ERROR) != 0) { - debug("coap_print_wellknown failed\n"); - goto error; - } - - resp->length += COAP_PRINT_OUTPUT_LENGTH(result); - return resp; - - error: - /* set error code 5.03 and remove all options and data from response */ - resp->hdr->code = COAP_RESPONSE_CODE(503); - resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length; - return resp; -} - -/** - * This function cancels outstanding messages for the remote peer and - * token specified in @p sent. Any observation relationship for - * sent->remote and the token are removed. Calling this function is - * required when receiving an RST message (usually in response to a - * notification) or a GET request with the Observe option set to 1. - * - * This function returns @c 0 when the token is unknown with this - * peer, or a value greater than zero otherwise. - */ -static int -coap_cancel(coap_context_t *context, const coap_queue_t *sent) { -#ifndef WITHOUT_OBSERVE - str token = { 0, NULL }; - int num_cancelled = 0; /* the number of observers cancelled */ - - /* remove observer for this resource, if any - * get token from sent and try to find a matching resource. Uh! - */ - - COAP_SET_STR(&token, sent->pdu->hdr->token_length, sent->pdu->hdr->token); - - RESOURCES_ITER(context->resources, r) { - num_cancelled += coap_delete_observer(r, &sent->remote, &token); - coap_cancel_all_messages(context, &sent->remote, token.s, token.length); - } - - return num_cancelled; -#else /* WITOUT_OBSERVE */ - return 0; -#endif /* WITOUT_OBSERVE */ -} - -/** - * Internal flags to control the treatment of responses (specifically - * in presence of the No-Response option). - */ -enum respond_t { RESPONSE_DEFAULT, RESPONSE_DROP, RESPONSE_SEND }; - -/** - * Checks for No-Response option in given @p request and - * returns @c 1 if @p response should be suppressed - * according to RFC 7967. - * - * The value of the No-Response option is encoded as - * follows: - * - * +-------+-----------------------+-----------------------------------+ - * | Value | Binary Representation | Description | - * +-------+-----------------------+-----------------------------------+ - * | 0 | | Interested in all responses. | - * +-------+-----------------------+-----------------------------------+ - * | 2 | 00000010 | Not interested in 2.xx responses. | - * +-------+-----------------------+-----------------------------------+ - * | 8 | 00001000 | Not interested in 4.xx responses. | - * +-------+-----------------------+-----------------------------------+ - * | 16 | 00010000 | Not interested in 5.xx responses. | - * +-------+-----------------------+-----------------------------------+ - * - * @param request The CoAP request to check for the No-Response option. - * This parameter must not be NULL. - * @param response The response that is potentially suppressed. - * This parameter must not be NULL. - * @return RESPONSE_DEFAULT when no special treatment is requested, - * RESPONSE_DROP when the response must be discarded, or - * RESPONSE_SEND when the response must be sent. - */ -static enum respond_t -no_response(coap_pdu_t *request, coap_pdu_t *response) { - coap_opt_t *nores; - coap_opt_iterator_t opt_iter; - uint8_t val = 0; - - assert(request); - assert(response); - - if (COAP_RESPONSE_CLASS(response->hdr->code) > 0) { - nores = coap_check_option(request, COAP_OPTION_NORESPONSE, &opt_iter); - - if (nores) { - val = coap_decode_var_bytes(coap_opt_value(nores), coap_opt_length(nores)); - - /* The response should be dropped when the bit corresponding to - * the response class is set (cf. table in funtion - * documentation). When a No-Response option is present and the - * bit is not set, the sender explicitly indicates interest in - * this response. */ - if (((1 << (COAP_RESPONSE_CLASS(response->hdr->code) - 1)) & val) > 0) { - return RESPONSE_DROP; - } else { - return RESPONSE_SEND; - } - } - } - - /* Default behavior applies when we are not dealing with a response - * (class == 0) or the request did not contain a No-Response option. - */ - return RESPONSE_DEFAULT; -} - -#define WANT_WKC(Pdu,Key) \ - (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key)) - -static void -handle_request(coap_context_t *context, coap_queue_t *node) { - coap_method_handler_t h = NULL; - coap_pdu_t *response = NULL; - coap_opt_filter_t opt_filter; - coap_resource_t *resource; - coap_key_t key; - /* The respond field indicates whether a response must be treated - * specially due to a No-Response option that declares disinterest - * or interest in a specific response class. DEFAULT indicates that - * No-Response has not been specified. */ - enum respond_t respond = RESPONSE_DEFAULT; - - coap_option_filter_clear(opt_filter); - - /* try to find the resource from the request URI */ - coap_hash_request_uri(node->pdu, key); - resource = coap_get_resource_from_key(context, key); - - if (!resource) { - /* The resource was not found. Check if the request URI happens to - * be the well-known URI. In that case, we generate a default - * response, otherwise, we return 4.04 */ - - if (is_wkc(key)) { /* request for .well-known/core */ - if (node->pdu->hdr->code == COAP_REQUEST_GET) { /* GET */ - info("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); - response = coap_wellknown_response(context, node->pdu); - } else { - debug("method not allowed for .well-known/core\n"); - response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), - opt_filter); - } - } else { /* request for any another resource, return 4.04 */ - - debug("request for unknown resource 0x%02x%02x%02x%02x, return 4.04\n", - key[0], key[1], key[2], key[3]); - response = - coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(404), - opt_filter); - } - - if (response - && (no_response(node->pdu, response) != RESPONSE_DROP) - && (coap_send(context, &node->local_if, - &node->remote, response) == COAP_INVALID_TID)) { - warn("cannot send response for transaction %u\n", node->id); - } - coap_delete_pdu(response); - response = NULL; - - return; - } - - /* the resource was found, check if there is a registered handler */ - if ((size_t)node->pdu->hdr->code - 1 < - sizeof(resource->handler)/sizeof(coap_method_handler_t)) - h = resource->handler[node->pdu->hdr->code - 1]; - - if (h) { - debug("call custom handler for resource 0x%02x%02x%02x%02x\n", - key[0], key[1], key[2], key[3]); - response = coap_pdu_init(node->pdu->hdr->type == COAP_MESSAGE_CON - ? COAP_MESSAGE_ACK - : COAP_MESSAGE_NON, - 0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE); - - /* Implementation detail: coap_add_token() immediately returns 0 - if response == NULL */ - if (coap_add_token(response, node->pdu->hdr->token_length, - node->pdu->hdr->token)) { - str token = { node->pdu->hdr->token_length, node->pdu->hdr->token }; - coap_opt_iterator_t opt_iter; - coap_opt_t *observe = NULL; - int observe_action = COAP_OBSERVE_CANCEL; - - /* check for Observe option */ - if (resource->observable) { - observe = coap_check_option(node->pdu, COAP_OPTION_OBSERVE, &opt_iter); - if (observe) { - observe_action = - coap_decode_var_bytes(coap_opt_value(observe), - coap_opt_length(observe)); - - if ((observe_action & COAP_OBSERVE_CANCEL) == 0) { - coap_subscription_t *subscription; - - coap_log(LOG_DEBUG, "create new subscription\n"); - subscription = coap_add_observer(resource, &node->local_if, - &node->remote, &token); - if (subscription) { - coap_touch_observer(context, &node->remote, &token); - } - } else { - coap_log(LOG_DEBUG, "removed observer\n"); - coap_delete_observer(resource, &node->remote, &token); - } - } - } - - h(context, resource, &node->local_if, &node->remote, - node->pdu, &token, response); - - respond = no_response(node->pdu, response); - if (respond != RESPONSE_DROP) { - if (observe && (COAP_RESPONSE_CLASS(response->hdr->code) > 2)) { - coap_log(LOG_DEBUG, "removed observer\n"); - coap_delete_observer(resource, &node->remote, &token); - } - - /* If original request contained a token, and the registered - * application handler made no changes to the response, then - * this is an empty ACK with a token, which is a malformed - * PDU */ - if ((response->hdr->type == COAP_MESSAGE_ACK) - && (response->hdr->code == 0)) { - /* Remove token from otherwise-empty acknowledgment PDU */ - response->hdr->token_length = 0; - response->length = sizeof(coap_hdr_t); - } - - if ((respond == RESPONSE_SEND) - || /* RESPOND_DEFAULT */ - (response->hdr->type != COAP_MESSAGE_NON || - (response->hdr->code >= 64 - && !coap_mcast_interface(&node->local_if)))) { - - if (coap_send(context, &node->local_if, - &node->remote, response) == COAP_INVALID_TID) { - debug("cannot send response for message %d\n", node->pdu->hdr->id); - } - } - } - coap_delete_pdu(response); - response = NULL; - } else { - warn("cannot generate response\r\n"); - } - } else { - if (WANT_WKC(node->pdu, key)) { - debug("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); - response = coap_wellknown_response(context, node->pdu); - debug("have wellknown response %p\n", (void *)response); - } else - response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), - opt_filter); - - if (response && (no_response(node->pdu, response) != RESPONSE_DROP)) { - if (coap_send(context, &node->local_if, &node->remote, - response) == COAP_INVALID_TID) { - debug("cannot send response for transaction %u\n", node->id); - } - } - coap_delete_pdu(response); - response = NULL; - } - - assert(response == NULL); -} - -static inline void -handle_response(coap_context_t *context, - coap_queue_t *sent, coap_queue_t *rcvd) { - - coap_send_ack(context, &rcvd->local_if, &rcvd->remote, rcvd->pdu); - - /* In a lossy context, the ACK of a separate response may have - * been lost, so we need to stop retransmitting requests with the - * same token. - */ - coap_cancel_all_messages(context, &rcvd->remote, - rcvd->pdu->hdr->token, - rcvd->pdu->hdr->token_length); - - /* Call application-specific response handler when available. */ - if (context->response_handler) { - context->response_handler(context, &rcvd->local_if, - &rcvd->remote, sent ? sent->pdu : NULL, - rcvd->pdu, rcvd->id); - } -} - -static inline int -#ifdef __GNUC__ -handle_locally(coap_context_t *context __attribute__ ((unused)), - coap_queue_t *node __attribute__ ((unused))) { -#else /* not a GCC */ -handle_locally(coap_context_t *context, coap_queue_t *node) { -#endif /* GCC */ - /* this function can be used to check if node->pdu is really for us */ - return 1; -} - -void -coap_dispatch(coap_context_t *context, coap_queue_t *rcvd) { - coap_queue_t *sent = NULL; - coap_pdu_t *response; - coap_opt_filter_t opt_filter; - - if (!context) - return; - - memset(opt_filter, 0, sizeof(coap_opt_filter_t)); - - { - /* version has been checked in coap_handle_message() */ - /* if ( rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION ) { */ - /* debug("dropped packet with unknown version %u\n", rcvd->pdu->hdr->version); */ - /* goto cleanup; */ - /* } */ - - switch (rcvd->pdu->hdr->type) { - case COAP_MESSAGE_ACK: - /* find transaction in sendqueue to stop retransmission */ - coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); - - if (rcvd->pdu->hdr->code == 0) - goto cleanup; - - /* if sent code was >= 64 the message might have been a - * notification. Then, we must flag the observer to be alive - * by setting obs->fail_cnt = 0. */ - if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2) { - const str token = - { sent->pdu->hdr->token_length, sent->pdu->hdr->token }; - coap_touch_observer(context, &sent->remote, &token); - } - break; - - case COAP_MESSAGE_RST : - /* We have sent something the receiver disliked, so we remove - * not only the transaction but also the subscriptions we might - * have. */ - -#ifndef WITH_CONTIKI - coap_log(LOG_ALERT, "got RST for message %u\n", ntohs(rcvd->pdu->hdr->id)); -#else /* WITH_CONTIKI */ - coap_log(LOG_ALERT, "got RST for message %u\n", uip_ntohs(rcvd->pdu->hdr->id)); -#endif /* WITH_CONTIKI */ - - /* find transaction in sendqueue to stop retransmission */ - coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); - - if (sent) - coap_cancel(context, sent); - goto cleanup; - - case COAP_MESSAGE_NON : /* check for unknown critical options */ - if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0) - goto cleanup; - break; - - case COAP_MESSAGE_CON : /* check for unknown critical options */ - if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0) { - - /* FIXME: send response only if we have received a request. Otherwise, - * send RST. */ - response = - coap_new_error_response(rcvd->pdu, COAP_RESPONSE_CODE(402), opt_filter); - - if (!response) - warn("coap_dispatch: cannot create error response\n"); - else { - if (coap_send(context, &rcvd->local_if, &rcvd->remote, response) - == COAP_INVALID_TID) { - warn("coap_dispatch: error sending response\n"); - } - coap_delete_pdu(response); - } - - goto cleanup; - } - default: break; - } - - /* Pass message to upper layer if a specific handler was - * registered for a request that should be handled locally. */ - if (handle_locally(context, rcvd)) { - if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr)) - handle_request(context, rcvd); - else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr)) - handle_response(context, sent, rcvd); - else { - debug("dropped message with invalid code (%d.%02d)\n", - COAP_RESPONSE_CLASS(rcvd->pdu->hdr->code), - rcvd->pdu->hdr->code & 0x1f); - - if (!coap_is_mcast(&rcvd->local_if.addr)) { - coap_send_message_type(context, &rcvd->local_if, &rcvd->remote, - rcvd->pdu, COAP_MESSAGE_RST); - } - } - } - - cleanup: - coap_delete_node(sent); - coap_delete_node(rcvd); - } -} - -int -coap_can_exit( coap_context_t *context ) { - return !context || (context->sendqueue == NULL); -} - -#ifdef WITH_CONTIKI - -/*---------------------------------------------------------------------------*/ -/* CoAP message retransmission */ -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_retransmit_process, ev, data) -{ - coap_tick_t now; - coap_queue_t *nextpdu; - - PROCESS_BEGIN(); - - debug("Started retransmit process\r\n"); - - while(1) { - PROCESS_YIELD(); - if (ev == PROCESS_EVENT_TIMER) { - if (etimer_expired(&the_coap_context.retransmit_timer)) { - - nextpdu = coap_peek_next(&the_coap_context); - - coap_ticks(&now); - while (nextpdu && nextpdu->t <= now) { - coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context)); - nextpdu = coap_peek_next(&the_coap_context); - } - - /* need to set timer to some value even if no nextpdu is available */ - etimer_set(&the_coap_context.retransmit_timer, - nextpdu ? nextpdu->t - now : 0xFFFF); - } -#ifndef WITHOUT_OBSERVE - if (etimer_expired(&the_coap_context.notify_timer)) { - coap_check_notify(&the_coap_context); - etimer_reset(&the_coap_context.notify_timer); - } -#endif /* WITHOUT_OBSERVE */ - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ - -#endif /* WITH_CONTIKI */ - -#ifdef WITH_LWIP -/* FIXME: retransmits that are not required any more due to incoming packages - * do *not* get cleared at the moment, the wakeup when the transmission is due - * is silently accepted. this is mainly due to the fact that the required - * checks are similar in two places in the code (when receiving ACK and RST) - * and that they cause more than one patch chunk, as it must be first checked - * whether the sendqueue item to be dropped is the next one pending, and later - * the restart function has to be called. nothing insurmountable, but it can - * also be implemented when things have stabilized, and the performance - * penality is minimal - * - * also, this completely ignores COAP_RESOURCE_CHECK_TIME. - * */ - -static void coap_retransmittimer_execute(void *arg) -{ - coap_context_t *ctx = (coap_context_t*)arg; - coap_tick_t now; - coap_tick_t elapsed; - coap_queue_t *nextinqueue; - - ctx->timer_configured = 0; - - coap_ticks(&now); - - elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */ - - nextinqueue = coap_peek_next(ctx); - while (nextinqueue != NULL) - { - if (nextinqueue->t > elapsed) { - nextinqueue->t -= elapsed; - break; - } else { - elapsed -= nextinqueue->t; - coap_retransmit(ctx, coap_pop_next(ctx)); - nextinqueue = coap_peek_next(ctx); - } - } - - ctx->sendqueue_basetime = now; - - coap_retransmittimer_restart(ctx); -} - -static void coap_retransmittimer_restart(coap_context_t *ctx) -{ - coap_tick_t now, elapsed, delay; - - if (ctx->timer_configured) - { - printf("clearing\n"); - sys_untimeout(coap_retransmittimer_execute, (void*)ctx); - ctx->timer_configured = 0; - } - if (ctx->sendqueue != NULL) - { - coap_ticks(&now); - elapsed = now - ctx->sendqueue_basetime; - if (ctx->sendqueue->t >= elapsed) { - delay = ctx->sendqueue->t - elapsed; - } else { - /* a strange situation, but not completely impossible. - * - * this happens, for example, right after - * coap_retransmittimer_execute, when a retransmission - * was *just not yet* due, and the clock ticked before - * our coap_ticks was called. - * - * not trying to retransmit anything now, as it might - * cause uncontrollable recursion; let's just try again - * with the next main loop run. - * */ - delay = 0; - } - - printf("scheduling for %d ticks\n", delay); - sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx); - ctx->timer_configured = 1; - } -} -#endif diff --git a/components/coap/libcoap/src/option.c b/components/coap/libcoap/src/option.c deleted file mode 100644 index 60c0788d7..000000000 --- a/components/coap/libcoap/src/option.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * option.c -- helpers for handling options in CoAP PDUs - * - * Copyright (C) 2010-2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - - -#include "coap_config.h" - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include - -#include "option.h" -#include "encode.h" /* for coap_fls() */ -#include "debug.h" - -coap_opt_t * -options_start(coap_pdu_t *pdu) { - - if (pdu && pdu->hdr && - (pdu->hdr->token + pdu->hdr->token_length - < (unsigned char *)pdu->hdr + pdu->length)) { - - coap_opt_t *opt = pdu->hdr->token + pdu->hdr->token_length; - return (*opt == COAP_PAYLOAD_START) ? NULL : opt; - - } else - return NULL; -} - -size_t -coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result) { - - const coap_opt_t *opt_start = opt; /* store where parsing starts */ - - assert(opt); assert(result); - -#define ADVANCE_OPT(o,e,step) if ((e) < step) { \ - debug("cannot advance opt past end\n"); \ - return 0; \ - } else { \ - (e) -= step; \ - (o) = ((unsigned char *)(o)) + step; \ - } - - if (length < 1) - return 0; - - result->delta = (*opt & 0xf0) >> 4; - result->length = *opt & 0x0f; - - switch(result->delta) { - case 15: - if (*opt != COAP_PAYLOAD_START) { - debug("ignored reserved option delta 15\n"); - } - return 0; - case 14: - /* Handle two-byte value: First, the MSB + 269 is stored as delta value. - * After that, the option pointer is advanced to the LSB which is handled - * just like case delta == 13. */ - ADVANCE_OPT(opt,length,1); - result->delta = ((*opt & 0xff) << 8) + 269; - if (result->delta < 269) { - debug("delta too large\n"); - return 0; - } - /* fall through */ - case 13: - ADVANCE_OPT(opt,length,1); - result->delta += *opt & 0xff; - break; - - default: - ; - } - - switch(result->length) { - case 15: - debug("found reserved option length 15\n"); - return 0; - case 14: - /* Handle two-byte value: First, the MSB + 269 is stored as delta value. - * After that, the option pointer is advanced to the LSB which is handled - * just like case delta == 13. */ - ADVANCE_OPT(opt,length,1); - result->length = ((*opt & 0xff) << 8) + 269; - /* fall through */ - case 13: - ADVANCE_OPT(opt,length,1); - result->length += *opt & 0xff; - break; - - default: - ; - } - - ADVANCE_OPT(opt,length,1); - /* opt now points to value, if present */ - - result->value = (unsigned char *)opt; - if (length < result->length) { - debug("invalid option length\n"); - return 0; - } - -#undef ADVANCE_OPT - - return (opt + result->length) - opt_start; -} - -coap_opt_iterator_t * -coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, - const coap_opt_filter_t filter) { - assert(pdu); - assert(pdu->hdr); - assert(oi); - - memset(oi, 0, sizeof(coap_opt_iterator_t)); - - oi->next_option = (unsigned char *)pdu->hdr + sizeof(coap_hdr_t) - + pdu->hdr->token_length; - if ((unsigned char *)pdu->hdr + pdu->length <= oi->next_option) { - oi->bad = 1; - return NULL; - } - - assert((sizeof(coap_hdr_t) + pdu->hdr->token_length) <= pdu->length); - - oi->length = pdu->length - (sizeof(coap_hdr_t) + pdu->hdr->token_length); - - if (filter) { - memcpy(oi->filter, filter, sizeof(coap_opt_filter_t)); - oi->filtered = 1; - } - return oi; -} - -static inline int -opt_finished(coap_opt_iterator_t *oi) { - assert(oi); - - if (oi->bad || oi->length == 0 || - !oi->next_option || *oi->next_option == COAP_PAYLOAD_START) { - oi->bad = 1; - } - - return oi->bad; -} - -coap_opt_t * -coap_option_next(coap_opt_iterator_t *oi) { - coap_option_t option; - coap_opt_t *current_opt = NULL; - size_t optsize; - int b; /* to store result of coap_option_getb() */ - - assert(oi); - - if (opt_finished(oi)) - return NULL; - - while (1) { - /* oi->option always points to the next option to deliver; as - * opt_finished() filters out any bad conditions, we can assume that - * oi->option is valid. */ - current_opt = oi->next_option; - - /* Advance internal pointer to next option, skipping any option that - * is not included in oi->filter. */ - optsize = coap_opt_parse(oi->next_option, oi->length, &option); - if (optsize) { - assert(optsize <= oi->length); - - oi->next_option += optsize; - oi->length -= optsize; - - oi->type += option.delta; - } else { /* current option is malformed */ - oi->bad = 1; - return NULL; - } - - /* Exit the while loop when: - * - no filtering is done at all - * - the filter matches for the current option - * - the filter is too small for the current option number - */ - if (!oi->filtered || - (b = coap_option_getb(oi->filter, oi->type)) > 0) - break; - else if (b < 0) { /* filter too small, cannot proceed */ - oi->bad = 1; - return NULL; - } - } - - return current_opt; -} - -coap_opt_t * -coap_check_option(coap_pdu_t *pdu, unsigned short type, - coap_opt_iterator_t *oi) { - coap_opt_filter_t f; - - coap_option_filter_clear(f); - coap_option_setb(f, type); - - coap_option_iterator_init(pdu, oi, f); - - return coap_option_next(oi); -} - -unsigned short -coap_opt_delta(const coap_opt_t *opt) { - unsigned short n; - - n = (*opt++ & 0xf0) >> 4; - - switch (n) { - case 15: /* error */ - warn("coap_opt_delta: illegal option delta\n"); - - /* This case usually should not happen, hence we do not have a - * proper way to indicate an error. */ - return 0; - case 14: - /* Handle two-byte value: First, the MSB + 269 is stored as delta value. - * After that, the option pointer is advanced to the LSB which is handled - * just like case delta == 13. */ - n = ((*opt++ & 0xff) << 8) + 269; - /* fall through */ - case 13: - n += *opt & 0xff; - break; - default: /* n already contains the actual delta value */ - ; - } - - return n; -} - -unsigned short -coap_opt_length(const coap_opt_t *opt) { - unsigned short length; - - length = *opt & 0x0f; - switch (*opt & 0xf0) { - case 0xf0: - debug("illegal option delta\n"); - return 0; - case 0xe0: - ++opt; - /* fall through to skip another byte */ - case 0xd0: - ++opt; - /* fall through to skip another byte */ - default: - ++opt; - } - - switch (length) { - case 0x0f: - debug("illegal option length\n"); - return 0; - case 0x0e: - length = (*opt++ << 8) + 269; - /* fall through */ - case 0x0d: - length += *opt++; - break; - default: - ; - } - return length; -} - -unsigned char * -coap_opt_value(coap_opt_t *opt) { - size_t ofs = 1; - - switch (*opt & 0xf0) { - case 0xf0: - debug("illegal option delta\n"); - return 0; - case 0xe0: - ++ofs; - /* fall through */ - case 0xd0: - ++ofs; - break; - default: - ; - } - - switch (*opt & 0x0f) { - case 0x0f: - debug("illegal option length\n"); - return 0; - case 0x0e: - ++ofs; - /* fall through */ - case 0x0d: - ++ofs; - break; - default: - ; - } - - return (unsigned char *)opt + ofs; -} - -size_t -coap_opt_size(const coap_opt_t *opt) { - coap_option_t option; - - /* we must assume that opt is encoded correctly */ - return coap_opt_parse(opt, (size_t)-1, &option); -} - -size_t -coap_opt_setheader(coap_opt_t *opt, size_t maxlen, - unsigned short delta, size_t length) { - size_t skip = 0; - - assert(opt); - - if (maxlen == 0) /* need at least one byte */ - return 0; - - if (delta < 13) { - opt[0] = delta << 4; - } else if (delta < 270) { - if (maxlen < 2) { - debug("insufficient space to encode option delta %d\n", delta); - return 0; - } - - opt[0] = 0xd0; - opt[++skip] = delta - 13; - } else { - if (maxlen < 3) { - debug("insufficient space to encode option delta %d\n", delta); - return 0; - } - - opt[0] = 0xe0; - opt[++skip] = ((delta - 269) >> 8) & 0xff; - opt[++skip] = (delta - 269) & 0xff; - } - - if (length < 13) { - opt[0] |= length & 0x0f; - } else if (length < 270) { - if (maxlen < skip + 2) { - debug("insufficient space to encode option length %zu\n", length); - return 0; - } - - opt[0] |= 0x0d; - opt[++skip] = length - 13; - } else { - if (maxlen < skip + 3) { - debug("insufficient space to encode option delta %d\n", delta); - return 0; - } - - opt[0] |= 0x0e; - opt[++skip] = ((length - 269) >> 8) & 0xff; - opt[++skip] = (length - 269) & 0xff; - } - - return skip + 1; -} - -size_t -coap_opt_encode(coap_opt_t *opt, size_t maxlen, unsigned short delta, - const unsigned char *val, size_t length) { - size_t l = 1; - - l = coap_opt_setheader(opt, maxlen, delta, length); - assert(l <= maxlen); - - if (!l) { - debug("coap_opt_encode: cannot set option header\n"); - return 0; - } - - maxlen -= l; - opt += l; - - if (maxlen < length) { - debug("coap_opt_encode: option too large for buffer\n"); - return 0; - } - - if (val) /* better be safe here */ - memcpy(opt, val, length); - - return l + length; -} - -/* coap_opt_filter_t has the following internal structure: */ -typedef struct { - uint16_t mask; - -#define LONG_MASK ((1 << COAP_OPT_FILTER_LONG) - 1) -#define SHORT_MASK \ - (~LONG_MASK & ((1 << (COAP_OPT_FILTER_LONG + COAP_OPT_FILTER_SHORT)) - 1)) - - uint16_t long_opts[COAP_OPT_FILTER_LONG]; - uint8_t short_opts[COAP_OPT_FILTER_SHORT]; -} opt_filter; - -/** Returns true iff @p type denotes an option type larger than 255. */ -static inline int -is_long_option(unsigned short type) { return type > 255; } - -/** Operation specifiers for coap_filter_op(). */ -enum filter_op_t { FILTER_SET, FILTER_CLEAR, FILTER_GET }; - -/** - * Applies @p op on @p filter with respect to @p type. The following - * operations are defined: - * - * FILTER_SET: Store @p type into an empty slot in @p filter. Returns - * @c 1 on success, or @c 0 if no spare slot was available. - * - * FILTER_CLEAR: Remove @p type from filter if it exists. - * - * FILTER_GET: Search for @p type in @p filter. Returns @c 1 if found, - * or @c 0 if not found. - * - * @param filter The filter object. - * @param type The option type to set, get or clear in @p filter. - * @param op The operation to apply to @p filter and @p type. - * - * @return 1 on success, and 0 when FILTER_GET yields no - * hit or no free slot is available to store @p type with FILTER_SET. - */ -static int -coap_option_filter_op(coap_opt_filter_t filter, - unsigned short type, - enum filter_op_t op) { - size_t index = 0; - opt_filter *of = (opt_filter *)filter; - uint16_t nr, mask = 0; - - if (is_long_option(type)) { - mask = LONG_MASK; - - for (nr = 1; index < COAP_OPT_FILTER_LONG; nr <<= 1, index++) { - - if (((of->mask & nr) > 0) && (of->long_opts[index] == type)) { - if (op == FILTER_CLEAR) { - of->mask &= ~nr; - } - - return 1; - } - } - } else { - mask = SHORT_MASK; - - for (nr = 1 << COAP_OPT_FILTER_LONG; index < COAP_OPT_FILTER_SHORT; - nr <<= 1, index++) { - - if (((of->mask & nr) > 0) && (of->short_opts[index] == (type & 0xff))) { - if (op == FILTER_CLEAR) { - of->mask &= ~nr; - } - - return 1; - } - } - } - - /* type was not found, so there is nothing to do if op is CLEAR or GET */ - if ((op == FILTER_CLEAR) || (op == FILTER_GET)) { - return 0; - } - - /* handle FILTER_SET: */ - - index = coap_fls(~of->mask & mask); - if (!index) { - return 0; - } - - if (is_long_option(type)) { - of->long_opts[index - 1] = type; - } else { - of->short_opts[index - COAP_OPT_FILTER_LONG - 1] = type; - } - - of->mask |= 1 << (index - 1); - - return 1; -} - -int -coap_option_filter_set(coap_opt_filter_t filter, unsigned short type) { - return coap_option_filter_op(filter, type, FILTER_SET); -} - -int -coap_option_filter_unset(coap_opt_filter_t filter, unsigned short type) { - return coap_option_filter_op(filter, type, FILTER_CLEAR); -} - -int -coap_option_filter_get(const coap_opt_filter_t filter, unsigned short type) { - /* Ugly cast to make the const go away (FILTER_GET wont change filter - * but as _set and _unset do, the function does not take a const). */ - return coap_option_filter_op((uint16_t *)filter, type, FILTER_GET); -} diff --git a/components/coap/libcoap/src/pdu.c b/components/coap/libcoap/src/pdu.c deleted file mode 100644 index ff73d6ab4..000000000 --- a/components/coap/libcoap/src/pdu.c +++ /dev/null @@ -1,433 +0,0 @@ -/* pdu.c -- CoAP message structure - * - * Copyright (C) 2010--2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#include "debug.h" -#include "pdu.h" -#include "option.h" -#include "encode.h" -#include "mem.h" - -void -coap_pdu_clear(coap_pdu_t *pdu, size_t size) { - assert(pdu); - -#ifdef WITH_LWIP - /* the pdu itself is not wiped as opposed to the other implementations, - * because we have to rely on the pbuf to be set there. */ - pdu->hdr = pdu->pbuf->payload; -#else - pdu->max_delta = 0; - pdu->data = NULL; -#endif - memset(pdu->hdr, 0, size); - pdu->max_size = size; - pdu->hdr->version = COAP_DEFAULT_VERSION; - - /* data is NULL unless explicitly set by coap_add_data() */ - pdu->length = sizeof(coap_hdr_t); -} - -#ifdef WITH_LWIP -coap_pdu_t * -coap_pdu_from_pbuf(struct pbuf *pbuf) -{ - if (pbuf == NULL) return NULL; - - LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len); - LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1); - - coap_pdu_t *result = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); - if (!result) { - pbuf_free(pbuf); - return NULL; - } - - memset(result, 0, sizeof(coap_pdu_t)); - - result->max_size = pbuf->tot_len; - result->length = pbuf->tot_len; - result->hdr = pbuf->payload; - result->pbuf = pbuf; - - return result; -} -#endif - -coap_pdu_t * -coap_pdu_init(unsigned char type, unsigned char code, - unsigned short id, size_t size) { - coap_pdu_t *pdu; -#ifdef WITH_LWIP - struct pbuf *p; -#endif - - assert(size <= COAP_MAX_PDU_SIZE); - /* Size must be large enough to fit the header. */ - if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE) - return NULL; - - /* size must be large enough for hdr */ -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) - pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); - if (!pdu) return NULL; - pdu->hdr = coap_malloc_type(COAP_PDU_BUF, size); - if (pdu->hdr == NULL) { - coap_free_type(COAP_PDU, pdu); - pdu = NULL; - } -#endif /* WITH_POSIX or WITH_CONTIKI */ -#ifdef WITH_LWIP - pdu = (coap_pdu_t*)coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); - if (!pdu) return NULL; - p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (p == NULL) { - coap_free_type(COAP_PDU, pdu); - pdu = NULL; - } -#endif - if (pdu) { -#ifdef WITH_LWIP - pdu->pbuf = p; -#endif - coap_pdu_clear(pdu, size); - pdu->hdr->id = id; - pdu->hdr->type = type; - pdu->hdr->code = code; - } - return pdu; -} - -coap_pdu_t * -coap_new_pdu(void) { - coap_pdu_t *pdu; - -#ifndef WITH_CONTIKI - pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE); -#else /* WITH_CONTIKI */ - pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE); -#endif /* WITH_CONTIKI */ - -#ifndef NDEBUG - if (!pdu) - coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n"); -#endif - return pdu; -} - -void -coap_delete_pdu(coap_pdu_t *pdu) { -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) - if (pdu != NULL) { - if (pdu->hdr != NULL) { - coap_free_type(COAP_PDU_BUF, pdu->hdr); - } - coap_free_type(COAP_PDU, pdu); - } -#endif -#ifdef WITH_LWIP - if (pdu != NULL) /* accepting double free as the other implementation accept that too */ - pbuf_free(pdu->pbuf); - coap_free_type(COAP_PDU, pdu); -#endif -} - -int -coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data) { - const size_t HEADERLENGTH = len + 4; - /* must allow for pdu == NULL as callers may rely on this */ - if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH) - return 0; - - pdu->hdr->token_length = len; - if (len) - memcpy(pdu->hdr->token, data, len); - pdu->max_delta = 0; - pdu->length = HEADERLENGTH; - pdu->data = NULL; - - return 1; -} - -/** @FIXME de-duplicate code with coap_add_option_later */ -size_t -coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data) { - size_t optsize; - coap_opt_t *opt; - - assert(pdu); - pdu->data = NULL; - - if (type < pdu->max_delta) { - warn("coap_add_option: options are not in correct order\n"); - return 0; - } - - opt = (unsigned char *)pdu->hdr + pdu->length; - - /* encode option and check length */ - optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, - type - pdu->max_delta, data, len); - - if (!optsize) { - warn("coap_add_option: cannot add option\n"); - /* error */ - return 0; - } else { - pdu->max_delta = type; - pdu->length += optsize; - } - - return optsize; -} - -/** @FIXME de-duplicate code with coap_add_option */ -unsigned char* -coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len) { - size_t optsize; - coap_opt_t *opt; - - assert(pdu); - pdu->data = NULL; - - if (type < pdu->max_delta) { - warn("coap_add_option: options are not in correct order\n"); - return NULL; - } - - opt = (unsigned char *)pdu->hdr + pdu->length; - - /* encode option and check length */ - optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, - type - pdu->max_delta, NULL, len); - - if (!optsize) { - warn("coap_add_option: cannot add option\n"); - /* error */ - return NULL; - } else { - pdu->max_delta = type; - pdu->length += optsize; - } - - return ((unsigned char*)opt) + optsize - len; -} - -int -coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data) { - assert(pdu); - assert(pdu->data == NULL); - - if (len == 0) - return 1; - - if (pdu->length + len + 1 > pdu->max_size) { - warn("coap_add_data: cannot add: data too large for PDU\n"); - assert(pdu->data == NULL); - return 0; - } - - pdu->data = (unsigned char *)pdu->hdr + pdu->length; - *pdu->data = COAP_PAYLOAD_START; - pdu->data++; - - memcpy(pdu->data, data, len); - pdu->length += len + 1; - return 1; -} - -int -coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data) { - assert(pdu); - assert(len); - assert(data); - - if (pdu->data) { - *len = (unsigned char *)pdu->hdr + pdu->length - pdu->data; - *data = pdu->data; - } else { /* no data, clear everything */ - *len = 0; - *data = NULL; - } - - return *data != NULL; -} - -#ifndef SHORT_ERROR_RESPONSE -typedef struct { - unsigned char code; - char *phrase; -} error_desc_t; - -/* if you change anything here, make sure, that the longest string does not - * exceed COAP_ERROR_PHRASE_LENGTH. */ -error_desc_t coap_error[] = { - { COAP_RESPONSE_CODE(201), "Created" }, - { COAP_RESPONSE_CODE(202), "Deleted" }, - { COAP_RESPONSE_CODE(203), "Valid" }, - { COAP_RESPONSE_CODE(204), "Changed" }, - { COAP_RESPONSE_CODE(205), "Content" }, - { COAP_RESPONSE_CODE(231), "Continue" }, - { COAP_RESPONSE_CODE(400), "Bad Request" }, - { COAP_RESPONSE_CODE(401), "Unauthorized" }, - { COAP_RESPONSE_CODE(402), "Bad Option" }, - { COAP_RESPONSE_CODE(403), "Forbidden" }, - { COAP_RESPONSE_CODE(404), "Not Found" }, - { COAP_RESPONSE_CODE(405), "Method Not Allowed" }, - { COAP_RESPONSE_CODE(406), "Not Acceptable" }, - { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" }, - { COAP_RESPONSE_CODE(412), "Precondition Failed" }, - { COAP_RESPONSE_CODE(413), "Request Entity Too Large" }, - { COAP_RESPONSE_CODE(415), "Unsupported Content-Format" }, - { COAP_RESPONSE_CODE(500), "Internal Server Error" }, - { COAP_RESPONSE_CODE(501), "Not Implemented" }, - { COAP_RESPONSE_CODE(502), "Bad Gateway" }, - { COAP_RESPONSE_CODE(503), "Service Unavailable" }, - { COAP_RESPONSE_CODE(504), "Gateway Timeout" }, - { COAP_RESPONSE_CODE(505), "Proxying Not Supported" }, - { 0, NULL } /* end marker */ -}; - -char * -coap_response_phrase(unsigned char code) { - int i; - for (i = 0; coap_error[i].code; ++i) { - if (coap_error[i].code == code) - return coap_error[i].phrase; - } - return NULL; -} -#endif - -/** - * Advances *optp to next option if still in PDU. This function - * returns the number of bytes opt has been advanced or @c 0 - * on error. - */ -static size_t -next_option_safe(coap_opt_t **optp, size_t *length) { - coap_option_t option; - size_t optsize; - - assert(optp); assert(*optp); - assert(length); - - optsize = coap_opt_parse(*optp, *length, &option); - if (optsize) { - assert(optsize <= *length); - - *optp += optsize; - *length -= optsize; - } - - return optsize; -} - -int -coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu) { - coap_opt_t *opt; - - assert(data); - assert(pdu); - - if (pdu->max_size < length) { - debug("insufficient space to store parsed PDU\n"); - return 0; - } - - if (length < sizeof(coap_hdr_t)) { - debug("discarded invalid PDU\n"); - } - -#ifdef WITH_LWIP - /* this verifies that with the classical copy-at-parse-time and lwip's - * zerocopy-into-place approaches, both share the same idea of destination - * addresses */ - LWIP_ASSERT("coap_pdu_parse with unexpected addresses", data == (void*)pdu->hdr); - LWIP_ASSERT("coap_pdu_parse with unexpected length", length == pdu->length); -#else - - pdu->hdr->version = data[0] >> 6; - pdu->hdr->type = (data[0] >> 4) & 0x03; - pdu->hdr->token_length = data[0] & 0x0f; - pdu->hdr->code = data[1]; -#endif - pdu->data = NULL; - - /* sanity checks */ - if (pdu->hdr->code == 0) { - if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length) { - debug("coap_pdu_parse: empty message is not empty\n"); - goto discard; - } - } - - if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length - || pdu->hdr->token_length > 8) { - debug("coap_pdu_parse: invalid Token\n"); - goto discard; - } - -#ifndef WITH_LWIP - /* Copy message id in network byte order, so we can easily write the - * response back to the network. */ - memcpy(&pdu->hdr->id, data + 2, 2); - - /* Append data (including the Token) to pdu structure, if any. */ - if (length > sizeof(coap_hdr_t)) { - memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t)); - } - pdu->length = length; - - /* Finally calculate beginning of data block and thereby check integrity - * of the PDU structure. */ -#endif - - /* skip header + token */ - length -= (pdu->hdr->token_length + sizeof(coap_hdr_t)); - opt = (unsigned char *)(pdu->hdr + 1) + pdu->hdr->token_length; - - while (length && *opt != COAP_PAYLOAD_START) { - if (!next_option_safe(&opt, (size_t *)&length)) { - debug("coap_pdu_parse: drop\n"); - goto discard; - } - } - - /* end of packet or start marker */ - if (length) { - assert(*opt == COAP_PAYLOAD_START); - opt++; length--; - - if (!length) { - debug("coap_pdu_parse: message ending in payload start marker\n"); - goto discard; - } - - debug("set data to %p (pdu ends at %p)\n", (unsigned char *)opt, - (unsigned char *)pdu->hdr + pdu->length); - pdu->data = (unsigned char *)opt; - } - - return 1; - - discard: - return 0; -} diff --git a/components/coap/libcoap/src/resource.c b/components/coap/libcoap/src/resource.c deleted file mode 100644 index 61ab87ca8..000000000 --- a/components/coap/libcoap/src/resource.c +++ /dev/null @@ -1,756 +0,0 @@ -/* resource.c -- generic resource handling - * - * Copyright (C) 2010--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "coap.h" -#include "debug.h" -#include "mem.h" -#include "net.h" -#include "resource.h" -#include "subscribe.h" -#include "utlist.h" - -#ifdef WITH_LWIP -/* mem.h is only needed for the string free calls for - * COAP_ATTR_FLAGS_RELEASE_NAME / COAP_ATTR_FLAGS_RELEASE_VALUE / - * COAP_RESOURCE_FLAGS_RELEASE_URI. not sure what those lines should actually - * do on lwip. */ - -#include - -#define COAP_MALLOC_TYPE(Type) \ - ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) -#define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object) - -#endif - -#ifdef WITH_POSIX - -#define COAP_MALLOC_TYPE(Type) \ - ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) -#define COAP_FREE_TYPE(Type, Object) coap_free(Object) - -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI -#include "memb.h" - -#define COAP_MALLOC_TYPE(Type) \ - ((coap_##Type##_t *)memb_alloc(&(Type##_storage))) -#define COAP_FREE_TYPE(Type, Object) memb_free(&(Type##_storage), (Object)) - -MEMB(subscription_storage, coap_subscription_t, COAP_MAX_SUBSCRIBERS); - -void -coap_resources_init() { - memb_init(&subscription_storage); -} - -static inline coap_subscription_t * -coap_malloc_subscription() { - return memb_alloc(&subscription_storage); -} - -static inline void -coap_free_subscription(coap_subscription_t *subscription) { - memb_free(&subscription_storage, subscription); -} - -#endif /* WITH_CONTIKI */ - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -/* Helper functions for conditional output of character sequences into - * a given buffer. The first Offset characters are skipped. - */ - -/** - * Adds Char to Buf if Offset is zero. Otherwise, Char is not written - * and Offset is decremented. - */ -#define PRINT_WITH_OFFSET(Buf,Offset,Char) \ - if ((Offset) == 0) { \ - (*(Buf)++) = (Char); \ - } else { \ - (Offset)--; \ - } \ - -/** - * Adds Char to Buf if Offset is zero and Buf is less than Bufend. - */ -#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \ - if ((Buf) < (Bufend)) { \ - PRINT_WITH_OFFSET(Buf,Offset,Char); \ - } \ - (Result)++; \ - } - -/** - * Copies at most Length characters of Str to Buf. The first Offset - * characters are skipped. Output may be truncated to Bufend - Buf - * characters. - */ -#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \ - size_t i; \ - for (i = 0; i < (Length); i++) { \ - PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ - } \ - } - -static int -match(const str *text, const str *pattern, int match_prefix, int match_substring) { - assert(text); assert(pattern); - - if (text->length < pattern->length) - return 0; - - if (match_substring) { - unsigned char *next_token = text->s; - size_t remaining_length = text->length; - while (remaining_length) { - size_t token_length; - unsigned char *token = next_token; - next_token = memchr(token, ' ', remaining_length); - - if (next_token) { - token_length = next_token - token; - remaining_length -= (token_length + 1); - next_token++; - } else { - token_length = remaining_length; - remaining_length = 0; - } - - if ((match_prefix || pattern->length == token_length) && - memcmp(token, pattern->s, pattern->length) == 0) - return 1; - } - return 0; - } - - return (match_prefix || pattern->length == text->length) && - memcmp(text->s, pattern->s, pattern->length) == 0; -} - -/** - * Prints the names of all known resources to @p buf. This function - * sets @p buflen to the number of bytes actually written and returns - * @c 1 on succes. On error, the value in @p buflen is undefined and - * the return value will be @c 0. - * - * @param context The context with the resource map. - * @param buf The buffer to write the result. - * @param buflen Must be initialized to the maximum length of @p buf and will be - * set to the length of the well-known response on return. - * @param offset The offset in bytes where the output shall start and is - * shifted accordingly with the characters that have been - * processed. This parameter is used to support the block - * option. - * @param query_filter A filter query according to Link Format - * - * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are - * set to the number of bytes that have actually been written to - * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been - * truncated. - */ -#if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) -coap_print_status_t -coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, - size_t offset, - coap_opt_t *query_filter __attribute__ ((unused))) { -#else /* not a GCC */ -coap_print_status_t -coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, - size_t offset, coap_opt_t *query_filter) { -#endif /* GCC */ - unsigned char *p = buf; - const unsigned char *bufend = buf + *buflen; - size_t left, written = 0; - coap_print_status_t result; - const size_t old_offset = offset; - int subsequent_resource = 0; -#ifndef WITHOUT_QUERY_FILTER - str resource_param = { 0, NULL }, query_pattern = { 0, NULL }; - int flags = 0; /* MATCH_SUBSTRING, MATCH_PREFIX, MATCH_URI */ -#define MATCH_URI 0x01 -#define MATCH_PREFIX 0x02 -#define MATCH_SUBSTRING 0x04 - static const str _rt_attributes[] = { - {2, (unsigned char *)"rt"}, - {2, (unsigned char *)"if"}, - {3, (unsigned char *)"rel"}, - {0, NULL}}; -#endif /* WITHOUT_QUERY_FILTER */ - -#ifndef WITHOUT_QUERY_FILTER - /* split query filter, if any */ - if (query_filter) { - resource_param.s = COAP_OPT_VALUE(query_filter); - while (resource_param.length < COAP_OPT_LENGTH(query_filter) - && resource_param.s[resource_param.length] != '=') - resource_param.length++; - - if (resource_param.length < COAP_OPT_LENGTH(query_filter)) { - const str *rt_attributes; - if (resource_param.length == 4 && - memcmp(resource_param.s, "href", 4) == 0) - flags |= MATCH_URI; - - for (rt_attributes = _rt_attributes; rt_attributes->s; rt_attributes++) { - if (resource_param.length == rt_attributes->length && - memcmp(resource_param.s, rt_attributes->s, rt_attributes->length) == 0) { - flags |= MATCH_SUBSTRING; - break; - } - } - - /* rest is query-pattern */ - query_pattern.s = - COAP_OPT_VALUE(query_filter) + resource_param.length + 1; - - assert((resource_param.length + 1) <= COAP_OPT_LENGTH(query_filter)); - query_pattern.length = - COAP_OPT_LENGTH(query_filter) - (resource_param.length + 1); - - if ((query_pattern.s[0] == '/') && ((flags & MATCH_URI) == MATCH_URI)) { - query_pattern.s++; - query_pattern.length--; - } - - if (query_pattern.length && - query_pattern.s[query_pattern.length-1] == '*') { - query_pattern.length--; - flags |= MATCH_PREFIX; - } - } - } -#endif /* WITHOUT_QUERY_FILTER */ - - RESOURCES_ITER(context->resources, r) { - -#ifndef WITHOUT_QUERY_FILTER - if (resource_param.length) { /* there is a query filter */ - - if (flags & MATCH_URI) { /* match resource URI */ - if (!match(&r->uri, &query_pattern, (flags & MATCH_PREFIX) != 0, (flags & MATCH_SUBSTRING) != 0)) - continue; - } else { /* match attribute */ - coap_attr_t *attr; - str unquoted_val; - attr = coap_find_attr(r, resource_param.s, resource_param.length); - if (!attr) continue; - if (attr->value.s[0] == '"') { /* if attribute has a quoted value, remove double quotes */ - unquoted_val.length = attr->value.length - 2; - unquoted_val.s = attr->value.s + 1; - } else { - unquoted_val = attr->value; - } - if (!(match(&unquoted_val, &query_pattern, - (flags & MATCH_PREFIX) != 0, - (flags & MATCH_SUBSTRING) != 0))) - continue; - } - } -#endif /* WITHOUT_QUERY_FILTER */ - - if (!subsequent_resource) { /* this is the first resource */ - subsequent_resource = 1; - } else { - PRINT_COND_WITH_OFFSET(p, bufend, offset, ',', written); - } - - left = bufend - p; /* calculate available space */ - result = coap_print_link(r, p, &left, &offset); - - if (result & COAP_PRINT_STATUS_ERROR) { - break; - } - - /* coap_print_link() returns the number of characters that - * where actually written to p. Now advance to its end. */ - p += COAP_PRINT_OUTPUT_LENGTH(result); - written += left; - } - - *buflen = written; - result = p - buf; - if (result + old_offset - offset < *buflen) { - result |= COAP_PRINT_STATUS_TRUNC; - } - return result; -} - -coap_resource_t * -coap_resource_init(const unsigned char *uri, size_t len, int flags) { - coap_resource_t *r; - -#ifdef WITH_LWIP - r = (coap_resource_t *)memp_malloc(MEMP_COAP_RESOURCE); -#endif -#ifndef WITH_LWIP - r = (coap_resource_t *)coap_malloc_type(COAP_RESOURCE, sizeof(coap_resource_t)); -#endif - if (r) { - memset(r, 0, sizeof(coap_resource_t)); - - r->uri.s = (unsigned char *)uri; - r->uri.length = len; - - coap_hash_path(r->uri.s, r->uri.length, r->key); - - r->flags = flags; - } else { - debug("coap_resource_init: no memory left\n"); - } - - return r; -} - -coap_attr_t * -coap_add_attr(coap_resource_t *resource, - const unsigned char *name, size_t nlen, - const unsigned char *val, size_t vlen, - int flags) { - coap_attr_t *attr; - - if (!resource || !name) - return NULL; - -#ifdef WITH_LWIP - attr = (coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR); -#endif -#ifndef WITH_LWIP - attr = (coap_attr_t *)coap_malloc_type(COAP_RESOURCEATTR, sizeof(coap_attr_t)); -#endif - - if (attr) { - attr->name.length = nlen; - attr->value.length = val ? vlen : 0; - - attr->name.s = (unsigned char *)name; - attr->value.s = (unsigned char *)val; - - attr->flags = flags; - - /* add attribute to resource list */ - LL_PREPEND(resource->link_attr, attr); - } else { - debug("coap_add_attr: no memory left\n"); - } - - return attr; -} - -coap_attr_t * -coap_find_attr(coap_resource_t *resource, - const unsigned char *name, size_t nlen) { - coap_attr_t *attr; - - if (!resource || !name) - return NULL; - - LL_FOREACH(resource->link_attr, attr) { - if (attr->name.length == nlen && - memcmp(attr->name.s, name, nlen) == 0) - return attr; - } - - return NULL; -} - -void -coap_delete_attr(coap_attr_t *attr) { - if (!attr) - return; - if (attr->flags & COAP_ATTR_FLAGS_RELEASE_NAME) - coap_free(attr->name.s); - if (attr->flags & COAP_ATTR_FLAGS_RELEASE_VALUE) - coap_free(attr->value.s); - -#ifdef WITH_LWIP - memp_free(MEMP_COAP_RESOURCEATTR, attr); -#endif -#ifndef WITH_LWIP - coap_free_type(COAP_RESOURCEATTR, attr); -#endif -} - -void -coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key) { - coap_opt_iterator_t opt_iter; - coap_opt_filter_t filter; - coap_opt_t *option; - - memset(key, 0, sizeof(coap_key_t)); - - coap_option_filter_clear(filter); - coap_option_setb(filter, COAP_OPTION_URI_PATH); - - coap_option_iterator_init((coap_pdu_t *)request, &opt_iter, filter); - while ((option = coap_option_next(&opt_iter))) - coap_hash(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), key); -} - -void -coap_add_resource(coap_context_t *context, coap_resource_t *resource) { - RESOURCES_ADD(context->resources, resource); -} - -static void -coap_free_resource(coap_resource_t *resource) { - coap_attr_t *attr, *tmp; - coap_subscription_t *obs, *otmp; - - assert(resource); - - /* delete registered attributes */ - LL_FOREACH_SAFE(resource->link_attr, attr, tmp) coap_delete_attr(attr); - - if (resource->flags & COAP_RESOURCE_FLAGS_RELEASE_URI) - coap_free(resource->uri.s); - - /* free all elements from resource->subscribers */ - LL_FOREACH_SAFE(resource->subscribers, obs, otmp) COAP_FREE_TYPE(subscription, obs); - -#ifdef WITH_LWIP - memp_free(MEMP_COAP_RESOURCE, resource); -#endif -#ifndef WITH_LWIP - coap_free_type(COAP_RESOURCE, resource); -#endif /* WITH_CONTIKI */ -} - -int -coap_delete_resource(coap_context_t *context, coap_key_t key) { - coap_resource_t *resource; - - if (!context) - return 0; - - resource = coap_get_resource_from_key(context, key); - - if (!resource) - return 0; - - /* remove resource from list */ - RESOURCES_DELETE(context->resources, resource); - - /* and free its allocated memory */ - coap_free_resource(resource); - - return 1; -} - -void -coap_delete_all_resources(coap_context_t *context) { - coap_resource_t *res; - coap_resource_t *rtmp; - - /* Cannot call RESOURCES_ITER because coap_free_resource() releases - * the allocated storage. */ - -#ifdef COAP_RESOURCES_NOHASH - LL_FOREACH_SAFE(context->resources, res, rtmp) { -#else - HASH_ITER(hh, context->resources, res, rtmp) { - HASH_DELETE(hh, context->resources, res); -#endif - coap_free_resource(res); - } - - context->resources = NULL; -} - -coap_resource_t * -coap_get_resource_from_key(coap_context_t *context, coap_key_t key) { - coap_resource_t *result; - - RESOURCES_FIND(context->resources, key, result); - - return result; -} - -coap_print_status_t -coap_print_link(const coap_resource_t *resource, - unsigned char *buf, size_t *len, size_t *offset) { - unsigned char *p = buf; - const unsigned char *bufend = buf + *len; - coap_attr_t *attr; - coap_print_status_t result = 0; - const size_t old_offset = *offset; - - *len = 0; - PRINT_COND_WITH_OFFSET(p, bufend, *offset, '<', *len); - PRINT_COND_WITH_OFFSET(p, bufend, *offset, '/', *len); - - COPY_COND_WITH_OFFSET(p, bufend, *offset, - resource->uri.s, resource->uri.length, *len); - - PRINT_COND_WITH_OFFSET(p, bufend, *offset, '>', *len); - - LL_FOREACH(resource->link_attr, attr) { - - PRINT_COND_WITH_OFFSET(p, bufend, *offset, ';', *len); - - COPY_COND_WITH_OFFSET(p, bufend, *offset, - attr->name.s, attr->name.length, *len); - - if (attr->value.s) { - PRINT_COND_WITH_OFFSET(p, bufend, *offset, '=', *len); - - COPY_COND_WITH_OFFSET(p, bufend, *offset, - attr->value.s, attr->value.length, *len); - } - - } - if (resource->observable) { - COPY_COND_WITH_OFFSET(p, bufend, *offset, ";obs", 4, *len); - } - - result = p - buf; - if (result + old_offset - *offset < *len) { - result |= COAP_PRINT_STATUS_TRUNC; - } - - return result; -} - -#ifndef WITHOUT_OBSERVE -coap_subscription_t * -coap_find_observer(coap_resource_t *resource, const coap_address_t *peer, - const str *token) { - coap_subscription_t *s; - - assert(resource); - assert(peer); - - LL_FOREACH(resource->subscribers, s) { - if (coap_address_equals(&s->subscriber, peer) - && (!token || (token->length == s->token_length - && memcmp(token->s, s->token, token->length) == 0))) - return s; - } - - return NULL; -} - -coap_subscription_t * -coap_add_observer(coap_resource_t *resource, - const coap_endpoint_t *local_interface, - const coap_address_t *observer, - const str *token) { - coap_subscription_t *s; - - assert(observer); - - /* Check if there is already a subscription for this peer. */ - s = coap_find_observer(resource, observer, token); - - /* We are done if subscription was found. */ - if (s) - return s; - - /* s points to a different subscription, so we have to create - * another one. */ - s = COAP_MALLOC_TYPE(subscription); - - if (!s) - return NULL; - - coap_subscription_init(s); - s->local_if = *local_interface; - memcpy(&s->subscriber, observer, sizeof(coap_address_t)); - - if (token && token->length) { - s->token_length = token->length; - memcpy(s->token, token->s, min(s->token_length, 8)); - } - - /* add subscriber to resource */ - LL_PREPEND(resource->subscribers, s); - - return s; -} - -void -coap_touch_observer(coap_context_t *context, const coap_address_t *observer, - const str *token) { - coap_subscription_t *s; - - RESOURCES_ITER(context->resources, r) { - s = coap_find_observer(r, observer, token); - if (s) { - s->fail_cnt = 0; - } - } -} - -int -coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer, - const str *token) { - coap_subscription_t *s; - - s = coap_find_observer(resource, observer, token); - - if (resource->subscribers && s) { - LL_DELETE(resource->subscribers, s); - - COAP_FREE_TYPE(subscription,s); - } - - return s != NULL; -} - -static void -coap_notify_observers(coap_context_t *context, coap_resource_t *r) { - coap_method_handler_t h; - coap_subscription_t *obs; - str token; - coap_pdu_t *response; - - if (r->observable && (r->dirty || r->partiallydirty)) { - r->partiallydirty = 0; - - /* retrieve GET handler, prepare response */ - h = r->handler[COAP_REQUEST_GET - 1]; - assert(h); /* we do not allow subscriptions if no - * GET handler is defined */ - - LL_FOREACH(r->subscribers, obs) { - if (r->dirty == 0 && obs->dirty == 0) - /* running this resource due to partiallydirty, but this observation's notification was already enqueued */ - continue; - - coap_tid_t tid = COAP_INVALID_TID; - obs->dirty = 0; - /* initialize response */ - response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE); - if (!response) { - obs->dirty = 1; - r->partiallydirty = 1; - debug("coap_check_notify: pdu init failed, resource stays partially dirty\n"); - continue; - } - - if (!coap_add_token(response, obs->token_length, obs->token)) { - obs->dirty = 1; - r->partiallydirty = 1; - debug("coap_check_notify: cannot add token, resource stays partially dirty\n"); - coap_delete_pdu(response); - continue; - } - - token.length = obs->token_length; - token.s = obs->token; - - response->hdr->id = coap_new_message_id(context); - if ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_CON) == 0 - && obs->non_cnt < COAP_OBS_MAX_NON) { - response->hdr->type = COAP_MESSAGE_NON; - } else { - response->hdr->type = COAP_MESSAGE_CON; - } - /* fill with observer-specific data */ - h(context, r, &obs->local_if, &obs->subscriber, NULL, &token, response); - - /* TODO: do not send response and remove observer when - * COAP_RESPONSE_CLASS(response->hdr->code) > 2 - */ - if (response->hdr->type == COAP_MESSAGE_CON) { - tid = coap_send_confirmed(context, &obs->local_if, &obs->subscriber, response); - obs->non_cnt = 0; - } else { - tid = coap_send(context, &obs->local_if, &obs->subscriber, response); - obs->non_cnt++; - } - - if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON) - coap_delete_pdu(response); - if (COAP_INVALID_TID == tid) - { - debug("coap_check_notify: sending failed, resource stays partially dirty\n"); - obs->dirty = 1; - r->partiallydirty = 1; - } - - } - - /* Increment value for next Observe use. */ - context->observe++; - } - r->dirty = 0; -} - -void -coap_check_notify(coap_context_t *context) { - - RESOURCES_ITER(context->resources, r) { - coap_notify_observers(context, r); - } -} - -/** - * Checks the failure counter for (peer, token) and removes peer from - * the list of observers for the given resource when COAP_OBS_MAX_FAIL - * is reached. - * - * @param context The CoAP context to use - * @param resource The resource to check for (peer, token) - * @param peer The observer's address - * @param token The token that has been used for subscription. - */ -static void -coap_remove_failed_observers(coap_context_t *context, - coap_resource_t *resource, - const coap_address_t *peer, - const str *token) { - coap_subscription_t *obs, *otmp; - - LL_FOREACH_SAFE(resource->subscribers, obs, otmp) { - if (coap_address_equals(peer, &obs->subscriber) && - token->length == obs->token_length && - memcmp(token->s, obs->token, token->length) == 0) { - - /* count failed notifies and remove when - * COAP_MAX_FAILED_NOTIFY is reached */ - if (obs->fail_cnt < COAP_OBS_MAX_FAIL) - obs->fail_cnt++; - else { - LL_DELETE(resource->subscribers, obs); - obs->fail_cnt = 0; - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&obs->subscriber, addr, INET6_ADDRSTRLEN+8)) - debug("** removed observer %s\n", addr); - } -#endif - coap_cancel_all_messages(context, &obs->subscriber, - obs->token, obs->token_length); - - COAP_FREE_TYPE(subscription, obs); - } - } - break; /* break loop if observer was found */ - } -} - -void -coap_handle_failed_notify(coap_context_t *context, - const coap_address_t *peer, - const str *token) { - - RESOURCES_ITER(context->resources, r) { - coap_remove_failed_observers(context, r, peer, token); - } -} -#endif /* WITHOUT_NOTIFY */ diff --git a/components/coap/libcoap/src/str.c b/components/coap/libcoap/src/str.c deleted file mode 100644 index f5800c257..000000000 --- a/components/coap/libcoap/src/str.c +++ /dev/null @@ -1,34 +0,0 @@ -/* str.c -- strings to be used in the CoAP library - * - * Copyright (C) 2010,2011 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#include - -#include "debug.h" -#include "mem.h" -#include "str.h" - -str *coap_new_string(size_t size) { - str *s = coap_malloc(sizeof(str) + size + 1); - if ( !s ) { -#ifndef NDEBUG - coap_log(LOG_CRIT, "coap_new_string: malloc\n"); -#endif - return NULL; - } - - memset(s, 0, sizeof(str)); - s->s = ((unsigned char *)s) + sizeof(str); - return s; -} - -void coap_delete_string(str *s) { - coap_free(s); -} - diff --git a/components/coap/libcoap/src/subscribe.c b/components/coap/libcoap/src/subscribe.c deleted file mode 100644 index 860b8dafc..000000000 --- a/components/coap/libcoap/src/subscribe.c +++ /dev/null @@ -1,23 +0,0 @@ -/* subscribe.c -- subscription handling for CoAP - * see draft-ietf-coap-observe-16 - * - * Copyright (C) 2010--2013,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "coap.h" - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include "subscribe.h" - -void -coap_subscription_init(coap_subscription_t *s) { - assert(s); - memset(s, 0, sizeof(coap_subscription_t)); -} diff --git a/components/coap/libcoap/src/uri.c b/components/coap/libcoap/src/uri.c deleted file mode 100644 index 73732b8b4..000000000 --- a/components/coap/libcoap/src/uri.c +++ /dev/null @@ -1,492 +0,0 @@ -/* uri.c -- helper functions for URI treatment - * - * Copyright (C) 2010--2012,2015-2016 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include - -#include "mem.h" -#include "debug.h" -#include "pdu.h" -#include "option.h" -#include "uri.h" - -/** - * A length-safe version of strchr(). This function returns a pointer - * to the first occurrence of @p c in @p s, or @c NULL if not found. - * - * @param s The string to search for @p c. - * @param len The length of @p s. - * @param c The character to search. - * - * @return A pointer to the first occurence of @p c, or @c NULL - * if not found. - */ -static inline unsigned char * -strnchr(unsigned char *s, size_t len, unsigned char c) { - while (len && *s++ != c) - --len; - - return len ? s : NULL; -} - -#define ISEQUAL_CI(a,b) \ - ((a) == (b) || (islower(b) && ((a) == ((b) - 0x20)))) - -int -coap_split_uri(const unsigned char *str_var, size_t len, coap_uri_t *uri) { - const unsigned char *p, *q; - int secure = 0, res = 0; - - if (!str_var || !uri) - return -1; - - memset(uri, 0, sizeof(coap_uri_t)); - uri->port = COAP_DEFAULT_PORT; - - /* search for scheme */ - p = str_var; - if (*p == '/') { - q = p; - goto path; - } - - q = (unsigned char *)COAP_DEFAULT_SCHEME; - while (len && *q && ISEQUAL_CI(*p, *q)) { - ++p; ++q; --len; - } - - /* If q does not point to the string end marker '\0', the schema - * identifier is wrong. */ - if (*q) { - res = -1; - goto error; - } - - /* There might be an additional 's', indicating the secure version: */ - if (len && (secure = *p == 's')) { - ++p; --len; - } - - q = (unsigned char *)"://"; - while (len && *q && *p == *q) { - ++p; ++q; --len; - } - - if (*q) { - res = -2; - goto error; - } - - /* p points to beginning of Uri-Host */ - q = p; - if (len && *p == '[') { /* IPv6 address reference */ - ++p; - - while (len && *q != ']') { - ++q; --len; - } - - if (!len || *q != ']' || p == q) { - res = -3; - goto error; - } - - COAP_SET_STR(&uri->host, q - p, (unsigned char *)p); - ++q; --len; - } else { /* IPv4 address or FQDN */ - while (len && *q != ':' && *q != '/' && *q != '?') { - ++q; - --len; - } - - if (p == q) { - res = -3; - goto error; - } - - COAP_SET_STR(&uri->host, q - p, (unsigned char *)p); - } - - /* check for Uri-Port */ - if (len && *q == ':') { - p = ++q; - --len; - - while (len && isdigit(*q)) { - ++q; - --len; - } - - if (p < q) { /* explicit port number given */ - int uri_port = 0; - - while (p < q) - uri_port = uri_port * 10 + (*p++ - '0'); - - /* check if port number is in allowed range */ - if (uri_port > 65535) { - res = -4; - goto error; - } - - uri->port = uri_port; - } - } - - path: /* at this point, p must point to an absolute path */ - - if (!len) - goto end; - - if (*q == '/') { - p = ++q; - --len; - - while (len && *q != '?') { - ++q; - --len; - } - - if (p < q) { - COAP_SET_STR(&uri->path, q - p, (unsigned char *)p); - p = q; - } - } - - /* Uri_Query */ - if (len && *p == '?') { - ++p; - --len; - COAP_SET_STR(&uri->query, len, (unsigned char *)p); - len = 0; - } - - end: - return len ? -1 : 0; - - error: - return res; -} - -/** - * Calculates decimal value from hexadecimal ASCII character given in - * @p c. The caller must ensure that @p c actually represents a valid - * heaxdecimal character, e.g. with isxdigit(3). - * - * @hideinitializer - */ -#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) - -/** - * Decodes percent-encoded characters while copying the string @p seg - * of size @p length to @p buf. The caller of this function must - * ensure that the percent-encodings are correct (i.e. the character - * '%' is always followed by two hex digits. and that @p buf provides - * sufficient space to hold the result. This function is supposed to - * be called by make_decoded_option() only. - * - * @param seg The segment to decode and copy. - * @param length Length of @p seg. - * @param buf The result buffer. - */ -static void -decode_segment(const unsigned char *seg, size_t length, unsigned char *buf) { - - while (length--) { - - if (*seg == '%') { - *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); - - seg += 2; length -= 2; - } else { - *buf = *seg; - } - - ++buf; ++seg; - } -} - -/** - * Runs through the given path (or query) segment and checks if - * percent-encodings are correct. This function returns @c -1 on error - * or the length of @p s when decoded. - */ -static int -check_segment(const unsigned char *s, size_t length) { - - size_t n = 0; - - while (length) { - if (*s == '%') { - if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) - return -1; - - s += 2; - length -= 2; - } - - ++s; ++n; --length; - } - - return n; -} - -/** - * Writes a coap option from given string @p s to @p buf. @p s should - * point to a (percent-encoded) path or query segment of a coap_uri_t - * object. The created option will have type @c 0, and the length - * parameter will be set according to the size of the decoded string. - * On success, this function returns the option's size, or a value - * less than zero on error. This function must be called from - * coap_split_path_impl() only. - * - * @param s The string to decode. - * @param length The size of the percent-encoded string @p s. - * @param buf The buffer to store the new coap option. - * @param buflen The maximum size of @p buf. - * - * @return The option's size, or @c -1 on error. - * - * @bug This function does not split segments that are bigger than 270 - * bytes. - */ -static int -make_decoded_option(const unsigned char *s, size_t length, - unsigned char *buf, size_t buflen) { - int res; - size_t written; - - if (!buflen) { - debug("make_decoded_option(): buflen is 0!\n"); - return -1; - } - - res = check_segment(s, length); - if (res < 0) - return -1; - - /* write option header using delta 0 and length res */ - written = coap_opt_setheader(buf, buflen, 0, res); - - assert(written <= buflen); - - if (!written) /* encoding error */ - return -1; - - buf += written; /* advance past option type/length */ - buflen -= written; - - if (buflen < (size_t)res) { - debug("buffer too small for option\n"); - return -1; - } - - decode_segment(s, length, buf); - - return written + res; -} - - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -typedef void (*segment_handler_t)(unsigned char *, size_t, void *); - -/** - * Checks if path segment @p s consists of one or two dots. - */ -static inline int -dots(unsigned char *s, size_t len) { - return *s == '.' && (len == 1 || (*(s+1) == '.' && len == 2)); -} - -/** - * Splits the given string into segments. You should call one of the - * macros coap_split_path() or coap_split_query() instead. - * - * @param s The URI string to be tokenized. - * @param length The length of @p s. - * @param h A handler that is called with every token. - * @param data Opaque data that is passed to @p h when called. - * - * @return The number of characters that have been parsed from @p s. - */ -static size_t -coap_split_path_impl(const unsigned char *s, size_t length, - segment_handler_t h, void *data) { - - const unsigned char *p, *q; - - p = q = s; - while (length > 0 && !strnchr((unsigned char *)"?#", 2, *q)) { - if (*q == '/') { /* start new segment */ - - if (!dots((unsigned char *)p, q - p)) { - h((unsigned char *)p, q - p, data); - } - - p = q + 1; - } - - q++; - length--; - } - - /* write last segment */ - if (!dots((unsigned char *)p, q - p)) { - h((unsigned char *)p, q - p, data); - } - - return q - s; -} - -struct cnt_str { - str buf; - int n; -}; - -static void -write_option(unsigned char *s, size_t len, void *data) { - struct cnt_str *state = (struct cnt_str *)data; - int res; - assert(state); - - res = make_decoded_option(s, len, state->buf.s, state->buf.length); - if (res > 0) { - state->buf.s += res; - state->buf.length -= res; - state->n++; - } -} - -int -coap_split_path(const unsigned char *s, size_t length, - unsigned char *buf, size_t *buflen) { - struct cnt_str tmp = { { *buflen, buf }, 0 }; - - coap_split_path_impl(s, length, write_option, &tmp); - - *buflen = *buflen - tmp.buf.length; - - return tmp.n; -} - -int -coap_split_query(const unsigned char *s, size_t length, - unsigned char *buf, size_t *buflen) { - struct cnt_str tmp = { { *buflen, buf }, 0 }; - const unsigned char *p; - - p = s; - while (length > 0 && *s != '#') { - if (*s == '&') { /* start new query element */ - write_option((unsigned char *)p, s - p, &tmp); - p = s + 1; - } - - s++; - length--; - } - - /* write last query element */ - write_option((unsigned char *)p, s - p, &tmp); - - *buflen = *buflen - tmp.buf.length; - return tmp.n; -} - -#define URI_DATA(uriobj) ((unsigned char *)(uriobj) + sizeof(coap_uri_t)) - -coap_uri_t * -coap_new_uri(const unsigned char *uri, unsigned int length) { - unsigned char *result; - - result = coap_malloc(length + 1 + sizeof(coap_uri_t)); - - if (!result) - return NULL; - - memcpy(URI_DATA(result), uri, length); - URI_DATA(result)[length] = '\0'; /* make it zero-terminated */ - - if (coap_split_uri(URI_DATA(result), length, (coap_uri_t *)result) < 0) { - coap_free(result); - return NULL; - } - return (coap_uri_t *)result; -} - -coap_uri_t * -coap_clone_uri(const coap_uri_t *uri) { - coap_uri_t *result; - - if ( !uri ) - return NULL; - - result = (coap_uri_t *)coap_malloc( uri->query.length + uri->host.length + - uri->path.length + sizeof(coap_uri_t) + 1); - - if ( !result ) - return NULL; - - memset( result, 0, sizeof(coap_uri_t) ); - - result->port = uri->port; - - if ( uri->host.length ) { - result->host.s = URI_DATA(result); - result->host.length = uri->host.length; - - memcpy(result->host.s, uri->host.s, uri->host.length); - } - - if ( uri->path.length ) { - result->path.s = URI_DATA(result) + uri->host.length; - result->path.length = uri->path.length; - - memcpy(result->path.s, uri->path.s, uri->path.length); - } - - if ( uri->query.length ) { - result->query.s = URI_DATA(result) + uri->host.length + uri->path.length; - result->query.length = uri->query.length; - - memcpy(result->query.s, uri->query.s, uri->query.length); - } - - return result; -} - -/* hash URI path segments */ - -/* The function signature of coap_hash() is different from - * segment_handler_t hence we use this wrapper as safe typecast. */ -static inline void -hash_segment(unsigned char *s, size_t len, void *data) { - coap_hash(s, len, data); -} - -int -coap_hash_path(const unsigned char *path, size_t len, coap_key_t key) { - if (!path) - return 0; - - memset(key, 0, sizeof(coap_key_t)); - - coap_split_path_impl(path, len, hash_segment, key); - - return 1; -} diff --git a/components/coap/libcoap/tests/Makefile.am b/components/coap/libcoap/tests/Makefile.am deleted file mode 100644 index 140d0437f..000000000 --- a/components/coap/libcoap/tests/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ -# doc/Makefile.am -# -# Copyright (C) 2015-2016 Carsten Schoenert -# -# This file is part of the CoAP C library libcoap. Please see README and -# COPYING for terms of use. - -# just do anything if 'HAVE_CUNIT' is defined -if HAVE_CUNIT - -# picking up the default warning CFLAGS -AM_CFLAGS = -I$(top_srcdir)/include/coap -I$(top_builddir)/include/coap $(WARNING_CFLAGS) $(CUNIT_CFLAGS) -std=c99 - -noinst_PROGRAMS = \ - testdriver - -testdriver_SOURCES = \ - testdriver.c \ - test_error_response.c \ - test_options.c \ - test_pdu.c \ - test_sendqueue.c \ - test_uri.c \ - test_wellknown.c - -testdriver_LDADD = $(CUNIT_LIBS) $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la - -# If there is a API change to something $(LIBCOAP_API_VERSION) > 1 there is -# nothing to adopt here. No needed to implement something here because the test -# unit will always be build againts the actual header files! - -CLEANFILES = testdriver - -all-am: testdriver - -endif # HAVE_CUNIT diff --git a/components/coap/libcoap/tests/test_error_response.c b/components/coap/libcoap/tests/test_error_response.c deleted file mode 100644 index 37afba47b..000000000 --- a/components/coap/libcoap/tests/test_error_response.c +++ /dev/null @@ -1,374 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_error_response.h" - -#include - -#include -#include -#include -#include - -coap_pdu_t *pdu; /* Holds the request PDU for most tests */ -coap_opt_filter_t opts; /* option filter used for generating responses */ - -/************************************************************************ - ** PDU decoder - ************************************************************************/ - -/* FIXME: handle COAP_ERROR_PHRASE_LENGTH == 0 */ - -static void -t_error_response1(void) { - uint8_t teststr[] = { - 0x60, 0x80, 0x12, 0x34, 0xff, 'B', 'a', 'd', - ' ', 'R', 'e', 'q', 'u', 'e', 's', 't' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - pdu->hdr->id = htons(0x1234); - - /* result = coap_add_token(pdu, 5, (unsigned char *)"token"); */ - coap_option_filter_clear(opts); - response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(400), opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 0); - CU_ASSERT(response->hdr->code == 0x80); - CU_ASSERT(pdu->hdr->id == htons(0x1234)); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response2(void) { - uint8_t teststr[] = { - 0x55, 0x84, 0x12, 0x34, 't', 'o', 'k', 'e', - 'n', 0xff, 'N', 'o', 't', ' ', 'F', 'o', - 'u', 'n', 'd' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_NON; - pdu->hdr->id = htons(0x1234); - coap_add_token(pdu, 5, (unsigned char *)"token"); - coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); - - coap_option_filter_clear(opts); - response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(404), opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_NON); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == 0x84); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response3(void) { - const unsigned char code = COAP_RESPONSE_CODE(402); - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0x90, 0xff, 'B', 'a', 'd', ' ', 'O', - 'p', 't', 'i', 'o', 'n' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ - - /* unknown critical option 9 */ - coap_add_option(pdu, 9, 0, NULL); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 9); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response4(void) { - const unsigned char code = COAP_RESPONSE_CODE(402); - unsigned char optval[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b - }; - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0x9c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 'B', - 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', - 'n' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ - - /* unknown critical option 9 */ - coap_add_option(pdu, 9, sizeof(optval), optval); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 9); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response5(void) { - const unsigned char code = COAP_RESPONSE_CODE(402); - unsigned char optval[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12 - }; - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0x9d, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, - 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, 'B', - 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', - 'n' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ - - /* unknown critical option 9 */ - coap_add_option(pdu, 9, sizeof(optval), optval); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 9); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response6(void) { - const unsigned char code = COAP_RESPONSE_CODE(402); - unsigned char optval[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12 - }; - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, - 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', - 'o', 'n' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ - - /* unknown critical option 23 */ - coap_add_option(pdu, 23, sizeof(optval), optval); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 23); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response7(void) { - const unsigned char code = COAP_RESPONSE_CODE(402); - unsigned char optval[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12 - }; - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, - 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', - 'o', 'n' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* known option 11 */ - coap_add_option(pdu, 11, 4, (unsigned char *)"time"); - - /* unknown critical option 23 */ - coap_add_option(pdu, 23, sizeof(optval), optval); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 23); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static void -t_error_response8(void) { - const unsigned char code = COAP_RESPONSE_CODE(503); - uint8_t teststr[] = { - 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', - 'n', 0xe0, 0x02, 0xdc, 0xd0, 0x00, 0xff, 'S', - 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'U', - 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', - 'l', 'e' - }; - coap_pdu_t *response; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - coap_add_token(pdu, 5, (unsigned char *)"token"); - /* known option 1000 */ - coap_add_option(pdu, 1000, 0, NULL); - - /* unknown options 1001 and 1014 */ - coap_add_option(pdu, 1001, 0, NULL); - coap_add_option(pdu, 1014, 0, NULL); - - /* known option 2000 */ - coap_add_option(pdu, 2000, 0, NULL); - - coap_option_filter_clear(opts); - coap_option_setb(opts, 1001); - coap_option_setb(opts, 1014); - response = coap_new_error_response(pdu, code, opts); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(response->length == sizeof(teststr)); - CU_ASSERT(response->hdr->version == 1); - CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(response->hdr->token_length == 5); - CU_ASSERT(response->hdr->code == code); - - CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); - coap_delete_pdu(response); -} - -static int -t_error_response_tests_create(void) { - pdu = coap_pdu_init(0, 0, 0, COAP_MAX_PDU_SIZE); - - return pdu == NULL; -} - -static int -t_error_response_tests_remove(void) { - coap_delete_pdu(pdu); - return 0; -} - -CU_pSuite -t_init_error_response_tests(void) { - CU_pSuite suite[1]; - - suite[0] = CU_add_suite("error response generator", - t_error_response_tests_create, - t_error_response_tests_remove); - if (!suite[0]) { /* signal error */ - fprintf(stderr, "W: cannot add error response generator test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define ERROR_RESPONSE_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add error response generator test (%s)\n", \ - CU_get_error_msg()); \ - } - - ERROR_RESPONSE_TEST(suite[0], t_error_response1); - ERROR_RESPONSE_TEST(suite[0], t_error_response2); - ERROR_RESPONSE_TEST(suite[0], t_error_response3); - ERROR_RESPONSE_TEST(suite[0], t_error_response4); - ERROR_RESPONSE_TEST(suite[0], t_error_response5); - ERROR_RESPONSE_TEST(suite[0], t_error_response6); - ERROR_RESPONSE_TEST(suite[0], t_error_response7); - ERROR_RESPONSE_TEST(suite[0], t_error_response8); - - return suite[0]; -} - diff --git a/components/coap/libcoap/tests/test_error_response.h b/components/coap/libcoap/tests/test_error_response.h deleted file mode 100644 index 2bab63c90..000000000 --- a/components/coap/libcoap/tests/test_error_response.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_error_response_tests(void); diff --git a/components/coap/libcoap/tests/test_options.c b/components/coap/libcoap/tests/test_options.c deleted file mode 100644 index 5bb51f4d0..000000000 --- a/components/coap/libcoap/tests/test_options.c +++ /dev/null @@ -1,999 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_options.h" - -#include - -#include -#include -#include - -/************************************************************************ - ** decoder tests - ************************************************************************/ - -static void -t_parse_option1(void) { - /* delta == 0, length == 0, value == 0 */ - str teststr = { 1, (unsigned char *)"" }; - - size_t result; - coap_option_t option; - - /* result = coap_opt_parse(teststr.s, teststr.s + teststr.length, &option); */ - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 1); - CU_ASSERT(option.delta == 0); - CU_ASSERT(option.length == 0); - /* FIXME: value? */ -} - -static void -t_parse_option2(void) { - /* delta == 12, length == 1, value == 0 */ - str teststr = { 2, (unsigned char *)"\xc1" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 2); - CU_ASSERT(option.delta == 12); - CU_ASSERT(option.length == 1); - CU_ASSERT(option.value == teststr.s + 1); -} - -static void -t_parse_option3(void) { - /* delta == 3, length == 12, value == 0 */ - str teststr = { 13, (unsigned char *)"\x3c\x00\x01\x02\x03\x04" - "\x05\x06\x07\x08\x09\x0a\x0b" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 13); - CU_ASSERT(option.delta == 3); - CU_ASSERT(option.length == 12); - CU_ASSERT(option.value == teststr.s + 1); - /* CU_ASSERT(memcmp(option.value, teststr.s + 1, 12) == 0); */ -} - -static void -t_parse_option4(void) { - /* delta == 15, length == 3, value == 0 */ - str teststr = { 2, (unsigned char *)"\xf3" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option5(void) { - /* delta == 3, length == 15, value == 0 */ - str teststr = { 2, (unsigned char *)"\x3f" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option6(void) { - /* delta == 15, length == 15 */ - str teststr = { 1, (unsigned char *)"\xff" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option7(void) { - /* delta == 20, length == 0 */ - str teststr = { 2, (unsigned char *)"\xd0\x07" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 2); - CU_ASSERT(option.delta == 20); - CU_ASSERT(option.length == 0); -} - -static void -t_parse_option8(void) { - /* delta == 780, length == 0 */ - str teststr = { 3, (unsigned char *)"\xe0\x01\xff" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 3); - CU_ASSERT(option.delta == 780); - CU_ASSERT(option.length == 0); -} - -static void -t_parse_option9(void) { - /* delta == 65535, length == 0 */ - str teststr = { 3, (unsigned char *)"\xe0\xfe\xf2" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 3); - CU_ASSERT(option.delta == 65535); -} - -static void -t_parse_option10(void) { - /* delta > 65535 (illegal), length == 0 */ - str teststr = { 3, (unsigned char *)"\xe0\xff\xff" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option11(void) { - /* illegal delta value (option too short) */ - str teststr = { 1, (unsigned char *)"\xd0" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option12(void) { - /* delta == 280, length == 500 */ - str teststr = { 3, (unsigned char *)"\xee\xff\x0b" }; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == 0); -} - -static void -t_parse_option13(void) { - /* delta == 280, length == 500 */ - unsigned char _data[505]; - str teststr = { sizeof(_data), _data }; - teststr.s[0] = 0xee; - teststr.s[1] = 0x00; - teststr.s[2] = 0x0b; - teststr.s[3] = 0x00; - teststr.s[4] = 0xe7; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(teststr.s, teststr.length, &option); - CU_ASSERT(result == sizeof(_data)); - CU_ASSERT(option.delta == 280); - CU_ASSERT(option.length == 500); - CU_ASSERT(option.value == &_data[5]); -} - -static void -t_parse_option14(void) { - /* delta == 268, length == 65535 */ - unsigned char *data; - unsigned int length = 4 + 65535; - - data = (unsigned char *)malloc(length); - if (!data) { - CU_FAIL("internal error in test framework -- insufficient memory\n"); - return; - } - - data[0] = 0xde; - data[1] = 0xff; - data[2] = 0xfe; - data[3] = 0xf2; - - size_t result; - coap_option_t option; - - result = coap_opt_parse(data, length, &option); - CU_ASSERT(result == length); - CU_ASSERT(option.delta == 268); - CU_ASSERT(option.length == 65535); - CU_ASSERT(option.value == &data[4]); -} - -/************************************************************************ - ** encoder tests - ************************************************************************/ - -static void -t_encode_option1(void) { - char teststr[] = { 0x00 }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 0, 0); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option2(void) { - uint8_t teststr[] = { 0x5d, 0xff }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5, 268); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option3(void) { - uint8_t teststr[] = { 0xd1, 0x01 }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 14, 1); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option4(void) { - uint8_t teststr[] = { 0xdd, 0xff, 0xab }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 268, 184); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option5(void) { - uint8_t teststr[] = { 0xed, 0x13, 0x00, 0xff }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5133, 268); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option6(void) { - uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0xfe, 0xf2 }; - unsigned char buf[40]; - size_t result; - - result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 65535, 65535); - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option7(void) { - uint8_t teststr[] = { 0x35, 'v', 'a', 'l', 'u', 'e' }; - const size_t valoff = 1; - unsigned char buf[40]; - size_t result; - - result = coap_opt_encode((coap_opt_t *)buf, sizeof(buf), 3, - (unsigned char *)teststr + valoff, - sizeof(teststr) - valoff); - - CU_ASSERT(result == sizeof(teststr)); - - CU_ASSERT(memcmp(buf, teststr, result) == 0); -} - -static void -t_encode_option8(void) { - /* value does not fit in message buffer */ - unsigned char buf[40]; - size_t result; - - result = coap_opt_encode((coap_opt_t *)buf, 8, 15, - (unsigned char *)"something", 9); - - CU_ASSERT(result == 0); - - result = coap_opt_encode((coap_opt_t *)buf, 1, 15, - (unsigned char *)"something", 9); - - CU_ASSERT(result == 0); -} - -/************************************************************************ - ** accessor tests - ************************************************************************/ - -static void -t_access_option1(void) { - const uint8_t teststr[] = { 0x12, 'a', 'b' }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 1); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 2); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 1); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr)); -} - -static void -t_access_option2(void) { - const uint8_t teststr[] = { 0xe2, 0x18, 0xfd, 'a', 'b' }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 6666); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 2); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 3); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr)); -} - -static void -t_access_option3(void) { - const uint8_t teststr[] = { 0xed, 0x18, 0x0a, 0x00, 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm' - }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 6423); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 13); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 4); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr)); -} - -static void -t_access_option4(void) { - const uint8_t teststr[] = { 0xde, 0xff, 0xfe, 0xf2, 'a', 'b', 'c' }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 268); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 65535); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 4); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 65535 + 4); -} - -static void -t_access_option5(void) { - const uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0x00, 0xdd, 'a', 'b', 'c' }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 65535); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 490); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 5); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 495); -} - -static void -t_access_option6(void) { - coap_log_t level = coap_get_log_level(); - const uint8_t teststr[] = { 0xf2, 'a', 'b' }; - - coap_set_log_level(LOG_CRIT); - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 0); - coap_set_log_level(level); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 0); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), NULL); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 0); -} - -static void -t_access_option7(void) { - const uint8_t teststr[] = { 0x2f, 'a', 'b' }; - - CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 2); - CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 0); - CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), NULL); - CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 0); -} - -/************************************************************************ - ** accessor tests - ************************************************************************/ - -#define TEST_MAX_SIZE 1000 - -static void -t_iterate_option1(void) { - /* CoAP PDU without token, options, or data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - - result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); - - CU_ASSERT(result == NULL); - CU_ASSERT(oi.bad == 1); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT(option == NULL); -} - -static void -t_iterate_option2(void) { - /* CoAP PDU with token but without options and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k' - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - - result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); - - CU_ASSERT(result == NULL); - CU_ASSERT(oi.bad == 1); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT(option == NULL); -} - -static void -t_iterate_option3(void) { - /* CoAP PDU with token and options */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, - 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x' - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - - result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 1); - CU_ASSERT_PTR_EQUAL(option, teststr + 7); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 1); - CU_ASSERT_PTR_EQUAL(option, teststr + 11); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 30); - CU_ASSERT_PTR_EQUAL(option, teststr + 12); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option4(void) { - /* CoAP PDU with token, options, and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, - 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x', 0xff, - 'd', 'a', 't', 'a' - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - - result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 1); - CU_ASSERT_PTR_EQUAL(option, teststr + 7); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 1); - CU_ASSERT_PTR_EQUAL(option, teststr + 11); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 30); - CU_ASSERT_PTR_EQUAL(option, teststr + 12); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option5(void) { - /* CoAP PDU with malformed option */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x52, 'o', 'p', 0xee, - 0x12, 0x03, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - - result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 5); - CU_ASSERT_PTR_EQUAL(option, teststr + 4); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option6(void) { - /* option filter */ - /* CoAP PDU with token, options, and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, - 0xc0, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - coap_opt_filter_t filter; - - coap_option_filter_clear(filter); - coap_option_setb(filter, 10); /* option nr 10 only */ - result = coap_option_iterator_init(&pdu, &oi, filter); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 10); - CU_ASSERT_PTR_EQUAL(option, teststr + 5); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 10); - CU_ASSERT_PTR_EQUAL(option, teststr + 6); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 10); - CU_ASSERT_PTR_EQUAL(option, teststr + 7); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option7(void) { - /* option filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, - 0xc0, 0x00, 0x10, 0x10, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - coap_opt_filter_t filter; - - /* search options nr 8 and 22 */ - coap_option_filter_clear(filter); - coap_option_setb(filter, 8); - coap_option_setb(filter, 22); - result = coap_option_iterator_init(&pdu, &oi, filter); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 8); - CU_ASSERT_PTR_EQUAL(option, teststr + 4); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 22); - CU_ASSERT_PTR_EQUAL(option, teststr + 8); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT(oi.type == 22); - CU_ASSERT_PTR_EQUAL(option, teststr + 9); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option8(void) { - /* option filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, - 0xc0, 0x00, 0x10, 0x10, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - coap_opt_filter_t filter; - - /* search option nr 36 */ - coap_option_filter_clear(filter); - coap_option_setb(filter, 36); - result = coap_option_iterator_init(&pdu, &oi, filter); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option9(void) { - /* options filter: option number too large for filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, - 0xc0, 0x00, 0x10, 0x10, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - coap_opt_filter_t filter; - - /* search option nr 100 */ - coap_option_filter_clear(filter); - coap_option_setb(filter, 100); - result = coap_option_iterator_init(&pdu, &oi, filter); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -static void -t_iterate_option10(void) { - /* options filter: option numbers in PDU exceed filter size */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, - 0xd0, 0x26, 0xe0, 0x10, 0x00 - }; - - coap_pdu_t pdu = { - .max_size = TEST_MAX_SIZE, - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - coap_opt_iterator_t oi, *result; - coap_opt_t *option; - coap_opt_filter_t filter; - - /* search option nr 61 */ - coap_option_filter_clear(filter); - coap_option_setb(filter, 61); - result = coap_option_iterator_init(&pdu, &oi, filter); - - CU_ASSERT_PTR_EQUAL(result, &oi); - CU_ASSERT(oi.bad == 0); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 0); - CU_ASSERT_PTR_EQUAL(option, teststr + 8); - - option = coap_option_next(&oi); - CU_ASSERT(oi.bad == 1); - CU_ASSERT_PTR_EQUAL(option, NULL); -} - -/************************************************************************ - ** filter tests - ************************************************************************/ - -static void -t_filter_option1(void) { - coap_opt_filter_t filter; - - coap_option_filter_clear(filter); - - CU_ASSERT(coap_option_filter_set(filter, 0) == 1); - CU_ASSERT(coap_option_filter_set(filter, 37) == 1); - CU_ASSERT(coap_option_filter_set(filter, 37) == 1); - CU_ASSERT(coap_option_filter_set(filter, 43) == 1); - CU_ASSERT(coap_option_filter_set(filter, 290) == 1); - CU_ASSERT(coap_option_filter_set(filter, 65535) == 1); - - CU_ASSERT(coap_option_filter_get(filter, 0) == 1); - CU_ASSERT(coap_option_filter_get(filter, 37) == 1); - CU_ASSERT(coap_option_filter_get(filter, 43) == 1); - CU_ASSERT(coap_option_filter_get(filter, 290) == 1); - CU_ASSERT(coap_option_filter_get(filter, 65535) == 1); - - CU_ASSERT(coap_option_filter_unset(filter, 37) == 1); - - CU_ASSERT(coap_option_filter_get(filter, 0) == 1); - CU_ASSERT(coap_option_filter_get(filter, 43) == 1); - CU_ASSERT(coap_option_filter_get(filter, 290) == 1); - CU_ASSERT(coap_option_filter_get(filter, 65535) == 1); - - CU_ASSERT(coap_option_filter_get(filter, 37) == 0); - CU_ASSERT(coap_option_filter_get(filter, 89) == 0); -} - -static void -t_filter_option2(void) { - coap_opt_filter_t filter; - int s; - - coap_option_filter_clear(filter); - - /* fill all COAP_OPT_FILTER_SHORT slots */ - for (s = 0; s < COAP_OPT_FILTER_SHORT; s++) { - CU_ASSERT(coap_option_filter_set(filter, s)); - } - - /* adding a short option type must fail */ - CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 0); - - /* adding a long option type must succeed */ - CU_ASSERT(coap_option_filter_set(filter, 256) == 1); -} - -static void -t_filter_option3(void) { - coap_opt_filter_t filter; - int l; - - coap_option_filter_clear(filter); - - /* set COAP_OPT_FILTER_LONG long filters */ - for (l = 0; l < COAP_OPT_FILTER_LONG; l++) { - CU_ASSERT(coap_option_filter_set(filter, 256 + l) == 1); - } - - /* the next must fail and must not be found */ - CU_ASSERT(coap_option_filter_set(filter, 256 + COAP_OPT_FILTER_LONG) == 0); - CU_ASSERT(coap_option_filter_get(filter, 256 + COAP_OPT_FILTER_LONG) == 0); - - /* remove one item */ - CU_ASSERT(coap_option_filter_unset(filter, 256) == 1); - CU_ASSERT(coap_option_filter_get(filter, 256) == 0); - - /* now, storing a new filter must succeed */ - CU_ASSERT(coap_option_filter_set(filter, 256 + COAP_OPT_FILTER_LONG) == 1); - CU_ASSERT(coap_option_filter_get(filter, 256 + COAP_OPT_FILTER_LONG) == 1); - - /* and all other items must be available as well */ - for (l = 0; l < COAP_OPT_FILTER_LONG; l++) { - CU_ASSERT(coap_option_filter_get(filter, 256 + l + 1) == 1); - } - - /* set COAP_OPT_FILTER_SHORT short filters */ - for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) { - CU_ASSERT(coap_option_filter_set(filter, l) == 1); - } - - /* the next must fail and must not be found */ - CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 0); - CU_ASSERT(coap_option_filter_get(filter, COAP_OPT_FILTER_SHORT) == 0); - - /* remove one item */ - CU_ASSERT(coap_option_filter_unset(filter, 0) == 1); - CU_ASSERT(coap_option_filter_get(filter, 0) == 0); - - /* now, storing a new filter must succeed */ - CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 1); - CU_ASSERT(coap_option_filter_get(filter, COAP_OPT_FILTER_SHORT) == 1); - - /* and all other items must be available as well */ - for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) { - CU_ASSERT(coap_option_filter_get(filter, l + 1) == 1); - } -} - -/************************************************************************ - ** initialization - ************************************************************************/ - -CU_pSuite -t_init_option_tests(void) { - CU_pSuite suite[5]; - - suite[0] = CU_add_suite("option parser", NULL, NULL); - if (!suite[0]) { /* signal error */ - fprintf(stderr, "W: cannot add option parser test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define OPTION_TEST(n,s) \ - if (!CU_add_test(suite[0], s, t_parse_option##n)) { \ - fprintf(stderr, "W: cannot add option parser test (%s)\n", \ - CU_get_error_msg()); \ - } - - OPTION_TEST(1, "parse option #1"); - OPTION_TEST(2, "parse option #2"); - OPTION_TEST(3, "parse option #3"); - OPTION_TEST(4, "parse option #4"); - OPTION_TEST(5, "parse option #5"); - OPTION_TEST(6, "parse option #6"); - OPTION_TEST(7, "parse option #7"); - OPTION_TEST(8, "parse option #8"); - OPTION_TEST(9, "parse option #9"); - OPTION_TEST(10, "parse option #10"); - OPTION_TEST(11, "parse option #11"); - OPTION_TEST(12, "parse option #12"); - OPTION_TEST(13, "parse option #13"); - OPTION_TEST(14, "parse option #14"); - - if ((suite[1] = CU_add_suite("option encoder", NULL, NULL))) { -#define OPTION_ENCODER_TEST(n,s) \ - if (!CU_add_test(suite[1], s, t_encode_option##n)) { \ - fprintf(stderr, "W: cannot add option encoder test (%s)\n", \ - CU_get_error_msg()); \ - } - - OPTION_ENCODER_TEST(1, "encode option #1"); - OPTION_ENCODER_TEST(2, "encode option #2"); - OPTION_ENCODER_TEST(3, "encode option #3"); - OPTION_ENCODER_TEST(4, "encode option #4"); - OPTION_ENCODER_TEST(5, "encode option #5"); - OPTION_ENCODER_TEST(6, "encode option #6"); - OPTION_ENCODER_TEST(7, "encode option #7"); - OPTION_ENCODER_TEST(8, "encode option #8"); - - } else { - fprintf(stderr, "W: cannot add option encoder test suite (%s)\n", - CU_get_error_msg()); - } - - if ((suite[2] = CU_add_suite("option accessors", NULL, NULL))) { -#define OPTION_ACCESSOR_TEST(n,s) \ - if (!CU_add_test(suite[2], s, t_access_option##n)) { \ - fprintf(stderr, "W: cannot add option accessor function test (%s)\n", \ - CU_get_error_msg()); \ - } - - OPTION_ACCESSOR_TEST(1, "access option #1"); - OPTION_ACCESSOR_TEST(2, "access option #2"); - OPTION_ACCESSOR_TEST(3, "access option #3"); - OPTION_ACCESSOR_TEST(4, "access option #4"); - OPTION_ACCESSOR_TEST(5, "access option #5"); - OPTION_ACCESSOR_TEST(6, "access option #6"); - OPTION_ACCESSOR_TEST(7, "access option #7"); - - } else { - fprintf(stderr, "W: cannot add option acessor function test suite (%s)\n", - CU_get_error_msg()); - } - - if ((suite[3] = CU_add_suite("option iterator", NULL, NULL))) { -#define OPTION_ITERATOR_TEST(n,s) \ - if (!CU_add_test(suite[3], s, t_iterate_option##n)) { \ - fprintf(stderr, "W: cannot add option iterator test (%s)\n", \ - CU_get_error_msg()); \ - } - - OPTION_ITERATOR_TEST(1, "option iterator #1"); - OPTION_ITERATOR_TEST(2, "option iterator #2"); - OPTION_ITERATOR_TEST(3, "option iterator #3"); - OPTION_ITERATOR_TEST(4, "option iterator #4"); - OPTION_ITERATOR_TEST(5, "option iterator #5"); - OPTION_ITERATOR_TEST(6, "option iterator #6"); - OPTION_ITERATOR_TEST(7, "option iterator #7"); - OPTION_ITERATOR_TEST(8, "option iterator #8"); - OPTION_ITERATOR_TEST(9, "option iterator #9"); - OPTION_ITERATOR_TEST(10, "option iterator #10"); - - } else { - fprintf(stderr, "W: cannot add option iterator test suite (%s)\n", - CU_get_error_msg()); - } - - if ((suite[4] = CU_add_suite("option filter", NULL, NULL))) { -#define OPTION_FILTER_TEST(n,s) \ - if (!CU_add_test(suite[4], s, t_filter_option##n)) { \ - fprintf(stderr, "W: cannot add option filter test (%s)\n", \ - CU_get_error_msg()); \ - } - - OPTION_FILTER_TEST(1, "option filter #1"); - OPTION_FILTER_TEST(2, "option filter #2"); - OPTION_FILTER_TEST(3, "option filter #3"); - - } else { - fprintf(stderr, "W: cannot add option filter test suite (%s)\n", - CU_get_error_msg()); - } - - return suite[0]; -} - diff --git a/components/coap/libcoap/tests/test_options.h b/components/coap/libcoap/tests/test_options.h deleted file mode 100644 index 3ffcefe3e..000000000 --- a/components/coap/libcoap/tests/test_options.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_option_tests(void); diff --git a/components/coap/libcoap/tests/test_pdu.c b/components/coap/libcoap/tests/test_pdu.c deleted file mode 100644 index 13608308f..000000000 --- a/components/coap/libcoap/tests/test_pdu.c +++ /dev/null @@ -1,694 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_pdu.h" - -#include - -#include -#include -#include -#include - -coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ - -/************************************************************************ - ** PDU decoder - ************************************************************************/ - -static void -t_parse_pdu1(void) { - uint8_t teststr[] = { 0x40, 0x01, 0x93, 0x34 }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_CON); - CU_ASSERT(pdu->hdr->token_length == 0); - CU_ASSERT(pdu->hdr->code == COAP_REQUEST_GET); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); - CU_ASSERT_PTR_NULL(pdu->data); -} - -static void -t_parse_pdu2(void) { - uint8_t teststr[] = { 0x55, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); - CU_ASSERT(pdu->hdr->token_length == 5); - CU_ASSERT(pdu->hdr->code == 0x69); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); - CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); - CU_ASSERT_PTR_NULL(pdu->data); -} - -static void -t_parse_pdu3(void) { - uint8_t teststr[] = { 0x53, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu4(void) { - /* illegal token length */ - uint8_t teststr[] = { 0x59, 0x69, 0x12, 0x34, - 't', 'o', 'k', 'e', 'n', '1', '2', '3', '4' }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); - - teststr[0] = 0x5f; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu5(void) { - /* PDU with options */ - uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', - 'n', 0x00, 0xc1, 0x00 - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); - CU_ASSERT(pdu->hdr->token_length == 5); - CU_ASSERT(pdu->hdr->code == 0x73); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); - CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); - CU_ASSERT_PTR_NULL(pdu->data); - - /* FIXME: check options */ -} - -static void -t_parse_pdu6(void) { - /* PDU with options that exceed the PDU */ - uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', - 'n', 0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03 - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu7(void) { - /* PDU with options and payload */ - uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', - 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', - 'l', 'o', 'a', 'd' - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); - CU_ASSERT(pdu->hdr->token_length == 5); - CU_ASSERT(pdu->hdr->code == 0x73); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); - CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); - - /* FIXME: check options */ - - CU_ASSERT(pdu->data == (unsigned char *)pdu->hdr + 13); - CU_ASSERT(memcmp(pdu->data, teststr + 13, 7) == 0); -} - -static void -t_parse_pdu8(void) { - /* PDU without options but with payload */ - uint8_t teststr[] = { 0x50, 0x73, 0x12, 0x34, - 0xff, 'p', 'a', 'y', 'l', 'o', 'a', - 'd' - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); - CU_ASSERT(pdu->hdr->token_length == 0); - CU_ASSERT(pdu->hdr->code == 0x73); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); - - /* FIXME: check options */ - - CU_ASSERT(pdu->data == (unsigned char *)pdu->hdr + 5); - CU_ASSERT(memcmp(pdu->data, teststr + 5, 7) == 0); -} - -static void -t_parse_pdu9(void) { - /* PDU without options and payload but with payload start marker */ - uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, 0xff }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu10(void) { - /* PDU without payload but with options and payload start marker */ - uint8_t teststr[] = { 0x53, 0x73, 0x12, 0x34, 't', 'o', 'k', - 0x30, 0xc1, 0x00, 0xff - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu11(void) { - uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34 }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_ACK); - CU_ASSERT(pdu->hdr->token_length == 0); - CU_ASSERT(pdu->hdr->code == 0); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); -} - -static void -t_parse_pdu12(void) { - /* RST */ - uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34 }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result > 0); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(pdu->hdr->version == 1); - CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_RST); - CU_ASSERT(pdu->hdr->token_length == 0); - CU_ASSERT(pdu->hdr->code == 0); - CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); -} - -static void -t_parse_pdu13(void) { - /* RST with content */ - uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, - 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -static void -t_parse_pdu14(void) { - /* ACK with content */ - uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34, - 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' - }; - int result; - - result = coap_pdu_parse((unsigned char *)teststr, sizeof(teststr), pdu); - CU_ASSERT(result == 0); -} - -/************************************************************************ - ** PDU encoder - ************************************************************************/ - -static void -t_encode_pdu1(void) { - uint8_t teststr[] = { 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; - int result; - - coap_pdu_clear(pdu, pdu->max_size); - pdu->hdr->type = COAP_MESSAGE_CON; - pdu->hdr->code = COAP_REQUEST_GET; - pdu->hdr->id = htons(0x1234); - - result = coap_add_token(pdu, 5, (unsigned char *)"token"); - - CU_ASSERT(result == 1); - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT_PTR_NULL(pdu->data); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu2(void) { - size_t old_max = pdu->max_size; - int result; - - coap_pdu_clear(pdu, 7); /* set very small PDU size */ - - pdu->hdr->type = COAP_MESSAGE_CON; - pdu->hdr->code = COAP_REQUEST_GET; - pdu->hdr->id = htons(0x1234); - - result = coap_add_token(pdu, 5, (unsigned char *)"token"); - - CU_ASSERT(result == 0); - - coap_pdu_clear(pdu, old_max); /* restore PDU size */ -} - -static void -t_encode_pdu3(void) { - int result; - - result = coap_add_token(pdu, 9, (unsigned char *)"123456789"); - - CU_ASSERT(result == 0); -} - -static void -t_encode_pdu4(void) { - /* PDU with options */ - uint8_t teststr[] = { 0x60, 0x99, 0x12, 0x34, 0x3d, 0x05, 0x66, 0x61, - 0x6e, 0x63, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x2e, 0x63, 0x6f, 0x61, 0x70, 0x2e, 0x6d, 0x65, - 0x84, 0x70, 0x61, 0x74, 0x68, 0x00, 0xe8, 0x1e, - 0x28, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x6f, 0x70, - 0x74 - }; - int result; - - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_ACK; - pdu->hdr->code = 0x99; - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_option(pdu, COAP_OPTION_URI_HOST, - 18, (unsigned char *)"fancyproxy.coap.me"); - - CU_ASSERT(result == 20); - CU_ASSERT(pdu->max_delta == 3); - CU_ASSERT(pdu->length == 24); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_URI_PATH, - 4, (unsigned char *)"path"); - - CU_ASSERT(result == 5); - CU_ASSERT(pdu->max_delta == 11); - CU_ASSERT(pdu->length == 29); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 0, NULL); - - CU_ASSERT(result == 1); - CU_ASSERT(pdu->max_delta == 11); - CU_ASSERT(pdu->length == 30); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, 8000, 8, (unsigned char *)"fancyopt"); - - CU_ASSERT(result == 11); - CU_ASSERT(pdu->max_delta == 8000); - CU_ASSERT(pdu->length == 41); - CU_ASSERT_PTR_NULL(pdu->data); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu5(void) { - /* PDU with token and options */ - uint8_t teststr[] = { 0x68, 0x84, 0x12, 0x34, '1', '2', '3', '4', - '5', '6', '7', '8', 0x18, 0x41, 0x42, 0x43, - 0x44, 0x45, 0x46, 0x47, 0x48, 0xd1, 0x03, 0x12 - }; - int result; - - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_ACK; - pdu->hdr->code = COAP_RESPONSE_CODE(404); - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_token(pdu, 8, (unsigned char *)"12345678"); - - CU_ASSERT(pdu->length == 12); - - result = coap_add_option(pdu, COAP_OPTION_IF_MATCH, - 8, (unsigned char *)"ABCDEFGH"); - - CU_ASSERT(result == 9); - CU_ASSERT(pdu->max_delta == 1); - CU_ASSERT(pdu->length == 21); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_ACCEPT, - 1, (unsigned char *)"\x12"); - - CU_ASSERT(result == 3); - CU_ASSERT(pdu->max_delta == 17); - CU_ASSERT(pdu->length == 24); - CU_ASSERT_PTR_NULL(pdu->data); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu6(void) { - /* PDU with data */ - uint8_t teststr[] = { 0x50, 0x02, 0x12, 0x34, 0xff, '1', '2', '3', - '4', '5', '6', '7', '8' - }; - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_NON; - pdu->hdr->code = COAP_REQUEST_POST; - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - CU_ASSERT_PTR_NULL(pdu->data); - - coap_add_data(pdu, 8, (unsigned char *)"12345678"); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu7(void) { - /* PDU with empty data */ - uint8_t teststr[] = { 0x40, 0x43, 0x12, 0x34 }; - int result; - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_CON; - pdu->hdr->code = COAP_RESPONSE_CODE(203); - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_data(pdu, 0, NULL); - - CU_ASSERT(result > 0); - CU_ASSERT(pdu->length == 4); - CU_ASSERT_PTR_NULL(pdu->data); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu8(void) { - /* PDU with token and data */ - uint8_t teststr[] = { 0x42, 0x43, 0x12, 0x34, 0x00, 0x01, 0xff, 0x00 }; - int result; - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_CON; - pdu->hdr->code = COAP_RESPONSE_CODE(203); - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_token(pdu, 2, (unsigned char *)"\x00\x01"); - - CU_ASSERT(result > 0); - - result = coap_add_data(pdu, 1, (unsigned char *)"\0"); - - CU_ASSERT(result > 0); - CU_ASSERT(pdu->length == 8); - CU_ASSERT(pdu->data == (unsigned char *)pdu->hdr + 7); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu9(void) { - /* PDU with options and data */ - uint8_t teststr[] = { 0x60, 0x44, 0x12, 0x34, 0x48, 's', 'o', 'm', - 'e', 'e', 't', 'a', 'g', 0x10, 0xdd, 0x11, - 0x04, 's', 'o', 'm', 'e', 'r', 'a', 't', - 'h', 'e', 'r', 'l', 'o', 'n', 'g', 'u', - 'r', 'i', 0xff, 'd', 'a', 't', 'a' - }; - int result; - - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_ACK; - pdu->hdr->code = COAP_RESPONSE_CODE(204); - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_option(pdu, COAP_OPTION_ETAG, 8, (unsigned char *)"someetag"); - - CU_ASSERT(result == 9); - CU_ASSERT(pdu->max_delta == 4); - CU_ASSERT(pdu->length == 13); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_IF_NONE_MATCH, 0, NULL); - - CU_ASSERT(result == 1); - CU_ASSERT(pdu->max_delta == 5); - CU_ASSERT(pdu->length == 14); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_PROXY_URI, - 17, (unsigned char *)"someratherlonguri"); - - CU_ASSERT(result == 20); - CU_ASSERT(pdu->max_delta == 35); - CU_ASSERT(pdu->length == 34); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_data(pdu, 4, (unsigned char *)"data"); - - CU_ASSERT(result > 0); - CU_ASSERT(pdu->length == 39); - CU_ASSERT(pdu->data == (unsigned char *)pdu->hdr + 35); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu10(void) { - /* PDU with token, options and data */ - uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, - 'c', 'o', 'a', 'p', ':', '/', '/', 'e', - 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', - 'o', 'm', '/', '1', '2', '3', '4', '5', - '/', '%', '3', 'F', 'x', 'y', 'z', '/', - '3', '0', '4', '8', '2', '3', '4', '2', - '3', '4', '/', '2', '3', '4', '0', '2', - '3', '4', '8', '2', '3', '4', '/', '2', - '3', '9', '0', '8', '4', '2', '3', '4', - '-', '2', '3', '/', '%', 'A', 'B', '%', - '3', '0', '%', 'a', 'f', '/', '+', '1', - '2', '3', '/', 'h', 'f', 'k', 's', 'd', - 'h', '/', '2', '3', '4', '8', '0', '-', - '2', '3', '4', '-', '9', '8', '2', '3', - '5', '/', '1', '2', '0', '4', '/', '2', - '4', '3', '5', '4', '6', '3', '4', '5', - '3', '4', '5', '2', '4', '3', '/', '0', - '1', '9', '8', 's', 'd', 'n', '3', '-', - 'a', '-', '3', '/', '/', '/', 'a', 'f', - 'f', '0', '9', '3', '4', '/', '9', '7', - 'u', '2', '1', '4', '1', '/', '0', '0', - '0', '2', '/', '3', '9', '3', '2', '4', - '2', '3', '5', '3', '2', '/', '5', '6', - '2', '3', '4', '0', '2', '3', '/', '-', - '-', '-', '-', '/', '=', '1', '2', '3', - '4', '=', '/', '0', '9', '8', '1', '4', - '1', '-', '9', '5', '6', '4', '6', '4', - '3', '/', '2', '1', '9', '7', '0', '-', - '-', '-', '-', '-', '/', '8', '2', '3', - '6', '4', '9', '2', '3', '4', '7', '2', - 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', - '0', '-', '9', '2', '1', '-', '3', '9', - '1', '2', '3', '-', '3', '4', '/', 0x0d, - 0x01, '/', '/', '4', '9', '2', '4', '0', - '3', '-', '-', '0', '9', '8', '/', 0xc1, - '*', 0xff, 'd', 'a', 't', 'a' - }; - int result; - - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_ACK; - pdu->hdr->code = COAP_RESPONSE_CODE(204); - pdu->hdr->id = htons(0x1234); - - CU_ASSERT(pdu->length == 4); - - result = coap_add_token(pdu, 2, (unsigned char *)"\0\0"); - - CU_ASSERT(result > 0); - result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, - (unsigned char *)"coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/"); - - CU_ASSERT(result == 257); - CU_ASSERT(pdu->max_delta == 8); - CU_ASSERT(pdu->length == 263); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 14, - (unsigned char *)"//492403--098/"); - - CU_ASSERT(result == 16); - CU_ASSERT(pdu->max_delta == 8); - CU_ASSERT(pdu->length == 279); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, - 1, (unsigned char *)"*"); - - CU_ASSERT(result == 2); - CU_ASSERT(pdu->max_delta == 20); - CU_ASSERT(pdu->length == 281); - CU_ASSERT_PTR_NULL(pdu->data); - - result = coap_add_data(pdu, 4, (unsigned char *)"data"); - - CU_ASSERT(result > 0); - CU_ASSERT(pdu->length == 286); - CU_ASSERT(pdu->data == (unsigned char *)pdu->hdr + 282); - - CU_ASSERT(pdu->length == sizeof(teststr)); - CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); -} - -static void -t_encode_pdu11(void) { - coap_log_t level = coap_get_log_level(); - /* data too long for PDU */ - size_t old_max = pdu->max_size; - int result; - - coap_pdu_clear(pdu, 8); /* clear PDU, with small maximum */ - - CU_ASSERT(pdu->data == NULL); - coap_set_log_level(LOG_CRIT); - result = coap_add_data(pdu, 10, (unsigned char *)"0123456789"); - coap_set_log_level(level); - - CU_ASSERT(result == 0); - CU_ASSERT(pdu->data == NULL); - - pdu->max_size = old_max; -} - -static int -t_pdu_tests_create(void) { - pdu = coap_pdu_init(0, 0, 0, COAP_MAX_PDU_SIZE); - - return pdu == NULL; -} - -static int -t_pdu_tests_remove(void) { - coap_delete_pdu(pdu); - return 0; -} - -CU_pSuite -t_init_pdu_tests(void) { - CU_pSuite suite[2]; - - suite[0] = CU_add_suite("pdu parser", t_pdu_tests_create, t_pdu_tests_remove); - if (!suite[0]) { /* signal error */ - fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define PDU_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \ - CU_get_error_msg()); \ - } - - PDU_TEST(suite[0], t_parse_pdu1); - PDU_TEST(suite[0], t_parse_pdu2); - PDU_TEST(suite[0], t_parse_pdu3); - PDU_TEST(suite[0], t_parse_pdu4); - PDU_TEST(suite[0], t_parse_pdu5); - PDU_TEST(suite[0], t_parse_pdu6); - PDU_TEST(suite[0], t_parse_pdu7); - PDU_TEST(suite[0], t_parse_pdu8); - PDU_TEST(suite[0], t_parse_pdu9); - PDU_TEST(suite[0], t_parse_pdu10); - PDU_TEST(suite[0], t_parse_pdu11); - PDU_TEST(suite[0], t_parse_pdu12); - PDU_TEST(suite[0], t_parse_pdu13); - PDU_TEST(suite[0], t_parse_pdu14); - - suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove); - if (suite[1]) { -#define PDU_ENCODER_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \ - CU_get_error_msg()); \ - } - PDU_ENCODER_TEST(suite[1], t_encode_pdu1); - PDU_ENCODER_TEST(suite[1], t_encode_pdu2); - PDU_ENCODER_TEST(suite[1], t_encode_pdu3); - PDU_ENCODER_TEST(suite[1], t_encode_pdu4); - PDU_ENCODER_TEST(suite[1], t_encode_pdu5); - PDU_ENCODER_TEST(suite[1], t_encode_pdu6); - PDU_ENCODER_TEST(suite[1], t_encode_pdu7); - PDU_ENCODER_TEST(suite[1], t_encode_pdu8); - PDU_ENCODER_TEST(suite[1], t_encode_pdu9); - PDU_ENCODER_TEST(suite[1], t_encode_pdu10); - PDU_ENCODER_TEST(suite[1], t_encode_pdu11); - - } else /* signal error */ - fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", - CU_get_error_msg()); - - return suite[0]; -} - diff --git a/components/coap/libcoap/tests/test_pdu.h b/components/coap/libcoap/tests/test_pdu.h deleted file mode 100644 index 992b37720..000000000 --- a/components/coap/libcoap/tests/test_pdu.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_pdu_tests(void); diff --git a/components/coap/libcoap/tests/test_sendqueue.c b/components/coap/libcoap/tests/test_sendqueue.c deleted file mode 100644 index 82d69d204..000000000 --- a/components/coap/libcoap/tests/test_sendqueue.c +++ /dev/null @@ -1,367 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_sendqueue.h" - -#include - -#include - -static coap_queue_t *sendqueue; - -/* timestamps for tests. The first element in this array denotes the - * base time in ticks, the following elements are timestamps relative - * to this basetime. - */ -static coap_tick_t timestamp[] = { - 0, 100, 200, 30, 160 -}; - -/* nodes for testing. node[0] is left empty */ -coap_queue_t *node[5]; - -static coap_tick_t -add_timestamps(coap_queue_t *queue, size_t num) { - coap_tick_t t = 0; - while (queue && num--) { - t += queue->t; - queue = queue->next; - } - - return t; -} - -static void -t_sendqueue1(void) { - int result = coap_insert_node(&sendqueue, node[1]); - - CU_ASSERT(result > 0); - CU_ASSERT_PTR_NOT_NULL(sendqueue); - CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); - CU_ASSERT(node[1]->t == timestamp[1]); -} - -static void -t_sendqueue2(void) { - int result; - - result = coap_insert_node(&sendqueue, node[2]); - - CU_ASSERT(result > 0); - CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); - CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]); - - CU_ASSERT(sendqueue->t == timestamp[1]); - CU_ASSERT(node[2]->t == timestamp[2] - timestamp[1]); -} - -/* insert new node as first element in queue */ -static void -t_sendqueue3(void) { - int result; - result = coap_insert_node(&sendqueue, node[3]); - - CU_ASSERT(result > 0); - - CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); - CU_ASSERT(node[3]->t == timestamp[3]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next); - CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next); - - CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]); - CU_ASSERT(sendqueue->next->next->t == timestamp[2] - timestamp[1]); -} - -/* insert new node as fourth element in queue */ -static void -t_sendqueue4(void) { - int result; - - result = coap_insert_node(&sendqueue, node[4]); - - CU_ASSERT(result > 0); - - CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next); - CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next); - CU_ASSERT_PTR_EQUAL(sendqueue->next->next, node[4]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next->next); - CU_ASSERT_PTR_EQUAL(sendqueue->next->next->next, node[2]); - - CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]); - CU_ASSERT(add_timestamps(sendqueue, 1) == timestamp[3]); - CU_ASSERT(add_timestamps(sendqueue, 2) == timestamp[1]); - CU_ASSERT(add_timestamps(sendqueue, 3) == timestamp[4]); - CU_ASSERT(add_timestamps(sendqueue, 4) == timestamp[2]); -} - -static void -t_sendqueue5(void) { - const coap_tick_diff_t delta1 = 20, delta2 = 130; - unsigned int result; - coap_tick_t now; - struct coap_context_t ctx; - - /* space for saving the current node timestamps */ - static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)]; - coap_queue_t *p; - int i; - - /* save timestamps of nodes in the sendqueue in their actual order */ - memset(times, 0, sizeof(times)); - for (p = sendqueue, i = 0; p; p = p->next, i++) { - times[i] = p->t; - } - - coap_ticks(&now); - ctx.sendqueue = sendqueue; - ctx.sendqueue_basetime = now; - - now -= delta1; - result = coap_adjust_basetime(&ctx, now); - - CU_ASSERT(result == 0); - CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); - CU_ASSERT(ctx.sendqueue_basetime == now); - CU_ASSERT(ctx.sendqueue->t == timestamp[3] + delta1); - - now += delta2; - result = coap_adjust_basetime(&ctx, now); - CU_ASSERT(result == 2); - CU_ASSERT(ctx.sendqueue_basetime == now); - CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); - CU_ASSERT(ctx.sendqueue->t == 0); - - CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next); - CU_ASSERT(ctx.sendqueue->next->t == 0); - - CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next->next); - CU_ASSERT(ctx.sendqueue->next->next->t == delta2 - delta1 - timestamp[1]); - - /* restore timestamps of nodes in the sendqueue */ - for (p = sendqueue, i = 0; p; p = p->next, i++) { - p->t = times[i]; - } -} - -static void -t_sendqueue6(void) { - unsigned int result; - coap_tick_t now; - const coap_tick_diff_t delta = 20; - struct coap_context_t ctx; - - /* space for saving the current node timestamps */ - static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)]; - coap_queue_t *p; - int i; - - /* save timestamps of nodes in the sendqueue in their actual order */ - memset(times, 0, sizeof(times)); - for (p = sendqueue, i = 0; p; p = p->next, i++) { - times[i] = p->t; - } - - coap_ticks(&now); - ctx.sendqueue = NULL; - ctx.sendqueue_basetime = now; - - result = coap_adjust_basetime(&ctx, now + delta); - - CU_ASSERT(result == 0); - CU_ASSERT(ctx.sendqueue_basetime == now + delta); - - /* restore timestamps of nodes in the sendqueue */ - for (p = sendqueue, i = 0; p; p = p->next, i++) { - p->t = times[i]; - } -} - -static void -t_sendqueue7(void) { - int result; - coap_queue_t *tmp_node; - - CU_ASSERT_PTR_NOT_NULL(sendqueue); - CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next); - CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]); - - result = coap_remove_from_queue(&sendqueue, 3, &tmp_node); - - CU_ASSERT(result == 1); - CU_ASSERT_PTR_NOT_NULL(tmp_node); - CU_ASSERT_PTR_EQUAL(tmp_node, node[3]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue); - CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); - - CU_ASSERT(sendqueue->t == timestamp[1]); -} - -static void -t_sendqueue8(void) { - int result; - coap_queue_t *tmp_node; - - result = coap_remove_from_queue(&sendqueue, 4, &tmp_node); - - CU_ASSERT(result == 1); - CU_ASSERT_PTR_NOT_NULL(tmp_node); - CU_ASSERT_PTR_EQUAL(tmp_node, node[4]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue); - CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); - CU_ASSERT(sendqueue->t == timestamp[1]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue->next); - CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]); - CU_ASSERT(sendqueue->next->t == timestamp[2] - timestamp[1]); - - CU_ASSERT_PTR_NULL(sendqueue->next->next); -} - -static void -t_sendqueue9(void) { - coap_queue_t *tmp_node; - struct coap_context_t ctx; - - /* Initialize a fake context that points to our global sendqueue - * Note that all changes happen on ctx.sendqueue. */ - ctx.sendqueue = sendqueue; - tmp_node = coap_peek_next(&ctx); - sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ - - CU_ASSERT_PTR_NOT_NULL(tmp_node); - CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); - CU_ASSERT_PTR_EQUAL(tmp_node, ctx.sendqueue); - - tmp_node = coap_pop_next(&ctx); - sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ - - CU_ASSERT_PTR_NOT_NULL(tmp_node); - CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); - - CU_ASSERT_PTR_NOT_NULL(sendqueue); - CU_ASSERT_PTR_EQUAL(sendqueue, node[2]); - - CU_ASSERT(tmp_node->t == timestamp[1]); - CU_ASSERT(sendqueue->t == timestamp[2]); - - CU_ASSERT_PTR_NULL(sendqueue->next); -} - -static void -t_sendqueue10(void) { - coap_queue_t *tmp_node; - struct coap_context_t ctx; - - /* Initialize a fake context that points to our global sendqueue - * Note that all changes happen on ctx.sendqueue. */ - ctx.sendqueue = sendqueue; - - tmp_node = coap_pop_next(&ctx); - sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ - - CU_ASSERT_PTR_NOT_NULL(tmp_node); - CU_ASSERT_PTR_EQUAL(tmp_node, node[2]); - - CU_ASSERT_PTR_NULL(sendqueue); - - CU_ASSERT(tmp_node->t == timestamp[2]); -} - -/* This function creates a set of nodes for testing. These nodes - * will exist for all tests and are modified by coap_insert_node() - * and coap_remove_from_queue(). - */ -static int -t_sendqueue_tests_create(void) { - size_t n, error = 0; - sendqueue = NULL; - coap_ticks(×tamp[0]); - - memset(node, 0, sizeof(node)); - for (n = 1; n < sizeof(node)/sizeof(coap_queue_t *); n++) { - node[n] = coap_new_node(); - if (!node[n]) { - error = 1; - break; - } - - node[n]->id = n; - node[n]->t = timestamp[n]; - } - - if (error) { - /* destroy all test nodes and set entry to zero */ - for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) { - if (node[n]) { - coap_delete_node(node[n]); - node[n] = NULL; - } - } - } - - return error; -} - -static int -t_sendqueue_tests_remove(void) { - size_t n; - - /* destroy all test nodes */ - for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) { - if (node[n]) { - coap_delete_node(node[n]); - } - } - - return 0; -} - -CU_pSuite -t_init_sendqueue_tests(void) { - CU_pSuite suite; - - suite = CU_add_suite("sendqueue", - t_sendqueue_tests_create, t_sendqueue_tests_remove); - if (!suite) { /* signal error */ - fprintf(stderr, "W: cannot add sendqueue test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define SENDQUEUE_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \ - CU_get_error_msg()); \ - } - - SENDQUEUE_TEST(suite, t_sendqueue1); - SENDQUEUE_TEST(suite, t_sendqueue2); - SENDQUEUE_TEST(suite, t_sendqueue3); - SENDQUEUE_TEST(suite, t_sendqueue4); - SENDQUEUE_TEST(suite, t_sendqueue5); - SENDQUEUE_TEST(suite, t_sendqueue6); - SENDQUEUE_TEST(suite, t_sendqueue7); - SENDQUEUE_TEST(suite, t_sendqueue8); - SENDQUEUE_TEST(suite, t_sendqueue9); - SENDQUEUE_TEST(suite, t_sendqueue10); - - return suite; -} - diff --git a/components/coap/libcoap/tests/test_sendqueue.h b/components/coap/libcoap/tests/test_sendqueue.h deleted file mode 100644 index 56f3c1edb..000000000 --- a/components/coap/libcoap/tests/test_sendqueue.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_sendqueue_tests(void); diff --git a/components/coap/libcoap/tests/test_uri.c b/components/coap/libcoap/tests/test_uri.c deleted file mode 100644 index 004cbd6ab..000000000 --- a/components/coap/libcoap/tests/test_uri.c +++ /dev/null @@ -1,463 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012,2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_uri.h" - -#include - -#include - -static void -t_parse_uri1(void) { - char teststr[] = "coap://[::1]/.well-known/core"; - - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 3); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); - - CU_ASSERT(uri.port == COAP_DEFAULT_PORT); - - CU_ASSERT(uri.path.length == 16); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri2(void) { - char teststr[] = "coap://[::1]:8000/.well-known/core"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 3); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); - - CU_ASSERT(uri.port == 8000); - - CU_ASSERT(uri.path.length == 16); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri3(void) { - char teststr[] = "coap://localhost/?foo&bla=fasel"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 9); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "localhost", 9); - - CU_ASSERT(uri.port == COAP_DEFAULT_PORT); - - CU_ASSERT(uri.path.length == 0); - - CU_ASSERT(uri.query.length == 13); - CU_ASSERT_NSTRING_EQUAL(uri.query.s, "foo&bla=fasel", 13); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri4(void) { - char teststr[] = "coap://:100000"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - CU_ASSERT(result < 0); -} - -static void -t_parse_uri5(void) { - char teststr[] = "coap://foo:100000"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 3); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo", 3); - - CU_ASSERT(uri.path.length == 0); - CU_ASSERT(uri.path.s == NULL); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - - CU_FAIL("invalid port not detected"); - } else { - CU_PASS("detected invalid port"); - } -} - -static void -t_parse_uri6(void) { - char teststr[] = "coap://134.102.218.2/.well-known/core"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 13); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "134.102.218.2", 13); - - CU_ASSERT(uri.port == COAP_DEFAULT_PORT); - - CU_ASSERT(uri.path.length == 16); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri7(void) { - char teststr[] = "coap://foo.bar:5683/some_resource/with/multiple/segments"; - int result; - coap_uri_t uri; - unsigned char buf[40]; - size_t buflen = sizeof(buf); - - /* The list of path segments to check against. Each segment is - preceded by a dummy option indicating that holds the (dummy) - delta value 0 and the actual segment length. */ - const unsigned char checkbuf[] = { - 0x0d, 0x00, 's', 'o', 'm', 'e', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', - 0x04, 'w', 'i', 't', 'h', - 0x08, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', - 0x08, 's', 'e', 'g', 'm', 'e', 'n', 't', 's' - }; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 7); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo.bar", 7); - - CU_ASSERT(uri.port == 5683); - - CU_ASSERT(uri.path.length == 36); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, "some_resource/with/multiple/segments", 36); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - - /* check path segments */ - result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - CU_ASSERT(result == 4); - CU_ASSERT(buflen == sizeof(checkbuf)); - CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri8(void) { - char teststr[] = "http://example.com/%7E%AB%13"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result < 0) { - CU_PASS("detected non-coap URI"); - } else { - CU_FAIL("non-coap URI not recognized"); - } -} - -static void -t_parse_uri9(void) { - char teststr[] = "http://example.com/%x"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result < 0) { - CU_PASS("detected non-coap URI"); - } else { - CU_FAIL("non-coap URI not recognized"); - } -} - -static void -t_parse_uri10(void) { - char teststr[] = "/absolute/path"; - int result; - coap_uri_t uri; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 0); - CU_ASSERT(uri.host.s == NULL); - - CU_ASSERT(uri.port == COAP_DEFAULT_PORT); - - CU_ASSERT(uri.path.length == 13); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, "absolute/path", 13); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri11(void) { - char teststr[] = - "coap://xn--18j4d.example/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"; - int result; - coap_uri_t uri; - unsigned char buf[40]; - size_t buflen = sizeof(buf); - - /* The list of path segments to check against. Each segment is - preceded by a dummy option indicating that holds the (dummy) - delta value 0 and the actual segment length. */ - const unsigned char checkbuf[] = { - 0x0d, 0x02, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, - 0xE3, 0x81, 0xAB, 0xE3, 0x81, 0xA1, 0xE3, 0x81, - 0xAF - }; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 17); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "xn--18j4d.example", 17); - - CU_ASSERT(uri.port == COAP_DEFAULT_PORT); - - CU_ASSERT(uri.path.length == 45); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, - "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF", 45); - - CU_ASSERT(uri.query.length == 0); - CU_ASSERT(uri.query.s == NULL); - - /* check path segments */ - result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - CU_ASSERT(result == 1); - CU_ASSERT(buflen == sizeof(checkbuf)); - CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri12(void) { - char teststr[] = "coap://198.51.100.1:61616//%2F//?%2F%2F&?%26"; - int result; - coap_uri_t uri; - unsigned char buf[40]; - size_t buflen = sizeof(buf); - - /* The list of path segments to check against. Each segment is - preceded by a dummy option indicating that holds the (dummy) - delta value 0 and the actual segment length. */ - const unsigned char uricheckbuf[] = { 0x00, 0x01, 0x2f, 0x00, 0x00 }; - const unsigned char querycheckbuf[] = { 0x02, 0x2f, 0x2f, 0x02, 0x3f, 0x26 }; - - result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); - if (result == 0) { - CU_ASSERT(uri.host.length == 12); - CU_ASSERT_NSTRING_EQUAL(uri.host.s, "198.51.100.1", 12); - - CU_ASSERT(uri.port == 61616); - - CU_ASSERT(uri.path.length == 6); - CU_ASSERT_NSTRING_EQUAL(uri.path.s, "/%2F//", 6); - - CU_ASSERT(uri.query.length == 11); - CU_ASSERT_NSTRING_EQUAL(uri.query.s, "%2F%2F&?%26", 11); - - /* check path segments */ - result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - CU_ASSERT(result == 4); - CU_ASSERT(buflen == sizeof(uricheckbuf)); - CU_ASSERT_NSTRING_EQUAL(buf, uricheckbuf, buflen); - - /* check query segments */ - buflen = sizeof(buf); - result = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); - CU_ASSERT(result == 2); - CU_ASSERT(buflen == sizeof(querycheckbuf)); - CU_ASSERT_NSTRING_EQUAL(buf, querycheckbuf, buflen); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri13(void) { - uint8_t teststr[] __attribute__ ((aligned (8))) = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 'f', 'o', - 'o', 0x3b, '.', 'w', 'e', 'l', 'l', '-', - 'k', 'n', 'o', 'w', 'n', 0x04, 'c', 'o', - 'r', 'e' - }; - - coap_pdu_t pdu = { - .max_size = sizeof(teststr), - .hdr = (coap_hdr_t *)teststr, - .length = sizeof(teststr) - }; - - coap_key_t key; - - coap_hash_request_uri(&pdu, key); - - CU_ASSERT(sizeof(key) == sizeof(COAP_DEFAULT_WKC_HASHKEY) - 1); - CU_ASSERT_NSTRING_EQUAL(key, COAP_DEFAULT_WKC_HASHKEY, sizeof(key)); -} - -static void -t_parse_uri14(void) { - char teststr[] = - "longerthan13lessthan270=0123456789012345678901234567890123456789"; - int result; - - /* buf is large enough to hold sizeof(teststr) - 1 bytes content and - * 2 bytes for the option header. */ - unsigned char buf[sizeof(teststr) + 1]; - size_t buflen = sizeof(buf); - - result = coap_split_query((unsigned char *)teststr, strlen(teststr), - buf, &buflen); - if (result >= 0) { - CU_ASSERT(buf[0] == 0x0d); - CU_ASSERT(buf[1] == strlen(teststr) - 13); - - CU_ASSERT_NSTRING_EQUAL(buf+2, teststr, strlen(teststr)); - } else { - CU_FAIL("uri parser error"); - } -} - -static void -t_parse_uri15(void) { - char teststr[] = - "longerthan13lessthan270=0123456789012345678901234567890123456789"; - int result; - - /* buf is too small to hold sizeof(teststr) - 1 bytes content and 2 - * bytes for the option header. */ - unsigned char buf[sizeof(teststr) - 1]; - size_t buflen = sizeof(buf); - - result = coap_split_query((unsigned char *)teststr, strlen(teststr), - buf, &buflen); - CU_ASSERT(result == 0); -} - -static void -t_parse_uri16(void) { - char teststr[] = - "longerthan13lessthan270=0123456789012345678901234567890123456789"; - int result; - - /* buf is too small to hold the option header. */ - unsigned char buf[1]; - size_t buflen = sizeof(buf); - - result = coap_split_query((unsigned char *)teststr, strlen(teststr), - buf, &buflen); - CU_ASSERT(result == 0); -} - -static void -t_parse_uri17(void) { - char teststr[] = - "thisislongerthan269=" - "01234567890123456789012345678901234567890123456789" - "01234567890123456789012345678901234567890123456789" - "01234567890123456789012345678901234567890123456789" - "01234567890123456789012345678901234567890123456789" - "01234567890123456789012345678901234567890123456789"; - int result; - - /* buf is large enough to hold sizeof(teststr) - 1 bytes content and - * 3 bytes for the option header. */ - unsigned char buf[sizeof(teststr) + 2]; - size_t buflen = sizeof(buf); - - result = coap_split_query((unsigned char *)teststr, strlen(teststr), - buf, &buflen); - if (result >= 0) { - CU_ASSERT(buf[0] == 0x0e); - CU_ASSERT(buf[1] == (((strlen(teststr) - 269) >> 8) & 0xff)); - CU_ASSERT(buf[2] == ((strlen(teststr) - 269) & 0xff)); - - CU_ASSERT_NSTRING_EQUAL(buf+3, teststr, strlen(teststr)); - } else { - CU_FAIL("uri parser error"); - } -} - -CU_pSuite -t_init_uri_tests(void) { - CU_pSuite suite; - - suite = CU_add_suite("uri parser", NULL, NULL); - if (!suite) { /* signal error */ - fprintf(stderr, "W: cannot add uri parser test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define URI_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add uri parser test (%s)\n", \ - CU_get_error_msg()); \ - } - - URI_TEST(suite, t_parse_uri1); - URI_TEST(suite, t_parse_uri2); - URI_TEST(suite, t_parse_uri3); - URI_TEST(suite, t_parse_uri4); - URI_TEST(suite, t_parse_uri5); - URI_TEST(suite, t_parse_uri6); - URI_TEST(suite, t_parse_uri7); - URI_TEST(suite, t_parse_uri8); - URI_TEST(suite, t_parse_uri9); - URI_TEST(suite, t_parse_uri10); - URI_TEST(suite, t_parse_uri11); - URI_TEST(suite, t_parse_uri12); - URI_TEST(suite, t_parse_uri13); - URI_TEST(suite, t_parse_uri14); - URI_TEST(suite, t_parse_uri15); - URI_TEST(suite, t_parse_uri16); - URI_TEST(suite, t_parse_uri17); - - return suite; -} - diff --git a/components/coap/libcoap/tests/test_uri.h b/components/coap/libcoap/tests/test_uri.h deleted file mode 100644 index 165fad3ff..000000000 --- a/components/coap/libcoap/tests/test_uri.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2012 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_uri_tests(void); diff --git a/components/coap/libcoap/tests/test_wellknown.c b/components/coap/libcoap/tests/test_wellknown.c deleted file mode 100644 index 57a4db7a4..000000000 --- a/components/coap/libcoap/tests/test_wellknown.c +++ /dev/null @@ -1,331 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013--2015 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" -#include "test_wellknown.h" - -#include - -#include -#include -#include -#include -#include - -#define TEST_PDU_SIZE 120 -#define TEST_URI_LEN 4 - -coap_context_t *ctx; /* Holds the coap context for most tests */ -coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ - -static void -t_wellknown1(void) { - coap_print_status_t result; - coap_resource_t *r; - unsigned char buf[40]; - size_t buflen, offset, ofs; - - char teststr[] = { /* ;title="some attribute";ct=0 (31 chars) */ - '<', '/', '>', ';', 't', 'i', 't', 'l', - 'e', '=', '"', 's', 'o', 'm', 'e', ' ', - 'a', 't', 't', 'r', 'i', 'b', 'u', 't', - 'e', '"', ';', 'c', 't', '=', '0' - }; - - r = coap_resource_init(NULL, 0, 0); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"some attribute\"", 16, 0); - - coap_add_resource(ctx, r); - - for (offset = 0; offset < sizeof(teststr); offset++) { - ofs = offset; - buflen = sizeof(buf); - - result = coap_print_link(r, buf, &buflen, &ofs); - - CU_ASSERT(result == sizeof(teststr) - offset); - CU_ASSERT(buflen == sizeof(teststr)); - CU_ASSERT(memcmp(buf, teststr + offset, sizeof(teststr) - offset) == 0); - } - - /* offset points behind teststr */ - ofs = offset; - buflen = sizeof(buf); - result = coap_print_link(r, buf, &buflen, &ofs); - - CU_ASSERT(result == 0); - CU_ASSERT(buflen == sizeof(teststr)); - - /* offset exceeds buffer */ - buflen = sizeof(buf); - ofs = buflen; - result = coap_print_link(r, buf, &buflen, &ofs); - - CU_ASSERT(result == 0); - CU_ASSERT(buflen == sizeof(teststr)); -} - -static void -t_wellknown2(void) { - coap_print_status_t result; - coap_resource_t *r; - unsigned char buf[10]; /* smaller than teststr */ - size_t buflen, offset, ofs; - - char teststr[] = { /* ,;if="one";obs (21 chars) */ - '<', '/', 'a', 'b', 'c', 'd', '>', ';', - 'i', 'f', '=', '"', 'o', 'n', 'e', '"', - ';', 'o', 'b', 's' - }; - - r = coap_resource_init((unsigned char *)"abcd", 4, 0); - r->observable = 1; - coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"one\"", 5, 0); - - coap_add_resource(ctx, r); - - for (offset = 0; offset < sizeof(teststr) - sizeof(buf); offset++) { - ofs = offset; - buflen = sizeof(buf); - - result = coap_print_link(r, buf, &buflen, &ofs); - - CU_ASSERT(result == (COAP_PRINT_STATUS_TRUNC | sizeof(buf))); - CU_ASSERT(buflen == sizeof(teststr)); - CU_ASSERT(ofs == 0); - CU_ASSERT(memcmp(buf, teststr + offset, sizeof(buf)) == 0); - } - - /* from here on, the resource description fits into buf */ - for (; offset < sizeof(teststr); offset++) { - ofs = offset; - buflen = sizeof(buf); - result = coap_print_link(r, buf, &buflen, &ofs); - - CU_ASSERT(result == sizeof(teststr) - offset); - CU_ASSERT(buflen == sizeof(teststr)); - CU_ASSERT(ofs == 0); - CU_ASSERT(memcmp(buf, teststr + offset, - COAP_PRINT_OUTPUT_LENGTH(result)) == 0); - } - - /* offset exceeds buffer */ - buflen = sizeof(buf); - ofs = offset; - result = coap_print_link(r, buf, &buflen, &ofs); - CU_ASSERT(result == 0); - CU_ASSERT(buflen == sizeof(teststr)); - CU_ASSERT(ofs == offset - sizeof(teststr)); -} - -static void -t_wellknown3(void) { - coap_print_status_t result; - int j; - coap_resource_t *r; - static char uris[2 * COAP_MAX_PDU_SIZE]; - unsigned char *uribuf = (unsigned char *)uris; - unsigned char buf[40]; - size_t buflen = sizeof(buf); - size_t offset; - const unsigned short num_resources = (sizeof(uris) / TEST_URI_LEN) - 1; - - /* , (TEST_URI_LEN + 4 chars) */ - for (j = 0; j < num_resources; j++) { - int len = snprintf((char *)uribuf, TEST_URI_LEN + 1, - "%0*d", TEST_URI_LEN, j); - r = coap_resource_init(uribuf, len, 0); - coap_add_resource(ctx, r); - uribuf += TEST_URI_LEN; - } - - /* the following test assumes that the first two resources from - * t_wellknown1() and t_wellknown2() need more than buflen - * characters. Otherwise, CU_ASSERT(result > 0) will fail. - */ - offset = num_resources * (TEST_URI_LEN + 4); - result = coap_print_wellknown(ctx, buf, &buflen, offset, NULL); - CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0 ); - CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) > 0); -} - -/* Create wellknown response for request without Block-option. */ -static void -t_wellknown4(void) { - coap_pdu_t *response; - coap_block_t block; - - response = coap_wellknown_response(ctx, pdu); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); - - CU_ASSERT(block.num == 0); - CU_ASSERT(block.m == 1); - CU_ASSERT(1 << (block.szx + 4) - == (unsigned char *)response->hdr + response->length - response->data); - - coap_delete_pdu(response); -} - -/* Create wellknown response for request with Block2-option and an szx - * value smaller than COAP_MAX_BLOCK_SZX. - */ -static void -t_wellknown5(void) { - coap_pdu_t *response; - coap_block_t inblock = { .num = 1, .m = 0, .szx = 1 }; - coap_block_t block; - unsigned char buf[3]; - - if (!coap_add_option(pdu, COAP_OPTION_BLOCK2, - coap_encode_var_bytes(buf, ((inblock.num << 4) | - (inblock.m << 3) | - inblock.szx)), buf)) { - CU_FAIL("cannot add Block2 option"); - return; - } - - response = coap_wellknown_response(ctx, pdu); - - CU_ASSERT_PTR_NOT_NULL(response); - - CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); - - CU_ASSERT(block.num == inblock.num); - CU_ASSERT(block.m == 1); - CU_ASSERT(1 << (block.szx + 4) - == (unsigned char *)response->hdr + response->length - response->data); - - coap_delete_pdu(response); -} - -static void -t_wellknown6(void) { - coap_pdu_t *response; - coap_block_t block = { .num = 0, .szx = 6 }; - unsigned char buf[TEST_PDU_SIZE]; - - - do { - coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ - - pdu->hdr->type = COAP_MESSAGE_NON; - pdu->hdr->code = COAP_REQUEST_GET; - pdu->hdr->id = htons(0x1234); - - CU_ASSERT_PTR_NOT_NULL(pdu); - - if (!pdu || !coap_add_option(pdu, COAP_OPTION_BLOCK2, - coap_encode_var_bytes(buf, - ((block.num << 4) | block.szx)), buf)) { - CU_FAIL("cannot create request"); - return; - } - - response = coap_wellknown_response(ctx, pdu); - - CU_ASSERT_PTR_NOT_NULL(response); - - /* coap_show_pdu(response); */ - - CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); - - block.num++; - coap_delete_pdu(response); - } while (block.m == 1); -} - -static int -t_wkc_tests_create(void) { - coap_address_t addr; - - coap_address_init(&addr); - - addr.size = sizeof(struct sockaddr_in6); - addr.addr.sin6.sin6_family = AF_INET6; - addr.addr.sin6.sin6_addr = in6addr_any; - addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); - - ctx = coap_new_context(&addr); - - pdu = coap_pdu_init(0, 0, 0, TEST_PDU_SIZE); -#if 0 - /* add resources to coap context */ - if (ctx && pdu) { - coap_resource_t *r; - static char _buf[2 * COAP_MAX_PDU_SIZE]; - unsigned char *buf = (unsigned char *)_buf; - int i; - - /* ;title="some attribute";ct=0 (31 chars) */ - r = coap_resource_init(NULL, 0, 0); - - coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); - coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"some attribute\"", 16, 0); - coap_add_resource(ctx, r); - - /* ,;if="one";obs (21 chars) */ - r = coap_resource_init((unsigned char *)"abcd", 4, 0); - r->observable = 1; - coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"one\"", 5, 0); - - coap_add_resource(ctx, r); - - /* , (TEST_URI_LEN + 4 chars) */ - for (i = 0; i < sizeof(_buf) / (TEST_URI_LEN + 4); i++) { - int len = snprintf((char *)buf, TEST_URI_LEN + 1, - "%0*d", TEST_URI_LEN, i); - r = coap_resource_init(buf, len, 0); - coap_add_resource(ctx, r); - buf += TEST_URI_LEN + 1; - } - - } -#endif - return ctx == NULL || pdu == NULL; -} - -static int -t_wkc_tests_remove(void) { - coap_delete_pdu(pdu); - coap_free_context(ctx); - return 0; -} - -CU_pSuite -t_init_wellknown_tests(void) { - CU_pSuite suite; - - suite = CU_add_suite(".well-known/core", t_wkc_tests_create, t_wkc_tests_remove); - if (!suite) { /* signal error */ - fprintf(stderr, "W: cannot add .well-known/core test suite (%s)\n", - CU_get_error_msg()); - - return NULL; - } - -#define WKC_TEST(s,t) \ - if (!CU_ADD_TEST(s,t)) { \ - fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \ - CU_get_error_msg()); \ - } - - WKC_TEST(suite, t_wellknown1); - WKC_TEST(suite, t_wellknown2); - WKC_TEST(suite, t_wellknown3); - WKC_TEST(suite, t_wellknown4); - WKC_TEST(suite, t_wellknown5); - WKC_TEST(suite, t_wellknown6); - - return suite; -} - diff --git a/components/coap/libcoap/tests/test_wellknown.h b/components/coap/libcoap/tests/test_wellknown.h deleted file mode 100644 index 47f20b344..000000000 --- a/components/coap/libcoap/tests/test_wellknown.h +++ /dev/null @@ -1,11 +0,0 @@ -/* libcoap unit tests - * - * Copyright (C) 2013 Olaf Bergmann - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include - -CU_pSuite t_init_wellknown_tests(void); diff --git a/components/coap/libcoap/tests/testdriver.c b/components/coap/libcoap/tests/testdriver.c deleted file mode 100644 index b65dd6182..000000000 --- a/components/coap/libcoap/tests/testdriver.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include -#include - -/* #include */ - -#include "test_uri.h" -#include "test_options.h" -#include "test_pdu.h" -#include "test_error_response.h" -#include "test_sendqueue.h" -#include "test_wellknown.h" - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -int -main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - CU_ErrorCode result; - CU_BasicRunMode run_mode = CU_BRM_VERBOSE; - - if (CU_initialize_registry() != CUE_SUCCESS) { - fprintf(stderr, "E: test framework initialization failed\n"); - return -2; - } - - t_init_uri_tests(); - t_init_option_tests(); - t_init_pdu_tests(); - t_init_error_response_tests(); - t_init_sendqueue_tests(); - t_init_wellknown_tests(); - - CU_basic_set_mode(run_mode); - result = CU_basic_run_tests(); - - CU_cleanup_registry(); - - return result; -} diff --git a/components/coap/port/coap_io.c b/components/coap/port/coap_io.c new file mode 100644 index 000000000..a8f35c180 --- /dev/null +++ b/components/coap/port/coap_io.c @@ -0,0 +1,1417 @@ +/* coap_io.c -- Default network I/O functions for libcoap + * + * Copyright (C) 2012,2014,2016-2019 Olaf Bergmann and others + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "coap_config.h" + +#ifdef HAVE_STDIO_H +# include +#endif + +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +# define OPTVAL_T(t) (t) +# define OPTVAL_GT(t) (t) +#endif +#ifdef HAVE_SYS_IOCTL_H + #include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +# define OPTVAL_T(t) (const char*)(t) +# define OPTVAL_GT(t) (char*)(t) +# undef CMSG_DATA +# define CMSG_DATA WSA_CMSG_DATA +#endif +#ifdef HAVE_SYS_UIO_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#ifdef WITH_CONTIKI +# include "uip.h" +#endif + +#include "libcoap.h" +#include "coap_debug.h" +#include "mem.h" +#include "net.h" +#include "coap_io.h" +#include "pdu.h" +#include "utlist.h" +#include "resource.h" + +#if !defined(WITH_CONTIKI) + /* define generic PKTINFO for IPv4 */ +#if defined(IP_PKTINFO) +# define GEN_IP_PKTINFO IP_PKTINFO +#elif defined(IP_RECVDSTADDR) +# define GEN_IP_PKTINFO IP_RECVDSTADDR +#else +# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." +#endif /* IP_PKTINFO */ + +/* define generic KTINFO for IPv6 */ +#ifdef IPV6_RECVPKTINFO +# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO +#elif defined(IPV6_PKTINFO) +# define GEN_IPV6_PKTINFO IPV6_PKTINFO +#else +# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." +#endif /* IPV6_RECVPKTINFO */ +#endif + +void coap_free_endpoint(coap_endpoint_t *ep); + +#ifdef WITH_CONTIKI +static int ep_initialized = 0; + +struct coap_endpoint_t * + coap_malloc_endpoint() { + static struct coap_endpoint_t ep; + + if (ep_initialized) { + return NULL; + } else { + ep_initialized = 1; + return &ep; + } +} + +void +coap_mfree_endpoint(struct coap_endpoint_t *ep) { + ep_initialized = 0; + coap_session_mfree(&ep->hello); +} + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + sock->conn = udp_new(NULL, 0, NULL); + + if (!sock->conn) { + coap_log(LOG_WARNING, "coap_socket_bind_udp"); + return 0; + } + + coap_address_init(bound_addr); + uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr); + bound_addr->port = listen_addr->port; + udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port); + return 1; +} + +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + return 0; +} + +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { + return -1; +} + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { + return -1; +} + +void coap_socket_close(coap_socket_t *sock) { + if (sock->conn) + uip_udp_remove((struct uip_udp_conn *)sock->conn); + sock->flags = COAP_SOCKET_EMPTY; +} + +#else + +static const char *coap_socket_format_errno( int error ); + +struct coap_endpoint_t * + coap_malloc_endpoint(void) { + return (struct coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(struct coap_endpoint_t)); +} + +void +coap_mfree_endpoint(struct coap_endpoint_t *ep) { + coap_session_mfree(&ep->hello); + coap_free_type(COAP_ENDPOINT, ep); +} + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + int on = 1, off = 0; +#ifdef _WIN32 + u_long u_on = 1; +#endif + + sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, + "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror()); + goto error; + } + +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, + "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror()); + } + + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + + switch (listen_addr->addr.sa.sa_family) { + case AF_INET: + if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n", + coap_socket_strerror()); + break; + case AF_INET6: + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); + if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n", + coap_socket_strerror()); + setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)); /* ignore error, because the likely cause is that IPv4 is disabled at the os level */ + break; + default: + coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n"); + break; + } + + if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + + bound_addr->size = (socklen_t)sizeof(*bound_addr); + if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) { + coap_log(LOG_WARNING, + "coap_socket_bind_udp: getsockname: %s\n", + coap_socket_strerror()); + goto error; + } + + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + int on = 1, off = 0; +#ifdef _WIN32 + u_long u_on = 1; +#endif + coap_address_t connect_addr; + coap_address_copy( &connect_addr, server ); + + sock->flags &= ~COAP_SOCKET_CONNECTED; + sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } + + switch (server->addr.sa.sa_family) { + case AF_INET: + if (connect_addr.addr.sin.sin_port == 0) + connect_addr.addr.sin.sin_port = htons(default_port); + break; + case AF_INET6: + if (connect_addr.addr.sin6.sin6_port == 0) + connect_addr.addr.sin6.sin6_port = htons(default_port); + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); + break; + default: + coap_log(LOG_ALERT, "coap_socket_connect_tcp1: unsupported sa_family\n"); + break; + } + + if (local_if && local_if->addr.sa.sa_family) { + coap_address_copy(local_addr, local_if); + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: bind: %s\n", + coap_socket_strerror()); + goto error; + } + } else { + local_addr->addr.sa.sa_family = server->addr.sa.sa_family; + } + + if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAEWOULDBLOCK) { +#else + if (errno == EINPROGRESS) { +#endif + /* + * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes + * by underlying TLS libraries during connect() and we do not want to + * assert() in coap_read_session() or coap_write_session() when called by coap_read() + */ + sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED; + return 1; + } + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: connect: %s\n", + coap_socket_strerror()); + goto error; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getpeername: %s\n", + coap_socket_strerror()); + } + + sock->flags |= COAP_SOCKET_CONNECTED; + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + int error = 0; +#ifdef _WIN32 + int optlen = (int)sizeof( error ); +#else + socklen_t optlen = (socklen_t)sizeof( error ); +#endif + + sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT); + + if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error), + &optlen) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_finish_connect_tcp: getsockopt: %s\n", + coap_socket_strerror()); + } + + if (error) { + coap_log(LOG_WARNING, + "coap_socket_finish_connect_tcp: connect failed: %s\n", + coap_socket_format_errno(error)); + coap_socket_close(sock); + return 0; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp: getpeername: %s\n", + coap_socket_strerror()); + } + + return 1; +} + +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + int on = 1, off = 0; +#ifdef _WIN32 + u_long u_on = 1; +#endif + + sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_bind_tcp: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_bind_tcp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } + if (setsockopt (sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on), + sizeof (on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n", + coap_socket_strerror()); + + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), + sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + + switch (listen_addr->addr.sa.sa_family) { + case AF_INET: + break; + case AF_INET6: + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); + break; + default: + coap_log(LOG_ALERT, "coap_socket_bind_tcp: unsupported sa_family\n"); + } + + if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_ALERT, "coap_socket_bind_tcp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + + bound_addr->size = (socklen_t)sizeof(*bound_addr); + if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) { + coap_log(LOG_WARNING, "coap_socket_bind_tcp: getsockname: %s\n", + coap_socket_strerror()); + goto error; + } + + if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) { + coap_log(LOG_ALERT, "coap_socket_bind_tcp: listen: %s\n", + coap_socket_strerror()); + goto error; + } + + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr) { +#ifdef _WIN32 + u_long u_on = 1; +#else + int on = 1; +#endif + + server->flags &= ~COAP_SOCKET_CAN_ACCEPT; + + new_client->fd = accept(server->fd, &remote_addr->addr.sa, + &remote_addr->size); + if (new_client->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_accept_tcp: accept: %s\n", + coap_socket_strerror()); + return 0; + } + + if (getsockname( new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0) + coap_log(LOG_WARNING, "coap_socket_accept_tcp: getsockname: %s\n", + coap_socket_strerror()); + + #ifdef _WIN32 + if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_accept_tcp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } + + return 1; +} + +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + int on = 1, off = 0; +#ifdef _WIN32 + u_long u_on = 1; +#endif + coap_address_t connect_addr; + int is_mcast = coap_is_mcast(server); + coap_address_copy(&connect_addr, server); + + sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST); + sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } + + switch (connect_addr.addr.sa.sa_family) { + case AF_INET: + if (connect_addr.addr.sin.sin_port == 0) + connect_addr.addr.sin.sin_port = htons(default_port); + break; + case AF_INET6: + if (connect_addr.addr.sin6.sin6_port == 0) + connect_addr.addr.sin6.sin6_port = htons(default_port); + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); + break; + default: + coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n"); + break; + } + + if (local_if && local_if->addr.sa.sa_family) { + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + } + + /* special treatment for sockets that are used for multicast communication */ + if (is_mcast) { + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, + "coap_socket_connect_udp: getsockname for multicast socket: %s\n", + coap_socket_strerror()); + } + coap_address_copy(remote_addr, &connect_addr); + sock->flags |= COAP_SOCKET_MULTICAST; + return 1; + } + + if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n", + coap_socket_strerror()); + goto error; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n", + coap_socket_strerror()); + } + + sock->flags |= COAP_SOCKET_CONNECTED; + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +void coap_socket_close(coap_socket_t *sock) { + if (sock->fd != COAP_INVALID_SOCKET) { + coap_closesocket(sock->fd); + sock->fd = COAP_INVALID_SOCKET; + } + sock->flags = COAP_SOCKET_EMPTY; +} + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { + ssize_t r; + + sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE); +#ifdef _WIN32 + r = send(sock->fd, (const char *)data, (int)data_len, 0); +#else + r = send(sock->fd, data, data_len, 0); +#endif + if (r == COAP_SOCKET_ERROR) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAEWOULDBLOCK) { +#elif EAGAIN != EWOULDBLOCK + if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { +#else + if (errno==EAGAIN || errno == EINTR) { +#endif + sock->flags |= COAP_SOCKET_WANT_WRITE; + return 0; + } + coap_log(LOG_WARNING, "coap_socket_write: send: %s\n", + coap_socket_strerror()); + return -1; + } + if (r < (ssize_t)data_len) + sock->flags |= COAP_SOCKET_WANT_WRITE; + return r; +} + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { + ssize_t r; +#ifdef _WIN32 + int error; +#endif + +#ifdef _WIN32 + r = recv(sock->fd, (char *)data, (int)data_len, 0); +#else + r = recv(sock->fd, data, data_len, 0); +#endif + if (r == 0) { + /* graceful shutdown */ + sock->flags &= ~COAP_SOCKET_CAN_READ; + return -1; + } else if (r == COAP_SOCKET_ERROR) { + sock->flags &= ~COAP_SOCKET_CAN_READ; +#ifdef _WIN32 + error = WSAGetLastError(); + if (error == WSAEWOULDBLOCK) { +#elif EAGAIN != EWOULDBLOCK + if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { +#else + if (errno==EAGAIN || errno == EINTR) { +#endif + return 0; + } +#ifdef _WIN32 + if (error != WSAECONNRESET) +#else + if (errno != ECONNRESET) +#endif + coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n", + coap_socket_strerror()); + return -1; + } + if (r < (ssize_t)data_len) + sock->flags &= ~COAP_SOCKET_CAN_READ; + return r; +} + +#endif /* WITH_CONTIKI */ + +#if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) ) +/* define struct in6_pktinfo and struct in_pktinfo if not available + FIXME: check with configure +*/ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +#endif + +#if !defined(WITH_CONTIKI) && !defined(SOL_IP) +/* Solaris expects level IPPROTO_IP for ancillary data. */ +#define SOL_IP IPPROTO_IP +#endif + +#ifdef __GNUC__ +#define UNUSED_PARAM __attribute__ ((unused)) +#else /* not a GCC */ +#define UNUSED_PARAM +#endif /* GCC */ + +#if defined(_WIN32) +#include +static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL; +/* Map struct WSABUF fields to their posix counterpart */ +#define msghdr _WSAMSG +#define msg_name name +#define msg_namelen namelen +#define msg_iov lpBuffers +#define msg_iovlen dwBufferCount +#define msg_control Control.buf +#define msg_controllen Control.len +#define iovec _WSABUF +#define iov_base buf +#define iov_len len +#define iov_len_t u_long +#undef CMSG_DATA +#define CMSG_DATA WSA_CMSG_DATA +#define ipi_spec_dst ipi_addr +#else +#define iov_len_t size_t +#endif + +ssize_t +coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) { + ssize_t bytes_written = 0; + + if (!coap_debug_send_packet()) { + bytes_written = (ssize_t)datalen; +#ifndef WITH_CONTIKI + } else if (sock->flags & COAP_SOCKET_CONNECTED) { +#ifdef _WIN32 + bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0); +#else + bytes_written = send(sock->fd, data, datalen, 0); +#endif +#endif + } else { +#ifndef WITH_CONTIKI +#ifdef _WIN32 + DWORD dwNumberOfBytesSent = 0; + int r; +#endif +#ifndef COAP_BAD_RECVMSG + /* a buffer large enough to hold all packet info types, ipv6 is the largest */ + char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct msghdr mhdr; + struct iovec iov[1]; + const void *addr = &session->remote_addr.addr; + + assert(session); + + memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base)); + iov[0].iov_len = (iov_len_t)datalen; + + memset(buf, 0, sizeof (buf)); + + memset(&mhdr, 0, sizeof(struct msghdr)); + memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name)); + mhdr.msg_namelen = session->remote_addr.size; + + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + + if (!coap_address_isany(&session->local_addr) && !coap_is_mcast(&session->local_addr)) switch (session->local_addr.addr.sa.sa_family) { + case AF_INET6: + { + struct cmsghdr *cmsg; + + if (IN6_IS_ADDR_V4MAPPED(&session->local_addr.addr.sin6.sin6_addr)) { +#if defined(IP_PKTINFO) + struct in_pktinfo *pktinfo; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi_ifindex = session->ifindex; + memcpy(&pktinfo->ipi_spec_dst, session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(pktinfo->ipi_spec_dst)); +#elif defined(IP_SENDSRCADDR) + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + + memcpy(CMSG_DATA(cmsg), session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(struct in_addr)); +#endif /* IP_PKTINFO */ + } else { + struct in6_pktinfo *pktinfo; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + + pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi6_ifindex = session->ifindex; + memcpy(&pktinfo->ipi6_addr, &session->local_addr.addr.sin6.sin6_addr, sizeof(pktinfo->ipi6_addr)); + } + break; + } + case AF_INET: + { +#if defined(IP_PKTINFO) + struct cmsghdr *cmsg; + struct in_pktinfo *pktinfo; + + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi_ifindex = session->ifindex; + memcpy(&pktinfo->ipi_spec_dst, &session->local_addr.addr.sin.sin_addr, sizeof(pktinfo->ipi_spec_dst)); +#elif defined(IP_SENDSRCADDR) + struct cmsghdr *cmsg; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + + memcpy(CMSG_DATA(cmsg), &session->local_addr.addr.sin.sin_addr, sizeof(struct in_addr)); +#endif /* IP_PKTINFO */ + break; + } + default: + /* error */ + coap_log(LOG_WARNING, "protocol not supported\n"); + bytes_written = -1; + } +#endif /* ! COAP_BAD_RECVMSG */ + +#ifdef _WIN32 + r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/); + if (r == 0) + bytes_written = (ssize_t)dwNumberOfBytesSent; + else + bytes_written = -1; +#else +#ifndef COAP_BAD_RECVMSG + bytes_written = sendmsg(sock->fd, &mhdr, 0); +#else /* COAP_BAD_RECVMSG */ + bytes_written = sendto(sock->fd, data, datalen, 0, &session->remote_addr.addr.sa, session->remote_addr.size); +#endif /* COAP_BAD_RECVMSG */ +#endif +#else /* WITH_CONTIKI */ + /* FIXME: untested */ + /* FIXME: is there a way to check if send was successful? */ + (void)datalen; + (void)data; + uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen, + &session->remote_addr.addr, session->remote_addr.port); + bytes_written = datalen; +#endif /* WITH_CONTIKI */ + } + + if (bytes_written < 0) + coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror()); + + return bytes_written; +} + +#define SIN6(A) ((struct sockaddr_in6 *)(A)) + +void +coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) { + *address = packet->payload; + *length = packet->length; +} + +void coap_packet_set_addr(coap_packet_t *packet, const coap_address_t *src, const coap_address_t *dst) { + coap_address_copy(&packet->src, src); + coap_address_copy(&packet->dst, dst); +} + +ssize_t +coap_network_read(coap_socket_t *sock, coap_packet_t *packet) { + ssize_t len = -1; + + assert(sock); + assert(packet); + + if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) { + return -1; + } else { + /* clear has-data flag */ + sock->flags &= ~COAP_SOCKET_CAN_READ; + } + +#ifndef WITH_CONTIKI + if (sock->flags & COAP_SOCKET_CONNECTED) { +#ifdef _WIN32 + len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0); +#else + len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0); +#endif + if (len < 0) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAECONNRESET) { +#else + if (errno == ECONNREFUSED) { +#endif + /* client-side ICMP destination unreachable, ignore it */ + coap_log(LOG_WARNING, "coap_network_read: unreachable\n"); + return -2; + } + coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror()); + goto error; + } else if (len > 0) { + packet->length = (size_t)len; + } + } else { +#endif /* WITH_CONTIKI */ +#if defined(_WIN32) + DWORD dwNumberOfBytesRecvd = 0; + int r; +#endif +#if !defined(WITH_CONTIKI) +#ifndef COAP_BAD_RECVMSG + /* a buffer large enough to hold all packet info types, ipv6 is the largest */ + char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct msghdr mhdr; + struct iovec iov[1]; + + iov[0].iov_base = packet->payload; + iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE; + + memset(&mhdr, 0, sizeof(struct msghdr)); + + mhdr.msg_name = (struct sockaddr*)&packet->src.addr; + mhdr.msg_namelen = sizeof(packet->src.addr); + + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + + mhdr.msg_control = buf; + mhdr.msg_controllen = sizeof(buf); + +#if defined(_WIN32) + if (!lpWSARecvMsg) { + GUID wsaid = WSAID_WSARECVMSG; + DWORD cbBytesReturned = 0; + if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) { + coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n"); + return -1; + } + } + r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */); + if (r == 0) + len = (ssize_t)dwNumberOfBytesRecvd; +#else + len = recvmsg(sock->fd, &mhdr, 0); +#endif + +#else /* COAP_BAD_RECVMSG */ + packet->src.size = packet->src.size; + len = recvfrom(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0, &packet->src.addr.sa, &packet->src.size); +#endif /* COAP_BAD_RECVMSG */ + + if (len < 0) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAECONNRESET) { +#else + if (errno == ECONNREFUSED) { +#endif + /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */ + return 0; + } + coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror()); + goto error; + } else { +#ifndef COAP_BAD_RECVMSG + struct cmsghdr *cmsg; + + packet->src.size = mhdr.msg_namelen; + packet->length = (size_t)len; + + /* Walk through ancillary data records until the local interface + * is found where the data was received. */ + for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { + + /* get the local interface for IPv6 */ + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { + union { + uint8_t *c; + struct in6_pktinfo *p; + } u; + u.c = CMSG_DATA(cmsg); + packet->ifindex = (int)(u.p->ipi6_ifindex); + memcpy(&packet->dst.addr.sin6.sin6_addr, &u.p->ipi6_addr, sizeof(struct in6_addr)); + break; + } + + /* local interface for IPv4 */ +#if defined(IP_PKTINFO) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { + union { + uint8_t *c; + struct in_pktinfo *p; + } u; + u.c = CMSG_DATA(cmsg); + packet->ifindex = u.p->ipi_ifindex; + if (packet->dst.addr.sa.sa_family == AF_INET6) { + memset(packet->dst.addr.sin6.sin6_addr.s6_addr, 0, 10); + packet->dst.addr.sin6.sin6_addr.s6_addr[10] = 0xff; + packet->dst.addr.sin6.sin6_addr.s6_addr[11] = 0xff; + memcpy(packet->dst.addr.sin6.sin6_addr.s6_addr + 12, &u.p->ipi_addr, sizeof(struct in_addr)); + } else { + memcpy(&packet->dst.addr.sin.sin_addr, &u.p->ipi_addr, sizeof(struct in_addr)); + } + break; + } +#elif defined(IP_RECVDSTADDR) + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { + packet->ifindex = 0; + memcpy(&packet->dst.addr.sin.sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr)); + break; + } +#endif /* IP_PKTINFO */ + } +#else /* COAP_BAD_RECVMSG */ + packet->length = (size_t)len; + packet->ifindex = 0; + if (getsockname(sock->fd, &packet->dst.addr.sa, &packet->dst.size) < 0) { + coap_log(LOG_DEBUG, "Cannot determine local port\n"); + goto error; + } +#endif /* COAP_BAD_RECVMSG */ + } +#endif /* !defined(WITH_CONTIKI) */ +#ifdef WITH_CONTIKI + /* FIXME: untested, make this work */ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + + if (uip_newdata()) { + uip_ipaddr_copy(&packet->src.addr, &UIP_IP_BUF->srcipaddr); + packet->src.port = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&(packet)->dst.addr, &UIP_IP_BUF->destipaddr); + packet->dst.port = UIP_UDP_BUF->destport; + + len = uip_datalen(); + + if (len > COAP_RXBUFFER_SIZE) { + /* FIXME: we might want to send back a response */ + coap_log(LOG_WARNING, "discarded oversized packet\n"); + return -1; + } + + ((char *)uip_appdata)[len] = 0; +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr_str[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&packet->src, addr_str, INET6_ADDRSTRLEN + 8)) { + coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str); + } + } +#endif /* NDEBUG */ + + packet->length = len; + memcpy(&packet->payload, uip_appdata, len); + } + +#undef UIP_IP_BUF +#undef UIP_UDP_BUF +#endif /* WITH_CONTIKI */ +#ifndef WITH_CONTIKI + } +#endif /* WITH_CONTIKI */ + + if (len >= 0) + return len; +#if !defined(WITH_CONTIKI) +error: +#endif + return -1; +} + +#if !defined(WITH_CONTIKI) + +unsigned int +coap_write(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now) +{ + coap_queue_t *nextpdu; + coap_endpoint_t *ep; + coap_session_t *s; + coap_tick_t session_timeout; + coap_tick_t timeout = 0; + coap_session_t *tmp; + + *num_sockets = 0; + + /* Check to see if we need to send off any Observe requests */ + coap_check_notify(ctx); + + if (ctx->session_timeout > 0) + session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND; + else + session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND; + + LL_FOREACH(ctx->endpoint, ep) { + if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &ep->sock; + } + LL_FOREACH_SAFE(ep->sessions, s, tmp) { + if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && + s->delayqueue == NULL && + (s->last_rx_tx + session_timeout <= now || + s->state == COAP_SESSION_STATE_NONE)) { + coap_session_free(s); + } else { + if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && s->delayqueue == NULL) { + coap_tick_t s_timeout = (s->last_rx_tx + session_timeout) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &s->sock; + } + } + } + } + LL_FOREACH_SAFE(ctx->sessions, s, tmp) { + if ( + s->type == COAP_SESSION_TYPE_CLIENT + && COAP_PROTO_RELIABLE(s->proto) + && s->state == COAP_SESSION_STATE_ESTABLISHED + && ctx->ping_timeout > 0 + ) { + coap_tick_t s_timeout; + if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) { + if ((s->last_ping > 0 && s->last_pong < s->last_ping) + || coap_session_send_ping(s) == COAP_INVALID_TID) + { + /* Make sure the session object is not deleted in the callback */ + coap_session_reference(s); + coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE); + coap_session_release(s); + continue; + } + s->last_rx_tx = now; + s->last_ping = now; + } + s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + + if ( + s->type == COAP_SESSION_TYPE_CLIENT + && COAP_PROTO_RELIABLE(s->proto) + && s->state == COAP_SESSION_STATE_CSM + && ctx->csm_timeout > 0 + ) { + coap_tick_t s_timeout; + if (s->csm_tx == 0) { + s->csm_tx = now; + } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) { + /* Make sure the session object is not deleted in the callback */ + coap_session_reference(s); + coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE); + coap_session_release(s); + continue; + } + s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + + if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_CONNECT)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &s->sock; + } + } + + nextpdu = coap_peek_next(ctx); + + while (nextpdu && now >= ctx->sendqueue_basetime && nextpdu->t <= now - ctx->sendqueue_basetime) { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + + if (nextpdu && (timeout == 0 || nextpdu->t - ( now - ctx->sendqueue_basetime ) < timeout)) + timeout = nextpdu->t - (now - ctx->sendqueue_basetime); + + if (ctx->dtls_context) { + if (coap_dtls_is_context_timeout()) { + coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context); + if (tls_timeout > 0) { + if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10) + tls_timeout = now + COAP_TICKS_PER_SECOND / 10; + coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n", + (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND)); + if (timeout == 0 || tls_timeout - now < timeout) + timeout = tls_timeout - now; + } + } else { + LL_FOREACH(ctx->endpoint, ep) { + if (ep->proto == COAP_PROTO_DTLS) { + LL_FOREACH(ep->sessions, s) { + if (s->proto == COAP_PROTO_DTLS && s->tls) { + coap_tick_t tls_timeout = coap_dtls_get_timeout(s); + while (tls_timeout > 0 && tls_timeout <= now) { + coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", + coap_session_str(s)); + coap_dtls_handle_timeout(s); + if (s->tls) + tls_timeout = coap_dtls_get_timeout(s); + else { + tls_timeout = 0; + timeout = 1; + } + } + if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) + timeout = tls_timeout - now; + } + } + } + } + LL_FOREACH(ctx->sessions, s) { + if (s->proto == COAP_PROTO_DTLS && s->tls) { + coap_tick_t tls_timeout = coap_dtls_get_timeout(s); + while (tls_timeout > 0 && tls_timeout <= now) { + coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s)); + coap_dtls_handle_timeout(s); + if (s->tls) + tls_timeout = coap_dtls_get_timeout(s); + else { + tls_timeout = 0; + timeout = 1; + } + } + if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) + timeout = tls_timeout - now; + } + } + } + } + + return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND); +} + +int +coap_run_once(coap_context_t *ctx, unsigned timeout_ms) { + fd_set readfds, writefds, exceptfds; + coap_fd_t nfds = 0; + struct timeval tv; + coap_tick_t before, now; + int result; + coap_socket_t *sockets[64]; + unsigned int num_sockets = 0, i, timeout; + + coap_ticks(&before); + + timeout = coap_write(ctx, sockets, (unsigned int)(sizeof(sockets) / sizeof(sockets[0])), &num_sockets, before); + if (timeout == 0 || timeout_ms < timeout) + timeout = timeout_ms; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + for (i = 0; i < num_sockets; i++) { + if (sockets[i]->fd + 1 > nfds) + nfds = sockets[i]->fd + 1; + if (sockets[i]->flags & COAP_SOCKET_WANT_READ) + FD_SET(sockets[i]->fd, &readfds); + if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE) + FD_SET(sockets[i]->fd, &writefds); + if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) + FD_SET(sockets[i]->fd, &readfds); + if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) { + FD_SET(sockets[i]->fd, &writefds); + FD_SET(sockets[i]->fd, &exceptfds); + } + } + + if ( timeout > 0 ) { + tv.tv_usec = (timeout % 1000) * 1000; + tv.tv_sec = (long)(timeout / 1000); + } + + result = select(nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL); + + if (result < 0) { /* error */ +#ifdef _WIN32 + if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */ +#else + if (errno != EINTR) { +#endif + coap_log(LOG_DEBUG, "%s", coap_socket_strerror()); + return -1; + } + } + + if (result > 0) { + for (i = 0; i < num_sockets; i++) { + if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds)) + sockets[i]->flags |= COAP_SOCKET_CAN_READ; + if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds)) + sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT; + if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds)) + sockets[i]->flags |= COAP_SOCKET_CAN_WRITE; + if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds))) + sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT; + } + } + + coap_ticks(&now); + coap_read(ctx, now); + + return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); +} + +#else +int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms) { + return -1; +} + +unsigned int +coap_write(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now) +{ + *num_sockets = 0; + return 0; +} +#endif + +#ifdef _WIN32 +static const char *coap_socket_format_errno(int error) { + static char szError[256]; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), NULL) == 0) + strcpy(szError, "Unknown error"); + return szError; +} + +const char *coap_socket_strerror(void) { + return coap_socket_format_errno(WSAGetLastError()); +} +#else +#ifndef WITH_CONTIKI +static const char *coap_socket_format_errno(int error) { + return strerror(error); +} +#endif /* WITH_CONTIKI */ + +const char *coap_socket_strerror(void) { + return strerror(errno); +} +#endif + +ssize_t +coap_socket_send(coap_socket_t *sock, coap_session_t *session, + const uint8_t *data, size_t data_len) { + return session->context->network_send(sock, session, data, data_len); +} + +#undef SIN6 diff --git a/components/coap/port/coap_io_socket.c b/components/coap/port/coap_io_socket.c deleted file mode 100644 index 4c3f85b45..000000000 --- a/components/coap/port/coap_io_socket.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Network function implementation with socket for ESP32 platform. - * - * Uses libcoap software implementation for failover when concurrent - * network operations are in use. - * - * coap_io.h -- Default network I/O functions for libcoap - * - * Copyright (C) 2012,2014 Olaf Bergmann - * - * Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#ifdef HAVE_STDIO_H -# include -#endif - -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_SYS_UIO_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#include - -#ifdef WITH_CONTIKI -# include "uip.h" -#endif - -#include "pdu.h" -#include "debug.h" -#include "mem.h" -#include "coap_io.h" - -#ifdef WITH_POSIX -/* define generic PKTINFO for IPv4 */ -#if defined(IP_PKTINFO) -# define GEN_IP_PKTINFO IP_PKTINFO -#elif defined(IP_RECVDSTADDR) -# define GEN_IP_PKTINFO IP_RECVDSTADDR -#else -# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." -#endif /* IP_PKTINFO */ - -/* define generic KTINFO for IPv6 */ -#ifdef IPV6_RECVPKTINFO -# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO -#elif defined(IPV6_PKTINFO) -# define GEN_IPV6_PKTINFO IPV6_PKTINFO -#else -# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." -#endif /* IPV6_RECVPKTINFO */ - -struct coap_packet_t { - coap_if_handle_t hnd; /**< the interface handle */ - coap_address_t src; /**< the packet's source address */ - coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; - - int ifindex; - void *session; /**< opaque session data */ - - size_t length; /**< length of payload */ - unsigned char payload[]; /**< payload */ -}; -#endif - -#ifdef CUSTOM_COAP_NETWORK_ENDPOINT - -#ifdef WITH_CONTIKI -static int ep_initialized = 0; - -static inline struct coap_endpoint_t * -coap_malloc_contiki_endpoint() { - static struct coap_endpoint_t ep; - - if (ep_initialized) { - return NULL; - } else { - ep_initialized = 1; - return &ep; - } -} - -static inline void -coap_free_contiki_endpoint(struct coap_endpoint_t *ep) { - ep_initialized = 0; -} - -coap_endpoint_t * -coap_new_endpoint(const coap_address_t *addr, int flags) { - struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint(); - - if (ep) { - memset(ep, 0, sizeof(struct coap_endpoint_t)); - ep->handle.conn = udp_new(NULL, 0, NULL); - - if (!ep->handle.conn) { - coap_free_endpoint(ep); - return NULL; - } - - coap_address_init(&ep->addr); - uip_ipaddr_copy(&ep->addr.addr, &addr->addr); - ep->addr.port = addr->port; - udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port); - } - return ep; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if (ep) { - if (ep->handle.conn) { - uip_udp_remove((struct uip_udp_conn *)ep->handle.conn); - } - coap_free_contiki_endpoint(ep); - } -} - -#else /* WITH_CONTIKI */ -static inline struct coap_endpoint_t * -coap_malloc_posix_endpoint(void) { - return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t)); -} - -static inline void -coap_free_posix_endpoint(struct coap_endpoint_t *ep) { - coap_free(ep); -} - -coap_endpoint_t * -coap_new_endpoint(const coap_address_t *addr, int flags) { - int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); - int on = 1; - struct coap_endpoint_t *ep; - - if (sockfd < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: socket"); - return NULL; - } - - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR"); - - if (bind(sockfd, &addr->addr.sa, addr->size) < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: bind"); - close (sockfd); - return NULL; - } - - ep = coap_malloc_posix_endpoint(); - if (!ep) { - coap_log(LOG_WARNING, "coap_new_endpoint: malloc"); - close(sockfd); - return NULL; - } - - memset(ep, 0, sizeof(struct coap_endpoint_t)); - ep->handle.fd = sockfd; - ep->flags = flags; - - ep->addr.size = addr->size; - if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) { - coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address"); - close (sockfd); - return NULL; - } - -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr_str[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) { - debug("created %sendpoint %s\n", - ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "", - addr_str); - } - } -#endif /* NDEBUG */ - - return (coap_endpoint_t *)ep; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if(ep) { - if (ep->handle.fd >= 0) - close(ep->handle.fd); - coap_free_posix_endpoint((struct coap_endpoint_t *)ep); - } -} - -#endif /* WITH_CONTIKI */ -#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */ - -#ifdef CUSTOM_COAP_NETWORK_SEND - -#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H) -/* define struct in6_pktinfo and struct in_pktinfo if not available - FIXME: check with configure -*/ -struct in6_pktinfo { - struct in6_addr ipi6_addr; /* src/dst IPv6 address */ - unsigned int ipi6_ifindex; /* send/recv interface index */ -}; - -struct in_pktinfo { - int ipi_ifindex; - struct in_addr ipi_spec_dst; - struct in_addr ipi_addr; -}; -#endif - -#if defined(WITH_POSIX) && !defined(SOL_IP) -/* Solaris expects level IPPROTO_IP for ancillary data. */ -#define SOL_IP IPPROTO_IP -#endif - -#ifdef __GNUC__ -#define UNUSED_PARAM __attribute__ ((unused)) -#else /* not a GCC */ -#define UNUSED_PARAM -#endif /* GCC */ - -ssize_t -coap_network_send(struct coap_context_t *context UNUSED_PARAM, - const coap_endpoint_t *local_interface, - const coap_address_t *dst, - unsigned char *data, - size_t datalen) { - - struct coap_endpoint_t *ep = - (struct coap_endpoint_t *)local_interface; - -#ifndef WITH_CONTIKI - return sendto(ep->handle.fd, data, datalen, 0, (struct sockaddr*)&dst->addr.sa, sizeof(struct sockaddr)); -#else /* WITH_CONTIKI */ - /* FIXME: untested */ - /* FIXME: is there a way to check if send was successful? */ - uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen, - &dst->addr, dst->port); - return datalen; -#endif /* WITH_CONTIKI */ -} - -#endif /* CUSTOM_COAP_NETWORK_SEND */ - -#ifdef CUSTOM_COAP_NETWORK_READ - -#define SIN6(A) ((struct sockaddr_in6 *)(A)) - -#ifdef WITH_POSIX -static coap_packet_t * -coap_malloc_packet(void) { - coap_packet_t *packet; - const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE; - - packet = (coap_packet_t *)coap_malloc(need); - if (packet) { - memset(packet, 0, need); - } - return packet; -} - -void -coap_free_packet(coap_packet_t *packet) { - coap_free(packet); -} -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI -static inline coap_packet_t * -coap_malloc_packet(void) { - return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0); -} - -void -coap_free_packet(coap_packet_t *packet) { - coap_free_type(COAP_PACKET, packet); -} -#endif /* WITH_CONTIKI */ - -static inline size_t -coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { - return COAP_MAX_PDU_SIZE; -} - -void -coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) -{ - target->handle = packet->interface->handle; - memcpy(&target->addr, &packet->dst, sizeof(target->addr)); - target->ifindex = packet->ifindex; - target->flags = 0; /* FIXME */ -} -void -coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) -{ - memcpy(target, &packet->src, sizeof(coap_address_t)); -} -void -coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) -{ - *address = packet->payload; - *length = packet->length; -} - -/** - * Checks if a message with destination address @p dst matches the - * local interface with address @p local. This function returns @c 1 - * if @p dst is a valid match, and @c 0 otherwise. - */ -static inline int -is_local_if(const coap_address_t *local, const coap_address_t *dst) { - return coap_address_isany(local) || coap_address_equals(dst, local) || - coap_is_mcast(dst); -} - -ssize_t -coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { - ssize_t len = -1; - -#ifdef WITH_POSIX - #define SOC_APPDATA_LEN 1460 - char *soc_appdata = NULL; - struct sockaddr_in soc_srcipaddr; - socklen_t soc_srcsize = sizeof(struct sockaddr_in); -#endif /* WITH_POSIX */ - - assert(ep); - assert(packet); - - *packet = coap_malloc_packet(); - - if (!*packet) { - warn("coap_network_read: insufficient memory, drop packet\n"); - return -1; - } - - coap_address_init(&(*packet)->dst); /* the local interface address */ - coap_address_init(&(*packet)->src); /* the remote peer */ - -#ifdef WITH_POSIX - soc_appdata = coap_malloc(SOC_APPDATA_LEN); - if (soc_appdata){ - len = recvfrom(ep->handle.fd, soc_appdata, SOC_APPDATA_LEN, 0, (struct sockaddr *)&soc_srcipaddr, (socklen_t *)&soc_srcsize); - - if (len < 0){ - coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno)); - goto error; - } else { - /* use getsockname() to get the local port */ - (*packet)->dst.size = sizeof((*packet)->dst.addr); - if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) { - coap_log(LOG_DEBUG, "cannot determine local port\n"); - goto error; - } - - /* local interface for IPv4 */ - (*packet)->src.size = sizeof((*packet)->src.addr.sa); - memcpy(&((*packet)->src.addr.sa), &soc_srcipaddr, (*packet)->src.size); - - if (len > coap_get_max_packetlength(*packet)) { - /* FIXME: we might want to send back a response */ - warn("discarded oversized packet\n"); - goto error; - } - - if (!is_local_if(&ep->addr, &(*packet)->dst)) { - coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n"); - printf("error 3\n"); - goto error; - } - - (*packet)->length = len; - - memcpy(&(*packet)->payload, soc_appdata, len); - } - - coap_free(soc_appdata); - soc_appdata = NULL; - } else { - goto error; - } -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI - /* FIXME: untested, make this work */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) - - if(uip_newdata()) { - uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr); - (*packet)->src.port = UIP_UDP_BUF->srcport; - uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr); - (*packet)->dst.port = UIP_UDP_BUF->destport; - - if (!is_local_if(&ep->addr, &(*packet)->dst)) { - coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n"); - goto error; - } - - len = uip_datalen(); - - if (len > coap_get_max_packetlength(*packet)) { - /* FIXME: we might want to send back a response */ - warn("discarded oversized packet\n"); - return -1; - } - - ((char *)uip_appdata)[len] = 0; -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr_str[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) { - debug("received %zd bytes from %s\n", len, addr_str); - } - } -#endif /* NDEBUG */ - - (*packet)->length = len; - memcpy(&(*packet)->payload, uip_appdata, len); - } - -#undef UIP_IP_BUF -#undef UIP_UDP_BUF -#endif /* WITH_CONTIKI */ -#ifdef WITH_LWIP -#error "coap_network_read() not implemented on this platform" -#endif - - (*packet)->interface = ep; - - return len; - error: -#ifdef WITH_POSIX - if (soc_appdata) - coap_free(soc_appdata); - soc_appdata = NULL; -#endif - coap_free_packet(*packet); - *packet = NULL; - return -1; -} - -#undef SIN6 - -#endif /* CUSTOM_COAP_NETWORK_READ */ diff --git a/components/coap/port/include/coap/coap.h b/components/coap/port/include/coap/coap.h index cbdc9dfc8..f048ca857 100644 --- a/components/coap/port/include/coap/coap.h +++ b/components/coap/port/include/coap/coap.h @@ -17,19 +17,21 @@ #ifndef _COAP_H_ #define _COAP_H_ -#include "libcoap.h" - #ifdef __cplusplus extern "C" { #endif +#include "libcoap.h" + #include "address.h" #include "async.h" #include "bits.h" #include "block.h" +#include "coap_dtls.h" +#include "coap_event.h" #include "coap_io.h" #include "coap_time.h" -#include "debug.h" +#include "coap_debug.h" #include "encode.h" #include "mem.h" #include "net.h" @@ -40,8 +42,6 @@ extern "C" { #include "str.h" #include "subscribe.h" #include "uri.h" -#include "uthash.h" -#include "utlist.h" #ifdef __cplusplus } diff --git a/components/coap/port/include/coap_config.h b/components/coap/port/include/coap_config.h index db314f2de..1efa37aa7 100644 --- a/components/coap/port/include/coap_config.h +++ b/components/coap/port/include/coap_config.h @@ -18,10 +18,13 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#ifdef WITH_POSIX -#include "coap_config_posix.h" +/* Always enabled in ESP-IDF */ +#ifndef WITH_POSIX +#define WITH_POSIX #endif +#include "coap_config_posix.h" + #define HAVE_STDIO_H #define HAVE_ASSERT_H diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index a925b8d23..8f5a5cfb1 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -25,19 +25,14 @@ #define HAVE_SYS_SOCKET_H #define HAVE_MALLOC #define HAVE_ARPA_INET_H +#define HAVE_TIME_H -#define IP_PKTINFO IP_MULTICAST_IF #define IPV6_PKTINFO IPV6_V6ONLY #define PACKAGE_NAME "libcoap-posix" #define PACKAGE_VERSION "?" -#define CUSTOM_COAP_NETWORK_ENDPOINT -#define CUSTOM_COAP_NETWORK_SEND -#define CUSTOM_COAP_NETWORK_READ - -#define COAP_IPV6 LWIP_IPV6 - -#endif +#define COAP_BAD_RECVMSG +#endif /* WITH_POSIX */ #endif /* COAP_CONFIG_POSIX_H_ */ diff --git a/components/console/CMakeLists.txt b/components/console/CMakeLists.txt new file mode 100644 index 000000000..446444dfb --- /dev/null +++ b/components/console/CMakeLists.txt @@ -0,0 +1,9 @@ +set(COMPONENT_ADD_INCLUDEDIRS .) +set(COMPONENT_SRCS "commands.c" + "split_argv.c" + "argtable3/argtable3.c" + "linenoise/linenoise.c") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/console/argtable3/LICENSE b/components/console/argtable3/LICENSE new file mode 100644 index 000000000..1a28ef95b --- /dev/null +++ b/components/console/argtable3/LICENSE @@ -0,0 +1,26 @@ +Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + diff --git a/components/console/argtable3/argtable3.c b/components/console/argtable3/argtable3.c new file mode 100644 index 000000000..43464d396 --- /dev/null +++ b/components/console/argtable3/argtable3.c @@ -0,0 +1,4956 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include "argtable3.h" + +#pragma GCC diagnostic ignored "-Wclobbered" + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARG_UTILS_H +#define ARG_UTILS_H + +#define ARG_ENABLE_TRACE 0 +#define ARG_ENABLE_LOG 1 + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + EMINCOUNT = 1, + EMAXCOUNT, + EBADINT, + EOVERFLOW, + EBADDOUBLE, + EBADDATE, + EREGNOMATCH +}; + + +#if defined(_MSC_VER) +#define ARG_TRACE(x) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) \ + __pragma(warning(pop)) + +#define ARG_LOG(x) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) \ + __pragma(warning(pop)) +#else +#define ARG_TRACE(x) \ + do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) + +#define ARG_LOG(x) \ + do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) +#endif + +extern void dbg_printf(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include + + +void dbg_printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +/* $Id: getopt.h,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#if 0 +#include +#endif + +/* + * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DEFINED +#define _GETOPT_DEFINED +int getopt(int, char * const *, const char *); +int getsubopt(char **, char * const *, char **); + +extern char *optarg; /* getopt(3) external variables */ +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *suboptarg; /* getsubopt(3) external variable */ +#endif /* _GETOPT_DEFINED */ + +#ifdef __cplusplus +} +#endif +#endif /* !_GETOPT_H_ */ +/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#ifndef lint +//static const char rcsid[]="$Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $"; +#endif /* lint */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +// Define this to replace system getopt +// +//#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + + +#if defined(_WIN32) || defined(ESP_PLATFORM) + +/* Windows needs warnx(). We change the definition though: + * 1. (another) global is defined, opterrmsg, which holds the error message + * 2. errors are always printed out on stderr w/o the program name + * Note that opterrmsg always gets set no matter what opterr is set to. The + * error message will not be printed if opterr is 0 as usual. + */ + +#include +#include + +extern char opterrmsg[128]; +char opterrmsg[128]; /* buffer for the last error message */ + +static void warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + /* + Make sure opterrmsg is always zero-terminated despite the _vsnprintf() + implementation specifics and manually suppress the warning. + */ + memset(opterrmsg, 0, sizeof opterrmsg); + if (fmt != NULL) + vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); + va_end(ap); +#if defined(_WIN32) +#pragma warning(suppress: 6053) +#endif + fprintf(stderr, "%s\n", opterrmsg); +} + +#else +#include +#endif /*_WIN32*/ + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} + + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} +#endif /* REPLACE_GETOPT */ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + + +char * arg_strptime(const char *buf, const char *fmt, struct tm *tm); + + +static void arg_date_resetfn(struct arg_date *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_date_scanfn(struct arg_date *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* no argument value was given, leave parent->tmval[] unaltered but still count it */ + parent->count++; + } + else + { + const char *pend; + struct tm tm = parent->tmval[parent->count]; + + /* parse the given argument value, store result in parent->tmval[] */ + pend = arg_strptime(argval, parent->format, &tm); + if (pend && pend[0] == '\0') + parent->tmval[parent->count++] = tm; + else + errorcode = EBADDATE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_date_checkfn(struct arg_date *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_date_errorfn( + struct arg_date *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADDATE: + { + struct tm tm; + char buff[200]; + + fprintf(fp, "illegal timestamp format \"%s\"\n", argval); + memset(&tm, 0, sizeof(tm)); + arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm); + strftime(buff, sizeof(buff), parent->format, &tm); + printf("correct format is \"%s\"\n", buff); + break; + } + } +} + + +struct arg_date * arg_date0( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + const char *glossary) +{ + return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary); +} + + +struct arg_date * arg_date1( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + const char *glossary) +{ + return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary); +} + + +struct arg_date * arg_daten( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_date *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + /* default time format is the national date format for the locale */ + if (!format) + format = "%x"; + + nbytes = sizeof(struct arg_date) /* storage for struct arg_date */ + + maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */ + + /* allocate storage for the arg_date struct + tmval[] array. */ + /* we use calloc because we want the tmval[] array zero filled. */ + result = (struct arg_date *)calloc(1, nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : format; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_date_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_date_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_date_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_date_errorfn; + + /* store the tmval[maxcount] array immediately after the arg_date struct */ + result->tmval = (struct tm *)(result + 1); + + /* init the remaining arg_date member variables */ + result->count = 0; + result->format = format; + } + + ARG_TRACE(("arg_daten() returns %p\n", result)); + return result; +} + + +/*- + * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Klaus Klein. + * Heavily optimised by David Laight + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * We do not implement alternate representations. However, we always + * check whether a given modifier is allowed for a certain conversion. + */ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } +#define TM_YEAR_BASE (1900) + +static int conv_num(const char * *, int *, int, int); + +static const char *day[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" +}; + +static const char *abday[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *mon[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" +}; + +static const char *abmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char *am_pm[2] = { + "AM", "PM" +}; + + +static int arg_strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + while (tolower(*us1) == tolower(*us2++)) + if (*us1++ == '\0') + return 0; + + return tolower(*us1) - tolower(*--us2); +} + + +static int arg_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + do + { + if (tolower(*us1) != tolower(*us2++)) + return tolower(*us1) - tolower(*--us2); + + if (*us1++ == '\0') + break; + } while (--n != 0); + } + + return 0; +} + + +char * arg_strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace((int) c)) { + while (isspace((int) *bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + +again: + switch (c = *fmt++) + { + case '%': /* "%%" is converted to "%". */ +literal: + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%x %X", tm); + if (!bp) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M", tm); + if (!bp) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%I:%M:%S %p", tm); + if (!bp) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(day[i]); + if (arg_strncasecmp(day[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (arg_strncasecmp(abday[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(mon[i]); + if (arg_strncasecmp(mon[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (arg_strncasecmp(abmon[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (arg_strcasecmp(am_pm[0], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(am_pm[0]); + break; + } + /* PM? */ + else if (arg_strcasecmp(am_pm[1], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(am_pm[1]); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace((int) *bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + + } + + /* LINTED functional specification */ + return ((char *)bp); +} + + +static int conv_num(const char * *buf, int *dest, int llim, int ulim) +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_dbl_resetfn(struct arg_dbl *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_dbl_scanfn(struct arg_dbl *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } + else + { + double val; + char *end; + + /* extract double from argval into val */ + val = strtod(argval, &end); + + /* if success then store result in parent->dval[] array otherwise return error*/ + if (*end == 0) + parent->dval[parent->count++] = val; + else + errorcode = EBADDOUBLE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_dbl_checkfn(struct arg_dbl *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_dbl_errorfn( + struct arg_dbl *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADDOUBLE: + fprintf(fp, "invalid argument \"%s\" to option ", argval); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + } +} + + +struct arg_dbl * arg_dbl0( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_dbl * arg_dbl1( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_dbl * arg_dbln( + const char * shortopts, + const char * longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_dbl *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */ + + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */ + + result = (struct arg_dbl *)malloc(nbytes); + if (result) + { + size_t addr; + size_t rem; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_dbl_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_dbl_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_dbl_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_dbl_errorfn; + + /* Store the dval[maxcount] array on the first double boundary that + * immediately follows the arg_dbl struct. We do the memory alignment + * purely for SPARC and Motorola systems. They require floats and + * doubles to be aligned on natural boundaries. + */ + addr = (size_t)(result + 1); + rem = addr % sizeof(double); + result->dval = (double *)(addr + sizeof(double) - rem); + ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem)); + + result->count = 0; + } + + ARG_TRACE(("arg_dbln() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_end_resetfn(struct arg_end *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static void arg_end_errorfn( + void *parent, + FILE *fp, + int error, + const char *argval, + const char *progname) +{ + /* suppress unreferenced formal parameter warning */ + (void)parent; + + progname = progname ? progname : ""; + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(error) + { + case ARG_ELIMIT: + fputs("too many errors to display", fp); + break; + case ARG_EMALLOC: + fputs("insufficent memory", fp); + break; + case ARG_ENOMATCH: + fprintf(fp, "unexpected argument \"%s\"", argval); + break; + case ARG_EMISSARG: + fprintf(fp, "option \"%s\" requires an argument", argval); + break; + case ARG_ELONGOPT: + fprintf(fp, "invalid option \"%s\"", argval); + break; + default: + fprintf(fp, "invalid option \"-%c\"", error); + break; + } + + fputc('\n', fp); +} + + +struct arg_end * arg_end(int maxcount) +{ + size_t nbytes; + struct arg_end *result; + + nbytes = sizeof(struct arg_end) + + maxcount * sizeof(int) /* storage for int error[maxcount] array*/ + + maxcount * sizeof(void *) /* storage for void* parent[maxcount] array */ + + maxcount * sizeof(char *); /* storage for char* argval[maxcount] array */ + + result = (struct arg_end *)malloc(nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_TERMINATOR; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = NULL; + result->hdr.glossary = NULL; + result->hdr.mincount = 1; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_end_resetfn; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = (arg_errorfn *)arg_end_errorfn; + + /* store error[maxcount] array immediately after struct arg_end */ + result->error = (int *)(result + 1); + + /* store parent[maxcount] array immediately after error[] array */ + result->parent = (void * *)(result->error + maxcount ); + + /* store argval[maxcount] array immediately after parent[] array */ + result->argval = (const char * *)(result->parent + maxcount ); + } + + ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result)); + return result; +} + + +void arg_print_errors(FILE * fp, struct arg_end * end, const char * progname) +{ + int i; + ARG_TRACE(("arg_errors()\n")); + for (i = 0; i < end->count; i++) + { + struct arg_hdr *errorparent = (struct arg_hdr *)(end->parent[i]); + if (errorparent->errorfn) + errorparent->errorfn(end->parent[i], + fp, + end->error[i], + end->argval[i], + progname); + } +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + +#ifdef WIN32 +# define FILESEPARATOR1 '\\' +# define FILESEPARATOR2 '/' +#else +# define FILESEPARATOR1 '/' +# define FILESEPARATOR2 '/' +#endif + + +static void arg_file_resetfn(struct arg_file *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +/* Returns ptr to the base filename within *filename */ +static const char * arg_basename(const char *filename) +{ + const char *result = NULL, *result1, *result2; + + /* Find the last occurrence of eother file separator character. */ + /* Two alternative file separator chars are supported as legal */ + /* file separators but not both together in the same filename. */ + result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL); + result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL); + + if (result2) + result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */ + + if (result1) + result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */ + + if (!result) + result = filename; /* neither file separator was found so basename is the whole filename */ + + /* special cases of "." and ".." are not considered basenames */ + if (result && ( strcmp(".", result) == 0 || strcmp("..", result) == 0 )) + result = filename + strlen(filename); + + return result; +} + + +/* Returns ptr to the file extension within *basename */ +static const char * arg_extension(const char *basename) +{ + /* find the last occurrence of '.' in basename */ + const char *result = (basename ? strrchr(basename, '.') : NULL); + + /* if no '.' was found then return pointer to end of basename */ + if (basename && !result) + result = basename + strlen(basename); + + /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */ + if (basename && result == basename) + result = basename + strlen(basename); + + /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */ + if (basename && result && result[1] == '\0') + result = basename + strlen(basename); + + return result; +} + + +static int arg_file_scanfn(struct arg_file *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + parent->filename[parent->count] = argval; + parent->basename[parent->count] = arg_basename(argval); + parent->extension[parent->count] = + arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/ + parent->count++; + } + + ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_file_checkfn(struct arg_file *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_file_errorfn( + struct arg_file *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + default: + fprintf(fp, "unknown error at \"%s\"\n", argval); + } +} + + +struct arg_file * arg_file0( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_filen(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_file * arg_file1( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_filen(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_file * arg_filen( + const char * shortopts, + const char * longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_file *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_file) /* storage for struct arg_file */ + + sizeof(char *) * maxcount /* storage for filename[maxcount] array */ + + sizeof(char *) * maxcount /* storage for basename[maxcount] array */ + + sizeof(char *) * maxcount; /* storage for extension[maxcount] array */ + + result = (struct arg_file *)malloc(nbytes); + if (result) + { + int i; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.glossary = glossary; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_file_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_file_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_file_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_file_errorfn; + + /* store the filename,basename,extension arrays immediately after the arg_file struct */ + result->filename = (const char * *)(result + 1); + result->basename = result->filename + maxcount; + result->extension = result->basename + maxcount; + result->count = 0; + + /* foolproof the string pointers by initialising them with empty strings */ + for (i = 0; i < maxcount; i++) + { + result->filename[i] = ""; + result->basename[i] = ""; + result->extension[i] = ""; + } + } + + ARG_TRACE(("arg_filen() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include +#include + +#include "argtable3.h" + + +static void arg_int_resetfn(struct arg_int *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +/* strtol0x() is like strtol() except that the numeric string is */ +/* expected to be prefixed by "0X" where X is a user supplied char. */ +/* The string may optionally be prefixed by white space and + or - */ +/* as in +0X123 or -0X123. */ +/* Once the prefix has been scanned, the remainder of the numeric */ +/* string is converted using strtol() with the given base. */ +/* eg: to parse hex str="-0X12324", specify X='X' and base=16. */ +/* eg: to parse oct str="+0o12324", specify X='O' and base=8. */ +/* eg: to parse bin str="-0B01010", specify X='B' and base=2. */ +/* Failure of conversion is indicated by result where *endptr==str. */ +static long int strtol0X(const char * str, + const char * *endptr, + char X, + int base) +{ + long int val; /* stores result */ + int s = 1; /* sign is +1 or -1 */ + const char *ptr = str; /* ptr to current position in str */ + + /* skip leading whitespace */ + while (isspace((int) *ptr)) + ptr++; + /* printf("1) %s\n",ptr); */ + + /* scan optional sign character */ + switch (*ptr) + { + case '+': + ptr++; + s = 1; + break; + case '-': + ptr++; + s = -1; + break; + default: + s = 1; + break; + } + /* printf("2) %s\n",ptr); */ + + /* '0X' prefix */ + if ((*ptr++) != '0') + { + /* printf("failed to detect '0'\n"); */ + *endptr = str; + return 0; + } + /* printf("3) %s\n",ptr); */ + if (toupper((int) *ptr++) != toupper((int) X)) + { + /* printf("failed to detect '%c'\n",X); */ + *endptr = str; + return 0; + } + /* printf("4) %s\n",ptr); */ + + /* attempt conversion on remainder of string using strtol() */ + val = strtol(ptr, (char * *)endptr, base); + if (*endptr == ptr) + { + /* conversion failed */ + *endptr = str; + return 0; + } + + /* success */ + return s * val; +} + + +/* Returns 1 if str matches suffix (case insensitive). */ +/* Str may contain trailing whitespace, but nothing else. */ +static int detectsuffix(const char *str, const char *suffix) +{ + /* scan pairwise through strings until mismatch detected */ + while( toupper((int) *str) == toupper((int) *suffix) ) + { + /* printf("'%c' '%c'\n", *str, *suffix); */ + + /* return 1 (success) if match persists until the string terminator */ + if (*str == '\0') + return 1; + + /* next chars */ + str++; + suffix++; + } + /* printf("'%c' '%c' mismatch\n", *str, *suffix); */ + + /* return 0 (fail) if the matching did not consume the entire suffix */ + if (*suffix != 0) + return 0; /* failed to consume entire suffix */ + + /* skip any remaining whitespace in str */ + while (isspace((int) *str)) + str++; + + /* return 1 (success) if we have reached end of str else return 0 (fail) */ + return (*str == '\0') ? 1 : 0; +} + + +static int arg_int_scanfn(struct arg_int *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + long int val; + const char *end; + + /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */ + val = strtol0X(argval, &end, 'X', 16); + if (end == argval) + { + /* hex failed, attempt octal conversion (eg +0o123) */ + val = strtol0X(argval, &end, 'O', 8); + if (end == argval) + { + /* octal failed, attempt binary conversion (eg +0B101) */ + val = strtol0X(argval, &end, 'B', 2); + if (end == argval) + { + /* binary failed, attempt decimal conversion with no prefix (eg 1234) */ + val = strtol(argval, (char * *)&end, 10); + if (end == argval) + { + /* all supported number formats failed */ + return EBADINT; + } + } + } + } + + /* Safety check for integer overflow. WARNING: this check */ + /* achieves nothing on machines where size(int)==size(long). */ + if ( val > INT_MAX || val < INT_MIN ) + errorcode = EOVERFLOW; + + /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */ + /* We need to be mindful of integer overflows when using such big numbers. */ + if (detectsuffix(end, "KB")) /* kilobytes */ + { + if ( val > (INT_MAX / 1024) || val < (INT_MIN / 1024) ) + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1024; /* 1KB = 1024 */ + } + else if (detectsuffix(end, "MB")) /* megabytes */ + { + if ( val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576) ) + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1048576; /* 1MB = 1024*1024 */ + } + else if (detectsuffix(end, "GB")) /* gigabytes */ + { + if ( val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824) ) + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1073741824; /* 1GB = 1024*1024*1024 */ + } + else if (!detectsuffix(end, "")) + errorcode = EBADINT; /* invalid suffix detected */ + + /* if success then store result in parent->ival[] array */ + if (errorcode == 0) + parent->ival[parent->count++] = val; + } + + /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */ + return errorcode; +} + + +static int arg_int_checkfn(struct arg_int *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ + return errorcode; +} + + +static void arg_int_errorfn( + struct arg_int *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADINT: + fprintf(fp, "invalid argument \"%s\" to option ", argval); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EOVERFLOW: + fputs("integer overflow at option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, " "); + fprintf(fp, "(%s is too large)\n", argval); + break; + } +} + + +struct arg_int * arg_int0( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_intn(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_int * arg_int1( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_intn(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_int * arg_intn( + const char *shortopts, + const char *longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_int *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_int) /* storage for struct arg_int */ + + maxcount * sizeof(int); /* storage for ival[maxcount] array */ + + result = (struct arg_int *)malloc(nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_int_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_int_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_int_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_int_errorfn; + + /* store the ival[maxcount] array immediately after the arg_int struct */ + result->ival = (int *)(result + 1); + result->count = 0; + } + + ARG_TRACE(("arg_intn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_lit_resetfn(struct arg_lit *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_lit_scanfn(struct arg_lit *parent, const char *argval) +{ + int errorcode = 0; + if (parent->count < parent->hdr.maxcount ) + parent->count++; + else + errorcode = EMAXCOUNT; + + ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval, + errorcode)); + return errorcode; +} + + +static int arg_lit_checkfn(struct arg_lit *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_lit_errorfn( + struct arg_lit *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + switch(errorcode) + { + case EMINCOUNT: + fprintf(fp, "%s: missing option ", progname); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + fprintf(fp, "\n"); + break; + + case EMAXCOUNT: + fprintf(fp, "%s: extraneous option ", progname); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + } + + ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp, + errorcode, argval, progname)); +} + + +struct arg_lit * arg_lit0( + const char * shortopts, + const char * longopts, + const char * glossary) +{ + return arg_litn(shortopts, longopts, 0, 1, glossary); +} + + +struct arg_lit * arg_lit1( + const char *shortopts, + const char *longopts, + const char *glossary) +{ + return arg_litn(shortopts, longopts, 1, 1, glossary); +} + + +struct arg_lit * arg_litn( + const char *shortopts, + const char *longopts, + int mincount, + int maxcount, + const char *glossary) +{ + struct arg_lit *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + result = (struct arg_lit *)malloc(sizeof(struct arg_lit)); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = 0; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = NULL; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_lit_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_lit_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_lit_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_lit_errorfn; + + /* init local variables */ + result->count = 0; + } + + ARG_TRACE(("arg_litn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include + +#include "argtable3.h" + +struct arg_rem *arg_rem(const char *datatype, const char *glossary) +{ + struct arg_rem *result = (struct arg_rem *)malloc(sizeof(struct arg_rem)); + if (result) + { + result->hdr.flag = 0; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = datatype; + result->hdr.glossary = glossary; + result->hdr.mincount = 1; + result->hdr.maxcount = 1; + result->hdr.parent = result; + result->hdr.resetfn = NULL; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = NULL; + } + + ARG_TRACE(("arg_rem() returns %p\n", result)); + return result; +} + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + + +#ifndef _TREX_H_ +#define _TREX_H_ +/*************************************************************** + T-Rex a tiny regular expression library + + Copyright (C) 2003-2006 Alberto Demichelis + + This software is provided 'as-is', without any express + or implied warranty. In no event will the authors be held + liable for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for + any purpose, including commercial applications, and to alter + it and redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. + + 2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any + source distribution. + +****************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _UNICODE +#define TRexChar unsigned short +#define MAX_CHAR 0xFFFF +#define _TREXC(c) L##c +#define trex_strlen wcslen +#define trex_printf wprintf +#else +#define TRexChar char +#define MAX_CHAR 0xFF +#define _TREXC(c) (c) +#define trex_strlen strlen +#define trex_printf printf +#endif + +#ifndef TREX_API +#define TREX_API extern +#endif + +#define TRex_True 1 +#define TRex_False 0 + +#define TREX_ICASE ARG_REX_ICASE + +typedef unsigned int TRexBool; +typedef struct TRex TRex; + +typedef struct { + const TRexChar *begin; + int len; +} TRexMatch; + +TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags); +TREX_API void trex_free(TRex *exp); +TREX_API TRexBool trex_match(TRex* exp, const TRexChar* text); +TREX_API TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API int trex_getsubexpcount(TRex* exp); +TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp); + +#ifdef __cplusplus +} +#endif + +#endif + + + +struct privhdr +{ + const char *pattern; + int flags; +}; + + +static void arg_rex_resetfn(struct arg_rex *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_rex_scanfn(struct arg_rex *parent, const char *argval) +{ + int errorcode = 0; + const TRexChar *error = NULL; + TRex *rex = NULL; + TRexBool is_match = TRex_False; + + if (parent->count == parent->hdr.maxcount ) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } + else + { + struct privhdr *priv = (struct privhdr *)parent->hdr.priv; + + /* test the current argument value for a match with the regular expression */ + /* if a match is detected, record the argument value in the arg_rex struct */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + is_match = trex_match(rex, argval); + if (!is_match) + errorcode = EREGNOMATCH; + else + parent->sval[parent->count++] = argval; + + trex_free(rex); + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n",__FILE__,parent,errorcode)); + return errorcode; +} + +static int arg_rex_checkfn(struct arg_rex *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + //struct privhdr *priv = (struct privhdr*)parent->hdr.priv; + + /* free the regex "program" we constructed in resetfn */ + //regfree(&(priv->regex)); + + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ + return errorcode; +} + +static void arg_rex_errorfn(struct arg_rex *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EREGNOMATCH: + fputs("illegal value ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + default: + { + //char errbuff[256]; + //regerror(errorcode, NULL, errbuff, sizeof(errbuff)); + //printf("%s\n", errbuff); + } + break; + } +} + + +struct arg_rex * arg_rex0(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int flags, + const char *glossary) +{ + return arg_rexn(shortopts, + longopts, + pattern, + datatype, + 0, + 1, + flags, + glossary); +} + +struct arg_rex * arg_rex1(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int flags, + const char *glossary) +{ + return arg_rexn(shortopts, + longopts, + pattern, + datatype, + 1, + 1, + flags, + glossary); +} + + +struct arg_rex * arg_rexn(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int mincount, + int maxcount, + int flags, + const char *glossary) +{ + size_t nbytes; + struct arg_rex *result; + struct privhdr *priv; + int i; + const TRexChar *error = NULL; + TRex *rex = NULL; + + if (!pattern) + { + printf( + "argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n"); + printf("argtable: Bad argument table.\n"); + return NULL; + } + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_rex) /* storage for struct arg_rex */ + + sizeof(struct privhdr) /* storage for private arg_rex data */ + + maxcount * sizeof(char *); /* storage for sval[maxcount] array */ + + result = (struct arg_rex *)malloc(nbytes); + if (result == NULL) + return result; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : pattern; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_rex_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_rex_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_rex_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_rex_errorfn; + + /* store the arg_rex_priv struct immediately after the arg_rex struct */ + result->hdr.priv = result + 1; + priv = (struct privhdr *)(result->hdr.priv); + priv->pattern = pattern; + priv->flags = flags; + + /* store the sval[maxcount] array immediately after the arg_rex_priv struct */ + result->sval = (const char * *)(priv + 1); + result->count = 0; + + /* foolproof the string pointers by initializing them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + + /* here we construct and destroy a regex representation of the regular + * expression for no other reason than to force any regex errors to be + * trapped now rather than later. If we don't, then errors may go undetected + * until an argument is actually parsed. + */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + if (rex == NULL) + { + ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern)); + ARG_LOG(("argtable: Bad argument table.\n")); + } + + trex_free(rex); + + ARG_TRACE(("arg_rexn() returns %p\n", result)); + return result; +} + + + +/* see copyright notice in trex.h */ +#include +#include +#include +#include + +#ifdef _UINCODE +#define scisprint iswprint +#define scstrlen wcslen +#define scprintf wprintf +#define _SC(x) L(x) +#else +#define scisprint isprint +#define scstrlen strlen +#define scprintf printf +#define _SC(x) (x) +#endif + +#ifdef _DEBUG +#include + +static const TRexChar *g_nnames[] = +{ + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") +}; + +#endif +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) + +#define TREX_SYMBOL_ANY_CHAR ('.') +#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') +#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*') +#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?') +#define TREX_SYMBOL_BRANCH ('|') +#define TREX_SYMBOL_END_OF_STRING ('$') +#define TREX_SYMBOL_BEGINNING_OF_STRING ('^') +#define TREX_SYMBOL_ESCAPE_CHAR ('\\') + + +typedef int TRexNodeType; + +typedef struct tagTRexNode{ + TRexNodeType type; + int left; + int right; + int next; +}TRexNode; + +struct TRex{ + const TRexChar *_eol; + const TRexChar *_bol; + const TRexChar *_p; + int _first; + int _op; + TRexNode *_nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch *_matches; + int _currsubexp; + void *_jmpbuf; + const TRexChar **_error; + int _flags; +}; + +static int trex_list(TRex *exp); + +static int trex_newnode(TRex *exp, TRexNodeType type) +{ + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + exp->_nallocated *= 2; + exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; +} + +static void trex_error(TRex *exp,const TRexChar *error) +{ + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); +} + +static void trex_expect(TRex *exp, int n){ + if((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; +} + +static TRexChar trex_escapechar(TRex *exp) +{ + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint((int) *exp->_p)) trex_error(exp,_SC("letter expected")); + return (*exp->_p++); +} + +static int trex_charclass(TRex *exp,int classid) +{ + int n = trex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; +} + +static int trex_charnode(TRex *exp,TRexBool isclass) +{ + TRexChar t; + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return trex_newnode(exp,'\n'); + case 't': exp->_p++; return trex_newnode(exp,'\t'); + case 'r': exp->_p++; return trex_newnode(exp,'\r'); + case 'f': exp->_p++; return trex_newnode(exp,'\f'); + case 'v': exp->_p++; return trex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return trex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + int node = trex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + /* falls through */ + default: + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); + } + } + else if(!scisprint((int) *exp->_p)) { + + trex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); +} +static int trex_class(TRex *exp) +{ + int ret = -1; + int first = -1,chain; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ + ret = trex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = trex_newnode(exp,OP_CLASS); + + if(*exp->_p == ']') trex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + int r,t; + if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); + r = trex_newnode(exp,OP_RANGE); + if(first>*exp->_p) trex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp,TRex_True); + } + else{ + first = trex_charnode(exp,TRex_True); + } + } + } + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; +} + +static int trex_parsenumber(TRex *exp) +{ + int ret = *exp->_p-'0'; + int positions = 10; + exp->_p++; + while(isdigit((int) *exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; +} + +static int trex_element(TRex *exp) +{ + int ret = -1; + switch(*exp->_p) + { + case '(': { + int expr,newn; + exp->_p++; + + + if(*exp->_p =='?') { + exp->_p++; + trex_expect(exp,':'); + expr = trex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = trex_newnode(exp,OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp,']'); + break; + case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; + case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; + default: + ret = trex_charnode(exp,TRex_False); + break; + } + + { + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; + case '{': + exp->_p++; + if(!isdigit((int) *exp->_p)) trex_error(exp,_SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit((int) *exp->_p)){ + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp,'}'); + break; + default: + trex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; + + } + if(isgreedy) { + int nnode = trex_newnode(exp,OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } + + return ret; +} + +static int trex_list(TRex *exp) +{ + int ret=-1,e; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp,OP_BOL); + } + e = trex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; + + if(*exp->_p == TREX_SYMBOL_BRANCH) { + int temp,tright; + exp->_p++; + temp = trex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; +} + +static TRexBool trex_matchcclass(int cclass,TRexChar ch) +{ + int c = ch; + switch(cclass) { + case 'a': return isalpha(c)?TRex_True:TRex_False; + case 'A': return !isalpha(c)?TRex_True:TRex_False; + case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; + case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; + case 's': return isspace(c)?TRex_True:TRex_False; + case 'S': return !isspace(c)?TRex_True:TRex_False; + case 'd': return isdigit(c)?TRex_True:TRex_False; + case 'D': return !isdigit(c)?TRex_True:TRex_False; + case 'x': return isxdigit(c)?TRex_True:TRex_False; + case 'X': return !isxdigit(c)?TRex_True:TRex_False; + case 'c': return iscntrl(c)?TRex_True:TRex_False; + case 'C': return !iscntrl(c)?TRex_True:TRex_False; + case 'p': return ispunct(c)?TRex_True:TRex_False; + case 'P': return !ispunct(c)?TRex_True:TRex_False; + case 'l': return islower(c)?TRex_True:TRex_False; + case 'u': return isupper(c)?TRex_True:TRex_False; + } + return TRex_False; /*cannot happen*/ +} + +static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c) +{ + do { + switch(node->type) { + case OP_RANGE: + if (exp->_flags & TREX_ICASE) + { + if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; + if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; + } + else + { + if(c >= node->left && c <= node->right) return TRex_True; + } + break; + case OP_CCLASS: + if(trex_matchcclass(node->left,c)) return TRex_True; + break; + default: + if (exp->_flags & TREX_ICASE) + { + if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; + } + else + { + if(c == node->type)return TRex_True; + } + + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return TRex_False; +} + +static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next) +{ + + TRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + TRexNode *greedystop = NULL; + int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const TRexChar *s=str, *good = str; + + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } + + while((nmaches == 0xFFFF || nmaches < p1)) { + + const TRexChar *stop; + if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + TRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } + + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const TRexChar *asd = str; + TRexNode *temp=&exp->_nodes[node->left]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + TRexNode *n = &exp->_nodes[node->left]; + const TRexChar *cur = str; + int capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + TRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = trex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); + + if(capture != -1) + exp->_matches[capture].len = cur - exp->_matches[capture].begin; + return cur; + } + case OP_WB: + if((str == exp->_bol && !isspace((int) *str)) + || ((str == exp->_eol && !isspace((int) *(str-1)))) + || ((!isspace((int) *str) && isspace((int) *(str+1)))) + || ((isspace((int) *str) && !isspace((int) *(str+1)))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT: + str++; + return str; + case OP_NCLASS: + case OP_CLASS: + if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { + str++; + return str; + } + return NULL; + case OP_CCLASS: + if(trex_matchcclass(node->left,*str)) { + str++; + return str; + } + return NULL; + default: /* char */ + if (exp->_flags & TREX_ICASE) + { + if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; + } + else + { + if (*str != node->type) return NULL; + } + str++; + return str; + } + return NULL; +} + +/* public api */ +TRex *trex_compile(const TRexChar *pattern,const TRexChar **error,int flags) +{ + TRex *exp = (TRex *)malloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = malloc(sizeof(jmp_buf)); + exp->_flags = flags; + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + trex_error(exp,_SC("unexpected character")); +#ifdef _DEBUG + { + int nsize,i; + TRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } +#endif + exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); + } + else{ + trex_free(exp); + return NULL; + } + return exp; +} + +void trex_free(TRex *exp) +{ + if(exp) { + if(exp->_nodes) free(exp->_nodes); + if(exp->_jmpbuf) free(exp->_jmpbuf); + if(exp->_matches) free(exp->_matches); + free(exp); + } +} + +TRexBool trex_match(TRex* exp,const TRexChar* text) +{ + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; +} + +TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) +{ + const TRexChar *cur = NULL; + int node = exp->_first; + if(text_begin >= text_end) return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while(cur == NULL && text_begin != text_end); + + if(cur == NULL) + return TRex_False; + + --text_begin; + + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return TRex_True; +} + +TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) +{ + return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); +} + +int trex_getsubexpcount(TRex* exp) +{ + return exp->_nsubexpr; +} + +TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp) +{ + if( n<0 || n >= exp->_nsubexpr) return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_str_resetfn(struct arg_str *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_str_scanfn(struct arg_str *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + parent->sval[parent->count++] = argval; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_str_checkfn(struct arg_str *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_str_errorfn( + struct arg_str *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + } +} + + +struct arg_str * arg_str0( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_strn(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_str * arg_str1( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_strn(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_str * arg_strn( + const char *shortopts, + const char *longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_str *result; + + /* should not allow this stupid error */ + /* we should return an error code warning this logic error */ + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_str) /* storage for struct arg_str */ + + maxcount * sizeof(char *); /* storage for sval[maxcount] array */ + + result = (struct arg_str *)malloc(nbytes); + if (result) + { + int i; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_str_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_str_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_str_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_str_errorfn; + + /* store the sval[maxcount] array immediately after the arg_str struct */ + result->sval = (const char * *)(result + 1); + result->count = 0; + + /* foolproof the string pointers by initialising them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + } + + ARG_TRACE(("arg_strn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN 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. + ******************************************************************************/ + +#include +#include +#include +#include + +#include "argtable3.h" + +static +void arg_register_error(struct arg_end *end, + void *parent, + int error, + const char *argval) +{ + /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */ + if (end->count < end->hdr.maxcount) + { + end->error[end->count] = error; + end->parent[end->count] = parent; + end->argval[end->count] = argval; + end->count++; + } + else + { + end->error[end->hdr.maxcount - 1] = ARG_ELIMIT; + end->parent[end->hdr.maxcount - 1] = end; + end->argval[end->hdr.maxcount - 1] = NULL; + } +} + + +/* + * Return index of first table entry with a matching short option + * or -1 if no match was found. + */ +static +int find_shortoption(struct arg_hdr * *table, char shortopt) +{ + int tabindex; + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->shortopts && + strchr(table[tabindex]->shortopts, shortopt)) + return tabindex; + } + return -1; +} + + +struct longoptions +{ + int getoptval; + int noptions; + struct option *options; +}; + +#if 0 +static +void dump_longoptions(struct longoptions * longoptions) +{ + int i; + printf("getoptval = %d\n", longoptions->getoptval); + printf("noptions = %d\n", longoptions->noptions); + for (i = 0; i < longoptions->noptions; i++) + { + printf("options[%d].name = \"%s\"\n", + i, + longoptions->options[i].name); + printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg); + printf("options[%d].flag = %p\n", i, longoptions->options[i].flag); + printf("options[%d].val = %d\n", i, longoptions->options[i].val); + } +} +#endif + +static +struct longoptions * alloc_longoptions(struct arg_hdr * *table) +{ + struct longoptions *result; + size_t nbytes; + int noptions = 1; + size_t longoptlen = 0; + int tabindex; + + /* + * Determine the total number of option structs required + * by counting the number of comma separated long options + * in all table entries and return the count in noptions. + * note: noptions starts at 1 not 0 because we getoptlong + * requires a NULL option entry to terminate the option array. + * While we are at it, count the number of chars required + * to store private copies of all the longoption strings + * and return that count in logoptlen. + */ + tabindex = 0; + do + { + const char *longopts = table[tabindex]->longopts; + longoptlen += (longopts ? strlen(longopts) : 0) + 1; + while (longopts) + { + noptions++; + longopts = strchr(longopts + 1, ','); + } + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); + /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/ + + + /* allocate storage for return data structure as: */ + /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */ + nbytes = sizeof(struct longoptions) + + sizeof(struct option) * noptions + + longoptlen; + result = (struct longoptions *)malloc(nbytes); + if (result) + { + int option_index = 0; + char *store; + + result->getoptval = 0; + result->noptions = noptions; + result->options = (struct option *)(result + 1); + store = (char *)(result->options + noptions); + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + const char *longopts = table[tabindex]->longopts; + + while(longopts && *longopts) + { + char *storestart = store; + + /* copy progressive longopt strings into the store */ + while (*longopts != 0 && *longopts != ',') + *store++ = *longopts++; + *store++ = 0; + if (*longopts == ',') + longopts++; + /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/ + + result->options[option_index].name = storestart; + result->options[option_index].flag = &(result->getoptval); + result->options[option_index].val = tabindex; + if (table[tabindex]->flag & ARG_HASOPTVALUE) + result->options[option_index].has_arg = 2; + else if (table[tabindex]->flag & ARG_HASVALUE) + result->options[option_index].has_arg = 1; + else + result->options[option_index].has_arg = 0; + + option_index++; + } + } + /* terminate the options array with a zero-filled entry */ + result->options[option_index].name = 0; + result->options[option_index].has_arg = 0; + result->options[option_index].flag = 0; + result->options[option_index].val = 0; + } + + /*dump_longoptions(result);*/ + return result; +} + +static +char * alloc_shortoptions(struct arg_hdr * *table) +{ + char *result; + size_t len = 2; + int tabindex; + + /* determine the total number of option chars required */ + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + struct arg_hdr *hdr = table[tabindex]; + len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0); + } + + result = malloc(len); + if (result) + { + char *res = result; + + /* add a leading ':' so getopt return codes distinguish */ + /* unrecognised option and options missing argument values */ + *res++ = ':'; + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + struct arg_hdr *hdr = table[tabindex]; + const char *shortopts = hdr->shortopts; + while(shortopts && *shortopts) + { + *res++ = *shortopts++; + if (hdr->flag & ARG_HASVALUE) + *res++ = ':'; + if (hdr->flag & ARG_HASOPTVALUE) + *res++ = ':'; + } + } + /* null terminate the string */ + *res = 0; + } + + /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/ + return result; +} + + +/* return index of the table terminator entry */ +static +int arg_endindex(struct arg_hdr * *table) +{ + int tabindex = 0; + while (!(table[tabindex]->flag & ARG_TERMINATOR)) + tabindex++; + return tabindex; +} + + +static +void arg_parse_tagged(int argc, + char * *argv, + struct arg_hdr * *table, + struct arg_end *endtable) +{ + struct longoptions *longoptions; + char *shortoptions; + int copt; + + /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + + /* allocate short and long option arrays for the given opttable[]. */ + /* if the allocs fail then put an error msg in the last table entry. */ + longoptions = alloc_longoptions(table); + shortoptions = alloc_shortoptions(table); + if (!longoptions || !shortoptions) + { + /* one or both memory allocs failed */ + arg_register_error(endtable, endtable, ARG_EMALLOC, NULL); + /* free anything that was allocated (this is null safe) */ + free(shortoptions); + free(longoptions); + return; + } + + /*dump_longoptions(longoptions);*/ + + /* reset getopts internal option-index to zero, and disable error reporting */ + optind = 0; + opterr = 0; + + /* fetch and process args using getopt_long */ + while( (copt = + getopt_long(argc, argv, shortoptions, longoptions->options, + NULL)) != -1) + { + /* + printf("optarg='%s'\n",optarg); + printf("optind=%d\n",optind); + printf("copt=%c\n",(char)copt); + printf("optopt=%c (%d)\n",optopt, (int)(optopt)); + */ + switch(copt) + { + case 0: + { + int tabindex = longoptions->getoptval; + void *parent = table[tabindex]->parent; + /*printf("long option detected from argtable[%d]\n", tabindex);*/ + if (optarg && optarg[0] == 0 && + (table[tabindex]->flag & ARG_HASVALUE)) + { + /* printf(": long option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, + argv[optind - 1]); + /* continue to scan the (empty) argument value to enforce argument count checking */ + } + if (table[tabindex]->scanfn) + { + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } + break; + + case '?': + /* + * getopt_long() found an unrecognised short option. + * if it was a short option its value is in optopt + * if it was a long option then optopt=0 + */ + switch (optopt) + { + case 0: + /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/ + arg_register_error(endtable, endtable, ARG_ELONGOPT, + argv[optind - 1]); + break; + default: + /*printf("?* unrecognised short option '%c'\n",optopt);*/ + arg_register_error(endtable, endtable, optopt, NULL); + break; + } + break; + + case ':': + /* + * getopt_long() found an option with its argument missing. + */ + /*printf(": option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, + argv[optind - 1]); + break; + + default: + { + /* getopt_long() found a valid short option */ + int tabindex = find_shortoption(table, (char)copt); + /*printf("short option detected from argtable[%d]\n", tabindex);*/ + if (tabindex == -1) + { + /* should never get here - but handle it just in case */ + /*printf("unrecognised short option %d\n",copt);*/ + arg_register_error(endtable, endtable, copt, NULL); + } + else + { + if (table[tabindex]->scanfn) + { + void *parent = table[tabindex]->parent; + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } + break; + } + } + } + + free(shortoptions); + free(longoptions); +} + + +static +void arg_parse_untagged(int argc, + char * *argv, + struct arg_hdr * *table, + struct arg_end *endtable) +{ + int tabindex = 0; + int errorlast = 0; + const char *optarglast = NULL; + void *parentlast = NULL; + + /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + while (!(table[tabindex]->flag & ARG_TERMINATOR)) + { + void *parent; + int errorcode; + + /* if we have exhausted our argv[optind] entries then we have finished */ + if (optind >= argc) + { + /*printf("arg_parse_untagged(): argv[] exhausted\n");*/ + return; + } + + /* skip table entries with non-null long or short options (they are not untagged entries) */ + if (table[tabindex]->longopts || table[tabindex]->shortopts) + { + /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/ + tabindex++; + continue; + } + + /* skip table entries with NULL scanfn */ + if (!(table[tabindex]->scanfn)) + { + /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/ + tabindex++; + continue; + } + + /* attempt to scan the current argv[optind] with the current */ + /* table[tabindex] entry. If it succeeds then keep it, otherwise */ + /* try again with the next table[] entry. */ + parent = table[tabindex]->parent; + errorcode = table[tabindex]->scanfn(parent, argv[optind]); + if (errorcode == 0) + { + /* success, move onto next argv[optind] but stay with same table[tabindex] */ + /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/ + optind++; + + /* clear the last tentative error */ + errorlast = 0; + } + else + { + /* failure, try same argv[optind] with next table[tabindex] entry */ + /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/ + tabindex++; + + /* remember this as a tentative error we may wish to reinstate later */ + errorlast = errorcode; + optarglast = argv[optind]; + parentlast = parent; + } + + } + + /* if a tenative error still remains at this point then register it as a proper error */ + if (errorlast) + { + arg_register_error(endtable, parentlast, errorlast, optarglast); + optind++; + } + + /* only get here when not all argv[] entries were consumed */ + /* register an error for each unused argv[] entry */ + while (optind < argc) + { + /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/ + arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]); + } + + return; +} + + +static +void arg_parse_check(struct arg_hdr * *table, struct arg_end *endtable) +{ + int tabindex = 0; + /* printf("arg_parse_check()\n"); */ + do + { + if (table[tabindex]->checkfn) + { + void *parent = table[tabindex]->parent; + int errorcode = table[tabindex]->checkfn(parent); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, NULL); + } + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + + +static +void arg_reset(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex = 0; + /*printf("arg_reset(%p)\n",argtable);*/ + do + { + if (table[tabindex]->resetfn) + table[tabindex]->resetfn(table[tabindex]->parent); + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + + +int arg_parse(int argc, char * *argv, void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + struct arg_end *endtable; + int endindex; + char * *argvcopy = NULL; + + /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/ + + /* reset any argtable data from previous invocations */ + arg_reset(argtable); + + /* locate the first end-of-table marker within the array */ + endindex = arg_endindex(table); + endtable = (struct arg_end *)table[endindex]; + + /* Special case of argc==0. This can occur on Texas Instruments DSP. */ + /* Failure to trap this case results in an unwanted NULL result from */ + /* the malloc for argvcopy (next code block). */ + if (argc == 0) + { + /* We must still perform post-parse checks despite the absence of command line arguments */ + arg_parse_check(table, endtable); + + /* Now we are finished */ + return endtable->count; + } + + argvcopy = (char **)malloc(sizeof(char *) * (argc + 1)); + if (argvcopy) + { + int i; + + /* + Fill in the local copy of argv[]. We need a local copy + because getopt rearranges argv[] which adversely affects + susbsequent parsing attempts. + */ + for (i = 0; i < argc; i++) + argvcopy[i] = argv[i]; + + argvcopy[argc] = NULL; + + /* parse the command line (local copy) for tagged options */ + arg_parse_tagged(argc, argvcopy, table, endtable); + + /* parse the command line (local copy) for untagged options */ + arg_parse_untagged(argc, argvcopy, table, endtable); + + /* if no errors so far then perform post-parse checks otherwise dont bother */ + if (endtable->count == 0) + arg_parse_check(table, endtable); + + /* release the local copt of argv[] */ + free(argvcopy); + } + else + { + /* memory alloc failed */ + arg_register_error(endtable, endtable, ARG_EMALLOC, NULL); + } + + return endtable->count; +} + + +/* + * Concatenate contents of src[] string onto *pdest[] string. + * The *pdest pointer is altered to point to the end of the + * target string and *pndest is decremented by the same number + * of chars. + * Does not append more than *pndest chars into *pdest[] + * so as to prevent buffer overruns. + * Its something like strncat() but more efficient for repeated + * calls on the same destination string. + * Example of use: + * char dest[30] = "good" + * size_t ndest = sizeof(dest); + * char *pdest = dest; + * arg_char(&pdest,"bye ",&ndest); + * arg_char(&pdest,"cruel ",&ndest); + * arg_char(&pdest,"world!",&ndest); + * Results in: + * dest[] == "goodbye cruel world!" + * ndest == 10 + */ +static +void arg_cat(char * *pdest, const char *src, size_t *pndest) +{ + char *dest = *pdest; + char *end = dest + *pndest; + + /*locate null terminator of dest string */ + while(dest < end && *dest != 0) + dest++; + + /* concat src string to dest string */ + while(dest < end && *src != 0) + *dest++ = *src++; + + /* null terminate dest string */ + *dest = 0; + + /* update *pdest and *pndest */ + *pndest = end - dest; + *pdest = dest; +} + + +static +void arg_cat_option(char *dest, + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue) +{ + if (shortopts) + { + char option[3]; + + /* note: option array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + option[0] = '-'; + option[1] = shortopts[0]; + option[2] = 0; + + arg_cat(&dest, option, &ndest); + if (datatype) + { + arg_cat(&dest, " ", &ndest); + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } + } + else if (longopts) + { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(longopts, ","); + strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest); + + if (datatype) + { + arg_cat(&dest, "=", &ndest); + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } + } + else if (datatype) + { + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } +} + +static +void arg_cat_optionv(char *dest, + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue, + const char *separator) +{ + separator = separator ? separator : ""; + + if (shortopts) + { + const char *c = shortopts; + while(*c) + { + /* "-a|-b|-c" */ + char shortopt[3]; + + /* note: shortopt array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + shortopt[0] = '-'; + shortopt[1] = *c; + shortopt[2] = 0; + + arg_cat(&dest, shortopt, &ndest); + if (*++c) + arg_cat(&dest, separator, &ndest); + } + } + + /* put separator between long opts and short opts */ + if (shortopts && longopts) + arg_cat(&dest, separator, &ndest); + + if (longopts) + { + const char *c = longopts; + while(*c) + { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(c, ","); + strncat(dest, c, (ncspn < ndest) ? ncspn : ndest); + c += ncspn; + + /* add given separator in place of comma */ + if (*c == ',') + { + arg_cat(&dest, separator, &ndest); + c++; + } + } + } + + if (datatype) + { + if (longopts) + arg_cat(&dest, "=", &ndest); + else if (shortopts) + arg_cat(&dest, " ", &ndest); + + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } +} + + +/* this function should be deprecated because it doesnt consider optional argument values (ARG_HASOPTVALUE) */ +void arg_print_option(FILE *fp, + const char *shortopts, + const char *longopts, + const char *datatype, + const char *suffix) +{ + char syntax[200] = ""; + suffix = suffix ? suffix : ""; + + /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */ + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + 0, + "|"); + + fputs(syntax, fp); + fputs(suffix, fp); +} + + +/* + * Print a GNU style [OPTION] string in which all short options that + * do not take argument values are presented in abbreviated form, as + * in: -xvfsd, or -xvf[sd], or [-xvsfd] + */ +static +void arg_print_gnuswitch(FILE *fp, struct arg_hdr * *table) +{ + int tabindex; + const char *format1 = " -%c"; + const char *format2 = " [-%c"; + const char *suffix = ""; + + /* print all mandatory switches that are without argument values */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + /* skip optional options */ + if (table[tabindex]->mincount < 1) + continue; + + /* skip non-short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip options that take argument values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print the short option (only the first short option char, ignore multiple choices)*/ + fprintf(fp, format1, table[tabindex]->shortopts[0]); + format1 = "%c"; + format2 = "[%c"; + } + + /* print all optional switches that are without argument values */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + /* skip mandatory args */ + if (table[tabindex]->mincount > 0) + continue; + + /* skip args without short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip args with values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print first short option */ + fprintf(fp, format2, table[tabindex]->shortopts[0]); + format2 = "%c"; + suffix = "]"; + } + + fprintf(fp, "%s", suffix); +} + + +void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int i, tabindex; + + /* print GNU style [OPTION] string */ + arg_print_gnuswitch(fp, table); + + /* print remaining options in abbreviated style */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + /* skip short options without arg values (they were printed by arg_print_gnu_switch) */ + if (table[tabindex]->shortopts && + !(table[tabindex]->flag & ARG_HASVALUE)) + continue; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_option(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE); + + if (strlen(syntax) > 0) + { + /* print mandatory instances of this option */ + for (i = 0; i < table[tabindex]->mincount; i++) + fprintf(fp, " %s", syntax); + + /* print optional instances enclosed in "[..]" */ + switch ( table[tabindex]->maxcount - table[tabindex]->mincount ) + { + case 0: + break; + case 1: + fprintf(fp, " [%s]", syntax); + break; + case 2: + fprintf(fp, " [%s] [%s]", syntax, syntax); + break; + default: + fprintf(fp, " [%s]...", syntax); + break; + } + } + } + + if (suffix) + fprintf(fp, "%s", suffix); +} + + +void arg_print_syntaxv(FILE *fp, void * *argtable, const char *suffix) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int i, tabindex; + + /* print remaining options in abbreviated style */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + "|"); + + /* print mandatory options */ + for (i = 0; i < table[tabindex]->mincount; i++) + fprintf(fp, " %s", syntax); + + /* print optional args enclosed in "[..]" */ + switch ( table[tabindex]->maxcount - table[tabindex]->mincount ) + { + case 0: + break; + case 1: + fprintf(fp, " [%s]", syntax); + break; + case 2: + fprintf(fp, " [%s] [%s]", syntax, syntax); + break; + default: + fprintf(fp, " [%s]...", syntax); + break; + } + } + + if (suffix) + fprintf(fp, "%s", suffix); +} + + +void arg_print_glossary(FILE *fp, void * *argtable, const char *format) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + + format = format ? format : " %-20s %s\n"; + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->glossary) + { + char syntax[200] = ""; + const char *shortopts = table[tabindex]->shortopts; + const char *longopts = table[tabindex]->longopts; + const char *datatype = table[tabindex]->datatype; + const char *glossary = table[tabindex]->glossary; + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + ", "); + fprintf(fp, format, syntax, glossary); + } + } +} + + +/** + * Print a piece of text formatted, which means in a column with a + * left and a right margin. The lines are wrapped at whitspaces next + * to right margin. The function does not indent the first line, but + * only the following ones. + * + * Example: + * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * Too long lines will be wrapped in the middle of a word. + * + * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * As you see, the first line is not indented. This enables output of + * lines, which start in a line where output already happened. + * + * Author: Uli Fouquet + */ +void arg_print_formatted( FILE *fp, + const unsigned lmargin, + const unsigned rmargin, + const char *text ) +{ + const unsigned textlen = strlen( text ); + unsigned line_start = 0; + unsigned line_end = textlen + 1; + const unsigned colwidth = (rmargin - lmargin) + 1; + + /* Someone doesn't like us... */ + if ( line_end < line_start ) + { fprintf( fp, "%s\n", text ); } + + while (line_end - 1 > line_start ) + { + /* Eat leading whitespaces. This is essential because while + wrapping lines, there will often be a whitespace at beginning + of line */ + while ( isspace((int) *(text + line_start)) ) + { line_start++; } + + if ((line_end - line_start) > colwidth ) + { line_end = line_start + colwidth; } + + /* Find last whitespace, that fits into line */ + while ( ( line_end > line_start ) + && ( line_end - line_start > colwidth ) + && !isspace((int) *(text + line_end))) + { line_end--; } + + /* Do not print trailing whitespace. If this text + has got only one line, line_end now points to the + last char due to initialization. */ + line_end--; + + /* Output line of text */ + while ( line_start < line_end ) + { + fputc(*(text + line_start), fp ); + line_start++; + } + fputc( '\n', fp ); + + /* Initialize another line */ + if ( line_end + 1 < textlen ) + { + unsigned i; + + for (i = 0; i < lmargin; i++ ) + { fputc( ' ', fp ); } + + line_end = textlen; + } + + /* If we have to print another line, get also the last char. */ + line_end++; + + } /* lines of text */ +} + +/** + * Prints the glossary in strict GNU format. + * Differences to arg_print_glossary() are: + * - wraps lines after 80 chars + * - indents lines without shortops + * - does not accept formatstrings + * + * Contributed by Uli Fouquet + */ +void arg_print_glossary_gnu(FILE *fp, void * *argtable ) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->glossary) + { + char syntax[200] = ""; + const char *shortopts = table[tabindex]->shortopts; + const char *longopts = table[tabindex]->longopts; + const char *datatype = table[tabindex]->datatype; + const char *glossary = table[tabindex]->glossary; + + if ( !shortopts && longopts ) + { + /* Indent trailing line by 4 spaces... */ + memset( syntax, ' ', 4 ); + *(syntax + 4) = '\0'; + } + + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + ", "); + + /* If syntax fits not into column, print glossary in new line... */ + if ( strlen(syntax) > 25 ) + { + fprintf( fp, " %-25s %s\n", syntax, "" ); + *syntax = '\0'; + } + + fprintf( fp, " %-25s ", syntax ); + arg_print_formatted( fp, 28, 79, glossary ); + } + } /* for each table entry */ + + fputc( '\n', fp ); +} + + +/** + * Checks the argtable[] array for NULL entries and returns 1 + * if any are found, zero otherwise. + */ +int arg_nullcheck(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + /*printf("arg_nullcheck(%p)\n",argtable);*/ + + if (!table) + return 1; + + tabindex = 0; + do + { + /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/ + if (!table[tabindex]) + return 1; + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); + + return 0; +} + + +/* + * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design. + * The flaw results in memory leak in the (very rare) case that an intermediate + * entry in the argtable array failed its memory allocation while others following + * that entry were still allocated ok. Those subsequent allocations will not be + * deallocated by arg_free(). + * Despite the unlikeliness of the problem occurring, and the even unlikelier event + * that it has any deliterious effect, it is fixed regardless by replacing arg_free() + * with the newer arg_freetable() function. + * We still keep arg_free() for backwards compatibility. + */ +void arg_free(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex = 0; + int flag; + /*printf("arg_free(%p)\n",argtable);*/ + do + { + /* + if we encounter a NULL entry then somewhat incorrectly we presume + we have come to the end of the array. It isnt strictly true because + an intermediate entry could be NULL with other non-NULL entries to follow. + The subsequent argtable entries would then not be freed as they should. + */ + if (table[tabindex] == NULL) + break; + + flag = table[tabindex]->flag; + free(table[tabindex]); + table[tabindex++] = NULL; + + } while(!(flag & ARG_TERMINATOR)); +} + +/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */ +void arg_freetable(void * *argtable, size_t n) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + size_t tabindex = 0; + /*printf("arg_freetable(%p)\n",argtable);*/ + for (tabindex = 0; tabindex < n; tabindex++) + { + if (table[tabindex] == NULL) + continue; + + free(table[tabindex]); + table[tabindex] = NULL; + }; +} + diff --git a/components/console/argtable3/argtable3.h b/components/console/argtable3/argtable3.h new file mode 100644 index 000000000..37a321fb5 --- /dev/null +++ b/components/console/argtable3/argtable3.h @@ -0,0 +1,306 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN 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 AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARGTABLE3 +#define ARGTABLE3 + +#include /* FILE */ +#include /* struct tm */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARG_REX_ICASE 1 + +/* bit masks for arg_hdr.flag */ +enum +{ + ARG_TERMINATOR=0x1, + ARG_HASVALUE=0x2, + ARG_HASOPTVALUE=0x4 +}; + +typedef void (arg_resetfn)(void *parent); +typedef int (arg_scanfn)(void *parent, const char *argval); +typedef int (arg_checkfn)(void *parent); +typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname); + + +/* +* The arg_hdr struct defines properties that are common to all arg_xxx structs. +* The argtable library requires each arg_xxx struct to have an arg_hdr +* struct as its first data member. +* The argtable library functions then use this data to identify the +* properties of the command line option, such as its option tags, +* datatype string, and glossary strings, and so on. +* Moreover, the arg_hdr struct contains pointers to custom functions that +* are provided by each arg_xxx struct which perform the tasks of parsing +* that particular arg_xxx arguments, performing post-parse checks, and +* reporting errors. +* These functions are private to the individual arg_xxx source code +* and are the pointer to them are initiliased by that arg_xxx struct's +* constructor function. The user could alter them after construction +* if desired, but the original intention is for them to be set by the +* constructor and left unaltered. +*/ +struct arg_hdr +{ + char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */ + const char *shortopts; /* String defining the short options */ + const char *longopts; /* String defiing the long options */ + const char *datatype; /* Description of the argument data type */ + const char *glossary; /* Description of the option as shown by arg_print_glossary function */ + int mincount; /* Minimum number of occurences of this option accepted */ + int maxcount; /* Maximum number of occurences if this option accepted */ + void *parent; /* Pointer to parent arg_xxx struct */ + arg_resetfn *resetfn; /* Pointer to parent arg_xxx reset function */ + arg_scanfn *scanfn; /* Pointer to parent arg_xxx scan function */ + arg_checkfn *checkfn; /* Pointer to parent arg_xxx check function */ + arg_errorfn *errorfn; /* Pointer to parent arg_xxx error function */ + void *priv; /* Pointer to private header data for use by arg_xxx functions */ +}; + +struct arg_rem +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ +}; + +struct arg_lit +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ +}; + +struct arg_int +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + int *ival; /* Array of parsed argument values */ +}; + +struct arg_dbl +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + double *dval; /* Array of parsed argument values */ +}; + +struct arg_str +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char **sval; /* Array of parsed argument values */ +}; + +struct arg_rex +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char **sval; /* Array of parsed argument values */ +}; + +struct arg_file +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args*/ + const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */ + const char **basename; /* Array of parsed basenames (eg: foo.bar) */ + const char **extension; /* Array of parsed extensions (eg: .bar) */ +}; + +struct arg_date +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + const char *format; /* strptime format string used to parse the date */ + int count; /* Number of matching command line args */ + struct tm *tmval; /* Array of parsed time values */ +}; + +enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG}; +struct arg_end +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of errors encountered */ + int *error; /* Array of error codes */ + void **parent; /* Array of pointers to offending arg_xxx struct */ + const char **argval; /* Array of pointers to offending argv[] string */ +}; + + +/**** arg_xxx constructor functions *********************************/ + +struct arg_rem* arg_rem(const char* datatype, const char* glossary); + +struct arg_lit* arg_lit0(const char* shortopts, + const char* longopts, + const char* glossary); +struct arg_lit* arg_lit1(const char* shortopts, + const char* longopts, + const char *glossary); +struct arg_lit* arg_litn(const char* shortopts, + const char* longopts, + int mincount, + int maxcount, + const char *glossary); + +struct arg_key* arg_key0(const char* keyword, + int flags, + const char* glossary); +struct arg_key* arg_key1(const char* keyword, + int flags, + const char* glossary); +struct arg_key* arg_keyn(const char* keyword, + int flags, + int mincount, + int maxcount, + const char* glossary); + +struct arg_int* arg_int0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_int* arg_int1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_int* arg_intn(const char* shortopts, + const char* longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_dbl* arg_dbl0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_dbl* arg_dbl1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_dbl* arg_dbln(const char* shortopts, + const char* longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_str* arg_str0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_str* arg_str1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_str* arg_strn(const char* shortopts, + const char* longopts, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_rex* arg_rex0(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int flags, + const char* glossary); +struct arg_rex* arg_rex1(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int flags, + const char *glossary); +struct arg_rex* arg_rexn(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int mincount, + int maxcount, + int flags, + const char *glossary); + +struct arg_file* arg_file0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_file* arg_file1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_file* arg_filen(const char* shortopts, + const char* longopts, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_date* arg_date0(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + const char* glossary); +struct arg_date* arg_date1(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + const char *glossary); +struct arg_date* arg_daten(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_end* arg_end(int maxerrors); + + +/**** other functions *******************************************/ +int arg_nullcheck(void **argtable); +int arg_parse(int argc, char **argv, void **argtable); +void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix); +void arg_print_syntax(FILE *fp, void **argtable, const char *suffix); +void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix); +void arg_print_glossary(FILE *fp, void **argtable, const char *format); +void arg_print_glossary_gnu(FILE *fp, void **argtable); +void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname); +void arg_freetable(void **argtable, size_t n); +void arg_print_formatted(FILE *fp, const unsigned lmargin, const unsigned rmargin, const char *text); + +/**** deprecated functions, for back-compatibility only ********/ +void arg_free(void **argtable); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/console/commands.c b/components/console/commands.c new file mode 100644 index 000000000..7d7232869 --- /dev/null +++ b/components/console/commands.c @@ -0,0 +1,243 @@ +// Copyright 2016-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_console.h" +#include "linenoise/linenoise.h" +#include "argtable3/argtable3.h" +#include "rom/queue.h" + +#define ANSI_COLOR_DEFAULT 39 /** Default foreground color */ + +typedef struct cmd_item_ { + /** + * Command name (statically allocated by application) + */ + const char *command; + /** + * Help text (statically allocated by application), may be NULL. + */ + const char *help; + /** + * Hint text, usually lists possible arguments, dynamically allocated. + * May be NULL. + */ + char *hint; + esp_console_cmd_func_t func; //!< pointer to the command handler + void *argtable; //!< optional pointer to arg table + SLIST_ENTRY(cmd_item_) next; //!< next command in the list +} cmd_item_t; + +/** linked list of command structures */ +static SLIST_HEAD(cmd_list_, cmd_item_) s_cmd_list; + +/** run-time configuration options */ +static esp_console_config_t s_config; + +/** temporary buffer used for command line parsing */ +static char *s_tmp_line_buf; + +static const cmd_item_t *find_command_by_name(const char *name); + +esp_err_t esp_console_init(const esp_console_config_t *config) +{ + if (s_tmp_line_buf) { + return ESP_ERR_INVALID_STATE; + } + memcpy(&s_config, config, sizeof(s_config)); + if (s_config.hint_color == 0) { + s_config.hint_color = ANSI_COLOR_DEFAULT; + } + s_tmp_line_buf = calloc(config->max_cmdline_length, 1); + if (s_tmp_line_buf == NULL) { + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +esp_err_t esp_console_deinit() +{ + if (!s_tmp_line_buf) { + return ESP_ERR_INVALID_STATE; + } + free(s_tmp_line_buf); + cmd_item_t *it, *tmp; + SLIST_FOREACH_SAFE(it, &s_cmd_list, next, tmp) { + free(it->hint); + free(it); + } + return ESP_OK; +} + +esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) +{ + cmd_item_t *item = (cmd_item_t *) calloc(1, sizeof(*item)); + if (item == NULL) { + return ESP_ERR_NO_MEM; + } + if (cmd->command == NULL) { + free(item); + return ESP_ERR_INVALID_ARG; + } + if (strchr(cmd->command, ' ') != NULL) { + free(item); + return ESP_ERR_INVALID_ARG; + } + item->command = cmd->command; + item->help = cmd->help; + if (cmd->hint) { + /* Prepend a space before the hint. It separates command name and + * the hint. arg_print_syntax below adds this space as well. + */ + int unused __attribute__((unused)); + unused = asprintf(&item->hint, " %s", cmd->hint); + } else if (cmd->argtable) { + /* Generate hint based on cmd->argtable */ + char *buf = NULL; + size_t buf_size = 0; + FILE *f = open_memstream(&buf, &buf_size); + if (f != NULL) { + arg_print_syntax(f, cmd->argtable, NULL); + fclose(f); + } + item->hint = buf; + } + item->argtable = cmd->argtable; + item->func = cmd->func; + cmd_item_t *last = SLIST_FIRST(&s_cmd_list); + if (last == NULL) { + SLIST_INSERT_HEAD(&s_cmd_list, item, next); + } else { + cmd_item_t *it; + while ((it = SLIST_NEXT(last, next)) != NULL) { + last = it; + } + SLIST_INSERT_AFTER(last, item, next); + } + return ESP_OK; +} + +void esp_console_get_completion(const char *buf, linenoiseCompletions *lc) +{ + size_t len = strlen(buf); + if (len == 0) { + return; + } + cmd_item_t *it; + SLIST_FOREACH(it, &s_cmd_list, next) { + /* Check if command starts with buf */ + if (strncmp(buf, it->command, len) == 0) { + linenoiseAddCompletion(lc, it->command); + } + } +} + +const char *esp_console_get_hint(const char *buf, int *color, int *bold) +{ + int len = strlen(buf); + cmd_item_t *it; + SLIST_FOREACH(it, &s_cmd_list, next) { + if (strlen(it->command) == len && + strncmp(buf, it->command, len) == 0) { + *color = s_config.hint_color; + *bold = s_config.hint_bold; + return it->hint; + } + } + return NULL; +} + +static const cmd_item_t *find_command_by_name(const char *name) +{ + const cmd_item_t *cmd = NULL; + cmd_item_t *it; + SLIST_FOREACH(it, &s_cmd_list, next) { + if (strcmp(name, it->command) == 0) { + cmd = it; + break; + } + } + return cmd; +} + +esp_err_t esp_console_run(const char *cmdline, int *cmd_ret) +{ + if (s_tmp_line_buf == NULL) { + return ESP_ERR_INVALID_STATE; + } + char **argv = (char **) calloc(s_config.max_cmdline_args, sizeof(char *)); + if (argv == NULL) { + return ESP_ERR_NO_MEM; + } + strlcpy(s_tmp_line_buf, cmdline, s_config.max_cmdline_length); + + size_t argc = esp_console_split_argv(s_tmp_line_buf, argv, + s_config.max_cmdline_args); + if (argc == 0) { + free(argv); + return ESP_ERR_INVALID_ARG; + } + const cmd_item_t *cmd = find_command_by_name(argv[0]); + if (cmd == NULL) { + free(argv); + return ESP_ERR_NOT_FOUND; + } + *cmd_ret = (*cmd->func)(argc, argv); + free(argv); + return ESP_OK; +} + +static int help_command(int argc, char **argv) +{ + cmd_item_t *it; + + /* Print summary of each command */ + SLIST_FOREACH(it, &s_cmd_list, next) { + if (it->help == NULL) { + continue; + } + /* First line: command name and hint + * Pad all the hints to the same column + */ + const char *hint = (it->hint) ? it->hint : ""; + printf("%-s %s\n", it->command, hint); + /* Second line: print help. + * Argtable has a nice helper function for this which does line + * wrapping. + */ + printf(" "); // arg_print_formatted does not indent the first line + arg_print_formatted(stdout, 2, 78, it->help); + /* Finally, print the list of arguments */ + if (it->argtable) { + arg_print_glossary(stdout, (void **) it->argtable, " %12s %s\n"); + } + printf("\n"); + } + return 0; +} + + +esp_err_t esp_console_register_help_command() +{ + esp_console_cmd_t command = { + .command = "help", + .help = "Print the list of registered commands", + .func = &help_command + }; + return esp_console_cmd_register(&command); +} diff --git a/components/console/component.mk b/components/console/component.mk new file mode 100644 index 000000000..c7bb95b12 --- /dev/null +++ b/components/console/component.mk @@ -0,0 +1,3 @@ + +COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_SRCDIRS := linenoise argtable3 . diff --git a/components/console/esp_console.h b/components/console/esp_console.h new file mode 100644 index 000000000..45a10b7a2 --- /dev/null +++ b/components/console/esp_console.h @@ -0,0 +1,192 @@ +// Copyright 2016-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include "esp_err.h" + +// Forward declaration. Definition in linenoise/linenoise.h. +typedef struct linenoiseCompletions linenoiseCompletions; + +/** + * @brief Parameters for console initialization + */ +typedef struct { + size_t max_cmdline_length; //!< length of command line buffer, in bytes + size_t max_cmdline_args; //!< maximum number of command line arguments to parse + int hint_color; //!< ASCII color code of hint text + int hint_bold; //!< Set to 1 to print hint text in bold +} esp_console_config_t; + +/** + * @brief initialize console module + * Call this once before using other console module features + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if out of memory + * - ESP_ERR_INVALID_STATE if already initialized + */ +esp_err_t esp_console_init(const esp_console_config_t* config); + + +/** + * @brief de-initialize console module + * Call this once when done using console module functions + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if not initialized yet + */ +esp_err_t esp_console_deinit(); + + +/** + * @brief Console command main function + * @param argc number of arguments + * @param argv array with argc entries, each pointing to a zero-terminated string argument + * @return console command return code, 0 indicates "success" + */ +typedef int (*esp_console_cmd_func_t)(int argc, char** argv); + +/** + * @brief Console command description + */ +typedef struct { + /** + * Command name. Must not be NULL, must not contain spaces. + * The pointer must be valid until the call to esp_console_deinit. + */ + const char* command; //!< command name + /** + * Help text for the command, shown by help command. + * If set, the pointer must be valid until the call to esp_console_deinit. + * If not set, the command will not be listed in 'help' output. + */ + const char* help; + /** + * Hint text, usually lists possible arguments. + * If set to NULL, and 'argtable' field is non-NULL, hint will be generated + * automatically + */ + const char* hint; + /** + * Pointer to a function which implements the command. + */ + esp_console_cmd_func_t func; + /** + * Array or structure of pointers to arg_xxx structures, may be NULL. + * Used to generate hint text if 'hint' is set to NULL. + * Array/structure which this field points to must end with an arg_end. + * Only used for the duration of esp_console_cmd_register call. + */ + void* argtable; +} esp_console_cmd_t; + +/** + * @brief Register console command + * @param cmd pointer to the command description; can point to a temporary value + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if out of memory + */ +esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd); + +/** + * @brief Run command line + * @param cmdline command line (command name followed by a number of arguments) + * @param[out] cmd_ret return code from the command (set if command was run) + * @return + * - ESP_OK, if command was run + * - ESP_ERR_INVALID_ARG, if the command line is empty, or only contained + * whitespace + * - ESP_ERR_NOT_FOUND, if command with given name wasn't registered + * - ESP_ERR_INVALID_STATE, if esp_console_init wasn't called + */ +esp_err_t esp_console_run(const char* cmdline, int* cmd_ret); + +/** + * @brief Split command line into arguments in place + * + * - This function finds whitespace-separated arguments in the given input line. + * + * 'abc def 1 20 .3' -> [ 'abc', 'def', '1', '20', '.3' ] + * + * - Argument which include spaces may be surrounded with quotes. In this case + * spaces are preserved and quotes are stripped. + * + * 'abc "123 456" def' -> [ 'abc', '123 456', 'def' ] + * + * - Escape sequences may be used to produce backslash, double quote, and space: + * + * 'a\ b\\c\"' -> [ 'a b\c"' ] + * + * Pointers to at most argv_size - 1 arguments are returned in argv array. + * The pointer after the last one (i.e. argv[argc]) is set to NULL. + * + * @param line pointer to buffer to parse; it is modified in place + * @param argv array where the pointers to arguments are written + * @param argv_size number of elements in argv_array (max. number of arguments) + * @return number of arguments found (argc) + */ +size_t esp_console_split_argv(char *line, char **argv, size_t argv_size); + +/** + * @brief Callback which provides command completion for linenoise library + * + * When using linenoise for line editing, command completion support + * can be enabled like this: + * + * linenoiseSetCompletionCallback(&esp_console_get_completion); + * + * @param buf the string typed by the user + * @param lc linenoiseCompletions to be filled in + */ +void esp_console_get_completion(const char *buf, linenoiseCompletions *lc); + +/** + * @brief Callback which provides command hints for linenoise library + * + * When using linenoise for line editing, hints support can be enabled as + * follows: + * + * linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint); + * + * The extra cast is needed because linenoiseHintsCallback is defined as + * returning a char* instead of const char*. + * + * @param buf line typed by the user + * @param[out] color ANSI color code to be used when displaying the hint + * @param[out] bold set to 1 if hint has to be displayed in bold + * @return string containing the hint text. This string is persistent and should + * not be freed (i.e. linenoiseSetFreeHintsCallback should not be used). + */ +const char *esp_console_get_hint(const char *buf, int *color, int *bold); + +/** + * @brief Register a 'help' command + * Default 'help' command prints the list of registered commands along with + * hints and help strings. + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE, if esp_console_init wasn't called + */ +esp_err_t esp_console_register_help_command(); + +#ifdef __cplusplus +} +#endif diff --git a/components/console/linenoise/LICENSE b/components/console/linenoise/LICENSE new file mode 100644 index 000000000..18e814865 --- /dev/null +++ b/components/console/linenoise/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2010-2014, Salvatore Sanfilippo +Copyright (c) 2010-2013, Pieter Noordhuis + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/console/linenoise/linenoise.c b/components/console/linenoise/linenoise.c new file mode 100644 index 000000000..f88a24620 --- /dev/null +++ b/components/console/linenoise/linenoise.c @@ -0,0 +1,1116 @@ +/* linenoise.c -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * You can find the latest source code at: + * + * http://github.com/antirez/linenoise + * + * Does a number of crazy assumptions that happen to be true in 99.9999% of + * the 2010 UNIX computers around. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010-2016, Salvatore Sanfilippo + * Copyright (c) 2010-2013, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------------------------ + * + * References: + * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html + * + * Todo list: + * - Filter bogus Ctrl+ combinations. + * - Win32 support + * + * Bloat: + * - History search like Ctrl+r in readline? + * + * List of escape sequences used by this program, we do everything just + * with three sequences. In order to be so cheap we may have some + * flickering effect with some slow terminal, but the lesser sequences + * the more compatible. + * + * EL (Erase Line) + * Sequence: ESC [ n K + * Effect: if n is 0 or missing, clear from cursor to end of line + * Effect: if n is 1, clear from beginning of line to cursor + * Effect: if n is 2, clear entire line + * + * CUF (CUrsor Forward) + * Sequence: ESC [ n C + * Effect: moves cursor forward n chars + * + * CUB (CUrsor Backward) + * Sequence: ESC [ n D + * Effect: moves cursor backward n chars + * + * The following is used to get the terminal width if getting + * the width with the TIOCGWINSZ ioctl fails + * + * DSR (Device Status Report) + * Sequence: ESC [ 6 n + * Effect: reports the current cusor position as ESC [ n ; m R + * where n is the row and m is the column + * + * When multi line mode is enabled, we also use an additional escape + * sequence. However multi line editing is disabled by default. + * + * CUU (Cursor Up) + * Sequence: ESC [ n A + * Effect: moves cursor up of n chars. + * + * CUD (Cursor Down) + * Sequence: ESC [ n B + * Effect: moves cursor down of n chars. + * + * When linenoiseClearScreen() is called, two additional escape sequences + * are used in order to clear the screen and position the cursor at home + * position. + * + * CUP (Cursor position) + * Sequence: ESC [ H + * Effect: moves the cursor to upper left corner + * + * ED (Erase display) + * Sequence: ESC [ 2 J + * Effect: clear the whole screen + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linenoise.h" + +#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 +#define LINENOISE_MAX_LINE 4096 + +static linenoiseCompletionCallback *completionCallback = NULL; +static linenoiseHintsCallback *hintsCallback = NULL; +static linenoiseFreeHintsCallback *freeHintsCallback = NULL; + +static int mlmode = 0; /* Multi line mode. Default is single line. */ +static int dumbmode = 0; /* Dumb mode where line editing is disabled. Off by default */ +static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; +static int history_len = 0; +static char **history = NULL; + +/* The linenoiseState structure represents the state during line editing. + * We pass this state to functions implementing specific editing + * functionalities. */ +struct linenoiseState { + char *buf; /* Edited line buffer. */ + size_t buflen; /* Edited line buffer size. */ + const char *prompt; /* Prompt to display. */ + size_t plen; /* Prompt length. */ + size_t pos; /* Current cursor position. */ + size_t oldpos; /* Previous refresh cursor position. */ + size_t len; /* Current edited line length. */ + size_t cols; /* Number of columns in terminal. */ + size_t maxrows; /* Maximum num of rows used so far (multiline mode) */ + int history_index; /* The history index we are currently editing. */ +}; + +enum KEY_ACTION{ + KEY_NULL = 0, /* NULL */ + CTRL_A = 1, /* Ctrl+a */ + CTRL_B = 2, /* Ctrl-b */ + CTRL_C = 3, /* Ctrl-c */ + CTRL_D = 4, /* Ctrl-d */ + CTRL_E = 5, /* Ctrl-e */ + CTRL_F = 6, /* Ctrl-f */ + CTRL_H = 8, /* Ctrl-h */ + TAB = 9, /* Tab */ + CTRL_K = 11, /* Ctrl+k */ + CTRL_L = 12, /* Ctrl+l */ + ENTER = 10, /* Enter */ + CTRL_N = 14, /* Ctrl-n */ + CTRL_P = 16, /* Ctrl-p */ + CTRL_T = 20, /* Ctrl-t */ + CTRL_U = 21, /* Ctrl+u */ + CTRL_W = 23, /* Ctrl+w */ + ESC = 27, /* Escape */ + BACKSPACE = 127 /* Backspace */ +}; + +int linenoiseHistoryAdd(const char *line); +static void refreshLine(struct linenoiseState *l); + +/* Debugging macro. */ +#if 0 +FILE *lndebug_fp = NULL; +#define lndebug(...) \ + do { \ + if (lndebug_fp == NULL) { \ + lndebug_fp = fopen("/tmp/lndebug.txt","a"); \ + fprintf(lndebug_fp, \ + "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \ + (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \ + (int)l->maxrows,old_rows); \ + } \ + fprintf(lndebug_fp, ", " __VA_ARGS__); \ + fflush(lndebug_fp); \ + } while (0) +#else +#define lndebug(fmt, ...) +#endif + +/* ======================= Low level terminal handling ====================== */ + +/* Set if to use or not the multi line mode. */ +void linenoiseSetMultiLine(int ml) { + mlmode = ml; +} + +/* Set if terminal does not recognize escape sequences */ +void linenoiseSetDumbMode(int set) { + dumbmode = set; +} + +/* Use the ESC [6n escape sequence to query the horizontal cursor position + * and return it. On error -1 is returned, on success the position of the + * cursor. */ +static int getCursorPosition() { + char buf[32]; + int cols, rows; + unsigned int i = 0; + + /* Report cursor location */ + fprintf(stdout, "\x1b[6n"); + + /* Read the response: ESC [ rows ; cols R */ + while (i < sizeof(buf)-1) { + if (fread(buf+i, 1, 1, stdin) != 1) break; + if (buf[i] == 'R') break; + i++; + } + buf[i] = '\0'; + /* Parse it. */ + if (buf[0] != ESC || buf[1] != '[') return -1; + if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1; + return cols; +} + +/* Try to get the number of columns in the current terminal, or assume 80 + * if it fails. */ +static int getColumns() { + int start, cols; + + /* Get the initial position so we can restore it later. */ + start = getCursorPosition(); + if (start == -1) goto failed; + + /* Go to right margin and get position. */ + if (fwrite("\x1b[999C", 1, 6, stdout) != 6) goto failed; + cols = getCursorPosition(); + if (cols == -1) goto failed; + + /* Restore position. */ + if (cols > start) { + char seq[32]; + snprintf(seq,32,"\x1b[%dD",cols-start); + if (fwrite(seq, 1, strlen(seq), stdout) == -1) { + /* Can't recover... */ + } + } + return cols; + +failed: + return 80; +} + +/* Clear the screen. Used to handle ctrl+l */ +void linenoiseClearScreen(void) { + fprintf(stdout,"\x1b[H\x1b[2J"); +} + +/* Beep, used for completion when there is nothing to complete or when all + * the choices were already shown. */ +static void linenoiseBeep(void) { + fprintf(stdout, "\x7"); +} + +/* ============================== Completion ================================ */ + +/* Free a list of completion option populated by linenoiseAddCompletion(). */ +static void freeCompletions(linenoiseCompletions *lc) { + size_t i; + for (i = 0; i < lc->len; i++) + free(lc->cvec[i]); + if (lc->cvec != NULL) + free(lc->cvec); +} + +/* This is an helper function for linenoiseEdit() and is called when the + * user types the key in order to complete the string currently in the + * input. + * + * The state of the editing is encapsulated into the pointed linenoiseState + * structure as described in the structure definition. */ +static int completeLine(struct linenoiseState *ls) { + linenoiseCompletions lc = { 0, NULL }; + int nread, nwritten; + char c = 0; + + completionCallback(ls->buf,&lc); + if (lc.len == 0) { + linenoiseBeep(); + } else { + size_t stop = 0, i = 0; + + while(!stop) { + /* Show completion or original buffer */ + if (i < lc.len) { + struct linenoiseState saved = *ls; + + ls->len = ls->pos = strlen(lc.cvec[i]); + ls->buf = lc.cvec[i]; + refreshLine(ls); + ls->len = saved.len; + ls->pos = saved.pos; + ls->buf = saved.buf; + } else { + refreshLine(ls); + } + + nread = fread(&c, 1, 1, stdin); + if (nread <= 0) { + freeCompletions(&lc); + return -1; + } + + switch(c) { + case TAB: /* tab */ + i = (i+1) % (lc.len+1); + if (i == lc.len) linenoiseBeep(); + break; + case ESC: /* escape */ + /* Re-show original buffer */ + if (i < lc.len) refreshLine(ls); + stop = 1; + break; + default: + /* Update buffer and return */ + if (i < lc.len) { + nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]); + ls->len = ls->pos = nwritten; + } + stop = 1; + break; + } + } + } + + freeCompletions(&lc); + return c; /* Return last read character */ +} + +/* Register a callback function to be called for tab-completion. */ +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { + completionCallback = fn; +} + +/* Register a hits function to be called to show hits to the user at the + * right of the prompt. */ +void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) { + hintsCallback = fn; +} + +/* Register a function to free the hints returned by the hints callback + * registered with linenoiseSetHintsCallback(). */ +void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) { + freeHintsCallback = fn; +} + +/* This function is used by the callback function registered by the user + * in order to add completion options given the input string when the + * user typed . See the example.c source code for a very easy to + * understand example. */ +void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { + size_t len = strlen(str); + char *copy, **cvec; + + copy = malloc(len+1); + if (copy == NULL) return; + memcpy(copy,str,len+1); + cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1)); + if (cvec == NULL) { + free(copy); + return; + } + lc->cvec = cvec; + lc->cvec[lc->len++] = copy; +} + +/* =========================== Line editing ================================= */ + +/* We define a very simple "append buffer" structure, that is an heap + * allocated string where we can append to. This is useful in order to + * write all the escape sequences in a buffer and flush them to the standard + * output in a single call, to avoid flickering effects. */ +struct abuf { + char *b; + int len; +}; + +static void abInit(struct abuf *ab) { + ab->b = NULL; + ab->len = 0; +} + +static void abAppend(struct abuf *ab, const char *s, int len) { + char *new = realloc(ab->b,ab->len+len); + + if (new == NULL) return; + memcpy(new+ab->len,s,len); + ab->b = new; + ab->len += len; +} + +static void abFree(struct abuf *ab) { + free(ab->b); +} + +/* Helper of refreshSingleLine() and refreshMultiLine() to show hints + * to the right of the prompt. */ +void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) { + char seq[64]; + if (hintsCallback && plen+l->len < l->cols) { + int color = -1, bold = 0; + char *hint = hintsCallback(l->buf,&color,&bold); + if (hint) { + int hintlen = strlen(hint); + int hintmaxlen = l->cols-(plen+l->len); + if (hintlen > hintmaxlen) hintlen = hintmaxlen; + if (bold == 1 && color == -1) color = 37; + if (color != -1 || bold != 0) + snprintf(seq,64,"\033[%d;%d;49m",bold,color); + abAppend(ab,seq,strlen(seq)); + abAppend(ab,hint,hintlen); + if (color != -1 || bold != 0) + abAppend(ab,"\033[0m",4); + /* Call the function to free the hint returned. */ + if (freeHintsCallback) freeHintsCallback(hint); + } + } +} + +/* Single line low level line refresh. + * + * Rewrite the currently edited line accordingly to the buffer content, + * cursor position, and number of columns of the terminal. */ +static void refreshSingleLine(struct linenoiseState *l) { + char seq[64]; + size_t plen = l->plen; + char *buf = l->buf; + size_t len = l->len; + size_t pos = l->pos; + struct abuf ab; + + while((plen+pos) >= l->cols) { + buf++; + len--; + pos--; + } + while (plen+len > l->cols) { + len--; + } + + abInit(&ab); + /* Cursor to left edge */ + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + /* Write the prompt and the current buffer content */ + abAppend(&ab,l->prompt,strlen(l->prompt)); + abAppend(&ab,buf,len); + /* Show hits if any. */ + refreshShowHints(&ab,l,plen); + /* Erase to right */ + snprintf(seq,64,"\x1b[0K"); + abAppend(&ab,seq,strlen(seq)); + /* Move cursor to original position. */ + snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen)); + abAppend(&ab,seq,strlen(seq)); + if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */ + abFree(&ab); +} + +/* Multi line low level line refresh. + * + * Rewrite the currently edited line accordingly to the buffer content, + * cursor position, and number of columns of the terminal. */ +static void refreshMultiLine(struct linenoiseState *l) { + char seq[64]; + int plen = l->plen; + int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */ + int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */ + int rpos2; /* rpos after refresh. */ + int col; /* colum position, zero-based. */ + int old_rows = l->maxrows; + int j; + struct abuf ab; + + /* Update maxrows if needed. */ + if (rows > (int)l->maxrows) l->maxrows = rows; + + /* First step: clear all the lines used before. To do so start by + * going to the last row. */ + abInit(&ab); + if (old_rows-rpos > 0) { + lndebug("go down %d", old_rows-rpos); + snprintf(seq,64,"\x1b[%dB", old_rows-rpos); + abAppend(&ab,seq,strlen(seq)); + } + + /* Now for every row clear it, go up. */ + for (j = 0; j < old_rows-1; j++) { + lndebug("clear+up"); + snprintf(seq,64,"\r\x1b[0K\x1b[1A"); + abAppend(&ab,seq,strlen(seq)); + } + + /* Clean the top line. */ + lndebug("clear"); + snprintf(seq,64,"\r\x1b[0K"); + abAppend(&ab,seq,strlen(seq)); + + /* Write the prompt and the current buffer content */ + abAppend(&ab,l->prompt,strlen(l->prompt)); + abAppend(&ab,l->buf,l->len); + + /* Show hits if any. */ + refreshShowHints(&ab,l,plen); + + /* If we are at the very end of the screen with our prompt, we need to + * emit a newline and move the prompt to the first column. */ + if (l->pos && + l->pos == l->len && + (l->pos+plen) % l->cols == 0) + { + lndebug(""); + abAppend(&ab,"\n",1); + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + rows++; + if (rows > (int)l->maxrows) l->maxrows = rows; + } + + /* Move cursor to right position. */ + rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */ + lndebug("rpos2 %d", rpos2); + + /* Go up till we reach the expected positon. */ + if (rows-rpos2 > 0) { + lndebug("go-up %d", rows-rpos2); + snprintf(seq,64,"\x1b[%dA", rows-rpos2); + abAppend(&ab,seq,strlen(seq)); + } + + /* Set column. */ + col = (plen+(int)l->pos) % (int)l->cols; + lndebug("set col %d", 1+col); + if (col) + snprintf(seq,64,"\r\x1b[%dC", col); + else + snprintf(seq,64,"\r"); + abAppend(&ab,seq,strlen(seq)); + + lndebug("\n"); + l->oldpos = l->pos; + + if (fwrite(ab.b,ab.len,1,stdout) == -1) {} /* Can't recover from write error. */ + abFree(&ab); +} + +/* Calls the two low level functions refreshSingleLine() or + * refreshMultiLine() according to the selected mode. */ +static void refreshLine(struct linenoiseState *l) { + if (mlmode) + refreshMultiLine(l); + else + refreshSingleLine(l); +} + +/* Insert the character 'c' at cursor current position. + * + * On error writing to the terminal -1 is returned, otherwise 0. */ +int linenoiseEditInsert(struct linenoiseState *l, char c) { + if (l->len < l->buflen) { + if (l->len == l->pos) { + l->buf[l->pos] = c; + l->pos++; + l->len++; + l->buf[l->len] = '\0'; + if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) { + /* Avoid a full update of the line in the + * trivial case. */ + if (fwrite(&c,1,1,stdout) == -1) return -1; + } else { + refreshLine(l); + } + } else { + memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos); + l->buf[l->pos] = c; + l->len++; + l->pos++; + l->buf[l->len] = '\0'; + refreshLine(l); + } + } + return 0; +} + +/* Move cursor on the left. */ +void linenoiseEditMoveLeft(struct linenoiseState *l) { + if (l->pos > 0) { + l->pos--; + refreshLine(l); + } +} + +/* Move cursor on the right. */ +void linenoiseEditMoveRight(struct linenoiseState *l) { + if (l->pos != l->len) { + l->pos++; + refreshLine(l); + } +} + +/* Move cursor to the start of the line. */ +void linenoiseEditMoveHome(struct linenoiseState *l) { + if (l->pos != 0) { + l->pos = 0; + refreshLine(l); + } +} + +/* Move cursor to the end of the line. */ +void linenoiseEditMoveEnd(struct linenoiseState *l) { + if (l->pos != l->len) { + l->pos = l->len; + refreshLine(l); + } +} + +/* Substitute the currently edited line with the next or previous history + * entry as specified by 'dir'. */ +#define LINENOISE_HISTORY_NEXT 0 +#define LINENOISE_HISTORY_PREV 1 +void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) { + if (history_len > 1) { + /* Update the current history entry before to + * overwrite it with the next one. */ + free(history[history_len - 1 - l->history_index]); + history[history_len - 1 - l->history_index] = strdup(l->buf); + /* Show the new entry */ + l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1; + if (l->history_index < 0) { + l->history_index = 0; + return; + } else if (l->history_index >= history_len) { + l->history_index = history_len-1; + return; + } + strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen); + l->buf[l->buflen-1] = '\0'; + l->len = l->pos = strlen(l->buf); + refreshLine(l); + } +} + +/* Delete the character at the right of the cursor without altering the cursor + * position. Basically this is what happens with the "Delete" keyboard key. */ +void linenoiseEditDelete(struct linenoiseState *l) { + if (l->len > 0 && l->pos < l->len) { + memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1); + l->len--; + l->buf[l->len] = '\0'; + refreshLine(l); + } +} + +/* Backspace implementation. */ +void linenoiseEditBackspace(struct linenoiseState *l) { + if (l->pos > 0 && l->len > 0) { + memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos); + l->pos--; + l->len--; + l->buf[l->len] = '\0'; + refreshLine(l); + } +} + +/* Delete the previosu word, maintaining the cursor at the start of the + * current word. */ +void linenoiseEditDeletePrevWord(struct linenoiseState *l) { + size_t old_pos = l->pos; + size_t diff; + + while (l->pos > 0 && l->buf[l->pos-1] == ' ') + l->pos--; + while (l->pos > 0 && l->buf[l->pos-1] != ' ') + l->pos--; + diff = old_pos - l->pos; + memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1); + l->len -= diff; + refreshLine(l); +} + +/* This function is the core of the line editing capability of linenoise. + * It expects 'fd' to be already in "raw mode" so that every key pressed + * will be returned ASAP to read(). + * + * The resulting string is put into 'buf' when the user type enter, or + * when ctrl+d is typed. + * + * The function returns the length of the current buffer. */ +static int linenoiseEdit(char *buf, size_t buflen, const char *prompt) +{ + struct linenoiseState l; + + /* Populate the linenoise state that we pass to functions implementing + * specific editing functionalities. */ + l.buf = buf; + l.buflen = buflen; + l.prompt = prompt; + l.plen = strlen(prompt); + l.oldpos = l.pos = 0; + l.len = 0; + l.cols = getColumns(); + l.maxrows = 0; + l.history_index = 0; + + /* Buffer starts empty. */ + l.buf[0] = '\0'; + l.buflen--; /* Make sure there is always space for the nulterm */ + + /* The latest history entry is always our current buffer, that + * initially is just an empty string. */ + linenoiseHistoryAdd(""); + + int pos1 = getCursorPosition(); + if (fwrite(prompt,l.plen,1,stdout) == -1) return -1; + int pos2 = getCursorPosition(); + if (pos1 >= 0 && pos2 >= 0) { + l.plen = pos2 - pos1; + } + while(1) { + char c; + int nread; + char seq[3]; + + nread = fread(&c, 1, 1, stdin); + if (nread <= 0) return l.len; + + /* Only autocomplete when the callback is set. It returns < 0 when + * there was an error reading from fd. Otherwise it will return the + * character that should be handled next. */ + if (c == 9 && completionCallback != NULL) { + int c2 = completeLine(&l); + /* Return on errors */ + if (c2 < 0) return l.len; + /* Read next character when 0 */ + if (c2 == 0) continue; + c = c2; + } + + switch(c) { + case ENTER: /* enter */ + history_len--; + free(history[history_len]); + if (mlmode) linenoiseEditMoveEnd(&l); + if (hintsCallback) { + /* Force a refresh without hints to leave the previous + * line as the user typed it after a newline. */ + linenoiseHintsCallback *hc = hintsCallback; + hintsCallback = NULL; + refreshLine(&l); + hintsCallback = hc; + } + return (int)l.len; + case CTRL_C: /* ctrl-c */ + errno = EAGAIN; + return -1; + case BACKSPACE: /* backspace */ + case 8: /* ctrl-h */ + linenoiseEditBackspace(&l); + break; + case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the + line is empty, act as end-of-file. */ + if (l.len > 0) { + linenoiseEditDelete(&l); + } else { + history_len--; + free(history[history_len]); + return -1; + } + break; + case CTRL_T: /* ctrl-t, swaps current character with previous. */ + if (l.pos > 0 && l.pos < l.len) { + int aux = buf[l.pos-1]; + buf[l.pos-1] = buf[l.pos]; + buf[l.pos] = aux; + if (l.pos != l.len-1) l.pos++; + refreshLine(&l); + } + break; + case CTRL_B: /* ctrl-b */ + linenoiseEditMoveLeft(&l); + break; + case CTRL_F: /* ctrl-f */ + linenoiseEditMoveRight(&l); + break; + case CTRL_P: /* ctrl-p */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); + break; + case CTRL_N: /* ctrl-n */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); + break; + case ESC: /* escape sequence */ + /* Read the next two bytes representing the escape sequence. */ + if (fread(seq, 1, 2, stdin) < 2) break; + + /* ESC [ sequences. */ + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + /* Extended escape, read additional byte. */ + if (fread(seq+2, 1, 1, stdin) == -1) break; + if (seq[2] == '~') { + switch(seq[1]) { + case '3': /* Delete key. */ + linenoiseEditDelete(&l); + break; + } + } + } else { + switch(seq[1]) { + case 'A': /* Up */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); + break; + case 'B': /* Down */ + linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); + break; + case 'C': /* Right */ + linenoiseEditMoveRight(&l); + break; + case 'D': /* Left */ + linenoiseEditMoveLeft(&l); + break; + case 'H': /* Home */ + linenoiseEditMoveHome(&l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(&l); + break; + } + } + } + + /* ESC O sequences. */ + else if (seq[0] == 'O') { + switch(seq[1]) { + case 'H': /* Home */ + linenoiseEditMoveHome(&l); + break; + case 'F': /* End*/ + linenoiseEditMoveEnd(&l); + break; + } + } + break; + default: + if (linenoiseEditInsert(&l,c)) return -1; + break; + case CTRL_U: /* Ctrl+u, delete the whole line. */ + buf[0] = '\0'; + l.pos = l.len = 0; + refreshLine(&l); + break; + case CTRL_K: /* Ctrl+k, delete from current to end of line. */ + buf[l.pos] = '\0'; + l.len = l.pos; + refreshLine(&l); + break; + case CTRL_A: /* Ctrl+a, go to the start of the line */ + linenoiseEditMoveHome(&l); + break; + case CTRL_E: /* ctrl+e, go to the end of the line */ + linenoiseEditMoveEnd(&l); + break; + case CTRL_L: /* ctrl+l, clear screen */ + linenoiseClearScreen(); + refreshLine(&l); + break; + case CTRL_W: /* ctrl+w, delete previous word */ + linenoiseEditDeletePrevWord(&l); + break; + } + if (__fbufsize(stdout) > 0) { + fflush(stdout); + } + } + return l.len; +} + +int linenoiseProbe() { + /* Switch to non-blocking mode */ + int flags = fcntl(STDIN_FILENO, F_GETFL); + flags |= O_NONBLOCK; + int res = fcntl(STDIN_FILENO, F_SETFL, flags); + if (res != 0) { + return -1; + } + /* Device status request */ + fprintf(stdout, "\x1b[5n"); + + /* Try to read response */ + int timeout_ms = 200; + size_t read_bytes = 0; + while (timeout_ms > 0 && read_bytes < 4) { // response is ESC[0n or ESC[3n + usleep(10000); + char c; + int cb = fread(&c, 1, 1, stdin); + read_bytes += cb; + timeout_ms--; + } + /* Restore old mode */ + flags &= ~O_NONBLOCK; + res = fcntl(STDIN_FILENO, F_SETFL, flags); + if (res != 0) { + return -1; + } + if (read_bytes < 4) { + return -2; + } + return 0; +} + +static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { + int count; + + if (buflen == 0) { + errno = EINVAL; + return -1; + } + + count = linenoiseEdit(buf, buflen, prompt); + fputc('\n', stdout); + return count; +} + +static int linenoiseDumb(char* buf, size_t buflen, const char* prompt) { + /* dumb terminal, fall back to fgets */ + fputs(prompt, stdout); + int count = 0; + while (count < buflen) { + int c = fgetc(stdin); + if (c == '\n') { + break; + } else if (c >= 0x1c && c <= 0x1f){ + continue; /* consume arrow keys */ + } else if (c == BACKSPACE || c == 0x8) { + if (count > 0) { + buf[count - 1] = 0; + count --; + } + fputs("\x08 ", stdout); /* Windows CMD: erase symbol under cursor */ + } else { + buf[count] = c; + ++count; + } + fputc(c, stdout); /* echo */ + } + fputc('\n', stdout); + return count; +} + +static void sanitize(char* src) { + char* dst = src; + for (int c = *src; c != 0; src++, c = *src) { + if (isprint(c)) { + *dst = c; + ++dst; + } + } + *dst = 0; +} + +/* The high level function that is the main API of the linenoise library. */ +char *linenoise(const char *prompt) { + char *buf = calloc(1, LINENOISE_MAX_LINE); + int count = 0; + if (!dumbmode) { + count = linenoiseRaw(buf, LINENOISE_MAX_LINE, prompt); + } else { + count = linenoiseDumb(buf, LINENOISE_MAX_LINE, prompt); + } + if (count > 0) { + sanitize(buf); + count = strlen(buf); + } + if (count <= 0) { + free(buf); + return NULL; + } + return buf; +} + +/* This is just a wrapper the user may want to call in order to make sure + * the linenoise returned buffer is freed with the same allocator it was + * created with. Useful when the main program is using an alternative + * allocator. */ +void linenoiseFree(void *ptr) { + free(ptr); +} + +/* ================================ History ================================= */ + +void linenoiseHistoryFree() { + if (history) { + for (int j = 0; j < history_len; j++) { + free(history[j]); + } + free(history); + } + history = NULL; +} + +/* This is the API call to add a new entry in the linenoise history. + * It uses a fixed array of char pointers that are shifted (memmoved) + * when the history max length is reached in order to remove the older + * entry and make room for the new one, so it is not exactly suitable for huge + * histories, but will work well for a few hundred of entries. + * + * Using a circular buffer is smarter, but a bit more complex to handle. */ +int linenoiseHistoryAdd(const char *line) { + char *linecopy; + + if (history_max_len == 0) return 0; + + /* Initialization on first call. */ + if (history == NULL) { + history = malloc(sizeof(char*)*history_max_len); + if (history == NULL) return 0; + memset(history,0,(sizeof(char*)*history_max_len)); + } + + /* Don't add duplicated lines. */ + if (history_len && !strcmp(history[history_len-1], line)) return 0; + + /* Add an heap allocated copy of the line in the history. + * If we reached the max length, remove the older line. */ + linecopy = strdup(line); + if (!linecopy) return 0; + if (history_len == history_max_len) { + free(history[0]); + memmove(history,history+1,sizeof(char*)*(history_max_len-1)); + history_len--; + } + history[history_len] = linecopy; + history_len++; + return 1; +} + +/* Set the maximum length for the history. This function can be called even + * if there is already some history, the function will make sure to retain + * just the latest 'len' elements if the new history length value is smaller + * than the amount of items already inside the history. */ +int linenoiseHistorySetMaxLen(int len) { + char **new; + + if (len < 1) return 0; + if (history) { + int tocopy = history_len; + + new = malloc(sizeof(char*)*len); + if (new == NULL) return 0; + + /* If we can't copy everything, free the elements we'll not use. */ + if (len < tocopy) { + int j; + + for (j = 0; j < tocopy-len; j++) free(history[j]); + tocopy = len; + } + memset(new,0,sizeof(char*)*len); + memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy); + free(history); + history = new; + } + history_max_len = len; + if (history_len > history_max_len) + history_len = history_max_len; + return 1; +} + +/* Save the history in the specified file. On success 0 is returned + * otherwise -1 is returned. */ +int linenoiseHistorySave(const char *filename) { + FILE *fp; + int j; + + fp = fopen(filename,"w"); + if (fp == NULL) return -1; + for (j = 0; j < history_len; j++) + fprintf(fp,"%s\n",history[j]); + fclose(fp); + return 0; +} + +/* Load the history from the specified file. If the file does not exist + * zero is returned and no operation is performed. + * + * If the file exists and the operation succeeded 0 is returned, otherwise + * on error -1 is returned. */ +int linenoiseHistoryLoad(const char *filename) { + FILE *fp = fopen(filename,"r"); + char buf[LINENOISE_MAX_LINE]; + + if (fp == NULL) return -1; + + while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { + char *p; + + p = strchr(buf,'\r'); + if (!p) p = strchr(buf,'\n'); + if (p) *p = '\0'; + linenoiseHistoryAdd(buf); + } + fclose(fp); + return 0; +} diff --git a/components/console/linenoise/linenoise.h b/components/console/linenoise/linenoise.h new file mode 100644 index 000000000..a82701f83 --- /dev/null +++ b/components/console/linenoise/linenoise.h @@ -0,0 +1,76 @@ +/* linenoise.h -- VERSION 1.0 + * + * Guerrilla line editing library against the idea that a line editing lib + * needs to be 20,000 lines of C code. + * + * See linenoise.c for more information. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010-2014, Salvatore Sanfilippo + * Copyright (c) 2010-2013, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINENOISE_H +#define __LINENOISE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct linenoiseCompletions { + size_t len; + char **cvec; +} linenoiseCompletions; + +typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); +typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); +typedef void(linenoiseFreeHintsCallback)(void *); +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); +void linenoiseSetHintsCallback(linenoiseHintsCallback *); +void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); +void linenoiseAddCompletion(linenoiseCompletions *, const char *); + +int linenoiseProbe(void); +char *linenoise(const char *prompt); +void linenoiseFree(void *ptr); +int linenoiseHistoryAdd(const char *line); +int linenoiseHistorySetMaxLen(int len); +int linenoiseHistorySave(const char *filename); +int linenoiseHistoryLoad(const char *filename); +void linenoiseHistoryFree(); +void linenoiseClearScreen(void); +void linenoiseSetMultiLine(int ml); +void linenoiseSetDumbMode(int set); +void linenoisePrintKeyCodes(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LINENOISE_H */ diff --git a/components/console/split_argv.c b/components/console/split_argv.c new file mode 100644 index 000000000..79ae918fc --- /dev/null +++ b/components/console/split_argv.c @@ -0,0 +1,120 @@ +// Copyright 2016-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#define SS_FLAG_ESCAPE 0x8 + +typedef enum { + /* parsing the space between arguments */ + SS_SPACE = 0x0, + /* parsing an argument which isn't quoted */ + SS_ARG = 0x1, + /* parsing a quoted argument */ + SS_QUOTED_ARG = 0x2, + /* parsing an escape sequence within unquoted argument */ + SS_ARG_ESCAPED = SS_ARG | SS_FLAG_ESCAPE, + /* parsing an escape sequence within a quoted argument */ + SS_QUOTED_ARG_ESCAPED = SS_QUOTED_ARG | SS_FLAG_ESCAPE, +} split_state_t; + +size_t esp_console_split_argv(char *line, char **argv, size_t argv_size) +{ + const int QUOTE = '"'; + const int ESCAPE = '\\'; + const int SPACE = ' '; + split_state_t state = SS_SPACE; + int argc = 0; + char *next_arg_start = line; + char *out_ptr = line; + for (char *in_ptr = line; argc < argv_size - 1; ++in_ptr) { + int char_in = (unsigned char) *in_ptr; + if (char_in == 0) { + break; + } + int char_out = -1; + + /* helper function, called when done with an argument */ + void end_arg() { + char_out = 0; + argv[argc++] = next_arg_start; + state = SS_SPACE; + } + + switch (state) { + case SS_SPACE: + if (char_in == SPACE) { + /* skip space */ + } else if (char_in == QUOTE) { + next_arg_start = out_ptr; + state = SS_QUOTED_ARG; + } else if (char_in == ESCAPE) { + next_arg_start = out_ptr; + state = SS_ARG_ESCAPED; + } else { + next_arg_start = out_ptr; + state = SS_ARG; + char_out = char_in; + } + break; + + case SS_QUOTED_ARG: + if (char_in == QUOTE) { + end_arg(); + } else if (char_in == ESCAPE) { + state = SS_QUOTED_ARG_ESCAPED; + } else { + char_out = char_in; + } + break; + + case SS_ARG_ESCAPED: + case SS_QUOTED_ARG_ESCAPED: + if (char_in == ESCAPE || char_in == QUOTE || char_in == SPACE) { + char_out = char_in; + } else { + /* unrecognized escape character, skip */ + } + state = (split_state_t) (state & (~SS_FLAG_ESCAPE)); + break; + + case SS_ARG: + if (char_in == SPACE) { + end_arg(); + } else if (char_in == ESCAPE) { + state = SS_ARG_ESCAPED; + } else { + char_out = char_in; + } + break; + } + /* need to output anything? */ + if (char_out >= 0) { + *out_ptr = char_out; + ++out_ptr; + } + } + /* make sure the final argument is terminated */ + *out_ptr = 0; + /* finalize the last argument */ + if (state != SS_SPACE && argc < argv_size - 1) { + argv[argc++] = next_arg_start; + } + /* add a NULL at the end of argv */ + argv[argc] = NULL; + + return argc; +} diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt new file mode 100644 index 000000000..199c554ad --- /dev/null +++ b/components/esp-tls/CMakeLists.txt @@ -0,0 +1,21 @@ +set(srcs esp_tls.c) +if(CONFIG_ESP_TLS_USING_MBEDTLS) + list(APPEND srcs + "esp_tls_mbedtls.c") +endif() + +if(CONFIG_ESP_TLS_USING_WOLFSSL) + list(APPEND srcs + "esp_tls_wolfssl.c") +endif() + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "." + PRIV_INCLUDE_DIRS "private_include" + REQUIRES mbedtls + PRIV_REQUIRES lwip http_parser) + +if(CONFIG_ESP_TLS_USING_WOLFSSL) + idf_component_get_property(wolfssl esp-wolfssl COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${wolfssl}) +endif() diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig new file mode 100644 index 000000000..e61145974 --- /dev/null +++ b/components/esp-tls/Kconfig @@ -0,0 +1,69 @@ +menu "ESP-TLS" + choice ESP_TLS_LIBRARY_CHOOSE + prompt "Choose SSL/TLS library for ESP-TLS (See help for more Info)" + default ESP_TLS_USING_MBEDTLS + help + The ESP-TLS APIs support multiple backend TLS libraries. Currently mbedTLS and WolfSSL are + supported. Different TLS libraries may support different features and have different resource + usage. Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details. + config ESP_TLS_USING_MBEDTLS + bool "mbedTLS" + config ESP_TLS_USING_WOLFSSL + bool "wolfSSL (License info in wolfSSL directory README)" + endchoice + + config ESP_TLS_SERVER + bool "Enable ESP-TLS Server" + default n + help + Enable support for creating server side SSL/TLS session, available for mbedTLS + as well as wolfSSL TLS library. + + config ESP_TLS_PSK_VERIFICATION + bool "Enable PSK verification" + select MBEDTLS_PSK_MODES if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_DHE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_RSA_PSK if ESP_TLS_USING_MBEDTLS + default n + help + Enable support for pre shared key ciphers, supported for both mbedTLS as well as + wolfSSL TLS library. + + config ESP_TLS_INSECURE + bool "Allow potentially insecure options" + help + You can enable some potentially insecure options. These options should only be used for testing pusposes. + Only enable these options if you are very sure. + + config ESP_TLS_SKIP_SERVER_CERT_VERIFY + bool "Skip server certificate verification by default (WARNING: ONLY FOR TESTING PURPOSE, READ HELP)" + depends on ESP_TLS_INSECURE + help + After enabling this option the esp-tls client will skip the server certificate verification + by default. Note that this option will only modify the default behaviour of esp-tls client + regarding server cert verification. The default behaviour should only be applicable when + no other option regarding the server cert verification is opted in the esp-tls config + (e.g. crt_bundle_attach, use_global_ca_store etc.). + WARNING : Enabling this option comes with a potential risk of establishing a TLS connection + with a server which has a fake identity, provided that the server certificate + is not provided either through API or other mechanism like ca_store etc. + + config ESP_WOLFSSL_SMALL_CERT_VERIFY + bool "Enable SMALL_CERT_VERIFY" + depends on ESP_TLS_USING_WOLFSSL + default y + help + Enables server verification with Intermediate CA cert, does not authenticate full chain + of trust upto the root CA cert (After Enabling this option client only needs to have Intermediate + CA certificate of the server to authenticate server, root CA cert is not necessary). + + config ESP_DEBUG_WOLFSSL + bool "Enable debug logs for wolfSSL" + depends on ESP_TLS_USING_WOLFSSL + default n + help + Enable detailed debug prints for wolfSSL SSL library. + +endmenu diff --git a/components/esp-tls/component.mk b/components/esp-tls/component.mk new file mode 100644 index 000000000..70f6f2fa7 --- /dev/null +++ b/components/esp-tls/component.mk @@ -0,0 +1,16 @@ + +COMPONENT_SRCDIRS := . +COMPONENT_OBJS := esp_tls.o + +COMPONENT_ADD_INCLUDEDIRS := . private_include + + +ifneq ($(CONFIG_ESP_TLS_USING_MBEDTLS), ) +COMPONENT_OBJS += esp_tls_mbedtls.o +endif + +ifneq ($(CONFIG_ESP_TLS_USING_WOLFSSL), ) +COMPONENT_OBJS += esp_tls_wolfssl.o +endif + +CFLAGS += -DWOLFSSL_USER_SETTINGS diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c new file mode 100644 index 000000000..a5daf24f9 --- /dev/null +++ b/components/esp-tls/esp_tls.c @@ -0,0 +1,507 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "esp_tls.h" +#include "esp_tls_error_capture_internal.h" +#include +static const char *TAG = "esp-tls"; + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#include "esp_tls_mbedtls.h" +#elif CONFIG_ESP_TLS_USING_WOLFSSL +#include "esp_tls_wolfssl.h" +#endif + +#ifdef ESP_PLATFORM +#include +#else +#define ESP_LOGD(TAG, ...) //printf(__VA_ARGS__); +#define ESP_LOGE(TAG, ...) printf(__VA_ARGS__); +#endif + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#define _esp_create_ssl_handle esp_create_mbedtls_handle +#define _esp_tls_handshake esp_mbedtls_handshake +#define _esp_tls_read esp_mbedtls_read +#define _esp_tls_write esp_mbedtls_write +#define _esp_tls_conn_delete esp_mbedtls_conn_delete +#ifdef CONFIG_ESP_TLS_SERVER +#define _esp_tls_server_session_create esp_mbedtls_server_session_create +#define _esp_tls_server_session_delete esp_mbedtls_server_session_delete +#endif /* CONFIG_ESP_TLS_SERVER */ +#define _esp_tls_get_bytes_avail esp_mbedtls_get_bytes_avail +#define _esp_tls_init_global_ca_store esp_mbedtls_init_global_ca_store +#define _esp_tls_set_global_ca_store esp_mbedtls_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */ +#define _esp_tls_get_global_ca_store esp_mbedtls_get_global_ca_store +#define _esp_tls_free_global_ca_store esp_mbedtls_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */ +#define _esp_tls_get_ciphersuites_list esp_mbedtls_get_ciphersuites_list +#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#define _esp_create_ssl_handle esp_create_wolfssl_handle +#define _esp_tls_handshake esp_wolfssl_handshake +#define _esp_tls_read esp_wolfssl_read +#define _esp_tls_write esp_wolfssl_write +#define _esp_tls_conn_delete esp_wolfssl_conn_delete +#ifdef CONFIG_ESP_TLS_SERVER +#define _esp_tls_server_session_create esp_wolfssl_server_session_create +#define _esp_tls_server_session_delete esp_wolfssl_server_session_delete +#endif /* CONFIG_ESP_TLS_SERVER */ +#define _esp_tls_get_bytes_avail esp_wolfssl_get_bytes_avail +#define _esp_tls_init_global_ca_store esp_wolfssl_init_global_ca_store +#define _esp_tls_set_global_ca_store esp_wolfssl_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */ +#define _esp_tls_free_global_ca_store esp_wolfssl_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */ +#else /* ESP_TLS_USING_WOLFSSL */ +#error "No TLS stack configured" +#endif + +static esp_err_t create_ssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ + return _esp_create_ssl_handle(hostname, hostlen, cfg, tls); +} + +static esp_err_t esp_tls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + return _esp_tls_handshake(tls, cfg); +} + +static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen) +{ + return recv(tls->sockfd, data, datalen, 0); +} + +static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + return send(tls->sockfd, data, datalen, 0); +} + +/** + * @brief Close the TLS connection and free any allocated resources. + */ +void esp_tls_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + _esp_tls_conn_delete(tls); + if (tls->sockfd >= 0) { + close(tls->sockfd); + } + free(tls->error_handle); + free(tls); + } +} + +esp_tls_t *esp_tls_init(void) +{ + esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t)); + if (!tls) { + return NULL; + } + tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); + if (!tls->error_handle) { + free(tls); + return NULL; + } +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + tls->server_fd.fd = -1; +#endif + tls->sockfd = -1; + return tls; +} + +static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addrinfo **address_info) +{ + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + char *use_host = strndup(host, hostlen); + if (!use_host) { + return ESP_ERR_NO_MEM; + } + + ESP_LOGD(TAG, "host:%s: strlen %lu", use_host, (unsigned long)hostlen); + if (getaddrinfo(use_host, NULL, &hints, address_info)) { + ESP_LOGE(TAG, "couldn't get hostname for :%s:", use_host); + free(use_host); + return ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME; + } + free(use_host); + return ESP_OK; +} + +static void ms_to_timeval(int timeout_ms, struct timeval *tv) +{ + tv->tv_sec = timeout_ms / 1000; + tv->tv_usec = (timeout_ms % 1000) * 1000; +} + +static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, const esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + esp_err_t ret; + struct addrinfo *addrinfo; + if ((ret = resolve_host_name(host, hostlen, &addrinfo)) != ESP_OK) { + return ret; + } + + int fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); + if (fd < 0) { + ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ret = ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET; + goto err_freeaddr; + } + + void *addr_ptr; + if (addrinfo->ai_family == AF_INET) { + struct sockaddr_in *p = (struct sockaddr_in *)addrinfo->ai_addr; + p->sin_port = htons(port); + addr_ptr = p; + } +#if LWIP_IPV6 + else if (addrinfo->ai_family == AF_INET6) { + struct sockaddr_in6 *p = (struct sockaddr_in6 *)addrinfo->ai_addr; + p->sin6_port = htons(port); + p->sin6_family = AF_INET6; + addr_ptr = p; + } +#endif + else { + ESP_LOGE(TAG, "Unsupported protocol family %d", addrinfo->ai_family); + ret = ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY; + goto err_freesocket; + } + + if (cfg) { + if (cfg->timeout_ms >= 0) { + struct timeval tv; + ms_to_timeval(cfg->timeout_ms, &tv); + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + } + if (cfg->non_block) { + int flags = fcntl(fd, F_GETFL, 0); + ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (ret < 0) { + ESP_LOGE(TAG, "Failed to configure the socket as non-blocking (errno %d)", errno); + goto err_freesocket; + } + } + } + + ret = connect(fd, addr_ptr, addrinfo->ai_addrlen); + if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) { + + ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST; + goto err_freesocket; + } + + *sockfd = fd; + freeaddrinfo(addrinfo); + return ESP_OK; + +err_freesocket: + close(fd); +err_freeaddr: + freeaddrinfo(addrinfo); + return ret; +} + +static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + if (!tls) { + ESP_LOGE(TAG, "empty esp_tls parameter"); + return -1; + } + esp_err_t esp_ret; + /* These states are used to keep a tab on connection progress in case of non-blocking connect, + and in case of blocking connect these cases will get executed one after the other */ + switch (tls->conn_state) { + case ESP_TLS_INIT: + tls->sockfd = -1; + if (cfg != NULL) { +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + mbedtls_net_init(&tls->server_fd); +#endif + tls->is_tls = true; + } + if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + return -1; + } + if (!cfg) { + tls->read = tcp_read; + tls->write = tcp_write; + ESP_LOGD(TAG, "non-tls connection established"); + return 1; + } + if (cfg->non_block) { + FD_ZERO(&tls->rset); + FD_SET(tls->sockfd, &tls->rset); + tls->wset = tls->rset; + } + tls->conn_state = ESP_TLS_CONNECTING; + /* falls through */ + case ESP_TLS_CONNECTING: + if (cfg->non_block) { + ESP_LOGD(TAG, "connecting..."); + struct timeval tv; + ms_to_timeval(cfg->timeout_ms, &tv); + + /* In case of non-blocking I/O, we use the select() API to check whether + connection has been established or not*/ + if (select(tls->sockfd + 1, &tls->rset, &tls->wset, NULL, + cfg->timeout_ms>0 ? &tv : NULL) == 0) { + ESP_LOGD(TAG, "select() timed out"); + return 0; + } + if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) { + int error; + unsigned int len = sizeof(error); + /* pending error check */ + if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + ESP_LOGD(TAG, "Non blocking connect failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + } + } + /* By now, the connection has been established */ + esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "create_ssl_handle failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + tls->read = _esp_tls_read; + tls->write = _esp_tls_write; + tls->conn_state = ESP_TLS_HANDSHAKE; + /* falls through */ + case ESP_TLS_HANDSHAKE: + ESP_LOGD(TAG, "handshake in progress..."); + return esp_tls_handshake(tls, cfg); + break; + case ESP_TLS_FAIL: + ESP_LOGE(TAG, "failed to open a new connection");; + break; + default: + ESP_LOGE(TAG, "invalid esp-tls state"); + break; + } + return -1; +} + +/** + * @brief Create a new TLS/SSL connection + */ +esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg) +{ + esp_tls_t *tls = esp_tls_init(); + if (!tls) { + return NULL; + } + /* esp_tls_conn_new() API establishes connection in a blocking manner thus this loop ensures that esp_tls_conn_new() + API returns only after connection is established unless there is an error*/ + size_t start = xTaskGetTickCount(); + while (1) { + int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); + if (ret == 1) { + return tls; + } else if (ret == -1) { + esp_tls_conn_delete(tls); + ESP_LOGE(TAG, "Failed to open new connection"); + return NULL; + } else if (ret == 0 && cfg->timeout_ms >= 0) { + size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms); + uint32_t expired = xTaskGetTickCount() - start; + if (expired >= timeout_ticks) { + esp_tls_conn_delete(tls); + ESP_LOGE(TAG, "Failed to open new connection in specified timeout"); + return NULL; + } + } + } + return NULL; +} + +int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + /* esp_tls_conn_new_sync() is a sync alternative to esp_tls_conn_new_async() with symmetric function prototype + it is an alternative to esp_tls_conn_new() which is left for compatibility reasons */ + size_t start = xTaskGetTickCount(); + while (1) { + int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); + if (ret == 1) { + return ret; + } else if (ret == -1) { + ESP_LOGE(TAG, "Failed to open new connection"); + return -1; + } else if (ret == 0 && cfg->timeout_ms >= 0) { + size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms); + uint32_t expired = xTaskGetTickCount() - start; + if (expired >= timeout_ticks) { + ESP_LOGW(TAG, "Failed to open new connection in specified timeout"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT); + return 0; + } + } + } + return 0; +} + +/* + * @brief Create a new TLS/SSL non-blocking connection + */ +int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + return esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); +} + +static int get_port(const char *url, struct http_parser_url *u) +{ + if (u->field_data[UF_PORT].len) { + return strtol(&url[u->field_data[UF_PORT].off], NULL, 10); + } else { + if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "http", u->field_data[UF_SCHEMA].len) == 0) { + return 80; + } else if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "https", u->field_data[UF_SCHEMA].len) == 0) { + return 443; + } + } + return 0; +} + +/** + * @brief Create a new TLS/SSL connection with a given "HTTP" url + */ +esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg) +{ + /* Parse URI */ + struct http_parser_url u; + http_parser_url_init(&u); + http_parser_parse_url(url, strlen(url), 0, &u); + esp_tls_t *tls = esp_tls_init(); + if (!tls) { + return NULL; + } + /* Connect to host */ + if (esp_tls_conn_new_sync(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, + get_port(url, &u), cfg, tls) == 1) { + return tls; + } + esp_tls_conn_delete(tls); + return NULL; +} + +/** + * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url + */ +int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + /* Parse URI */ + struct http_parser_url u; + http_parser_url_init(&u); + http_parser_parse_url(url, strlen(url), 0, &u); + + /* Connect to host */ + return esp_tls_conn_new_async(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, + get_port(url, &u), cfg, tls); +} + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + +mbedtls_x509_crt *esp_tls_get_global_ca_store(void) +{ + return _esp_tls_get_global_ca_store(); +} + +const int *esp_tls_get_ciphersuites_list(void) +{ + return _esp_tls_get_ciphersuites_list(); +} +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create a server side TLS/SSL connection + */ +int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) +{ + return _esp_tls_server_session_create(cfg, sockfd, tls); +} +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + */ +void esp_tls_server_session_delete(esp_tls_t *tls) +{ + return _esp_tls_server_session_delete(tls); +} +#endif /* CONFIG_ESP_TLS_SERVER */ + +ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls) +{ + return _esp_tls_get_bytes_avail(tls); +} + +esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd) +{ + if (!tls || !sockfd) { + ESP_LOGE(TAG, "Invalid arguments passed"); + return ESP_ERR_INVALID_ARG; + } + *sockfd = tls->sockfd; + return ESP_OK; +} + +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags) +{ + if (!h) { + return ESP_ERR_INVALID_STATE; + } + esp_err_t last_err = h->last_error; + if (esp_tls_code) { + *esp_tls_code = h->esp_tls_error_code; + } + if (esp_tls_flags) { + *esp_tls_flags = h->esp_tls_flags; + } + memset(h, 0, sizeof(esp_tls_last_error_t)); + return last_err; +} + +esp_err_t esp_tls_init_global_ca_store(void) +{ + return _esp_tls_init_global_ca_store(); +} + +esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + return _esp_tls_set_global_ca_store(cacert_pem_buf, cacert_pem_bytes); +} + +void esp_tls_free_global_ca_store(void) +{ + return _esp_tls_free_global_ca_store(); +} diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h new file mode 100644 index 000000000..a9ff17d5d --- /dev/null +++ b/components/esp-tls/esp_tls.h @@ -0,0 +1,619 @@ +// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP_TLS_H_ +#define _ESP_TLS_H_ + +#include +#include +#include +#include "esp_err.h" +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#include "mbedtls/platform.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/esp_debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" +#elif CONFIG_ESP_TLS_USING_WOLFSSL +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/ssl.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */ +#define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */ +#define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */ +#define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */ +#define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */ +#define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set socket option */ +#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */ +#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */ +#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */ +#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */ + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ +#define ESP_TLS_ERR_SSL_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE +#define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT +#endif /*CONFIG_ESP_TLS_USING_WOLFSSL */ +typedef struct esp_tls_last_error* esp_tls_error_handle_t; + +/** +* @brief Error structure containing relevant errors in case tls error occurred +*/ +typedef struct esp_tls_last_error { + esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */ + int esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */ + int esp_tls_flags; /*!< last certification verification flags */ +} esp_tls_last_error_t; + +/** + * @brief ESP-TLS Connection State + */ +typedef enum esp_tls_conn_state { + ESP_TLS_INIT = 0, + ESP_TLS_CONNECTING, + ESP_TLS_HANDSHAKE, + ESP_TLS_FAIL, + ESP_TLS_DONE, +} esp_tls_conn_state_t; + +typedef enum esp_tls_role { + ESP_TLS_CLIENT = 0, + ESP_TLS_SERVER, +} esp_tls_role_t; + +/** + * @brief ESP-TLS preshared key and hint structure + */ +typedef struct psk_key_hint { + const uint8_t* key; /*!< key in PSK authentication mode in binary format */ + const size_t key_size; /*!< length of the key */ + const char* hint; /*!< hint in PSK authentication mode in string format */ +} psk_hint_key_t; + +/** + * @brief ESP-TLS configuration parameters + * + * @note Note about format of certificates: + * - This structure includes certificates of a Certificate Authority, of client or server as well + * as private keys, which may be of PEM or DER format. In case of PEM format, the buffer must be + * NULL terminated (with NULL character included in certificate size). + * - Certificate Authority's certificate may be a chain of certificates in case of PEM format, + * but could be only one certificate in case of DER format + * - Variables names of certificates and private key buffers and sizes are defined as unions providing + * backward compatibility for legacy *_pem_buf and *_pem_bytes names which suggested only PEM format + * was supported. It is encouraged to use generic names such as cacert_buf and cacert_bytes. + */ +typedef struct esp_tls_cfg { + const char **alpn_protos; /*!< Application protocols required for HTTP2. + If HTTP2/ALPN support is required, a list + of protocols that should be negotiated. + The format is length followed by protocol + name. + For the most common cases the following is ok: + const char **alpn_protos = { "h2", NULL }; + - where 'h2' is the protocol name */ + + union { + const unsigned char *cacert_buf; /*!< Certificate Authority's certificate in a buffer. + Format may be PEM or DER, depending on mbedtls-support + This buffer should be NULL terminated in case of PEM */ + const unsigned char *cacert_pem_buf; /*!< CA certificate buffer legacy name */ + }; + + union { + unsigned int cacert_bytes; /*!< Size of Certificate Authority certificate + pointed to by cacert_buf + (including NULL-terminator in case of PEM format) */ + unsigned int cacert_pem_bytes; /*!< Size of Certificate Authority certificate legacy name */ + }; + + union { + const unsigned char *clientcert_buf; /*!< Client certificate in a buffer + Format may be PEM or DER, depending on mbedtls-support + This buffer should be NULL terminated in case of PEM */ + const unsigned char *clientcert_pem_buf; /*!< Client certificate legacy name */ + }; + + union { + unsigned int clientcert_bytes; /*!< Size of client certificate pointed to by + clientcert_pem_buf + (including NULL-terminator in case of PEM format) */ + unsigned int clientcert_pem_bytes; /*!< Size of client certificate legacy name */ + }; + + union { + const unsigned char *clientkey_buf; /*!< Client key in a buffer + Format may be PEM or DER, depending on mbedtls-support + This buffer should be NULL terminated in case of PEM */ + const unsigned char *clientkey_pem_buf; /*!< Client key legacy name */ + }; + + union { + unsigned int clientkey_bytes; /*!< Size of client key pointed to by + clientkey_pem_buf + (including NULL-terminator in case of PEM format) */ + unsigned int clientkey_pem_bytes; /*!< Size of client key legacy name */ + }; + + const unsigned char *clientkey_password;/*!< Client key decryption password string */ + + unsigned int clientkey_password_len; /*!< String length of the password pointed to by + clientkey_password */ + + bool non_block; /*!< Configure non-blocking mode. If set to true the + underneath socket will be configured in non + blocking mode after tls session is established */ + + int timeout_ms; /*!< Network timeout in milliseconds */ + + bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which + this bool is set. */ + + const char *common_name; /*!< If non-NULL, server certificate CN must match this name. + If NULL, server certificate CN must match hostname. */ + + bool skip_common_name; /*!< Skip any validation of server certificate CN field */ + + const psk_hint_key_t* psk_hint_key; /*!< Pointer to PSK hint and key. if not NULL (and certificates are NULL) + then PSK authentication is enabled with configured setup. + Important note: the pointer must be valid for connection */ + + esp_err_t (*crt_bundle_attach)(void *conf); + /*!< Function pointer to esp_crt_bundle_attach. Enables the use of certification + bundle for server verification, must be enabled in menuconfig */ + const int *ciphersuites_list; /*!< Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + Please check the list validity by esp_tls_get_ciphersuites_list() API */ +} esp_tls_cfg_t; + +#ifdef CONFIG_ESP_TLS_SERVER +typedef struct esp_tls_cfg_server { + const char **alpn_protos; /*!< Application protocols required for HTTP2. + If HTTP2/ALPN support is required, a list + of protocols that should be negotiated. + The format is length followed by protocol + name. + For the most common cases the following is ok: + const char **alpn_protos = { "h2", NULL }; + - where 'h2' is the protocol name */ + + union { + const unsigned char *cacert_buf; /*!< Client CA certificate in a buffer. + This buffer should be NULL terminated */ + const unsigned char *cacert_pem_buf; /*!< Client CA certificate legacy name */ + }; + + union { + unsigned int cacert_bytes; /*!< Size of client CA certificate + pointed to by cacert_pem_buf */ + unsigned int cacert_pem_bytes; /*!< Size of client CA certificate legacy name */ + }; + + union { + const unsigned char *servercert_buf; /*!< Server certificate in a buffer + This buffer should be NULL terminated */ + const unsigned char *servercert_pem_buf; /*!< Server certificate legacy name */ + }; + + union { + unsigned int servercert_bytes; /*!< Size of server certificate pointed to by + servercert_pem_buf */ + unsigned int servercert_pem_bytes; /*!< Size of server certificate legacy name */ + }; + + union { + const unsigned char *serverkey_buf; /*!< Server key in a buffer + This buffer should be NULL terminated */ + const unsigned char *serverkey_pem_buf; /*!< Server key legacy name */ + }; + + union { + unsigned int serverkey_bytes; /*!< Size of server key pointed to by + serverkey_pem_buf */ + unsigned int serverkey_pem_bytes; /*!< Size of server key legacy name */ + }; + + const unsigned char *serverkey_password; /*!< Server key decryption password string */ + + unsigned int serverkey_password_len; /*!< String length of the password pointed to by + serverkey_password */ + +} esp_tls_cfg_server_t; +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +/** + * @brief ESP-TLS Connection Handle + */ +typedef struct esp_tls { +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + mbedtls_ssl_context ssl; /*!< TLS/SSL context */ + + mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */ + + mbedtls_ctr_drbg_context ctr_drbg; /*!< mbedTLS ctr drbg context structure. + CTR_DRBG is deterministic random + bit generation based on AES-256 */ + + mbedtls_ssl_config conf; /*!< TLS/SSL configuration to be shared + between mbedtls_ssl_context + structures */ + + mbedtls_net_context server_fd; /*!< mbedTLS wrapper type for sockets */ + + mbedtls_x509_crt cacert; /*!< Container for the X.509 CA certificate */ + + mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ + + mbedtls_x509_crt clientcert; /*!< Container for the X.509 client certificate */ + + mbedtls_pk_context clientkey; /*!< Container for the private key of the client + certificate */ +#ifdef CONFIG_ESP_TLS_SERVER + mbedtls_x509_crt servercert; /*!< Container for the X.509 server certificate */ + + mbedtls_pk_context serverkey; /*!< Container for the private key of the server + certificate */ +#endif +#elif CONFIG_ESP_TLS_USING_WOLFSSL + void *priv_ctx; + void *priv_ssl; +#endif + int sockfd; /*!< Underlying socket file descriptor. */ + + ssize_t (*read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL + connection. */ + + ssize_t (*write)(struct esp_tls *tls, const char *data, size_t datalen); /*!< Callback function for writing data to TLS/SSL + connection. */ + + esp_tls_conn_state_t conn_state; /*!< ESP-TLS Connection state */ + + fd_set rset; /*!< read file descriptors */ + + fd_set wset; /*!< write file descriptors */ + + bool is_tls; /*!< indicates connection type (TLS or NON-TLS) */ + + esp_tls_role_t role; /*!< esp-tls role + - ESP_TLS_CLIENT + - ESP_TLS_SERVER */ + + esp_tls_error_handle_t error_handle; /*!< handle to error descriptor */ + +} esp_tls_t; + + +/** + * @brief Create TLS connection + * + * This function allocates and initializes esp-tls structure handle. + * + * @return tls Pointer to esp-tls as esp-tls handle if successfully initialized, + * NULL if allocation error + */ +esp_tls_t *esp_tls_init(void); + + + + +/** + * @brief Create a new blocking TLS/SSL connection + * + * This function establishes a TLS/SSL connection with the specified host in blocking manner. + * + * Note: This API is present for backward compatibility reasons. Alternative function + * with the same functionality is `esp_tls_conn_new_sync` (and its asynchronous version + * `esp_tls_conn_new_async`) + * + * @param[in] hostname Hostname of the host. + * @param[in] hostlen Length of hostname. + * @param[in] port Port number of the host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * non-TLS connection, keep this NULL. For TLS connection, + * a pass pointer to esp_tls_cfg_t. At a minimum, this + * structure should be zero-initialized. + * + * @return pointer to esp_tls_t, or NULL if connection couldn't be opened. + */ +esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg) __attribute__ ((deprecated)); + +/** + * @brief Create a new blocking TLS/SSL connection + * + * This function establishes a TLS/SSL connection with the specified host in blocking manner. + * + * @param[in] hostname Hostname of the host. + * @param[in] hostlen Length of hostname. + * @param[in] port Port number of the host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * non-TLS connection, keep this NULL. For TLS connection, + * a pass pointer to esp_tls_cfg_t. At a minimum, this + * structure should be zero-initialized. + * @param[in] tls Pointer to esp-tls as esp-tls handle. + * + * @return + * - -1 If connection establishment fails. + * - 1 If connection establishment is successful. + * - 0 If connection state is in progress. + */ +int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls); + +/** + * @brief Create a new blocking TLS/SSL connection with a given "HTTP" url + * + * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url. + * + * @param[in] url url of host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * non-TLS connection, keep this NULL. For TLS connection, + * a pass pointer to 'esp_tls_cfg_t'. At a minimum, this + * structure should be zero-initialized. + * @return pointer to esp_tls_t, or NULL if connection couldn't be opened. + */ +esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg); + +/** + * @brief Create a new non-blocking TLS/SSL connection + * + * This function initiates a non-blocking TLS/SSL connection with the specified host, but due to + * its non-blocking nature, it doesn't wait for the connection to get established. + * + * @param[in] hostname Hostname of the host. + * @param[in] hostlen Length of hostname. + * @param[in] port Port number of the host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. `non_block` member of + * this structure should be set to be true. + * @param[in] tls pointer to esp-tls as esp-tls handle. + * + * @return + * - -1 If connection establishment fails. + * - 0 If connection establishment is in progress. + * - 1 If connection establishment is successful. + */ +int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls); + +/** + * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url + * + * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url. + * + * @param[in] url url of host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. + * @param[in] tls pointer to esp-tls as esp-tls handle. + * + * @return + * - -1 If connection establishment fails. + * - 0 If connection establishment is in progress. + * - 1 If connection establishment is successful. + */ +int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls); + +/** + * @brief Write from buffer 'data' into specified tls connection. + * + * @param[in] tls pointer to esp-tls as esp-tls handle. + * @param[in] data Buffer from which data will be written. + * @param[in] datalen Length of data buffer. + * + * @return + * - >0 if write operation was successful, the return value is the number + * of bytes actually written to the TLS/SSL connection. + * - 0 if write operation was not successful. The underlying + * connection was closed. + * - <0 if write operation was not successful, because either an + * error occured or an action must be taken by the calling process. + */ +static inline ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_t datalen) +{ + return tls->write(tls, (char *)data, datalen); +} + +/** + * @brief Read from specified tls connection into the buffer 'data'. + * + * @param[in] tls pointer to esp-tls as esp-tls handle. + * @param[in] data Buffer to hold read data. + * @param[in] datalen Length of data buffer. + * + * @return + * - >0 if read operation was successful, the return value is the number + * of bytes actually read from the TLS/SSL connection. + * - 0 if read operation was not successful. The underlying + * connection was closed. + * - <0 if read operation was not successful, because either an + * error occured or an action must be taken by the calling process. + */ +static inline ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen) +{ + return tls->read(tls, (char *)data, datalen); +} + +/** + * @brief Close the TLS/SSL connection and free any allocated resources. + * + * This function should be called to close each tls connection opened with esp_tls_conn_new() or + * esp_tls_conn_http_new() APIs. + * + * @param[in] tls pointer to esp-tls as esp-tls handle. + */ +void esp_tls_conn_delete(esp_tls_t *tls); + +/** + * @brief Return the number of application data bytes remaining to be + * read from the current record + * + * This API is a wrapper over mbedtls's mbedtls_ssl_get_bytes_avail() API. + * + * @param[in] tls pointer to esp-tls as esp-tls handle. + * + * @return + * - -1 in case of invalid arg + * - bytes available in the application data + * record read buffer + */ +ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls); + +/** + * @brief Returns the connection socket file descriptor from esp_tls session + * + * @param[in] tls handle to esp_tls context + * + * @param[out] sockfd int pointer to sockfd value. + * + * @return - ESP_OK on success and value of sockfd will be updated with socket file descriptor for connection + * - ESP_ERR_INVALID_ARG if (tls == NULL || sockfd == NULL) + */ +esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd); + +/** + * @brief Create a global CA store, initially empty. + * + * This function should be called if the application wants to use the same CA store for multiple connections. + * This function initialises the global CA store which can be then set by calling esp_tls_set_global_ca_store(). + * To be effective, this function must be called before any call to esp_tls_set_global_ca_store(). + * + * @return + * - ESP_OK if creating global CA store was successful. + * - ESP_ERR_NO_MEM if an error occured when allocating the mbedTLS resources. + */ +esp_err_t esp_tls_init_global_ca_store(void); + +/** + * @brief Set the global CA store with the buffer provided in pem format. + * + * This function should be called if the application wants to set the global CA store for + * multiple connections i.e. to add the certificates in the provided buffer to the certificate chain. + * This function implicitly calls esp_tls_init_global_ca_store() if it has not already been called. + * The application must call this function before calling esp_tls_conn_new(). + * + * @param[in] cacert_pem_buf Buffer which has certificates in pem format. This buffer + * is used for creating a global CA store, which can be used + * by other tls connections. + * @param[in] cacert_pem_bytes Length of the buffer. + * + * @return + * - ESP_OK if adding certificates was successful. + * - Other if an error occured or an action must be taken by the calling process. + */ +esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); + +/** + * @brief Free the global CA store currently being used. + * + * The memory being used by the global CA store to store all the parsed certificates is + * freed up. The application can call this API if it no longer needs the global CA store. + */ +void esp_tls_free_global_ca_store(void); + +/** + * @brief Returns last error in esp_tls with detailed mbedtls related error codes. + * The error information is cleared internally upon return + * + * @param[in] h esp-tls error handle. + * @param[out] esp_tls_code last error code returned from mbedtls api (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * @param[out] esp_tls_flags last certification verification flags (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * + * @return + * - ESP_ERR_INVALID_STATE if invalid parameters + * - ESP_OK (0) if no error occurred + * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise + */ +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags); + +#if CONFIG_ESP_TLS_USING_MBEDTLS +/** + * @brief Get the pointer to the global CA store currently being used. + * + * The application must first call esp_tls_set_global_ca_store(). Then the same + * CA store could be used by the application for APIs other than esp_tls. + * + * @note Modifying the pointer might cause a failure in verifying the certificates. + * + * @return + * - Pointer to the global CA store currently being used if successful. + * - NULL if there is no global CA store set. + */ +mbedtls_x509_crt *esp_tls_get_global_ca_store(void); + +/** + * @brief Get supported TLS ciphersuites list. + * + * See https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 for the list of ciphersuites + * + * @return Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + * + */ +const int *esp_tls_get_ciphersuites_list(void); +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + * + * This function creates a TLS/SSL server context for already accepted client connection + * and performs TLS/SSL handshake with the client + * + * @param[in] cfg Pointer to esp_tls_cfg_server_t + * @param[in] sockfd FD of accepted connection + * @param[out] tls Pointer to allocated esp_tls_t + * + * @return + * - 0 if successful + * - <0 in case of error + * + */ +int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls); + +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + * + * This function should be called to close each tls connection opened with esp_tls_server_session_create() + * + * @param[in] tls pointer to esp_tls_t + */ +void esp_tls_server_session_delete(esp_tls_t *tls); +#endif /* ! CONFIG_ESP_TLS_SERVER */ +#ifdef __cplusplus +} +#endif + +#endif /* ! _ESP_TLS_H_ */ diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c new file mode 100644 index 000000000..3fb0678fc --- /dev/null +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -0,0 +1,581 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "esp_tls_mbedtls.h" +#include "esp_tls_error_capture_internal.h" +#include +#include "esp_log.h" + +#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + + +static const char *TAG = "esp-tls-mbedtls"; +static mbedtls_x509_crt *global_cacert = NULL; + +typedef struct esp_tls_pki_t { + mbedtls_x509_crt *public_cert; + mbedtls_pk_context *pk_key; + const unsigned char *publiccert_pem_buf; + unsigned int publiccert_pem_bytes; + const unsigned char *privkey_pem_buf; + unsigned int privkey_pem_bytes; + const unsigned char *privkey_password; + unsigned int privkey_password_len; +} esp_tls_pki_t; + +esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + esp_err_t esp_ret = ESP_FAIL; + tls->server_fd.fd = tls->sockfd; + mbedtls_ssl_init(&tls->ssl); + mbedtls_ctr_drbg_init(&tls->ctr_drbg); + mbedtls_ssl_config_init(&tls->conf); + mbedtls_entropy_init(&tls->entropy); + + if (tls->role == ESP_TLS_CLIENT) { + esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client configurations"); + goto exit; + } + } else if (tls->role == ESP_TLS_SERVER) { +#ifdef CONFIG_ESP_TLS_SERVER + esp_ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls); + if (esp_ret != 0) { + ESP_LOGE(TAG, "Failed to set server configurations"); + goto exit; + } +#else + ESP_LOGE(TAG, "ESP_TLS_SERVER Not enabled in Kconfig"); + goto exit; +#endif + } + + if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, + mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED; + goto exit; + } + + mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); + +#ifdef CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log(&tls->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); +#endif + + if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED; + goto exit; + } + mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + return ESP_OK; + +exit: + esp_mbedtls_cleanup(tls); + return esp_ret; + +} + +int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + int ret; + ret = mbedtls_ssl_handshake(&tls->ssl); + if (ret == 0) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); + if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + esp_mbedtls_verify_certificate(tls); + } + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + /* Irrespective of blocking or non-blocking I/O, we return on getting ESP_TLS_ERR_SSL_WANT_READ + or ESP_TLS_ERR_SSL_WANT_WRITE during handshake */ + return 0; + } +} + +ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen) +{ + + ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen); + if (ret < 0) { + if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + return 0; + } + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_LOGE(TAG, "read error :%d:", ret); + } + } + return ret; +} + +ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + size_t written = 0; + size_t write_len = datalen; + while (written < datalen) { + if (write_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { + write_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + } + if (datalen > MBEDTLS_SSL_OUT_CONTENT_LEN) { + ESP_LOGD(TAG, "Fragmenting data of excessive size :%d, offset: %d, size %d", datalen, written, write_len); + } + ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len); + if (ret <= 0) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE && ret != 0) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED); + ESP_LOGE(TAG, "write error :%d:", ret); + return ret; + } else { + // Exitting the tls-write process as less than desired datalen are writable + ESP_LOGD(TAG, "mbedtls_ssl_write() returned %d, already written %d, exitting...", ret, written); + return written; + } + } + written += ret; + write_len = datalen - written; + } + return written; +} + +void esp_mbedtls_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_mbedtls_cleanup(tls); + if (tls->is_tls) { + mbedtls_net_free(&tls->server_fd); + } + } +} + +void esp_mbedtls_verify_certificate(esp_tls_t *tls) +{ + int flags; + char buf[100]; + if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { + ESP_LOGI(TAG, "Failed to verify peer certificate!"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS_CERT_FLAGS, flags); + bzero(buf, sizeof(buf)); + mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); + ESP_LOGI(TAG, "verification info: %s", buf); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +} + +ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls) +{ + if (!tls) { + ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); + return ESP_FAIL; + } + return mbedtls_ssl_get_bytes_avail(&tls->ssl); +} + +void esp_mbedtls_cleanup(esp_tls_t *tls) +{ + if (!tls) { + return; + } + if (tls->cacert_ptr != global_cacert) { + mbedtls_x509_crt_free(tls->cacert_ptr); + } + tls->cacert_ptr = NULL; +#ifdef CONFIG_ESP_TLS_SERVER + mbedtls_x509_crt_free(&tls->servercert); + mbedtls_pk_free(&tls->serverkey); +#endif + mbedtls_x509_crt_free(&tls->cacert); + mbedtls_x509_crt_free(&tls->clientcert); + mbedtls_pk_free(&tls->clientkey); + mbedtls_entropy_free(&tls->entropy); + mbedtls_ssl_config_free(&tls->conf); + mbedtls_ctr_drbg_free(&tls->ctr_drbg); + mbedtls_ssl_free(&tls->ssl); +} + +static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len) +{ + assert(tls); + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return ESP_OK; +} + +static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) +{ + assert(tls); + assert(pki); + int ret; + + if (pki->publiccert_pem_buf != NULL && + pki->privkey_pem_buf != NULL && + pki->public_cert != NULL && + pki->pk_key != NULL) { + + mbedtls_x509_crt_init(pki->public_cert); + mbedtls_pk_init(pki->pk_key); + + ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + + ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, + pki->privkey_password, pki->privkey_password_len); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; + } + + ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; + } + } else { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t set_global_ca_store(esp_tls_t *tls) +{ + assert(tls); + if (global_cacert == NULL) { + ESP_LOGE(TAG, "global_cacert is NULL"); + return ESP_ERR_INVALID_STATE; + } + tls->cacert_ptr = global_cacert; + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return ESP_OK; +} + + +#ifdef CONFIG_ESP_TLS_SERVER +esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + esp_err_t esp_ret; + if ((ret = mbedtls_ssl_config_defaults(&tls->conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; + } + +#ifdef CONFIG_MBEDTLS_SSL_ALPN + if (cfg->alpn_protos) { + mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); + } +#endif + + if (cfg->cacert_buf != NULL) { + esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) { + esp_tls_pki_t pki = { + .public_cert = &tls->servercert, + .pk_key = &tls->serverkey, + .publiccert_pem_buf = cfg->servercert_buf, + .publiccert_pem_bytes = cfg->servercert_bytes, + .privkey_pem_buf = cfg->serverkey_buf, + .privkey_pem_bytes = cfg->serverkey_bytes, + .privkey_password = cfg->serverkey_password, + .privkey_password_len = cfg->serverkey_password_len, + }; + esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set server pki context"); + return esp_ret; + } + } else { + ESP_LOGE(TAG, "Missing server certificate and/or key"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + if (!cfg->skip_common_name) { + char *use_host = NULL; + if (cfg->common_name != NULL) { + use_host = strndup(cfg->common_name, strlen(cfg->common_name)); + } else { + use_host = strndup(hostname, hostlen); + } + + if (use_host == NULL) { + return ESP_ERR_NO_MEM; + } + /* Hostname set here should match CN in server certificate */ + if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + free(use_host); + return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED; + } + free(use_host); + } + + if ((ret = mbedtls_ssl_config_defaults(&tls->conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; + } + + + if (cfg->alpn_protos) { +#ifdef CONFIG_MBEDTLS_SSL_ALPN + if ((ret = mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos) != 0)) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED; + } +#else + ESP_LOGE(TAG, "alpn_protos configured but not enabled in menuconfig: Please enable MBEDTLS_SSL_ALPN option"); + return ESP_ERR_INVALID_STATE; +#endif + } + + if (cfg->crt_bundle_attach != NULL) { +#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + ESP_LOGD(TAG, "Use certificate bundle"); + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + cfg->crt_bundle_attach(&tls->conf); +#else //CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + ESP_LOGE(TAG, "use_crt_bundle configured but not enabled in menuconfig: Please enable MBEDTLS_CERTIFICATE_BUNDLE option"); + return ESP_ERR_INVALID_STATE; +#endif + } else if (cfg->use_global_ca_store == true) { + esp_err_t esp_ret = set_global_ca_store(tls); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } else if (cfg->cacert_buf != NULL) { + esp_err_t esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); + if (esp_ret != ESP_OK) { + return esp_ret; + } + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + } else if (cfg->psk_hint_key) { +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) + // + // PSK encryption mode is configured only if no certificate supplied and psk pointer not null + ESP_LOGD(TAG, "ssl psk authentication"); + ret = mbedtls_ssl_conf_psk(&tls->conf, cfg->psk_hint_key->key, cfg->psk_hint_key->key_size, + (const unsigned char *)cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_psk returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED; + } +#else + ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); + return ESP_ERR_INVALID_STATE; +#endif + } else { +#ifdef CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); +#else + ESP_LOGE(TAG, "No server verification option set in esp_tls_cfg_t structure. Check esp_tls API reference"); + return ESP_ERR_MBEDTLS_SSL_SETUP_FAILED; +#endif + } + + if (cfg->clientcert_buf != NULL && cfg->clientkey_buf != NULL) { + esp_tls_pki_t pki = { + .public_cert = &tls->clientcert, + .pk_key = &tls->clientkey, + .publiccert_pem_buf = cfg->clientcert_buf, + .publiccert_pem_bytes = cfg->clientcert_bytes, + .privkey_pem_buf = cfg->clientkey_buf, + .privkey_pem_bytes = cfg->clientkey_bytes, + .privkey_password = cfg->clientkey_password, + .privkey_password_len = cfg->clientkey_password_len, + }; + esp_err_t esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client pki context"); + return esp_ret; + } + } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); + return ESP_ERR_INVALID_STATE; + } + + if (cfg->ciphersuites_list != NULL && cfg->ciphersuites_list[0] != 0) { + ESP_LOGD(TAG, "Set the ciphersuites list"); + mbedtls_ssl_conf_ciphersuites(&tls->conf, cfg->ciphersuites_list); + } + return ESP_OK; +} + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + */ +int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) +{ + if (tls == NULL || cfg == NULL) { + return -1; + } + tls->role = ESP_TLS_SERVER; + tls->sockfd = sockfd; + esp_err_t esp_ret = esp_create_mbedtls_handle(NULL, 0, cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "create_ssl_handle failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + tls->read = esp_mbedtls_read; + tls->write = esp_mbedtls_write; + int ret; + while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned %d", ret); + tls->conn_state = ESP_TLS_FAIL; + return ret; + } + } + return 0; +} +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + */ +void esp_mbedtls_server_session_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_mbedtls_cleanup(tls); + free(tls); + } +}; +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +esp_err_t esp_mbedtls_init_global_ca_store(void) +{ + if (global_cacert == NULL) { + global_cacert = (mbedtls_x509_crt *)calloc(1, sizeof(mbedtls_x509_crt)); + if (global_cacert == NULL) { + ESP_LOGE(TAG, "global_cacert not allocated"); + return ESP_ERR_NO_MEM; + } + mbedtls_x509_crt_init(global_cacert); + } + return ESP_OK; +} + +esp_err_t esp_mbedtls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + if (cacert_pem_buf == NULL) { + ESP_LOGE(TAG, "cacert_pem_buf is null"); + return ESP_ERR_INVALID_ARG; + } + int ret; + if (global_cacert == NULL) { + ret = esp_mbedtls_init_global_ca_store(); + if (ret != ESP_OK) { + return ret; + } + } + ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + mbedtls_x509_crt_free(global_cacert); + global_cacert = NULL; + return ESP_FAIL; + } else if (ret > 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret); + return ESP_ERR_MBEDTLS_CERT_PARTLY_OK; + } + return ESP_OK; +} + +mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void) +{ + return global_cacert; +} + +void esp_mbedtls_free_global_ca_store(void) +{ + if (global_cacert) { + mbedtls_x509_crt_free(global_cacert); + global_cacert = NULL; + } +} + +const int *esp_mbedtls_get_ciphersuites_list(void) +{ + return mbedtls_ssl_list_ciphersuites(); +} diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c new file mode 100644 index 000000000..d44198b41 --- /dev/null +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -0,0 +1,560 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "esp_tls_wolfssl.h" +#include "esp_tls_error_capture_internal.h" +#include +#include "esp_log.h" + +static unsigned char *global_cacert = NULL; +static unsigned int global_cacert_pem_bytes = 0; +static const char *TAG = "esp-tls-wolfssl"; + +/* Prototypes for the static functions */ +static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls); + +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) +#include "freertos/semphr.h" +static SemaphoreHandle_t tls_conn_lock; +static inline unsigned int esp_wolfssl_psk_client_cb(WOLFSSL* ssl, const char* hint, char* identity, + unsigned int id_max_len, unsigned char* key,unsigned int key_max_len); +static esp_err_t esp_wolfssl_set_cipher_list(WOLFSSL_CTX *ctx); +#ifdef WOLFSSL_TLS13 +#define PSK_MAX_ID_LEN 128 +#else +#define PSK_MAX_ID_LEN 64 +#endif +#define PSK_MAX_KEY_LEN 64 + +static char psk_id_str[PSK_MAX_ID_LEN]; +static uint8_t psk_key_array[PSK_MAX_KEY_LEN]; +static uint8_t psk_key_max_len = 0; +#endif /* CONFIG_ESP_TLS_PSK_VERIFICATION */ + +#ifdef CONFIG_ESP_TLS_SERVER +static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls); +#endif /* CONFIG_ESP_TLS_SERVER */ + +typedef enum x509_file_type { + FILE_TYPE_CA_CERT = 0, /* CA certificate to authenticate entity at other end */ + FILE_TYPE_SELF_CERT, /* Self certificate of the entity */ + FILE_TYPE_SELF_KEY, /* Private key in the self cert-key pair */ +} x509_file_type_t; + +/* Checks whether the certificate provided is in pem format or not */ +static esp_err_t esp_load_wolfssl_verify_buffer(esp_tls_t *tls, const unsigned char *cert_buf, unsigned int cert_len, x509_file_type_t type, int *err_ret) +{ + int wolf_fileformat = WOLFSSL_FILETYPE_DEFAULT; + if (type == FILE_TYPE_SELF_KEY) { + if (cert_buf[cert_len - 1] == '\0' && strstr( (const char *) cert_buf, "-----BEGIN " )) { + wolf_fileformat = WOLFSSL_FILETYPE_PEM; + } else { + wolf_fileformat = WOLFSSL_FILETYPE_ASN1; + } + if ((*err_ret = wolfSSL_CTX_use_PrivateKey_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cert_buf, cert_len, wolf_fileformat)) == WOLFSSL_SUCCESS) { + return ESP_OK; + } + return ESP_FAIL; + } else { + if (cert_buf[cert_len - 1] == '\0' && strstr( (const char *) cert_buf, "-----BEGIN CERTIFICATE-----" )) { + wolf_fileformat = WOLFSSL_FILETYPE_PEM; + } else { + wolf_fileformat = WOLFSSL_FILETYPE_ASN1; + } + if (type == FILE_TYPE_SELF_CERT) { + if ((*err_ret = wolfSSL_CTX_use_certificate_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cert_buf, cert_len, wolf_fileformat)) == WOLFSSL_SUCCESS) { + return ESP_OK; + } + return ESP_FAIL; + } else if (type == FILE_TYPE_CA_CERT) { + if ((*err_ret = wolfSSL_CTX_load_verify_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cert_buf, cert_len, wolf_fileformat)) == WOLFSSL_SUCCESS) { + return ESP_OK; + } + return ESP_FAIL; + } else { + /* Wrong file type provided */ + return ESP_FAIL; + } + } +} + +esp_err_t esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ +#ifdef CONFIG_ESP_DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + assert(cfg != NULL); + assert(tls != NULL); + + esp_err_t esp_ret = ESP_FAIL; + int ret; + + ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Init wolfSSL failed: %d", ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + goto exit; + } + + if (tls->role == ESP_TLS_CLIENT) { + esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client configurations"); + goto exit; + } + } else if (tls->role == ESP_TLS_SERVER) { +#ifdef CONFIG_ESP_TLS_SERVER + esp_ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set server configurations"); + goto exit; + } +#else + ESP_LOGE(TAG, "ESP_TLS_SERVER Not enabled in menuconfig"); + goto exit; +#endif + } + else { + ESP_LOGE(TAG, "tls->role is not valid"); + goto exit; + } + + return ESP_OK; +exit: + esp_wolfssl_cleanup(tls); + return esp_ret; +} + +static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + int ret = WOLFSSL_FAILURE; + tls->priv_ctx = (void *)wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!tls->priv_ctx) { + ESP_LOGE(TAG, "Set wolfSSL ctx failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + + if (cfg->use_global_ca_store == true) { + if ((esp_load_wolfssl_verify_buffer(tls, global_cacert, global_cacert_pem_bytes, FILE_TYPE_CA_CERT, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_PEER, NULL); + } else if (cfg->cacert_buf != NULL) { + if ((esp_load_wolfssl_verify_buffer(tls, cfg->cacert_buf, cfg->cacert_bytes, FILE_TYPE_CA_CERT, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_PEER, NULL); + } else if (cfg->psk_hint_key) { +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) + /*** PSK encryption mode is configured only if no certificate supplied and psk pointer not null ***/ + if(cfg->psk_hint_key->key == NULL || cfg->psk_hint_key->hint == NULL || cfg->psk_hint_key->key_size <= 0) { + ESP_LOGE(TAG, "Please provide appropriate key, keysize and hint to use PSK"); + return ESP_FAIL; + } + /* mutex is given back when call back function executes or in case of failure (at cleanup) */ + if ((xSemaphoreTake(tls_conn_lock, 1000/portTICK_PERIOD_MS) != pdTRUE)) { + ESP_LOGE(TAG, "tls_conn_lock could not be obtained in specified time"); + return -1; + } + ESP_LOGI(TAG, "setting psk configurations"); + if((cfg->psk_hint_key->key_size > PSK_MAX_KEY_LEN) || (strlen(cfg->psk_hint_key->hint) > PSK_MAX_ID_LEN)) { + ESP_LOGE(TAG, "psk key length should be <= %d and identity hint length should be <= %d", PSK_MAX_KEY_LEN, PSK_MAX_ID_LEN); + return ESP_ERR_INVALID_ARG; + } + psk_key_max_len = cfg->psk_hint_key->key_size; + memset(psk_key_array, 0, sizeof(psk_key_array)); + memset(psk_id_str, 0, sizeof(psk_id_str)); + memcpy(psk_key_array, cfg->psk_hint_key->key, psk_key_max_len); + memcpy(psk_id_str, cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); + wolfSSL_CTX_set_psk_client_callback( (WOLFSSL_CTX *)tls->priv_ctx, esp_wolfssl_psk_client_cb); + if(esp_wolfssl_set_cipher_list( (WOLFSSL_CTX *)tls->priv_ctx) != ESP_OK) { + ESP_LOGE(TAG, "error in setting cipher-list"); + return ESP_FAIL; + } +#else + ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); + return ESP_ERR_INVALID_STATE; +#endif + } else { +#ifdef CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_NONE, NULL); +#else + ESP_LOGE(TAG, "No server verification option set in esp_tls_cfg_t structure. Check esp_tls API reference"); + return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; +#endif + } + + if (cfg->clientcert_buf != NULL && cfg->clientkey_buf != NULL) { + if ((esp_load_wolfssl_verify_buffer(tls,cfg->clientcert_buf, cfg->clientcert_bytes, FILE_TYPE_SELF_CERT, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + if ((esp_load_wolfssl_verify_buffer(tls,cfg->clientkey_buf, cfg->clientkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading private key verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication\n\n"); + return ESP_FAIL; + } + + if (cfg->crt_bundle_attach != NULL) { + ESP_LOGE(TAG,"use_crt_bundle not supported in wolfssl"); + return ESP_FAIL; + } + + tls->priv_ssl =(void *)wolfSSL_new( (WOLFSSL_CTX *)tls->priv_ctx); + if (!tls->priv_ssl) { + ESP_LOGE(TAG, "Create wolfSSL failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; + } + + if (!cfg->skip_common_name) { +#ifdef HAVE_SNI + char *use_host = NULL; + if (cfg->common_name != NULL) { + use_host = strdup(cfg->common_name); + } else { + use_host = strndup(hostname, hostlen); + } + if (use_host == NULL) { + return ESP_ERR_NO_MEM; + } + /* Hostname set here should match CN in server certificate */ + if ((ret = wolfSSL_check_domain_name( (WOLFSSL *)tls->priv_ssl, use_host))!= WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_check_domain_name returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + free(use_host); + return ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED; + } + free(use_host); +#endif /* HAVE_SNI */ + } + + if (cfg->alpn_protos) { +#ifdef CONFIG_WOLFSSL_HAVE_ALPN + char **alpn_list = (char **)cfg->alpn_protos; + for (; *alpn_list != NULL; alpn_list ++) { + ESP_LOGD(TAG, "alpn protocol is %s", *alpn_list); + if ((ret = wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)) != WOLFSSL_SUCCESS) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "wolfSSL UseALPN failed, returned %d", ret); + return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED; + } + } +#else + ESP_LOGE(TAG, "CONFIG_WOLFSSL_HAVE_ALPN not enabled in menuconfig"); + return ESP_FAIL; +#endif /* CONFIG_WOLFSSL_HAVE_ALPN */ + } + + wolfSSL_set_fd((WOLFSSL *)tls->priv_ssl, tls->sockfd); + return ESP_OK; +} + +#ifdef CONFIG_ESP_TLS_SERVER +static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) +{ + int ret = WOLFSSL_FAILURE; + tls->priv_ctx = (void *)wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + if (!tls->priv_ctx) { + ESP_LOGE(TAG, "Set wolfSSL ctx failed"); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + + if (cfg->cacert_buf != NULL) { + if ((esp_load_wolfssl_verify_buffer(tls,cfg->cacert_buf, cfg->cacert_bytes, FILE_TYPE_CA_CERT, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + ESP_LOGD(TAG," Verify Client for Mutual Auth"); + } else { + ESP_LOGD(TAG," Not verifying Client "); + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_NONE, NULL); + } + + if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) { + if ((esp_load_wolfssl_verify_buffer(tls,cfg->servercert_buf, cfg->servercert_bytes, FILE_TYPE_SELF_CERT, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + if ((esp_load_wolfssl_verify_buffer(tls,cfg->serverkey_buf, cfg->serverkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { + ESP_LOGE(TAG, "Error in loading private key verify buffer, returned %d", ret); + return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; + } + } else { + ESP_LOGE(TAG, "You have to provide both servercert_buf and serverkey_buf for https_server\n\n"); + return ESP_FAIL; + } + + tls->priv_ssl =(void *)wolfSSL_new( (WOLFSSL_CTX *)tls->priv_ctx); + if (!tls->priv_ssl) { + ESP_LOGE(TAG, "Create wolfSSL failed"); + return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; + } + + wolfSSL_set_fd((WOLFSSL *)tls->priv_ssl, tls->sockfd); + return ESP_OK; +} +#endif + +int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + int ret; + ret = wolfSSL_connect( (WOLFSSL *)tls->priv_ssl); + if (ret == WOLFSSL_SUCCESS) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + if (err != ESP_TLS_ERR_SSL_WANT_READ && err != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED); + if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + esp_wolfssl_verify_certificate(tls); + } + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + /* Irrespective of blocking or non-blocking I/O, we return on getting wolfSSL_want_read + or wolfSSL_want_write during handshake */ + return 0; + } +} + +ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen) +{ + ssize_t ret = wolfSSL_read( (WOLFSSL *)tls->priv_ssl, (unsigned char *)data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + /* peer sent close notify */ + if (ret == WOLFSSL_ERROR_ZERO_RETURN) { + return 0; + } + + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "read error :%d:", ret); + } + } + return ret; +} + +ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + ssize_t ret = wolfSSL_write( (WOLFSSL *)tls->priv_ssl, (unsigned char *) data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED); + ESP_LOGE(TAG, "write error :%d:", ret); + + } + } + return ret; +} + +void esp_wolfssl_verify_certificate(esp_tls_t *tls) +{ + int flags; + if ((flags = wolfSSL_get_verify_result( (WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Failed to verify peer certificate , returned %d!", flags); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL_CERT_FLAGS, flags); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +} + +ssize_t esp_wolfssl_get_bytes_avail(esp_tls_t *tls) +{ + if (!tls) { + ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); + return ESP_FAIL; + } + return wolfSSL_pending( (WOLFSSL *)tls->priv_ssl); +} + +void esp_wolfssl_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_wolfssl_cleanup(tls); + } +} + +void esp_wolfssl_cleanup(esp_tls_t *tls) +{ + if (!tls) { + return; + } +#ifdef CONFIG_ESP_TLS_PSK_VERIFICATION + xSemaphoreGive(tls_conn_lock); +#endif /* CONFIG_ESP_TLS_PSK_VERIFICATION */ + wolfSSL_shutdown( (WOLFSSL *)tls->priv_ssl); + wolfSSL_free( (WOLFSSL *)tls->priv_ssl); + tls->priv_ssl = NULL; + wolfSSL_CTX_free( (WOLFSSL_CTX *)tls->priv_ctx); + tls->priv_ctx = NULL; + wolfSSL_Cleanup(); +} + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + */ +int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) +{ + if (tls == NULL || cfg == NULL) { + return -1; + } + tls->role = ESP_TLS_SERVER; + tls->sockfd = sockfd; + esp_err_t esp_ret = esp_create_wolfssl_handle(NULL, 0, cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "create_ssl_handle failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + tls->read = esp_wolfssl_read; + tls->write = esp_wolfssl_write; + int ret; + while ((ret = wolfSSL_accept((WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "wolfSSL_handshake_server returned %d", ret); + tls->conn_state = ESP_TLS_FAIL; + return ret; + } + } + return 0; +} + +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + */ +void esp_wolfssl_server_session_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_wolfssl_cleanup(tls); + free(tls); + } +} +#endif /* CONFIG_ESP_TLS_SERVER */ + +esp_err_t esp_wolfssl_init_global_ca_store(void) +{ + /* This function is just to provide consistancy between function calls of esp_tls.h and wolfssl */ + return ESP_OK; +} + +esp_err_t esp_wolfssl_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + if (cacert_pem_buf == NULL) { + ESP_LOGE(TAG, "cacert_pem_buf is null"); + return ESP_ERR_INVALID_ARG; + } + if (global_cacert != NULL) { + esp_wolfssl_free_global_ca_store(); + } + + global_cacert = (unsigned char *)strndup((const char *)cacert_pem_buf, cacert_pem_bytes); + if (!global_cacert) { + return ESP_FAIL; + } + + global_cacert_pem_bytes = cacert_pem_bytes; + + return ESP_OK; +} + +void esp_wolfssl_free_global_ca_store(void) +{ + if (global_cacert) { + free(global_cacert); + global_cacert = NULL; + global_cacert_pem_bytes = 0; + } +} + +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) +static esp_err_t esp_wolfssl_set_cipher_list(WOLFSSL_CTX *ctx) +{ + const char *defaultCipherList; + int ret; +#if defined(HAVE_AESGCM) && !defined(NO_DH) +#ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; +#else + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; +#endif +#elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; +#else + defaultCipherList = "PSK-AES128-CBC-SHA256"; +#endif + ESP_LOGD(TAG, "cipher list is %s", defaultCipherList); + if ((ret = wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList)) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); + ESP_LOGE(TAG, "can't set cipher list, returned %02x", ret); + return ESP_FAIL; + } + return ESP_OK; +} + +/* initialize the mutex before app_main() when using PSK */ +static void __attribute__((constructor)) +espt_tls_wolfssl_init_conn_lock (void) +{ + if ((tls_conn_lock = xSemaphoreCreateMutex()) == NULL) { + ESP_EARLY_LOGE(TAG, "mutex for tls psk connection could not be created"); + } +} + +/* Some callback functions required by PSK */ +static inline unsigned int esp_wolfssl_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + memcpy(identity, psk_id_str, id_max_len); + for(int count = 0; count < psk_key_max_len; count ++) { + key[count] = psk_key_array[count]; + } + xSemaphoreGive(tls_conn_lock); + return psk_key_max_len; + /* return length of key in octets or 0 or for error */ +} +#endif /* CONFIG_ESP_TLS_PSK_VERIFICATION */ diff --git a/components/esp-tls/private_include/esp_tls_error_capture_internal.h b/components/esp-tls/private_include/esp_tls_error_capture_internal.h new file mode 100644 index 000000000..d047b543b --- /dev/null +++ b/components/esp-tls/private_include/esp_tls_error_capture_internal.h @@ -0,0 +1,69 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_TLS_ERROR_CAPTURE_INTERNAL_H__ +#define __ESP_TLS_ERROR_CAPTURE_INTERNAL_H__ +/** +* Note: this is an implementation placeholder for error logger. +* This version is internal to esp-tls component and only saves single esp_err of last occurred error +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* Definition of different types/sources of error codes reported +* from different components +*/ +typedef enum { + ERR_TYPE_UNKNOWN = 0, + ERR_TYPE_SYSTEM, + ERR_TYPE_MBEDTLS, + ERR_TYPE_MBEDTLS_CERT_FLAGS, + ERR_TYPE_ESP, + ERR_TYPE_WOLFSSL, + ERR_TYPE_WOLFSSL_CERT_FLAGS, +} err_type_t; + +/** + * Error tracker logging macro, this implementation saves latest errors of + * ERR_TYPE_ESP, ERR_TYPE_ESP_TLS and ERR_TYPE_ESP_TLS_CERT_FLAGS types + */ +#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_int_event_tracker_capture(h, type, code) + +static inline void esp_int_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code) +{ + if (h) { + if (type == ERR_TYPE_ESP) { + h->last_error = code; + } else if (type == ERR_TYPE_MBEDTLS) { + h->esp_tls_error_code = code; + } else if (type == ERR_TYPE_MBEDTLS_CERT_FLAGS) { + h->esp_tls_flags = code; + } else if (type == ERR_TYPE_WOLFSSL) { + h->esp_tls_error_code = code; + } else if (type == ERR_TYPE_WOLFSSL_CERT_FLAGS) { + h->esp_tls_flags = code; + } + } +} + + + +#ifdef __cplusplus +} +#endif + +#endif //__ESP_TLS_ERROR_CAPTURE_INTERNAL_H__ diff --git a/components/esp-tls/private_include/esp_tls_mbedtls.h b/components/esp-tls/private_include/esp_tls_mbedtls.h new file mode 100644 index 000000000..4e542cbe6 --- /dev/null +++ b/components/esp-tls/private_include/esp_tls_mbedtls.h @@ -0,0 +1,109 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "esp_tls.h" + +/** + * Internal Callback API for mbedtls_ssl_read + */ +ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen); + +/** + * Internal callback API for mbedtls_ssl_write + */ +ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen); + +/** + * Internal Callback for mbedtls_handshake + */ +int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg); + +/** + * Internal Callback for mbedtls_cleanup , frees up all the memory used by mbedtls + */ +void esp_mbedtls_cleanup(esp_tls_t *tls); + +/** + * Internal Callback for Certificate verification for mbedtls + */ +void esp_mbedtls_verify_certificate(esp_tls_t *tls); + +/** + * Internal Callback for deleting the mbedtls connection + */ +void esp_mbedtls_conn_delete(esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_get_bytes_avail + */ +ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls); + +/** + * Internal Callback for creating ssl handle for mbedtls + */ +esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls); + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * Internal Callback for set_server_config + * + * /note :- can only be used with mbedtls ssl library + */ +esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_server_session_create + * + * /note :- The function can only be used with mbedtls ssl library + */ +int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_server_session_delete + * + * /note :- The function can only be used with mbedtls ssl library + */ +void esp_mbedtls_server_session_delete(esp_tls_t *tls); +#endif + +/** + * Internal Callback for set_client_config_function + */ +esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_init_global_ca_store + */ +esp_err_t esp_mbedtls_init_global_ca_store(void); + +/** + * Callback function for setting global CA store data for TLS/SSL using mbedtls + */ +esp_err_t esp_mbedtls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); + +/** + * Internal Callback for esp_tls_global_ca_store + */ +mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void); + +/** + * Callback function for freeing global ca store for TLS/SSL using mbedtls + */ +void esp_mbedtls_free_global_ca_store(void); + +/** + * Internal Callback for esp_tls_get_ciphersuites_list + */ +const int *esp_mbedtls_get_ciphersuites_list(void); diff --git a/components/esp-tls/private_include/esp_tls_wolfssl.h b/components/esp-tls/private_include/esp_tls_wolfssl.h new file mode 100644 index 000000000..a04ad796c --- /dev/null +++ b/components/esp-tls/private_include/esp_tls_wolfssl.h @@ -0,0 +1,86 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "esp_tls.h" + +/** + * Internal Callback for creating ssl handle for wolfssl + */ +int esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls); + +/** + * Internal Callback for wolfssl_handshake + */ +int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg); + +/** + * Internal Callback API for wolfssl_ssl_read + */ +ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen); + +/** + * Internal callback API for wolfssl_ssl_write + */ +ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen); + +/** + * Internal Callback for wolfssl_cleanup , frees up all the memory used by wolfssl + */ +void esp_wolfssl_cleanup(esp_tls_t *tls); + +/** + * Internal Callback for Certificate verification for wolfssl + */ +void esp_wolfssl_verify_certificate(esp_tls_t *tls); + +/** + * Internal Callback for deleting the wolfssl connection + */ +void esp_wolfssl_conn_delete(esp_tls_t *tls); + +/** + * Internal Callback for wolfssl_get_bytes_avail + */ +ssize_t esp_wolfssl_get_bytes_avail(esp_tls_t *tls); + +/** + * Callback function for setting global CA store data for TLS/SSL using wolfssl + */ +esp_err_t esp_wolfssl_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); + +/** + * Callback function for freeing global ca store for TLS/SSL using wolfssl + */ +void esp_wolfssl_free_global_ca_store(void); + +/** + * + * Callback function for Initializing the global ca store for TLS?SSL using wolfssl + */ +esp_err_t esp_wolfssl_init_global_ca_store(void); + +#ifdef CONFIG_ESP_TLS_SERVER + +/** + * Function to Create ESP-TLS Server session with wolfssl Stack + */ +int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls); + +/* + * Delete Server Session + */ +void esp_wolfssl_server_session_delete(esp_tls_t *tls); + +#endif diff --git a/components/esp-wolfssl/CMakeLists.txt b/components/esp-wolfssl/CMakeLists.txt new file mode 100644 index 000000000..ad01f57ed --- /dev/null +++ b/components/esp-wolfssl/CMakeLists.txt @@ -0,0 +1,21 @@ +idf_build_get_property(target IDF_TARGET) +if(CONFIG_ESP_WOLFSSL_INTERNAL) +set(COMPONENT_ADD_INCLUDEDIRS wolfssl/include wolfssl/wolfssl wolfssl/wolfssl/wolfssl) +set(COMPONENT_SRCDIRS "wolfssl/source") + +set(COMPONENT_REQUIRES "lwip" "${target}") +endif() + +register_component() + +if(CONFIG_ESP_WOLFSSL_INTERNAL) +target_compile_options(${COMPONENT_LIB} PUBLIC -DWOLFSSL_USER_SETTINGS) + +target_link_libraries(${COMPONENT_LIB} PUBLIC "-L ${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/lib") + +if(CONFIG_WOLFSSL_DEBUG) +target_link_libraries(${COMPONENT_LIB} PUBLIC "wolfssl_debug") +else() +target_link_libraries(${COMPONENT_LIB} PUBLIC "wolfssl") +endif() +endif() diff --git a/components/esp-wolfssl/Kconfig b/components/esp-wolfssl/Kconfig new file mode 100644 index 000000000..0c33c8d0c --- /dev/null +++ b/components/esp-wolfssl/Kconfig @@ -0,0 +1,17 @@ +menu "esp-wolfssl(internal)" + +config ESP_WOLFSSL_INTERNAL + bool "Enable esp-wolfssl(internal)" + default n + help + Enable esp-wolfssl(internal). + + If users want to use external wolfssl, please disable this option. + +config WOLFSSL_DEBUG + bool "Enable esp-wolfssl(internal) debugging" + default n + help + Enable esp-wolfssl(internal) debugging functions at compile time. + +endmenu diff --git a/components/esp-wolfssl/Makefile.projbuild b/components/esp-wolfssl/Makefile.projbuild new file mode 100644 index 000000000..1b4604339 --- /dev/null +++ b/components/esp-wolfssl/Makefile.projbuild @@ -0,0 +1,6 @@ +# Anyone compiling mbedTLS code needs the name of the +# alternative config file + +ifdef CONFIG_ESP_WOLFSSL_INTERNAL +CPPFLAGS += -DWOLFSSL_USER_SETTINGS +endif diff --git a/components/esp-wolfssl/component.mk b/components/esp-wolfssl/component.mk new file mode 100644 index 000000000..3490e4642 --- /dev/null +++ b/components/esp-wolfssl/component.mk @@ -0,0 +1,18 @@ +# +# Component Makefile +# + +ifdef CONFIG_ESP_WOLFSSL_INTERNAL +COMPONENT_ADD_INCLUDEDIRS := wolfssl/include wolfssl/wolfssl wolfssl/wolfssl/wolfssl + +ifdef CONFIG_WOLFSSL_DEBUG +WOLFSSLLIB = wolfssl_debug +COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH)/wolfssl/lib -lwolfssl_debug +else +WOLFSSLLIB = wolfssl +COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH)/wolfssl/lib -lwolfssl +endif + +# re-link program if wolfssl library change +COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/wolfssl/lib/lib%.a,$(WOLFSSLLIB)) +endif \ No newline at end of file diff --git a/components/esp-wolfssl/wolfssl/README b/components/esp-wolfssl/wolfssl/README new file mode 100644 index 000000000..429dd11ac --- /dev/null +++ b/components/esp-wolfssl/wolfssl/README @@ -0,0 +1,8 @@ +Espressif has a license to distribute wolfSSL royalty-free in binary form on all Espressif MCU products. +You can use the binary wolfSSL library on Espressif devices in products, without additional royalty costs. +The binary library does not include wolfSSL features for TLS 1.3, FIPS or DTLS 1.2. + +Updates to these wolfSSL binary libraries will be available until at least March 2021. + +To discuss additional features, additional support and updates, or to obtain a quote for +other individual licensing options then please contact licensing@wolfssl.com diff --git a/components/ssl/wolfssl/include/user_settings.h b/components/esp-wolfssl/wolfssl/include/user_settings.h similarity index 85% rename from components/ssl/wolfssl/include/user_settings.h rename to components/esp-wolfssl/wolfssl/include/user_settings.h index 07b9abaed..a4488ff0a 100644 --- a/components/ssl/wolfssl/include/user_settings.h +++ b/components/esp-wolfssl/wolfssl/include/user_settings.h @@ -5,7 +5,8 @@ * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * * http://www.wolfssl.com */ @@ -31,6 +32,8 @@ #define NO_RC4 #define NO_RABBIT #define HAVE_ECC +#define HAVE_AES_ECB +#define WOLFSSL_AES_DIRECT #define WC_NO_HARDEN #define FREERTOS #define WOLFSSL_TYPES @@ -39,6 +42,7 @@ #define WOLFSSL_ALLOW_TLSV10 #define WOLFSSL_SMALL_STACK #define SMALL_SESSION_CACHE +#define OPENSSL_EXTRA #define SSL_CTX_use_certificate_ASN1(ctx,len,buf) wolfSSL_CTX_use_certificate_buffer(ctx,buf,len,WOLFSSL_FILETYPE_PEM) #define SSL_CTX_use_PrivateKey_ASN1(type,ctx,buf,len) wolfSSL_CTX_use_PrivateKey_buffer(ctx,buf,len, WOLFSSL_FILETYPE_PEM) @@ -54,6 +58,7 @@ #endif #ifndef CUSTOM_RAND_GENERATE_BLOCK +#include "esp_libc.h" /* To use define the following:*/ #define CUSTOM_RAND_GENERATE_BLOCK os_get_random #endif diff --git a/components/esp-wolfssl/wolfssl/lib/libwolfssl.a b/components/esp-wolfssl/wolfssl/lib/libwolfssl.a new file mode 100644 index 000000000..f475465b0 Binary files /dev/null and b/components/esp-wolfssl/wolfssl/lib/libwolfssl.a differ diff --git a/components/esp-wolfssl/wolfssl/lib/libwolfssl_debug.a b/components/esp-wolfssl/wolfssl/lib/libwolfssl_debug.a new file mode 100644 index 000000000..713d419c6 Binary files /dev/null and b/components/esp-wolfssl/wolfssl/lib/libwolfssl_debug.a differ diff --git a/components/esp-wolfssl/wolfssl/source/cmake_compiling.c b/components/esp-wolfssl/wolfssl/source/cmake_compiling.c new file mode 100644 index 000000000..b80224b1a --- /dev/null +++ b/components/esp-wolfssl/wolfssl/source/cmake_compiling.c @@ -0,0 +1 @@ +// Just for passing cmake project compiling. diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h new file mode 100644 index 000000000..6d22c4b10 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/asn1.h @@ -0,0 +1,51 @@ +/* asn1.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* asn1.h for openssl */ + +#ifndef WOLFSSL_ASN1_H_ +#define WOLFSSL_ASN1_H_ + +#include + +#define ASN1_STRING_new wolfSSL_ASN1_STRING_type_new +#define ASN1_STRING_type_new wolfSSL_ASN1_STRING_type_new +#define ASN1_STRING_set wolfSSL_ASN1_STRING_set +#define ASN1_STRING_free wolfSSL_ASN1_STRING_free + +#define V_ASN1_OCTET_STRING 0x04 /* tag for ASN1_OCTET_STRING */ +#define V_ASN1_NEG 0x100 +#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) + +/* Type for ASN1_print_ex */ +# define ASN1_STRFLGS_ESC_2253 1 +# define ASN1_STRFLGS_ESC_CTRL 2 +# define ASN1_STRFLGS_ESC_MSB 4 +# define ASN1_STRFLGS_ESC_QUOTE 8 +# define ASN1_STRFLGS_UTF8_CONVERT 0x10 +# define ASN1_STRFLGS_IGNORE_TYPE 0x20 +# define ASN1_STRFLGS_SHOW_TYPE 0x40 +# define ASN1_STRFLGS_DUMP_ALL 0x80 +# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 +# define ASN1_STRFLGS_DUMP_DER 0x200 +# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +#define MBSTRING_UTF8 0x1000 + +#endif /* WOLFSSL_ASN1_H_ */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/bn.h similarity index 94% rename from components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/bn.h index e360df777..dc6f12715 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/bn.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/bn.h @@ -1,17 +1,23 @@ /* bn.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ /* bn.h for openssl */ +/*! + \file wolfssl/openssl/bn.h + \brief bn.h for openssl +*/ + #ifndef WOLFSSL_BN_H_ #define WOLFSSL_BN_H_ @@ -96,7 +102,7 @@ WOLFSSL_API int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM*, int, WOLFSSL_API WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) - WOLFSSL_API int wolfSSL_BN_print_fp(FILE*, const WOLFSSL_BIGNUM*); + WOLFSSL_API int wolfSSL_BN_print_fp(XFILE, const WOLFSSL_BIGNUM*); #endif WOLFSSL_API int wolfSSL_BN_rshift(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, int); WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx); diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h new file mode 100644 index 000000000..0f195b1c6 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/crypto.h @@ -0,0 +1,72 @@ +/* crypto.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* crypto.h for openSSL */ + +#ifndef WOLFSSL_CRYPTO_H_ +#define WOLFSSL_CRYPTO_H_ + +#include + +#include + +#ifdef WOLFSSL_PREFIX +#include "prefix_crypto.h" +#endif + + +WOLFSSL_API const char* wolfSSLeay_version(int type); +WOLFSSL_API unsigned long wolfSSLeay(void); + +#ifdef OPENSSL_EXTRA +WOLFSSL_API void wolfSSL_OPENSSL_free(void*); +WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a); +#endif + +#define CRYPTO_THREADID void + +#define SSLeay_version wolfSSLeay_version +#define SSLeay wolfSSLeay + + +#define SSLEAY_VERSION 0x0090600fL +#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION +#define CRYPTO_lock wc_LockMutex_ex + +/* this function was used to set the default malloc, free, and realloc */ +#define CRYPTO_malloc_init() /* CRYPTO_malloc_init is not needed */ + +#define OPENSSL_free wolfSSL_OPENSSL_free +#define OPENSSL_malloc wolfSSL_OPENSSL_malloc + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) +#define CRYPTO_set_mem_ex_functions wolfSSL_CRYPTO_set_mem_ex_functions +#define FIPS_mode wolfSSL_FIPS_mode +#define FIPS_mode_set wolfSSL_FIPS_mode_set +typedef struct CRYPTO_EX_DATA CRYPTO_EX_DATA; +typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void* argp); +#define CRYPTO_THREADID_set_callback wolfSSL_THREADID_set_callback +#define CRYPTO_THREADID_set_numeric wolfSSL_THREADID_set_numeric + +#define CRYPTO_r_lock wc_LockMutex_ex +#define CRYPTO_unlock wc_LockMutex_ex + +#define CRYPTO_THREAD_lock wc_LockMutex +#define CRYPTO_THREAD_r_lock wc_LockMutex +#define CRYPTO_THREAD_unlock wc_UnLockMutex + +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* header */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h similarity index 89% rename from components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h index bdcde8e0a..16fd2d336 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/dsa.h @@ -1,12 +1,13 @@ /* dsa.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ec.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ec.h new file mode 100644 index 000000000..e3497143e --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ec.h @@ -0,0 +1,225 @@ +/* ec.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* ec.h for openssl */ + +#ifndef WOLFSSL_EC_H_ +#define WOLFSSL_EC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Map OpenSSL NID value */ +enum { + POINT_CONVERSION_COMPRESSED = 2, + POINT_CONVERSION_UNCOMPRESSED = 4, + +#ifdef HAVE_ECC + /* Use ecc_curve_type enum values for NID */ + NID_X9_62_prime192v1 = ECC_SECP192R1, + NID_X9_62_prime256v1 = ECC_SECP256R1, + NID_secp112r1 = ECC_SECP112R1, + NID_secp112r2 = ECC_SECP112R2, + NID_secp128r1 = ECC_SECP128R1, + NID_secp128r2 = ECC_SECP128R2, + NID_secp160r1 = ECC_SECP160R1, + NID_secp160r2 = ECC_SECP160R2, + NID_secp224r1 = ECC_SECP224R1, + NID_secp384r1 = ECC_SECP384R1, + NID_secp521r1 = ECC_SECP521R1, + NID_secp160k1 = ECC_SECP160K1, + NID_secp192k1 = ECC_SECP192K1, + NID_secp224k1 = ECC_SECP224K1, + NID_secp256k1 = ECC_SECP256K1, + NID_brainpoolP160r1 = ECC_BRAINPOOLP160R1, + NID_brainpoolP192r1 = ECC_BRAINPOOLP192R1, + NID_brainpoolP224r1 = ECC_BRAINPOOLP224R1, + NID_brainpoolP256r1 = ECC_BRAINPOOLP256R1, + NID_brainpoolP320r1 = ECC_BRAINPOOLP320R1, + NID_brainpoolP384r1 = ECC_BRAINPOOLP384R1, + NID_brainpoolP512r1 = ECC_BRAINPOOLP512R1, +#endif + + OPENSSL_EC_NAMED_CURVE = 0x001 +}; + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +typedef WOLFSSL_EC_KEY EC_KEY; +typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_POINT EC_POINT; + +struct WOLFSSL_EC_POINT { + WOLFSSL_BIGNUM *X; + WOLFSSL_BIGNUM *Y; + WOLFSSL_BIGNUM *Z; + + void* internal; /* our ECC point */ + char inSet; /* internal set from external ? */ + char exSet; /* external set from internal ? */ +}; + +struct WOLFSSL_EC_GROUP { + int curve_idx; /* index of curve, used by WolfSSL as reference */ + int curve_nid; /* NID of curve, used by OpenSSL/OpenSSH as reference */ + int curve_oid; /* OID of curve, used by OpenSSL/OpenSSH as reference */ +}; + +struct WOLFSSL_EC_KEY { + WOLFSSL_EC_GROUP *group; + WOLFSSL_EC_POINT *pub_key; + WOLFSSL_BIGNUM *priv_key; + + void* internal; /* our ECC Key */ + char inSet; /* internal set from external ? */ + char exSet; /* external set from internal ? */ +}; + + +#define WOLFSSL_EC_KEY_LOAD_PRIVATE 1 +#define WOLFSSL_EC_KEY_LOAD_PUBLIC 2 + +WOLFSSL_API +int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve, + const WOLFSSL_EC_POINT *p, + unsigned char *out, unsigned int *len); +WOLFSSL_API +int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p); +WOLFSSL_API +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, + const unsigned char* der, int derSz); +WOLFSSL_API +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, + const unsigned char* der, int derSz, int opt); +WOLFSSL_API +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key); +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key); +WOLFSSL_API +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid); +WOLFSSL_API +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void); +WOLFSSL_API +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key); +WOLFSSL_API +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag); +WOLFSSL_API +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub); +WOLFSSL_API +void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag); +WOLFSSL_API +WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid); +WOLFSSL_API +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group); +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + WOLFSSL_BIGNUM *x, + WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, + const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point); +WOLFSSL_API +int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point); +WOLFSSL_API +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a); + +#ifndef HAVE_SELFTEST +WOLFSSL_API +char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, + WOLFSSL_BN_CTX* ctx); +#endif + +#define EC_KEY_new wolfSSL_EC_KEY_new +#define EC_KEY_free wolfSSL_EC_KEY_free +#define EC_KEY_get0_public_key wolfSSL_EC_KEY_get0_public_key +#define EC_KEY_get0_group wolfSSL_EC_KEY_get0_group +#define EC_KEY_set_private_key wolfSSL_EC_KEY_set_private_key +#define EC_KEY_get0_private_key wolfSSL_EC_KEY_get0_private_key +#define EC_KEY_new_by_curve_name wolfSSL_EC_KEY_new_by_curve_name +#define EC_KEY_set_group wolfSSL_EC_KEY_set_group +#define EC_KEY_generate_key wolfSSL_EC_KEY_generate_key +#define EC_KEY_set_asn1_flag wolfSSL_EC_KEY_set_asn1_flag +#define EC_KEY_set_public_key wolfSSL_EC_KEY_set_public_key + +#define EC_GROUP_free wolfSSL_EC_GROUP_free +#define EC_GROUP_set_asn1_flag wolfSSL_EC_GROUP_set_asn1_flag +#define EC_GROUP_new_by_curve_name wolfSSL_EC_GROUP_new_by_curve_name +#define EC_GROUP_cmp wolfSSL_EC_GROUP_cmp +#define EC_GROUP_get_curve_name wolfSSL_EC_GROUP_get_curve_name +#define EC_GROUP_get_degree wolfSSL_EC_GROUP_get_degree +#define EC_GROUP_get_order wolfSSL_EC_GROUP_get_order + +#define EC_POINT_new wolfSSL_EC_POINT_new +#define EC_POINT_free wolfSSL_EC_POINT_free +#define EC_POINT_get_affine_coordinates_GFp \ + wolfSSL_EC_POINT_get_affine_coordinates_GFp +#define EC_POINT_mul wolfSSL_EC_POINT_mul +#define EC_POINT_clear_free wolfSSL_EC_POINT_clear_free +#define EC_POINT_cmp wolfSSL_EC_POINT_cmp +#define EC_POINT_is_at_infinity wolfSSL_EC_POINT_is_at_infinity + +#ifndef HAVE_SELFTEST + #define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex +#endif + +#define EC_POINT_dump wolfSSL_EC_POINT_dump + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/evp.h similarity index 80% rename from components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/evp.h index 0f9f4035b..674951732 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/evp.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/evp.h @@ -1,19 +1,21 @@ /* evp.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ -/* evp.h defines mini evp openssl compatibility layer - * +/*! + \file wolfssl/openssl/evp.h + \brief evp.h defines mini evp openssl compatibility layer */ @@ -51,6 +53,7 @@ extern "C" { #endif + typedef char WOLFSSL_EVP_CIPHER; #ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ typedef char WOLFSSL_EVP_MD; @@ -58,6 +61,9 @@ typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; #define WOLFSSL_EVP_TYPE_DEFINED #endif +typedef WOLFSSL_EVP_PKEY EVP_PKEY; +typedef WOLFSSL_EVP_PKEY PKCS8_PRIV_KEY_INFO; + #ifndef NO_MD4 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void); #endif @@ -75,8 +81,10 @@ WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void); +#if !defined(NO_AES) && defined(HAVE_AES_CBC) WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void); +#endif WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void); @@ -112,6 +120,7 @@ typedef union { #endif } WOLFSSL_Hasher; +typedef struct WOLFSSL_EVP_PKEY_CTX WOLFSSL_EVP_PKEY_CTX; typedef struct WOLFSSL_EVP_MD_CTX { union { @@ -119,6 +128,7 @@ typedef struct WOLFSSL_EVP_MD_CTX { Hmac hmac; } hash; unsigned char macType; + WOLFSSL_EVP_PKEY_CTX *pctx; } WOLFSSL_EVP_MD_CTX; @@ -205,11 +215,11 @@ typedef struct WOLFSSL_EVP_CIPHER_CTX { int lastUsed; } WOLFSSL_EVP_CIPHER_CTX; -typedef struct WOLFSSL_EVP_PKEY_CTX { +struct WOLFSSL_EVP_PKEY_CTX { WOLFSSL_EVP_PKEY *pkey; int op; /* operation */ int padding; -} WOLFSSL_EVP_PKEY_CTX; +}; typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; @@ -255,12 +265,22 @@ WOLFSSL_API int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, WOLFSSL_API int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen); -#ifndef NO_MD5 +WOLFSSL_API int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, size_t cnt); +WOLFSSL_API int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + const unsigned char *sig, + size_t siglen); + + WOLFSSL_API int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER*, const WOLFSSL_EVP_MD*, const unsigned char*, const unsigned char*, int, int, unsigned char*, unsigned char*); -#endif WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx); @@ -327,6 +347,10 @@ WOLFSSL_API int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_get_cipherbynid(int); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_RSA(WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_RSA* key); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_EC_KEY(WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_EC_KEY* key); WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY *key); @@ -349,7 +373,11 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, const unsigned char *in, size_t inlen); WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx); WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void); +WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type); +WOLFSSL_API int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type); @@ -378,11 +406,14 @@ WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *ciph WOLFSSL_API unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher); WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher); WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags); WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *c, int pad); WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest); WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher); - +WOLFSSL_API void wolfSSL_EVP_cleanup(void); +WOLFSSL_API int wolfSSL_add_all_algorithms(void); +WOLFSSL_API int wolfSSL_OpenSSL_add_all_algorithms_noconf(void); WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char * pass, int passlen, const unsigned char * salt, @@ -459,15 +490,18 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_MD_CTX_type wolfSSL_EVP_MD_CTX_type #define EVP_MD_type wolfSSL_EVP_MD_type -#define EVP_DigestInit wolfSSL_EVP_DigestInit -#define EVP_DigestInit_ex wolfSSL_EVP_DigestInit_ex -#define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate -#define EVP_DigestFinal wolfSSL_EVP_DigestFinal -#define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex -#define EVP_DigestSignInit wolfSSL_EVP_DigestSignInit -#define EVP_DigestSignUpdate wolfSSL_EVP_DigestSignUpdate -#define EVP_DigestSignFinal wolfSSL_EVP_DigestSignFinal -#define EVP_BytesToKey wolfSSL_EVP_BytesToKey +#define EVP_DigestInit wolfSSL_EVP_DigestInit +#define EVP_DigestInit_ex wolfSSL_EVP_DigestInit_ex +#define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate +#define EVP_DigestFinal wolfSSL_EVP_DigestFinal +#define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex +#define EVP_DigestSignInit wolfSSL_EVP_DigestSignInit +#define EVP_DigestSignUpdate wolfSSL_EVP_DigestSignUpdate +#define EVP_DigestSignFinal wolfSSL_EVP_DigestSignFinal +#define EVP_DigestVerifyInit wolfSSL_EVP_DigestVerifyInit +#define EVP_DigestVerifyUpdate wolfSSL_EVP_DigestVerifyUpdate +#define EVP_DigestVerifyFinal wolfSSL_EVP_DigestVerifyFinal +#define EVP_BytesToKey wolfSSL_EVP_BytesToKey #define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname #define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname @@ -508,40 +542,54 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname #define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname -#define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA -#define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA -#define EVP_PKEY_set1_RSA wolfSSL_EVP_PKEY_set1_RSA -#define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY -#define EVP_PKEY_get0_hmac wolfSSL_EVP_PKEY_get0_hmac -#define EVP_PKEY_new_mac_key wolfSSL_EVP_PKEY_new_mac_key -#define EVP_MD_CTX_copy wolfSSL_EVP_MD_CTX_copy -#define EVP_MD_CTX_copy_ex wolfSSL_EVP_MD_CTX_copy_ex -#define EVP_PKEY_bits wolfSSL_EVP_PKEY_bits -#define EVP_PKEY_CTX_free wolfSSL_EVP_PKEY_CTX_free -#define EVP_PKEY_CTX_new wolfSSL_EVP_PKEY_CTX_new -#define EVP_PKEY_CTX_set_rsa_padding wolfSSL_EVP_PKEY_CTX_set_rsa_padding -#define EVP_PKEY_decrypt wolfSSL_EVP_PKEY_decrypt -#define EVP_PKEY_decrypt_init wolfSSL_EVP_PKEY_decrypt_init -#define EVP_PKEY_encrypt wolfSSL_EVP_PKEY_encrypt -#define EVP_PKEY_encrypt_init wolfSSL_EVP_PKEY_encrypt_init -#define EVP_PKEY_new wolfSSL_PKEY_new -#define EVP_PKEY_free wolfSSL_EVP_PKEY_free -#define EVP_PKEY_size wolfSSL_EVP_PKEY_size -#define EVP_SignFinal wolfSSL_EVP_SignFinal -#define EVP_SignInit wolfSSL_EVP_SignInit -#define EVP_SignUpdate wolfSSL_EVP_SignUpdate -#define EVP_VerifyFinal wolfSSL_EVP_VerifyFinal -#define EVP_VerifyInit wolfSSL_EVP_VerifyInit -#define EVP_VerifyUpdate wolfSSL_EVP_VerifyUpdate +#define EVP_PKEY_asign_RSA wolfSSL_EVP_PKEY_assign_RSA +#define EVP_PKEY_asign_EC_KEY wolfSSL_EVP_PKEY_assign_EC_KEY +#define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA +#define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA +#define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA +#define EVP_PKEY_set1_RSA wolfSSL_EVP_PKEY_set1_RSA +#define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY +#define EVP_PKEY_get0_hmac wolfSSL_EVP_PKEY_get0_hmac +#define EVP_PKEY_new_mac_key wolfSSL_EVP_PKEY_new_mac_key +#define EVP_MD_CTX_copy wolfSSL_EVP_MD_CTX_copy +#define EVP_MD_CTX_copy_ex wolfSSL_EVP_MD_CTX_copy_ex +#define EVP_PKEY_bits wolfSSL_EVP_PKEY_bits +#define EVP_PKEY_CTX_free wolfSSL_EVP_PKEY_CTX_free +#define EVP_PKEY_CTX_new wolfSSL_EVP_PKEY_CTX_new +#define EVP_PKEY_CTX_set_rsa_padding wolfSSL_EVP_PKEY_CTX_set_rsa_padding +#define EVP_PKEY_decrypt wolfSSL_EVP_PKEY_decrypt +#define EVP_PKEY_decrypt_init wolfSSL_EVP_PKEY_decrypt_init +#define EVP_PKEY_encrypt wolfSSL_EVP_PKEY_encrypt +#define EVP_PKEY_encrypt_init wolfSSL_EVP_PKEY_encrypt_init +#define EVP_PKEY_new wolfSSL_PKEY_new +#define EVP_PKEY_free wolfSSL_EVP_PKEY_free +#define EVP_PKEY_size wolfSSL_EVP_PKEY_size +#define EVP_PKEY_type wolfSSL_EVP_PKEY_type +#define EVP_PKEY_base_id wolfSSL_EVP_PKEY_base_id +#define EVP_PKEY_id wolfSSL_EVP_PKEY_id +#define EVP_SignFinal wolfSSL_EVP_SignFinal +#define EVP_SignInit wolfSSL_EVP_SignInit +#define EVP_SignUpdate wolfSSL_EVP_SignUpdate +#define EVP_VerifyFinal wolfSSL_EVP_VerifyFinal +#define EVP_VerifyInit wolfSSL_EVP_VerifyInit +#define EVP_VerifyUpdate wolfSSL_EVP_VerifyUpdate #define EVP_CIPHER_CTX_block_size wolfSSL_EVP_CIPHER_CTX_block_size #define EVP_CIPHER_block_size wolfSSL_EVP_CIPHER_block_size #define EVP_CIPHER_flags wolfSSL_EVP_CIPHER_flags #define EVP_CIPHER_CTX_set_flags wolfSSL_EVP_CIPHER_CTX_set_flags +#define EVP_CIPHER_CTX_clear_flags wolfSSL_EVP_CIPHER_CTX_clear_flags #define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding #define EVP_CIPHER_CTX_flags wolfSSL_EVP_CIPHER_CTX_flags #define EVP_add_digest wolfSSL_EVP_add_digest #define EVP_add_cipher wolfSSL_EVP_add_cipher +#define EVP_cleanup wolfSSL_EVP_cleanup + +#define OpenSSL_add_all_digests() wolfCrypt_Init() +#define OpenSSL_add_all_ciphers() wolfCrypt_Init() +#define OpenSSL_add_all_algorithms wolfSSL_add_all_algorithms +#define OpenSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf +#define wolfSSL_OPENSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf #define PKCS5_PBKDF2_HMAC_SHA1 wolfSSL_PKCS5_PBKDF2_HMAC_SHA1 diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h new file mode 100644 index 000000000..31702f7cc --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/hmac.h @@ -0,0 +1,85 @@ +/* hmac.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + + + +/* hmac.h defines mini hamc openssl compatibility layer + * + */ + + +#ifndef WOLFSSL_HMAC_H_ +#define WOLFSSL_HMAC_H_ + +#include + +#ifdef WOLFSSL_PREFIX +#include "prefix_hmac.h" +#endif + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +WOLFSSL_API unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, + const void* key, int key_len, + const unsigned char* d, int n, unsigned char* md, + unsigned int* md_len); + + +typedef struct WOLFSSL_HMAC_CTX { + Hmac hmac; + int type; + word32 save_ipad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 save_opad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; +} WOLFSSL_HMAC_CTX; + + +WOLFSSL_API int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, + WOLFSSL_HMAC_CTX* src); +WOLFSSL_LOCAL int wolfSSL_HmacCopy(Hmac* des, Hmac* src); +WOLFSSL_API int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, + int keylen, const EVP_MD* type); +WOLFSSL_API int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e); +WOLFSSL_API int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, + const unsigned char* data, int len); +WOLFSSL_API int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len); +WOLFSSL_API int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx); + +typedef struct WOLFSSL_HMAC_CTX HMAC_CTX; + +#define HMAC(a,b,c,d,e,f,g) wolfSSL_HMAC((a),(b),(c),(d),(e),(f),(g)) + +#define HMAC_CTX_init wolfSSL_HMAC_CTX_Init +#define HMAC_CTX_copy wolfSSL_HMAC_CTX_copy +#define HMAC_Init_ex wolfSSL_HMAC_Init_ex +#define HMAC_Init wolfSSL_HMAC_Init +#define HMAC_Update wolfSSL_HMAC_Update +#define HMAC_Final wolfSSL_HMAC_Final +#define HMAC_cleanup wolfSSL_HMAC_cleanup + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_HMAC_H_ */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/md5.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/md5.h new file mode 100644 index 000000000..8eab49a11 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/md5.h @@ -0,0 +1,68 @@ +/* md5.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* md5.h for openssl */ + + +#ifndef WOLFSSL_MD5_H_ +#define WOLFSSL_MD5_H_ + +#include + +#ifndef NO_MD5 + +#include + +#ifdef WOLFSSL_PREFIX +#include "prefix_md5.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef struct WOLFSSL_MD5_CTX { + void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; /* big enough to hold wolfcrypt md5, but check on init */ +} WOLFSSL_MD5_CTX; + +WOLFSSL_API int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*); +WOLFSSL_API int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*); + + +typedef WOLFSSL_MD5_CTX MD5_CTX; + +#define MD5_Init wolfSSL_MD5_Init +#define MD5_Update wolfSSL_MD5_Update +#define MD5_Final wolfSSL_MD5_Final + +#ifdef OPENSSL_EXTRA_BSD + #define MD5Init wolfSSL_MD5_Init + #define MD5Update wolfSSL_MD5_Update + #define MD5Final wolfSSL_MD5_Final +#endif + +#ifndef MD5 +#define MD5(d, n, md) wc_Md5Hash((d), (n), (md)) +#endif + +#define MD5_DIGEST_LENGTH MD5_DIGEST_SIZE + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ + +#endif /* WOLFSSL_MD5_H_ */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h new file mode 100644 index 000000000..9955bf38e --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/opensslv.h @@ -0,0 +1,33 @@ +/* opensslv.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* opensslv.h compatibility */ + +#ifndef WOLFSSL_OPENSSLV_H_ +#define WOLFSSL_OPENSSLV_H_ + + +/* api version compatibility */ +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* version number can be increased for Lighty after compatibility for ECDH + is added */ + #define OPENSSL_VERSION_NUMBER 0x10001000L +#else + #define OPENSSL_VERSION_NUMBER 0x0090810fL +#endif + +#define OPENSSL_VERSION_TEXT LIBWOLFSSL_VERSION_STRING + + +#endif /* header */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h similarity index 78% rename from components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h index a8ba08453..22dfcc571 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ripemd.h @@ -1,12 +1,13 @@ /* ripemd.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h new file mode 100644 index 000000000..1b406e50b --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/rsa.h @@ -0,0 +1,113 @@ +/* rsa.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* rsa.h for openSSL */ + + +#ifndef WOLFSSL_RSA_H_ +#define WOLFSSL_RSA_H_ + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Padding types */ +#define RSA_PKCS1_PADDING 0 +#define RSA_PKCS1_OAEP_PADDING 1 + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_RSA RSA; + +struct WOLFSSL_RSA { +#ifdef WC_RSA_BLINDING + WC_RNG* rng; /* for PrivateDecrypt blinding */ +#endif + WOLFSSL_BIGNUM* n; + WOLFSSL_BIGNUM* e; + WOLFSSL_BIGNUM* d; + WOLFSSL_BIGNUM* p; + WOLFSSL_BIGNUM* q; + WOLFSSL_BIGNUM* dmp1; /* dP */ + WOLFSSL_BIGNUM* dmq1; /* dQ */ + WOLFSSL_BIGNUM* iqmp; /* u */ + void* heap; + void* internal; /* our RSA */ + char inSet; /* internal set from external ? */ + char exSet; /* external set from internal ? */ + char ownRng; /* flag for if the rng should be free'd */ +}; + + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_new(void); +WOLFSSL_API void wolfSSL_RSA_free(WOLFSSL_RSA*); + +WOLFSSL_API int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA*, int bits, WOLFSSL_BIGNUM*, + void* cb); + +WOLFSSL_API int wolfSSL_RSA_blinding_on(WOLFSSL_RSA*, WOLFSSL_BN_CTX*); +WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, + unsigned char* out, WOLFSSL_RSA* rsa, int padding); + +WOLFSSL_API int wolfSSL_RSA_size(const WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_sign_ex(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA*, int); +WOLFSSL_API int wolfSSL_RSA_verify(int type, const unsigned char* m, + unsigned int mLen, const unsigned char* sig, + unsigned int sigLen, WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, + unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA*, const unsigned char*, int sz); +WOLFSSL_API int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA*, const unsigned char*, int sz, int opt); + +#define WOLFSSL_RSA_LOAD_PRIVATE 1 +#define WOLFSSL_RSA_LOAD_PUBLIC 2 +#define WOLFSSL_RSA_F4 0x10001L + +#define RSA_new wolfSSL_RSA_new +#define RSA_free wolfSSL_RSA_free + +#define RSA_generate_key_ex wolfSSL_RSA_generate_key_ex + +#define RSA_blinding_on wolfSSL_RSA_blinding_on +#define RSA_public_encrypt wolfSSL_RSA_public_encrypt +#define RSA_private_decrypt wolfSSL_RSA_private_decrypt +#define RSA_private_encrypt wolfSSL_RSA_private_encrypt + +#define RSA_size wolfSSL_RSA_size +#define RSA_sign wolfSSL_RSA_sign +#define RSA_verify wolfSSL_RSA_verify +#define RSA_public_decrypt wolfSSL_RSA_public_decrypt + +#define RSA_F4 WOLFSSL_RSA_F4 + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* header */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/sha.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/sha.h new file mode 100644 index 000000000..63bd5e723 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/sha.h @@ -0,0 +1,188 @@ +/* sha.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/* sha.h for openssl */ + + +#ifndef WOLFSSL_SHA_H_ +#define WOLFSSL_SHA_H_ + +#include +#include + +#ifdef WOLFSSL_PREFIX +#include "prefix_sha.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef struct WOLFSSL_SHA_CTX { + /* big enough to hold wolfcrypt Sha, but check on init */ + void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA_CTX; + +WOLFSSL_API int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_SHA_Final(unsigned char*, WOLFSSL_SHA_CTX*); + +/* SHA1 points to above, shouldn't use SHA0 ever */ +WOLFSSL_API int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_SHA1_Final(unsigned char*, WOLFSSL_SHA_CTX*); + +enum { + SHA_DIGEST_LENGTH = 20 +}; + + +typedef WOLFSSL_SHA_CTX SHA_CTX; + +#define SHA_Init wolfSSL_SHA_Init +#define SHA_Update wolfSSL_SHA_Update +#define SHA_Final wolfSSL_SHA_Final + +#define SHA1_Init wolfSSL_SHA1_Init +#define SHA1_Update wolfSSL_SHA1_Update +#define SHA1_Final wolfSSL_SHA1_Final + + +#ifdef WOLFSSL_SHA224 + +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any derefrence to those elements after casting to + * Sha224, is expected to also be 16 byte aligned addresses. */ +typedef struct WOLFSSL_SHA224_CTX { + /* big enough to hold wolfcrypt Sha224, but check on init */ + ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA224_CTX; + +WOLFSSL_API int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX*); +WOLFSSL_API int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA224_Final(unsigned char*, WOLFSSL_SHA224_CTX*); + +enum { + SHA224_DIGEST_LENGTH = 28 +}; + + +typedef WOLFSSL_SHA224_CTX SHA224_CTX; + +#define SHA224_Init wolfSSL_SHA224_Init +#define SHA224_Update wolfSSL_SHA224_Update +#define SHA224_Final wolfSSL_SHA224_Final + +#endif /* WOLFSSL_SHA224 */ + + +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any derefrence to those elements after casting to + * Sha256, is expected to also be 16 byte aligned addresses. */ +typedef struct WOLFSSL_SHA256_CTX { + /* big enough to hold wolfcrypt Sha256, but check on init */ + ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA256_CTX; + +WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); +WOLFSSL_API int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); + +enum { + SHA256_DIGEST_LENGTH = 32 +}; + + +typedef WOLFSSL_SHA256_CTX SHA256_CTX; + +#define SHA256_Init wolfSSL_SHA256_Init +#define SHA256_Update wolfSSL_SHA256_Update +#define SHA256_Final wolfSSL_SHA256_Final +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA256 is only available in non-fips mode because of SHA256 enum in FIPS + * build. */ + #define SHA256 wolfSSL_SHA256 +#endif + + +#ifdef WOLFSSL_SHA384 + +typedef struct WOLFSSL_SHA384_CTX { + /* big enough to hold wolfCrypt Sha384, but check on init */ + void* holder[(256 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA384_CTX; + +WOLFSSL_API int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX*); +WOLFSSL_API int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA384_Final(unsigned char*, WOLFSSL_SHA384_CTX*); + +enum { + SHA384_DIGEST_LENGTH = 48 +}; + + +typedef WOLFSSL_SHA384_CTX SHA384_CTX; + +#define SHA384_Init wolfSSL_SHA384_Init +#define SHA384_Update wolfSSL_SHA384_Update +#define SHA384_Final wolfSSL_SHA384_Final +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA384 is only available in non-fips mode because of SHA384 enum in FIPS + * build. */ + #define SHA384 wolfSSL_SHA384 +#endif +#endif /* WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 + +typedef struct WOLFSSL_SHA512_CTX { + /* big enough to hold wolfCrypt Sha384, but check on init */ + void* holder[(288 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA512_CTX; + +WOLFSSL_API int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*); +WOLFSSL_API int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA512_Final(unsigned char*, WOLFSSL_SHA512_CTX*); + +enum { + SHA512_DIGEST_LENGTH = 64 +}; + + +typedef WOLFSSL_SHA512_CTX SHA512_CTX; + +#define SHA512_Init wolfSSL_SHA512_Init +#define SHA512_Update wolfSSL_SHA512_Update +#define SHA512_Final wolfSSL_SHA512_Final +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA512 is only available in non-fips mode because of SHA512 enum in FIPS + * build. */ + #define SHA512 wolfSSL_SHA512 +#endif +#endif /* WOLFSSL_SHA512 */ + + + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_SHA_H_ */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h new file mode 100644 index 000000000..2fb088c81 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/openssl/ssl.h @@ -0,0 +1,971 @@ +/* ssl.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + + + +/* ssl.h defines wolfssl_openssl compatibility layer + * + */ + + +#ifndef WOLFSSL_OPENSSL_H_ +#define WOLFSSL_OPENSSL_H_ + +/* wolfssl_openssl compatibility layer */ +#ifndef OPENSSL_EXTRA_SSL_GUARD +#define OPENSSL_EXTRA_SSL_GUARD +#include +#endif /* OPENSSL_EXTRA_SSL_GUARD */ + +#include +#ifdef OPENSSL_EXTRA +#include +#endif + +#if defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef _WIN32 + /* wincrypt.h clashes */ + #undef X509_NAME +#endif + +#ifdef WOLFSSL_UTASKER + /* tcpip.h clashes */ + #undef ASN1_INTEGER +#endif + + +typedef WOLFSSL SSL; +typedef WOLFSSL_SESSION SSL_SESSION; +typedef WOLFSSL_METHOD SSL_METHOD; +typedef WOLFSSL_CTX SSL_CTX; + +typedef WOLFSSL_X509 X509; +typedef WOLFSSL_X509 X509_REQ; +typedef WOLFSSL_X509_NAME X509_NAME; +typedef WOLFSSL_X509_CHAIN X509_CHAIN; + +typedef WOLFSSL_STACK EXTENDED_KEY_USAGE; + + +/* redeclare guard */ +#define WOLFSSL_TYPES_DEFINED + +typedef WOLFSSL_BIO BIO; +typedef WOLFSSL_BIO_METHOD BIO_METHOD; +typedef WOLFSSL_CIPHER SSL_CIPHER; +typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; +typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; +typedef WOLFSSL_X509_CRL X509_CRL; +typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; +typedef WOLFSSL_ASN1_TIME ASN1_TIME; +typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; +typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; +typedef WOLFSSL_ASN1_STRING ASN1_STRING; +typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; +typedef WOLFSSL_BUF_MEM BUF_MEM; + +/* GENERAL_NAME and BASIC_CONSTRAINTS structs may need implemented as + * compatibility layer expands. For now treating them as an ASN1_OBJECT */ +typedef WOLFSSL_ASN1_OBJECT GENERAL_NAME; +typedef WOLFSSL_ASN1_OBJECT BASIC_CONSTRAINTS; + +#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME + +typedef WOLFSSL_COMP_METHOD COMP_METHOD; +typedef WOLFSSL_X509_REVOKED X509_REVOKED; +typedef WOLFSSL_X509_OBJECT X509_OBJECT; +typedef WOLFSSL_X509_STORE X509_STORE; +typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; + +#define EVP_CIPHER_INFO EncryptedInfo + +#define STACK_OF(x) WOLFSSL_STACK + +#define CRYPTO_free XFREE +#define CRYPTO_malloc XMALLOC +#define CRYPTO_EX_new WOLFSSL_CRYPTO_EX_new +#define CRYPTO_EX_dup WOLFSSL_CRYPTO_EX_dup +#define CRYPTO_EX_free WOLFSSL_CRYPTO_EX_free + +/* depreciated */ +#define CRYPTO_thread_id wolfSSL_thread_id +#define CRYPTO_set_id_callback wolfSSL_set_id_callback + +#define CRYPTO_LOCK 0x01 +#define CRYPTO_UNLOCK 0x02 +#define CRYPTO_READ 0x04 +#define CRYPTO_WRITE 0x08 + +#define CRYPTO_set_locking_callback wolfSSL_set_locking_callback +#define CRYPTO_set_dynlock_create_callback wolfSSL_set_dynlock_create_callback +#define CRYPTO_set_dynlock_lock_callback wolfSSL_set_dynlock_lock_callback +#define CRYPTO_set_dynlock_destroy_callback wolfSSL_set_dynlock_destroy_callback +#define CRYPTO_num_locks wolfSSL_num_locks +#define CRYPTO_dynlock_value WOLFSSL_dynlock_value + +#define CRYPTO_cleanup_all_ex_data wolfSSL_cleanup_all_ex_data + +/* this function was used to set the default malloc, free, and realloc */ +#define CRYPTO_malloc_init() /* CRYPTO_malloc_init is not needed */ + +#define SSL_get_client_random(ssl,out,outSz) \ + wolfSSL_get_client_random((ssl),(out),(outSz)) +#define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list_ex((ctx),(i)) +#define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) +#define SSL_get_shared_ciphers(ctx,buf,len) \ + wolfSSL_get_shared_ciphers((ctx),(buf),(len)) + +/* at the moment only returns ok */ +#define SSL_get_verify_result wolfSSL_get_verify_result +#define SSL_get_verify_mode wolfSSL_SSL_get_mode +#define SSL_get_verify_depth wolfSSL_get_verify_depth +#define SSL_CTX_get_verify_mode wolfSSL_CTX_get_verify_mode +#define SSL_CTX_get_verify_depth wolfSSL_CTX_get_verify_depth +#define SSL_get_certificate wolfSSL_get_certificate +#define SSL_use_certificate wolfSSL_use_certificate +#define SSL_use_certificate_ASN1 wolfSSL_use_certificate_ASN1 +#define d2i_PKCS8_PRIV_KEY_INFO_bio wolfSSL_d2i_PKCS8_PKEY_bio +#define d2i_PKCS8PrivateKey_bio wolfSSL_d2i_PKCS8PrivateKey_bio +#define PKCS8_PRIV_KEY_INFO_free wolfSSL_EVP_PKEY_free +#define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp + +#define d2i_PUBKEY wolfSSL_d2i_PUBKEY +#define d2i_PUBKEY_bio wolfSSL_d2i_PUBKEY_bio +#define d2i_PrivateKey wolfSSL_d2i_PrivateKey +#define d2i_AutoPrivateKey wolfSSL_d2i_AutoPrivateKey +#define SSL_use_PrivateKey wolfSSL_use_PrivateKey +#define SSL_use_PrivateKey_ASN1 wolfSSL_use_PrivateKey_ASN1 +#define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1 +#define SSL_get_privatekey wolfSSL_get_privatekey + +#define SSLv23_method wolfSSLv23_method +#define SSLv23_client_method wolfSSLv23_client_method +#define SSLv2_client_method wolfSSLv2_client_method +#define SSLv2_server_method wolfSSLv2_server_method +#define SSLv3_server_method wolfSSLv3_server_method +#define SSLv3_client_method wolfSSLv3_client_method +#define TLSv1_method wolfTLSv1_method +#define TLSv1_server_method wolfTLSv1_server_method +#define TLSv1_client_method wolfTLSv1_client_method +#define TLSv1_1_method wolfTLSv1_1_method +#define TLSv1_1_server_method wolfTLSv1_1_server_method +#define TLSv1_1_client_method wolfTLSv1_1_client_method +#define TLSv1_2_method wolfTLSv1_2_method +#define TLSv1_2_server_method wolfTLSv1_2_server_method +#define TLSv1_2_client_method wolfTLSv1_2_client_method +#define TLSv1_3_method wolfTLSv1_3_method +#define TLSv1_3_server_method wolfTLSv1_3_server_method +#define TLSv1_3_client_method wolfTLSv1_3_client_method + +#define X509_FILETYPE_ASN1 SSL_FILETYPE_ASN1 + +#ifdef WOLFSSL_DTLS + #define DTLSv1_client_method wolfDTLSv1_client_method + #define DTLSv1_server_method wolfDTLSv1_server_method + #define DTLSv1_2_client_method wolfDTLSv1_2_client_method + #define DTLSv1_2_server_method wolfDTLSv1_2_server_method +#endif + + +#ifndef NO_FILESYSTEM + #define SSL_CTX_use_certificate_file wolfSSL_CTX_use_certificate_file + #define SSL_CTX_use_PrivateKey_file wolfSSL_CTX_use_PrivateKey_file + #define SSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations + #define SSL_CTX_use_certificate_chain_file wolfSSL_CTX_use_certificate_chain_file + #define SSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file + + #define SSL_use_certificate_file wolfSSL_use_certificate_file + #define SSL_use_PrivateKey_file wolfSSL_use_PrivateKey_file + #define SSL_use_certificate_chain_file wolfSSL_use_certificate_chain_file + #define SSL_use_RSAPrivateKey_file wolfSSL_use_RSAPrivateKey_file +#endif + +#define SSL_CTX_new wolfSSL_CTX_new +#define SSL_new wolfSSL_new +#define SSL_set_fd wolfSSL_set_fd +#define SSL_get_fd wolfSSL_get_fd +#define SSL_connect wolfSSL_connect +#define SSL_clear wolfSSL_clear +#define SSL_state wolfSSL_state + +#define SSL_write wolfSSL_write +#define SSL_read wolfSSL_read +#define SSL_peek wolfSSL_peek +#define SSL_accept wolfSSL_accept +#define SSL_CTX_free wolfSSL_CTX_free +#define SSL_free wolfSSL_free +#define SSL_shutdown wolfSSL_shutdown + +#define SSL_CTX_set_quiet_shutdown wolfSSL_CTX_set_quiet_shutdown +#define SSL_set_quiet_shutdown wolfSSL_set_quiet_shutdown +#define SSL_get_error wolfSSL_get_error +#define SSL_set_session wolfSSL_set_session +#define SSL_get_session wolfSSL_get_session +#define SSL_flush_sessions wolfSSL_flush_sessions +/* assume unlimited temporarily */ +#define SSL_CTX_get_session_cache_mode(ctx) 0 + +#define SSL_CTX_set_verify wolfSSL_CTX_set_verify +#define SSL_set_verify wolfSSL_set_verify +#define SSL_pending wolfSSL_pending +#define SSL_load_error_strings wolfSSL_load_error_strings +#define SSL_library_init wolfSSL_library_init +#define SSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode +#define SSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list +#define SSL_set_cipher_list wolfSSL_set_cipher_list + +#define SSL_set_ex_data wolfSSL_set_ex_data +#define SSL_get_shutdown wolfSSL_get_shutdown +#define SSL_set_rfd wolfSSL_set_rfd +#define SSL_set_wfd wolfSSL_set_wfd +#define SSL_set_shutdown wolfSSL_set_shutdown +#define SSL_set_session_id_context wolfSSL_set_session_id_context +#define SSL_set_connect_state wolfSSL_set_connect_state +#define SSL_set_accept_state wolfSSL_set_accept_state +#define SSL_session_reused wolfSSL_session_reused +#define SSL_SESSION_free wolfSSL_SESSION_free +#define SSL_is_init_finished wolfSSL_is_init_finished + +#define SSL_get_version wolfSSL_get_version +#define SSL_get_current_cipher wolfSSL_get_current_cipher + +/* use wolfSSL_get_cipher_name for its return format */ +#define SSL_get_cipher wolfSSL_get_cipher_name +#define SSL_CIPHER_description wolfSSL_CIPHER_description +#define SSL_CIPHER_get_name wolfSSL_CIPHER_get_name +#define SSL_get1_session wolfSSL_get1_session + +#define SSL_get_keyblock_size wolfSSL_get_keyblock_size +#define SSL_get_keys wolfSSL_get_keys +#define SSL_SESSION_get_master_key wolfSSL_SESSION_get_master_key +#define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length + +#define DSA_dup_DH wolfSSL_DSA_dup_DH + +#define i2d_X509_bio wolfSSL_i2d_X509_bio +#define d2i_X509_bio wolfSSL_d2i_X509_bio +#define d2i_X509_fp wolfSSL_d2i_X509_fp +#define i2d_X509 wolfSSL_i2d_X509 +#define d2i_X509 wolfSSL_d2i_X509 +#define PEM_read_bio_X509 wolfSSL_PEM_read_bio_X509 +#define PEM_read_bio_X509_AUX wolfSSL_PEM_read_bio_X509_AUX +#define PEM_read_X509 wolfSSL_PEM_read_X509 +#define PEM_write_bio_X509 wolfSSL_PEM_write_bio_X509 +#define PEM_write_bio_X509_AUX wolfSSL_PEM_write_bio_X509_AUX + +#define i2d_X509_REQ wolfSSL_i2d_X509_REQ +#define X509_REQ_new wolfSSL_X509_REQ_new +#define X509_REQ_free wolfSSL_X509_REQ_free +#define X509_REQ_sign wolfSSL_X509_REQ_sign +#define X509_REQ_set_subject_name wolfSSL_X509_REQ_set_subject_name +#define X509_REQ_set_pubkey wolfSSL_X509_REQ_set_pubkey +#define PEM_write_bio_X509_REQ wolfSSL_PEM_write_bio_X509_REQ + +#define X509_new wolfSSL_X509_new +#define X509_free wolfSSL_X509_free +#define X509_load_certificate_file wolfSSL_X509_load_certificate_file +#define X509_digest wolfSSL_X509_digest +#define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i +#define X509_get_issuer_name wolfSSL_X509_get_issuer_name +#define X509_get_subject_name wolfSSL_X509_get_subject_name +#define X509_get_pubkey wolfSSL_X509_get_pubkey +#define X509_get_notBefore(cert) (ASN1_TIME*)wolfSSL_X509_notBefore((cert)) +#define X509_get_notAfter(cert) (ASN1_TIME*)wolfSSL_X509_notAfter((cert)) +#define X509_get_serialNumber wolfSSL_X509_get_serialNumber +#define X509_get0_pubkey_bitstr wolfSSL_X509_get0_pubkey_bitstr +#define X509_get_ex_new_index wolfSSL_X509_get_ex_new_index +#define X509_get_ex_data wolfSSL_X509_get_ex_data +#define X509_set_ex_data wolfSSL_X509_set_ex_data +#define X509_get1_ocsp wolfSSL_X509_get1_ocsp +#ifndef WOLFSSL_HAPROXY +#define X509_get_version wolfSSL_X509_get_version +#endif +#define X509_get_signature_nid wolfSSL_X509_get_signature_nid +#define X509_set_subject_name wolfSSL_X509_set_subject_name +#define X509_set_pubkey wolfSSL_X509_set_pubkey +#define X509_print wolfSSL_X509_print +#define X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string +#define X509_verify_cert wolfSSL_X509_verify_cert +#define X509_check_private_key wolfSSL_X509_check_private_key +#define X509_check_ca wolfSSL_X509_check_ca +#define X509_check_host wolfSSL_X509_check_host +#define X509_email_free wolfSSL_X509_email_free +#define X509_check_issued wolfSSL_X509_check_issued +#define X509_dup wolfSSL_X509_dup + +#define sk_X509_new wolfSSL_sk_X509_new +#define sk_X509_num wolfSSL_sk_X509_num +#define sk_X509_value wolfSSL_sk_X509_value +#define sk_X509_push wolfSSL_sk_X509_push +#define sk_X509_pop wolfSSL_sk_X509_pop +#define sk_X509_pop_free wolfSSL_sk_X509_pop_free +#define sk_X509_free wolfSSL_sk_X509_free + +#define i2d_X509_NAME wolfSSL_i2d_X509_NAME +#define X509_NAME_new wolfSSL_X509_NAME_new +#define X509_NAME_free wolfSSL_X509_NAME_free +#define X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID +#define X509_NAME_cmp wolfSSL_X509_NAME_cmp +#define X509_NAME_ENTRY_free wolfSSL_X509_NAME_ENTRY_free +#define X509_NAME_ENTRY_create_by_NID wolfSSL_X509_NAME_ENTRY_create_by_NID +#define X509_NAME_add_entry wolfSSL_X509_NAME_add_entry +#define X509_NAME_add_entry_by_txt wolfSSL_X509_NAME_add_entry_by_txt +#define X509_NAME_oneline wolfSSL_X509_NAME_oneline +#define X509_NAME_get_index_by_NID wolfSSL_X509_NAME_get_index_by_NID +#define X509_NAME_print_ex wolfSSL_X509_NAME_print_ex +#define X509_NAME_digest wolfSSL_X509_NAME_digest +#define X509_cmp_current_time wolfSSL_X509_cmp_current_time + +#define sk_X509_NAME_pop_free wolfSSL_sk_X509_NAME_pop_free +#define sk_X509_NAME_num wolfSSL_sk_X509_NAME_num +#define sk_X509_NAME_value wolfSSL_sk_X509_NAME_value + + typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; + +#define X509_NAME_entry_count wolfSSL_X509_NAME_entry_count +#define X509_NAME_ENTRY_get_object wolfSSL_X509_NAME_ENTRY_get_object +#define X509_NAME_get_entry wolfSSL_X509_NAME_get_entry +#define X509_NAME_ENTRY_get_data wolfSSL_X509_NAME_ENTRY_get_data +#define X509_NAME_ENTRY_get_object wolfSSL_X509_NAME_ENTRY_get_object + +#define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK +#define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL + +#define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME +#define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME +#define X509_CHECK_FLAG_NO_WILDCARDS WOLFSSL_NO_WILDCARDS + +#define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert +#define X509_STORE_CTX_set_verify_cb wolfSSL_X509_STORE_CTX_set_verify_cb +#define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new +#define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free +#define X509_STORE_CTX_get_chain wolfSSL_X509_STORE_CTX_get_chain +#define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error +#define X509_STORE_CTX_get_error_depth wolfSSL_X509_STORE_CTX_get_error_depth +#define X509_STORE_CTX_init wolfSSL_X509_STORE_CTX_init +#define X509_STORE_CTX_cleanup wolfSSL_X509_STORE_CTX_cleanup +#define X509_STORE_CTX_set_error wolfSSL_X509_STORE_CTX_set_error +#define X509_STORE_CTX_get_ex_data wolfSSL_X509_STORE_CTX_get_ex_data + +#define X509_STORE_new wolfSSL_X509_STORE_new +#define X509_STORE_free wolfSSL_X509_STORE_free +#define X509_STORE_add_lookup wolfSSL_X509_STORE_add_lookup +#define X509_STORE_add_cert wolfSSL_X509_STORE_add_cert +#define X509_STORE_add_crl wolfSSL_X509_STORE_add_crl +#define X509_STORE_set_flags wolfSSL_X509_STORE_set_flags +#define X509_STORE_get1_certs wolfSSL_X509_STORE_get1_certs +#define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject +#define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer +#define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time + +#define X509_LOOKUP_add_dir wolfSSL_X509_LOOKUP_add_dir +#define X509_LOOKUP_load_file wolfSSL_X509_LOOKUP_load_file +#define X509_LOOKUP_hash_dir wolfSSL_X509_LOOKUP_hash_dir +#define X509_LOOKUP_file wolfSSL_X509_LOOKUP_file + +#define d2i_X509_CRL wolfSSL_d2i_X509_CRL +#define d2i_X509_CRL_fp wolfSSL_d2i_X509_CRL_fp +#define PEM_read_X509_CRL wolfSSL_PEM_read_X509_CRL + +#define X509_CRL_free wolfSSL_X509_CRL_free +#define X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate +#define X509_CRL_get_nextUpdate wolfSSL_X509_CRL_get_nextUpdate +#define X509_CRL_verify wolfSSL_X509_CRL_verify +#define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED + +#define sk_X509_REVOKED_num wolfSSL_sk_X509_REVOKED_num +#define sk_X509_REVOKED_value wolfSSL_sk_X509_REVOKED_value + +#define X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents + +#define OCSP_parse_url wolfSSL_OCSP_parse_url + +#define MD4_Init wolfSSL_MD4_Init +#define MD4_Update wolfSSL_MD4_Update +#define MD4_Final wolfSSL_MD4_Final + +#define BIO_new wolfSSL_BIO_new +#define BIO_free wolfSSL_BIO_free +#define BIO_free_all wolfSSL_BIO_free_all +#define BIO_nread0 wolfSSL_BIO_nread0 +#define BIO_nread wolfSSL_BIO_nread +#define BIO_read wolfSSL_BIO_read +#define BIO_nwrite0 wolfSSL_BIO_nwrite0 +#define BIO_nwrite wolfSSL_BIO_nwrite +#define BIO_write wolfSSL_BIO_write +#define BIO_push wolfSSL_BIO_push +#define BIO_pop wolfSSL_BIO_pop +#define BIO_flush wolfSSL_BIO_flush +#define BIO_pending wolfSSL_BIO_pending + +#define BIO_get_mem_data wolfSSL_BIO_get_mem_data +#define BIO_new_mem_buf wolfSSL_BIO_new_mem_buf + +#define BIO_f_buffer wolfSSL_BIO_f_buffer +#define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size +#define BIO_f_ssl wolfSSL_BIO_f_ssl +#define BIO_new_socket wolfSSL_BIO_new_socket +#define SSL_set_bio wolfSSL_set_bio +#define BIO_eof wolfSSL_BIO_eof +#define BIO_set_ss wolfSSL_BIO_set_ss + +#define BIO_s_mem wolfSSL_BIO_s_mem +#define BIO_f_base64 wolfSSL_BIO_f_base64 +#define BIO_set_flags wolfSSL_BIO_set_flags + +#define SSLeay_add_ssl_algorithms wolfSSL_add_all_algorithms +#define SSLeay_add_all_algorithms wolfSSL_add_all_algorithms + +#define RAND_screen wolfSSL_RAND_screen +#define RAND_file_name wolfSSL_RAND_file_name +#define RAND_write_file wolfSSL_RAND_write_file +#define RAND_load_file wolfSSL_RAND_load_file +#define RAND_egd wolfSSL_RAND_egd +#define RAND_seed wolfSSL_RAND_seed +#define RAND_cleanup wolfSSL_RAND_Cleanup +#define RAND_add wolfSSL_RAND_add +#define RAND_poll wolfSSL_RAND_poll +#define RAND_status wolfSSL_RAND_status +#define RAND_bytes wolfSSL_RAND_bytes +#define RAND_pseudo_bytes wolfSSL_RAND_pseudo_bytes + +#define COMP_zlib wolfSSL_COMP_zlib +#define COMP_rle wolfSSL_COMP_rle +#define SSL_COMP_add_compression_method wolfSSL_COMP_add_compression_method + +#define SSL_get_ex_new_index wolfSSL_get_ex_new_index + + +typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; + +#define ASN1_TIME_adj wolfSSL_ASN1_TIME_adj +#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_TIME_to_generalizedtime wolfSSL_ASN1_TIME_to_generalizedtime +#define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print +#define ASN1_GENERALIZEDTIME_free wolfSSL_ASN1_GENERALIZEDTIME_free + +#define ASN1_tag2str wolfSSL_ASN1_tag2str + +#define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER +#define i2c_ASN1_INTEGER wolfSSL_i2c_ASN1_INTEGER +#define ASN1_INTEGER_new wolfSSL_ASN1_INTEGER_new +#define ASN1_INTEGER_free wolfSSL_ASN1_INTEGER_free +#define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp +#define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get +#define ASN1_INTEGER_to_BN wolfSSL_ASN1_INTEGER_to_BN + +#define ASN1_STRING_data wolfSSL_ASN1_STRING_data +#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data +#define ASN1_STRING_length wolfSSL_ASN1_STRING_length +#define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 +#define ASN1_STRING_print_ex wolfSSL_ASN1_STRING_print_ex + +#define ASN1_UTCTIME_pr wolfSSL_ASN1_UTCTIME_pr + +#define ASN1_IA5STRING WOLFSSL_ASN1_STRING + +#define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING + +#define SSL_load_client_CA_file wolfSSL_load_client_CA_file + +#define SSL_CTX_get_client_CA_list wolfSSL_SSL_CTX_get_client_CA_list +#define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list +#define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store +#define SSL_CTX_get_cert_store wolfSSL_CTX_get_cert_store +#define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx +#define SSL_get_ex_data wolfSSL_get_ex_data + +#define SSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata +#define SSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb + +#define SSL_CTX_set_timeout(ctx, to) \ + wolfSSL_CTX_set_timeout(ctx, (unsigned int) to) +#define SSL_CTX_set_info_callback wolfSSL_CTX_set_info_callback +#define SSL_CTX_set_alpn_protos wolfSSL_CTX_set_alpn_protos + +#define SSL_alert_type_string wolfSSL_alert_type_string +#define SSL_alert_desc_string wolfSSL_alert_desc_string +#define SSL_state_string wolfSSL_state_string + +#define RSA_free wolfSSL_RSA_free +#define RSA_generate_key wolfSSL_RSA_generate_key +#define SSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback + +#define PEM_def_callback wolfSSL_PEM_def_callback + +#define SSL_CTX_sess_accept wolfSSL_CTX_sess_accept +#define SSL_CTX_sess_connect wolfSSL_CTX_sess_connect +#define SSL_CTX_sess_accept_good wolfSSL_CTX_sess_accept_good +#define SSL_CTX_sess_connect_good wolfSSL_CTX_sess_connect_good +#define SSL_CTX_sess_accept_renegotiate wolfSSL_CTX_sess_accept_renegotiate +#define SSL_CTX_sess_connect_renegotiate wolfSSL_CTX_sess_connect_renegotiate +#define SSL_CTX_sess_hits wolfSSL_CTX_sess_hits +#define SSL_CTX_sess_cb_hits wolfSSL_CTX_sess_cb_hits +#define SSL_CTX_sess_cache_full wolfSSL_CTX_sess_cache_full +#define SSL_CTX_sess_misses wolfSSL_CTX_sess_misses +#define SSL_CTX_sess_timeouts wolfSSL_CTX_sess_timeouts +#define SSL_CTX_sess_number wolfSSL_CTX_sess_number +#define SSL_CTX_sess_get_cache_size wolfSSL_CTX_sess_get_cache_size + + +#define SSL_DEFAULT_CIPHER_LIST WOLFSSL_DEFAULT_CIPHER_LIST + +#define SSL_CTX_set_psk_client_callback wolfSSL_CTX_set_psk_client_callback +#define SSL_set_psk_client_callback wolfSSL_set_psk_client_callback + +#define SSL_get_psk_identity_hint wolfSSL_get_psk_identity_hint +#define SSL_get_psk_identity wolfSSL_get_psk_identity + +#define SSL_CTX_use_psk_identity_hint wolfSSL_CTX_use_psk_identity_hint +#define SSL_use_psk_identity_hint wolfSSL_use_psk_identity_hint + +#define SSL_CTX_set_psk_server_callback wolfSSL_CTX_set_psk_server_callback +#define SSL_set_psk_server_callback wolfSSL_set_psk_server_callback + +/* system file ints for ERR_put_error */ +#define SYS_F_ACCEPT WOLFSSL_SYS_ACCEPT +#define SYS_F_BIND WOLFSSL_SYS_BIND +#define SYS_F_CONNECT WOLFSSL_SYS_CONNECT +#define SYS_F_FOPEN WOLFSSL_SYS_FOPEN +#define SYS_F_FREAD WOLFSSL_SYS_FREAD +#define SYS_F_GETADDRINFO WOLFSSL_SYS_GETADDRINFO +#define SYS_F_GETSOCKOPT WOLFSSL_SYS_GETSOCKOPT +#define SYS_F_GETSOCKNAME WOLFSSL_SYS_GETSOCKNAME +#define SYS_F_OPENDIR WOLFSSL_SYS_OPENDIR +#define SYS_F_SETSOCKOPT WOLFSSL_SYS_SETSOCKOPT +#define SYS_F_SOCKET WOLFSSL_SYS_SOCKET +#define SYS_F_GETHOSTBYNAME WOLFSSL_SYS_GETHOSTBYNAME +#define SYS_F_GETNAMEINFO WOLFSSL_SYS_GETNAMEINFO +#define SYS_F_GETSERVBYNAME WOLFSSL_SYS_GETSERVBYNAME +#define SYS_F_IOCTLSOCKET WOLFSSL_SYS_IOCTLSOCKET +#define SYS_F_LISTEN WOLFSSL_SYS_LISTEN + +#define ERR_GET_REASON wolfSSL_ERR_GET_REASON + +#define ERR_put_error wolfSSL_ERR_put_error +#define ERR_peek_error wolfSSL_ERR_peek_error +#define ERR_peek_errors_fp wolfSSL_ERR_peek_errors_fp +#define ERR_peek_error_line_data wolfSSL_ERR_peek_error_line_data +#define ERR_peek_last_error wolfSSL_ERR_peek_last_error +#define ERR_peek_last_error_line wolfSSL_ERR_peek_last_error_line +#define ERR_get_error_line wolfSSL_ERR_get_error_line +#define ERR_get_error_line_data wolfSSL_ERR_get_error_line_data +#define ERR_get_error wolfSSL_ERR_get_error +#define ERR_print_errors_fp(file) wolfSSL_ERR_dump_errors_fp((file)) +#define ERR_clear_error wolfSSL_ERR_clear_error +#define ERR_free_strings wolfSSL_ERR_free_strings +#define ERR_remove_state wolfSSL_ERR_remove_state +#define ERR_remove_thread_state wolfSSL_ERR_remove_thread_state +#define ERR_error_string wolfSSL_ERR_error_string +#define ERR_error_string_n wolfSSL_ERR_error_string_n +#define ERR_reason_error_string wolfSSL_ERR_reason_error_string +#define ERR_load_BIO_strings wolfSSL_ERR_load_BIO_strings + +#define SSLv23_server_method wolfSSLv23_server_method +#define SSL_CTX_set_options wolfSSL_CTX_set_options +#define SSL_CTX_get_options wolfSSL_CTX_get_options +#define SSL_CTX_clear_options wolfSSL_CTX_clear_options + +#define SSL_CTX_check_private_key wolfSSL_CTX_check_private_key +#define SSL_check_private_key wolfSSL_check_private_key + +#define SSL_CTX_set_mode wolfSSL_CTX_set_mode +#define SSL_CTX_get_mode wolfSSL_CTX_get_mode +#define SSL_CTX_set_default_read_ahead wolfSSL_CTX_set_default_read_ahead + +#define SSL_CTX_sess_set_cache_size wolfSSL_CTX_sess_set_cache_size +#define SSL_CTX_set_default_verify_paths wolfSSL_CTX_set_default_verify_paths + +#define SSL_CTX_set_session_id_context wolfSSL_CTX_set_session_id_context +#define SSL_get_peer_certificate wolfSSL_get_peer_certificate +#define SSL_get_peer_cert_chain wolfSSL_get_peer_cert_chain + +#define SSL_want_read wolfSSL_want_read +#define SSL_want_write wolfSSL_want_write + +#define BIO_prf wolfSSL_BIO_prf + +#define sk_num wolfSSL_sk_num +#define sk_value wolfSSL_sk_value + +#define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio +#define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp + +#define d2i_RSAPublicKey wolfSSL_d2i_RSAPublicKey +#define d2i_RSAPrivateKey wolfSSL_d2i_RSAPrivateKey +#define i2d_RSAPrivateKey wolfSSL_i2d_RSAPrivateKey +#define i2d_RSAPublicKey wolfSSL_i2d_RSAPublicKey + +#define SSL_CTX_get_ex_data wolfSSL_CTX_get_ex_data +#define SSL_CTX_set_ex_data wolfSSL_CTX_set_ex_data +#define SSL_CTX_sess_set_get_cb wolfSSL_CTX_sess_set_get_cb +#define SSL_CTX_sess_set_new_cb wolfSSL_CTX_sess_set_new_cb +#define SSL_CTX_sess_set_remove_cb wolfSSL_CTX_sess_set_remove_cb + +#define i2d_SSL_SESSION wolfSSL_i2d_SSL_SESSION +#define d2i_SSL_SESSION wolfSSL_d2i_SSL_SESSION +#define SSL_SESSION_set_timeout wolfSSL_SSL_SESSION_set_timeout +#define SSL_SESSION_get_timeout wolfSSL_SESSION_get_timeout +#define SSL_SESSION_get_time wolfSSL_SESSION_get_time +#define SSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index +#define PEM_read wolfSSL_PEM_read +#define PEM_write wolfSSL_PEM_write +#define PEM_get_EVP_CIPHER_INFO wolfSSL_PEM_get_EVP_CIPHER_INFO +#define PEM_do_header wolfSSL_PEM_do_header + +/*#if OPENSSL_API_COMPAT < 0x10100000L*/ +#define CONF_modules_free() +#define ENGINE_cleanup() +#define HMAC_CTX_cleanup wolfSSL_HMAC_cleanup +#define SSL_CTX_need_tmp_RSA(ctx) 0 +#define SSL_CTX_set_tmp_rsa(ctx,rsa) 1 +#define SSL_need_tmp_RSA(ssl) 0 +#define SSL_set_tmp_rsa(ssl,rsa) 1 +/*#endif*/ + +#define CONF_modules_unload(a) + +#define SSL_get_hit wolfSSL_session_reused + +/* yassl had set the default to be 500 */ +#define SSL_get_default_timeout(ctx) 500 + +#define SSL_CTX_use_certificate wolfSSL_CTX_use_certificate +#define SSL_CTX_use_PrivateKey wolfSSL_CTX_use_PrivateKey +#define BIO_read_filename wolfSSL_BIO_read_filename +#define BIO_s_file wolfSSL_BIO_s_file +#define SSL_CTX_set_verify_depth wolfSSL_CTX_set_verify_depth +#define SSL_set_verify_depth wolfSSL_set_verify_depth +#define SSL_get_app_data wolfSSL_get_app_data +#define SSL_set_app_data wolfSSL_set_app_data +#define SHA1 wolfSSL_SHA1 + +#define SSL_dup_CA_list wolfSSL_dup_CA_list + +enum { + GEN_DNS = 0x02, /* ASN_DNS_TYPE */ + GEN_EMAIL = 0x01, /* ASN_RFC822_TYPE */ + GEN_URI = 0x06 /* ASN_URI_TYPE */ +}; + +#define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams +#define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_get_ciphers(x) wolfSSL_get_ciphers_compat(x) +#define SSL_SESSION_get_id wolfSSL_SESSION_get_id +#define SSL_get_cipher_bits(s,np) \ + wolfSSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +#define sk_SSL_CIPHER_num wolfSSL_sk_SSL_CIPHER_num +#define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero +#define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value +#endif /* OPENSSL_ALL || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) +#include + +typedef STACK_OF(WOLFSSL_ASN1_OBJECT) GENERAL_NAMES; +#define SSL_CTRL_CHAIN 88 +#define BIO_CTRL_WPENDING 13 +#define GEN_IPADD 7 +#define ERR_LIB_SSL 20 +#define SSL_R_SHORT_READ 10 +#define ERR_R_PEM_LIB 9 +#define V_ASN1_IA5STRING 22 +#define SSL_CTRL_MODE 33 + +#define SSL_CTX_clear_chain_certs(ctx) SSL_CTX_set0_chain(ctx,NULL) +#define d2i_RSAPrivateKey_bio wolfSSL_d2i_RSAPrivateKey_bio +#define SSL_CTX_use_RSAPrivateKey wolfSSL_CTX_use_RSAPrivateKey +#define d2i_PrivateKey_bio wolfSSL_d2i_PrivateKey_bio +#define BIO_new_bio_pair wolfSSL_BIO_new_bio_pair +#define SSL_get_verify_callback wolfSSL_get_verify_callback +#define GENERAL_NAMES_free(GENERAL_NAMES)NULL + +#define SSL_set_mode(ssl,op) wolfSSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) + +#define SSL_CTX_use_certificate_ASN1 wolfSSL_CTX_use_certificate_ASN1 +#define SSL_CTX_set0_chain(ctx,sk) \ + wolfSSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +#define SSL_CTX_get_app_data(ctx) wolfSSL_CTX_get_ex_data(ctx,0) +#define SSL_CTX_set_app_data(ctx,arg) wolfSSL_CTX_set_ex_data(ctx,0, \ + (char *)(arg)) +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + +#define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh + +#define BIO_new_file wolfSSL_BIO_new_file +#define BIO_ctrl wolfSSL_BIO_ctrl +#define BIO_ctrl_pending wolfSSL_BIO_ctrl_pending +#define BIO_wpending wolfSSL_BIO_wpending +#define BIO_get_mem_ptr wolfSSL_BIO_get_mem_ptr +#define BIO_int_ctrl wolfSSL_BIO_int_ctrl +#define BIO_reset wolfSSL_BIO_reset +#define BIO_s_file wolfSSL_BIO_s_file +#define BIO_s_bio wolfSSL_BIO_s_bio +#define BIO_s_socket wolfSSL_BIO_s_socket +#define BIO_set_fd wolfSSL_BIO_set_fd +#define BIO_ctrl_reset_read_request wolfSSL_BIO_ctrl_reset_read_request + +#define BIO_set_write_buf_size wolfSSL_BIO_set_write_buf_size +#define BIO_make_bio_pair wolfSSL_BIO_make_bio_pair + +#define BIO_set_fp wolfSSL_BIO_set_fp +#define BIO_get_fp wolfSSL_BIO_get_fp +#define BIO_seek wolfSSL_BIO_seek +#define BIO_write_filename wolfSSL_BIO_write_filename +#define BIO_set_mem_eof_return wolfSSL_BIO_set_mem_eof_return + +#define TLSEXT_STATUSTYPE_ocsp 1 + +#define SSL_set_options wolfSSL_set_options +#define SSL_get_options wolfSSL_get_options +#define SSL_clear_options wolfSSL_clear_options +#define SSL_set_tmp_dh wolfSSL_set_tmp_dh +#define SSL_clear_num_renegotiations wolfSSL_clear_num_renegotiations +#define SSL_total_renegotiations wolfSSL_total_renegotiations +#define SSL_set_tlsext_debug_arg wolfSSL_set_tlsext_debug_arg +#define SSL_set_tlsext_status_type wolfSSL_set_tlsext_status_type +#define SSL_set_tlsext_status_exts wolfSSL_set_tlsext_status_exts +#define SSL_get_tlsext_status_ids wolfSSL_get_tlsext_status_ids +#define SSL_set_tlsext_status_ids wolfSSL_set_tlsext_status_ids +#define SSL_get_tlsext_status_ocsp_res wolfSSL_get_tlsext_status_ocsp_resp +#define SSL_set_tlsext_status_ocsp_res wolfSSL_set_tlsext_status_ocsp_resp +#define SSL_set_tlsext_status_ocsp_resp wolfSSL_set_tlsext_status_ocsp_resp +#define SSL_get_tlsext_status_ocsp_resp wolfSSL_get_tlsext_status_ocsp_resp + +#define SSL_CTX_add_extra_chain_cert wolfSSL_CTX_add_extra_chain_cert +#define SSL_CTX_get_read_ahead wolfSSL_CTX_get_read_ahead +#define SSL_CTX_set_read_ahead wolfSSL_CTX_set_read_ahead +#define SSL_CTX_set_tlsext_status_arg wolfSSL_CTX_set_tlsext_status_arg +#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg \ + wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg +#define SSL_get_server_random wolfSSL_get_server_random + +#define SSL_get_tlsext_status_exts wolfSSL_get_tlsext_status_exts + +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130 +#define BIO_C_SET_WRITE_BUF_SIZE 136 +#define BIO_C_MAKE_BIO_PAIR 138 + +#define BIO_CTRL_RESET 1 +#define BIO_CTRL_INFO 3 +#define BIO_CTRL_FLUSH 11 +#define BIO_CLOSE 0x01 +#define BIO_FP_WRITE 0x04 + +#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 + +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_EXTRA_CHAIN_CERT 14 + +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#define SSL_CTRL_GET_READ_AHEAD 40 +#define SSL_CTRL_SET_READ_AHEAD 41 + +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 + +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 + +#define SSL_ctrl wolfSSL_ctrl +#define SSL_CTX_ctrl wolfSSL_CTX_ctrl + +#define SSL3_RANDOM_SIZE 32 /* same as RAN_LEN in internal.h */ +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(OPENSSL_EXTRA) \ + || defined(OPENSSL_ALL) +#include + +#define SSL2_VERSION 0x0002 +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define DTLS1_VERSION 0xFEFF +#define SSL23_ST_SR_CLNT_HELLO_A (0x210|0x2000) +#define SSL3_ST_SR_CLNT_HELLO_A (0x110|0x2000) +#define ASN1_STRFLGS_ESC_MSB 4 + +#define SSL_MAX_MASTER_KEY_LENGTH WOLFSSL_MAX_MASTER_KEY_LENGTH + +#define SSL_alert_desc_string_long wolfSSL_alert_desc_string_long +#define SSL_alert_type_string_long wolfSSL_alert_type_string_long +#define SSL_CIPHER_get_bits wolfSSL_CIPHER_get_bits +#define sk_GENERAL_NAME_num wolfSSL_sk_GENERAL_NAME_num +#define SSL_CTX_get_options wolfSSL_CTX_get_options + +#define SSL_CTX_flush_sessions wolfSSL_flush_sessions +#define SSL_CTX_add_session wolfSSL_CTX_add_session +#define SSL_version wolfSSL_version +#define SSL_get_state wolfSSL_get_state +#define SSL_state_string_long wolfSSL_state_string_long + +#define sk_GENERAL_NAME_value wolfSSL_sk_GENERAL_NAME_value +#define SSL_SESSION_get_ex_data wolfSSL_SESSION_get_ex_data +#define SSL_SESSION_set_ex_data wolfSSL_SESSION_set_ex_data +#define SSL_SESSION_get_ex_new_index wolfSSL_SESSION_get_ex_new_index +#define SSL_SESSION_get_id wolfSSL_SESSION_get_id +#define sk_GENERAL_NAME_pop_free wolfSSL_sk_GENERAL_NAME_pop_free +#define GENERAL_NAME_free NULL + +#define SSL3_AL_FATAL 2 +#define SSL_TLSEXT_ERR_OK 0 +#define SSL_TLSEXT_ERR_ALERT_FATAL alert_fatal +#define SSL_TLSEXT_ERR_NOACK alert_warning +#define TLSEXT_NAMETYPE_host_name WOLFSSL_SNI_HOST_NAME + +#define SSL_set_tlsext_host_name wolfSSL_set_tlsext_host_name +#define SSL_get_servername wolfSSL_get_servername +#define SSL_set_SSL_CTX wolfSSL_set_SSL_CTX +#define SSL_CTX_get_verify_callback wolfSSL_CTX_get_verify_callback +#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_tlsext_servername_callback +#define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg + +#define PSK_MAX_PSK_LEN 256 +#define PSK_MAX_IDENTITY_LEN 128 +#define SSL_CTX_clear_options wolfSSL_CTX_clear_options + + +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ +#define SSL_CTX_get_default_passwd_cb wolfSSL_CTX_get_default_passwd_cb +#define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata + +#define SSL_CTX_set_msg_callback wolfSSL_CTX_set_msg_callback +#define SSL_set_msg_callback wolfSSL_set_msg_callback +#define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg +#define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg + + +/* Nginx uses this to determine if reached end of certs in file. + * PEM_read_bio_X509 is called and the return error is lost. + * The error that needs to be detected is: SSL_NO_PEM_HEADER. + */ +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define PEM_R_NO_START_LINE 108 +#define ERR_LIB_PEM 9 +#define ERR_LIB_X509 10 + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_ALL) || \ + defined(HAVE_LIGHTY) + +#include + +#define OPENSSL_STRING WOLFSSL_STRING + +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + +/* Nginx checks these to see if the error was a handshake error. */ +#define SSL_R_BAD_CHANGE_CIPHER_SPEC LENGTH_ERROR +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG BUFFER_E +#define SSL_R_DIGEST_CHECK_FAILED VERIFY_MAC_ERROR +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST SUITES_ERROR +#define SSL_R_EXCESSIVE_MESSAGE_SIZE BUFFER_ERROR +#define SSL_R_LENGTH_MISMATCH LENGTH_ERROR +#define SSL_R_NO_CIPHERS_SPECIFIED SUITES_ERROR +#define SSL_R_NO_COMPRESSION_SPECIFIED COMPRESSION_ERROR +#define SSL_R_NO_SHARED_CIPHER MATCH_SUITE_ERROR +#define SSL_R_RECORD_LENGTH_MISMATCH HANDSHAKE_SIZE_ERROR +#define SSL_R_UNEXPECTED_MESSAGE OUT_OF_ORDER_E +#define SSL_R_UNEXPECTED_RECORD SANITY_MSG_E +#define SSL_R_UNKNOWN_ALERT_TYPE BUFFER_ERROR +#define SSL_R_UNKNOWN_PROTOCOL VERSION_ERROR +#define SSL_R_WRONG_VERSION_NUMBER VERSION_ERROR +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC ENCRYPT_ERROR +#define SSL_R_HTTPS_PROXY_REQUEST PARSE_ERROR +#define SSL_R_HTTP_REQUEST PARSE_ERROR +#define SSL_R_UNSUPPORTED_PROTOCOL VERSION_ERROR + + +#ifdef HAVE_SESSION_TICKET +#define SSL_OP_NO_TICKET SSL_OP_NO_TICKET +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +#endif + +#define OPENSSL_config wolfSSL_OPENSSL_config +#define OPENSSL_memdup wolfSSL_OPENSSL_memdup +#define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout +#define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh +#define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_in_init wolfSSL_SSL_in_init +#define SSL_get0_session wolfSSL_SSL_get0_session +#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb +#define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb +#define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value +#define SSL_get0_alpn_selected wolfSSL_get0_alpn_selected +#define SSL_select_next_proto wolfSSL_select_next_proto +#define SSL_CTX_set_alpn_select_cb wolfSSL_CTX_set_alpn_select_cb +#define SSL_CTX_set_next_protos_advertised_cb wolfSSL_CTX_set_next_protos_advertised_cb +#define SSL_CTX_set_next_proto_select_cb wolfSSL_CTX_set_next_proto_select_cb +#define SSL_get0_next_proto_negotiated wolfSSL_get0_next_proto_negotiated +#define SSL_is_server wolfSSL_is_server +#define SSL_CTX_set1_curves_list wolfSSL_CTX_set1_curves_list + +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || WOLFSSL_MYSQL_COMPATIBLE || + OPENSSL_ALL || HAVE_LIGHTY */ + +#ifdef OPENSSL_EXTRA +#define SSL_CTX_add_client_CA wolfSSL_CTX_add_client_CA +#define SSL_CTX_set_srp_password wolfSSL_CTX_set_srp_password +#define SSL_CTX_set_srp_username wolfSSL_CTX_set_srp_username +#define SSL_get_SSL_CTX wolfSSL_get_SSL_CTX + +#define ERR_NUM_ERRORS 16 +#define EVP_PKEY_RSA 6 +#define EVP_PKEY_RSA2 19 +#define SN_pkcs9_emailAddress "Email" +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress 1L,2L,840L,113539L,1L,9L,1L + +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#endif /* OPENSSL_EXTRA */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* wolfSSL_openssl_h__ */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/ssl.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/ssl.h new file mode 100644 index 000000000..fffefc82a --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/ssl.h @@ -0,0 +1,3065 @@ +/* ssl.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + +/*! + \file ../wolfssl/ssl.h + \brief Header file containing key wolfSSL API +*/ + +/* wolfSSL API */ + +#ifndef WOLFSSL_SSL_H +#define WOLFSSL_SSL_H + + +/* for users not using preprocessor flags*/ +#include +#include +#include +#include + +#ifdef HAVE_WOLF_EVENT + #include +#endif + +#ifndef NO_FILESYSTEM + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #endif +#endif + +#ifdef WOLFSSL_PREFIX + #include "prefix_ssl.h" +#endif + +#ifdef LIBWOLFSSL_VERSION_STRING + #define WOLFSSL_VERSION LIBWOLFSSL_VERSION_STRING +#endif + +#ifdef _WIN32 + /* wincrypt.h clashes */ + #undef OCSP_REQUEST + #undef OCSP_RESPONSE +#endif + +#ifdef OPENSSL_COEXIST + /* mode to allow wolfSSL and OpenSSL to exist together */ + #ifdef TEST_OPENSSL_COEXIST + /* + ./configure --enable-opensslcoexist \ + CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \ + LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto" + */ + #include + #include + #include + #include + #include + #include + #endif + + /* make sure old names are disabled */ + #ifndef NO_OLD_SSL_NAMES + #define NO_OLD_SSL_NAMES + #endif + #ifndef NO_OLD_WC_NAMES + #define NO_OLD_WC_NAMES + #endif + +#elif (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #include + #include + + /* We need the old SSL names */ + #ifdef NO_OLD_SSL_NAMES + #undef NO_OLD_SSL_NAMES + #endif + #ifdef NO_OLD_WC_NAMES + #undef NO_OLD_WC_NAMES + #endif +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED +typedef struct WOLFSSL WOLFSSL; +#endif +typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; +typedef struct WOLFSSL_METHOD WOLFSSL_METHOD; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif + +typedef struct WOLFSSL_STACK WOLFSSL_STACK; +typedef struct WOLFSSL_X509 WOLFSSL_X509; +typedef struct WOLFSSL_X509_NAME WOLFSSL_X509_NAME; +typedef struct WOLFSSL_X509_NAME_ENTRY WOLFSSL_X509_NAME_ENTRY; +typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; +typedef struct WC_PKCS12 WOLFSSL_X509_PKCS12; + +typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; +typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; +typedef struct WOLFSSL_CRL WOLFSSL_CRL; + +typedef void *WOLFSSL_X509_STORE_CTX_verify_cb; /* verify callback */ + +/* redeclare guard */ +#define WOLFSSL_TYPES_DEFINED + +#include + + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + +typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER; +typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP; +typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD; +typedef struct WOLFSSL_CRL WOLFSSL_X509_CRL; +typedef struct WOLFSSL_X509_STORE WOLFSSL_X509_STORE; +typedef struct WOLFSSL_X509_VERIFY_PARAM WOLFSSL_X509_VERIFY_PARAM; +typedef struct WOLFSSL_BIO WOLFSSL_BIO; +typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; +typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; +typedef struct WOLFSSL_ASN1_TIME WOLFSSL_ASN1_TIME; +typedef struct WOLFSSL_ASN1_INTEGER WOLFSSL_ASN1_INTEGER; +typedef struct WOLFSSL_ASN1_OBJECT WOLFSSL_ASN1_OBJECT; + +typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; +typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; +typedef struct WOLFSSL_DH WOLFSSL_DH; +typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; + +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME + +#define WOLFSSL_ASN1_INTEGER_MAX 20 +struct WOLFSSL_ASN1_INTEGER { + /* size can be increased set at 20 for tag, length then to hold at least 16 + * byte type */ + unsigned char intData[WOLFSSL_ASN1_INTEGER_MAX]; + /* ASN_INTEGER | LENGTH | hex of number */ + unsigned char negative; /* negative number flag */ + + unsigned char* data; + unsigned int dataMax; /* max size of data buffer */ + unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ +}; + +struct WOLFSSL_ASN1_TIME { + /* MAX_DATA_SIZE is 32 */ + unsigned char data[32 + 2]; + /* ASN_TIME | LENGTH | date bytes */ +}; + +struct WOLFSSL_ASN1_STRING { + int length; + int type; /* type of string i.e. CTC_UTF8 */ + char* data; + long flags; +}; + +#define WOLFSSL_MAX_SNAME 40 +struct WOLFSSL_ASN1_OBJECT { + void* heap; + const unsigned char* obj; + /* sName is short name i.e sha256 rather than oid (null terminated) */ + char sName[WOLFSSL_MAX_SNAME]; + int type; /* oid */ + int grp; /* type of OID, i.e. oidCertPolicyType */ + int nid; + unsigned int objSz; + unsigned char dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */ + #define WOLFSSL_ASN1_DYNAMIC 0x1 + #define WOLFSSL_ASN1_DYNAMIC_DATA 0x2 + struct d { /* derefrenced */ + WOLFSSL_ASN1_STRING ia5_internal; + WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */ + WOLFSSL_ASN1_STRING* dNSName; + WOLFSSL_ASN1_STRING* iPAddress; + } d; +}; + +struct WOLFSSL_EVP_PKEY { + void* heap; + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; /* der format of key / or raw for NTRU */ + } pkey; + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #ifndef NO_RSA + WOLFSSL_RSA* rsa; + byte ownRsa; /* if struct owns RSA and should free it */ + #endif + #ifdef HAVE_ECC + WOLFSSL_EC_KEY* ecc; + byte ownEcc; /* if struct owns ECC and should free it */ + #endif + WC_RNG rng; + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + #ifdef HAVE_ECC + int pkey_curve; + #endif +}; +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO; + +#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +typedef char WOLFSSL_EVP_MD; +#define WOLFSSL_EVP_TYPE_DEFINED +#endif + +#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */ + + +enum BIO_TYPE { + WOLFSSL_BIO_BUFFER = 1, + WOLFSSL_BIO_SOCKET = 2, + WOLFSSL_BIO_SSL = 3, + WOLFSSL_BIO_MEMORY = 4, + WOLFSSL_BIO_BIO = 5, + WOLFSSL_BIO_FILE = 6, + WOLFSSL_BIO_BASE64 = 7 +}; + +enum BIO_FLAGS { + WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01, + WOLFSSL_BIO_FLAG_READ = 0x02, + WOLFSSL_BIO_FLAG_WRITE = 0x04, + WOLFSSL_BIO_FLAG_IO_SPECIAL = 0x08, + WOLFSSL_BIO_FLAG_RETRY = 0x10 +}; + +typedef struct WOLFSSL_BUF_MEM { + char* data; /* dereferenced */ + size_t length; /* current length */ + size_t max; /* maximum length */ +} WOLFSSL_BUF_MEM; + +typedef struct WOLFSSL_COMP_METHOD { + int type; /* stunnel dereference */ +} WOLFSSL_COMP_METHOD; + +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; + +struct WOLFSSL_X509_LOOKUP { + WOLFSSL_X509_STORE *store; +}; + +struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ + WOLFSSL_CERT_MANAGER* cm; + WOLFSSL_X509_LOOKUP lookup; +#ifdef OPENSSL_EXTRA + int isDynamic; +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) + WOLFSSL_X509_CRL *crl; +#endif +}; + +#ifdef OPENSSL_EXTRA +#define WOLFSSL_USE_CHECK_TIME 0x2 +#define WOLFSSL_NO_CHECK_TIME 0x200000 +#define WOLFSSL_NO_WILDCARDS 0x4 +struct WOLFSSL_X509_VERIFY_PARAM { + time_t check_time; + unsigned long flags; +}; +#endif + +typedef struct WOLFSSL_ALERT { + int code; + int level; +} WOLFSSL_ALERT; + +typedef struct WOLFSSL_ALERT_HISTORY { + WOLFSSL_ALERT last_rx; + WOLFSSL_ALERT last_tx; +} WOLFSSL_ALERT_HISTORY; + +typedef struct WOLFSSL_X509_REVOKED { + WOLFSSL_ASN1_INTEGER* serialNumber; /* stunnel dereference */ +} WOLFSSL_X509_REVOKED; + + +typedef struct WOLFSSL_X509_OBJECT { + union { + char* ptr; + WOLFSSL_X509 *x509; + WOLFSSL_X509_CRL* crl; /* stunnel dereference */ + } data; +} WOLFSSL_X509_OBJECT; + +typedef struct WOLFSSL_BUFFER_INFO { + unsigned char* buffer; + unsigned int length; +} WOLFSSL_BUFFER_INFO; + +typedef struct WOLFSSL_X509_STORE_CTX { + WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ + WOLFSSL_X509* current_cert; /* current X509 (OPENSSL_EXTRA) */ +#ifdef WOLFSSL_ASIO + WOLFSSL_X509* current_issuer; /* asio dereference */ +#endif + WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */ + WOLFSSL_STACK* chain; +#ifdef OPENSSL_EXTRA + WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ +#endif + char* domain; /* subject CN domain name */ + void* ex_data; /* external data, for fortress build */ + void* userCtx; /* user ctx */ + int error; /* current error */ + int error_depth; /* index of cert depth for this error */ + int discardSessionCerts; /* so verify callback can flag for discard */ + int totalCerts; /* number of peer cert buffers */ + WOLFSSL_BUFFER_INFO* certs; /* peer certs */ + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */ +} WOLFSSL_X509_STORE_CTX; + +typedef char* WOLFSSL_STRING; + +/* Valid Alert types from page 16/17 + * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c + */ +enum AlertDescription { + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + record_overflow = 22, + decompression_failure = 30, + handshake_failure = 40, + no_certificate = 41, + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47, + decode_error = 50, + decrypt_error = 51, + #ifdef WOLFSSL_MYSQL_COMPATIBLE + /* catch name conflict for enum protocol with MYSQL build */ + wc_protocol_version = 70, + #else + protocol_version = 70, + #endif + no_renegotiation = 100, + unsupported_extension = 110, /**< RFC 5246, section 7.2.2 */ + unrecognized_name = 112, /**< RFC 6066, section 3 */ + bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ + unknown_psk_identity = 115, /**< RFC 4279, section 2 */ + no_application_protocol = 120 +}; + + +enum AlertLevel { + alert_warning = 1, + alert_fatal = 2 +}; + +/* Maximum master key length (SECRET_LEN) */ +#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 +/* Maximum number of groups that can be set */ +#define WOLFSSL_MAX_GROUP_COUNT 10 + +typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); + +/* CTX Method EX Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap); +#endif + +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); + +#ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap); +#endif + +/* CTX Method Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void); +#endif + +#ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void); +#endif + +#ifdef HAVE_POLY1305 + WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int); +#endif + +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS + +#ifndef WOLFSSL_DTLS_EXPORT_TYPES +typedef int (*wc_dtls_export)(WOLFSSL* ssl, + unsigned char* exportBuffer, unsigned int sz, void* userCtx); +#define WOLFSSL_DTLS_EXPORT_TYPES +#endif /* WOLFSSL_DTLS_EXPORT_TYPES */ + +WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, + unsigned int sz); +WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, + wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + +#ifdef WOLFSSL_STATIC_MEMORY +#ifndef WOLFSSL_MEM_GUARD +#define WOLFSSL_MEM_GUARD + typedef struct WOLFSSL_MEM_STATS WOLFSSL_MEM_STATS; + typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS; +#endif +WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, + wolfSSL_method_func method, + unsigned char* buf, unsigned int sz, + int flag, int max); +WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, + WOLFSSL_MEM_STATS* mem_stats); +WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl, + WOLFSSL_MEM_CONN_STATS* mem_stats); +#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + +WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); + +#define WOLFSSL_LOAD_FLAG_NONE 0x00000000 +#define WOLFSSL_LOAD_FLAG_IGNORE_ERR 0x00000001 +#define WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY 0x00000002 +#define WOLFSSL_LOAD_FLAG_PEM_CA_ONLY 0x00000004 +WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX*, const char*, + const char*, unsigned int); +WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, + const char*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int); +#endif +WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *, + const char *file); +WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *, + const char *file, int format); +WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); + +WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl); +WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int); +WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int); +WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, const char *file); +WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*, + const char *file, int format); +WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); + +#ifdef WOLFSSL_DER_LOAD + WOLFSSL_API int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX*, + const char*, int); +#endif + +#ifdef HAVE_NTRU + WOLFSSL_API int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX*, const char*); + /* load NTRU private key blob */ +#endif + +#endif /* !NO_FILESYSTEM && !NO_CERTS */ + +WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); +WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_is_server(WOLFSSL*); +WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); +WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int); +WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); +WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority); +WOLFSSL_API int wolfSSL_get_ciphers(char*, int); +WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, + const unsigned char); +WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, + int len); +WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); +/* please see note at top of README if you get an error from connect */ +WOLFSSL_API int wolfSSL_connect(WOLFSSL*); +WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); +WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); +WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int); +WOLFSSL_API int wolfSSL_accept(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, + const unsigned char* secret, unsigned int secretSz); +WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); + +WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); +WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); + +#ifdef WOLFSSL_EARLY_DATA +WOLFSSL_API int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, + unsigned int sz); +WOLFSSL_API int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz); +WOLFSSL_API int wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*); +WOLFSSL_API int wolfSSL_read_early_data(WOLFSSL*, void*, int, int*); +#endif +#endif +WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); +WOLFSSL_API void wolfSSL_free(WOLFSSL*); +WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); +WOLFSSL_API int wolfSSL_send(WOLFSSL*, const void*, int sz, int flags); +WOLFSSL_API int wolfSSL_recv(WOLFSSL*, void*, int sz, int flags); + +WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int); +WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int); + +WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *); + +WOLFSSL_API int wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*); +WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long); +WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) +WOLFSSL_API int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t, + WOLFSSL_BIO**, size_t); + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**); +WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*, + int, const unsigned char*); +WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**); +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + +#ifdef SESSION_INDEX +WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session); +#endif /* SESSION_INDEX */ + +#if defined(SESSION_INDEX) && defined(SESSION_CERTS) +WOLFSSL_API + WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session); +#endif /* SESSION_INDEX && SESSION_CERTS */ + +typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); +#ifdef OPENSSL_EXTRA +typedef void (CallbackInfoState)(const WOLFSSL*, int, int); + +typedef struct WOLFSSL_CRYPTO_EX_DATA { + WOLFSSL_STACK* data; +} WOLFSSL_CRYPTO_EX_DATA; + +typedef int (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); +typedef int (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out, + WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg); +typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); + +WOLFSSL_API int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b, + WOLFSSL_CRYPTO_EX_free* c); +#endif + +WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, + VerifyCallback verify_callback); +WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback); +WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*); + +WOLFSSL_API int wolfSSL_pending(WOLFSSL*); + +WOLFSSL_API void wolfSSL_load_error_strings(void); +WOLFSSL_API int wolfSSL_library_init(void); +WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, long); + +#ifdef HAVE_SECRET_CALLBACK +typedef int (*SessionSecretCb)(WOLFSSL* ssl, + void* secret, int* secretSz, void* ctx); +WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, void*); +#endif /* HAVE_SECRET_CALLBACK */ + +/* session cache persistence */ +WOLFSSL_API int wolfSSL_save_session_cache(const char*); +WOLFSSL_API int wolfSSL_restore_session_cache(const char*); +WOLFSSL_API int wolfSSL_memsave_session_cache(void*, int); +WOLFSSL_API int wolfSSL_memrestore_session_cache(const void*, int); +WOLFSSL_API int wolfSSL_get_session_cache_memsize(void); + +/* certificate cache persistence, uses ctx since certs are per ctx */ +WOLFSSL_API int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX*, void*, int, int*); +WOLFSSL_API int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX*, const void*, int); +WOLFSSL_API int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX*); + +/* only supports full name from cipher_name[] delimited by : */ +WOLFSSL_API int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_set_cipher_list(WOLFSSL*, const char*); + +/* Nonblocking DTLS helper functions */ +WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*); +#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock +#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock + /* The old names are deprecated. */ +WOLFSSL_API int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int); +WOLFSSL_API int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int); +WOLFSSL_API int wolfSSL_dtls_got_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_dtls(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int); +WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*); + +WOLFSSL_API int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); +WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); + +WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*, + unsigned int*, unsigned int*); +WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, + const unsigned char*, unsigned int, + const unsigned char*, const unsigned char*, + const unsigned char*); +WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); +WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +WOLFSSL_API int wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_mcast_get_max_peers(void); +typedef int (*CallbackMcastHighwater)(unsigned short peerId, + unsigned int maxSeq, + unsigned int curSeq, void* ctx); +WOLFSSL_API int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*, + unsigned int, + unsigned int, + unsigned int, + CallbackMcastHighwater); +WOLFSSL_API int wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*); + +WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); +WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); +WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, + unsigned long sz); +WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); + +/* extras */ + +#ifndef WOLF_STACK_OF + #define WOLF_STACK_OF(x) WOLFSSL_STACK +#endif +#ifndef DECLARE_STACK_OF + #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x); +#endif + +WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + WOLFSSL_X509* x509); +WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value( + WOLFSSL_STACK* sk, int i); +WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, + void f (WOLFSSL_ASN1_OBJECT*)); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); +WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); + +WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); +WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); +WOLFSSL_API int wolfSSL_set_rfd(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_wfd(WOLFSSL*, int); +WOLFSSL_API void wolfSSL_set_shutdown(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*, + unsigned int); +WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*); +WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*); +WOLFSSL_API int wolfSSL_session_reused(WOLFSSL*); +WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); +WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); + +WOLFSSL_API const char* wolfSSL_get_version(WOLFSSL*); +WOLFSSL_API int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL*); +WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); +WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); +WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); + /* what's ref count */ + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); + +WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, + char** path, int* ssl); + +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void); +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void); +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void); + +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*); +WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type); +WOLFSSL_API int wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int); +WOLFSSL_API int wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_flush(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_pending(WOLFSSL_BIO*); + +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void); +WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size); +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int flag); +WOLFSSL_API int wolfSSL_BIO_eof(WOLFSSL_BIO*); + +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void); +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); +WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); + +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); + + +WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); +WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag); +WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); + +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +#endif + +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); + +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); + +WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); +WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); +WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b); +WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf); +WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); + +WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); +WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); +WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); + +WOLFSSL_API void wolfSSL_RAND_screen(void); +WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long); +WOLFSSL_API int wolfSSL_RAND_write_file(const char*); +WOLFSSL_API int wolfSSL_RAND_load_file(const char*, long); +WOLFSSL_API int wolfSSL_RAND_egd(const char*); +WOLFSSL_API int wolfSSL_RAND_seed(const void*, int); +WOLFSSL_API void wolfSSL_RAND_Cleanup(void); +WOLFSSL_API void wolfSSL_RAND_add(const void*, int, double); +WOLFSSL_API int wolfSSL_RAND_poll(void); + +WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void); +WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void); +WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*); + +WOLFSSL_API unsigned long wolfSSL_thread_id(void); +WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void)); +WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, + int)); +WOLFSSL_API void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f) + (const char*, int)); +WOLFSSL_API void wolfSSL_set_dynlock_lock_callback(void (*f)(int, + WOLFSSL_dynlock_value*, const char*, int)); +WOLFSSL_API void wolfSSL_set_dynlock_destroy_callback(void (*f) + (WOLFSSL_dynlock_value*, const char*, int)); +WOLFSSL_API int wolfSSL_num_locks(void); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( + WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*); + +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); +WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, + unsigned char** out); +WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int); +WOLFSSL_API int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int); +WOLFSSL_API int wolfSSL_X509_get_isCA(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509*); +WOLFSSL_API unsigned int wolfSSL_X509_get_pathLength(WOLFSSL_X509*); +WOLFSSL_API unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509*); +WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID( + WOLFSSL_X509*, unsigned char*, int*); +WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID( + WOLFSSL_X509*, unsigned char*, int*); + +WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_set_pubkey(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); + +WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID( + WOLFSSL_X509_NAME*, int, char*, int); +WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID( + WOLFSSL_X509_NAME*, int, int); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*); + +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type); +WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1); +WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, + const void* data, int dataSz); +WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long); +WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*); + +WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long); +WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*, + long); +WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void); +WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void); + +WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE*, + WOLFSSL_X509_LOOKUP_METHOD*); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void); +WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*); +WOLFSSL_API int wolfSSL_X509_STORE_add_cert( + WOLFSSL_X509_STORE*, WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, + unsigned long flag); +WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*); +WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*, + int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*, + WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*); + +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*); + +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio( + WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key, + unsigned char** in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, + WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key, + unsigned char** in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void); +WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); +WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*, + unsigned long flags, + time_t t); +#endif +WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*); +WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( + WOLFSSL_X509_REVOKED*,int); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*); +WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void); + +WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*); + +WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, + char* buf, int len); +WOLFSSL_API int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*, + const WOLFSSL_ASN1_INTEGER*); +WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*); + +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t, + int, long); +#endif + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); +WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, + WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int); +WOLFSSL_API int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error( + WOLFSSL_X509_STORE_CTX* ctx, int er); +WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int); + +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*, + void* userdata); +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, + pem_password_cb*); +WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx); +WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx); + +WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, + void (*)(const WOLFSSL* ssl, int type, int val)); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void); +WOLFSSL_API int wolfSSL_GET_REASON(int); + +WOLFSSL_API const char* wolfSSL_alert_type_string_long(int); +WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int); +WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*); + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long, + void(*)(int, int, void*), void*); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, + const unsigned char **pp, long len); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**, + const unsigned char**, long); +WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp); +WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp); +WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *, + WOLFSSL_RSA *(*)(WOLFSSL *, int, int)); + +WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key); + +WOLFSSL_API long wolfSSL_CTX_sess_accept(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_hits(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); +WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( + WOLFSSL_CTX*, void* arg); +WOLFSSL_API int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*); +WOLFSSL_API int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*); + +WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s); +WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh); +WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type); +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp); +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len); + +WOLFSSL_API void wolfSSL_CONF_modules_unload(int all); +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); + +#define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ + +enum { + WOLFSSL_OCSP_URL_OVERRIDE = 1, + WOLFSSL_OCSP_NO_NONCE = 2, + WOLFSSL_OCSP_CHECKALL = 4, + + WOLFSSL_CRL_CHECKALL = 1, + WOLFSSL_CRL_CHECK = 27, +}; + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +/* seperated out from other enums because of size */ +enum { + SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000004, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000008, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000010, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000020, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000040, + SSL_OP_TLS_D5_BUG = 0x00000080, + SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000100, + SSL_OP_TLS_ROLLBACK_BUG = 0x00000200, + SSL_OP_ALL = 0x00000400, + SSL_OP_EPHEMERAL_RSA = 0x00000800, + SSL_OP_NO_SSLv3 = 0x00001000, + SSL_OP_NO_TLSv1 = 0x00002000, + SSL_OP_PKCS1_CHECK_1 = 0x00004000, + SSL_OP_PKCS1_CHECK_2 = 0x00008000, + SSL_OP_NETSCAPE_CA_DN_BUG = 0x00010000, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x00020000, + SSL_OP_SINGLE_DH_USE = 0x00040000, + SSL_OP_NO_TICKET = 0x00080000, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00100000, + SSL_OP_NO_QUERY_MTU = 0x00200000, + SSL_OP_COOKIE_EXCHANGE = 0x00400000, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000, + SSL_OP_SINGLE_ECDH_USE = 0x01000000, + SSL_OP_CIPHER_SERVER_PREFERENCE = 0x02000000, + SSL_OP_NO_TLSv1_1 = 0x04000000, + SSL_OP_NO_TLSv1_2 = 0x08000000, + SSL_OP_NO_COMPRESSION = 0x10000000, + SSL_OP_NO_TLSv1_3 = 0x20000000, +}; + +enum { +#ifdef HAVE_OCSP + /* OCSP Flags */ + OCSP_NOCERTS = 1, + OCSP_NOINTERN = 2, + OCSP_NOSIGS = 4, + OCSP_NOCHAIN = 8, + OCSP_NOVERIFY = 16, + OCSP_NOEXPLICIT = 32, + OCSP_NOCASIGN = 64, + OCSP_NODELEGATED = 128, + OCSP_NOCHECKS = 256, + OCSP_TRUSTOTHER = 512, + OCSP_RESPID_KEY = 1024, + OCSP_NOTIME = 2048, + + /* OCSP Types */ + OCSP_CERTID = 2, + OCSP_REQUEST = 4, + OCSP_RESPONSE = 8, + OCSP_BASICRESP = 16, +#endif + + ASN1_GENERALIZEDTIME = 4, + SSL_MAX_SSL_SESSION_ID_LENGTH = 32, + + EVP_R_BAD_DECRYPT = 2, + + SSL_ST_CONNECT = 0x1000, + SSL_ST_ACCEPT = 0x2000, + SSL_ST_MASK = 0x0FFF, + + SSL_CB_LOOP = 0x01, + SSL_CB_EXIT = 0x02, + SSL_CB_READ = 0x04, + SSL_CB_WRITE = 0x08, + SSL_CB_HANDSHAKE_START = 0x10, + SSL_CB_HANDSHAKE_DONE = 0x20, + SSL_CB_ALERT = 0x4000, + SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ), + SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE), + SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP), + SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT), + SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP), + SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT), + SSL_CB_MODE_READ = 1, + SSL_CB_MODE_WRITE = 2, + + SSL_MODE_ENABLE_PARTIAL_WRITE = 2, + + BIO_FLAGS_BASE64_NO_NL = 1, + BIO_CLOSE = 1, + BIO_NOCLOSE = 0, + + X509_FILETYPE_PEM = 8, + X509_LU_X509 = 9, + X509_LU_CRL = 12, + + X509_V_OK = 0, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, + X509_V_ERR_CRL_HAS_EXPIRED = 15, + X509_V_ERR_CERT_REVOKED = 16, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, + X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, + X509_V_ERR_CERT_HAS_EXPIRED = 21, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, + X509_V_ERR_CERT_REJECTED = 23, + /* Required for Nginx */ + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 24, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 25, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26, + X509_V_ERR_CERT_UNTRUSTED = 27, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 28, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, + /* additional X509_V_ERR_* enums not used in wolfSSL */ + X509_V_ERR_UNABLE_TO_GET_CRL, + X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, + X509_V_ERR_CERT_SIGNATURE_FAILURE, + X509_V_ERR_CRL_NOT_YET_VALID, + X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, + X509_V_ERR_OUT_OF_MEM, + X509_V_ERR_INVALID_CA, + X509_V_ERR_PATH_LENGTH_EXCEEDED, + X509_V_ERR_INVALID_PURPOSE, + X509_V_ERR_AKID_SKID_MISMATCH, + X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, + X509_V_ERR_KEYUSAGE_NO_CERTSIGN, + X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, + X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, + X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, + X509_V_ERR_INVALID_NON_CA, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, + X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, + X509_V_ERR_INVALID_EXTENSION, + X509_V_ERR_INVALID_POLICY_EXTENSION, + X509_V_ERR_NO_EXPLICIT_POLICY, + X509_V_ERR_UNNESTED_RESOURCE, + + X509_R_CERT_ALREADY_IN_HASH_TABLE, + + XN_FLAG_SPC_EQ = (1 << 23), + XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, + + CRYPTO_LOCK = 1, + CRYPTO_NUM_LOCKS = 10, + + ASN1_STRFLGS_ESC_MSB = 4 +}; +#endif + +/* extras end */ + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* wolfSSL extension, provide last error from SSL_get_error + since not using thread storage error queue */ +#include +WOLFSSL_API void wolfSSL_ERR_print_errors_fp(XFILE, int err); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp); +#endif +#endif + + +#ifndef NO_OLD_SSL_NAMES + #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE + #define SSL_FAILURE WOLFSSL_FAILURE + #define SSL_SUCCESS WOLFSSL_SUCCESS + #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE + + #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND + #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE + #define SSL_BAD_STAT WOLFSSL_BAD_STAT + #define SSL_BAD_PATH WOLFSSL_BAD_PATH + #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE + #define SSL_BAD_FILE WOLFSSL_BAD_FILE + #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED + #define SSL_UNKNOWN WOLFSSL_UNKNOWN + #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR + + #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1 + #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM + #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT + #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW + + #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE + #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER + #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT + #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE + #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK + + #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF + #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT + #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER + #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH + #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR + #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP + #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE + #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL + + #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ + #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE + #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT + #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT + #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL + #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP + #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN + #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL + + #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN + #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN + #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + #define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2 + + #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE + #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA + #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN + #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE + + #define PEM_BUFSIZE WOLF_PEM_BUFSIZE +#endif + +enum { /* ssl Constants */ + WOLFSSL_ERROR_NONE = 0, /* for most functions */ + WOLFSSL_FAILURE = 0, /* for some functions */ + WOLFSSL_SUCCESS = 1, + WOLFSSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */ + + WOLFSSL_ALPN_NOT_FOUND = -9, + WOLFSSL_BAD_CERTTYPE = -8, + WOLFSSL_BAD_STAT = -7, + WOLFSSL_BAD_PATH = -6, + WOLFSSL_BAD_FILETYPE = -5, + WOLFSSL_BAD_FILE = -4, + WOLFSSL_NOT_IMPLEMENTED = -3, + WOLFSSL_UNKNOWN = -2, + WOLFSSL_FATAL_ERROR = -1, + + WOLFSSL_FILETYPE_ASN1 = 2, + WOLFSSL_FILETYPE_PEM = 1, + WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */ + WOLFSSL_FILETYPE_RAW = 3, /* NTRU raw key blob */ + + WOLFSSL_VERIFY_NONE = 0, + WOLFSSL_VERIFY_PEER = 1, + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, + WOLFSSL_VERIFY_CLIENT_ONCE = 4, + WOLFSSL_VERIFY_FAIL_EXCEPT_PSK = 8, + + WOLFSSL_SESS_CACHE_OFF = 0x0000, + WOLFSSL_SESS_CACHE_CLIENT = 0x0001, + WOLFSSL_SESS_CACHE_SERVER = 0x0002, + WOLFSSL_SESS_CACHE_BOTH = 0x0003, + WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, + WOLFSSL_SESS_CACHE_NO_INTERNAL = 0x0300, + + WOLFSSL_ERROR_WANT_READ = 2, + WOLFSSL_ERROR_WANT_WRITE = 3, + WOLFSSL_ERROR_WANT_CONNECT = 7, + WOLFSSL_ERROR_WANT_ACCEPT = 8, + WOLFSSL_ERROR_SYSCALL = 5, + WOLFSSL_ERROR_WANT_X509_LOOKUP = 83, + WOLFSSL_ERROR_ZERO_RETURN = 6, + WOLFSSL_ERROR_SSL = 85, + + WOLFSSL_SENT_SHUTDOWN = 1, + WOLFSSL_RECEIVED_SHUTDOWN = 2, + WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, + WOLFSSL_OP_NO_SSLv2 = 8, + + WOLFSSL_R_SSL_HANDSHAKE_FAILURE = 101, + WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, + WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, + WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, + + WOLF_PEM_BUFSIZE = 1024 +}; + +#ifndef NO_PSK + typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, + unsigned int, unsigned char*, unsigned int); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*, + wc_psk_client_callback); + WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*, + wc_psk_client_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*, + wc_psk_client_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*, + wc_psk_client_tls13_callback); +#endif + + WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*); + WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*); + + WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*); + WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*); + + typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*, + wc_psk_server_callback); + WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*, + wc_psk_server_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*, + wc_psk_server_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*, + wc_psk_server_tls13_callback); +#endif + + #define PSK_TYPES_DEFINED +#endif /* NO_PSK */ + + +#ifdef HAVE_ANON + WOLFSSL_API int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX*); +#endif /* HAVE_ANON */ + + +/* extra begins */ +#ifdef OPENSSL_EXTRA +enum { /* ERR Constants */ + ERR_TXT_STRING = 1 +}; + +/* bio misc */ +enum { + WOLFSSL_BIO_ERROR = -1, + WOLFSSL_BIO_UNSET = -2, + WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ +}; +#endif + +WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err, + const char* file, int line); +WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*); +WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, + const char**, int *); + +WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void); +WOLFSSL_API void wolfSSL_ERR_clear_error(void); + + +WOLFSSL_API int wolfSSL_RAND_status(void); +WOLFSSL_API int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num); +WOLFSSL_API int wolfSSL_RAND_bytes(unsigned char* buf, int num); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void); +WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); +WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); +WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); + +#ifndef NO_CERTS + WOLFSSL_API int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*); +#endif /* !NO_CERTS */ + +WOLFSSL_API void wolfSSL_ERR_free_strings(void); +WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long); +WOLFSSL_API int wolfSSL_clear(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_state(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void); +WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode); +WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m); +WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl); + + +WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*, + const unsigned char*, unsigned int); +WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); + +WOLFSSL_API int wolfSSL_want_read(WOLFSSL*); +WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); + +WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); +WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_UTCTIME*); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API int wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*); +WOLFSSL_API void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*, int); + +/* stunnel 4.28 needs */ +WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*); +WOLFSSL_API void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*, + WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)); +WOLFSSL_API void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)); +WOLFSSL_API void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX*, + void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)); + +WOLFSSL_API int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION*,unsigned char**); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION**, + const unsigned char**, long); + +WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*); +WOLFSSL_API int wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*); + +/* extra ends */ + + +/* wolfSSL extensions */ + +/* call before SSL_connect, if verifying will add name check to + date check and signature check */ +WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn); + +/* need to call once to load library (session cache) */ +WOLFSSL_API int wolfSSL_Init(void); +/* call when done to cleanup/free session cache mutex / resources */ +WOLFSSL_API int wolfSSL_Cleanup(void); + +/* which library version do we have */ +WOLFSSL_API const char* wolfSSL_lib_version(void); +/* which library version do we have in hex */ +WOLFSSL_API unsigned int wolfSSL_lib_version_hex(void); + +/* do accept or connect depedning on side */ +WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl); +/* turn on wolfSSL data compression */ +WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int); +WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int); + +/* get wolfSSL peer X509_CHAIN */ +WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl); +#ifdef WOLFSSL_ALT_CERT_CHAINS +WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl); +/* get wolfSSL alternate peer X509_CHAIN */ +WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl); +#endif +/* peer chain count */ +WOLFSSL_API int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain); +/* index cert length */ +WOLFSSL_API int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN*, int idx); +/* index cert */ +WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx); +/* index cert in X509 */ +WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx); +/* free X509 */ +#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509)) +WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*); +/* get index cert in PEM */ +WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx, + unsigned char* buf, int inLen, int* outLen); +WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(const WOLFSSL_SESSION* s); +WOLFSSL_API int wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*); +WOLFSSL_API char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509*); +WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*); +WOLFSSL_API const unsigned char* wolfSSL_X509_notBefore(WOLFSSL_X509*); +WOLFSSL_API const unsigned char* wolfSSL_X509_notAfter(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*); + +WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*); + +WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, + const unsigned char** in, int len); +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out); +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl, + const unsigned char *in, int len); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl); +#endif +WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl); + +#ifndef NO_FILESYSTEM + #ifndef NO_STDIO_FILESYSTEM + WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file); + #endif +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_load_certificate_file(const char* fname, int format); +#endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( + const unsigned char* buf, int sz, int format); + +#ifdef WOLFSSL_SEP + WOLFSSL_API unsigned char* + wolfSSL_X509_get_device_type(WOLFSSL_X509*, unsigned char*, int*); + WOLFSSL_API unsigned char* + wolfSSL_X509_get_hw_type(WOLFSSL_X509*, unsigned char*, int*); + WOLFSSL_API unsigned char* + wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509*, unsigned char*, int*); +#endif + +/* connect enough to get peer cert */ +WOLFSSL_API int wolfSSL_connect_cert(WOLFSSL* ssl); + + + +/* PKCS12 compatibility */ +typedef struct WC_PKCS12 WC_PKCS12; +WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, + WC_PKCS12** pkcs12); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp, + WOLFSSL_X509_PKCS12** pkcs12); +#endif +WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, + WOLF_STACK_OF(WOLFSSL_X509)** ca); +WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, + WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, + WOLF_STACK_OF(WOLFSSL_X509)* ca, + int keyNID, int certNID, int itt, int macItt, int keytype); +WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void); + + + +#ifndef NO_DH +/* server Diffie-Hellman parameters */ +WOLFSSL_API int wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz, + const unsigned char* g, int gSz); +WOLFSSL_API int wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz, + int format); +WOLFSSL_API int wolfSSL_SetEnableDhKeyTest(WOLFSSL*, int); +#ifndef NO_FILESYSTEM + WOLFSSL_API int wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format); +#endif + +/* server ctx Diffie-Hellman parameters */ +WOLFSSL_API int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX*, const unsigned char* p, + int pSz, const unsigned char* g, int gSz); +WOLFSSL_API int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* b, + long sz, int format); + +#ifndef NO_FILESYSTEM + WOLFSSL_API int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f, + int format); +#endif + +WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*); +#endif /* NO_DH */ + +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, unsigned short); + +/* keyblock size in bytes or -1 */ +/* need to call wolfSSL_KeepArrays before handshake to save keys */ +WOLFSSL_API int wolfSSL_get_keyblock_size(WOLFSSL*); +WOLFSSL_API int wolfSSL_get_keys(WOLFSSL*,unsigned char** ms, unsigned int* msLen, + unsigned char** sr, unsigned int* srLen, + unsigned char** cr, unsigned int* crLen); + +/* Computes EAP-TLS and EAP-TTLS keying material from the master_secret. */ +WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, + const char* label); + + +#ifndef _WIN32 + #ifndef NO_WRITEV + #ifdef __PPU + #include + #include + #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \ + !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \ + !defined(WOLFSSL_CHIBIOS) && !defined(WOLFSSL_CONTIKI) + #include + #endif + /* allow writev style writing */ + WOLFSSL_API int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, + int iovcnt); + #endif +#endif + + +#ifndef NO_CERTS + /* SSL_CTX versions */ + WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); +#endif + WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*, + const unsigned char*, long); + + /* SSL versions */ + WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*, + long, int); + WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, + int derSz); + WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*, + long, int); + WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*, + const unsigned char*, long); + WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*); + + #if defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT) + WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl); + #endif +#endif + +WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*); + + +#ifdef HAVE_FUZZER +enum fuzzer_type { + FUZZ_HMAC = 0, + FUZZ_ENCRYPT = 1, + FUZZ_SIGNATURE = 2, + FUZZ_HASH = 3, + FUZZ_HEAD = 4 +}; + +typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz, + int type, void* fuzzCtx); + +WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx); +#endif + + +WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, + const unsigned char*, + unsigned int); + + +/* I/O Callback default errors */ +enum IOerrors { + WOLFSSL_CBIO_ERR_GENERAL = -1, /* general unexpected err */ + WOLFSSL_CBIO_ERR_WANT_READ = -2, /* need to call read again */ + WOLFSSL_CBIO_ERR_WANT_WRITE = -2, /* need to call write again */ + WOLFSSL_CBIO_ERR_CONN_RST = -3, /* connection reset */ + WOLFSSL_CBIO_ERR_ISR = -4, /* interrupt */ + WOLFSSL_CBIO_ERR_CONN_CLOSE = -5, /* connection closed or epipe */ + WOLFSSL_CBIO_ERR_TIMEOUT = -6 /* socket timeout */ +}; + + +/* CA cache callbacks */ +enum { + WOLFSSL_SSLV3 = 0, + WOLFSSL_TLSV1 = 1, + WOLFSSL_TLSV1_1 = 2, + WOLFSSL_TLSV1_2 = 3, + WOLFSSL_TLSV1_3 = 4, + WOLFSSL_USER_CA = 1, /* user added as trusted */ + WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */ +}; + +WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*); + +WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version); +WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version); +WOLFSSL_API int wolfSSL_GetObjectSize(void); /* object size based on build */ +WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void); +WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void); +WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version); + +/* moved to asn.c, old names kept for backwards compatability */ +#define wolfSSL_KeyPemToDer wc_KeyPemToDer +#define wolfSSL_CertPemToDer wc_CertPemToDer +#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer +#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer +#define wolfSSL_PemCertToDer wc_PemCertToDer + + +typedef void (*CallbackCACache)(unsigned char* der, int sz, int type); +typedef void (*CbMissingCRL)(const char* url); +typedef int (*CbOCSPIO)(void*, const char*, int, + unsigned char*, int, unsigned char**); +typedef void (*CbOCSPRespFree)(void*,unsigned char*); + +#ifdef HAVE_CRL_IO +typedef int (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz); +#endif + +/* User Atomic Record Layer CallBacks */ +typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut, + const unsigned char* macIn, unsigned int macInSz, int macContent, + int macVerify, unsigned char* encOut, const unsigned char* encIn, + unsigned int encSz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX*, CallbackMacEncrypt); +WOLFSSL_API void wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl); + +typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int content, int verify, unsigned int* padSz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*, + CallbackDecryptVerify); +WOLFSSL_API void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl); + +WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int); +WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteIV(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetKeySize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetIVSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetSide(WOLFSSL*); +WOLFSSL_API int wolfSSL_IsTLSv1_1(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetBulkCipher(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetCipherBlockSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetAeadMacSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetHmacSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetHmacType(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetCipherType(WOLFSSL*); +WOLFSSL_API int wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*, + unsigned int, int, int); + +/* Atomic User Needs */ +enum { + WOLFSSL_SERVER_END = 0, + WOLFSSL_CLIENT_END = 1, + WOLFSSL_NEITHER_END = 3, + WOLFSSL_BLOCK_TYPE = 2, + WOLFSSL_STREAM_TYPE = 3, + WOLFSSL_AEAD_TYPE = 4, + WOLFSSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */ +}; + +/* for GetBulkCipher and internal use */ +enum BulkCipherAlgorithm { + wolfssl_cipher_null, + wolfssl_rc4, + wolfssl_rc2, + wolfssl_des, + wolfssl_triple_des, /* leading 3 (3des) not valid identifier */ + wolfssl_des40, +#ifdef HAVE_IDEA + wolfssl_idea, +#endif + wolfssl_aes, + wolfssl_aes_gcm, + wolfssl_aes_ccm, + wolfssl_chacha, + wolfssl_camellia, + wolfssl_hc128, /* wolfSSL extensions */ + wolfssl_rabbit +}; + + +/* for KDF TLS 1.2 mac types */ +enum KDF_MacAlgorithm { + wolfssl_sha256 = 4, /* needs to match internal MACAlgorithm */ + wolfssl_sha384, + wolfssl_sha512 +}; + + +/* Public Key Callback support */ +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + +struct ecc_key; + +typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key, + unsigned int keySz, int ecc_curve, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen); +WOLFSSL_API void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, CallbackEccSign); +WOLFSSL_API void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccVerify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify); +WOLFSSL_API void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret); +WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_DH +/* Public DH Key Callback support */ +struct DhKey; +typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree); +WOLFSSL_API void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl); +#endif /* !NO_DH */ + +#ifdef HAVE_ED25519 +struct ed25519_key; +typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*, + CallbackEd25519Sign); +WOLFSSL_API void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* msg, unsigned int msgSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*, + CallbackEd25519Verify); +WOLFSSL_API void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl); +#endif + +#ifdef HAVE_CURVE25519 +struct curve25519_key; + +typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key, + unsigned int keySz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen); +WOLFSSL_API void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl); + +typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl, + struct curve25519_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); + /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*, + CallbackX25519SharedSecret); +WOLFSSL_API void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_RSA +typedef int (*CallbackRsaSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign); +WOLFSSL_API void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify); +WOLFSSL_API void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX*, CallbackRsaVerify); +WOLFSSL_API void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl); + +#ifdef WC_RSA_PSS +typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign); +WOLFSSL_API void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl); +#endif + +/* RSA Public Encrypt cb */ +typedef int (*CallbackRsaEnc)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc); +WOLFSSL_API void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl); + +/* RSA Private Decrypt cb */ +typedef int (*CallbackRsaDec)(WOLFSSL* ssl, + unsigned char* in, unsigned int inSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec); +WOLFSSL_API void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); +#endif +#endif /* HAVE_PK_CALLBACKS */ + +#ifndef NO_CERTS + WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache); + + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*); + + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap); + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void); + WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*); + + WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f, + const char* d); + WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char* in, long sz, int format); + WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm); +#endif + WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f, + int format); + WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* buff, long sz, int format); + WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER*, + unsigned char*, int sz); + WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*, + int options); + WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*); + WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*, + const char*, int, int); + WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*, + CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*, + CbCrlIO); +#endif + WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, + unsigned char*, int sz); + WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*, + int options); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*); + WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*, + const char*); + WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*, + CbOCSPIO, CbOCSPRespFree, void*); + + WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); + + WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); + WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); + WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int); + WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb); +#endif + WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options); + WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*); + WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*); + WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*); + WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*); + + WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options); + WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx); + WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int); + WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO); +#endif + + WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options); + WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*); + WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*, + CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*); +#endif /* !NO_CERTS */ + + +#ifdef SINGLE_THREADED + WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*); +#endif + +/* end of handshake frees temporary arrays, if user needs for get_keys or + psk hints, call KeepArrays before handshake and then FreeArrays when done + if don't want to wait for object free */ +WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*); +WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*); + +WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); + +/* async additions */ +#define wolfSSL_UseAsync wolfSSL_SetDevId +#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId +WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId); +WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId); + +/* helpers to get device id and heap */ +WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); + +/* TLS Extensions */ + +/* Server Name Indication */ +#ifdef HAVE_SNI + +/* SNI types */ +enum { + WOLFSSL_SNI_HOST_NAME = 0 +}; + +WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type, + const void* data, unsigned short size); +WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type, + const void* data, unsigned short size); + +#ifndef NO_WOLFSSL_SERVER + +/* SNI options */ +enum { + /* Do not abort the handshake if the requested SNI didn't match. */ + WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01, + + /* Behave as if the requested SNI matched in a case of mismatch. */ + /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */ + WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02, + + /* Abort the handshake if the client didn't send a SNI request. */ + WOLFSSL_SNI_ABORT_ON_ABSENCE = 0x04, +}; + +WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type, + unsigned char options); +WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, + unsigned char type, unsigned char options); +WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( + const unsigned char* clientHello, unsigned int helloSz, + unsigned char type, unsigned char* sni, unsigned int* inOutSz); + +#endif /* NO_WOLFSSL_SERVER */ + +/* SNI status */ +enum { + WOLFSSL_SNI_NO_MATCH = 0, + WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */ + WOLFSSL_SNI_REAL_MATCH = 2, + WOLFSSL_SNI_FORCE_KEEP = 3 /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */ +}; + +WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type); + +WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl, + unsigned char type, void** data); + +#endif /* HAVE_SNI */ + +/* Application-Layer Protocol Negotiation */ +#ifdef HAVE_ALPN + +/* ALPN status code */ +enum { + WOLFSSL_ALPN_NO_MATCH = 0, + WOLFSSL_ALPN_MATCH = 1, + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2, + WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4, +}; + +enum { + WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255, + WOLFSSL_MAX_ALPN_NUMBER = 257 +}; + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, + unsigned char* outLen, const unsigned char* in, unsigned int inLen, + void *arg); +#endif + +WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, + unsigned int protocol_name_listSz, + unsigned char options); + +WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, + unsigned short *size); + +WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, + unsigned short *listSz); +WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list); +#endif /* HAVE_ALPN */ + +/* Maximum Fragment Length */ +#ifdef HAVE_MAX_FRAGMENT + +/* Fragment lengths */ +enum { + WOLFSSL_MFL_2_9 = 1, /* 512 bytes */ + WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */ + WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */ + WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */ + WOLFSSL_MFL_2_13 = 5, /* 8192 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_2_8 = 6, /* 256 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_MIN = WOLFSSL_MFL_2_9, + WOLFSSL_MFL_MAX = WOLFSSL_MFL_2_8, +}; + +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl); +WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl); + +#endif +#endif /* HAVE_MAX_FRAGMENT */ + +/* Truncated HMAC */ +#ifdef HAVE_TRUNCATED_HMAC +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx); + +#endif +#endif + +/* Certificate Status Request */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR_OCSP = 1 +}; + +/* Certificate Status Options (flags) */ +enum { + WOLFSSL_CSR_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Certificate Status Request v2 */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR2_OCSP = 1, + WOLFSSL_CSR2_OCSP_MULTI = 2 +}; + +/* Certificate Status v2 Options (flags) */ +enum { + WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Named Groups */ +enum { +#if 0 /* Not Supported */ + WOLFSSL_ECC_SECT163K1 = 1, + WOLFSSL_ECC_SECT163R1 = 2, + WOLFSSL_ECC_SECT163R2 = 3, + WOLFSSL_ECC_SECT193R1 = 4, + WOLFSSL_ECC_SECT193R2 = 5, + WOLFSSL_ECC_SECT233K1 = 6, + WOLFSSL_ECC_SECT233R1 = 7, + WOLFSSL_ECC_SECT239K1 = 8, + WOLFSSL_ECC_SECT283K1 = 9, + WOLFSSL_ECC_SECT283R1 = 10, + WOLFSSL_ECC_SECT409K1 = 11, + WOLFSSL_ECC_SECT409R1 = 12, + WOLFSSL_ECC_SECT571K1 = 13, + WOLFSSL_ECC_SECT571R1 = 14, +#endif + WOLFSSL_ECC_SECP160K1 = 15, + WOLFSSL_ECC_SECP160R1 = 16, + WOLFSSL_ECC_SECP160R2 = 17, + WOLFSSL_ECC_SECP192K1 = 18, + WOLFSSL_ECC_SECP192R1 = 19, + WOLFSSL_ECC_SECP224K1 = 20, + WOLFSSL_ECC_SECP224R1 = 21, + WOLFSSL_ECC_SECP256K1 = 22, + WOLFSSL_ECC_SECP256R1 = 23, + WOLFSSL_ECC_SECP384R1 = 24, + WOLFSSL_ECC_SECP521R1 = 25, + WOLFSSL_ECC_BRAINPOOLP256R1 = 26, + WOLFSSL_ECC_BRAINPOOLP384R1 = 27, + WOLFSSL_ECC_BRAINPOOLP512R1 = 28, + WOLFSSL_ECC_X25519 = 29, +#ifdef WOLFSSL_TLS13 + /* Not implemented. */ + WOLFSSL_ECC_X448 = 30, + + WOLFSSL_FFDHE_2048 = 256, + WOLFSSL_FFDHE_3072 = 257, + WOLFSSL_FFDHE_4096 = 258, + WOLFSSL_FFDHE_6144 = 259, + WOLFSSL_FFDHE_8192 = 260, +#endif +}; + +enum { + WOLFSSL_EC_PF_UNCOMPRESSED = 0, +#if 0 /* Not Supported */ + WOLFSSL_EC_PF_X962_COMP_PRIME = 1, + WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2, +#endif +}; + +#ifdef HAVE_SUPPORTED_CURVES +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, unsigned short name); +WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, + unsigned short name); + +#endif +#endif + +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, unsigned short group); +WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl); +#endif + + +/* Secure Renegotiation */ +#ifdef HAVE_SECURE_RENEGOTIATION + +WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); + +#endif + +/* Session Ticket */ +#ifdef HAVE_SESSION_TICKET + +#ifndef NO_WOLFSSL_CLIENT +WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*); +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, unsigned int); +typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*); +WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, + CallbackSessionTicket, void*); +#endif /* NO_WOLFSSL_CLIENT */ + + +#define WOLFSSL_TICKET_NAME_SZ 16 +#define WOLFSSL_TICKET_IV_SZ 16 +#define WOLFSSL_TICKET_MAC_SZ 32 + +enum TicketEncRet { + WOLFSSL_TICKET_RET_FATAL = -1, /* fatal error, don't use ticket */ + WOLFSSL_TICKET_RET_OK = 0, /* ok, use ticket */ + WOLFSSL_TICKET_RET_REJECT, /* don't use ticket, but not fatal */ + WOLFSSL_TICKET_RET_CREATE /* existing ticket ok and create new one */ +}; + +#ifndef NO_WOLFSSL_SERVER + +typedef int (*SessionTicketEncCb)(WOLFSSL*, + unsigned char key_name[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char*, int, int*, void*); +WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, + SessionTicketEncCb); +WOLFSSL_API int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int); +WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*); + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_QSH +/* Quantum-safe Crypto Schemes */ +enum { + WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65 */ + WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86 */ + WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */ + WOLFSSL_LWE_XXX = 0x0201, /* Learning With Error encryption scheme */ + WOLFSSL_HFE_XXX = 0x0301, /* Hidden Field Equation scheme */ + WOLFSSL_NULL_QSH = 0xFFFF /* QSHScheme is not used */ +}; + + +/* test if the connection is using a QSH secure connection return 1 if so */ +WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name); +#ifndef NO_WOLFSSL_CLIENT + /* user control over sending client public key in hello + when flag = 1 will send keys if flag is 0 or function is not called + then will not send keys in the hello extension */ + WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag); +#endif + +#endif /* QSH */ + +/* TLS Extended Master Secret Extension */ +WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx); + + +#define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */ +#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */ + + +/* notify user the handshake is done */ +typedef int (*HandShakeDoneCb)(WOLFSSL*, void*); +WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*); + + +WOLFSSL_API int wolfSSL_PrintSessionStats(void); +WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions); +/* External facing KDF */ +WOLFSSL_API +int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen, + const unsigned char* pms, unsigned int pmsLen, + const unsigned char* cr, const unsigned char* sr, + int tls1_2, int hash_type); + +WOLFSSL_API +int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, unsigned int msLen, + const unsigned char* pms, unsigned int pmsLen, + const unsigned char* sHash, unsigned int sHashLen, + int tls1_2, int hash_type); + +WOLFSSL_API +int wolfSSL_DeriveTlsKeys(unsigned char* key_data, unsigned int keyLen, + const unsigned char* ms, unsigned int msLen, + const unsigned char* sr, const unsigned char* cr, + int tls1_2, int hash_type); + +#ifdef WOLFSSL_CALLBACKS + +/* used internally by wolfSSL while OpenSSL types aren't */ +#include + +typedef int (*HandShakeCallBack)(HandShakeInfo*); +typedef int (*TimeoutCallBack)(TimeoutInfo*); + +/* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack + for diagnostics */ +WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, + Timeval); +WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, + Timeval); + +#endif /* WOLFSSL_CALLBACKS */ + + +#ifdef WOLFSSL_HAVE_WOLFSCEP + WOLFSSL_API void wolfSSL_wolfSCEP(void); +#endif /* WOLFSSL_HAVE_WOLFSCEP */ + +#ifdef WOLFSSL_HAVE_CERT_SERVICE + WOLFSSL_API void wolfSSL_cert_service(void); +#endif + +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Smaller subset of X509 compatibility functions. Avoid increasing the size of + * this subset and its memory usage */ + +#include +struct WOLFSSL_X509_NAME_ENTRY { + WOLFSSL_ASN1_OBJECT object; /* static object just for keeping grp, type */ + WOLFSSL_ASN1_STRING data; + WOLFSSL_ASN1_STRING* value; /* points to data, for lighttpd port */ + int nid; /* i.e. ASN_COMMON_NAME */ + int set; + int size; +}; +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + +enum { + WOLFSSL_SYS_ACCEPT = 0, + WOLFSSL_SYS_BIND, + WOLFSSL_SYS_CONNECT, + WOLFSSL_SYS_FOPEN, + WOLFSSL_SYS_FREAD, + WOLFSSL_SYS_GETADDRINFO, + WOLFSSL_SYS_GETSOCKOPT, + WOLFSSL_SYS_GETSOCKNAME, + WOLFSSL_SYS_GETHOSTBYNAME, + WOLFSSL_SYS_GETNAMEINFO, + WOLFSSL_SYS_GETSERVBYNAME, + WOLFSSL_SYS_IOCTLSOCKET, + WOLFSSL_SYS_LISTEN, + WOLFSSL_SYS_OPENDIR, + WOLFSSL_SYS_SETSOCKOPT, + WOLFSSL_SYS_SOCKET +}; + +/* Object functions */ +WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); +WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); +WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); + +WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n); +WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn); + +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n); +WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int n, WOLFSSL_ASN1_OBJECT *arg_obj); +WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name); + +WOLFSSL_API void wolfSSL_OBJ_cleanup(void); +/* end of object functions */ + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); +WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); +WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); + +#ifndef NO_CERTS +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( + WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, + unsigned char* data, int dataSz); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name, + WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, + const char *field, int type, const unsigned char *bytes, int len, int loc, + int set); +WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, + const WOLFSSL_X509_NAME* y); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); +WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx); +WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, + const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); +WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, + unsigned char* der, long derSz); +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl); +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, + long derSz); +#endif +#endif /* NO_CERTS */ + +WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r); + +WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz); +WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses); + +WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, + WOLFSSL_X509_STORE* str); +WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp, + WOLFSSL_X509** x509); +#endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, + WOLFSSL_X509** x509); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); + +WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); +WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, + unsigned char *out, size_t outlen); +WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, + unsigned char* out, size_t outSz); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX + (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, + WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); +#endif +WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, + EncryptedInfo* cipher); +WOLFSSL_API int wolfSSL_PEM_do_header(EncryptedInfo* cipher, + unsigned char* data, long* len, + pem_password_cb* callback, void* ctx); + +/*lighttp compatibility */ + +struct WOLFSSL_ASN1_BIT_STRING { + int length; + int type; + char* data; + long flags; +}; + + +#if defined(OPENSSL_EXTRA) \ + || defined(OPENSSL_ALL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) +WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); +WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); +WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); +/* These are to be merged shortly */ +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); +WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); +WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); +WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); +WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)); +WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ); +WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509); + +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); +WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); +#endif + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) + +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode); +WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*); +WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, + WOLFSSL_DH **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, + WOLFSSL_DSA **x, pem_password_cb *cb, void *u); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); + +#endif /* HAVE_STUNNEL || HAVE_LIGHTY */ + +#ifdef OPENSSL_ALL +WOLFSSL_API int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_new(void); +WOLFSSL_API void wolfSSL_X509_REQ_free(WOLFSSL_X509* req); +WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, + const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, + WOLFSSL_X509_NAME *name); +WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, + WOLFSSL_EVP_PKEY *pkey); +#endif + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) \ + || defined(HAVE_LIGHTY) + +#include + +/* SNI received callback type */ +typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); + +WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); + +WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void); + +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg); + +WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int, + void (*callback) (int, int, void *)); + +WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void); + +WOLFSSL_API int wolfSSL_FIPS_mode(void); + +WOLFSSL_API int wolfSSL_FIPS_mode_set(int r); + +WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth); + +WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits); + +WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s); + +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_new(void); +WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s); + +WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int, + unsigned long); + +WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr( + const WOLFSSL_X509*); + +WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*); + +WOLFSSL_API int wolfSSL_version(WOLFSSL*); + +WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*); + +WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int); + +WOLFSSL_API void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int); + +WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); + +WOLFSSL_API int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*); + +WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*, + CRYPTO_free_func*); + +WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*); + + +WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*, + unsigned int*); + +WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *); + +WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char); + +WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*); + +WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); + +WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); + +WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*); + +/* support for depricated old name */ +#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state + +#ifndef NO_FILESYSTEM +WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE fp); +#endif + +WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*)); + +WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val); + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); + +WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */ + +#if defined(OPENSSL_ALL) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); + +#endif + +#ifdef WOLFSSL_JNI +WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr); +WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl); +#endif /* WOLFSSL_JNI */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags); +WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names); + +typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, + const void *buf, size_t len, WOLFSSL *ssl, void *arg); + +WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg); +WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg); +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); +WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, + const unsigned char *protos, unsigned int protos_len); +WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, + size_t siz, const char* file, int line); +WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); +#endif + +#if defined(OPENSSL_ALL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response); +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); +/* Not an OpenSSL API. */ +WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl); +WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, + void *b, void *c); +WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); +WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, + void *data); + +WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len); + +WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, + WOLFSSL_EC_KEY *ecdh); +WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, + WOLFSSL_SESSION *c); + +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */ +#ifndef NO_SESSION_CACHE + WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s); +#endif +WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, + size_t chklen, unsigned int flags, char **peername); + +WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, + const WOLFSSL_ASN1_INTEGER *a); + +#ifdef HAVE_SESSION_TICKET +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +#endif + +#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(X509)** chain); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*)(WOLFSSL*, void*)); + +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); + +WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x); + +WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, + WOLFSSL_X509 *subject); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x); + +WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( + WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx); +#endif /* HAVE_OCSP */ + +WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, + WOLFSSL_X509 *cert); + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY*/ + +WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, + const unsigned char **data, unsigned int *len); +WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len); + + +#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context( + const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length); +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count); +#endif + +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len); +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len); +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x); +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor); +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x); +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub); +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir); +WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx); +WOLFSSL_API void ERR_load_SSL_strings(void); +WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p); + +WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag); +WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags); +WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out); +WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); +WOLFSSL_API int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE *store); +WOLFSSL_API long wolfSSL_X509_get_version(const WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509* x); + +WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd, + int passwdSz, pem_password_cb* cb, void* ctx); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, pem_password_cb* cb, void* u); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey( + WOLFSSL_EVP_PKEY** pkey, const unsigned char** data, long length); + +#endif /* OPENSSL_EXTRA */ + +#ifdef HAVE_PK_CALLBACKS +WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_SSL_H */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/version.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/version.h new file mode 100644 index 000000000..19377a212 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/version.h @@ -0,0 +1,32 @@ +/* wolfssl_version.h.in + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + + +#ifndef WOLFSSL_VERSION_H +#define WOLFSSL_VERSION_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBWOLFSSL_VERSION_STRING "3.15.7" +#define LIBWOLFSSL_VERSION_HEX 0x03015007 + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_VERSION_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h new file mode 100644 index 000000000..60d3467f8 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/aes.h @@ -0,0 +1,359 @@ +/* aes.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/aes.h +*/ + + +#ifndef WOLF_CRYPT_AES_H +#define WOLF_CRYPT_AES_H + +#include + +#ifndef NO_AES + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +/* included for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#include +#if defined(CYASSL_AES_COUNTER) && !defined(WOLFSSL_AES_COUNTER) + #define WOLFSSL_AES_COUNTER +#endif +#if !defined(WOLFSSL_AES_DIRECT) && defined(CYASSL_AES_DIRECT) + #define WOLFSSL_AES_DIRECT +#endif +#endif + +#ifndef WC_NO_RNG + #include +#endif +#ifdef STM32_CRYPTO + #include +#endif + +#ifdef WOLFSSL_AESNI + +#include +#include +#include + +#endif /* WOLFSSL_AESNI */ + + +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_aes.h" +#endif + +#ifdef WOLFSSL_AFALG +/* included for struct msghdr */ +#include +#endif + +#if defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC) +#include +#endif + +#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG) + #include +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +/* these are required for FIPS and non-FIPS */ +enum { + AES_128_KEY_SIZE = 16, /* for 128 bit */ + AES_192_KEY_SIZE = 24, /* for 192 bit */ + AES_256_KEY_SIZE = 32, /* for 256 bit */ + + AES_IV_SIZE = 16, /* always block size */ +}; + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */ + AES_ENCRYPTION = 0, + AES_DECRYPTION = 1, + + AES_BLOCK_SIZE = 16, + + KEYWRAP_BLOCK_SIZE = 8, + + GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + GCM_NONCE_MIN_SZ = 8, /* wolfCrypt's minimum nonce size allowed. */ + CCM_NONCE_MIN_SZ = 7, + CCM_NONCE_MAX_SZ = 13, + CTR_SZ = 4, + AES_IV_FIXED_SZ = 4, + +#ifdef HAVE_PKCS11 + AES_MAX_ID_LEN = 32, +#endif +}; + + +typedef struct Aes { + /* AESNI needs key first, rounds 2nd, not sure why yet */ + ALIGN16 word32 key[60]; + word32 rounds; + int keylen; + + ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + word32 invokeCtr[2]; + word32 nonceSz; +#endif +#ifdef HAVE_AESGCM + ALIGN16 byte H[AES_BLOCK_SIZE]; +#ifdef GCM_TABLE + /* key-based fast multiplication table. */ + ALIGN16 byte M0[256][AES_BLOCK_SIZE]; +#endif /* GCM_TABLE */ +#endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AESNI + byte use_aesni; +#endif /* WOLFSSL_AESNI */ +#ifdef WOLF_CRYPTO_DEV + int devId; +#endif +#ifdef HAVE_PKCS11 + byte id[AES_MAX_ID_LEN]; + int idLen; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + word32 asyncKey[AES_MAX_KEY_SIZE/8/sizeof(word32)]; /* raw key */ + word32 asyncIv[AES_BLOCK_SIZE/sizeof(word32)]; /* raw IV */ + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + word32 left; /* unused bytes left from last call */ +#endif +#ifdef WOLFSSL_XILINX_CRYPT + XSecure_Aes xilAes; + XCsuDma dma; + word32 key_init[8]; + word32 kup; +#endif +#ifdef WOLFSSL_AFALG + int alFd; /* server socket to bind to */ + int rdFd; /* socket to read from */ + struct msghdr msg; + int dir; /* flag for encrpyt or decrypt */ +#endif +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + word32 devKey[AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE/sizeof(word32)]; /* raw key */ + WC_CRYPTODEV ctx; +#endif + void* heap; /* memory hint to use */ +} Aes; + +#ifdef WOLFSSL_AES_XTS +typedef struct XtsAes { + Aes aes; + Aes tweak; +} XtsAes; +#endif + +#ifdef HAVE_AESGCM +typedef struct Gmac { + Aes aes; +} Gmac; +#endif /* HAVE_AESGCM */ +#endif /* HAVE_FIPS */ + + +/* Authenticate cipher function prototypes */ +typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +/* AES-CBC */ +WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir); +WOLFSSL_API int wc_AesSetIV(Aes* aes, const byte* iv); + +#ifdef HAVE_AES_CBC +WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + +#ifdef WOLFSSL_AES_CFB +WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#ifdef HAVE_AES_DECRYPT +WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef HAVE_AES_ECB +WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) + WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in); + WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in); + WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir); +#endif + +#ifdef HAVE_AESGCM +#ifdef WOLFSSL_XILINX_CRYPT + WOLFSSL_API int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, + word32 kup); +#endif + WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len); + WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +#ifndef WC_NO_RNG + WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); + WOLFSSL_API int wc_AesGcmSetIV(Aes* aes, word32 ivSz, + const byte* ivFixed, word32 ivFixedSz, + WC_RNG* rng); + WOLFSSL_API int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* WC_NO_RNG */ + + WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len); + WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz); +#ifndef WC_NO_RNG + WOLFSSL_API int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz, WC_RNG* rng); + WOLFSSL_API int wc_GmacVerify(const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + const byte* authTag, word32 authTagSz); +#endif /* WC_NO_RNG */ + WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz); +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); + WOLFSSL_API int wc_AesCcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesCcmSetNonce(Aes* aes, + const byte* nonce, word32 nonceSz); + WOLFSSL_API int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* HAVE_AESCCM */ +#ifdef HAVE_AES_KEYWRAP + WOLFSSL_API int wc_AesKeyWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); + WOLFSSL_API int wc_AesKeyUnWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); +#endif /* HAVE_AES_KEYWRAP */ + +#ifdef WOLFSSL_AES_XTS + +WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key, + word32 len, int dir, void* heap, int devId); + +WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); +#endif + +WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); + +WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, + int devId); +#endif +WOLFSSL_API void wc_AesFree(Aes* aes); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* NO_AES */ +#endif /* WOLF_CRYPT_AES_H */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h new file mode 100644 index 000000000..cbb9b198d --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/arc4.h @@ -0,0 +1,60 @@ +/* arc4.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/arc4.h +*/ + +#ifndef WOLF_CRYPT_ARC4_H +#define WOLF_CRYPT_ARC4_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + ARC4_ENC_TYPE = 4, /* cipher unique type */ + ARC4_STATE_SIZE = 256, + RC4_KEY_SIZE = 16, /* always 128bit */ +}; + +/* ARC4 encryption and decryption */ +typedef struct Arc4 { + byte x; + byte y; + byte state[ARC4_STATE_SIZE]; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif + void* heap; +} Arc4; + +WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32); +WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32); + +WOLFSSL_API int wc_Arc4Init(Arc4*, void*, int); +WOLFSSL_API void wc_Arc4Free(Arc4*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_ARC4_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h new file mode 100644 index 000000000..7199ce29f --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/asn_public.h @@ -0,0 +1,508 @@ +/* asn_public.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/asn_public.h +*/ + +#ifndef WOLF_CRYPT_ASN_PUBLIC_H +#define WOLF_CRYPT_ASN_PUBLIC_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* guard on redeclaration */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif +#ifndef WC_RNG_TYPE_DEFINED + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + + +/* Certificate file Type */ +enum CertType { + CERT_TYPE = 0, + PRIVATEKEY_TYPE, + DH_PARAM_TYPE, + DSA_PARAM_TYPE, + CRL_TYPE, + CA_TYPE, + ECC_PRIVATEKEY_TYPE, + DSA_PRIVATEKEY_TYPE, + CERTREQ_TYPE, + DSA_TYPE, + ECC_TYPE, + RSA_TYPE, + PUBLICKEY_TYPE, + RSA_PUBLICKEY_TYPE, + ECC_PUBLICKEY_TYPE, + TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, + ED25519_TYPE, + PKCS12_TYPE, + PKCS8_PRIVATEKEY_TYPE, + PKCS8_ENC_PRIVATEKEY_TYPE +}; + + +/* Signature type, by OID sum */ +enum Ctc_SigType { + CTC_SHAwDSA = 517, + CTC_MD2wRSA = 646, + CTC_MD5wRSA = 648, + CTC_SHAwRSA = 649, + CTC_SHAwECDSA = 520, + CTC_SHA224wRSA = 658, + CTC_SHA224wECDSA = 523, + CTC_SHA256wRSA = 655, + CTC_SHA256wECDSA = 524, + CTC_SHA384wRSA = 656, + CTC_SHA384wECDSA = 525, + CTC_SHA512wRSA = 657, + CTC_SHA512wECDSA = 526, + CTC_ED25519 = 256 +}; + +enum Ctc_Encoding { + CTC_UTF8 = 0x0c, /* utf8 */ + CTC_PRINTABLE = 0x13 /* printable */ +}; + +#ifndef WC_CTC_NAME_SIZE + #define WC_CTC_NAME_SIZE 64 +#endif +#ifndef WC_CTC_MAX_ALT_SIZE + #define WC_CTC_MAX_ALT_SIZE 16384 +#endif + +enum Ctc_Misc { + CTC_COUNTRY_SIZE = 2, + CTC_NAME_SIZE = WC_CTC_NAME_SIZE, + CTC_DATE_SIZE = 32, + CTC_MAX_ALT_SIZE = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */ + CTC_SERIAL_SIZE = 16, +#ifdef WOLFSSL_CERT_EXT + /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum + * We support only hash */ + CTC_MAX_SKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_AKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_CERTPOL_SZ = 64, + CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */ +#endif /* WOLFSSL_CERT_EXT */ +}; + +/* DER buffer */ +typedef struct DerBuffer { + byte* buffer; + void* heap; + word32 length; + int type; /* enum CertType */ + int dynType; /* DYNAMIC_TYPE_* */ +} DerBuffer; + +enum { + IV_SZ = 32, /* max iv sz */ + NAME_SZ = 80, /* max one line */ + + PEM_PASS_READ = 0, + PEM_PASS_WRITE = 1, +}; + + +typedef int (pem_password_cb)(char* passwd, int sz, int rw, void* userdata); + +typedef struct EncryptedInfo { + pem_password_cb* passwd_cb; + void* passwd_userdata; + + long consumed; /* tracks PEM bytes consumed */ + + int cipherType; + word32 keySz; + word32 ivSz; /* salt or encrypted IV size */ + + char name[NAME_SZ]; /* cipher name, such as "DES-CBC" */ + byte iv[IV_SZ]; /* salt or encrypted IV */ + + word16 set:1; /* if encryption set */ +} EncryptedInfo; + + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) +#ifdef WOLFSSL_EKU_OID + #ifndef CTC_MAX_EKU_NB + #define CTC_MAX_EKU_NB 1 + #endif + #ifndef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 30 + #endif +#else + #undef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 0 +#endif +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_CERT_GEN + +#ifdef WOLFSSL_MULTI_ATTRIB +#ifndef CTC_MAX_ATTRIB + #define CTC_MAX_ATTRIB 4 +#endif + +/* ASN Encoded Name field */ +typedef struct NameAttrib { + int sz; /* actual string value length */ + int id; /* id of name */ + int type; /* enc of name */ + char value[CTC_NAME_SIZE]; /* name */ +} NameAttrib; +#endif /* WOLFSSL_MULTI_ATTRIB */ + + +typedef struct CertName { + char country[CTC_NAME_SIZE]; + char countryEnc; + char state[CTC_NAME_SIZE]; + char stateEnc; + char locality[CTC_NAME_SIZE]; + char localityEnc; + char sur[CTC_NAME_SIZE]; + char surEnc; + char org[CTC_NAME_SIZE]; + char orgEnc; + char unit[CTC_NAME_SIZE]; + char unitEnc; + char commonName[CTC_NAME_SIZE]; + char commonNameEnc; + char serialDev[CTC_NAME_SIZE]; + char serialDevEnc; +#ifdef WOLFSSL_CERT_EXT + char busCat[CTC_NAME_SIZE]; + char busCatEnc; + char joiC[CTC_NAME_SIZE]; + char joiCEnc; + char joiSt[CTC_NAME_SIZE]; + char joiStEnc; +#endif + char email[CTC_NAME_SIZE]; /* !!!! email has to be last !!!! */ +#ifdef WOLFSSL_MULTI_ATTRIB + NameAttrib name[CTC_MAX_ATTRIB]; +#endif +} CertName; + + +/* for user to fill for certificate generation */ +typedef struct Cert { + int version; /* x509 version */ + byte serial[CTC_SERIAL_SIZE]; /* serial number */ + int serialSz; /* serial size */ + int sigType; /* signature algo type */ + CertName issuer; /* issuer info */ + int daysValid; /* validity days */ + int selfSigned; /* self signed flag */ + CertName subject; /* subject info */ + int isCA; /* is this going to be a CA */ + /* internal use only */ + int bodySz; /* pre sign total size */ + int keyType; /* public key type of subject */ +#ifdef WOLFSSL_ALT_NAMES + byte altNames[CTC_MAX_ALT_SIZE]; /* altNames copy */ + int altNamesSz; /* altNames size in bytes */ + byte beforeDate[CTC_DATE_SIZE]; /* before date copy */ + int beforeDateSz; /* size of copy */ + byte afterDate[CTC_DATE_SIZE]; /* after date copy */ + int afterDateSz; /* size of copy */ +#endif +#ifdef WOLFSSL_CERT_EXT + byte skid[CTC_MAX_SKID_SIZE]; /* Subject Key Identifier */ + int skidSz; /* SKID size in bytes */ + byte akid[CTC_MAX_AKID_SIZE]; /* Authority Key Identifier */ + int akidSz; /* AKID size in bytes */ + word16 keyUsage; /* Key Usage */ + byte extKeyUsage; /* Extended Key Usage */ +#ifdef WOLFSSL_EKU_OID + /* Extended Key Usage OIDs */ + byte extKeyUsageOID[CTC_MAX_EKU_NB][CTC_MAX_EKU_OID_SZ]; + byte extKeyUsageOIDSz[CTC_MAX_EKU_NB]; +#endif + char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; + word16 certPoliciesNb; /* Number of Cert Policy */ + byte issRaw[sizeof(CertName)]; /* raw issuer info */ + byte sbjRaw[sizeof(CertName)]; /* raw subject info */ +#endif +#ifdef WOLFSSL_CERT_REQ + char challengePw[CTC_NAME_SIZE]; +#endif + void* heap; /* heap hint */ +} Cert; + + + +/* Initialize and Set Certificate defaults: + version = 3 (0x2) + serial = 0 (Will be randomly generated) + sigType = SHA_WITH_RSA + issuer = blank + daysValid = 500 + selfSigned = 1 (true) use subject as issuer + subject = blank + isCA = 0 (false) + keyType = RSA_KEY (default) +*/ +WOLFSSL_API int wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, + int keyType, void* key, WC_RNG* rng); +WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + ecc_key*, WC_RNG*); +#ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz, + int, void*); + WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, + RsaKey*, ecc_key*); +#endif +WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer, + word32 buffSz, int keyType, void* key, + WC_RNG* rng); +WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer, + word32 derSz, RsaKey*, ecc_key*, WC_RNG*); +WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + WC_RNG*); +WOLFSSL_API int wc_SetIssuer(Cert*, const char*); +WOLFSSL_API int wc_SetSubject(Cert*, const char*); +#ifdef WOLFSSL_ALT_NAMES + WOLFSSL_API int wc_SetAltNames(Cert*, const char*); +#endif +WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); + +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetCertDates(Cert* cert, struct tm* before, + struct tm* after); +#endif + +#ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); +WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert); +WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz); +WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz); + +#ifdef HAVE_NTRU +WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, + word16 ntruKeySz); +#endif + +/* Set the KeyUsage. + * Value is a string separated tokens with ','. Accepted tokens are : + * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign, + * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly. + * + * nonRepudiation and contentCommitment are for the same usage. + */ +WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); + +/* Set ExtendedKeyUsage + * Value is a string separated tokens with ','. Accepted tokens are : + * any,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning + */ +WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value); + + +#ifdef WOLFSSL_EKU_OID +/* Set ExtendedKeyUsage with unique OID + * oid is expected to be in byte representation + */ +WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz, + byte idx, void* heap); +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ + + #ifdef HAVE_NTRU + WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, + const byte* ntruKey, word16 keySz, + WC_RNG*); + #endif + +#endif /* WOLFSSL_CERT_GEN */ + +WOLFSSL_API int wc_GetDateInfo(const byte* certDate, int certDateSz, + const byte** date, byte* format, int* length); +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetDateAsCalendarTime(const byte* date, int length, + byte format, struct tm* time); +#endif + +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + + WOLFSSL_API int wc_PemGetHeaderFooter(int type, const char** header, + const char** footer); + +#endif + +WOLFSSL_API int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap); +WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); + +#ifdef WOLFSSL_PEM_TO_DER + WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey); + + WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int, + unsigned char*, int, const char*); + WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int, + unsigned char*, int, int); +#endif /* WOLFSSL_PEM_TO_DER */ + +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + + WOLFSSL_API int wc_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#ifdef WOLFSSL_CERT_GEN + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemCertToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif +#endif /* WOLFSSL_CERT_GEN */ + +#ifdef WOLFSSL_DER_TO_PEM + WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, + word32 outputSz, int type); + WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, + word32 outputSz, byte *cipherIno, int type); +#endif + +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); +#endif + +#ifdef HAVE_ECC + /* private key helpers */ + WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, + ecc_key*, word32); + WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen); + + /* public key helper */ + WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, + ecc_key*, word32); + WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output, + word32 inLen, int with_AlgCurve); +#endif + +#ifdef HAVE_ED25519 + /* private key helpers */ + WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, + ed25519_key*, word32); + WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, + ed25519_key*, word32); + #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif +#endif + +/* DER encode signature */ +WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, + word32 digSz, int hashOID); +WOLFSSL_API int wc_GetCTC_HashOID(int type); + +WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, + word32* inOutIdx, word32 sz); +WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); + +#ifndef NO_ASN_TIME +/* Time */ +/* Returns seconds (Epoch/UTC) + * timePtr: is "time_t", which is typically "long" + * Example: + long lTime; + rc = wc_GetTime(&lTime, (word32)sizeof(lTime)); +*/ +WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS + WOLFSSL_API int wc_EncryptedInfoGet(EncryptedInfo* info, + const char* cipherInfo); +#endif + + +#ifdef WOLFSSL_CERT_PIV + +typedef struct _wc_CertPIV { + const byte* cert; + word32 certSz; + const byte* certErrDet; + word32 certErrDetSz; + const byte* nonce; /* Identiv Only */ + word32 nonceSz; /* Identiv Only */ + const byte* signedNonce; /* Identiv Only */ + word32 signedNonceSz; /* Identiv Only */ + + /* flags */ + word16 compression:2; + word16 isX509:1; + word16 isIdentiv:1; +} wc_CertPIV; + +WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalSz); +#endif /* WOLFSSL_CERT_PIV */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_ASN_PUBLIC_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h new file mode 100644 index 000000000..95254c34a --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/des3.h @@ -0,0 +1,139 @@ +/* des3.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/des3.h +*/ + +#ifndef WOLF_CRYPT_DES3_H +#define WOLF_CRYPT_DES3_H + +#include + +#ifndef NO_DES3 + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* included for fips @wc_fips */ +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* these are required for FIPS and non-FIPS */ +enum { + DES_KEY_SIZE = 8, /* des */ + DES3_KEY_SIZE = 24, /* 3 des ede */ + DES_IV_SIZE = 8, /* should be the same as DES_BLOCK_SIZE */ +}; + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + DES_ENC_TYPE = WC_CIPHER_DES, /* cipher unique type */ + DES3_ENC_TYPE = WC_CIPHER_DES3, /* cipher unique type */ + + DES_BLOCK_SIZE = 8, + DES_KS_SIZE = 32, /* internal DES key buffer size */ + + DES_ENCRYPTION = 0, + DES_DECRYPTION = 1 +}; + +#define DES_IVLEN 8 +#define DES_KEYLEN 8 +#define DES3_IVLEN 8 +#define DES3_KEYLEN 24 + + +#if defined(STM32_CRYPTO) +enum { + DES_CBC = 0, + DES_ECB = 1 +}; +#endif + + +/* DES encryption and decryption */ +typedef struct Des { + word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ + word32 key[DES_KS_SIZE]; +} Des; + + +/* DES3 encryption and decryption */ +typedef struct Des3 { + word32 key[3][DES_KS_SIZE]; + word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ +#ifdef WOLFSSL_ASYNC_CRYPT + const byte* key_raw; + const byte* iv_raw; + WC_ASYNC_DEV asyncDev; +#endif + void* heap; +} Des3; +#endif /* HAVE_FIPS */ + + +WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, + const byte* iv, int dir); +WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv); +WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_EcbEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out, + const byte* in, word32 sz); + +/* ECB decrypt same process as encrypt but with decrypt key */ +#define wc_Des_EcbDecrypt wc_Des_EcbEncrypt +#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt + +WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, + const byte* iv,int dir); +WOLFSSL_API int wc_Des3_SetIV(Des3* des, const byte* iv); +WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, + const byte* in,word32 sz); +WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, + const byte* in,word32 sz); + +/* These are only required when using either: + static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */ +WOLFSSL_API int wc_Des3Init(Des3*, void*, int); +WOLFSSL_API void wc_Des3Free(Des3*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DES3 */ +#endif /* WOLF_CRYPT_DES3_H */ + diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h similarity index 84% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h index 1b26ca606..0048968b3 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/ecc.h @@ -1,15 +1,20 @@ /* ecc.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ +/*! + \file wolfssl/wolfcrypt/ecc.h +*/ + #ifndef WOLF_CRYPT_ECC_H #define WOLF_CRYPT_ECC_H @@ -67,12 +72,12 @@ #define MAX_ECC_BITS 384 #elif defined(HAVE_ECC320) #define MAX_ECC_BITS 320 +#elif !defined(NO_ECC256) + #define MAX_ECC_BITS 256 #elif defined(HAVE_ECC239) #define MAX_ECC_BITS 239 #elif defined(HAVE_ECC224) #define MAX_ECC_BITS 224 -#elif !defined(NO_ECC256) - #define MAX_ECC_BITS 256 #elif defined(HAVE_ECC192) #define MAX_ECC_BITS 192 #elif defined(HAVE_ECC160) @@ -109,9 +114,22 @@ enum { /* max crypto hardware size */ #ifdef WOLFSSL_ATECC508A ECC_MAX_CRYPTO_HW_SIZE = ATECC_KEY_SIZE, /* from port/atmel/atmel.h */ + ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2), #elif defined(PLUTON_CRYPTO_ECC) ECC_MAX_CRYPTO_HW_SIZE = 32, #endif + + /* point compression type */ + ECC_POINT_COMP_EVEN = 0x02, + ECC_POINT_COMP_ODD = 0x03, + ECC_POINT_UNCOMP = 0x04, + + /* Shamir's dual add constants */ + SHAMIR_PRECOMP_SZ = 16, + +#ifdef HAVE_PKCS11 + ECC_MAX_ID_LEN = 32, +#endif }; /* Curve Types */ @@ -177,6 +195,7 @@ typedef byte ecc_oid_t; #endif /* ECC set type defined a GF(p) curve */ +#ifndef USE_WINDOWS_API typedef struct ecc_set_type { int size; /* The size of the curve in octets */ int id; /* id of this curve */ @@ -192,6 +211,31 @@ typedef struct ecc_set_type { word32 oidSum; /* sum of encoded OID bytes */ int cofactor; } ecc_set_type; +#else +/* MSC does something different with the pointers to the arrays than GCC, + * and it causes the FIPS checksum to fail. In the case of windows builds, + * store everything as arrays instead of pointers to strings. */ + +#define MAX_ECC_NAME 16 +#define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 1) + /* The values are stored as text strings. */ + +typedef struct ecc_set_type { + int size; /* The size of the curve in octets */ + int id; /* id of this curve */ + const char name[MAX_ECC_NAME]; /* name of this curve */ + const char prime[MAX_ECC_STRING]; /* prime that defines the field, curve is in (hex) */ + const char Af[MAX_ECC_STRING]; /* fields A param (hex) */ + const char Bf[MAX_ECC_STRING]; /* fields B param (hex) */ + const char order[MAX_ECC_STRING]; /* order of the curve (hex) */ + const char Gx[MAX_ECC_STRING]; /* x coordinate of the base point on curve (hex) */ + const char Gy[MAX_ECC_STRING]; /* y coordinate of the base point on curve (hex) */ + const ecc_oid_t oid[10]; + word32 oidSz; + word32 oidSum; /* sum of encoded OID bytes */ + int cofactor; +} ecc_set_type; +#endif #ifdef ALT_ECC_SIZE @@ -248,10 +292,15 @@ typedef struct ecc_set_type { * fp_digit array will be shorter. */ typedef struct alt_fp_int { int used, sign, size; - fp_digit dp[FP_SIZE_ECC]; + mp_digit dp[FP_SIZE_ECC]; } alt_fp_int; #endif /* ALT_ECC_SIZE */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif + /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ @@ -266,6 +315,9 @@ typedef struct { mp_int* z; /* The z coordinate */ alt_fp_int xyz[3]; #endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key* key; +#endif } ecc_point; /* ECC Flags */ @@ -294,25 +346,37 @@ struct ecc_key { mp_int k; /* private key */ #ifdef WOLFSSL_ATECC508A int slot; /* Key Slot Number (-1 unknown) */ - byte pubkey_raw[PUB_KEY_SIZE]; + byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE]; #endif -#ifdef PLUTON_CRYPTO_ECC +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV) int devId; #endif #ifdef WOLFSSL_ASYNC_CRYPT mp_int* r; /* sign/verify temps */ mp_int* s; WC_ASYNC_DEV asyncDev; + #ifdef HAVE_CAVIUM_V + mp_int* e; /* Sign, Verify and Shared Secret */ + mp_int* signK; + #endif #ifdef WOLFSSL_CERT_GEN CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ #endif #endif /* WOLFSSL_ASYNC_CRYPT */ -}; - -#ifndef WC_ECCKEY_TYPE_DEFINED - typedef struct ecc_key ecc_key; - #define WC_ECCKEY_TYPE_DEFINED +#ifdef HAVE_PKCS11 + byte id[ECC_MAX_ID_LEN]; + int idLen; #endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + mp_int* t1; + mp_int* t2; +#ifdef ALT_ECC_SIZE + mp_int* x; + mp_int* y; + mp_int* z; +#endif +#endif +}; /* ECC predefined curve sets */ @@ -388,6 +452,11 @@ WOLFSSL_API int wc_ecc_init(ecc_key* key); WOLFSSL_API int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API +int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, + int devId); +#endif #ifdef WOLFSSL_CUSTOM_CURVES WOLFSSL_LOCAL void wc_ecc_free_curve(const ecc_set_type* curve, void* heap); @@ -424,6 +493,8 @@ int wc_ecc_get_curve_id_from_params(int fieldSize, const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor); +WOLFSSL_API +int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len); WOLFSSL_API ecc_point* wc_ecc_new_point(void); @@ -474,6 +545,9 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, WOLFSSL_API int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); WOLFSSL_API +int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, + byte* out, word32* outlen); +WOLFSSL_API int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, byte* s, word32* sLen); WOLFSSL_API @@ -482,17 +556,24 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, WOLFSSL_API int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id); +WOLFSSL_API +int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, + byte* d, int curve_id); #endif /* HAVE_ECC_KEY_IMPORT */ #ifdef HAVE_ECC_KEY_EXPORT WOLFSSL_API +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, + int encType); +WOLFSSL_API int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); WOLFSSL_API int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, byte* qy, word32* qyLen); WOLFSSL_API int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, - byte* qy, word32* qyLen, byte* d, word32* dLen); + byte* qy, word32* qyLen, byte* d, word32* dLen); #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_EXPORT @@ -513,6 +594,8 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, WOLFSSL_API int wc_ecc_size(ecc_key* key); WOLFSSL_API +int wc_ecc_sig_size_calc(int sz); +WOLFSSL_API int wc_ecc_sig_size(ecc_key* key); WOLFSSL_API diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h new file mode 100644 index 000000000..9435b8f75 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hash.h @@ -0,0 +1,165 @@ +/* hash.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/hash.h +*/ + +#ifndef WOLF_CRYPT_HASH_H +#define WOLF_CRYPT_HASH_H + +#include + +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256) + #include +#endif +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #include +#endif +#ifdef HAVE_BLAKE2 + #include +#endif +#ifdef WOLFSSL_SHA3 + #include +#endif +#ifndef NO_MD4 + #include +#endif +#ifdef WOLFSSL_MD2 + #include +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#if !defined(HAVE_FIPS) && !defined(NO_OLD_WC_NAMES) + #define MAX_DIGEST_SIZE WC_MAX_DIGEST_SIZE +#endif + + +typedef union { + #ifndef NO_MD5 + wc_Md5 md5; + #endif + #ifndef NO_SHA + wc_Sha sha; + #endif + #ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; + #endif + #ifndef NO_SHA256 + wc_Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + #endif +} wc_HashAlg; + +/* Find largest possible digest size + Note if this gets up to the size of 80 or over check smallstack build */ +#if defined(WOLFSSL_SHA3) + #define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA3_224_BLOCK_SIZE /* 224 is the largest block size */ +#elif defined(WOLFSSL_SHA512) + #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA512_BLOCK_SIZE +#elif defined(HAVE_BLAKE2) + #define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES + #define WC_MAX_BLOCK_SIZE BLAKE2B_BLOCKBYTES +#elif defined(WOLFSSL_SHA384) + #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA384_BLOCK_SIZE +#elif !defined(NO_SHA256) + #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA256_BLOCK_SIZE +#elif defined(WOLFSSL_SHA224) + #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA224_BLOCK_SIZE +#elif !defined(NO_SHA) + #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA_BLOCK_SIZE +#elif !defined(NO_MD5) + #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_MD5_BLOCK_SIZE +#else + #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ + #define WC_MAX_BLOCK_SIZE 128 +#endif + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) +WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); +WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid); +#endif + +WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType); + +WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, + const byte* data, word32 data_len, + byte* hash, word32 hash_len); + +/* generic hash operation wrappers */ +WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type); +WOLFSSL_API int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, + const byte* data, word32 dataSz); +WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, + byte* out); +WOLFSSL_API int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type); + +#ifndef NO_MD5 +#include +WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash); +#endif + +#ifndef NO_SHA +#include +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA224 +#include +WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA224) */ + +#ifndef NO_SHA256 +#include +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA384 +#include +WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA384) */ + +#ifdef WOLFSSL_SHA512 +#include +WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); +#endif /* WOLFSSL_SHA512 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HASH_H */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h new file mode 100644 index 000000000..a539e571c --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/hmac.h @@ -0,0 +1,181 @@ +/* hmac.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/hmac.h +*/ + +#ifndef NO_HMAC + +#ifndef WOLF_CRYPT_HMAC_H +#define WOLF_CRYPT_HMAC_H + +#include + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* for fips @wc_fips */ + #include + #define WC_HMAC_BLOCK_SIZE HMAC_BLOCK_SIZE +#endif + + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifndef NO_OLD_WC_NAMES + #define HMAC_BLOCK_SIZE WC_HMAC_BLOCK_SIZE +#endif + +enum { + HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum */ + + IPAD = 0x36, + OPAD = 0x5C, + +/* If any hash is not enabled, add the ID here. */ +#ifdef NO_MD5 + WC_MD5 = WC_HASH_TYPE_MD5, +#endif +#ifdef NO_SHA + WC_SHA = WC_HASH_TYPE_SHA, +#endif +#ifdef NO_SHA256 + WC_SHA256 = WC_HASH_TYPE_SHA256, +#endif +#ifndef WOLFSSL_SHA512 + WC_SHA512 = WC_HASH_TYPE_SHA512, +#endif +#ifndef WOLFSSL_SHA384 + WC_SHA384 = WC_HASH_TYPE_SHA384, +#endif +#ifndef HAVE_BLAKE2 + BLAKE2B_ID = WC_HASH_TYPE_BLAKE2B, +#endif +#ifndef WOLFSSL_SHA224 + WC_SHA224 = WC_HASH_TYPE_SHA224, +#endif +#ifndef WOLFSSL_SHA3 + WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, + WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, + WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, + WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, +#endif +}; + +/* Select the largest available hash for the buffer size. */ +#define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE + +#if !defined(WOLFSSL_SHA3) && !defined(WOLFSSL_SHA512) && !defined(HAVE_BLAKE2) && \ + !defined(WOLFSSL_SHA384) && defined(NO_SHA256) && defined(WOLFSSL_SHA224) && \ + defined(NO_SHA) && defined(NO_MD5) + #error "You have to have some kind of hash if you want to use HMAC." +#endif + + +/* hash union */ +typedef union { +#ifndef NO_MD5 + wc_Md5 md5; +#endif +#ifndef NO_SHA + wc_Sha sha; +#endif +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; +#endif +#ifndef NO_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; +#endif +#ifdef HAVE_BLAKE2 + Blake2b blake2b; +#endif +#ifdef WOLFSSL_SHA3 + wc_Sha3 sha3; +#endif +} Hash; + +/* Hmac digest */ +typedef struct Hmac { + Hash hash; + word32 ipad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 opad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; + word32 innerHash[WC_MAX_DIGEST_SIZE / sizeof(word32)]; + void* heap; /* heap hint */ + byte macType; /* md5 sha or sha256 */ + byte innerHashKeyed; /* keyed flag */ + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + word16 keyLen; /* hmac key length (key in ipad) */ +#endif /* WOLFSSL_ASYNC_CRYPT */ +} Hmac; + +#endif /* HAVE_FIPS */ + +/* does init */ +WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz); +WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32); +WOLFSSL_API int wc_HmacFinal(Hmac*, byte*); +WOLFSSL_API int wc_HmacSizeByType(int type); + +WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId); +WOLFSSL_API void wc_HmacFree(Hmac*); + +WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); + +WOLFSSL_LOCAL int _InitHmac(Hmac* hmac, int type, void* heap); + +#ifdef HAVE_HKDF + +WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out); +WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + +WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + +#endif /* HAVE_HKDF */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HMAC_H */ + +#endif /* NO_HMAC */ + diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h similarity index 94% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h index 2ab1db1fc..cd677bb6f 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/integer.h @@ -1,12 +1,13 @@ /* integer.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ @@ -62,6 +63,11 @@ extern "C" { /* C++ compilers don't like assigning void * to mp_digit * */ #define OPT_CAST(x) (x *) +#elif defined(_SH3) + +/* SuperH SH3 compiler doesn't like assigning voi* to mp_digit* */ +#define OPT_CAST(x) (x *) + #else /* C on the other hand doesn't care */ @@ -268,6 +274,7 @@ MP_API int mp_unsigned_bin_size(mp_int * a); MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); /* end functions needed by Rsa */ @@ -354,15 +361,19 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); #define mp_dump(desc, a, verbose) #endif -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); #endif #if !defined(NO_DSA) || defined(HAVE_ECC) MP_API int mp_read_radix(mp_int* a, const char* str, int radix); #endif -#ifdef WOLFSSL_KEY_GEN +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || !defined(NO_DSA) || !defined(NO_DH) MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*); +#endif /* WOLFSSL_KEY_GEN NO_RSA NO_DSA NO_DH */ +#ifdef WOLFSSL_KEY_GEN MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h new file mode 100644 index 000000000..0a2d7f6b1 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/logging.h @@ -0,0 +1,179 @@ +/* logging.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/logging.h +*/ + + +/* submitted by eof */ + + +#ifndef WOLFSSL_LOGGING_H +#define WOLFSSL_LOGGING_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +enum wc_LogLevels { + ERROR_LOG = 0, + INFO_LOG, + ENTER_LOG, + LEAVE_LOG, + OTHER_LOG +}; + +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +enum wc_FuncNum { + WC_FUNC_HELLO_REQUEST_SEND = 0, + WC_FUNC_HELLO_REQUEST_DO, + WC_FUNC_CLIENT_HELLO_SEND, + WC_FUNC_CLIENT_HELLO_DO, + WC_FUNC_SERVER_HELLO_SEND, + WC_FUNC_SERVER_HELLO_DO, + WC_FUNC_ENCRYPTED_EXTENSIONS_SEND, + WC_FUNC_ENCRYPTED_EXTENSIONS_DO, + WC_FUNC_CERTIFICATE_REQUEST_SEND, + WC_FUNC_CERTIFICATE_REQUEST_DO, + WC_FUNC_CERTIFICATE_SEND, + WC_FUNC_CERTIFICATE_DO, + WC_FUNC_CERTIFICATE_VERIFY_SEND, + WC_FUNC_CERTIFICATE_VERIFY_DO, + WC_FUNC_FINISHED_SEND, + WC_FUNC_FINISHED_DO, + WC_FUNC_KEY_UPDATE_SEND, + WC_FUNC_KEY_UPDATE_DO, + WC_FUNC_EARLY_DATA_SEND, + WC_FUNC_EARLY_DATA_DO, + WC_FUNC_NEW_SESSION_TICKET_SEND, + WC_FUNC_NEW_SESSION_TICKET_DO, + WC_FUNC_SERVER_HELLO_DONE_SEND, + WC_FUNC_SERVER_HELLO_DONE_DO, + WC_FUNC_TICKET_SEND, + WC_FUNC_TICKET_DO, + WC_FUNC_CLIENT_KEY_EXCHANGE_SEND, + WC_FUNC_CLIENT_KEY_EXCHANGE_DO, + WC_FUNC_CERTIFICATE_STATUS_SEND, + WC_FUNC_CERTIFICATE_STATUS_DO, + WC_FUNC_SERVER_KEY_EXCHANGE_SEND, + WC_FUNC_SERVER_KEY_EXCHANGE_DO, + WC_FUNC_END_OF_EARLY_DATA_SEND, + WC_FUNC_END_OF_EARLY_DATA_DO, + WC_FUNC_COUNT +}; +#endif + +typedef void (*wolfSSL_Logging_cb)(const int logLevel, + const char *const logMessage); + +WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); + +/* turn logging on, only if compiled in */ +WOLFSSL_API int wolfSSL_Debugging_ON(void); +/* turn logging off */ +WOLFSSL_API void wolfSSL_Debugging_OFF(void); + + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_LOCAL int wc_LoggingInit(void); + WOLFSSL_LOCAL int wc_LoggingCleanup(void); + WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf, + char* file); + WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file, + const char **reason, int *line); + WOLFSSL_LOCAL void wc_RemoveErrorNode(int index); + WOLFSSL_LOCAL void wc_ClearErrorNodes(void); + WOLFSSL_LOCAL int wc_PullErrorNode(const char **file, const char **reason, + int *line); + WOLFSSL_API int wc_SetLoggingHeap(void* h); + WOLFSSL_API int wc_ERR_remove_state(void); + #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + WOLFSSL_API void wc_ERR_print_errors_fp(XFILE fp); + #endif +#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ + +#ifdef WOLFSSL_FUNC_TIME + /* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ + WOLFSSL_API void WOLFSSL_START(int funcNum); + WOLFSSL_API void WOLFSSL_END(int funcNum); + WOLFSSL_API void WOLFSSL_TIME(int count); +#else + #define WOLFSSL_START(n) + #define WOLFSSL_END(n) + #define WOLFSSL_TIME(n) +#endif + +#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_DEBUG_ERRORS_ONLY) + #if defined(_WIN32) + #if defined(INTIME_RTOS) + #define __func__ NULL + #else + #define __func__ __FUNCTION__ + #endif + #endif + + /* a is prepended to m and b is appended, creating a log msg a + m + b */ + #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " " #b + + WOLFSSL_API void WOLFSSL_ENTER(const char* msg); + WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret); + #define WOLFSSL_STUB(m) \ + WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) + + WOLFSSL_API void WOLFSSL_MSG(const char* msg); + WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); + +#else + + #define WOLFSSL_ENTER(m) + #define WOLFSSL_LEAVE(m, r) + #define WOLFSSL_STUB(m) + + #define WOLFSSL_MSG(m) + #define WOLFSSL_BUFFER(b, l) + +#endif /* DEBUG_WOLFSSL && !WOLFSSL_DEBUG_ERRORS_ONLY */ + +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_API void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line, + const char* file, void* ctx); + #define WOLFSSL_ERROR(x) \ + WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__, NULL) + #else + WOLFSSL_API void WOLFSSL_ERROR(int err); + #endif + WOLFSSL_API void WOLFSSL_ERROR_MSG(const char* msg); + +#else + #define WOLFSSL_ERROR(e) + #define WOLFSSL_ERROR_MSG(m) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* WOLFSSL_LOGGING_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h new file mode 100644 index 000000000..9386b388a --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/md5.h @@ -0,0 +1,114 @@ +/* md5.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/md5.h +*/ + + +#ifndef WOLF_CRYPT_MD5_H +#define WOLF_CRYPT_MD5_H + +#include + +#ifndef NO_MD5 + +#ifdef HAVE_FIPS + #define wc_InitMd5 InitMd5 + #define wc_Md5Update Md5Update + #define wc_Md5Final Md5Final + #define wc_Md5Hash Md5Hash +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef NO_OLD_WC_NAMES + #define Md5 wc_Md5 + #define MD5 WC_MD5 + #define MD5_BLOCK_SIZE WC_MD5_BLOCK_SIZE + #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_MD5 = WC_HASH_TYPE_MD5, + WC_MD5_BLOCK_SIZE = 64, + WC_MD5_DIGEST_SIZE = 16, + WC_MD5_PAD_SIZE = 56 +}; + + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else + +/* MD5 digest */ +typedef struct wc_Md5 { +#ifdef STM32_HASH + STM32_HASH_Context stmCtx; +#else + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[WC_MD5_BLOCK_SIZE / sizeof(word32)]; +#ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; +#else + word32 digest[WC_MD5_DIGEST_SIZE / sizeof(word32)]; +#endif + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#endif /* STM32_HASH */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} wc_Md5; + +#endif /* WOLFSSL_TI_HASH */ + +WOLFSSL_API int wc_InitMd5(wc_Md5*); +WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int); +WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32); +WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*); +WOLFSSL_API void wc_Md5Free(wc_Md5*); + +WOLFSSL_API int wc_Md5GetHash(wc_Md5*, byte*); +WOLFSSL_API int wc_Md5Copy(wc_Md5*, wc_Md5*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Md5SizeSet(wc_Md5* md5, word32 len); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ +#endif /* WOLF_CRYPT_MD5_H */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h similarity index 98% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h index d612969d3..2d5b23e1a 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_class.h @@ -1,12 +1,13 @@ /* mpi_class.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h similarity index 90% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h index 3f61dfafb..049d90018 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h @@ -1,12 +1,13 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h new file mode 100644 index 000000000..132d8d2bb --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/pwdbased.h @@ -0,0 +1,63 @@ +/* pwdbased.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/pwdbased.h +*/ + +#ifndef WOLF_CRYPT_PWDBASED_H +#define WOLF_CRYPT_PWDBASED_H + +#include + +#ifndef NO_PWDBASED + + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * hashType renamed to typeH to avoid shadowing global declaration here: + * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types + */ +WOLFSSL_API int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, + const byte* passwd, int passwdLen, + const byte* salt, int saltLen, int iterations, + int hashType, void* heap); +WOLFSSL_API int wc_PBKDF1(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, int kLen, + int typeH); +WOLFSSL_API int wc_PBKDF2(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, int kLen, + int typeH); +WOLFSSL_API int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, + int kLen, int typeH, int purpose); +WOLFSSL_API int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen, + const byte* salt, int saltLen, int iterations, int kLen, + int hashType, int id, void* heap); + +#ifdef HAVE_SCRYPT +WOLFSSL_API int wc_scrypt(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int cost, + int blockSize, int parallel, int dkLen); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_PWDBASED */ +#endif /* WOLF_CRYPT_PWDBASED_H */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h new file mode 100644 index 000000000..361532729 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/random.h @@ -0,0 +1,218 @@ +/* random.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/random.h +*/ + + + +#ifndef WOLF_CRYPT_RANDOM_H +#define WOLF_CRYPT_RANDOM_H + +#include + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +/* included for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + /* Maximum generate block length */ +#ifndef RNG_MAX_BLOCK_LEN + #ifdef HAVE_INTEL_QA + #define RNG_MAX_BLOCK_LEN (0xFFFF) + #else + #define RNG_MAX_BLOCK_LEN (0x10000) + #endif +#endif + +/* Size of the BRBG seed */ +#ifndef DRBG_SEED_LEN + #define DRBG_SEED_LEN (440/8) +#endif + + +#if !defined(CUSTOM_RAND_TYPE) + /* To maintain compatibility the default is byte */ + #define CUSTOM_RAND_TYPE byte +#endif + +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined + or CUSTOM_RAND_GENERATE_BLOCK is defined */ +#if !defined(WC_NO_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) + #undef HAVE_HASHDRBG + #define HAVE_HASHDRBG + #ifndef WC_RESEED_INTERVAL + #define WC_RESEED_INTERVAL (1000000) + #endif +#endif + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +/* RNG supports the following sources (in order): + * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and + * bypasses the options below. + * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. + * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG + * seeded via wc_GenerateSeed. This is the default source. + */ + + /* Seed source can be overriden by defining one of these: + CUSTOM_RAND_GENERATE_SEED + CUSTOM_RAND_GENERATE_SEED_OS + CUSTOM_RAND_GENERATE */ + + +#if defined(CUSTOM_RAND_GENERATE_BLOCK) + /* To use define the following: + * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ +#elif defined(HAVE_HASHDRBG) + #ifdef NO_SHA256 + #error "Hash DRBG requires SHA-256." + #endif /* NO_SHA256 */ + #include +#elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ +#elif defined(HAVE_INTEL_RDRAND) + /* Intel RDRAND or RDSEED */ +#elif !defined(WC_NO_RNG) + #error No RNG source defined! +#endif + +#ifdef HAVE_WNR + #include +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + + +#if defined(USE_WINDOWS_API) + #if defined(_WIN64) + typedef unsigned __int64 ProviderHandle; + /* type HCRYPTPROV, avoid #include */ + #else + typedef unsigned long ProviderHandle; + #endif +#endif + + +/* OS specific seeder */ +typedef struct OS_Seed { + #if defined(USE_WINDOWS_API) + ProviderHandle handle; + #else + int fd; + #endif +} OS_Seed; + + +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + +/* RNG context */ +struct WC_RNG { + OS_Seed seed; + void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ + struct DRBG* drbg; + byte status; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + int devId; +#endif +}; + +#endif /* NO FIPS or have FIPS v2*/ + +/* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, + * can't be used with CTaoCrypt FIPS */ +#if !defined(NO_OLD_RNGNAME) && !defined(HAVE_FIPS) + #define RNG WC_RNG +#endif + + +WOLFSSL_LOCAL +int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); + + +#ifdef HAVE_WNR + /* Whitewood netRandom client library */ + WOLFSSL_API int wc_InitNetRandom(const char*, wnr_hmac_key, int); + WOLFSSL_API int wc_FreeNetRandom(void); +#endif /* HAVE_WNR */ + +#ifndef WC_NO_RNG +WOLFSSL_API int wc_InitRng(WC_RNG*); +WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId); +WOLFSSL_API int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz); +WOLFSSL_API int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId); +WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz); +WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); +WOLFSSL_API int wc_FreeRng(WC_RNG*); +#else +#include +#define wc_InitRng(rng) NOT_COMPILED_IN +#define wc_InitRng_ex(rng, h, d) NOT_COMPILED_IN +#define wc_InitRngNonce(rng, n, s) NOT_COMPILED_IN +#define wc_InitRngNonce_ex(rng, n, s, h, d) NOT_COMPILED_IN +#define wc_RNG_GenerateBlock(rng, b, s) NOT_COMPILED_IN +#define wc_RNG_GenerateByte(rng, b) NOT_COMPILED_IN +#define wc_FreeRng(rng) (void)NOT_COMPILED_IN +#endif + + + +#ifdef HAVE_HASHDRBG + WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, + word32 entropySz); + WOLFSSL_API int wc_RNG_TestSeed(const byte* seed, word32 seedSz); + WOLFSSL_API int wc_RNG_HealthTest(int reseed, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz); + WOLFSSL_API int wc_RNG_HealthTest_ex(int reseed, + const byte* nonce, word32 nonceSz, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz, + void* heap, int devId); +#endif /* HAVE_HASHDRBG */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_RANDOM_H */ + diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h similarity index 84% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h index 5a22416b6..e8a0085fb 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/settings.h @@ -1,12 +1,13 @@ /* settings.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ @@ -67,6 +68,9 @@ /* Uncomment next line if building wolfSSL for LSR */ /* #define WOLFSSL_LSR */ +/* Uncomment next line if building for Freescale Classic MQX version 4.0 */ +/* #define FREESCALE_MQX_4_0 */ + /* Uncomment next line if building for Freescale Classic MQX/RTCS/MFS */ /* #define FREESCALE_MQX */ @@ -76,7 +80,8 @@ /* Uncomment next line if building for Freescale KSDK Bare Metal */ /* #define FREESCALE_KSDK_BM */ -/* Uncomment next line if building for Freescale KSDK FreeRTOS (old name FREESCALE_FREE_RTOS) */ +/* Uncomment next line if building for Freescale KSDK FreeRTOS, */ +/* (old name FREESCALE_FREE_RTOS) */ /* #define FREESCALE_KSDK_FREERTOS */ /* Uncomment next line if using STM32F2 */ @@ -85,6 +90,9 @@ /* Uncomment next line if using STM32F4 */ /* #define WOLFSSL_STM32F4 */ +/* Uncomment next line if using STM32FL */ +/* #define WOLFSSL_STM32FL */ + /* Uncomment next line if using STM32F7 */ /* #define WOLFSSL_STM32F7 */ @@ -153,6 +161,18 @@ /* Uncomment next line if building for using XILINX */ /* #define WOLFSSL_XILINX */ +/* Uncomment next line if building for Nucleus 1.2 */ +/* #define WOLFSSL_NUCLEUS_1_2 */ + +/* Uncomment next line if building for using Apache mynewt */ +/* #define WOLFSSL_APACHE_MYNEWT */ + +/* Uncomment next line if building for using ESP-IDF */ +/* #define WOLFSSL_ESPIDF */ + +/* Uncomment next line if using Espressif ESP32-WROOM-32 */ +/* #define WOLFSSL_ESPWROOM32 */ + #include #ifdef WOLFSSL_USER_SETTINGS @@ -194,6 +214,22 @@ #include #endif +#if defined(WOLFSSL_ESPIDF) + #define FREERTOS + #define WOLFSSL_LWIP + #define NO_WRITEV + #define SIZEOF_LONG_LONG 8 + #define NO_WOLFSSL_DIR + #define WOLFSSL_NO_CURRDIR + + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING +#if !defined(WOLFSSL_USER_SETTINGS) + #define HAVE_ECC +#endif /* !WOLFSSL_USER_SETTINGS */ +#endif /* WOLFSSL_ESPIDF */ + #if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */ #define WOLFSSL_LWIP #define NO_WRITEV @@ -202,6 +238,22 @@ #define NO_FILESYSTEM #endif +#if defined(WOLFSSL_CONTIKI) + #include + #define WOLFSSL_UIP + #define NO_WOLFSSL_MEMORY + #define NO_WRITEV + #define SINGLE_THREADED + #define WOLFSSL_USER_IO + #define NO_FILESYSTEM + #define CUSTOM_RAND_TYPE uint16_t + #define CUSTOM_RAND_GENERATE random_rand + static inline unsigned int LowResTimer(void) + { + return clock_seconds(); + } +#endif + #if defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_ROWLEY_ARM) #define NO_MAIN_DRIVER #define SINGLE_THREADED @@ -231,9 +283,15 @@ #endif #ifdef WOLFSSL_MICROCHIP_PIC32MZ - #define WOLFSSL_PIC32MZ_CRYPT - #define WOLFSSL_PIC32MZ_RNG - #define WOLFSSL_PIC32MZ_HASH + #ifndef NO_PIC32MZ_CRYPT + #define WOLFSSL_PIC32MZ_CRYPT + #endif + #ifndef NO_PIC32MZ_RNG + #define WOLFSSL_PIC32MZ_RNG + #endif + #ifndef NO_PIC32MZ_HASH + #define WOLFSSL_PIC32MZ_HASH + #endif #endif #ifdef MICROCHIP_TCPIP_V5 @@ -332,7 +390,8 @@ #ifdef VXWORKS_SIM #define TFM_NO_ASM #endif - #define WOLFSSL_PTHREADS + /* For VxWorks pthreads wrappers for mutexes uncomment the next line. */ + /* #define WOLFSSL_PTHREADS */ #define WOLFSSL_HAVE_MIN #define WOLFSSL_HAVE_MAX #define USE_FAST_MATH @@ -438,6 +497,32 @@ #include "wolfssl_chibios.h" #endif +#ifdef WOLFSSL_PB + /* PB is using older 1.2 version of Nucleus */ + #undef WOLFSSL_NUCLEUS + #define WOLFSSL_NUCLEUS_1_2 +#endif + +#ifdef WOLFSSL_NUCLEUS_1_2 + #define NO_WRITEV + #define NO_WOLFSSL_DIR + + #if !defined(NO_ASN_TIME) && !defined(USER_TIME) + #error User must define XTIME, see manual + #endif + + #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER) + extern void* nucleus_malloc(unsigned long size, void* heap, int type); + extern void* nucleus_realloc(void* ptr, unsigned long size, void* heap, + int type); + extern void nucleus_free(void* ptr, void* heap, int type); + + #define XMALLOC(s, h, type) nucleus_malloc((s), (h), (type)) + #define XREALLOC(p, n, h, t) nucleus_realloc((p), (n), (h), (t)) + #define XFREE(p, h, type) nucleus_free((p), (h), (type)) + #endif +#endif + #ifdef WOLFSSL_NRF5x #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 8 @@ -494,7 +579,7 @@ extern void uITRON4_free(void *p) ; #include "tm/tmonitor.h" /* static char* gets(char *buff); */ - static char* fgets(char *buff, int sz, FILE *fp) { + static char* fgets(char *buff, int sz, XFILE fp) { char * p = buff; *p = '\0'; while (1) { @@ -539,7 +624,9 @@ extern void uITRON4_free(void *p) ; #define XMALLOC(s, h, type) pvPortMalloc((s)) #define XFREE(p, h, type) vPortFree((p)) #endif - + #if defined(HAVE_ED25519) || defined(WOLFSSL_ESPIDF) + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) + #endif #ifndef NO_WRITEV #define NO_WRITEV #endif @@ -700,6 +787,11 @@ extern void uITRON4_free(void *p) ; #define TFM_TIMING_RESISTANT #endif +#ifdef FREESCALE_MQX_4_0 + /* use normal Freescale MQX port, but with minor changes for 4.0 */ + #define FREESCALE_MQX +#endif + #ifdef FREESCALE_MQX #define FREESCALE_COMMON #include "mqx.h" @@ -716,10 +808,12 @@ extern void uITRON4_free(void *p) ; #include "mutex.h" #endif - #define XMALLOC_OVERRIDE - #define XMALLOC(s, h, t) (void *)_mem_alloc_system((s)) - #define XFREE(p, h, t) {void* xp = (p); if ((xp)) _mem_free((xp));} - /* Note: MQX has no realloc, using fastmath above */ + #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER) + #define XMALLOC_OVERRIDE + #define XMALLOC(s, h, t) (void *)_mem_alloc_system((s)) + #define XFREE(p, h, t) {void* xp = (p); if ((xp)) _mem_free((xp));} + /* Note: MQX has no realloc, using fastmath above */ + #endif #endif #ifdef FREESCALE_KSDK_MQX @@ -946,14 +1040,6 @@ extern void uITRON4_free(void *p) ; #undef NO_ECC256 #define HAVE_ECC384 #endif - - /* enable features */ - #undef HAVE_CURVE25519 - #define HAVE_CURVE25519 - #undef HAVE_ED25519 - #define HAVE_ED25519 - #undef WOLFSSL_SHA512 - #define WOLFSSL_SHA512 #endif #endif #endif @@ -977,7 +1063,8 @@ extern void uITRON4_free(void *p) ; #endif #if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \ - defined(WOLFSSL_STM32F7) + defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32F1) || \ + defined(WOLFSSL_STM32L4) #define SIZEOF_LONG_LONG 8 #define NO_DEV_RANDOM @@ -987,10 +1074,17 @@ extern void uITRON4_free(void *p) ; #ifndef NO_STM32_RNG #undef STM32_RNG #define STM32_RNG + #ifdef WOLFSSL_STM32F427_RNG + #include "stm32f427xx.h" + #endif #endif #ifndef NO_STM32_CRYPTO #undef STM32_CRYPTO #define STM32_CRYPTO + + #ifdef WOLFSSL_STM32L4 + #define NO_AES_192 /* hardware does not support 192-bit */ + #endif #endif #ifndef NO_STM32_HASH #undef STM32_HASH @@ -1003,10 +1097,14 @@ extern void uITRON4_free(void *p) ; #ifdef WOLFSSL_STM32_CUBEMX #if defined(WOLFSSL_STM32F2) #include "stm32f2xx_hal.h" + #elif defined(WOLFSSL_STM32L4) + #include "stm32l4xx_hal.h" #elif defined(WOLFSSL_STM32F4) #include "stm32f4xx_hal.h" #elif defined(WOLFSSL_STM32F7) #include "stm32f7xx_hal.h" + #elif defined(WOLFSSL_STM32F1) + #include "stm32f1xx_hal.h" #endif #ifndef STM32_HAL_TIMEOUT @@ -1029,11 +1127,21 @@ extern void uITRON4_free(void *p) ; #ifdef STM32_HASH #include "stm32f4xx_hash.h" #endif + #elif defined(WOLFSSL_STM32L4) + #include "stm32l4xx.h" + #ifdef STM32_CRYPTO + #include "stm32l4xx_cryp.h" + #endif + #ifdef STM32_HASH + #include "stm32l4xx_hash.h" + #endif #elif defined(WOLFSSL_STM32F7) #include "stm32f7xx.h" + #elif defined(WOLFSSL_STM32F1) + #include "stm32f1xx.h" #endif #endif /* WOLFSSL_STM32_CUBEMX */ -#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32F7 */ +#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32L4 || WOLFSSL_STM32F7 */ #ifdef MICRIUM #include @@ -1070,12 +1178,6 @@ extern void uITRON4_free(void *p) ; #define CUSTOM_RAND_TYPE RAND_NBR #define CUSTOM_RAND_GENERATE Math_Rand #endif - - #define WOLFSSL_TYPES - typedef CPU_INT08U byte; - typedef CPU_INT16U word16; - typedef CPU_INT32U word32; - #define STRING_USER #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr))) #define XSTRNCPY(pstr_dest, pstr_src, len_max) \ @@ -1172,6 +1274,41 @@ extern void uITRON4_free(void *p) ; #endif #endif /*(WOLFSSL_XILINX_CRYPT)*/ +#if defined(WOLFSSL_APACHE_MYNEWT) + #include "os/os_malloc.h" + #if !defined(WOLFSSL_LWIP) + #include + #endif + + #if !defined(SIZEOF_LONG) + #define SIZEOF_LONG 4 + #endif + #if !defined(SIZEOF_LONG_LONG) + #define SIZEOF_LONG_LONG 8 + #endif + #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + #define BIG_ENDIAN_ORDER + #else + #undef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif + #define NO_WRITEV + #define WOLFSSL_USER_IO + #define SINGLE_THREADED + #define NO_DEV_RANDOM + #define NO_DH + #define NO_WOLFSSL_DIR + #define NO_ERROR_STRINGS + #define HAVE_ECC + #define NO_SESSION_CACHE + #define NO_ERROR_STRINGS + #define XMALLOC_USER + #define XMALLOC(sz, heap, type) os_malloc(sz) + #define XREALLOC(p, sz, heap, type) os_realloc(p, sz) + #define XFREE(p, heap, type) os_free(p) + +#endif /*(WOLFSSL_APACHE_MYNEWT)*/ + #ifdef WOLFSSL_IMX6 #ifndef SIZEOF_LONG_LONG #define SIZEOF_LONG_LONG 8 @@ -1232,7 +1369,6 @@ extern void uITRON4_free(void *p) ; #else #define TFM_TIMING_RESISTANT #define NO_WOLFSSL_DIR - #define NO_FILESYSTEM #define NO_WRITEV #define NO_MAIN_DRIVER #define WOLFSSL_LOG_PRINTF @@ -1240,9 +1376,6 @@ extern void uITRON4_free(void *p) ; #endif #else #define HAVE_ECC - #define ECC_TIMING_RESISTANT - #define TFM_TIMING_RESISTANT - #define NO_FILESYSTEM #define NO_WRITEV #define NO_MAIN_DRIVER #define USER_TICKS @@ -1252,6 +1385,10 @@ extern void uITRON4_free(void *p) ; #if !defined(HAVE_FIPS) && !defined(NO_RSA) #define WC_RSA_BLINDING #endif + + #define NO_FILESYSTEM + #define ECC_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT #define SINGLE_THREADED #define NO_ASN_TIME /* can not use headers such as windows.h */ #define HAVE_AESGCM @@ -1414,10 +1551,6 @@ extern void uITRON4_free(void *p) ; #ifndef NO_AES_CBC #undef HAVE_AES_CBC #define HAVE_AES_CBC - #else - #ifndef WOLFCRYPT_ONLY - #error "AES CBC is required for TLS and can only be disabled for WOLFCRYPT_ONLY builds" - #endif #endif #ifdef WOLFSSL_AES_XTS /* AES-XTS makes calls to AES direct functions */ @@ -1433,6 +1566,13 @@ extern void uITRON4_free(void *p) ; #endif #endif +#if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_TLS12)) || \ + (!defined(HAVE_AES_CBC) && defined(NO_DES3) && defined(NO_RC4) && \ + !defined(HAVE_CAMELLIA) && !defined(HAVE_IDEA) && \ + !defined(HAVE_NULL_CIPHER) && !defined(HAVE_HC128)) + #define WOLFSSL_AEAD_ONLY +#endif + /* if desktop type system and fastmath increase default max bits */ #ifdef WOLFSSL_X86_64_BUILD #ifdef USE_FAST_MATH @@ -1499,9 +1639,9 @@ extern void uITRON4_free(void *p) ; #define HAVE_WOLF_EVENT #ifdef WOLFSSL_ASYNC_CRYPT_TEST - #define WC_ASYNC_DEV_SIZE 320+24 + #define WC_ASYNC_DEV_SIZE 328+24 #else - #define WC_ASYNC_DEV_SIZE 320 + #define WC_ASYNC_DEV_SIZE 328 #endif #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ @@ -1551,7 +1691,7 @@ extern void uITRON4_free(void *p) ; #ifndef HAVE_AES_KEYWRAP #error PKCS7 requires AES key wrap please define HAVE_AES_KEYWRAP #endif - #ifndef HAVE_X963_KDF + #if defined(HAVE_ECC) && !defined(HAVE_X963_KDF) #error PKCS7 requires X963 KDF please define HAVE_X963_KDF #endif #endif @@ -1574,7 +1714,7 @@ extern void uITRON4_free(void *p) ; #undef HAVE_GMTIME_R /* don't trust macro with windows */ #endif /* WOLFSSL_MYSQL_COMPATIBLE */ -#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION #define OPENSSL_NO_ENGINE #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT @@ -1614,7 +1754,8 @@ extern void uITRON4_free(void *p) ; #ifndef WC_NO_HARDEN #if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \ (defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \ - (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS)) + (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) && \ + !defined(WC_NO_RNG)) #ifndef _MSC_VER #warning "For timing resistance / side-channel attack prevention consider using harden options" @@ -1626,8 +1767,8 @@ extern void uITRON4_free(void *p) ; #if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA) /* added to have compatibility with SHA256() */ - #if !defined(NO_OLD_SHA256_NAMES) && !defined(HAVE_FIPS) - #define NO_OLD_SHA256_NAMES + #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) + #define NO_OLD_SHA_NAMES #endif #endif @@ -1637,7 +1778,77 @@ extern void uITRON4_free(void *p) ; #undef OPENSSL_EXTRA_X509_SMALL #define OPENSSL_EXTRA_X509_SMALL #endif /* OPENSSL_EXTRA */ - + +/* support for converting DER to PEM */ +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || \ + defined(OPENSSL_EXTRA) + #undef WOLFSSL_DER_TO_PEM + #define WOLFSSL_DER_TO_PEM +#endif + +/* keep backwards compatibility enabling encrypted private key */ +#ifndef WOLFSSL_ENCRYPTED_KEYS + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) + #define WOLFSSL_ENCRYPTED_KEYS + #endif +#endif + +/* support for disabling PEM to DER */ +#if !defined(WOLFSSL_NO_PEM) + #undef WOLFSSL_PEM_TO_DER + #define WOLFSSL_PEM_TO_DER +#endif + +/* Parts of the openssl compatibility layer require peer certs */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #undef KEEP_PEER_CERT + #define KEEP_PEER_CERT +#endif + +/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/ +#ifdef WOLFSSL_ARMASM + #undef WOLFSSL_NO_HASH_RAW + #define WOLFSSL_NO_HASH_RAW +#endif + +#if !defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SHA512) && defined(NO_AES) && \ + !defined(WOLFSSL_SHA3) + #undef WOLFSSL_NO_WORD64_OPS + #define WOLFSSL_NO_WORD64_OPS +#endif + +#if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \ + defined(NO_PWDBASED) && !defined(HAVE_IDEA) + #undef WOLFSSL_NO_XOR_OPS + #define WOLFSSL_NO_XOR_OPS +#endif + +#if defined(NO_ASN) && defined(WOLFCRYPT_ONLY) + #undef WOLFSSL_NO_INT_ENCODE + #define WOLFSSL_NO_INT_ENCODE + #undef WOLFSSL_NO_INT_DECODE + #define WOLFSSL_NO_INT_DECODE +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_RSA_VERIFY_ONLY) && \ + defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CT_OPS + #define WOLFSSL_NO_CT_OPS +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(HAVE_CURVE25519) && \ + defined(WC_NO_RNG) && defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CONST_CMP + #define WOLFSSL_NO_CONST_CMP +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \ + defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_RSA_PUBLIC_ONLY) + #undef WOLFSSL_NO_FORCE_ZERO + #define WOLFSSL_NO_FORCE_ZERO +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h new file mode 100644 index 000000000..d9814d677 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha.h @@ -0,0 +1,143 @@ +/* sha.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/sha.h +*/ + + +#ifndef WOLF_CRYPT_SHA_H +#define WOLF_CRYPT_SHA_H + +#include + +#ifndef NO_SHA + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#define wc_Sha Sha +#define WC_SHA SHA +#define WC_SHA_BLOCK_SIZE SHA_BLOCK_SIZE +#define WC_SHA_DIGEST_SIZE SHA_DIGEST_SIZE +#define WC_SHA_PAD_SIZE SHA_PAD_SIZE + +/* for fips @wc_fips */ +#include +#endif + +#ifdef FREESCALE_LTC_SHA + #include "fsl_ltc.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA WC_SHA +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha wc_Sha + #define SHA_BLOCK_SIZE WC_SHA_BLOCK_SIZE + #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define SHA_PAD_SIZE WC_SHA_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA = WC_HASH_TYPE_SHA, + WC_SHA_BLOCK_SIZE = 64, + WC_SHA_DIGEST_SIZE = 20, + WC_SHA_PAD_SIZE = 56 +}; + + +#if defined(WOLFSSL_TI_HASH) + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" + +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" + +#else +/* Sha digest */ +typedef struct wc_Sha { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH) + STM32_HASH_Context stmCtx; +#else + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[WC_SHA_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)]; + #endif + void* heap; + #ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ + #endif + #ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #endif /* WOLFSSL_ASYNC_CRYPT */ +#endif +} wc_Sha; + +#endif /* WOLFSSL_TI_HASH */ + + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha(wc_Sha*); +WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId); +WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinalRaw(wc_Sha*, byte*); +WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*); +WOLFSSL_API void wc_ShaFree(wc_Sha*); + +WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*); +WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA */ +#endif /* WOLF_CRYPT_SHA_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h new file mode 100644 index 000000000..9565652e5 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/sha256.h @@ -0,0 +1,209 @@ +/* sha256.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/sha256.h +*/ + + +/* code submitted by raphael.huck@efixo.com */ + +#ifndef WOLF_CRYPT_SHA256_H +#define WOLF_CRYPT_SHA256_H + +#include + +#ifndef NO_SHA256 + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #define wc_Sha256 Sha256 + #define WC_SHA256 SHA256 + #define WC_SHA256_BLOCK_SIZE SHA256_BLOCK_SIZE + #define WC_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE + #define WC_SHA256_PAD_SIZE SHA256_PAD_SIZE + + #ifdef WOLFSSL_SHA224 + #define wc_Sha224 Sha224 + #define WC_SHA224 SHA224 + #define WC_SHA224_BLOCK_SIZE SHA224_BLOCK_SIZE + #define WC_SHA224_DIGEST_SIZE SHA224_DIGEST_SIZE + #define WC_SHA224_PAD_SIZE SHA224_PAD_SIZE + #endif + + /* for fips @wc_fips */ + #include +#endif + +#ifdef FREESCALE_LTC_SHA + #include "fsl_ltc.h" +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#if defined(WOLFSSL_DEVCRYPTO) && defined(WOLFSSL_DEVCRYPTO_HASH) + #include +#endif + +#if defined(_MSC_VER) + #define SHA256_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SHA256_NOINLINE __attribute__((noinline)) +#else + #define SHA256_NOINLINE +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA256 WC_SHA256 +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha256 wc_Sha256 + #define SHA256_BLOCK_SIZE WC_SHA256_BLOCK_SIZE + #define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define SHA256_PAD_SIZE WC_SHA256_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA256 = WC_HASH_TYPE_SHA256, + WC_SHA256_BLOCK_SIZE = 64, + WC_SHA256_DIGEST_SIZE = 32, + WC_SHA256_PAD_SIZE = 56 +}; + + +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#elif defined(WOLFSSL_AFALG_HASH) + #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h" +#else +/* wc_Sha256 digest */ +typedef struct wc_Sha256 { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH) + STM32_HASH_Context stmCtx; +#else + /* alignment on digest and buffer speeds up ARMv8 crypto operations */ + ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + ALIGN16 word32 buffer[WC_SHA256_BLOCK_SIZE / sizeof(word32)]; + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + void* heap; +#ifdef USE_INTEL_SPEEDUP + const byte* data; +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + word32* W; +#endif +#ifdef WOLFSSL_DEVCRYPTO_HASH + WC_CRYPTODEV ctx; + byte* msg; + word32 used; + word32 len; +#endif +#endif +} wc_Sha256; + +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha256(wc_Sha256*); +WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int); +WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*); +WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*); +WOLFSSL_API void wc_Sha256Free(wc_Sha256*); + +WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*); +WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32); +#endif + +#ifdef WOLFSSL_SHA224 +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifndef NO_OLD_WC_NAMES + #define Sha224 wc_Sha224 + #define SHA224 WC_SHA224 + #define SHA224_BLOCK_SIZE WC_SHA224_BLOCK_SIZE + #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define SHA224_PAD_SIZE WC_SHA224_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA224 = WC_HASH_TYPE_SHA224, + WC_SHA224_BLOCK_SIZE = WC_SHA256_BLOCK_SIZE, + WC_SHA224_DIGEST_SIZE = 28, + WC_SHA224_PAD_SIZE = WC_SHA256_PAD_SIZE +}; + + +typedef wc_Sha256 wc_Sha224; +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha224(wc_Sha224*); +WOLFSSL_API int wc_InitSha224_ex(wc_Sha224*, void*, int); +WOLFSSL_API int wc_Sha224Update(wc_Sha224*, const byte*, word32); +WOLFSSL_API int wc_Sha224Final(wc_Sha224*, byte*); +WOLFSSL_API void wc_Sha224Free(wc_Sha224*); + +WOLFSSL_API int wc_Sha224GetHash(wc_Sha224*, byte*); +WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst); + +#endif /* WOLFSSL_SHA224 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA256 */ +#endif /* WOLF_CRYPT_SHA256_H */ + diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h new file mode 100644 index 000000000..4fe68a412 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/types.h @@ -0,0 +1,758 @@ +/* types.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +/*! + \file wolfssl/wolfcrypt/types.h +*/ + +#ifndef WOLF_CRYPT_TYPES_H +#define WOLF_CRYPT_TYPES_H + + #include + #include + + #ifdef __cplusplus + extern "C" { + #endif + + + #if defined(WORDS_BIGENDIAN) + #define BIG_ENDIAN_ORDER + #endif + + #ifndef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif + + #ifndef WOLFSSL_TYPES + #ifndef byte + typedef unsigned char byte; + #endif + typedef unsigned short word16; + typedef unsigned int word32; + typedef byte word24[3]; + #endif + + + /* try to set SIZEOF_LONG or LONG_LONG if user didn't */ + #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) && !defined(__EMSCRIPTEN__) + #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) + #if (defined(__alpha__) || defined(__ia64__) || \ + defined(_ARCH_PPC64) || defined(__mips64) || \ + defined(__x86_64__) || \ + ((defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)))) + /* long should be 64bit */ + #define SIZEOF_LONG 8 + #elif defined(__i386__) || defined(__CORTEX_M3__) + /* long long should be 64bit */ + #define SIZEOF_LONG_LONG 8 + #endif + #endif + #endif + + #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + #define WORD64_AVAILABLE + #define W64LIT(x) x##ui64 + typedef unsigned __int64 word64; + #elif defined(__EMSCRIPTEN__) + #define WORD64_AVAILABLE + #define W64LIT(x) x##ull + typedef unsigned long long word64; + #elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long word64; + #elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #endif + +#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE) + /* These platforms have 64-bit CPU registers. */ + #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ + defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) || \ + defined(__aarch64__) || defined(__sparc64__) + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #elif (defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)) + /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits + * and int uses 32 bits. When using Solaris Studio sparc and __sparc are + * available for 32 bit detection but __sparc64__ could be missed. This + * uses LP64 for checking 64 bit CPU arch. */ + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #else + typedef word32 wolfssl_word; + #ifdef WORD64_AVAILABLE + #define WOLFCRYPT_SLOW_WORD64 + #endif + #endif +#else + #undef WORD64_AVAILABLE + typedef word32 wolfssl_word; + #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as + mp_digit, no 64 bit type so make mp_digit 16 bit */ +#endif + + enum { + WOLFSSL_WORD_SIZE = sizeof(wolfssl_word), + WOLFSSL_BIT_SIZE = 8, + WOLFSSL_WORD_BITS = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE + }; + + #define WOLFSSL_MAX_16BIT 0xffffU + + /* use inlining if compiler allows */ + #ifndef WC_INLINE + #ifndef NO_INLINE + #ifdef _MSC_VER + #define WC_INLINE __inline + #elif defined(__GNUC__) + #ifdef WOLFSSL_VXWORKS + #define WC_INLINE __inline__ + #else + #define WC_INLINE inline + #endif + #elif defined(__IAR_SYSTEMS_ICC__) + #define WC_INLINE inline + #elif defined(THREADX) + #define WC_INLINE _Inline + #else + #define WC_INLINE + #endif + #else + #define WC_INLINE + #endif + #endif + + #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + #define INLINE WC_INLINE + #endif + + + /* set up rotate style */ + #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \ + !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS) + #define INTEL_INTRINSICS + #define FAST_ROTATE + #elif defined(__MWERKS__) && TARGET_CPU_PPC + #define PPC_INTRINSICS + #define FAST_ROTATE + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + /* GCC does peephole optimizations which should result in using rotate + instructions */ + #define FAST_ROTATE + #endif + + + /* set up thread local storage if available */ + #ifdef HAVE_THREAD_LS + #if defined(_MSC_VER) + #define THREAD_LS_T __declspec(thread) + /* Thread local storage only in FreeRTOS v8.2.1 and higher */ + #elif defined(FREERTOS) || defined(FREERTOS_TCP) + #define THREAD_LS_T + #else + #define THREAD_LS_T __thread + #endif + #else + #define THREAD_LS_T + #endif + + /* GCC 7 has new switch() fall-through detection */ + #if defined(__GNUC__) + #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1))) + #define FALL_THROUGH __attribute__ ((fallthrough)) + #endif + #endif + #ifndef FALL_THROUGH + #define FALL_THROUGH + #endif + + /* Micrium will use Visual Studio for compilation but not the Win32 API */ + #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ + !defined(FREERTOS_TCP) && !defined(EBSNET) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) + #define USE_WINDOWS_API + #endif + + + /* idea to add global alloc override by Moises Guimaraes */ + /* default to libc stuff */ + /* XREALLOC is used once in normal math lib, not in fast math lib */ + /* XFREE on some embedded systems doesn't like free(0) so test */ + #if defined(HAVE_IO_POOL) + WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type); + WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type); + WOLFSSL_API void XFREE(void *p, void* heap, int type); + #elif defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA) + #include + #undef USE_WOLFSSL_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t), __func__, __LINE__) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t)) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t)) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif defined(XMALLOC_USER) + /* prototypes for user heap override functions */ + #include /* for size_t */ + extern void *XMALLOC(size_t n, void* heap, int type); + extern void *XREALLOC(void *p, size_t n, void* heap, int type); + extern void XFREE(void *p, void* heap, int type); + #elif defined(WOLFSSL_MEMORY_LOG) + #define XMALLOC(n, h, t) xmalloc(n, h, t, __func__, __FILE__, __LINE__) + #define XREALLOC(p, n, h, t) xrealloc(p, n, h, t, __func__, __FILE__, __LINE__) + #define XFREE(p, h, t) xfree(p, h, t, __func__, __FILE__, __LINE__) + + /* prototypes for user heap override functions */ + #include /* for size_t */ + #include + extern void *xmalloc(size_t n, void* heap, int type, const char* func, + const char* file, unsigned int line); + extern void *xrealloc(void *p, size_t n, void* heap, int type, + const char* func, const char* file, unsigned int line); + extern void xfree(void *p, void* heap, int type, const char* func, + const char* file, unsigned int line); + #elif defined(XMALLOC_OVERRIDE) + /* override the XMALLOC, XFREE and XREALLOC macros */ + #elif defined(NO_WOLFSSL_MEMORY) + /* just use plain C stdlib stuff if desired */ + #include + #define XMALLOC(s, h, t) ((void)h, (void)t, malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));} + #define XREALLOC(p, n, h, t) realloc((p), (n)) + #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ + && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ + && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ + && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4) + /* default C runtime, can install different routines at runtime via cbs */ + #include + #ifdef WOLFSSL_STATIC_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif !defined(FREERTOS) && !defined(FREERTOS_TCP) + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s), __func__, __LINE__)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #endif /* WOLFSSL_STATIC_MEMORY */ + #endif + + /* declare/free variable handling for async */ + #ifdef WOLFSSL_ASYNC_CRYPT + #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); + #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \ + VAR_TYPE* VAR_NAME = ({ \ + VAR_TYPE* ptr = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); \ + if (ptr && INIT_VALUE) { \ + XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \ + } \ + ptr; \ + }) + #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME[VAR_ITEMS]; \ + int idx##VAR_NAME; \ + for (idx##VAR_NAME=0; idx##VAR_NAME + #define XMEMCPY(d,s,l) memcpy((d),(s),(l)) + #define XMEMSET(b,c,l) memset((b),(c),(l)) + #define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n)) + #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) + + #define XSTRLEN(s1) strlen((s1)) + #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) + /* strstr, strncmp, and strncat only used by wolfSSL proper, + * not required for wolfCrypt only */ + #define XSTRSTR(s1,s2) strstr((s1),(s2)) + #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n)) + #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n)) + #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n)) + + #ifdef USE_WOLF_STRSEP + #define XSTRSEP(s1,d) wc_strsep((s1),(d)) + #else + #define XSTRSEP(s1,d) strsep((s1),(d)) + #endif + + #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS) + /* XC32 does not support strncasecmp, so use case sensitive one */ + #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n)) + #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM) + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #else + #if defined(HAVE_STRINGS_H) && defined(WOLF_C99) && \ + !defined(WOLFSSL_SGX) + #include + #endif + #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) + #endif + + /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when + debugging is turned on */ + #ifndef USE_WINDOWS_API + #if defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_PKCS7)) && !defined(NO_STDIO_FILESYSTEM) + /* case where stdio is not included else where but is needed for + * snprintf */ + #include + #endif + #define XSNPRINTF snprintf + #else + #define XSNPRINTF _snprintf + #endif + + #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN) + /* use only Thread Safe version of strtok */ + #if defined(USE_WOLF_STRTOK) + #define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr)) + #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS) + #define XSTRTOK(s1,d,ptr) strtok_s((s1),(d),(ptr)) + #else + #define XSTRTOK(s1,d,ptr) strtok_r((s1),(d),(ptr)) + #endif + #endif + #endif + + #ifdef USE_WOLF_STRTOK + WOLFSSL_API char* wc_strtok(char *str, const char *delim, char **nextp); + #endif + #ifdef USE_WOLF_STRSEP + WOLFSSL_API char* wc_strsep(char **stringp, const char *delim); + #endif + + #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + !defined(NO_STDIO_FILESYSTEM) + #ifndef XGETENV + #include + #define XGETENV getenv + #endif + #endif /* OPENSSL_EXTRA */ + + #ifndef CTYPE_USER + #include + #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \ + defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA) + #define XTOUPPER(c) toupper((c)) + #define XISALPHA(c) isalpha((c)) + #endif + /* needed by wolfSSL_check_domain_name() */ + #define XTOLOWER(c) tolower((c)) + #endif + + + /* memory allocation types for user hints */ + enum { + DYNAMIC_TYPE_CA = 1, + DYNAMIC_TYPE_CERT = 2, + DYNAMIC_TYPE_KEY = 3, + DYNAMIC_TYPE_FILE = 4, + DYNAMIC_TYPE_SUBJECT_CN = 5, + DYNAMIC_TYPE_PUBLIC_KEY = 6, + DYNAMIC_TYPE_SIGNER = 7, + DYNAMIC_TYPE_NONE = 8, + DYNAMIC_TYPE_BIGINT = 9, + DYNAMIC_TYPE_RSA = 10, + DYNAMIC_TYPE_METHOD = 11, + DYNAMIC_TYPE_OUT_BUFFER = 12, + DYNAMIC_TYPE_IN_BUFFER = 13, + DYNAMIC_TYPE_INFO = 14, + DYNAMIC_TYPE_DH = 15, + DYNAMIC_TYPE_DOMAIN = 16, + DYNAMIC_TYPE_SSL = 17, + DYNAMIC_TYPE_CTX = 18, + DYNAMIC_TYPE_WRITEV = 19, + DYNAMIC_TYPE_OPENSSL = 20, + DYNAMIC_TYPE_DSA = 21, + DYNAMIC_TYPE_CRL = 22, + DYNAMIC_TYPE_REVOKED = 23, + DYNAMIC_TYPE_CRL_ENTRY = 24, + DYNAMIC_TYPE_CERT_MANAGER = 25, + DYNAMIC_TYPE_CRL_MONITOR = 26, + DYNAMIC_TYPE_OCSP_STATUS = 27, + DYNAMIC_TYPE_OCSP_ENTRY = 28, + DYNAMIC_TYPE_ALTNAME = 29, + DYNAMIC_TYPE_SUITES = 30, + DYNAMIC_TYPE_CIPHER = 31, + DYNAMIC_TYPE_RNG = 32, + DYNAMIC_TYPE_ARRAYS = 33, + DYNAMIC_TYPE_DTLS_POOL = 34, + DYNAMIC_TYPE_SOCKADDR = 35, + DYNAMIC_TYPE_LIBZ = 36, + DYNAMIC_TYPE_ECC = 37, + DYNAMIC_TYPE_TMP_BUFFER = 38, + DYNAMIC_TYPE_DTLS_MSG = 39, + DYNAMIC_TYPE_X509 = 40, + DYNAMIC_TYPE_TLSX = 41, + DYNAMIC_TYPE_OCSP = 42, + DYNAMIC_TYPE_SIGNATURE = 43, + DYNAMIC_TYPE_HASHES = 44, + DYNAMIC_TYPE_SRP = 45, + DYNAMIC_TYPE_COOKIE_PWD = 46, + DYNAMIC_TYPE_USER_CRYPTO = 47, + DYNAMIC_TYPE_OCSP_REQUEST = 48, + DYNAMIC_TYPE_X509_EXT = 49, + DYNAMIC_TYPE_X509_STORE = 50, + DYNAMIC_TYPE_X509_CTX = 51, + DYNAMIC_TYPE_URL = 52, + DYNAMIC_TYPE_DTLS_FRAG = 53, + DYNAMIC_TYPE_DTLS_BUFFER = 54, + DYNAMIC_TYPE_SESSION_TICK = 55, + DYNAMIC_TYPE_PKCS = 56, + DYNAMIC_TYPE_MUTEX = 57, + DYNAMIC_TYPE_PKCS7 = 58, + DYNAMIC_TYPE_AES_BUFFER = 59, + DYNAMIC_TYPE_WOLF_BIGINT = 60, + DYNAMIC_TYPE_ASN1 = 61, + DYNAMIC_TYPE_LOG = 62, + DYNAMIC_TYPE_WRITEDUP = 63, + DYNAMIC_TYPE_PRIVATE_KEY = 64, + DYNAMIC_TYPE_HMAC = 65, + DYNAMIC_TYPE_ASYNC = 66, + DYNAMIC_TYPE_ASYNC_NUMA = 67, + DYNAMIC_TYPE_ASYNC_NUMA64 = 68, + DYNAMIC_TYPE_CURVE25519 = 69, + DYNAMIC_TYPE_ED25519 = 70, + DYNAMIC_TYPE_SECRET = 71, + DYNAMIC_TYPE_DIGEST = 72, + DYNAMIC_TYPE_RSA_BUFFER = 73, + DYNAMIC_TYPE_DCERT = 74, + DYNAMIC_TYPE_STRING = 75, + DYNAMIC_TYPE_PEM = 76, + DYNAMIC_TYPE_DER = 77, + DYNAMIC_TYPE_CERT_EXT = 78, + DYNAMIC_TYPE_ALPN = 79, + DYNAMIC_TYPE_ENCRYPTEDINFO= 80, + DYNAMIC_TYPE_DIRCTX = 81, + DYNAMIC_TYPE_HASHCTX = 82, + DYNAMIC_TYPE_SEED = 83, + DYNAMIC_TYPE_SYMMETRIC_KEY= 84, + DYNAMIC_TYPE_ECC_BUFFER = 85, + DYNAMIC_TYPE_QSH = 86, + DYNAMIC_TYPE_SALT = 87, + DYNAMIC_TYPE_HASH_TMP = 88, + DYNAMIC_TYPE_BLOB = 89, + DYNAMIC_TYPE_NAME_ENTRY = 90, + }; + + /* max error buffer string size */ + #ifndef WOLFSSL_MAX_ERROR_SZ + #define WOLFSSL_MAX_ERROR_SZ 80 + #endif + + /* stack protection */ + enum { + MIN_STACK_BUFFER = 8 + }; + + + /* Algorithm Types */ + enum wc_AlgoType { + WC_ALGO_TYPE_NONE = 0, + WC_ALGO_TYPE_HASH = 1, + WC_ALGO_TYPE_CIPHER = 2, + WC_ALGO_TYPE_PK = 3, + + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_PK + }; + + /* hash types */ + enum wc_HashType { + #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) + /* In selftest build, WC_* types are not mapped to WC_HASH_TYPE types. + * Values here are based on old selftest hmac.h enum, with additions */ + WC_HASH_TYPE_NONE = 15, + WC_HASH_TYPE_MD2 = 16, + WC_HASH_TYPE_MD4 = 17, + WC_HASH_TYPE_MD5 = 0, + WC_HASH_TYPE_SHA = 1, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 8, + WC_HASH_TYPE_SHA256 = 2, + WC_HASH_TYPE_SHA384 = 5, + WC_HASH_TYPE_SHA512 = 4, + WC_HASH_TYPE_MD5_SHA = 18, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_MD5_SHA + #else + WC_HASH_TYPE_NONE = 0, + WC_HASH_TYPE_MD2 = 1, + WC_HASH_TYPE_MD4 = 2, + WC_HASH_TYPE_MD5 = 3, + WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 5, + WC_HASH_TYPE_SHA256 = 6, + WC_HASH_TYPE_SHA384 = 7, + WC_HASH_TYPE_SHA512 = 8, + WC_HASH_TYPE_MD5_SHA = 9, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2B + #endif /* HAVE_SELFTEST */ + }; + + /* cipher types */ + enum wc_CipherType { + WC_CIPHER_NONE = 0, + WC_CIPHER_AES = 1, + WC_CIPHER_AES_CBC = 2, + WC_CIPHER_AES_GCM = 3, + WC_CIPHER_AES_CTR = 4, + WC_CIPHER_AES_XTS = 5, + WC_CIPHER_AES_CFB = 6, + WC_CIPHER_DES3 = 7, + WC_CIPHER_DES = 8, + WC_CIPHER_CHACHA = 9, + WC_CIPHER_HC128 = 10, + WC_CIPHER_IDEA = 11, + + WC_CIPHER_MAX = WC_CIPHER_HC128 + }; + + /* PK=public key (asymmetric) based algorithms */ + enum wc_PkType { + WC_PK_TYPE_NONE = 0, + WC_PK_TYPE_RSA = 1, + WC_PK_TYPE_DH = 2, + WC_PK_TYPE_ECDH = 3, + WC_PK_TYPE_ECDSA_SIGN = 4, + WC_PK_TYPE_ECDSA_VERIFY = 5, + WC_PK_TYPE_ED25519 = 6, + WC_PK_TYPE_CURVE25519 = 7, + WC_PK_TYPE_RSA_KEYGEN = 8, + WC_PK_TYPE_EC_KEYGEN = 9, + + WC_PK_TYPE_MAX = WC_PK_TYPE_EC_KEYGEN + }; + + + /* settings detection for compile vs runtime math incompatibilities */ + enum { + #if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x0 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x1 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x2 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x4 + #elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x8 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x10 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x20 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x40 + #else + #error "bad math long / long long settings" + #endif + }; + + + WOLFSSL_API word32 CheckRunTimeSettings(void); + + /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long + types need to match at compile time and run time, CheckCtcSettings will + return 1 if a match otherwise 0 */ + #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings()) + + /* invalid device id */ + #define INVALID_DEVID -2 + + + /* AESNI requires alignment and ARMASM gains some performance from it */ + #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || defined(USE_INTEL_SPEEDUP) + #if !defined(ALIGN16) + #if defined(__GNUC__) + #define ALIGN16 __attribute__ ( (aligned (16))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN16 __declspec (align (16)) + #else + #define ALIGN16 + #endif + #endif /* !ALIGN16 */ + + #if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif + #endif + + #if !defined(ALIGN32) + #if defined(__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif + #endif /* !ALIGN32 */ + + #if defined(__GNUC__) + #define ALIGN128 __attribute__ ( (aligned (128))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN128 __declspec (align (128)) + #else + #define ALIGN128 + #endif + + #if defined(__GNUC__) + #define ALIGN256 __attribute__ ( (aligned (256))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN256 __declspec (align (256)) + #else + #define ALIGN256 + #endif + + #else + #ifndef ALIGN16 + #define ALIGN16 + #endif + #ifndef ALIGN32 + #define ALIGN32 + #endif + #ifndef ALIGN128 + #define ALIGN128 + #endif + #ifndef ALIGN256 + #define ALIGN256 + #endif + #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ + + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + + + #ifdef WOLFSSL_RIOT_OS + #define EXIT_TEST(ret) exit(ret) + #elif defined(HAVE_STACK_SIZE) + #define EXIT_TEST(ret) return (void*)((size_t)(ret)) + #else + #define EXIT_TEST(ret) return ret + #endif + + + #if defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) + #else + #define WOLFSSL_PACK + #endif + + #ifndef __GNUC_PREREQ + #if defined(__GNUC__) && defined(__GNUC_MINOR__) + #define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) + #else + #define __GNUC_PREREQ(maj, min) (0) /* not GNUC */ + #endif + #endif + + #if defined(__GNUC__) + #define WC_NORETURN __attribute__((noreturn)) + #else + #define WC_NORETURN + #endif + + #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ + defined(WOLFSSL_PUBLIC_MP) || defined(OPENSSL_EXTRA) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) + #undef WC_MP_TO_RADIX + #define WC_MP_TO_RADIX + #endif + + #ifdef __cplusplus + } /* extern "C" */ + #endif + +#endif /* WOLF_CRYPT_TYPES_H */ diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h new file mode 100644 index 000000000..905d44c5e --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/visibility.h @@ -0,0 +1,71 @@ +/* visibility.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + + +/* Visibility control macros */ + +#ifndef WOLF_CRYPT_VISIBILITY_H +#define WOLF_CRYPT_VISIBILITY_H + + +/* for compatibility and so that fips is using same name of macro @wc_fips */ +/* The following visibility wrappers are for old FIPS. New FIPS should use + * the same as a non-FIPS build. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #include + #define WOLFSSL_API CYASSL_API + #define WOLFSSL_LOCAL CYASSL_LOCAL +#else + +/* WOLFSSL_API is used for the public API symbols. + It either imports or exports (or does nothing for static builds) + + WOLFSSL_LOCAL is used for non-API symbols (private). +*/ + +#if defined(BUILDING_WOLFSSL) + #if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(WOLFSSL_DLL) + #define WOLFSSL_API __declspec(dllexport) + #else + #define WOLFSSL_API + #endif + #define WOLFSSL_LOCAL + #elif defined(HAVE_VISIBILITY) && HAVE_VISIBILITY + #define WOLFSSL_API __attribute__ ((visibility("default"))) + #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden"))) + #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) + #define WOLFSSL_API __global + #define WOLFSSL_LOCAL __hidden + #else + #define WOLFSSL_API + #define WOLFSSL_LOCAL + #endif /* HAVE_VISIBILITY */ +#else /* BUILDING_WOLFSSL */ + #if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(WOLFSSL_DLL) + #define WOLFSSL_API __declspec(dllimport) + #else + #define WOLFSSL_API + #endif + #define WOLFSSL_LOCAL + #else + #define WOLFSSL_API + #define WOLFSSL_LOCAL + #endif +#endif /* BUILDING_WOLFSSL */ + +#endif /* HAVE_FIPS */ +#endif /* WOLF_CRYPT_VISIBILITY_H */ + diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h similarity index 79% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h index 7e1b71ded..aac872b50 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wc_port.h @@ -1,16 +1,19 @@ /* wc_port.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ - +/*! + \file wolfssl/wolfcrypt/wc_port.h +*/ #ifndef WOLF_CRYPT_PORT_H #define WOLF_CRYPT_PORT_H @@ -22,6 +25,14 @@ extern "C" { #endif +/* Detect if compiler supports C99. "NO_WOLF_C99" can be defined in + * user_settings.h to disable checking for C99 support. */ +#if !defined(WOLF_C99) && defined(__STDC_VERSION__) && \ + !defined(WOLFSSL_ARDUINO) && !defined(NO_WOLF_C99) + #if __STDC_VERSION__ >= 199901L + #define WOLF_C99 + #endif +#endif #ifdef USE_WINDOWS_API #ifdef WOLFSSL_GAME_BUILD @@ -55,6 +66,8 @@ /* do nothing */ #elif defined(FREESCALE_FREE_RTOS) #include "fsl_os_abstraction.h" +#elif defined(WOLFSSL_VXWORKS) + #include #elif defined(WOLFSSL_uITRON4) #include "stddef.h" #include "kernel.h" @@ -78,6 +91,13 @@ #elif defined(INTIME_RTOS) #include #include +#elif defined(WOLFSSL_NUCLEUS_1_2) + /* NU_DEBUG needed struct access in nucleus_realloc */ + #define NU_DEBUG + #include "plus/nucleus.h" + #include "nucleus.h" +#elif defined(WOLFSSL_APACHE_MYNEWT) + /* do nothing */ #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS @@ -125,6 +145,8 @@ typedef MUTEX_STRUCT wolfSSL_Mutex; #elif defined(FREESCALE_FREE_RTOS) typedef mutex_t wolfSSL_Mutex; + #elif defined(WOLFSSL_VXWORKS) + typedef SEM_ID wolfSSL_Mutex; #elif defined(WOLFSSL_uITRON4) typedef struct wolfSSL_Mutex { T_CSEM sem ; @@ -149,6 +171,8 @@ typedef mutex_t * wolfSSL_Mutex; #elif defined(INTIME_RTOS) typedef RTHANDLE wolfSSL_Mutex; + #elif defined(WOLFSSL_NUCLEUS_1_2) + typedef NU_SEMAPHORE wolfSSL_Mutex; #else #error Need a mutex type in multithreaded mode #endif /* USE_WINDOWS_API */ @@ -254,6 +278,34 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XSEEK_END FS_SEEK_END #define XBADFILE NULL #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_NUCLEUS_1_2) + #include "fal/inc/fal.h" + #define XFILE FILE* + #define XFOPEN fopen + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND rewind + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END PSEEK_END + #define XBADFILE NULL +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include + #define XFILE struct fs_file* + + #define XFOPEN mynewt_fopen + #define XFSEEK mynewt_fseek + #define XFTELL mynewt_ftell + #define XREWIND mynewt_rewind + #define XFREAD mynewt_fread + #define XFWRITE mynewt_fwrite + #define XFCLOSE mynewt_fclose + #define XSEEK_END 2 + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_USER_FILESYSTEM) + /* To be defined in user_settings.h */ #else /* stdio, default case */ #include @@ -274,7 +326,8 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XBADFILE NULL #define XFGETS fgets - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) #include #include #include @@ -288,7 +341,8 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define MAX_PATH 256 #endif -#if !defined(NO_WOLFSSL_DIR) +#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS) && \ + !defined(WOLFSSL_NUCLEUS_1_2) typedef struct ReadDirCtx { #ifdef USE_WINDOWS_API WIN32_FIND_DATAA FindFileData; @@ -301,6 +355,8 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); char name[MAX_FILENAME_SZ]; } ReadDirCtx; + #define WC_READDIR_NOFILE -1 + WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name); WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); @@ -308,10 +364,6 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif /* !NO_FILESYSTEM */ -#ifdef USE_WOLF_STRTOK - WOLFSSL_LOCAL char* wc_strtok(char *str, const char *delim, char **nextp); -#endif - /* Windows API defines its own min() macro. */ #if defined(USE_WINDOWS_API) #if defined(min) || defined(WOLFSSL_MYSQL_COMPATIBLE) @@ -367,8 +419,13 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XGMTIME(c, t) gmtime((c)) #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #ifdef FREESCALE_MQX_4_0 + #include + extern time_t mqx_time(time_t* timer); + #else + #define HAVE_GMTIME_R + #endif #define XTIME(t1) mqx_time((t1)) - #define HAVE_GMTIME_R #elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) #include @@ -378,7 +435,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif #define XGMTIME(c, t) gmtime((c)) -#elif defined(WOLFSSL_ATMEL) +#elif defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) #define XTIME(t1) atmel_get_curr_time_and_date((t1)) #define WOLFSSL_GMTIME #define USE_WOLF_TM @@ -396,24 +453,46 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XTIME(t1) windows_time((t1)) #define WOLFSSL_GMTIME +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include "os/os_time.h" + #define XTIME(t1) mynewt_time((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T #else /* default */ /* uses complete facility */ #include + #if defined(HAVE_SYS_TIME_H) + #include + #endif /* PowerPC time_t is int */ #ifdef __PPC__ - #define TIME_T_NOT_LONG + #define TIME_T_NOT_64BIT #endif #endif +#ifdef SIZEOF_TIME_T + /* check if size of time_t from autoconf is less than 8 bytes (64bits) */ + #if SIZEOF_TIME_T < 8 + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT + #endif +#endif +#ifdef TIME_T_NOT_LONG + /* one old reference to TIME_T_NOT_LONG in GCC-ARM example README + * this keeps support for the old macro name */ + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT +#endif /* Map default time functions */ #if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) #define XTIME(tl) time((tl)) #endif #if !defined(XGMTIME) && !defined(TIME_OVERRIDES) - #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) + #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) #define XGMTIME(c, t) gmtime((c)) #else #define XGMTIME(c, t) gmtime_r((c), (t)) @@ -444,8 +523,18 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #if defined(USE_WOLF_TIME_T) typedef long time_t; #endif +#if defined(USE_WOLF_SUSECONDS_T) + typedef long suseconds_t; +#endif +#if defined(USE_WOLF_TIMEVAL_T) + struct timeval + { + time_t tv_sec; + suseconds_t tv_usec; + }; +#endif -/* forward declarations */ + /* forward declarations */ #if defined(USER_TIME) struct tm* gmtime(const time_t* timer); extern time_t XTIME(time_t * timer); @@ -465,6 +554,16 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif #endif /* NO_ASN_TIME */ +#ifndef WOLFSSL_LEANPSK + char* mystrnstr(const char* s1, const char* s2, unsigned int n); +#endif + +#ifndef FILE_BUFFER_SIZE + #define FILE_BUFFER_SIZE 1024 /* default static file buffer size for input, + will use dynamic buffer if not big enough */ +#endif + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h new file mode 100644 index 000000000..5699be6f1 --- /dev/null +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfcrypt/wolfmath.h @@ -0,0 +1,70 @@ +/* wolfmath.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. + * + * This file is part of wolfSSL. + * + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. + * + * https://www.wolfssl.com + */ + + +#if defined(HAVE_WOLF_BIGINT) && !defined(WOLF_BIGINT_DEFINED) + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + + #define WOLF_BIGINT_DEFINED +#endif + + +/* only define functions if mp_int has been declared */ +#ifdef MP_INT_DEFINED + +#ifndef __WOLFMATH_H__ +#define __WOLFMATH_H__ + + /* timing resistance array */ + #if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + extern const wolfssl_word wc_off_on_addr[2]; + #endif + + /* common math functions */ + int get_digit_count(mp_int* a); + mp_digit get_digit(mp_int* a, int n); + int get_rand_digit(WC_RNG* rng, mp_digit* d); + int mp_rand(mp_int* a, int digits, WC_RNG* rng); + + enum { + /* format type */ + WC_TYPE_HEX_STR = 1, + WC_TYPE_UNSIGNED_BIN = 2, + }; + + WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len, + word32 keySz, int encType); + + #ifdef HAVE_WOLF_BIGINT + void wc_bigint_init(WC_BIGINT* a); + int wc_bigint_alloc(WC_BIGINT* a, word32 sz); + int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen); + int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen); + void wc_bigint_zero(WC_BIGINT* a); + void wc_bigint_free(WC_BIGINT* a); + + int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst); + int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz); + int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst); + #endif /* HAVE_WOLF_BIGINT */ + +#endif /* __WOLFMATH_H__ */ + +#endif /* MP_INT_DEFINED */ diff --git a/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfio.h similarity index 77% rename from components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h rename to components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfio.h index a224483d7..6993bd079 100644 --- a/components/ssl/wolfssl/wolfssl/wolfssl/wolfio.h +++ b/components/esp-wolfssl/wolfssl/wolfssl/wolfssl/wolfio.h @@ -1,15 +1,19 @@ /* io.h * - * Copyright (C) 2006-2017 wolfSSL Inc. All rights reserved. + * Copyright (C) 2006-2018 wolfSSL Inc. All rights reserved. * * This file is part of wolfSSL. * - * Contact licensing@wolfssl.com with any questions or comments. + * wolfSSL is distributed in binary form as licensed by Espressif Systems. + * See README file or contact licensing@wolfssl.com with any questions or comments. * - * http://www.wolfssl.com + * https://www.wolfssl.com */ +/*! + \file wolfssl/wolfio.h +*/ #ifndef WOLFSSL_IO_H #define WOLFSSL_IO_H @@ -18,16 +22,19 @@ extern "C" { #endif -/* OCSP and CRL_IO require HTTP client */ -#if defined(HAVE_OCSP) || defined(HAVE_CRL_IO) - #ifndef HAVE_HTTP_CLIENT - #define HAVE_HTTP_CLIENT +/* Micrium uses NetSock I/O callbacks in wolfio.c */ +#if !defined(WOLFSSL_USER_IO) + /* OCSP and CRL_IO require HTTP client */ + #if defined(HAVE_OCSP) || defined(HAVE_CRL_IO) + #ifndef HAVE_HTTP_CLIENT + #define HAVE_HTTP_CLIENT + #endif #endif #endif #if !defined(WOLFSSL_USER_IO) /* Micrium uses NetSock I/O callbacks in wolfio.c */ - #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) + #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) && !defined(WOLFSSL_CONTIKI) #define USE_WOLFSSL_IO #endif #endif @@ -40,7 +47,7 @@ #endif #ifndef USE_WINDOWS_API - #ifdef WOLFSSL_LWIP + #if defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) /* lwIP needs to be configured to use sockets API in this mode */ /* LWIP_SOCKET 1 in lwip/opt.h or in build */ #include "lwip/sockets.h" @@ -68,6 +75,9 @@ #elif defined(WOLFSSL_VXWORKS) #include #include + #elif defined(WOLFSSL_NUCLEUS_1_2) + #include + #include #elif defined(WOLFSSL_ATMEL) #include "socket/include/socket.h" #elif defined(INTIME_RTOS) @@ -92,6 +102,8 @@ #include #elif defined(WOLFSSL_SGX) #include + #elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + #include #elif !defined(WOLFSSL_NO_SOCK) #include #include @@ -105,7 +117,7 @@ #elif defined(EBSNET) #include "rtipapi.h" /* errno */ #include "socket.h" - #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_CONTIKI) #include #include #include @@ -135,7 +147,6 @@ #define SOCKET_EPIPE WSAEPIPE #define SOCKET_ECONNREFUSED WSAENOTCONN #define SOCKET_ECONNABORTED WSAECONNABORTED - #define close(s) closesocket(s) #elif defined(__PPU) #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK #define SOCKET_EAGAIN SYS_NET_EAGAIN @@ -187,6 +198,14 @@ #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SOCKET_EWOULDBLOCK NU_WOULD_BLOCK + #define SOCKET_EAGAIN NU_WOULD_BLOCK + #define SOCKET_ECONNRESET NU_NOT_CONNECTED + #define SOCKET_EINTR NU_NOT_CONNECTED + #define SOCKET_EPIPE NU_NOT_CONNECTED + #define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED + #define SOCKET_ECONNABORTED NU_NOT_CONNECTED #else #define SOCKET_EWOULDBLOCK EWOULDBLOCK #define SOCKET_EAGAIN EAGAIN @@ -198,13 +217,15 @@ #endif /* USE_WINDOWS_API */ + + #ifdef DEVKITPRO /* from network.h */ int net_send(int, const void*, int, unsigned int); int net_recv(int, void*, int, unsigned int); #define SEND_FUNCTION net_send #define RECV_FUNCTION net_recv -#elif defined(WOLFSSL_LWIP) +#elif defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) #define SEND_FUNCTION lwip_send #define RECV_FUNCTION lwip_recv #elif defined(WOLFSSL_PICOTCP) @@ -216,6 +237,9 @@ #elif defined(WOLFSSL_VXWORKS) #define SEND_FUNCTION send #define RECV_FUNCTION recv +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SEND_FUNCTION NU_Send + #define RECV_FUNCTION NU_Recv #else #define SEND_FUNCTION send #define RECV_FUNCTION recv @@ -250,6 +274,11 @@ typedef struct hostent HOSTENT; #endif /* HAVE_SOCKADDR */ + /* use gethostbyname for c99 */ + #ifdef WOLF_C99 + #undef HAVE_GETADDRINFO + #endif + #ifdef HAVE_GETADDRINFO typedef struct addrinfo ADDRINFO; #endif @@ -259,7 +288,7 @@ /* IO API's */ #ifdef HAVE_IO_TIMEOUT WOLFSSL_API int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking); - WOLFSSL_API void wolfIO_SetTimeout(int to_sec);; + WOLFSSL_API void wolfIO_SetTimeout(int to_sec); WOLFSSL_API int wolfIO_Select(SOCKET_T sockfd, int to_sec); #endif WOLFSSL_API int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, @@ -270,6 +299,28 @@ WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags); #endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ +#ifdef USE_WINDOWS_API + #ifndef CloseSocket + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #ifndef CloseSocket + extern int closesocket(int); + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() +#else + #ifndef CloseSocket + #define CloseSocket(s) close(s) + #endif + #define StartTCP() + #ifdef FREERTOS_TCP_WINSIM + extern int close(int); + #endif +#endif + + WOLFSSL_API int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx); WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); #if defined(USE_WOLFSSL_IO) @@ -334,8 +385,11 @@ WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); /* I/O callbacks */ typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); -WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); -WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); +WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); +/* deprecated old name */ +#define wolfSSL_SetIORecv wolfSSL_CTX_SetIORecv +#define wolfSSL_SetIOSend wolfSSL_CTX_SetIOSend WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); @@ -364,6 +418,46 @@ WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); WOLFSSL_LOCAL int MicriumSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); #endif /* MICRIUM */ +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + WOLFSSL_LOCAL int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx); + WOLFSSL_API void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, + struct mn_sockaddr_in* mnSockAddrIn); +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ + +#ifdef WOLFSSL_UIP + + struct uip_wolfssl_ctx { + union socket_connector { + struct tcp_socket tcp; + struct udp_socket udp; + } conn; + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + uint8_t *input_databuf; + uint8_t *output_databuf; + uint8_t *ssl_rx_databuf; + int ssl_rb_len; + int ssl_rb_off; + struct process *process; + tcp_socket_data_callback_t input_callback; + tcp_socket_event_callback_t event_callback; + int closing; + uip_ipaddr_t peer_addr; + uint16_t peer_port; + }; + + typedef struct uip_wolfssl_ctx uip_wolfssl_ctx; + + WOLFSSL_LOCAL int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_LOCAL int uIPReceive(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + +#endif + #ifdef WOLFSSL_DTLS typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, void* ctx); diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index 4ac9a8b41..887f9b6e6 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -1,57 +1,152 @@ -set(COMPONENT_SRCDIRS source driver) +if(BOOTLOADER_BUILD) + # For bootloader, all we need from esp8266 is headers + set(COMPONENT_ADD_INCLUDEDIRS include) + # set(COMPONENT_REQUIRES ${COMPONENTS}) + set(COMPONENT_SRCS source/ets_printf.c source/crc.c source/esp_fast_boot.c) + register_component(esp8266) -set(COMPONENT_ADD_INCLUDEDIRS include) + # as cmake won't attach linker args to a header-only library, attach + # linker args directly to the bootloader.elf + set(ESP8266_BOOTLOADER_LINKER_SCRIPTS + "${CMAKE_CURRENT_SOURCE_DIR}/ld/esp8266.rom.ld" + PARENT_SCOPE + ) -set(COMPONENT_PRIV_INCLUDEDIRS include/driver) + set(ESP8266_BOOTLOADER_LIBS + "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib" + "core" + PARENT_SCOPE + ) -set(COMPONENT_REQUIRES lwip) -set(COMPONENT_PRIV_REQUIRES freertos) +else() + # Regular app build -register_component() + set(srcs + "source/chip_boot.c" + "source/backtrace.c" + "source/esp_sleep.c" + "source/esp_timer.c" + "source/esp_wifi_os_adapter.c" + "source/esp_wifi.c" + "source/ets_printf.c" + "source/crc.c" + "source/phy_init.c" + "source/reset_reason.c" + "source/smartconfig.c" + "source/smartconfig_ack.c" + "source/startup.c" + "source/system_api.c" + "source/task_wdt.c" + "source/rom.c" + "source/hw_random.c" + "source/esp_fast_boot.c" + "driver/adc.c" + "driver/gpio.c" + "driver/hw_timer.c" + "driver/i2c.c" + "driver/i2s.c" + "driver/pwm.c" + "driver/spi.c" + "driver/hspi_logic_layer.c" + "driver/uart.c" + "driver/ir_tx.c" + "driver/ir_rx.c" + "driver/ledc.c") -target_link_libraries(${COMPONENT_NAME} "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") -if(NOT CONFIG_NO_BLOBS) - target_link_libraries(${COMPONENT_NAME} gcc hal core - net80211 phy pp smartconfig ssc wpa espnow wps) -endif() + set(include_dirs "include" "include/driver") -target_link_libraries(${COMPONENT_NAME} "-u call_user_start") + set(requires "esp_common" "esp_event") + set(priv_requires "wpa_supplicant" "log" "spi_flash" "tcpip_adapter" "esp_ringbuf" "bootloader_support" "nvs_flash" "app_update") + set(fragments linker.lf ld/esp8266_fragments.lf ld/esp8266_bss_fragments.lf) -set(ESPTOOLPY_FLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) + idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + REQUIRES "${requires}" + PRIV_REQUIRES "${priv_requires}" + LDFRAGMENTS "${fragments}" + REQUIRED_IDF_TARGETS esp8266) -if(ESPTOOLPY_FLASHSIZE STREQUAL "512KB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.512.${CONFIG_ESPTOOLPY_APP_NUM}.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "1MB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.1024.${CONFIG_ESPTOOLPY_APP_NUM}.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "2MB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.1024.${CONFIG_ESPTOOLPY_APP_NUM}.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "2MB-c1") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.2048.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "4MB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.1024.${CONFIG_ESPTOOLPY_APP_NUM}.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "4MB-c1") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.2048.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "8MB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.2048.ld) -endif() -if(ESPTOOLPY_FLASHSIZE STREQUAL "16MB") -set(ESP8266_LINKER_SCRIPTS eagle.app.v6.new.2048.ld) -endif() + target_link_libraries(${COMPONENT_LIB} PUBLIC "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib" "-lstdc++") + target_compile_definitions(${COMPONENT_LIB} PUBLIC -DUSING_IBUS_FASTER_GET) + if(NOT CONFIG_NO_BLOBS) + set(blobs "gcc" "hal" "phy" "rtc" "clk" "smartconfig" "ssc") + if(CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE) + list(APPEND blobs "core_dbg" "net80211_dbg" "pp_dbg" "espnow_dbg") + else() + list(APPEND blobs "core" "net80211" "pp" "espnow") + endif() + foreach(blob ${blobs}) + add_library(${blob} STATIC IMPORTED) + set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/lib${blob}.a) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${blob}) + + foreach(_blob ${blobs}) + if(NOT _blob STREQUAL ${blob}) + set_property(TARGET ${blob} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${_blob}) + endif() + endforeach() + + set_property(TARGET ${blob} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${COMPONENT_LIB}) + endforeach() + endif() + target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp8266_out.ld") -target_linker_script(${COMPONENT_NAME} - ld/${ESP8266_LINKER_SCRIPTS} - ld/eagle.app.v6.common.ld - ld/eagle.rom.addr.v6.ld) + target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp8266.project.ld.in" + PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp8266.project.ld") -target_compile_options(${COMPONENT_NAME} PUBLIC -Wno-error=char-subscripts -Wno-error=unknown-pragmas -Wno-error=implicit-function-declaration - -Wno-error=pointer-sign -Wno-error=switch -Wno-error=maybe-uninitialized -Wno-error=format= - -Wno-error=unused-value -Wno-error=address -Wno-error=return-type -Wno-error=format-extra-args - -Wno-error=format-zero-length -Wno-error=unused-label -Wno-error=sizeof-pointer-memaccess) + target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp8266.rom.ld") + target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp8266.peripherals.ld") -target_compile_options(${COMPONENT_NAME} PUBLIC -DICACHE_FLASH) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start") + + # Preprocess esp8266.ld linker script to include configuration, becomes esp8266_out.ld + set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld) + + partition_table_get_partition_info(app_offset "--partition-boot-default" "offset") + partition_table_get_partition_info(app_size "--partition-boot-default" "size") + set(CFLAGS ${CFLAGS} -DAPP_OFFSET=${app_offset} -DAPP_SIZE=${app_size}) + + add_custom_command( + OUTPUT esp8266_out.ld + COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp8266_out.ld ${CFLAGS} -I ${CONFIG_DIR} ${LD_DIR}/esp8266.ld + MAIN_DEPENDENCY ${LD_DIR}/esp8266.ld ${SDKCONFIG_H} + COMMENT "Generating memory map linker script..." + VERBATIM) + add_custom_target(esp8266_linker_script DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/esp8266_out.ld") + add_dependencies(${COMPONENT_LIB} esp8266_linker_script) + + if(CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION) + set(PHY_INIT_DATA_BIN ${build_dir}/phy_init_data.bin) + + # To get the phy_init_data.bin file, compile phy_init_data.h as a C file and then objcopy + # the object file to a raw binary + add_custom_command( + OUTPUT ${PHY_INIT_DATA_BIN} + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/include/esp_private/phy_init_data.h + COMMAND ${CMAKE_C_COMPILER} -x c -c + -I ${CMAKE_CURRENT_LIST_DIR} -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${CMAKE_BINARY_DIR} + -I ${CONFIG_DIR} -I ${CMAKE_CURRENT_LIST_DIR}/../esp_common/include + -o phy_init_data.obj + ${CMAKE_CURRENT_LIST_DIR}/include/esp_private/phy_init_data.h + COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${PHY_INIT_DATA_BIN} + ) + add_custom_target(phy_init_data ALL DEPENDS ${PHY_INIT_DATA_BIN}) + add_dependencies(flash phy_init_data) + + partition_table_get_partition_info(phy_init_data_offset "--partition-type data --partition-subtype phy" "offset") + esptool_py_flash_project_args(phy_init_data ${phy_init_data_offset} "${PHY_INIT_DATA_BIN}" FLASH_IN_PROJECT) + endif() + + if(CONFIG_ESP_FILENAME_MACRO_NO_PATH) + target_compile_definitions(${COMPONENT_LIB} PUBLIC -D __ESP_FILE__=__FILE__) + endif() + + if(CONFIG_ESP_FILENAME_MACRO_RAW) + target_compile_definitions(${COMPONENT_LIB} PUBLIC -D __ESP_FILE__=__FILE__) + endif() + + if(CONFIG_ESP_FILENAME_MACRO_NULL) + target_compile_definitions(${COMPONENT_LIB} PUBLIC -D __ESP_FILE__="null") + endif() + +endif() diff --git a/components/esp8266/Kconfig b/components/esp8266/Kconfig index 286205c55..f6268496e 100644 --- a/components/esp8266/Kconfig +++ b/components/esp8266/Kconfig @@ -1,33 +1,52 @@ menu "ESP8266-specific" -config APP_OFFSET - hex - default 0x1000 - -choice NEWLIB_STDOUT_LINE_ENDING - prompt "Line ending for UART output" - default NEWLIB_STDOUT_LINE_ENDING_CRLF +config ESP8266_NMI_WDT + bool "Enable non-mask watch dog" + default y help - This option allows configuring the desired line endings sent to UART - when a newline ('\n', LF) appears on stdout. - Three options are possible: + Important: this non-mask watch dog is registered to non-mask timer0, + so it can not work together with PWM. - CRLF: whenever LF is encountered, prepend it with CR + Enable this non-mask watch dog can help users to debug blocking code + when CPU is at critical state(disable interrupt). - LF: no modification is applied, stdout is sent as is - CR: each occurence of LF is replaced with CR +choice ESP8266_XTAL_FREQ_SEL + prompt "Main XTAL frequency" + default ESP8266_XTAL_FREQ_26 + help + ESP8266 currently supports the following XTAL frequencies: + + - 26 MHz + - 40 MHz + config ESP8266_XTAL_FREQ_40 + bool "40 MHz" + config ESP8266_XTAL_FREQ_26 + bool "26 MHz" +endchoice + +config ESP8266_XTAL_FREQ + int + default 40 if ESP8266_XTAL_FREQ_40 + default 26 if ESP8266_XTAL_FREQ_26 - This option doesn't affect behavior of the UART driver (drivers/uart.h). +choice ESP8266_DEFAULT_CPU_FREQ_MHZ + prompt "CPU frequency" + default ESP8266_DEFAULT_CPU_FREQ_160 + help + CPU frequency to be set on application startup. -config NEWLIB_STDOUT_LINE_ENDING_CRLF - bool "CRLF" -config NEWLIB_STDOUT_LINE_ENDING_LF - bool "LF" -config NEWLIB_STDOUT_LINE_ENDING_CR - bool "CR" + config ESP8266_DEFAULT_CPU_FREQ_80 + bool "80 MHz" + config ESP8266_DEFAULT_CPU_FREQ_160 + bool "160 MHz" endchoice +config ESP8266_DEFAULT_CPU_FREQ_MHZ + int + default 80 if ESP8266_DEFAULT_CPU_FREQ_80 + default 160 if ESP8266_DEFAULT_CPU_FREQ_160 + choice ESP_FILENAME_MACRO prompt "File name macro text" default ESP_FILENAME_MACRO_NO_PATH @@ -49,6 +68,41 @@ config ESP_FILENAME_MACRO_NULL bool "null" endchoice +config USING_NEW_ETS_VPRINTF + bool "Using new ets_vprintf instead of rom code" + default y + help + Enable this option, SDK will use new "ets_vprintf" function instead of old code "ets_vprintf" which is depend on ROM + code "ets_io_vprintf". + + Note: Bootloader can't use this function. + +config LINK_ETS_PRINTF_TO_IRAM + bool "Link ets_printf to IRAM" + default n + help + Enable this option, SDK will link the old/new "ets_printf" and "ets_vprintf" to IRAM instead of flash. + So although flash can't be access for SoC when reading to writing, the "ets_printf" and "ets_vprintf" also can be used by user. + + Using new "ets_vprintf" should cost more 1.6KB IRAM. + + Note: Bootloader can't use this function. + +config ETS_PRINTF_EXIT_WHEN_FLASH_RW + bool "ets_printf exits when flash R/W" + default y + depends on !LINK_ETS_PRINTF_TO_IRAM + help + By default option, we link the ets_printf function and its calling functions + in SPI Flash. So when the SPI Flash is working in read/write mode, and we + call ets_printf in high level interrupt like NMI, this behavior will cause a + crash, and the EXCCAUSE=0. + + Enable this option, we link the ets_printf in IRAM, and its calling functions + in SPI Flash. In the entry of ets_printf, we check if the SPI Flash is working + in read/write mode, and exit if it is. So that ets_printf will not call functions + in SPI Flash. + config SOC_FULL_ICACHE bool "Enable full cache mode" default n @@ -61,94 +115,63 @@ config SOC_IRAM_SIZE default 0x8000 if SOC_FULL_ICACHE default 0xC000 if !SOC_FULL_ICACHE -choice CONSOLE_UART_NUM - prompt "UART peripheral to use for console output (0-1)" - default CONSOLE_UART_CUSTOM_NUM_0 +config DISABLE_ROM_UART_PRINT + bool "Disable ROM UART print" + default n help - Configrate output console UART for "ets_printf", "printf", "ESP_LOGX" and so on. - -config CONSOLE_UART_CUSTOM_NUM_0 - bool "UART0" -config CONSOLE_UART_CUSTOM_NUM_1 - bool "UART1" -endchoice - -config CONSOLE_UART_NUM - int - default 0 if CONSOLE_UART_CUSTOM_NUM_0 - default 1 if CONSOLE_UART_CUSTOM_NUM_1 + "Disable main part of ROM UART print when rom bootloader process." -config CONSOLE_UART_BAUDRATE - int "UART console baud rate" - default 74880 - range 1200 4000000 - -config CONSOLE_UART_SWAP_IO - bool "Swap UART0 I/O pins" - default n +choice ESP_PANIC + prompt "Panic handler behaviour" + default ESP_PANIC_PRINT_REBOOT help - Enable this option, UART0's I/O pins are swaped: TXD <-> RTS, RTX <-> CTS. + If an unhandled exception, the panic handler is invoked. + Configure the panic handlers action here. -config MAIN_TASK_STACK_SIZE - int "Main task stack size" - default 3584 +config ESP_PANIC_PRINT_HALT + bool "Print registers and halt" help - Configure the "main task" stack size. This is the stack of the task - which calls app_main(). If app_main() returns then this task is deleted - and its stack memory is freed. + Outputs the relevant registers over the serial port and halt the + processor. Needs a manual reset to restart. -config TASK_WDT - bool "Initialize Task Watchdog Timer on startup" - default y +config ESP_PANIC_PRINT_REBOOT + bool "Print registers and reboot" help - The Task Watchdog Timer can be used to make sure individual tasks are still - running. Enabling this option will cause the Task Watchdog Timer to be - initialized automatically at startup. The Task Watchdog timer can be - initialized after startup as well. + Outputs the relevant registers over the serial port and immediately + reset the processor. -config TASK_WDT_PANIC - bool "Invoke panic handler on Task Watchdog timeout" - default y +config ESP_PANIC_SILENT_REBOOT + bool "Silent reboot" help - If this option is enabled, the Task Watchdog Timer will be configured to - trigger the panic handler when it times out. And it may cost some time. + Just resets the processor without outputting anything -choice TASK_WDT_TIMEOUT_S - prompt "Task Watchdog timeout period (seconds)" - default TASK_WDT_TIMEOUT_15N +config ESP_PANIC_GDBSTUB + bool "Invoke GDBStub" + select ESP_GDBSTUB_ENABLED help - Timeout period configuration for the Task Watchdog Timer in seconds. - This is also configurable at run time. + Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem + of the crash. -config TASK_WDT_TIMEOUT_13N - bool "6.5536s" -config TASK_WDT_TIMEOUT_14N - bool "13.1072s" -config TASK_WDT_TIMEOUT_15N - bool "26.2144s" + The UART's baudrate should be 115200 or others which can be recognized by xtensa GDB. endchoice -config TASK_WDT_TIMEOUT_S - int - default 13 if TASK_WDT_TIMEOUT_13N - default 14 if TASK_WDT_TIMEOUT_14N - default 15 if TASK_WDT_TIMEOUT_15N +config RESET_REASON + bool "Enable reset reason" + default y + help + Enable this option, the reset reason function can be used, or compiler will show function linking error. config WIFI_PPT_TASKSTACK_SIZE int "ppT task stack size" - default 2048 range 2048 8192 + default 2048 if !ESP8266_WIFI_ENABLE_WPA3_SAE + default 5120 if ESP8266_WIFI_ENABLE_WPA3_SAE + help Configure the "ppT task" stack size. This is the stack of the task which calls promiscuous callback function. So if user's function is complex, the stack must be set larger. -config EVENT_LOOP_STACK_SIZE - int "Event loop stack size" - default 2048 - help - Configure the Event loop task stack size per application. - config ESP8266_CORE_GLOBAL_DATA_LINK_IRAM bool "Link libcore.a internal global data to IRAM" default y @@ -157,14 +180,88 @@ config ESP8266_CORE_GLOBAL_DATA_LINK_IRAM help Link libcore.a internal global data(.bss .data COMMON) from DRAM to IRAM. +config INIT_OS_BEFORE_START + bool "Init OS before starting it" + default n + depends on DISABLE_FREERTOS + help + Some OSes should initialize their global data structure before starting them. rt-thread is like this one. + + FreeRTOS need not do this. + +config ESP8266_OTA_FROM_OLD + bool "ESP8266 update from old SDK by OTA" + default n + depends on IDF_TARGET_ESP8266 + select ESP8266_BOOT_COPY_APP if ESPTOOLPY_FLASHSIZE_1MB + help + The function is not released. + + Enable this option, script will generate the complete firmware for both old RTOS SDK(before V3.0) + and NonOS SDK to update to v3 by OTA. + + The old RTOS SDK(before V3.0) or NonOS SDK can download the firmware to its partition and run it as it self's application. + +config LOAD_OLD_RF_PARAMETER + bool "Load old RF Parameters" + default n + depends on ESP8266_OTA_FROM_OLD + select ESP_PHY_INIT_DATA_IN_PARTITION + help + The function is not released. + + Enable this option, after updating from old SDK to new SDK, bootloader will copy RF + parameters from old SDK partition to new SDK partition. + + Then application can read the RF parameters from new partition directly. + +config ESP8266_BOOT_COPY_APP + bool "Boot copy app" + default n + help + The function is not released. + + Enable this option, when it is that "OTA1" application is to run after update by OTA, + bootloader will copy "OTA1" application to "OTA0" partition and run "OTA0". + + choice ESP8266_TIME_SYSCALL + prompt "Timers used for gettimeofday function" + default ESP8266_TIME_SYSCALL_USE_FRC1 + help + This setting defines which hardware timers are used to + implement 'gettimeofday' and 'time' functions in C library. + + - If high-resolution timer is used, gettimeofday will + provide time at microsecond resolution. + Time will not be preserved when going into deep sleep mode. + - If no timers are used, gettimeofday and time functions + return -1 and set errno to ENOSYS. + + config ESP8266_TIME_SYSCALL_USE_FRC1 + bool "High-resolution timer" + config ESP8266_TIME_SYSCALL_USE_NONE + bool "None" + endchoice +endmenu + +menu "Power Management" + config PM_ENABLE + bool "Support for power management" + default n + help + If enabled, application is compiled with support for power management. + This option has run-time overhead (increased interrupt latency, + longer time to enter idle state), and it also reduces accuracy of + RTOS ticks and timers used for timekeeping. + Enable this option if application uses power management APIs. endmenu -menu WIFI +menu Wi-Fi config SCAN_AP_MAX int "Max scan AP number" - range 1 64 - default 32 + range 1 100 + default 99 help Function "esp_wifi_scan_get_ap_num" return value will be less than this. It is said that user cannot scan more than this. @@ -172,12 +269,248 @@ config SCAN_AP_MAX User can use own function "esp_wifi_scan_get_ap_num_max" to determin how many AP to scan , too. config WIFI_TX_RATE_SEQUENCE_FROM_HIGH - bool "Set wifi tx rate from 54M to 1M" + bool "Set WiFi TX rate from 54M to 1M" default y help - If this option is enabled, Wifi will try to send packets first from high rate(54M). If it fails, it will + If this option is enabled, WiFi will try to send packets first from high rate(54M). If it fails, it will try at low rate until the transmission is successful. +config ESP8266_WIFI_QOS_ENABLED + bool "WiFi QoS" + default n + help + Select this option to enable QoS feature + +config ESP8266_WIFI_AMPDU_RX_ENABLED + bool "WiFi AMPDU RX" + default n + help + Select this option to enable AMPDU RX feature + +config ESP8266_WIFI_RX_BA_WIN_SIZE + int "WiFi AMPDU RX BA window size" + depends on ESP8266_WIFI_AMPDU_RX_ENABLED + range 0 16 + default 6 + help + Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput and better + compatibility but more memory. + +config ESP8266_WIFI_AMSDU_ENABLED + bool "WiFi AMSDU RX" + default n + help + Select this option to enable AMSDU feature + +config ESP8266_WIFI_RX_BUFFER_NUM + int "Max number of WiFi RX buffers" + range 14 28 + default 16 + help + Set the number of WiFi RX buffers. Each buffer takes approximately ESP8266_WIFI_RX_BUFFER_LEN bytes of RAM. + + WiFi hardware use these buffers to receive all 802.11 frames. + A higher number may allow higher throughput but increases memory use. If ESP8266_WIFI_AMPDU_RX_ENABLED + is enabled, this value is recommended to set equal or bigger than 8*1024/ESP8266_WIFI_RX_BUFFER_LEN in order + to achieve better throughput and compatibility with both stations and APs. + Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP RX + throughput with iperf etc. For iperf test in shieldbox, the recommended value is 26. + +config ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM + int "The min number of WiFi continuous RX buffer" + range 0 16 + default 16 + help + Set the number of WiFi continuous RX buffer num. + The smaller the value, the easier RX hang will appear. Most of time we should NOT change the default + value unless special reason. + +config ESP8266_WIFI_RX_PKT_NUM + int "Max number of WiFi RX packets" + range 4 16 + default 7 + help + Set the max number of signle WiFi packet. + +config ESP8266_WIFI_TX_PKT_NUM + int "Max number of WiFi TX packets" + range 4 16 + default 6 + help + Set the number of WiFi TX packets. Each buffer takes approximately 1.6KB of RAM. + For some applications especially UDP applications, the upper layer can deliver frames faster than WiFi + layer can transmit. In these cases, we may run out of TX packets. + +config ESP8266_WIFI_NVS_ENABLED + bool "WiFi NVS flash" + default y + help + Select this option to enable WiFi NVS flash + +config ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET + bool "Connect open router when wifi password is set" + default y + help + When this option is enabled, ESP8266 will connect to open router even if wifi password is set, otherwise + ESP8266 will not connect to open router when wifi password is set. + +config ESP8266_WIFI_ENABLE_WPA3_SAE + bool "Enable WPA3-Personal" + default y + help + Select this option to allow the device to establish a WPA3-Personal connection with eligible AP's. + PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be + explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. + +config ESP8266_WIFI_DEBUG_LOG_ENABLE + bool "Enable WiFi debug log" + default n + help + Select this option to enable WiFi debug log + +choice ESP8266_WIFI_DEBUG_LOG_LEVEL + depends on ESP8266_WIFI_DEBUG_LOG_ENABLE + prompt "The DEBUG level is enabled" + default ESP8266_WIFI_DEBUG_LOG_ERROR + help + The WiFi log is divided into the following levels: ERROR,WARNING,INFO,DEBUG,VERBOSE. + The ERROR level is enabled by default, and the WARNING,INFO,DEBUG,VERBOSE levels can be enabled here. + + config ESP8266_WIFI_DEBUG_LOG_ERROR + bool "Error" + config ESP8266_WIFI_DEBUG_LOG_WARNING + bool "Warning" + config ESP8266_WIFI_DEBUG_LOG_INFO + bool "Info" + config ESP8266_WIFI_DEBUG_LOG_DEBUG + bool "Debug" + config ESP8266_WIFI_DEBUG_LOG_VERBOSE + bool "Verbose" +endchoice + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE + depends on ESP8266_WIFI_DEBUG_LOG_ENABLE + bool "WiFi debug log submodule" + default n + help + Enable this option to set the WiFi debug log submodule. + Currently the log submodule contains the following parts: INIT,IOCTL,CONN,SCAN. + The INIT submodule indicates the initialization process.The IOCTL submodule indicates the API calling + process. + The CONN submodule indicates the connecting process.The SCAN submodule indicates the scaning process. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_CORE + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "core" + default n + help + When this option is enabled, log for core module will be enabled.. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_SCAN + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "scan" + default n + help + When this option is enabled, log for scan module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_PM + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "power management" + default n + help + When this option is enabled, log for power management module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_NVS + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "NVS" + default n + help + When this option is enabled, log for NVS module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_TRC + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "TRC" + default n + help + When this option is enabled, log for TRC module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_EBUF + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "EBUF" + default n + help + When this option is enabled, log for EBUF module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_NET80211 + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "NET80211" + default n + help + When this option is enabled, log for net80211 module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_TIMER + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "TIMER" + default n + help + When this option is enabled, log for timer module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_ESPNOW + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "ESPNOW" + default n + help + When this option is enabled, log for espnow module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_MAC + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "MAC layer" + default n + help + When this option is enabled, log for mac layer module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPA + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "wpa" + default n + help + When this option is enabled, log for wpa module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPS + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "wps" + default n + help + When this option is enabled, log for wps module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_AMPDU + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "ampdu" + default n + help + When this option is enabled, log for ampdu module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_AMSDU + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "amsdu" + default n + help + When this option is enabled, log for amsdu module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_FRAG + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "fragment" + default n + help + When this option is enabled, log for frag module will be enabled. + +config ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPA2 + depends on ESP8266_WIFI_DEBUG_LOG_SUBMODULE + bool "wpa2_enterprise" + default n + help + When this option is enabled, log for wpa2_enterprise module will be enabled. + endmenu menu PHY @@ -187,9 +520,12 @@ config ESP_PHY_CALIBRATION_AND_DATA_STORAGE default y help If this option is enabled, NVS will be initialized and calibration data will be loaded from there. - PHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full calibration - will be performed and stored in NVS. Normally, only partial calibration will be performed. - If this option is disabled, full calibration will be performed. + If calibration data is not found, full calibration will be performed and stored in NVS. Normally, + only partial calibration will be performed. If this option is disabled, full calibration will be performed. + + Full calibration needs 170 - 180ms. + Partial calibration needs 35 - 40ms. + No calibration needs 3.260 - 3.264ms. If it's easy that your board calibrate bad data, choose 'n'. Two cases for example, you should choose 'n': @@ -213,5 +549,33 @@ config ESP_PHY_INIT_DATA_IN_PARTITION If unsure, choose 'n'. +config ESP_PHY_INIT_DATA_VDD33_CONST + int "vdd33_const value" + range 0 255 + default 33 + help + vdd33_const provides ADC mode settings, i.e. selecting system voltage or external voltage measurements. + When measuring system voltage, it must be set to 255. + To read the external voltage on TOUT(ADC) pin, vdd33_const need less than 255 + When the ADC reference voltage is set to the actual VDD33 power supply voltage, the value range of vdd33_const is [18,36], the unit is 0.1V. + When the ADC reference voltage is set to the default value of 3.3V as the supply voltage, the range of vdd33_const is [0, 18] or (36, 255). + +config ESP8266_PHY_MAX_WIFI_TX_POWER + int "Max WiFi TX power (dBm)" + range 0 21 + default 20 + help + Set maximum transmit power for WiFi radio. Actual transmit power for high + data rates may be lower than this setting. + endmenu # PHY +menu HSPI +config ESP8266_HSPI_HIGH_THROUGHPUT + bool "Do some optimization to improve throughput" + default n + help + If enable this configuration, some spi api will be placed into iram. + And it will reduce iram memory. +endmenu # Driver + diff --git a/components/esp8266/Makefile.projbuild b/components/esp8266/Makefile.projbuild index 073bed18f..d14b710ea 100644 --- a/components/esp8266/Makefile.projbuild +++ b/components/esp8266/Makefile.projbuild @@ -1,5 +1,5 @@ -SUPPORTED_TOOLCHAIN_COMMIT_DESC := 1.22.0-88-gde0bdc1 -SUPPORTED_TOOLCHAIN_GCC_VERSIONS := 4.8.5 +SUPPORTED_TOOLCHAIN_COMMIT_DESC := esp-2020r3-49-gd5524c1 +SUPPORTED_TOOLCHAIN_GCC_VERSIONS := 8.4.0 ifdef CONFIG_ESP8266_LEGACY @@ -35,14 +35,14 @@ PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin # Command to flash PHY init data partition -PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) ESP8266_COMPONENT_PATH := $(COMPONENT_PATH) -$(PHY_INIT_DATA_OBJ): $(ESP8266_COMPONENT_PATH)/source/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h +$(PHY_INIT_DATA_OBJ): $(ESP8266_COMPONENT_PATH)/include/esp_private/phy_init_data.h $(BUILD_DIR_BASE)/include/sdkconfig.h $(summary) CC $(notdir $@) - printf "#include \"source/phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP8266_COMPONENT_PATH) -I $(ESP8266_COMPONENT_PATH)/include -c -o $@ -xc - + printf "#include \"esp_private/phy_init_data.h\"\n" | $(CC) -I $(BUILD_DIR_BASE)/include -I $(ESP8266_COMPONENT_PATH) -I $(ESP8266_COMPONENT_PATH)/include -I $(ESP8266_COMPONENT_PATH)/../esp_common/include -c -o $@ -xc - $(PHY_INIT_DATA_BIN): $(PHY_INIT_DATA_OBJ) $(summary) BIN $(notdir $@) @@ -64,6 +64,15 @@ endif # CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION endif +ifndef IS_BOOTLOADER_BUILD +LINKER_SCRIPT_TEMPLATE := $(COMPONENT_PATH)/ld/esp8266.project.ld.in +LINKER_SCRIPT_OUTPUT_DIR := $(abspath $(BUILD_DIR_BASE)/esp8266) + +# Target to generate linker script generator from fragments presented by each of +# the components +$(eval $(call ldgen_process_template,$(LINKER_SCRIPT_TEMPLATE),$(LINKER_SCRIPT_OUTPUT_DIR)/esp8266.project.ld)) +endif + # global CFLAGS for ESP8266 CFLAGS += -DICACHE_FLASH @@ -82,50 +91,73 @@ CFLAGS += -D__ESP_FILE__='"null"' CXXFLAGS += -D__ESP_FILE__='"null"' endif -.PHONY: ota ota-clean - -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") -APP1_OFFSET ?= 0x10000 -APP1_SIZE ?= 0x70000 -APP2_OFFSET ?= 0x80000 -APP2_SIZE ?= 0x70000 -else -APP1_OFFSET ?= CONFIG_APP_OFFSET -APP1_SIZE ?= 0x100000 -endif +.PHONY: ota ota-clean app2 app2-flash app2-flash-all RAW_BIN := ./build/$(PROJECT_NAME).bin OTA_BIN := ./build/$(PROJECT_NAME).ota.bin OTA1_BIN := ./build/$(PROJECT_NAME).app1.bin OTA2_BIN := ./build/$(PROJECT_NAME).app2.bin -$(OTA2_BIN): all_binaries -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") - @rm -f ./build/esp8266/esp8266_out.ld - @make APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE) CFLAGS= CXXFLAGS= +OTA_V2_TO_V3_BIN := ./build/$(PROJECT_NAME).v2_to_v3.ota.bin + +ifndef CONFIG_ESP8266_BOOT_COPY_APP +ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB +__COMBILE_OTA_BIN := 1 +endif endif - @cp $(RAW_BIN) $(OTA2_BIN) - @echo [GEN] $(OTA2_BIN) -$(OTA1_BIN): all_binaries -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") +app2: all +ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB @rm -f ./build/esp8266/esp8266_out.ld + @export CFLAGS= && export CXXFLAGS= && make APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE) endif - @make APP_OFFSET=$(APP1_OFFSET) APP_SIZE=$(APP1_SIZE) CFLAGS= CXXFLAGS= + @echo "To flash all build output, run 'make flash' or:" + @echo $(ESPTOOLPY_WRITE_FLASH) $(APP2_OFFSET) $(APP_BIN) + +app2-flash: app2 + @$(ESPTOOLPY_WRITE_FLASH) $(APP2_OFFSET) $(APP_BIN) + +app2-flash-all: app2 + @$(ESPTOOLPY_WRITE_FLASH) $(patsubst $(APP_OFFSET),$(APP2_OFFSET),$(ESPTOOL_ALL_FLASH_ARGS)) + +$(OTA1_BIN): all_binaries + @cp $(RAW_BIN) $(RAW_BIN).old @cp $(RAW_BIN) $(OTA1_BIN) @echo [GEN] $(OTA1_BIN) -$(OTA_BIN): $(OTA1_BIN) $(OTA2_BIN) +$(OTA2_BIN): $(OTA1_BIN) +ifdef __COMBILE_OTA_BIN + @rm -f ./build/esp8266/esp8266_out.ld + @export CFLAGS= && export CXXFLAGS= && make $(APP_BIN) APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE) +endif + @cp $(RAW_BIN) $(OTA2_BIN) + @echo [GEN] $(OTA2_BIN) + +$(OTA_BIN): $(OTA2_BIN) @cp $(OTA1_BIN) $(OTA_BIN) -ifeq ($(CONFIG_ESPTOOLPY_FLASHSIZE), "1MB") +ifdef __COMBILE_OTA_BIN @cat $(OTA2_BIN) >> $(OTA_BIN) -endif @cp $(OTA1_BIN) $(RAW_BIN) +endif @echo [GEN] $(OTA_BIN) +PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) + +ifdef CONFIG_ESP8266_OTA_FROM_OLD +$(OTA_V2_TO_V3_BIN): all + @$(PYTHON) $(IDF_PATH)/tools/pack_fw.py --output $(OTA_V2_TO_V3_BIN) --app $(PROJECT_NAME).bin pack3 $(ESPTOOL_ALL_FLASH_ARGS) + @echo [GEN] $(OTA_V2_TO_V3_BIN) +endif + +ifdef CONFIG_ESP8266_OTA_FROM_OLD +ota: $(OTA_V2_TO_V3_BIN) +else ota: $(OTA_BIN) + @cp $(RAW_BIN).old $(RAW_BIN) + @rm $(RAW_BIN).old +endif ota-clean: - @rm -f $(OTA_BIN) $(OTA1_BIN) $(OTA2_BIN) + @rm -f $(OTA_BIN) $(OTA1_BIN) $(OTA2_BIN) $(OTA_V2_TO_V3_BIN) clean: ota-clean diff --git a/components/esp8266/component.mk b/components/esp8266/component.mk index 926161dbd..5b5552261 100644 --- a/components/esp8266/component.mk +++ b/components/esp8266/component.mk @@ -2,7 +2,7 @@ # Component Makefile # ifdef IS_BOOTLOADER_BUILD -COMPONENT_OBJS := source/ets_printf.o +COMPONENT_OBJS := source/ets_printf.o source/crc.o source/esp_fast_boot.o COMPONENT_SRCDIRS := source else COMPONENT_ADD_INCLUDEDIRS += include @@ -11,46 +11,49 @@ COMPONENT_SRCDIRS := driver source LIBS ?= ifndef CONFIG_NO_BLOBS +ifndef CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE LIBS += gcc hal core net80211 \ - phy pp smartconfig ssc wpa espnow wps + phy rtc clk pp smartconfig ssc espnow +else +LIBS += gcc hal core_dbg net80211_dbg \ + phy rtc clk pp_dbg smartconfig ssc espnow_dbg +endif endif +CFLAGS += -DUSING_IBUS_FASTER_GET #Linker scripts used to link the final application. #Warning: These linker scripts are only used when the normal app is compiled; the bootloader #specifies its own scripts. LINKER_SCRIPTS += esp8266.rom.ld esp8266.peripherals.ld +COMPONENT_ADD_LDFRAGMENTS += ld/esp8266_fragments.lf ld/esp8266_bss_fragments.lf linker.lf + COMPONENT_ADD_LDFLAGS += -L$(COMPONENT_PATH)/lib \ $(addprefix -l,$(LIBS)) \ -L $(COMPONENT_PATH)/ld \ -T esp8266_out.ld \ - -T esp8266_common_out.ld \ + -T $(COMPONENT_BUILD_DIR)/esp8266.project.ld \ -Wl,--no-check-sections \ -u call_user_start \ + -u g_esp_sys_info \ $(addprefix -T ,$(LINKER_SCRIPTS)) ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) # final linking of project ELF depends on all binary libraries, and # all linker scripts -COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/,$(LINKER_SCRIPTS)) +COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/, $(filter-out $(COMPONENT_BUILD_DIR)/esp8266.project.ld, $(LINKER_SCRIPTS))) \ + $(COMPONENT_BUILD_DIR)/esp8266.project.ld # Preprocess esp8266.ld linker script into esp8266_out.ld # # The library doesn't really depend on esp8266_out.ld, but it # saves us from having to add the target to a Makefile.projbuild -$(COMPONENT_LIBRARY): esp8266_out.ld esp8266_common_out.ld - -APP_OFFSET ?= $(CONFIG_APP_OFFSET) -APP_SIZE ?= 0x100000 -OUTLD_CFLAGS := -DAPP_OFFSET=$(APP_OFFSET) -DAPP_SIZE=$(APP_SIZE) +$(COMPONENT_LIBRARY): esp8266_out.ld esp8266_out.ld: $(COMPONENT_PATH)/ld/esp8266.ld ../include/sdkconfig.h - $(CC) $(OUTLD_CFLAGS) -I ../include -C -P -x c -E $< -o $@ - -esp8266_common_out.ld: $(COMPONENT_PATH)/ld/esp8266.common.ld ../include/sdkconfig.h - $(CC) -I ../include -C -P -x c -E $< -o $@ + $(CC) $(CFLAGS) -I ../include -C -P -x c -E $< -o $@ -COMPONENT_EXTRA_CLEAN := esp8266_out.ld +COMPONENT_EXTRA_CLEAN := esp8266_out.ld $(COMPONENT_BUILD_DIR)/esp8266.project.ld -endif \ No newline at end of file +endif diff --git a/components/esp8266/driver/adc.c b/components/esp8266/driver/adc.c new file mode 100644 index 000000000..80ee74198 --- /dev/null +++ b/components/esp8266/driver/adc.c @@ -0,0 +1,156 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_phy_init.h" +#include "esp_heap_caps.h" +#include "driver/adc.h" + +static const char *TAG = "adc"; + +#define ADC_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +extern uint16_t test_tout(); +extern void phy_adc_read_fast(uint16_t *adc_addr, uint16_t adc_num, uint8_t adc_clk_div); +extern uint16_t phy_get_vdd33(); + +typedef struct { + adc_config_t config; + SemaphoreHandle_t adc_mux; +} adc_handle_t; + +adc_handle_t *adc_handle = NULL; + +esp_err_t adc_read(uint16_t *data) +{ + ADC_CHECK(data, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + ADC_CHECK(adc_handle, "ADC has not been initialized yet.", ESP_FAIL); + uint16_t ret = 0; + xSemaphoreTake(adc_handle->adc_mux, portMAX_DELAY); + + if (adc_handle->config.mode == ADC_READ_TOUT_MODE) { + vTaskSuspendAll(); + ret = test_tout(0); + xTaskResumeAll(); + + if (ret != 0xFFFF) { + // The working voltage of ADC is designed according to 1.1v. Later, the actual working voltage of ADC is increased to 1.2v, so this scale is added. + ret = ret * 12 / 11; + + if (ret > 1023) { + // 10-bit precision ADC + ret = 1023; + } + } + } else if (adc_handle->config.mode == ADC_READ_VDD_MODE) { + vTaskSuspendAll(); + ret = phy_get_vdd33(); + xTaskResumeAll(); + + if (ret != 0xFFFF) { + // The working voltage of ADC is designed according to 1.1v. Later, the actual working voltage of ADC is increased to 1.2v, so this scale is added. + ret = ret * 12 / 11; + } + } + + *data = ret; + xSemaphoreGive(adc_handle->adc_mux); + return ESP_OK; +} + +esp_err_t adc_read_fast(uint16_t *data, uint16_t len) +{ + ADC_CHECK(data && len > 0, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + ADC_CHECK(adc_handle, "ADC has not been initialized yet.", ESP_FAIL); + ADC_CHECK(adc_handle->config.mode == ADC_READ_TOUT_MODE, "adc_read_fast can only be used in ADC_READ_TOUT_MODE mode", ESP_ERR_INVALID_ARG); + ADC_CHECK(adc_handle->config.clk_div >= 8 && adc_handle->config.clk_div <= 32, "ADC sample collection clock=80M/clk_div, range[8, 32]", ESP_FAIL); + uint16_t i; + uint16_t ret; + + xSemaphoreTake(adc_handle->adc_mux, portMAX_DELAY); + vTaskSuspendAll(); + phy_adc_read_fast(data, len, adc_handle->config.clk_div); + xTaskResumeAll(); + + for (i = 0; i < len; i++) { + ret = data[i]; + + if (ret != 0xFFFF) { + // The working voltage of ADC is designed according to 1.1v. Later, the actual working voltage of ADC is increased to 1.2v, so this scale is added. + ret = ret * 12 / 11; + + if (ret > 1023) { + // 10-bit precision ADC + ret = 1023; + } + } + + data[i] = ret; + } + + xSemaphoreGive(adc_handle->adc_mux); + return ESP_OK; +} + +esp_err_t adc_deinit() +{ + ADC_CHECK(adc_handle, "ADC has not been initialized yet.", ESP_FAIL); + + if (adc_handle->adc_mux) { + vSemaphoreDelete(adc_handle->adc_mux); + } + + heap_caps_free(adc_handle); + adc_handle = NULL; + return ESP_OK; +} + +esp_err_t adc_init(adc_config_t *config) +{ + ADC_CHECK(config, "config error", ESP_ERR_INVALID_ARG); + ADC_CHECK(NULL == adc_handle, "adc has been initialized", ESP_FAIL); + uint8_t vdd33_const; + esp_phy_init_data_t *phy_init_data; + + phy_init_data = (esp_phy_init_data_t *)esp_phy_get_init_data(); + vdd33_const = phy_init_data->params[107]; + + ADC_CHECK((config->mode == ADC_READ_TOUT_MODE) ? (vdd33_const < 255) : true, "To read the external voltage on TOUT(ADC) pin, vdd33_const need less than 255", ESP_FAIL); + ADC_CHECK((config->mode == ADC_READ_VDD_MODE) ? (vdd33_const == 255) : true, "When adc measuring system voltage, vdd33_const must be set to 255,", ESP_FAIL); + ADC_CHECK(config->mode <= ADC_READ_MAX_MODE, "adc mode err", ESP_FAIL); + + adc_handle = heap_caps_malloc(sizeof(adc_handle_t), MALLOC_CAP_8BIT); + ADC_CHECK(adc_handle, "adc handle malloc error", ESP_ERR_NO_MEM); + memcpy(&adc_handle->config, config, sizeof(adc_config_t)); + adc_handle->adc_mux = xSemaphoreCreateMutex(); + + if (NULL == adc_handle->adc_mux) { + adc_deinit(); + ADC_CHECK(false, "Semaphore create fail", ESP_ERR_NO_MEM); + } + + return ESP_OK; +} diff --git a/components/esp8266/driver/gpio.c b/components/esp8266/driver/gpio.c index a1c5d5460..a0124f669 100644 --- a/components/esp8266/driver/gpio.c +++ b/components/esp8266/driver/gpio.c @@ -86,7 +86,10 @@ static gpio_isr_func_t *gpio_isr_func = NULL; esp_err_t gpio_pullup_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -98,7 +101,10 @@ esp_err_t gpio_pullup_en(gpio_num_t gpio_num) esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -110,7 +116,10 @@ esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -122,7 +131,10 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -338,7 +350,7 @@ esp_err_t gpio_config(const gpio_config_t *gpio_cfg) return ESP_OK; } -void gpio_intr_service(void *arg) +void IRAM_ATTR gpio_intr_service(void *arg) { //GPIO intr process uint32_t gpio_num = 0; @@ -352,11 +364,10 @@ void gpio_intr_service(void *arg) do { if (gpio_num < GPIO_PIN_COUNT - 1) { if (gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio15 + GPIO.status_w1tc = BIT(gpio_num); if (gpio_isr_func[gpio_num].fn != NULL) { gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args); } - - GPIO.status_w1tc = BIT(gpio_num); } } } while (++gpio_num < GPIO_PIN_COUNT - 1); diff --git a/components/esp8266/driver/hspi_logic_layer.c b/components/esp8266/driver/hspi_logic_layer.c new file mode 100644 index 000000000..fbe7169ea --- /dev/null +++ b/components/esp8266/driver/hspi_logic_layer.c @@ -0,0 +1,278 @@ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/event_groups.h" +#include "freertos/stream_buffer.h" +#include "ringbuf.h" + +#include "esp8266/spi_struct.h" +#include "esp8266/gpio_struct.h" +#include "esp_system.h" +#include "esp_log.h" + +#include "driver/gpio.h" +#include "driver/spi.h" +#include "driver/hspi_logic_layer.h" + +static const char *TAG = "hspi_logic"; +#define SPI_CHECK(a, str, ret_val) \ + do { \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } \ + } while(0) + +typedef struct { + gpio_num_t trigger_pin; + uint8_t trigger_level; + bool is_sending; + bool is_blocking_recv; + uint32_t sending_len; + uint32_t recving_len; + StreamBufferHandle_t* tx_buffer; + StreamBufferHandle_t* rx_buffer; + + SemaphoreHandle_t semphor; + spi_event_callback_t event_cb; +} spi_logic_device_t; + +static spi_logic_device_t * spi_logic_device; + +static void IRAM_ATTR hspi_slave_event_callback(int event, void *arg) +{ + int x; + BaseType_t xHigherPriorityTaskWoken; + uint32_t status; + uint32_t trans_done; + uint32_t data[16]; + spi_trans_t trans; + uint16_t cmd = 0; + bool trigger_flag = false; + + switch (event) { + case SPI_TRANS_DONE_EVENT: { + gpio_set_level(spi_logic_device->trigger_pin, !spi_logic_device->trigger_level); + trans_done = *(uint32_t *)arg; + if (trans_done & SPI_SLV_RD_BUF_DONE) { + if (spi_logic_device->sending_len == 0) { + spi_logic_device->is_sending = false; + spi_logic_device->sending_len = xStreamBufferBytesAvailable(spi_logic_device->tx_buffer); + if (spi_logic_device->sending_len > 0) { + spi_slave_set_status(HSPI_HOST, (uint32_t*)&spi_logic_device->sending_len); + spi_logic_device->is_sending = true; + trigger_flag = true; + } + } else { + memset(&trans, 0x0, sizeof(trans)); + trans.cmd = &cmd; + trans.addr = NULL; + trans.bits.val = 0; + // In Slave mode, spi cmd must be longer than 3 bits and shorter than 16 bits + trans.bits.cmd = 8 * 1; + // In Slave mode, spi addr must be longer than 1 bits and shorter than 32 bits + trans.bits.addr = 8 * 1; + trans.bits.mosi = 0; + trans.miso = data; + trans.bits.miso = xStreamBufferReceiveFromISR(spi_logic_device->tx_buffer, data, 64, &xHigherPriorityTaskWoken); + if (trans.bits.miso != 0) { + spi_logic_device->sending_len -= trans.bits.miso; + trans.bits.miso <<= 3; + spi_trans(HSPI_HOST, &trans); + trigger_flag = true;; + } + } + } + + if (trans_done & SPI_SLV_WR_BUF_DONE) { + uint32_t len = spi_logic_device->recving_len; + if (len > 64) { + len = 64; + } + + if (len > 0) { + for (x = 0; x < 16; x++) { + data[x] = SPI1.data_buf[x]; + } + xStreamBufferSendFromISR(spi_logic_device->rx_buffer, (void *) data, len, &xHigherPriorityTaskWoken); + spi_logic_device->recving_len -= len; + } else { + ets_printf("remained %d\r\n", len); + } + + if (xStreamBufferSpacesAvailable(spi_logic_device->rx_buffer) >= 64) { + trigger_flag = true; + } else { + spi_logic_device->is_blocking_recv = true; + } + } + + if (trans_done & SPI_SLV_WR_STA_DONE) { + spi_slave_get_status(HSPI_HOST, &status); + spi_logic_device->recving_len = status; + uint32_t tx_size = xStreamBufferBytesAvailable(spi_logic_device->tx_buffer); + + if (spi_logic_device->recving_len > 0) { + trigger_flag = true; + } else if (tx_size > 0) { + if (spi_logic_device->is_sending == false) { + spi_slave_set_status(HSPI_HOST, &tx_size); + } + trigger_flag = true; + } + } + + if (trans_done & SPI_SLV_RD_STA_DONE) { + memset(&trans, 0x0, sizeof(trans)); + trans.cmd = &cmd; + trans.addr = NULL; + trans.bits.val = 0; + // In Slave mode, spi cmd must be longer than 3 bits and shorter than 16 bits + trans.bits.cmd = 8 * 1; + // In Slave mode, spi addr must be longer than 1 bits and shorter than 32 bits + trans.bits.addr = 8 * 1; + trans.bits.mosi = 0; + trans.miso = data; + trans.bits.miso = xStreamBufferReceiveFromISR(spi_logic_device->tx_buffer, data, 64, &xHigherPriorityTaskWoken); + if (trans.bits.miso != 0) { + spi_logic_device->sending_len -= trans.bits.miso; + trans.bits.miso <<= 3; + spi_trans(HSPI_HOST, &trans); + trigger_flag = true; + } + } + + if (trigger_flag) { + gpio_set_level(spi_logic_device->trigger_pin, spi_logic_device->trigger_level); + } + + if (spi_logic_device->event_cb) { + spi_logic_device->event_cb(event, arg); + } + + if (xHigherPriorityTaskWoken == pdTRUE) { + taskYIELD(); + } + } + break; + case SPI_DEINIT_EVENT: { + } + break; + } + +} + +uint32_t hspi_slave_logic_read_data(uint8_t*data, uint32_t len, TickType_t xTicksToWait) +{ + uint32_t ret = 0; + + ret = xStreamBufferReceive(spi_logic_device->rx_buffer, data, len, xTicksToWait); + if (spi_logic_device->is_blocking_recv) { + if (xStreamBufferBytesAvailable(spi_logic_device->rx_buffer) > 64) { + gpio_set_level(spi_logic_device->trigger_pin, spi_logic_device->trigger_level); + spi_logic_device->is_blocking_recv = false; + } + } + + return ret; +} + +uint32_t hspi_slave_logic_write_data(uint8_t*data, uint32_t len, TickType_t xTicksToWait) +{ + uint32_t ret = 0; + uint32_t avail_spaces = 0; + + if (!spi_logic_device->is_sending) { + portENTER_CRITICAL(); + avail_spaces = xStreamBufferSpacesAvailable(spi_logic_device->tx_buffer); + if (avail_spaces > len) { + avail_spaces = len; + } + ret = xStreamBufferSend(spi_logic_device->tx_buffer, data, avail_spaces, xTicksToWait); // + spi_logic_device->sending_len = xStreamBufferBytesAvailable(spi_logic_device->tx_buffer); + spi_slave_set_status(HSPI_HOST, (uint32_t*)&spi_logic_device->sending_len); + spi_logic_device->is_sending = true; + gpio_set_level(spi_logic_device->trigger_pin, spi_logic_device->trigger_level); + portEXIT_CRITICAL(); + } + + if (ret < len) { + ret += xStreamBufferSend(spi_logic_device->tx_buffer, data + ret, len - ret, xTicksToWait); + } + + return ret; +} + +esp_err_t hspi_slave_logic_device_create(gpio_num_t trigger_pin, uint32_t trigger_level,uint32_t tx_buffer_size, uint32_t rx_buffer_size) +{ + SPI_CHECK(GPIO_IS_VALID_GPIO(trigger_pin), "gpio num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(tx_buffer_size != 0, "tx buffer error", ESP_ERR_INVALID_ARG); + SPI_CHECK(rx_buffer_size != 0, "rx buffer error", ESP_ERR_INVALID_ARG); + + gpio_config_t io_conf; + + if (spi_logic_device) { + hspi_slave_logic_device_delete(); + } + spi_logic_device = (spi_logic_device_t*)malloc(sizeof(spi_logic_device_t)); + assert(spi_logic_device); + + memset(spi_logic_device, 0x0, sizeof(spi_logic_device_t)); + spi_logic_device->tx_buffer = xStreamBufferCreate(tx_buffer_size,1); + if (!spi_logic_device->tx_buffer) { + free(spi_logic_device); + spi_logic_device = NULL; + return ESP_ERR_NO_MEM; + } + + spi_logic_device->rx_buffer = xStreamBufferCreate(rx_buffer_size,1); + if (!spi_logic_device->rx_buffer) { + vStreamBufferDelete(spi_logic_device->tx_buffer); + spi_logic_device->tx_buffer = NULL; + + free(spi_logic_device); + spi_logic_device = NULL; + return ESP_ERR_NO_MEM; + } + + spi_logic_device->trigger_pin = trigger_pin; + spi_logic_device->trigger_level = (trigger_level==1)?1:0; + + memset(&io_conf, 0x0, sizeof(io_conf)); + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL << trigger_pin); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); + gpio_set_level(trigger_pin, !spi_logic_device->trigger_level); + + spi_get_event_callback(HSPI_HOST, &spi_logic_device->event_cb); + + spi_event_callback_t event_cb = hspi_slave_event_callback; + spi_set_event_callback(HSPI_HOST, &event_cb); + + return ESP_OK; +} + +esp_err_t hspi_slave_logic_device_delete(void) +{ + if (spi_logic_device == NULL) { + return ESP_ERR_INVALID_STATE; + } + + vStreamBufferDelete(spi_logic_device->tx_buffer); + spi_logic_device->tx_buffer = NULL; + + vStreamBufferDelete(spi_logic_device->rx_buffer); + spi_logic_device->rx_buffer = NULL; + + free(spi_logic_device); + spi_logic_device = NULL; + + return ESP_OK; +} diff --git a/components/esp8266/driver/hw_timer.c b/components/esp8266/driver/hw_timer.c new file mode 100644 index 000000000..e3eb26dd9 --- /dev/null +++ b/components/esp8266/driver/hw_timer.c @@ -0,0 +1,245 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include + +#include "FreeRTOS.h" + +#include "rom/ets_sys.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/timer_struct.h" + +#include "esp_heap_caps.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" + +#include "driver/hw_timer.h" + +#define ENTER_CRITICAL() portENTER_CRITICAL() +#define EXIT_CRITICAL() portEXIT_CRITICAL() + +static const char *TAG = "hw_timer"; + +#define HW_TIMER_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +#define hw_timer_intr_enable() _xt_isr_unmask(1 << ETS_FRC_TIMER1_INUM) + +#define hw_timer_intr_disable() _xt_isr_mask(1 << ETS_FRC_TIMER1_INUM) + +#define hw_timer_intr_register(a, b) _xt_isr_attach(ETS_FRC_TIMER1_INUM, (a), (b)) + + +typedef struct { + hw_timer_callback_t cb; +} hw_timer_obj_t; + +hw_timer_obj_t *hw_timer_obj = NULL; + +esp_err_t hw_timer_set_clkdiv(hw_timer_clkdiv_t clkdiv) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + HW_TIMER_CHECK(clkdiv >= TIMER_CLKDIV_1 && clkdiv <= TIMER_CLKDIV_256, "clkdiv is out of range.", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + frc1.ctrl.div = clkdiv; + EXIT_CRITICAL(); + + return ESP_OK; +} + +uint32_t hw_timer_get_clkdiv() +{ + return frc1.ctrl.div; +} + +esp_err_t hw_timer_set_intr_type(hw_timer_intr_type_t intr_type) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + HW_TIMER_CHECK(intr_type >= TIMER_EDGE_INT && intr_type <= TIMER_LEVEL_INT, "intr_type is out of range.", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + frc1.ctrl.intr_type = intr_type; + EXIT_CRITICAL(); + + return ESP_OK; +} + +uint32_t hw_timer_get_intr_type() +{ + return frc1.ctrl.intr_type; +} + +esp_err_t hw_timer_set_reload(bool reload) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + + ENTER_CRITICAL(); + if (true == reload) { + frc1.ctrl.reload = 0x01; + } else { + frc1.ctrl.reload = 0x00; + } + EXIT_CRITICAL(); + + return ESP_OK; + +} + +bool hw_timer_get_reload() +{ + if (frc1.ctrl.reload) { + return true; + } else { + return false; + } +} + +esp_err_t hw_timer_enable(bool en) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + + ENTER_CRITICAL(); + if (true == en) { + frc1.ctrl.en = 0x01; + } else { + frc1.ctrl.en = 0x00; + } + EXIT_CRITICAL(); + + return ESP_OK; +} + +bool hw_timer_get_enable() +{ + if (frc1.ctrl.en) { + return true; + } else { + return false; + } +} + +esp_err_t hw_timer_set_load_data(uint32_t load_data) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + HW_TIMER_CHECK(load_data < 0x1000000, "load_data is out of range.", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + frc1.load.data = load_data; + EXIT_CRITICAL(); + + return ESP_OK; +} + +uint32_t hw_timer_get_load_data() +{ + return frc1.load.data; +} + +uint32_t hw_timer_get_count_data() +{ + return frc1.count.data; +} + +static void IRAM_ATTR hw_timer_isr_cb(void* arg) +{ + if (!frc1.ctrl.reload) { + frc1.ctrl.en = 0; + } + if (hw_timer_obj->cb != NULL) { + hw_timer_obj->cb(arg); + } +} + +esp_err_t hw_timer_disarm(void) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + + frc1.ctrl.val = 0; + + return ESP_OK; +} + +esp_err_t hw_timer_alarm_us(uint32_t value, bool reload) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + HW_TIMER_CHECK( (reload ? ((value > 50) ? 1 : 0) : ((value > 10) ? 1 : 0)) && (value <= 0x199999), "value is out of range.", ESP_ERR_INVALID_ARG); + + hw_timer_set_reload(reload); + hw_timer_set_clkdiv(TIMER_CLKDIV_16); + hw_timer_set_intr_type(TIMER_EDGE_INT); + hw_timer_set_load_data(((TIMER_BASE_CLK >> hw_timer_get_clkdiv()) / 1000000) * value); // Calculate the number of timer clocks required for timing, ticks = (80MHz / div) * t + hw_timer_enable(true); + + return ESP_OK; +} + +static void hw_timer_obj_delete(void) +{ + if (NULL == hw_timer_obj) { + return; + } + hw_timer_obj->cb = NULL; + heap_caps_free(hw_timer_obj); + hw_timer_obj = NULL; +} + +static esp_err_t hw_timer_obj_create(void) +{ + hw_timer_obj = (hw_timer_obj_t *)heap_caps_malloc(sizeof(hw_timer_obj_t), MALLOC_CAP_8BIT); + + if (NULL == hw_timer_obj) { + hw_timer_obj_delete(); + return ESP_FAIL; + } + hw_timer_obj->cb = NULL; + + return ESP_OK; +} + +esp_err_t hw_timer_deinit(void) +{ + HW_TIMER_CHECK(hw_timer_obj, "hw_timer has not been initialized yet", ESP_FAIL); + + hw_timer_disarm(); + hw_timer_intr_disable(); + TM1_EDGE_INT_DISABLE(); + hw_timer_intr_register(NULL, NULL); + hw_timer_obj_delete(); + + return ESP_OK; +} + +esp_err_t hw_timer_init(hw_timer_callback_t callback, void *arg) +{ + HW_TIMER_CHECK(hw_timer_obj == NULL, "hw_timer has been initialized", ESP_FAIL); + HW_TIMER_CHECK(callback != NULL, "callback pointer NULL", ESP_ERR_INVALID_ARG); + + if (ESP_FAIL == hw_timer_obj_create()) { + return ESP_FAIL; + } + hw_timer_obj->cb = callback; + hw_timer_intr_register(hw_timer_isr_cb, arg); + TM1_EDGE_INT_ENABLE(); + hw_timer_intr_enable(); + + return ESP_OK; +} \ No newline at end of file diff --git a/components/esp8266/driver/i2c.c b/components/esp8266/driver/i2c.c index 41b559458..1de5eb36a 100644 --- a/components/esp8266/driver/i2c.c +++ b/components/esp8266/driver/i2c.c @@ -109,14 +109,21 @@ static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0}; static i2c_config_t *i2c_config[I2C_NUM_MAX] = {NULL}; static i2c_last_state_t *i2c_last_state[I2C_NUM_MAX] = {NULL}; -static void i2c_master_set_dc(i2c_port_t i2c_num, uint8_t sda, uint8_t scl) +static inline void i2c_master_set_dc(i2c_port_t i2c_num, uint8_t sda, uint8_t scl) { + uint32_t i = 0; + uint32_t clk_stretch_tick = i2c_config[i2c_num]->clk_stretch_tick; + gpio_set_level(i2c_config[i2c_num]->sda_io_num, sda & 0x1); + gpio_set_level(i2c_config[i2c_num]->scl_io_num, scl & 0x1); + if ((i2c_last_state[i2c_num]->scl == 0) && ((scl & 0x1) == 1)) { + // An I2C slave is allowed to hold down the clock if it needs to reduce the bus speed. The master, on the other hand, is required to read back the clock signal after releasing it to the high state and wait until the line has actually gone high. + while (gpio_get_level(i2c_config[i2c_num]->scl_io_num) == 0 && (i++) < clk_stretch_tick); // Clock stretching + } i2c_last_state[i2c_num]->val = ((sda & 0x1) << 1) | (scl & 0x1); - gpio_set_level(i2c_config[i2c_num]->sda_io_num, i2c_last_state[i2c_num]->sda); - gpio_set_level(i2c_config[i2c_num]->scl_io_num, i2c_last_state[i2c_num]->scl); + } -static uint8_t i2c_master_get_dc(i2c_port_t i2c_num) +static inline uint8_t i2c_master_get_dc(i2c_port_t i2c_num) { uint8_t sda_out; sda_out = gpio_get_level(i2c_config[i2c_num]->sda_io_num); diff --git a/components/esp8266/driver/i2s.c b/components/esp8266/driver/i2s.c new file mode 100644 index 000000000..15be3d6ae --- /dev/null +++ b/components/esp8266/driver/i2s.c @@ -0,0 +1,893 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/i2s_register.h" +#include "esp8266/i2s_struct.h" +#include "esp8266/slc_register.h" +#include "esp8266/slc_struct.h" +#include "rom/ets_sys.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_libc.h" +#include "esp_heap_caps.h" +#include "driver/i2s.h" + +static const char *I2S_TAG = "i2s"; + +#define I2S_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(I2S_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +#define dma_intr_enable() _xt_isr_unmask(1 << ETS_SLC_INUM) +#define dma_intr_disable() _xt_isr_mask(1 << ETS_SLC_INUM) +#define dma_intr_register(a, b) _xt_isr_attach(ETS_SLC_INUM, (a), (b)) + +#define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) // the maximum RAM can be allocated +#define I2S_BASE_CLK (2 * APB_CLK_FREQ) +#define I2S_ENTER_CRITICAL() portENTER_CRITICAL() +#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL() +#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) +#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) + +typedef struct lldesc { + uint32_t blocksize : 12; + uint32_t datalen : 12; + uint32_t unused : 5; + uint32_t sub_sof : 1; + uint32_t eof : 1; + volatile uint32_t owner : 1; // DMA can change this value + uint32_t *buf_ptr; + struct lldesc *next_link_ptr; +} lldesc_t; + +/** + * @brief DMA buffer object + */ +typedef struct { + char **buf; + int buf_size; + int rw_pos; + void *curr_ptr; + SemaphoreHandle_t mux; + xQueueHandle queue; + lldesc_t **desc; +} i2s_dma_t; + +/** + * @brief I2S object instance + */ +typedef struct { + i2s_port_t i2s_num; /*!< I2S port number*/ + int queue_size; /*!< I2S event queue size*/ + QueueHandle_t i2s_queue; /*!< I2S queue handler*/ + int dma_buf_count; /*!< DMA buffer count, number of buffer*/ + int dma_buf_len; /*!< DMA buffer length, length of each buffer*/ + i2s_dma_t *rx; /*!< DMA Tx buffer*/ + i2s_dma_t *tx; /*!< DMA Rx buffer*/ + int channel_num; /*!< Number of channels*/ + int bytes_per_sample; /*!< Bytes per sample*/ + int bits_per_sample; /*!< Bits per sample*/ + i2s_mode_t mode; /*!< I2S Working mode*/ + uint32_t sample_rate; /*!< I2S sample rate */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ + slc_struct_t *dma; +} i2s_obj_t; + +static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0}; +static i2s_struct_t *I2S[I2S_NUM_MAX] = {&I2S0}; + +static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); +static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma); + +static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_ENTER_CRITICAL(); + I2S[i2s_num]->conf.rx_fifo_reset = 1; + I2S[i2s_num]->conf.rx_fifo_reset = 0; + I2S[i2s_num]->conf.tx_fifo_reset = 1; + I2S[i2s_num]->conf.tx_fifo_reset = 0; + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + p_i2s_obj[i2s_num]->dma->int_clr.val = clr_mask; + return ESP_OK; +} + +esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_ENTER_CRITICAL(); + p_i2s_obj[i2s_num]->dma->int_ena.tx_suc_eof = 1; + p_i2s_obj[i2s_num]->dma->int_ena.tx_dscr_err = 1; + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_ENTER_CRITICAL(); + p_i2s_obj[i2s_num]->dma->int_ena.tx_suc_eof = 0; + p_i2s_obj[i2s_num]->dma->int_ena.tx_dscr_err = 0; + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_ENTER_CRITICAL(); + p_i2s_obj[i2s_num]->dma->int_ena.rx_eof = 0; + p_i2s_obj[i2s_num]->dma->int_ena.rx_dscr_err = 0; + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_ENTER_CRITICAL(); + p_i2s_obj[i2s_num]->dma->int_ena.rx_eof = 1; + p_i2s_obj[i2s_num]->dma->int_ena.rx_dscr_err = 1; + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +static void IRAM_ATTR i2s_intr_handler_default(void *arg) +{ + i2s_obj_t *p_i2s = (i2s_obj_t *) arg; + slc_struct_t *dma_reg = p_i2s->dma; + i2s_event_t i2s_event; + int dummy; + + portBASE_TYPE high_priority_task_awoken = 0; + + lldesc_t *finish_desc; + + if (dma_reg->int_st.tx_dscr_err || dma_reg->int_st.rx_dscr_err) { + ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", dma_reg->int_st.val); + + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_DMA_ERROR; + + if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + + xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &high_priority_task_awoken); + } + } + + if (dma_reg->int_st.rx_eof && p_i2s->tx) { + finish_desc = (lldesc_t *) dma_reg->rx_eof_des_addr; + + // All buffers are empty. This means we have an underflow on our hands. + if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { + xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); + + // See if tx descriptor needs to be auto cleared: + // This will avoid any kind of noise that may get introduced due to transmission + // of previous data from tx descriptor on I2S line. + if (p_i2s->tx_desc_auto_clear == true) { + memset((void *) dummy, 0, p_i2s->tx->buf_size); + } + } + + xQueueSendFromISR(p_i2s->tx->queue, (void *)(&finish_desc->buf_ptr), &high_priority_task_awoken); + + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_TX_DONE; + + if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + + xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &high_priority_task_awoken); + } + } + + if (dma_reg->int_st.tx_suc_eof && p_i2s->rx) { + // All buffers are full. This means we have an overflow. + finish_desc = (lldesc_t *) dma_reg->tx_eof_des_addr; + finish_desc->owner = 1; + + if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { + xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); + } + + xQueueSendFromISR(p_i2s->rx->queue, (void *)(&finish_desc->buf_ptr), &high_priority_task_awoken); + + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_RX_DONE; + + if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + + xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &high_priority_task_awoken); + } + } + + if (high_priority_task_awoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + + dma_reg->int_clr.val = dma_reg->int_st.val; +} + +static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) +{ + int bux_idx; + + if (p_i2s_obj[i2s_num] == NULL) { + ESP_LOGE(I2S_TAG, "Not initialized yet"); + return ESP_ERR_INVALID_ARG; + } + + if (dma == NULL) { + ESP_LOGE(I2S_TAG, "dma is NULL"); + return ESP_ERR_INVALID_ARG; + } + + for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { + if (dma->desc && dma->desc[bux_idx]) { + heap_caps_free(dma->desc[bux_idx]); + } + + if (dma->buf && dma->buf[bux_idx]) { + heap_caps_free(dma->buf[bux_idx]); + } + } + + if (dma->buf) { + heap_caps_free(dma->buf); + } + + if (dma->desc) { + heap_caps_free(dma->desc); + } + + vQueueDelete(dma->queue); + vSemaphoreDelete(dma->mux); + heap_caps_free(dma); + return ESP_OK; +} + +static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len) +{ + int bux_idx; + int sample_size = p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; + i2s_dma_t *dma = (i2s_dma_t *)heap_caps_zalloc(sizeof(i2s_dma_t), MALLOC_CAP_8BIT); + + if (dma == NULL) { + ESP_LOGE(I2S_TAG, "Error malloc i2s_dma_t"); + return NULL; + } + + dma->buf = (char **)heap_caps_zalloc(sizeof(char *) * dma_buf_count, MALLOC_CAP_8BIT); + + if (dma->buf == NULL) { + ESP_LOGE(I2S_TAG, "Error malloc dma buffer pointer"); + heap_caps_free(dma); + return NULL; + } + + for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + dma->buf[bux_idx] = (char *) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_8BIT); + + if (dma->buf[bux_idx] == NULL) { + ESP_LOGE(I2S_TAG, "Error malloc dma buffer"); + i2s_destroy_dma_queue(i2s_num, dma); + return NULL; + } + + ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]); + } + + dma->desc = (lldesc_t **)heap_caps_malloc(sizeof(lldesc_t *) * dma_buf_count, MALLOC_CAP_8BIT); + + if (dma->desc == NULL) { + ESP_LOGE(I2S_TAG, "Error malloc dma description"); + i2s_destroy_dma_queue(i2s_num, dma); + return NULL; + } + + for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + dma->desc[bux_idx] = (lldesc_t *) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_8BIT); + + if (dma->desc[bux_idx] == NULL) { + ESP_LOGE(I2S_TAG, "Error malloc dma description entry"); + i2s_destroy_dma_queue(i2s_num, dma); + return NULL; + } + } + + for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + // Configuring the DMA queue + dma->desc[bux_idx]->owner = 1; + dma->desc[bux_idx]->eof = 1; // Each linked list produces an EOF interrupt that notifies the task of filling the data more quickly + dma->desc[bux_idx]->sub_sof = 0; + dma->desc[bux_idx]->datalen = dma_buf_len * sample_size; // Actual number of bytes of data + dma->desc[bux_idx]->blocksize = dma_buf_len * sample_size; // Total number of bytes of data + dma->desc[bux_idx]->buf_ptr = (uint32_t *) dma->buf[bux_idx]; + dma->desc[bux_idx]->unused = 0; + dma->desc[bux_idx]->next_link_ptr = (lldesc_t *)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]); + } + + dma->queue = xQueueCreate(dma_buf_count - 1, sizeof(char *)); + dma->mux = xSemaphoreCreateMutex(); + dma->rw_pos = 0; + dma->buf_size = dma_buf_len * sample_size; + dma->curr_ptr = NULL; + ESP_LOGI(I2S_TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_buf_len * sample_size, dma_buf_count); + return dma; +} + +esp_err_t i2s_start(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + // start DMA link + I2S_ENTER_CRITICAL(); + i2s_reset_fifo(i2s_num); + // reset dma + p_i2s_obj[i2s_num]->dma->conf0.rx_rst = 1; + p_i2s_obj[i2s_num]->dma->conf0.rx_rst = 0; + p_i2s_obj[i2s_num]->dma->conf0.tx_rst = 1; + p_i2s_obj[i2s_num]->dma->conf0.tx_rst = 0; + + I2S[i2s_num]->conf.tx_reset = 1; + I2S[i2s_num]->conf.tx_reset = 0; + I2S[i2s_num]->conf.rx_reset = 1; + I2S[i2s_num]->conf.rx_reset = 0; + + dma_intr_disable(); + + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + i2s_enable_tx_intr(i2s_num); + p_i2s_obj[i2s_num]->dma->rx_link.start = 1; + } + + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + i2s_enable_rx_intr(i2s_num); + p_i2s_obj[i2s_num]->dma->tx_link.start = 1; + } + + // Both TX and RX are started to ensure clock generation + I2S[i2s_num]->conf.val |= I2S_I2S_TX_START | I2S_I2S_RX_START; + // Simultaneously reset to ensure the same phase. + I2S[i2s_num]->conf.val |= I2S_I2S_RESET_MASK; + I2S[i2s_num]->conf.val &= ~I2S_I2S_RESET_MASK; + dma_intr_enable(); + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_stop(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_ENTER_CRITICAL(); + dma_intr_disable(); + + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + p_i2s_obj[i2s_num]->dma->rx_link.stop = 1; + i2s_disable_tx_intr(i2s_num); + } + + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + p_i2s_obj[i2s_num]->dma->tx_link.stop = 1; + i2s_disable_rx_intr(i2s_num); + } + + I2S[i2s_num]->conf.val &= ~(I2S_I2S_TX_START | I2S_I2S_RX_START); + p_i2s_obj[i2s_num]->dma->int_clr.val = p_i2s_obj[i2s_num]->dma->int_st.val; // clear pending interrupt + I2S_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(pin, "param null", ESP_ERR_INVALID_ARG); + + if (pin->bck_o_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK); + } + + if (pin->ws_o_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); + } + + if (pin->data_out_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA); + } + + if (pin->bck_i_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_I2SI_BCK); + } + + if (pin->ws_i_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_I2SI_WS); + } + + if (pin->data_in_en == true) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_I2SI_DATA); + } + + return ESP_OK; +} + +static esp_err_t i2s_set_rate(i2s_port_t i2s_num, uint32_t rate) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + uint8_t bck_div = 1; + uint8_t mclk_div = 1; + + // Calculate the frequency division corresponding to the bit rate + uint32_t scaled_base_freq = I2S_BASE_CLK / 32; + float delta_best = scaled_base_freq; + + for (uint8_t i = 1; i < 64; i++) { + for (uint8_t j = i; j < 64; j++) { + float new_delta = abs(((float)scaled_base_freq / i / j) - rate); + + if (new_delta < delta_best) { + delta_best = new_delta; + bck_div = i; + mclk_div = j; + } + } + } + + // Configure the frequency division of I2S + I2S_ENTER_CRITICAL(); + I2S[i2s_num]->conf.bck_div_num = bck_div & 0x3F; + I2S[i2s_num]->conf.clkm_div_num = mclk_div & 0x3F; + I2S_EXIT_CRITICAL(); + p_i2s_obj[i2s_num]->sample_rate = rate; + return ESP_OK; +} + +esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + + i2s_dma_t *save_tx = NULL, *save_rx = NULL; + + if (bits % 8 != 0 || bits > I2S_BITS_PER_SAMPLE_24BIT || bits < I2S_BITS_PER_SAMPLE_16BIT) { + ESP_LOGE(I2S_TAG, "Invalid bits per sample"); + return ESP_ERR_INVALID_ARG; + } + + // wait all on-going writing finish + if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { + xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + } + + if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { + xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + } + + i2s_stop(i2s_num); + + i2s_set_rate(i2s_num, rate); + + uint32_t cur_mode = 0; + + if (p_i2s_obj[i2s_num]->channel_num != ch) { + p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; + cur_mode = I2S[i2s_num]->fifo_conf.tx_fifo_mod; + I2S[i2s_num]->fifo_conf.tx_fifo_mod = (ch == 2) ? cur_mode - 1 : cur_mode + 1; + cur_mode = I2S[i2s_num]->fifo_conf.rx_fifo_mod; + I2S[i2s_num]->fifo_conf.rx_fifo_mod = (ch == 2) ? cur_mode - 1 : cur_mode + 1; + I2S[i2s_num]->conf_chan.tx_chan_mod = (ch == 2) ? 0 : 1; + I2S[i2s_num]->conf_chan.rx_chan_mod = (ch == 2) ? 0 : 1; + } + + if (bits != p_i2s_obj[i2s_num]->bits_per_sample) { + //change fifo mode + if (p_i2s_obj[i2s_num]->bits_per_sample <= 16 && bits > 16) { + I2S[i2s_num]->fifo_conf.tx_fifo_mod += 2; + I2S[i2s_num]->fifo_conf.rx_fifo_mod += 2; + } else if (p_i2s_obj[i2s_num]->bits_per_sample > 16 && bits <= 16) { + I2S[i2s_num]->fifo_conf.tx_fifo_mod -= 2; + I2S[i2s_num]->fifo_conf.rx_fifo_mod -= 2; + } + + p_i2s_obj[i2s_num]->bits_per_sample = bits; + p_i2s_obj[i2s_num]->bytes_per_sample = p_i2s_obj[i2s_num]->bits_per_sample / 8; + + // Round bytes_per_sample up to next multiple of 16 bits + int halfwords_per_sample = (p_i2s_obj[i2s_num]->bits_per_sample + 15) / 16; + p_i2s_obj[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; + + // Because limited of DMA buffer is 4092 bytes + if (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num > 4092) { + p_i2s_obj[i2s_num]->dma_buf_len = 4092 / p_i2s_obj[i2s_num]->bytes_per_sample / p_i2s_obj[i2s_num]->channel_num; + } + + // Re-create TX DMA buffer + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + + save_tx = p_i2s_obj[i2s_num]->tx; + + p_i2s_obj[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); + + if (p_i2s_obj[i2s_num]->tx == NULL) { + ESP_LOGE(I2S_TAG, "Failed to create tx dma buffer"); + i2s_driver_uninstall(i2s_num); + return ESP_ERR_NO_MEM; + } + + p_i2s_obj[i2s_num]->dma->rx_link.addr = (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0]; + + // destroy old tx dma if exist + if (save_tx) { + i2s_destroy_dma_queue(i2s_num, save_tx); + } + } + + // Re-create RX DMA buffer + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + + save_rx = p_i2s_obj[i2s_num]->rx; + + p_i2s_obj[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); + + if (p_i2s_obj[i2s_num]->rx == NULL) { + ESP_LOGE(I2S_TAG, "Failed to create rx dma buffer"); + i2s_driver_uninstall(i2s_num); + return ESP_ERR_NO_MEM; + } + + I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample) / 4; + p_i2s_obj[i2s_num]->dma->tx_link.addr = (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0]; + + // destroy old rx dma if exist + if (save_rx) { + i2s_destroy_dma_queue(i2s_num, save_rx); + } + } + + } + + I2S[i2s_num]->conf.bits_mod = bits; + + // wait all writing on-going finish + if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { + xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); + } + + if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { + xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); + } + + i2s_start(i2s_num); + return ESP_OK; +} + +esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_ERR_INVALID_ARG); + return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); +} + +static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG); + + // configure I2S data port interface. + i2s_reset_fifo(i2s_num); + //reset i2s + I2S[i2s_num]->conf.tx_reset = 1; + I2S[i2s_num]->conf.tx_reset = 0; + I2S[i2s_num]->conf.rx_reset = 1; + I2S[i2s_num]->conf.rx_reset = 0; + + // disable all i2s interrupt + I2S[i2s_num]->int_ena.val = 0; + + //reset dma + p_i2s_obj[i2s_num]->dma->conf0.rx_rst = 1; + p_i2s_obj[i2s_num]->dma->conf0.rx_rst = 0; + p_i2s_obj[i2s_num]->dma->conf0.tx_rst = 1; + p_i2s_obj[i2s_num]->dma->conf0.tx_rst = 0; + + //Enable and configure DMA + p_i2s_obj[i2s_num]->dma->conf0.txdata_burst_en = 0; + p_i2s_obj[i2s_num]->dma->conf0.txdscr_burst_en = 1; + p_i2s_obj[i2s_num]->dma->rx_dscr_conf.rx_fill_mode = 0; + p_i2s_obj[i2s_num]->dma->rx_dscr_conf.rx_eof_mode = 0; + p_i2s_obj[i2s_num]->dma->rx_dscr_conf.rx_fill_en = 0; + p_i2s_obj[i2s_num]->dma->rx_dscr_conf.token_no_replace = 1; + p_i2s_obj[i2s_num]->dma->rx_dscr_conf.infor_no_replace = 1; + + + I2S[i2s_num]->fifo_conf.dscr_en = 0; + + I2S[i2s_num]->conf_chan.tx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left + I2S[i2s_num]->fifo_conf.tx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel + + I2S[i2s_num]->conf_chan.rx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left + I2S[i2s_num]->fifo_conf.rx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel + + I2S[i2s_num]->fifo_conf.dscr_en = 1;// connect dma to fifo + + I2S[i2s_num]->conf.tx_start = 0; + I2S[i2s_num]->conf.rx_start = 0; + + I2S[i2s_num]->conf.msb_right = 1; + I2S[i2s_num]->conf.right_first = 1; + + if (i2s_config->mode & I2S_MODE_TX) { + I2S[i2s_num]->conf.tx_slave_mod = 0; // Master + + if (i2s_config->mode & I2S_MODE_SLAVE) { + I2S[i2s_num]->conf.tx_slave_mod = 1;// TX Slave + } + } + + if (i2s_config->mode & I2S_MODE_RX) { + I2S[i2s_num]->conf.rx_slave_mod = 0; // Master + + if (i2s_config->mode & I2S_MODE_SLAVE) { + I2S[i2s_num]->conf.rx_slave_mod = 1;// RX Slave + } + } + + if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) { + I2S[i2s_num]->conf.tx_msb_shift = 1; + I2S[i2s_num]->conf.rx_msb_shift = 1; + + if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) { + if (i2s_config->mode & I2S_MODE_TX) { + I2S[i2s_num]->conf.tx_msb_shift = 0; + } + + if (i2s_config->mode & I2S_MODE_RX) { + I2S[i2s_num]->conf.rx_msb_shift = 0; + } + } + } + + if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) { + if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { + I2S[i2s_num]->conf.tx_slave_mod = 0; // TX Master + I2S[i2s_num]->conf.rx_slave_mod = 0; // RX Master + } else { + I2S[i2s_num]->conf.tx_slave_mod = 1; // TX Slave + I2S[i2s_num]->conf.rx_slave_mod = 1; // RX Slave + } + } + + p_i2s_obj[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; + return ESP_OK; +} + +esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "i2s not installed yet", ESP_FAIL); + + if (p_i2s_obj[i2s_num]->rx && p_i2s_obj[i2s_num]->rx->buf != NULL && p_i2s_obj[i2s_num]->rx->buf_size != 0) { + for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { + memset(p_i2s_obj[i2s_num]->rx->buf[i], 0, p_i2s_obj[i2s_num]->rx->buf_size); + } + } + + if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { + int bytes_left = 0; + bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; + + if (bytes_left) { + size_t zero_bytes = 0, bytes_written; + i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); + } + + for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { + memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); + } + } + + return ESP_OK; +} + +esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait) +{ + char *data_ptr, *src_byte; + int bytes_can_write; + *bytes_written = 0; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); + xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + + src_byte = (char *)src; + + while (size > 0) { + if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { + if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + break; + } + + p_i2s_obj[i2s_num]->tx->rw_pos = 0; + } + + ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr); + data_ptr = (char *)p_i2s_obj[i2s_num]->tx->curr_ptr; + data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; + bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos; + + if (bytes_can_write > size) { + bytes_can_write = size; + } + + memcpy(data_ptr, src_byte, bytes_can_write); + size -= bytes_can_write; + src_byte += bytes_can_write; + p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; + (*bytes_written) += bytes_can_write; + } + + xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); + return ESP_OK; +} + +esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) +{ + char *data_ptr, *dest_byte; + int bytes_can_read; + *bytes_read = 0; + dest_byte = (char *)dest; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG); + xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + + while (size > 0) { + if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { + if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { + break; + } + + p_i2s_obj[i2s_num]->rx->rw_pos = 0; + } + + data_ptr = (char *)p_i2s_obj[i2s_num]->rx->curr_ptr; + data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos; + bytes_can_read = p_i2s_obj[i2s_num]->rx->buf_size - p_i2s_obj[i2s_num]->rx->rw_pos; + + if (bytes_can_read > size) { + bytes_can_read = size; + } + + memcpy(dest_byte, data_ptr, bytes_can_read); + size -= bytes_can_read; + dest_byte += bytes_can_read; + p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read; + (*bytes_read) += bytes_can_read; + } + + xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); + return ESP_OK; +} + +esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) +{ + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK(p_i2s_obj[i2s_num], "already uninstalled", ESP_FAIL); + + i2s_stop(i2s_num); + dma_intr_register(NULL, NULL); + + if (p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->tx); + p_i2s_obj[i2s_num]->tx = NULL; + } + + if (p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->rx); + p_i2s_obj[i2s_num]->rx = NULL; + } + + if (p_i2s_obj[i2s_num]->i2s_queue) { + vQueueDelete(p_i2s_obj[i2s_num]->i2s_queue); + p_i2s_obj[i2s_num]->i2s_queue = NULL; + } + + heap_caps_free(p_i2s_obj[i2s_num]); + p_i2s_obj[i2s_num] = NULL; + + return ESP_OK; +} + +esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue) +{ + esp_err_t err; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_ERR_INVALID_ARG); + I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG); + I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG); + + if (p_i2s_obj[i2s_num] == NULL) { + p_i2s_obj[i2s_num] = (i2s_obj_t *)heap_caps_zalloc(sizeof(i2s_obj_t), MALLOC_CAP_8BIT); + I2S_CHECK(p_i2s_obj[i2s_num], "Malloc I2S driver error", ESP_ERR_NO_MEM); + + p_i2s_obj[i2s_num]->i2s_num = i2s_num; + p_i2s_obj[i2s_num]->dma = (slc_struct_t *)&SLC0; + p_i2s_obj[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; + p_i2s_obj[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; + p_i2s_obj[i2s_num]->i2s_queue = i2s_queue; + p_i2s_obj[i2s_num]->mode = i2s_config->mode; + + p_i2s_obj[i2s_num]->bits_per_sample = 0; + p_i2s_obj[i2s_num]->bytes_per_sample = 0; // Not initialized yet + p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1; + + //initial interrupt + dma_intr_register(i2s_intr_handler_default, p_i2s_obj[i2s_num]); + i2s_stop(i2s_num); + err = i2s_param_config(i2s_num, i2s_config); + + if (err != ESP_OK) { + i2s_driver_uninstall(i2s_num); + ESP_LOGE(I2S_TAG, "I2S param configure error"); + return err; + } + + if (i2s_queue) { + p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); + *((QueueHandle_t *) i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue; + ESP_LOGI(I2S_TAG, "queue heap_caps_free spaces: %d", (int)uxQueueSpacesAvailable(p_i2s_obj[i2s_num]->i2s_queue)); + } else { + p_i2s_obj[i2s_num]->i2s_queue = NULL; + } + + // set clock and start + return i2s_set_clk(i2s_num, i2s_config->sample_rate, i2s_config->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); + } + + ESP_LOGW(I2S_TAG, "I2S driver already installed"); + return ESP_OK; +} \ No newline at end of file diff --git a/components/esp8266/driver/ir_rx.c b/components/esp8266/driver/ir_rx.c new file mode 100644 index 000000000..a606b9904 --- /dev/null +++ b/components/esp8266/driver/ir_rx.c @@ -0,0 +1,271 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "driver/ir_rx.h" + +static const char *TAG = "ir rx"; + +#define IR_RX_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +typedef struct { + uint32_t io_num; + uint32_t buf_len; + SemaphoreHandle_t recv_mux; + RingbufHandle_t ring_buf; /*!< rx ring buffer handler*/ +} ir_rx_obj_t; + +ir_rx_obj_t *ir_rx_obj = NULL; + +typedef enum { + IR_RX_IDLE, + IR_RX_HEADER, + IR_RX_DATA, + IR_RX_REP, +} ir_rx_state_t; + +/** + * @brief ir rx state machine via gpio intr + */ +static void IRAM_ATTR ir_rx_intr_handler(void *arg) +{ + static int ir_state = IR_RX_IDLE; + static int ir_repeat = 0; + static ir_rx_nec_data_t ir_data = {0}; + static int cnt = 0; + static uint8_t rep_flg = 0; + static uint32_t time_last = 0; + + BaseType_t xHigherPriorityTaskWoken; + uint32_t time_escape, time_current; + struct timeval now; + + gettimeofday(&now, NULL); + time_current = now.tv_sec * 1000 * 1000 + now.tv_usec; + time_escape = time_current - time_last; + time_last = time_current; + + switch (ir_state) { + case IR_RX_IDLE: { + if (time_escape < IR_RX_NEC_HEADER_US + IR_RX_ERROR_US && time_escape > IR_RX_NEC_HEADER_US - IR_RX_ERROR_US) { + ir_state = IR_RX_DATA; + } + } + break; + + case IR_RX_DATA: { + if (time_escape < IR_RX_NEC_DATA1_US + IR_RX_ERROR_US && time_escape > IR_RX_NEC_DATA1_US - IR_RX_ERROR_US) { + ir_data.val = (ir_data.val >> 1) | (0x1 << (IR_RX_NEC_BIT_NUM * 4 - 1)); + cnt++; + } else if (time_escape < IR_RX_NEC_DATA0_US + IR_RX_ERROR_US && time_escape > IR_RX_NEC_DATA0_US - IR_RX_ERROR_US) { + ir_data.val = (ir_data.val >> 1) | (0x0 << (IR_RX_NEC_BIT_NUM * 4 - 1)); + cnt++; + } else { + goto reset_status; + } + + if (cnt == IR_RX_NEC_BIT_NUM * 4) { + // push rcv data to ringbuf + xRingbufferSendFromISR(ir_rx_obj->ring_buf, (void *) &ir_data, sizeof(ir_rx_nec_data_t) * 1, &xHigherPriorityTaskWoken); + ir_state = IR_RX_REP; + rep_flg = 0; + } + } + break; + + case IR_RX_REP: { + if (rep_flg == 0) { + if (time_escape > IR_RX_NEC_TM1_REP_US && time_escape < IR_RX_NEC_TM1_REP_US * 8) { + rep_flg = 1; + } else { + goto reset_status; + } + } else if (rep_flg == 1) { + if (time_escape < IR_RX_NEC_TM1_REP_US + IR_RX_ERROR_US && IR_RX_NEC_TM2_REP_US - IR_RX_ERROR_US) { + // push rcv data to ringbuf + xRingbufferSendFromISR(ir_rx_obj->ring_buf, (void *) &ir_data, sizeof(ir_rx_nec_data_t) * 1, &xHigherPriorityTaskWoken); + ir_repeat++; + rep_flg = 0; + } else { + goto reset_status; + } + } + } + break; + } + + if (xHigherPriorityTaskWoken == pdTRUE) { + taskYIELD(); + } + + return; + +reset_status: + ir_state = IR_RX_IDLE; + cnt = 0; + ir_data.val = 0; + ir_repeat = 0; + rep_flg = 0; +} + +esp_err_t ir_rx_disable() +{ + IR_RX_CHECK(ir_rx_obj, "ir rx not been initialized yet", ESP_FAIL); + gpio_isr_handler_remove(ir_rx_obj->io_num); + + return ESP_OK; +} + +esp_err_t ir_rx_enable() +{ + IR_RX_CHECK(ir_rx_obj, "ir rx not been initialized yet", ESP_FAIL); + gpio_isr_handler_add(ir_rx_obj->io_num, ir_rx_intr_handler, (void *) ir_rx_obj->io_num); + + return ESP_OK; +} + +int ir_rx_recv_data(ir_rx_nec_data_t *data, size_t len, uint32_t timeout_ticks) +{ + IR_RX_CHECK(ir_rx_obj, "ir rx not been initialized yet", ESP_FAIL); + int ret; + ir_rx_nec_data_t *buf = NULL; + size_t size = 0; + uint32_t ticks_escape = 0, ticks_last = 0; + struct timeval now; + + if (timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_last = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS; + } + + ret = xSemaphoreTake(ir_rx_obj->recv_mux, timeout_ticks); + + if (ret != pdTRUE) { + IR_RX_CHECK(false, "SemaphoreTake error", -1); + } + + if (timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_escape = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS - ticks_last; + + if (timeout_ticks <= ticks_escape) { + xSemaphoreGive(ir_rx_obj->recv_mux); + IR_RX_CHECK(false, "timeout", -1); + } else { + timeout_ticks -= ticks_escape; + } + } + + for (int x = 0; x < len;) { + buf = (ir_rx_nec_data_t *) xRingbufferReceive(ir_rx_obj->ring_buf, &size, timeout_ticks); + + if (buf == NULL) { + xSemaphoreGive(ir_rx_obj->recv_mux); + IR_RX_CHECK(false, "RingbufferReceive error", -1); + } + + memcpy(&data[x], buf, size); + vRingbufferReturnItem(ir_rx_obj->ring_buf, buf); + x += size; + + if (timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_escape = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS - ticks_last; + + if (timeout_ticks <= ticks_escape) { + xSemaphoreGive(ir_rx_obj->recv_mux); + IR_RX_CHECK(false, "timeout, return the actual accepted length", x); + } else { + timeout_ticks -= ticks_escape; + } + } + } + + xSemaphoreGive(ir_rx_obj->recv_mux); + + return len; +} + +static esp_err_t ir_rx_gpio_init(uint32_t io_num) +{ + gpio_config_t io_conf; + io_conf.intr_type = GPIO_INTR_NEGEDGE; + io_conf.pin_bit_mask = 1ULL << io_num; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + gpio_config(&io_conf); + gpio_install_isr_service(0); + + return ESP_OK; +} + +esp_err_t ir_rx_deinit() +{ + IR_RX_CHECK(ir_rx_obj, "ir rx has not been initialized yet.", ESP_FAIL); + + ir_rx_disable(); + + if (ir_rx_obj->ring_buf) { + vRingbufferDelete(ir_rx_obj->ring_buf); + ir_rx_obj->ring_buf = NULL; + } + + if (ir_rx_obj->recv_mux) { + vSemaphoreDelete(ir_rx_obj->recv_mux); + ir_rx_obj->recv_mux = NULL; + } + + heap_caps_free(ir_rx_obj); + ir_rx_obj = NULL; + return ESP_OK; +} + +esp_err_t ir_rx_init(ir_rx_config_t *config) +{ + IR_RX_CHECK(config, "config error", ESP_ERR_INVALID_ARG); + IR_RX_CHECK(NULL == ir_rx_obj, "ir rx has been initialized", ESP_FAIL); + + ir_rx_obj = heap_caps_malloc(sizeof(ir_rx_obj_t), MALLOC_CAP_8BIT); + IR_RX_CHECK(ir_rx_obj, "ir rx object malloc error", ESP_ERR_NO_MEM); + ir_rx_obj->io_num = config->io_num; + ir_rx_obj->buf_len = config->buf_len; + ir_rx_obj->ring_buf = xRingbufferCreate(sizeof(ir_rx_nec_data_t) * ir_rx_obj->buf_len, RINGBUF_TYPE_NOSPLIT); + ir_rx_obj->recv_mux = xSemaphoreCreateMutex(); + + if (NULL == ir_rx_obj->ring_buf || NULL == ir_rx_obj->recv_mux) { + ir_rx_deinit(); + IR_RX_CHECK(false, "Ringbuffer or Mutex create fail", ESP_ERR_NO_MEM); + } + + // gpio configure for IR rx pin + ir_rx_gpio_init(ir_rx_obj->io_num); + ir_rx_enable(); + + return ESP_OK; +} + diff --git a/components/esp8266/driver/ir_tx.c b/components/esp8266/driver/ir_tx.c new file mode 100644 index 000000000..b39fca9e5 --- /dev/null +++ b/components/esp8266/driver/ir_tx.c @@ -0,0 +1,446 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "driver/ir_tx.h" +#include "driver/hw_timer.h" +#include "driver/i2s.h" +#include "esp8266/gpio_struct.h" + +static const char *TAG = "ir tx"; + +int wDev_MacTimSetFunc(void (*handle)(void)); + +#define IR_TX_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +typedef enum { + TX_BIT_CARRIER, + TX_BIT_LOW, +} ir_tx_bit_state_t; + +typedef enum { + IR_TX_IDLE, + IR_TX_HEADER, + IR_TX_DATA, + IR_TX_REP, +} ir_tx_state_t; + +/** + * @brief IR TX transmission parameter structure type definition + */ +typedef struct { + ir_tx_nec_data_t data; + uint8_t repeat; +} ir_tx_trans_t; + +typedef struct { + uint32_t io_num; + uint32_t freq; + SemaphoreHandle_t done_sem; + SemaphoreHandle_t send_mux; + ir_tx_trans_t trans; + ir_tx_timer_t timer; +} ir_tx_obj_t; + +ir_tx_obj_t *ir_tx_obj = NULL; + +static ir_tx_state_t ir_tx_state = IR_TX_IDLE; + +static void inline ir_tx_clear_carrier() +{ + switch (ir_tx_obj->io_num) { + case 2: { + GPIO.out_w1tc |= 0x4; // GPIO 2 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); + } + break; + + case 14: { + GPIO.out_w1tc |= 0x4000; // GPIO 14 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); + } + break; + } +} + +static void inline ir_tx_gen_carrier() +{ + switch (ir_tx_obj->io_num) { + case 2: { + GPIO.out_w1ts |= 0x4; // GPIO 2 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); + } + break; + + case 14: { + GPIO.out_w1ts |= 0x4000; // GPIO 14 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_I2SI_WS); + } + break; + } +} + +static void inline ir_tx_timer_alarm(uint32_t val) +{ + if (ir_tx_obj->timer == IR_TX_WDEV_TIMER) { + REG_WRITE(WDEVTSFSW0_LO, 0); + REG_WRITE(WDEVTSFSW0_HI, 0); + REG_WRITE(WDEVTSFSW0_LO, 0); + REG_WRITE(WDEVTSF0_TIMER_LO, 0); + REG_WRITE(WDEVTSF0_TIMER_HI, 0); + REG_WRITE(WDEVTSF0_TIMER_LO, val - IR_TX_WDEV_TIMER_ERROR_US); + REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); + } else { + hw_timer_alarm_us(val - IR_TX_HW_TIMER_ERROR_US, false); + } +} + +void IRAM_ATTR ir_tx_handler() +{ + uint32_t t_expire = 0; + static uint32_t rep_expire_us = IR_TX_NEC_REP_CYCLE; //for nec 32bit mode + static uint16_t data_tmp = 0; + static uint8_t ir_tx_bit_num = 0; + static uint8_t ir_bit_state = TX_BIT_CARRIER; + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (ir_tx_obj->timer == IR_TX_WDEV_TIMER) { + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); + } + switch (ir_tx_state) { + case IR_TX_IDLE: { + ir_tx_gen_carrier(); + ir_tx_timer_alarm(IR_TX_NEC_HEADER_HIGH_US); + ir_tx_state = IR_TX_HEADER; + break; + } + + case IR_TX_HEADER: { + ir_tx_clear_carrier(); + ir_tx_timer_alarm(IR_TX_NEC_HEADER_LOW_US); + ir_tx_state = IR_TX_DATA; + ir_bit_state = TX_BIT_CARRIER; + data_tmp = ir_tx_obj->trans.data.addr1; + rep_expire_us -= (IR_TX_NEC_HEADER_HIGH_US + IR_TX_NEC_HEADER_LOW_US); + break; + } + + case IR_TX_DATA: { + if (ir_bit_state == TX_BIT_CARRIER) { + t_expire = IR_TX_NEC_DATA_HIGH_US; + ir_bit_state = TX_BIT_LOW; + ir_tx_gen_carrier(); + } else if (ir_bit_state == TX_BIT_LOW) { + ir_tx_clear_carrier(); + + if ((data_tmp >> (ir_tx_bit_num % IR_TX_NEC_BIT_NUM)) & 0x1) { + t_expire = IR_TX_NEC_DATA_LOW_1_US; + } else { + t_expire = IR_TX_NEC_DATA_LOW_0_US; + } + + ir_tx_bit_num++; + + if (ir_tx_bit_num == IR_TX_NEC_BIT_NUM) { + data_tmp = ir_tx_obj->trans.data.addr2; + } else if (ir_tx_bit_num == IR_TX_NEC_BIT_NUM * 2) { + data_tmp = ir_tx_obj->trans.data.cmd1; + } else if (ir_tx_bit_num == IR_TX_NEC_BIT_NUM * 3) { + data_tmp = ir_tx_obj->trans.data.cmd2; + } else if ((ir_tx_bit_num == (IR_TX_NEC_BIT_NUM * 4 + 1))) { + //clean up state for next or for repeat + ir_tx_bit_num = 0; + ir_bit_state = TX_BIT_CARRIER; + + if (ir_tx_obj->trans.repeat > 0) { + t_expire = (rep_expire_us - 5); + ir_tx_timer_alarm(t_expire); + rep_expire_us = IR_TX_NEC_REP_CYCLE; + ir_tx_state = IR_TX_REP; + } else { + rep_expire_us = IR_TX_NEC_REP_CYCLE; + ir_tx_state = IR_TX_IDLE; + xSemaphoreGiveFromISR(ir_tx_obj->done_sem, &xHigherPriorityTaskWoken); + } + + break; + + } + + ir_bit_state = TX_BIT_CARRIER; + } else { + } + + rep_expire_us -= t_expire; + ir_tx_timer_alarm(t_expire); + break; + } + + case IR_TX_REP: { + if (ir_tx_obj->trans.repeat > 0) { + if (ir_tx_bit_num == 0) { + ir_tx_gen_carrier(); + t_expire = IR_TX_NEC_REP_HIGH_US ; + } else if (ir_tx_bit_num == 1) { + ir_tx_clear_carrier(); + t_expire = IR_TX_NEC_REP_LOW_US ; + } else if (ir_tx_bit_num == 2) { + ir_tx_gen_carrier(); + t_expire = IR_TX_NEC_REP_STOP_US; + } else if (ir_tx_bit_num == 3) { + ir_tx_clear_carrier(); + ir_tx_obj->trans.repeat--; + + if (ir_tx_obj->trans.repeat > 0) { + t_expire = rep_expire_us ; + rep_expire_us = IR_TX_NEC_REP_CYCLE; + } else { + ir_tx_bit_num = 0; + rep_expire_us = IR_TX_NEC_REP_CYCLE; + ir_tx_state = IR_TX_IDLE; + ir_bit_state = TX_BIT_CARRIER; + xSemaphoreGiveFromISR(ir_tx_obj->done_sem, &xHigherPriorityTaskWoken); + break; + } + } else { + } + + ir_tx_bit_num++;//bit num reuse for repeat wave form + + if (ir_tx_bit_num == 4) { + ir_tx_bit_num = 0; + rep_expire_us = IR_TX_NEC_REP_CYCLE; + } else { + rep_expire_us -= t_expire; + } + + ir_tx_timer_alarm(t_expire); + } + + break; + } + + default: + break; + } + + if (xHigherPriorityTaskWoken == pdTRUE) { + taskYIELD(); + } +} + +static esp_err_t ir_tx_trans(ir_tx_nec_data_t data, uint8_t repeat, uint32_t *timeout_ticks) +{ + int ret; + uint32_t ticks_escape = 0, ticks_last = 0; + struct timeval now; + + if (*timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_last = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS; + } + + if (ir_tx_state != IR_TX_IDLE) { + IR_TX_CHECK(false, "When transmission begins, the state must be idle", ESP_FAIL); + } + + ir_tx_obj->trans.data = data; + ir_tx_obj->trans.repeat = repeat; + xSemaphoreTake(ir_tx_obj->done_sem, 0); // Clear possible semaphore + ir_tx_handler(); + + if (ir_tx_state != IR_TX_IDLE) { + ret = xSemaphoreTake(ir_tx_obj->done_sem, *timeout_ticks); + + if (ret != pdTRUE) { + IR_TX_CHECK(false, "Waiting for done_sem error", ESP_ERR_TIMEOUT); + } + } + + if (*timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_escape = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS - ticks_last; + + if (*timeout_ticks <= ticks_escape) { + IR_TX_CHECK(false, "timeout", ESP_ERR_TIMEOUT); + } else { + *timeout_ticks -= ticks_escape; + } + } + + return ESP_OK; +} + +int ir_tx_send_data(ir_tx_nec_data_t *data, size_t len, uint32_t timeout_ticks) +{ + IR_TX_CHECK(ir_tx_obj, "ir tx has not been initialized yet.", ESP_FAIL); + int ret; + int x, y; + uint32_t ticks_escape = 0, ticks_last = 0; + struct timeval now; + + if (timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_last = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS; + } + + ret = xSemaphoreTake(ir_tx_obj->send_mux, timeout_ticks); + + if (ret != pdTRUE) { + IR_TX_CHECK(false, "SemaphoreTake error", -1); + } + + if (timeout_ticks != portMAX_DELAY) { + gettimeofday(&now, NULL); + ticks_escape = (now.tv_sec * 1000 + now.tv_usec / 1000) / portTICK_RATE_MS - ticks_last; + + if (timeout_ticks <= ticks_escape) { + xSemaphoreGive(ir_tx_obj->send_mux); + IR_TX_CHECK(false, "timeout", -1); + } else { + timeout_ticks -= ticks_escape; + } + } + + for (x = 0; x < len;) { + for (y = 1; y < len - x; y++) { + if (data[y + x].val != data[x].val) { // search repeat + break; + } + } + + ret = ir_tx_trans(data[x], y - 1, &timeout_ticks); + + if (ret != ESP_OK) { + if (ret == ESP_ERR_TIMEOUT) { + x += y; + } + + xSemaphoreGive(ir_tx_obj->send_mux); + IR_TX_CHECK(false, "trans data error", x); + } + + x += y; + } + + xSemaphoreGive(ir_tx_obj->send_mux); + + return len; +} + +esp_err_t ir_tx_deinit() +{ + IR_TX_CHECK(ir_tx_obj, "ir tx has not been initialized yet.", ESP_FAIL); + + if (ir_tx_obj->done_sem) { + vSemaphoreDelete(ir_tx_obj->done_sem); + ir_tx_obj->done_sem = NULL; + } + + if (ir_tx_obj->send_mux) { + vSemaphoreDelete(ir_tx_obj->send_mux); + ir_tx_obj->send_mux = NULL; + } + + if (ir_tx_obj->timer == IR_TX_WDEV_TIMER) { + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); + wDev_MacTimSetFunc(NULL); + } else { + hw_timer_deinit(); + } + + i2s_driver_uninstall(I2S_NUM_0); + + heap_caps_free(ir_tx_obj); + ir_tx_obj = NULL; + return ESP_OK; +} + +esp_err_t ir_tx_init(ir_tx_config_t *config) +{ + IR_TX_CHECK(config, "config error", ESP_ERR_INVALID_ARG); + IR_TX_CHECK((config->io_num == 2) || (config->io_num == 14), "Only supports io2 and io14 as carrier outputs", ESP_ERR_INVALID_ARG); + IR_TX_CHECK(NULL == ir_tx_obj, "ir tx has been initialized", ESP_FAIL); + + ir_tx_obj = heap_caps_malloc(sizeof(ir_tx_obj_t), MALLOC_CAP_8BIT); + IR_TX_CHECK(ir_tx_obj, "ir tx object malloc error", ESP_ERR_NO_MEM); + ir_tx_obj->io_num = config->io_num; + ir_tx_obj->freq = config->freq; + ir_tx_obj->timer = config->timer; + ir_tx_obj->done_sem = xSemaphoreCreateBinary(); + ir_tx_obj->send_mux = xSemaphoreCreateMutex(); + + if (NULL == ir_tx_obj->done_sem || NULL == ir_tx_obj->send_mux) { + ir_tx_deinit(); + IR_TX_CHECK(false, "Semaphore create fail", ESP_ERR_NO_MEM); + } + + // init default data + ir_tx_obj->trans.data.addr1 = (uint8_t)0xee; //addr code + ir_tx_obj->trans.data.addr2 = (uint8_t)~0xee; + ir_tx_obj->trans.data.cmd1 = (uint8_t)0x5a; //cmd code + ir_tx_obj->trans.data.cmd2 = (uint8_t)~0x5a; + ir_tx_obj->trans.repeat = 5; //repeat number + + gpio_config_t io_conf; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = 1 << ir_tx_obj->io_num; + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER, // Only carrier mode + .sample_rate = ir_tx_obj->freq, + .bits_per_sample = 16, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels + .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 2, // no use + .dma_buf_len = 8 // no use + }; + i2s_pin_config_t pin_config = { + .bck_o_en = -1, + .ws_o_en = (ir_tx_obj->io_num == 2) ? 1 : -1, + .bck_i_en = -1, + .ws_i_en = (ir_tx_obj->io_num == 14) ? 1 : -1, + .data_out_en = -1, + .data_in_en = -1 + }; + + i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); + i2s_set_pin(I2S_NUM_0, &pin_config); + if (ir_tx_obj->timer == IR_TX_WDEV_TIMER) { + wDev_MacTimSetFunc(ir_tx_handler); + } else { + hw_timer_init(ir_tx_handler, NULL); + hw_timer_disarm(); + } + ir_tx_clear_carrier(); + + return ESP_OK; +} diff --git a/components/esp8266/driver/ledc.c b/components/esp8266/driver/ledc.c new file mode 100644 index 000000000..4220439e1 --- /dev/null +++ b/components/esp8266/driver/ledc.c @@ -0,0 +1,337 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "esp_err.h" +#include "esp_log.h" + +#include "driver/gpio.h" +#include "driver/ledc.h" +#include "driver/pwm.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" + +#define LEDC_PRIORITY (2) +#define LEDC_CHANNEL_MAX (8) +#define LEDC_STEP_TIME (10) +#define LEDC_FLAG_ON (1) +#define LEDC_FLAG_OFF (0) +#define LEDC_TASK_STACK_DEPTH (1024) +#define LEDC_MAX_DUTY (8196) + +static const char* LEDC_TAG = "ledc"; + +#define LEDC_CHECK(a, str, ret) \ + if (!(a)) { \ + ESP_LOGE(LEDC_TAG, "%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret); \ + } + +typedef struct { + ledc_channel_t channel_num; // Channel + uint32_t duty_p; // Duty at present + uint32_t duty; // Duty what we want to + uint32_t step_duty; // Duty/10ms means every 10ms change step_duty + uint32_t step_01duty; // 0.1 of the duty value + uint32_t step_001duty; // 0.01 of the duty value + uint32_t gpio_num;//gpio pins + float phase; //init phase + int fade_time; // Time to duty by fade +} ledc_obj_t; + +QueueHandle_t channel_queue; +static ledc_obj_t *p_ledc_obj[LEDC_CHANNEL_MAX] = { 0 }; +static uint8_t ledc_usr_channel_max = 0; //This is to allocate some channels according to the channel used by the user +static uint32_t ledc_period; + +/** + * @brief set down ledc duty by step + * + * @param channel set channel to change duty + * @param flag tells the caller whether the set duty cycle has been reached + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +static esp_err_t ledc_fade_down(ledc_channel_t channel, uint8_t* flag); + +/** + * @brief set up ledc duty by step + * + * @param channel set channel to change duty + * @param flag tells the caller whether the set duty cycle has been reached + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +static esp_err_t ledc_fade_up(ledc_channel_t channel, uint8_t* flag); + +esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) +{ + // Just freq_hz is useful + // Hz to period + LEDC_CHECK(timer_conf != NULL, "time_conf error", ESP_ERR_INVALID_ARG); + + ledc_period = 1000000 / timer_conf->freq_hz; + + return ESP_OK; +} + +// The difference between the current duty cycle and the target duty cycle +esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, uint32_t ledc_duty) +{ + LEDC_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_period * ledc_duty / LEDC_MAX_DUTY <= ledc_period, "ledc_duty error", ESP_ERR_INVALID_ARG); + + p_ledc_obj[ledc_channel]->channel_num = ledc_channel; + p_ledc_obj[ledc_channel]->duty = ledc_period * ledc_duty / LEDC_MAX_DUTY; + pwm_get_duty(ledc_channel, &p_ledc_obj[ledc_channel]->duty_p); + + p_ledc_obj[ledc_channel]->step_duty = (p_ledc_obj[ledc_channel]->duty_p > p_ledc_obj[ledc_channel]->duty ? p_ledc_obj[ledc_channel]->duty_p - p_ledc_obj[ledc_channel]->duty : p_ledc_obj[ledc_channel]->duty - p_ledc_obj[ledc_channel]->duty_p); + //The duty print value for this channel is duty/period(Program internal value), corresponding to duty/ledc_max_duty + ESP_LOGI(LEDC_TAG, "channel_num = %d | duty = %d; duty_p = %d | step_duty = %d;", + p_ledc_obj[ledc_channel]->channel_num, p_ledc_obj[ledc_channel]->duty, + p_ledc_obj[ledc_channel]->duty_p, p_ledc_obj[ledc_channel]->step_duty); + + return ESP_OK; +} + +esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t ledc_channel) +{ + // send the queue + LEDC_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + + uint8_t ret = xQueueSend(channel_queue, &ledc_channel, 0); + if (ret != pdPASS) { + ESP_LOGE(LEDC_TAG, "xQueueSend err\r\n"); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, uint32_t ledc_duty, int ledc_fade_time) +{ + // For porting, speed_mode is not used + LEDC_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_period * ledc_duty / LEDC_MAX_DUTY <= ledc_period, "ledc_duty error", ESP_ERR_INVALID_ARG); + + p_ledc_obj[ledc_channel]->channel_num = ledc_channel; + p_ledc_obj[ledc_channel]->duty = ledc_period * ledc_duty / LEDC_MAX_DUTY; + p_ledc_obj[ledc_channel]->fade_time = ledc_fade_time; + pwm_get_duty(ledc_channel, &p_ledc_obj[ledc_channel]->duty_p); + uint32_t duty_value = (p_ledc_obj[ledc_channel]->duty_p > p_ledc_obj[ledc_channel]->duty ? (p_ledc_obj[ledc_channel]->duty_p - p_ledc_obj[ledc_channel]->duty) : (p_ledc_obj[ledc_channel]->duty - p_ledc_obj[ledc_channel]->duty_p)); + + p_ledc_obj[ledc_channel]->step_duty = duty_value / (ledc_fade_time / LEDC_STEP_TIME); + p_ledc_obj[ledc_channel]->step_01duty = duty_value * 10 / (ledc_fade_time / LEDC_STEP_TIME) % 10; + p_ledc_obj[ledc_channel]->step_001duty = duty_value * 100 / (ledc_fade_time / LEDC_STEP_TIME) % 10; + + //The duty print value for this channel is duty/period(Program internal value), corresponding to duty/ledc_max_duty + ESP_LOGI(LEDC_TAG, "channel_num = %d | duty = %d; duty_p = %d | step_duty = %d | step_01duty = %d | step_001duty = %d", + p_ledc_obj[ledc_channel]->channel_num, p_ledc_obj[ledc_channel]->duty, + p_ledc_obj[ledc_channel]->duty_p, p_ledc_obj[ledc_channel]->step_duty, p_ledc_obj[ledc_channel]->step_01duty, p_ledc_obj[ledc_channel]->step_001duty); + + return ESP_OK; +} + +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, ledc_fade_mode_t fade_mode) +{ + LEDC_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + + esp_err_t ret; + ret = ledc_update_duty(speed_mode, ledc_channel); + if (ret == ESP_FAIL) { + return ESP_FAIL; + } + + if (fade_mode == LEDC_FADE_WAIT_DONE) { + vTaskDelay(p_ledc_obj[ledc_channel]->fade_time / portTICK_PERIOD_MS); + } + return ESP_OK; +} + +esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) +{ + LEDC_CHECK(ledc_conf != NULL, "ledc_conf error", ESP_ERR_INVALID_ARG); + LEDC_CHECK( ledc_conf->duty <= ledc_period, "ledc_duty error", ESP_ERR_INVALID_ARG); + + if (p_ledc_obj[ledc_usr_channel_max] == NULL){ + p_ledc_obj[ledc_usr_channel_max] = (ledc_obj_t *)calloc(1, sizeof(ledc_obj_t)); + if (p_ledc_obj[ledc_usr_channel_max] == NULL){ + ESP_LOGE(LEDC_TAG, "LEDC driver malloc error"); + return ESP_FAIL; + } + } + p_ledc_obj[ledc_usr_channel_max]->gpio_num = ledc_conf->gpio_num; + p_ledc_obj[ledc_usr_channel_max]->duty = ledc_period * ledc_conf->duty / LEDC_MAX_DUTY; + ledc_usr_channel_max++; + + return ESP_OK; +} + +esp_err_t ledc_fade_up(ledc_channel_t channel, uint8_t* flag) +{ + LEDC_CHECK(flag != NULL, "flag error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + + static uint8_t i[LEDC_CHANNEL_MAX] = { 0 }; + uint32_t duty_value = 0; + + duty_value = (i[channel] % 10 == 5 ? p_ledc_obj[channel]->step_duty + p_ledc_obj[channel]->step_01duty : p_ledc_obj[channel]->step_duty); + duty_value += (i[channel] == 50 ? p_ledc_obj[channel]->step_001duty : 0); + + if (p_ledc_obj[channel]->duty_p < p_ledc_obj[channel]->duty) { + if (p_ledc_obj[channel]->duty_p + duty_value > p_ledc_obj[channel]->duty) { + p_ledc_obj[channel]->duty_p = p_ledc_obj[channel]->duty; + } else { + p_ledc_obj[channel]->duty_p += duty_value; + } + pwm_set_duty(channel, p_ledc_obj[channel]->duty_p); + i[channel]++; + if (i[channel] == 100) { + i[channel] = 0; + } + } + if (p_ledc_obj[channel]->duty_p == p_ledc_obj[channel]->duty) { + *flag = LEDC_FLAG_OFF; + } + + return ESP_OK; +} + +esp_err_t ledc_fade_down(ledc_channel_t channel, uint8_t* flag) +{ + LEDC_CHECK(flag != NULL, "flag error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel < LEDC_CHANNEL_MAX, "ledc_channel error", ESP_ERR_INVALID_ARG); + + static uint8_t i[LEDC_CHANNEL_MAX] = { 0 }; + uint32_t duty_value = 0; + + duty_value = (i[channel] % 10 == 5 ? p_ledc_obj[channel]->step_duty + p_ledc_obj[channel]->step_01duty : p_ledc_obj[channel]->step_duty); + duty_value += (i[channel] == 50 ? p_ledc_obj[channel]->step_001duty : 0); + + if (p_ledc_obj[channel]->duty_p > p_ledc_obj[channel]->duty) { + // it is more smart than 'p_ledc_obj[channel].duty_p - p_ledc_obj[channel].step_duty < p_ledc_obj[channel].duty' + if (p_ledc_obj[channel]->duty_p < p_ledc_obj[channel]->duty + duty_value) { + p_ledc_obj[channel]->duty_p = p_ledc_obj[channel]->duty; + } else { + p_ledc_obj[channel]->duty_p -= duty_value; + } + pwm_set_duty(channel, p_ledc_obj[channel]->duty_p); + i[channel]++; + if (i[channel] == 100) { + i[channel] = 0; + } + } + if (p_ledc_obj[channel]->duty_p == p_ledc_obj[channel]->duty) { + *flag = LEDC_FLAG_OFF; + } + + return ESP_OK; +} + +// Complete message queue reception while changing duty cycle +static void ledc_task(void* pvParameters) +{ + ledc_channel_t channel; + uint8_t i; + uint8_t flag[LEDC_CHANNEL_MAX] = { 0 }; + + while (1) { + + while (pdTRUE == xQueueReceive(channel_queue, &channel, 0)) { + flag[channel] = LEDC_FLAG_ON; + } + vTaskSuspendAll(); + for (i = 0; i < ledc_usr_channel_max; i++) { + if (flag[i] == LEDC_FLAG_ON) { + if (p_ledc_obj[i]->duty_p < p_ledc_obj[i]->duty) { + ledc_fade_up(i, &flag[i]); + } else { + ledc_fade_down(i, &flag[i]); + } + } + } + pwm_start(); + xTaskResumeAll(); + vTaskDelay(LEDC_STEP_TIME / portTICK_PERIOD_MS); + } + vTaskDelete(NULL); +} + +esp_err_t ledc_fade_func_install(int intr_alloc_flags) +{ + float ledc_phase[LEDC_CHANNEL_MAX] = {0}; + uint32_t ledc_duty[LEDC_CHANNEL_MAX] = {0}; + uint32_t ledc_gpio_num[LEDC_CHANNEL_MAX] = {0}; + + for (int i = 0; i < ledc_usr_channel_max; i++){ + ledc_gpio_num[i] = p_ledc_obj[i]->gpio_num; + ledc_duty[i] = p_ledc_obj[i]->duty; + } + + LEDC_CHECK(ledc_usr_channel_max < LEDC_CHANNEL_MAX, "flag error", ESP_ERR_INVALID_ARG); + pwm_init(ledc_period, ledc_duty, ledc_usr_channel_max, ledc_gpio_num); + ESP_LOGI(LEDC_TAG, "ledc_usr_channel_max:%d", ledc_usr_channel_max); + for (int i = 0; i < ledc_usr_channel_max; i++) { + ESP_LOGI(LEDC_TAG, "gpio:%d", ledc_gpio_num[i]); + } + + pwm_set_phases(ledc_phase); + channel_queue = xQueueCreate(ledc_usr_channel_max, sizeof(uint8_t)); + if (channel_queue == 0) { + ESP_LOGE(LEDC_TAG, "xQueueCreate err\r\n"); + return ESP_ERR_INVALID_STATE; + } + + xTaskCreate(ledc_task, "ledc_task", LEDC_TASK_STACK_DEPTH, NULL, LEDC_PRIORITY, NULL); + + return pwm_start(); +} + +esp_err_t ledc_fade_func_uninstall(void) +{ + for (int i = 0; i < ledc_usr_channel_max; i++){ + free(p_ledc_obj[i]); + p_ledc_obj[i] = NULL; + } + return pwm_stop(0x00); +} + +esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level) +{ + LEDC_CHECK(idle_level == 0 || idle_level == 1, "idle_level error", ESP_ERR_INVALID_ARG); + + static uint32_t stop_level_mask = 0x0; + if (idle_level == 0){ + stop_level_mask = stop_level_mask | 0x1 << channel; + } + else if (idle_level == 1){ + stop_level_mask = stop_level_mask & ~(0x1 << channel); + } + + pwm_stop(stop_level_mask); + + return ESP_OK; +} + +int periph_module_enable(int none) +{ + return ESP_OK; +} \ No newline at end of file diff --git a/components/esp8266/driver/pwm.c b/components/esp8266/driver/pwm.c index 94dbb4669..6d4babfdf 100644 --- a/components/esp8266/driver/pwm.c +++ b/components/esp8266/driver/pwm.c @@ -26,7 +26,6 @@ #include "esp_heap_caps.h" #include "driver/pwm.h" - #include "driver/gpio.h" // Temporary use the FreeRTOS critical function @@ -46,26 +45,21 @@ static const char *TAG = "pwm"; #define US_TO_MAC_TICK(t) (t) #define US_TO_TICKS(t) US_TO_MAC_TICK(t) +// Time to switch PWM ahead of time #define AHEAD_TICKS0 0 -#define AHEAD_TICKS1 6 -#define AHEAD_TICKS2 8 +// Advance timing of the timer +#define AHEAD_TICKS1 8 +// The time that remains in the interrupt function (the adjacent target loops in the interrupt) +#define AHEAD_TICKS2 10 +// Minimum timing time #define AHEAD_TICKS3 2 #define MAX_TICKS 10000000ul -#define WDEVTSF0_TIME_LO 0x3ff21004 -#define WDEVTSF0_TIME_HI 0x3ff21008 -#define WDEVTSFSW0_LO 0x3ff21018 -#define WDEVTSFSW0_HI 0x3ff2101C -#define WDEVTSF0_TIMER_LO 0x3ff2109c -#define WDEVTSF0_TIMER_HI 0x3ff210a0 -#define WDEVTSF0TIMER_ENA 0x3ff21098 -#define WDEV_TSF0TIMER_ENA BIT(31) - -#define PWM_VERSION "PWM v3.0" +#define PWM_VERSION "PWM v3.4" typedef struct { uint32_t duty; /*!< pwm duty for each channel */ - int16_t phase; /*!< pwm phase for each channel */ + float phase; /*!< pwm phase for each channel */ uint8_t io_num; /*!< pwm io_num for each channel */ } pwm_info_t; @@ -114,18 +108,18 @@ int wDev_MacTimSetFunc(void (*handle)(void)); static void pwm_phase_init(void) { - int16_t time_delay; + int32_t time_delay; uint8_t i; for (i = 0; i < pwm_obj->channel_num; i++) { if (-180 < pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase < 0) { - time_delay = 0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 180); + time_delay = (int32_t)(0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 360.0)); } else if (pwm_obj->pwm_info[i].phase == 0) { continue; - } else if (180 > pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) { - time_delay = pwm_obj->pwm_info[i].phase * pwm_obj->depth / 180; + } else if (180 >= pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) { + time_delay = (int32_t)(pwm_obj->pwm_info[i].phase * pwm_obj->depth / 360.0); } else { - ESP_LOGE(TAG, "channel[%d] phase error %d, valid ramge from (-180,180)\n", i, pwm_obj->pwm_info[i].phase); + ESP_LOGE(TAG, "channel[%d] phase error %f, valid ramge from (-180,180]\n", i, pwm_obj->pwm_info[i].phase); continue; } @@ -158,6 +152,8 @@ static void pwm_insert_sort(void) esp_err_t pwm_set_period(uint32_t period) { PWM_CHECK(period >= 10, "period setting is too short", ESP_ERR_INVALID_ARG); + + pwm_obj->depth = period; // For ease of conversion, let the depth equal the period pwm_obj->period = period; return ESP_OK; @@ -190,7 +186,7 @@ esp_err_t pwm_clear_channel_invert(uint16_t channel_mask) esp_err_t pwm_set_duty(uint8_t channel_num, uint32_t duty) { - PWM_CHECK(channel_num <= pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); + PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); pwm_obj->pwm_info[channel_num].duty = duty; return ESP_OK; @@ -210,7 +206,7 @@ esp_err_t pwm_set_duties(uint32_t *duties) esp_err_t pwm_get_duty(uint8_t channel_num, uint32_t *duty_p) { - PWM_CHECK(channel_num <= pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); + PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); PWM_CHECK(NULL != duty_p, "Pointer is empty", ESP_ERR_INVALID_ARG); *duty_p = pwm_obj->pwm_info[channel_num].duty; @@ -228,16 +224,16 @@ esp_err_t pwm_set_period_duties(uint32_t period, uint32_t *duties) return ESP_OK; } -esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase) +esp_err_t pwm_set_phase(uint8_t channel_num, float phase) { - PWM_CHECK(channel_num <= pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); + PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); pwm_obj->pwm_info[channel_num].phase = phase; return ESP_OK; } -esp_err_t pwm_set_phases(int16_t *phases) +esp_err_t pwm_set_phases(float *phases) { uint8_t i; PWM_CHECK(NULL != phases, "Pointer is empty", ESP_ERR_INVALID_ARG); @@ -250,9 +246,9 @@ esp_err_t pwm_set_phases(int16_t *phases) return ESP_OK; } -esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p) +esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p) { - PWM_CHECK(channel_num <= pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); + PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); PWM_CHECK(NULL != phase_p, "Pointer is empty", ESP_ERR_INVALID_ARG); *phase_p = pwm_obj->pwm_info[channel_num].phase; @@ -263,9 +259,7 @@ esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p) static void pwm_timer_enable(uint8_t enable) { if (0 == enable) { - ENTER_CRITICAL(); REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); - EXIT_CRITICAL(); } else { REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); } @@ -290,7 +284,6 @@ static void IRAM_ATTR pwm_timer_intr_handler(void) pwm_obj->run_pwm_toggle = (pwm_obj->run_pwm_toggle ^ 0x1); pwm_obj->update_done = 0; } - mask = mask & (~pwm_obj->single->run_pwm_param[pwm_obj->single->run_channel_num - 1].io_clr_mask); mask = mask | pwm_obj->single->run_pwm_param[pwm_obj->single->run_channel_num - 1].io_set_mask; REG_WRITE(PERIPHS_GPIO_BASEADDR + GPIO_OUT_ADDRESS, mask); @@ -315,14 +308,20 @@ static void IRAM_ATTR pwm_timer_intr_handler(void) pwm_obj->this_target = AHEAD_TICKS1 + AHEAD_TICKS3; } + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) & (~WDEV_TSFUP0_ENA)); + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); REG_WRITE(WDEVTSFSW0_LO, 0); - //WARNING, pwm_obj->this_target - AHEAD_TICKS1 should be bigger than zero + //WARNING, pwm_obj->this_target - AHEAD_TICKS1 should be bigger than 2 REG_WRITE(WDEVTSF0_TIMER_LO, pwm_obj->this_target - AHEAD_TICKS1); REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) | WDEV_TSFUP0_ENA); } static void pwm_timer_start(uint32_t period) { + ENTER_CRITICAL(); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) & (~WDEV_TSFUP0_ENA)); + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); // suspend all task to void timer interrupt missed // TODO, do we need lock interrupt here, I think interrupt context will not take 1ms long // time low field to 0 @@ -339,8 +338,11 @@ static void pwm_timer_start(uint32_t period) pwm_obj->this_target = US_TO_TICKS(period); // WARNING: pwm_obj->this_target should bigger than AHEAD_TICKS1 REG_WRITE(WDEVTSF0_TIMER_LO, pwm_obj->this_target - AHEAD_TICKS1); - // enable timer + REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) | WDEV_TSFUP0_ENA); + //enable timer pwm_timer_enable(1); + EXIT_CRITICAL(); } static void pwm_timer_register(void (*handle)(void)) @@ -512,7 +514,7 @@ static esp_err_t pwm_obj_free(void) return ESP_OK; } -static esp_err_t pwm_obj_malloc(uint32_t channel_num) +static esp_err_t pwm_obj_malloc(uint8_t channel_num) { pwm_obj = (pwm_obj_t *)heap_caps_malloc(sizeof(pwm_obj_t), MALLOC_CAP_8BIT); @@ -537,27 +539,30 @@ static esp_err_t pwm_obj_malloc(uint32_t channel_num) return ESP_OK; } -esp_err_t pwm_init(uint32_t period, uint32_t *duties, uint32_t channel_num, const uint32_t *pin_mum) +esp_err_t pwm_init(uint32_t period, uint32_t *duties, uint8_t channel_num, const uint32_t *pin_num) { PWM_CHECK(pwm_obj == NULL, "pwm has been initialized", ESP_FAIL); PWM_CHECK(channel_num <= MAX_PWM_CHANNEL, "Channel num out of range", ESP_ERR_INVALID_ARG); PWM_CHECK(NULL != duties, "duties pointer is empty", ESP_ERR_INVALID_ARG); - PWM_CHECK(NULL != pin_mum, "Pointer is empty", ESP_ERR_INVALID_ARG); + PWM_CHECK(NULL != pin_num, "Pointer is empty", ESP_ERR_INVALID_ARG); PWM_CHECK(period >= 10, "period setting is too short", ESP_ERR_INVALID_ARG); uint8_t i; + /*enable tsf0 interrupt for pwm*/ + REG_WRITE(PERIPHS_DPORT_BASEADDR, (REG_READ(PERIPHS_DPORT_BASEADDR) & ~0x1F) | 0x1); + REG_WRITE(INT_ENA_WDEV, REG_READ(INT_ENA_WDEV) | WDEV_TSF0_REACH_INT); + if (ESP_ERR_NO_MEM == pwm_obj_malloc(channel_num)) { pwm_obj_free(); return ESP_ERR_NO_MEM; } - pwm_obj->depth = period; pwm_obj->channel_num = channel_num; for (i = 0; i < channel_num; i++) { - pwm_obj->pwm_info[i].io_num = pin_mum[i]; - pwm_obj->gpio_bit_mask |= (0x1 << pin_mum[i]); + pwm_obj->pwm_info[i].io_num = pin_num[i]; + pwm_obj->gpio_bit_mask |= (0x1 << pin_num[i]); } gpio_config_t io_conf; io_conf.intr_type = GPIO_INTR_DISABLE; @@ -579,7 +584,9 @@ esp_err_t pwm_stop(uint32_t stop_level_mask) { int16_t i = 0; + ENTER_CRITICAL(); pwm_timer_enable(0); + EXIT_CRITICAL(); uint32_t level_set = REG_READ(PERIPHS_GPIO_BASEADDR + GPIO_OUT_ADDRESS); for (i = 0; i < pwm_obj->channel_num; i++) { @@ -608,4 +615,4 @@ esp_err_t pwm_deinit(void) pwm_obj_free(); return ESP_OK; -} \ No newline at end of file +} diff --git a/components/esp8266/driver/spi.c b/components/esp8266/driver/spi.c new file mode 100644 index 000000000..a5a3ed4b9 --- /dev/null +++ b/components/esp8266/driver/spi.c @@ -0,0 +1,760 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/spi_struct.h" +#include "esp8266/pin_mux_register.h" +#include "esp_libc.h" +#include "esp_heap_caps.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "rom/ets_sys.h" +#include "spi.h" + + +#define ENTER_CRITICAL() portENTER_CRITICAL() +#define EXIT_CRITICAL() portEXIT_CRITICAL() +#define SPI_CHECK(a, str, ret_val) \ + do { \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } \ + } while(0) + +#ifndef CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT +#define ENTER_CRITICAL_HIGH_THROUGHPUT() ENTER_CRITICAL() +#define EXIT_CRITICAL_HIGH_THROUGHPUT() EXIT_CRITICAL() +#define SPI_HIGH_THROUGHPUT_ATTR +#define SPI_CHECK_HIGH_THROUGHPUT(a, str, ret_val) SPI_CHECK(a, str, ret_val) + +#else +#define SPI_HIGH_THROUGHPUT_ATTR IRAM_ATTR +#define ENTER_CRITICAL_HIGH_THROUGHPUT() do{} while(0) +#define EXIT_CRITICAL_HIGH_THROUGHPUT() do{} while(0) + +#define SPI_CHECK_HIGH_THROUGHPUT(a, str, ret_val) \ + do { \ + if (!(a)) { \ + ets_printf("%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } \ + } while(0) +#endif + +static const char *TAG = "spi"; + +#define spi_intr_enable() _xt_isr_unmask(1 << ETS_SPI_INUM) +#define spi_intr_disable() _xt_isr_mask(1 << ETS_SPI_INUM) +#define spi_intr_register(a, b) _xt_isr_attach(ETS_SPI_INUM, (a), (b)) + +/* SPI interrupt status register address definition for determining the interrupt source */ +#define DPORT_SPI_INT_STATUS_REG 0x3ff00020 +#define DPORT_SPI_INT_STATUS_SPI0 BIT4 +#define DPORT_SPI_INT_STATUS_SPI1 BIT7 + +typedef struct { + spi_mode_t mode; + spi_interface_t interface; + SemaphoreHandle_t trans_mux; + spi_event_callback_t event_cb; + spi_intr_enable_t intr_enable; + uint32_t *buf; +} spi_object_t; + +static spi_object_t *spi_object[SPI_NUM_MAX] = {NULL, NULL}; + +/* DRAM_ATTR is required to avoid SPI array placed in flash, due to accessed from ISR */ +static DRAM_ATTR spi_dev_t *const SPI[SPI_NUM_MAX] = {&SPI0, &SPI1}; + +esp_err_t spi_get_clk_div(spi_host_t host, spi_clk_div_t *clk_div) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(clk_div, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + if (SPI[host]->clock.clk_equ_sysclk) { + *clk_div = SPI_80MHz_DIV; + } + + *clk_div = SPI[host]->clock.clkcnt_n + 1; + return ESP_OK; +} + +esp_err_t spi_set_clk_div(spi_host_t host, spi_clk_div_t *clk_div) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(clk_div, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + + if (SPI_MASTER_MODE == spi_object[host]->mode) { + if (SPI_80MHz_DIV == *clk_div) { + switch (host) { + case CSPI_HOST: { + SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK); + } + break; + + case HSPI_HOST: { + SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); + } + break; + } + + SPI[host]->clock.clk_equ_sysclk = true; + } else { + // Configure the IO_MUX clock (required, otherwise the clock output will be confusing) + switch (host) { + case CSPI_HOST: { + CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK); + } + break; + + case HSPI_HOST: { + CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); + } + break; + } + + // FRE(SCLK) = clk_equ_sysclk ? 80MHz : APB_CLK(80MHz) / clkdiv_pre / clkcnt + SPI[host]->clock.clk_equ_sysclk = false; + SPI[host]->clock.clkdiv_pre = 0; + SPI[host]->clock.clkcnt_n = *clk_div - 1; + // In the master mode clkcnt_h = floor((clkcnt_n+1)/2-1). In the slave mode it must be 0 + SPI[host]->clock.clkcnt_h = *clk_div / 2 - 1; + // In the master mode clkcnt_l = clkcnt_n. In the slave mode it must be 0 + SPI[host]->clock.clkcnt_l = *clk_div - 1; + } + } else { + // Slave mode must be set to 0 + SPI[host]->clock.val = 0; + } + + EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t spi_get_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(intr_enable, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + intr_enable->val = (SPI[host]->slave.val >> 5) & 0x1F; + + return ESP_OK; +} + +esp_err_t spi_set_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(intr_enable, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + SPI[host]->slave.rd_buf_inten = intr_enable->read_buffer; + SPI[host]->slave.wr_buf_inten = intr_enable->write_buffer; + SPI[host]->slave.rd_sta_inten = intr_enable->read_status; + SPI[host]->slave.wr_sta_inten = intr_enable->write_status; + SPI[host]->slave.trans_inten = intr_enable->trans_done; + // Clear interrupt status register + SPI[host]->slave.rd_buf_done = false; + SPI[host]->slave.wr_buf_done = false; + SPI[host]->slave.rd_sta_done = false; + SPI[host]->slave.wr_sta_done = false; + SPI[host]->slave.trans_done = false; + EXIT_CRITICAL(); + + spi_object[host]->intr_enable.val = intr_enable->val; + + return ESP_OK; +} + +esp_err_t spi_get_mode(spi_host_t host, spi_mode_t *mode) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(mode, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + *mode = spi_object[host]->mode; + + return ESP_OK; +} + +esp_err_t spi_set_mode(spi_host_t host, spi_mode_t *mode) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(mode, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + spi_object[host]->mode = *mode; + ENTER_CRITICAL(); + // Disable flash operation mode + SPI[host]->user.flash_mode = false; + + if (SPI_MASTER_MODE == *mode) { + // Set to Master mode + SPI[host]->pin.slave_mode = false; + SPI[host]->slave.slave_mode = false; + // Master uses the entire hardware buffer to improve transmission speed + SPI[host]->user.usr_mosi_highpart = false; + SPI[host]->user.usr_miso_highpart = false; + SPI[host]->user.usr_mosi = true; + // Create hardware cs in advance + SPI[host]->user.cs_setup = true; + // Hysteresis to keep hardware cs + SPI[host]->user.cs_hold = true; + SPI[host]->user.duplex = true; + SPI[host]->user.ck_i_edge = true; + SPI[host]->ctrl2.mosi_delay_num = 0; + SPI[host]->ctrl2.miso_delay_num = 1; + } else { + // Set to Slave mode + SPI[host]->pin.slave_mode = true; + SPI[host]->slave.slave_mode = true; + SPI[host]->user.usr_mosi_highpart = false; + SPI[host]->user.usr_miso_highpart = false; + SPI[host]->user.usr_addr = 1; + // MOSI signals are delayed by APB_CLK(80MHz) mosi_delay_num cycles + SPI[host]->ctrl2.mosi_delay_num = 2; + SPI[host]->ctrl2.miso_delay_num = 0; + SPI[host]->slave.wr_rd_buf_en = 1; + SPI[host]->slave.wr_rd_sta_en = 1; + SPI[host]->slave1.status_bitlen = 31; + SPI[host]->slave1.status_readback = 0; + // Put the slave's miso on the highpart, so you can only send 512bits + // In Slave mode miso, mosi length is the same + SPI[host]->slave1.buf_bitlen = 511; + SPI[host]->slave1.wr_addr_bitlen = 7; + SPI[host]->slave1.rd_addr_bitlen = 7; + SPI[host]->user1.usr_addr_bitlen = 7; + SPI[host]->user1.usr_miso_bitlen = 31; + SPI[host]->user1.usr_mosi_bitlen = 31; + SPI[host]->user2.usr_command_bitlen = 7; + SPI[host]->cmd.usr = 1; + } + + SPI[host]->user.fwrite_dual = false; + SPI[host]->user.fwrite_quad = false; + SPI[host]->user.fwrite_dio = false; + SPI[host]->user.fwrite_qio = false; + SPI[host]->ctrl.fread_dual = false; + SPI[host]->ctrl.fread_quad = false; + SPI[host]->ctrl.fread_dio = false; + SPI[host]->ctrl.fread_qio = false; + SPI[host]->ctrl.fastrd_mode = true; + SPI[host]->slave.sync_reset = 1; + EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t spi_get_interface(spi_host_t host, spi_interface_t *interface) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(interface, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + *interface = spi_object[host]->interface; + + return ESP_OK; +} + +esp_err_t spi_set_interface(spi_host_t host, spi_interface_t *interface) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(interface, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + spi_object[host]->interface = *interface; + ENTER_CRITICAL(); + + switch (host) { + case CSPI_HOST: { + // Initialize SPI IO + PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_CLK_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SPICLK); + + if (interface->mosi_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_DATA1_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, FUNC_SPID_MOSI); + } + + if (interface->miso_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_DATA0_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, FUNC_SPIQ_MISO); + } + + if (interface->cs_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_CMD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, FUNC_SPICS0); + } + } + break; + + case HSPI_HOST: { + // Initialize HSPI IO + PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_HSPI_CLK); //GPIO14 is SPI CLK pin (Clock) + + if (interface->mosi_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); //GPIO13 is SPI MOSI pin (Master Data Out) + } + + if (interface->miso_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDI_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_HSPIQ_MISO); //GPIO12 is SPI MISO pin (Master Data In) + } + + if (interface->cs_en) { + PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_HSPI_CS0); + } + } + break; + } + + // Set the clock polarity and phase + SPI[host]->pin.ck_idle_edge = interface->cpol; + + if (interface->cpol == interface->cpha) { + SPI[host]->user.ck_out_edge = false; + } else { + SPI[host]->user.ck_out_edge = true; + } + + // Set data bit order + SPI[host]->ctrl.wr_bit_order = interface->bit_tx_order; + SPI[host]->ctrl.rd_bit_order = interface->bit_rx_order; + // Set data byte order + SPI[host]->user.wr_byte_order = interface->byte_tx_order; + SPI[host]->user.rd_byte_order = interface->byte_rx_order; + EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t spi_get_dummy(spi_host_t host, uint16_t *bitlen) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(bitlen, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + if (SPI[host]->user.usr_dummy) { + *bitlen = SPI[host]->user1.usr_dummy_cyclelen + 1; + } else { + *bitlen = 0; + } + + return ESP_OK; +} + +esp_err_t spi_set_dummy(spi_host_t host, uint16_t *bitlen) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(bitlen, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + SPI_CHECK(*bitlen <= 256, "spi dummy must be shorter than 256 bits", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + + if (*bitlen) { + SPI[host]->user.usr_dummy = 1; + SPI[host]->user1.usr_dummy_cyclelen = *bitlen - 1; + } else { + SPI[host]->user.usr_dummy = 0; + } + + EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t spi_get_event_callback(spi_host_t host, spi_event_callback_t *event_cb) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(event_cb, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + *event_cb = spi_object[host]->event_cb; + + return ESP_OK; +} + +esp_err_t spi_set_event_callback(spi_host_t host, spi_event_callback_t *event_cb) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(event_cb, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + spi_object[host]->event_cb = *event_cb; + + return ESP_OK; +} + +esp_err_t spi_slave_get_status(spi_host_t host, uint32_t *status) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK(SPI_SLAVE_MODE == spi_object[host]->mode, "this function must used by spi slave mode", ESP_FAIL); + SPI_CHECK(status, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL(); + + *status = SPI[host]->wr_status; + + EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t SPI_HIGH_THROUGHPUT_ATTR spi_slave_set_status(spi_host_t host, uint32_t *status) +{ + SPI_CHECK_HIGH_THROUGHPUT(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK_HIGH_THROUGHPUT(SPI_SLAVE_MODE == spi_object[host]->mode, "this function must used by spi slave mode", ESP_FAIL); + SPI_CHECK_HIGH_THROUGHPUT(status, "parameter pointer is empty", ESP_ERR_INVALID_ARG); + + ENTER_CRITICAL_HIGH_THROUGHPUT(); + + SPI[host]->rd_status.val = *status; + + EXIT_CRITICAL_HIGH_THROUGHPUT(); + + return ESP_OK; +} + +static esp_err_t SPI_HIGH_THROUGHPUT_ATTR spi_master_trans(spi_host_t host, spi_trans_t *trans) +{ + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.cmd <= 16, "spi cmd must be shorter than 16 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.addr <= 32, "spi addr must be shorter than 32 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.mosi <= 512, "spi mosi must be shorter than 512 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.miso <= 512, "spi miso must be shorter than 512 bits", ESP_ERR_INVALID_ARG); + + int x, y; + + // Waiting for an incomplete transfer + while (SPI[host]->cmd.usr); + + ENTER_CRITICAL_HIGH_THROUGHPUT(); + + // Set the cmd length and transfer cmd + if (trans->bits.cmd && trans->cmd) { + SPI[host]->user.usr_command = 1; + SPI[host]->user2.usr_command_bitlen = trans->bits.cmd - 1; + SPI[host]->user2.usr_command_value = *trans->cmd; + } else { + SPI[host]->user.usr_command = 0; + } + + // Set addr length and transfer addr + if (trans->bits.addr && trans->addr) { + SPI[host]->user.usr_addr = 1; + SPI[host]->user1.usr_addr_bitlen = trans->bits.addr - 1; + SPI[host]->addr = *trans->addr; + } else { + SPI[host]->user.usr_addr = 0; + } + + // Set mosi length and transmit mosi + if (trans->bits.mosi && trans->mosi) { + SPI[host]->user.usr_mosi = 1; + SPI[host]->user1.usr_mosi_bitlen = trans->bits.mosi - 1; + if ((uint32_t)(trans->mosi) % 4 == 0) { + for (x = 0; x < trans->bits.mosi; x += 32) { + y = x / 32; + SPI[host]->data_buf[y] = trans->mosi[y]; + } + } else { + ESP_LOGW(TAG,"Using unaligned data may reduce transmission efficiency"); + memset(spi_object[host]->buf, 0, sizeof(uint32_t) * 16); + memcpy(spi_object[host]->buf, trans->mosi, trans->bits.mosi / 8 + (trans->bits.mosi % 8) ? 1 : 0); + for (x = 0; x < trans->bits.mosi; x += 32) { + y = x / 32; + SPI[host]->data_buf[y] = spi_object[host]->buf[y]; + } + } + + } else { + SPI[host]->user.usr_mosi = 0; + } + + // Set the length of the miso + if (trans->bits.miso && trans->miso) { + SPI[host]->user.usr_miso = 1; + SPI[host]->user1.usr_miso_bitlen = trans->bits.miso - 1; + } else { + SPI[host]->user.usr_miso = 0; + } + + // Call the event callback function to send a transfer start event + if (spi_object[host]->event_cb) { + spi_object[host]->event_cb(SPI_TRANS_START_EVENT, NULL); + } + + // Start transmission + SPI[host]->cmd.usr = 1; + + // Receive miso data + if (trans->bits.miso && trans->miso) { + while (SPI[host]->cmd.usr); + + if ((uint32_t)(trans->miso) % 4 == 0) { + for (x = 0; x < trans->bits.miso; x += 32) { + y = x / 32; + trans->miso[y] = SPI[host]->data_buf[y]; + } + } else { + ESP_LOGW(TAG,"Using unaligned data may reduce transmission efficiency"); + memset(spi_object[host]->buf, 0, sizeof(uint32_t) * 16); + for (x = 0; x < trans->bits.miso; x += 32) { + y = x / 32; + spi_object[host]->buf[y] = SPI[host]->data_buf[y]; + } + memcpy(trans->miso, spi_object[host]->buf, trans->bits.miso / 8 + (trans->bits.miso % 8) ? 1 : 0); + } + } + + EXIT_CRITICAL_HIGH_THROUGHPUT(); + + return ESP_OK; +} + +static esp_err_t SPI_HIGH_THROUGHPUT_ATTR spi_slave_trans(spi_host_t host, spi_trans_t *trans) +{ + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.cmd >= 3 && trans->bits.cmd <= 16, "spi cmd must be longer than 3 bits and shorter than 16 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.addr >= 1 && trans->bits.addr <= 32, "spi addr must be longer than 1 bits and shorter than 32 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.miso <= 512, "spi miso must be shorter than 512 bits", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.mosi <= 512, "spi mosi must be shorter than 512 bits", ESP_ERR_INVALID_ARG); + + int x, y; + ENTER_CRITICAL_HIGH_THROUGHPUT(); + // Set cmd length and receive cmd + SPI[host]->user2.usr_command_bitlen = trans->bits.cmd - 1; + + if (trans->cmd) { + *trans->cmd = SPI[host]->user2.usr_command_value; + } + + // Set addr length and transfer addr + SPI[host]->slave1.wr_addr_bitlen = trans->bits.addr - 1; + SPI[host]->slave1.rd_addr_bitlen = trans->bits.addr - 1; + + if (trans->addr) { + *trans->addr = SPI[host]->addr; + } + + // Set the length of the miso and transfer the miso + if (trans->bits.miso && trans->miso) { + if ((uint32_t)(trans->miso) % 4 == 0) { + for (x = 0; x < trans->bits.miso; x += 32) { + y = x / 32; + SPI[host]->data_buf[y] = trans->miso[y]; + } + } else { + ESP_LOGW(TAG,"Using unaligned data may reduce transmission efficiency"); + memset(spi_object[host]->buf, 0, sizeof(uint32_t) * 16); + memcpy(spi_object[host]->buf, trans->miso, trans->bits.miso / 8 + (trans->bits.miso % 8) ? 1 : 0); + for (x = 0; x < trans->bits.miso; x += 32) { + y = x / 32; + SPI[host]->data_buf[y] = spi_object[host]->buf[y]; + } + } + } + + // Receive mosi data + if (trans->bits.mosi && trans->mosi) { + if ((uint32_t)(trans->mosi) % 4 == 0) { + for (x = 0; x < trans->bits.mosi; x += 32) { + y = x / 32; + trans->mosi[y] = SPI[host]->data_buf[y]; + } + } else { + ESP_LOGW(TAG,"Using unaligned data may reduce transmission efficiency"); + memset(spi_object[host]->buf, 0, sizeof(uint32_t) * 16); + for (x = 0; x < trans->bits.mosi; x += 32) { + y = x / 32; + spi_object[host]->buf[y] = SPI[host]->data_buf[y]; + } + memcpy(trans->mosi, spi_object[host]->buf, trans->bits.mosi / 8 + (trans->bits.mosi % 8) ? 1 : 0); + } + } + + EXIT_CRITICAL_HIGH_THROUGHPUT(); + + return ESP_OK; +} + +static esp_err_t SPI_HIGH_THROUGHPUT_ATTR spi_trans_static(spi_host_t host, spi_trans_t *trans) +{ + int ret; + if (SPI_MASTER_MODE == spi_object[host]->mode) { + ret = spi_master_trans(host, trans); + } else { + ret = spi_slave_trans(host, trans); + } + + return ret; +} + +esp_err_t SPI_HIGH_THROUGHPUT_ATTR spi_trans(spi_host_t host, spi_trans_t *trans) +{ + SPI_CHECK_HIGH_THROUGHPUT(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK_HIGH_THROUGHPUT(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + SPI_CHECK_HIGH_THROUGHPUT(trans->bits.val, "trans bits is empty", ESP_ERR_INVALID_ARG); + + int ret; + if (xPortInIsrContext()) { + /* In ISR Context */ + BaseType_t higher_task_woken = false; + if (xSemaphoreTakeFromISR(spi_object[host]->trans_mux, NULL) != pdTRUE) { + return ESP_FAIL; + } + ret = spi_trans_static(host, trans); + xSemaphoreGiveFromISR(spi_object[host]->trans_mux, &higher_task_woken); + if (higher_task_woken) { + portYIELD_FROM_ISR(); + } + } + else { + xSemaphoreTake(spi_object[host]->trans_mux, portMAX_DELAY); + ret = spi_trans_static(host, trans); + xSemaphoreGive(spi_object[host]->trans_mux); + } + return ret; +} + +static IRAM_ATTR void spi_intr(void *arg) +{ + spi_host_t host; + uint32_t trans_done; + uint32_t cnt = 0; + if (READ_PERI_REG(DPORT_SPI_INT_STATUS_REG) & DPORT_SPI_INT_STATUS_SPI0) { // DPORT_SPI_INT_STATUS_SPI0 + trans_done = SPI0.slave.val & 0x1F; + SPI0.slave.val &= ~0x3FF; + host = CSPI_HOST; + } else if (READ_PERI_REG(DPORT_SPI_INT_STATUS_REG) & DPORT_SPI_INT_STATUS_SPI1) { // DPORT_SPI_INT_STATUS_SPI1 + trans_done = SPI1.slave.val & 0x1F; + SPI1.slave.val &= ~0x1F; + // Hardware issues: We need to wait for the hardware to clear the registers successfully. + while ((SPI1.slave.val & 0x1F) != 0) { + if (cnt >= 50) { + ets_printf("WARNING: waiting too much time, maybe error\r\n"); + cnt = 0; + } + SPI1.slave.val &= ~0x1F; + cnt++; + } + + host = HSPI_HOST; + } else { + return; + } + + if (spi_object[host]) { + // Hardware has no interrupt flag, which can be generated by software. + trans_done &= spi_object[host]->intr_enable.val; + if (spi_object[host]->event_cb && trans_done != 0) { + spi_object[host]->event_cb(SPI_TRANS_DONE_EVENT, &trans_done); + } + } +} + +esp_err_t spi_deinit(spi_host_t host) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL); + + spi_intr_enable_t intr_enable; + // Turn off the current host interrupt enable + intr_enable.val = 0; + spi_set_intr_enable(host, &intr_enable); + + // Turn off the SPI interrupt if all other hosts are not initialized + if (host == CSPI_HOST) { + if (spi_object[HSPI_HOST] == NULL) { + spi_intr_disable(); + } + } else { + if (spi_object[CSPI_HOST] == NULL) { + spi_intr_disable(); + } + } + + // Waiting for all transfers to complete + while (SPI[host]->cmd.usr); + + // Call the event callback function to send the SPI_DEINIT event + if (spi_object[host]->event_cb) { + spi_object[host]->event_cb(SPI_DEINIT_EVENT, NULL); + } + + if (spi_object[host]->trans_mux) { + vSemaphoreDelete(spi_object[host]->trans_mux); + } + heap_caps_free(spi_object[host]->buf); + spi_object[host]->buf = NULL; + + heap_caps_free(spi_object[host]); + spi_object[host] = NULL; + + return ESP_OK; +} + +esp_err_t spi_init(spi_host_t host, spi_config_t *config) +{ + SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG); + SPI_CHECK(host > CSPI_HOST, "CSPI_HOST can't support now", ESP_FAIL); + SPI_CHECK(NULL == spi_object[host], "spi has been initialized", ESP_FAIL); + + spi_object[host] = (spi_object_t *)heap_caps_malloc(sizeof(spi_object_t), MALLOC_CAP_8BIT); + SPI_CHECK(spi_object[host], "malloc fail", ESP_ERR_NO_MEM); + spi_object[host]->trans_mux = xSemaphoreCreateMutex(); +#ifdef CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT + spi_object[host]->buf = (uint32_t *)heap_caps_malloc(sizeof(uint32_t) * 16, MALLOC_CAP_8BIT); +#else + spi_object[host]->buf = (uint32_t *)heap_caps_malloc(sizeof(uint32_t) * 16, MALLOC_CAP_32BIT); +#endif + if (NULL == spi_object[host]->trans_mux || NULL == spi_object[host]->buf) { + spi_deinit(host); + SPI_CHECK(false, "no memory", ESP_ERR_NO_MEM); + } + uint16_t dummy_bitlen = 0; + spi_set_event_callback(host, &config->event_cb); + spi_set_mode(host, &config->mode); + spi_set_interface(host, &config->interface); + spi_set_clk_div(host, &config->clk_div); + spi_set_dummy(host, &dummy_bitlen); + + spi_set_intr_enable(host, &config->intr_enable); + spi_intr_register(spi_intr, NULL); + spi_intr_enable(); + + if (spi_object[host]->event_cb) { + spi_object[host]->event_cb(SPI_INIT_EVENT, NULL); + } + return ESP_OK; +} diff --git a/components/esp8266/driver/uart.c b/components/esp8266/driver/uart.c index f7d88f985..ae067dd07 100644 --- a/components/esp8266/driver/uart.c +++ b/components/esp8266/driver/uart.c @@ -33,8 +33,7 @@ #include "rom/ets_sys.h" #include "driver/uart.h" - -#define portYIELD_FROM_ISR() taskYIELD() +#include "driver/uart_select.h" #define UART_ENTER_CRITICAL() portENTER_CRITICAL() #define UART_EXIT_CRITICAL() portEXIT_CRITICAL() @@ -78,6 +77,7 @@ typedef struct { // tx parameters SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ int tx_buf_size; /*!< TX ring buffer size */ RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ @@ -86,6 +86,8 @@ typedef struct { uart_tx_data_t *tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ uint32_t tx_len_cur; + bool wait_tx_done_flg; + uart_select_notif_callback_t uart_select_notif_callback; /*!< Notification about select() events */ } uart_obj_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -248,27 +250,74 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flo return ESP_OK; } -static esp_err_t uart_wait_tx_done(uart_port_t uart_num) +esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); - + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG); + uint32_t baudrate; uint32_t byte_delay_us = 0; - uart_get_baudrate(uart_num, &byte_delay_us); - byte_delay_us = (uint32_t)(10000000/byte_delay_us); // (1/baudrate)*10*1000_000 us - - while (1) { - // wait for tx done. - if (UART[uart_num]->status.txfifo_cnt == 0) { - ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion - return ESP_OK; + BaseType_t res; + portTickType ticks_cur; + portTickType ticks_start = xTaskGetTickCount(); + portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + /** + * Considering the overflow of the ticks_end and the ticks_cur (xTaskGetTickCount()), + * the possible tick timestamp is as follows: + * (one start tick timestamp, two end tick timestamps, four current tick timestamps) + * + * ticks: 0 0xFFFFFFFF + * |_______._______._______._______._______._______._______._______| + * cur1 end1 cur2 start cur3 end2 cur4 + */ + + // Take tx_mux + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); + if(res == pdFALSE) { + return ESP_ERR_TIMEOUT; + } + + if(false == p_uart_obj[uart_num]->wait_tx_done_flg) { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; + } + + uart_get_baudrate(uart_num, &baudrate); + byte_delay_us = (uint32_t)(10000000 / baudrate); // (1/baudrate)*10*1000_000 us + + ticks_cur = xTaskGetTickCount(); + if (ticks_start <= ticks_cur) { + ticks_to_wait = ticks_to_wait - (ticks_cur - ticks_start); + } else { + ticks_to_wait = ticks_to_wait - (portMAX_DELAY - ticks_start + ticks_cur); + } + // wait for tx done sem. + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, ticks_to_wait)) { + while (1) { + ticks_cur = xTaskGetTickCount(); + bool end1_timeout = (ticks_end < ticks_start && ticks_cur < ticks_start && ticks_cur > ticks_end); + bool end2_timeout = (ticks_start < ticks_end && (ticks_cur < ticks_start || ticks_end < ticks_cur)); + if (end1_timeout || end2_timeout) { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; + } + if (UART[uart_num]->status.txfifo_cnt == 0) { + ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion + break; + } } + p_uart_obj[uart_num]->wait_tx_done_flg = false; + } else { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; } esp_err_t uart_enable_swap(void) { // wait for tx done. - uart_wait_tx_done(UART_NUM_0); + uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); UART_ENTER_CRITICAL(); // MTCK -> UART0_CTS -> U0RXD @@ -285,7 +334,7 @@ esp_err_t uart_enable_swap(void) esp_err_t uart_disable_swap(void) { // wait for tx done. - uart_wait_tx_done(UART_NUM_0); + uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); UART_ENTER_CRITICAL(); // disable swap U0TXD <-> UART0_RTS and U0RXD <-> UART0_CTS @@ -377,6 +426,7 @@ static void uart_intr_service(void *arg) } do { + uart_intr_status = UART[uart_num]->int_st.val; if (uart_intr_status != 0) { if (uart_isr_func[uart_num].fn != NULL) { uart_isr_func[uart_num].fn(uart_isr_func[uart_num].args); @@ -390,6 +440,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + for (int num = 0; num < UART_NUM_MAX; num++) { + if (p_uart_obj[num] == NULL) { + uart_disable_intr_mask(num, UART_INTR_MASK); + } + } UART_ENTER_CRITICAL(); _xt_isr_mask(1 << ETS_UART_INUM); _xt_isr_attach(ETS_UART_INUM, uart_intr_service, NULL); @@ -475,6 +530,7 @@ static void uart_rx_intr_handler_default(void *param) BaseType_t task_woken = 0; while (uart_intr_status != 0x0) { + uart_select_notif_t notify = UART_SELECT_ERROR_NOTIF; buf_idx = 0; uart_event.type = UART_EVENT_MAX; @@ -557,7 +613,15 @@ static void uart_rx_intr_handler_default(void *param) } if (p_uart->tx_len_tot == 0) { - en_tx_flg = false; + if (tx_fifo_rem == 0) { + en_tx_flg = true; + } else{ + en_tx_flg = false; + } + xSemaphoreGiveFromISR(p_uart->tx_done_sem, &task_woken); + if (task_woken == pdTRUE) { + portYIELD_FROM_ISR(); + } } else { en_tx_flg = true; } @@ -597,6 +661,8 @@ static void uart_rx_intr_handler_default(void *param) p_uart->rx_buffered_len += p_uart->rx_stash_len; } + notify = UART_SELECT_READ_NOTIF; + if (task_woken == pdTRUE) { portYIELD_FROM_ISR(); } @@ -609,15 +675,26 @@ static void uart_rx_intr_handler_default(void *param) uart_reset_rx_fifo(uart_num); uart_reg->int_clr.rxfifo_ovf = 1; uart_event.type = UART_FIFO_OVF; + notify = UART_SELECT_ERROR_NOTIF; } else if (uart_intr_status & UART_FRM_ERR_INT_ST_M) { uart_reg->int_clr.frm_err = 1; uart_event.type = UART_FRAME_ERR; + notify = UART_SELECT_ERROR_NOTIF; } else if (uart_intr_status & UART_PARITY_ERR_INT_ST_M) { uart_reg->int_clr.parity_err = 1; uart_event.type = UART_PARITY_ERR; + notify = UART_SELECT_ERROR_NOTIF; } else { uart_reg->int_clr.val = uart_intr_status; // simply clear all other intr status uart_event.type = UART_EVENT_MAX; + notify = UART_SELECT_ERROR_NOTIF; + } + + if (uart_event.type != UART_EVENT_MAX && p_uart->uart_select_notif_callback) { + p_uart->uart_select_notif_callback(uart_num, notify, &task_woken); + if (task_woken == pdTRUE) { + portYIELD_FROM_ISR(); + } } if (uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) { @@ -676,7 +753,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size) // lock for uart_tx xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); - + p_uart_obj[uart_num]->wait_tx_done_flg = true; if (p_uart_obj[uart_num]->tx_buf_size > 0) { int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); int offset = 0; @@ -709,8 +786,8 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size) } xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); } - uart_wait_tx_done(uart_num); xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return original_size; } @@ -866,7 +943,7 @@ esp_err_t uart_flush_input(uart_port_t uart_num) return ESP_OK; } -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue) +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int no_use) { esp_err_t r; UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); @@ -885,6 +962,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->uart_num = uart_num; p_uart_obj[uart_num]->uart_mode = UART_MODE_UART; p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); + p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); @@ -893,6 +971,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->tx_head = NULL; p_uart_obj[uart_num]->tx_len_tot = 0; p_uart_obj[uart_num]->rx_buffered_len = 0; + p_uart_obj[uart_num]->wait_tx_done_flg = false; if (uart_queue) { p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); @@ -917,6 +996,8 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; } + + p_uart_obj[uart_num]->uart_select_notif_callback = NULL; } else { ESP_LOGE(UART_TAG, "UART driver already installed"); return ESP_FAIL; @@ -970,6 +1051,11 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) p_uart_obj[uart_num]->tx_fifo_sem = NULL; } + if (p_uart_obj[uart_num]->tx_done_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_done_sem = NULL; + } + if (p_uart_obj[uart_num]->tx_mux) { vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); p_uart_obj[uart_num]->tx_mux = NULL; @@ -1001,6 +1087,13 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) return ESP_OK; } +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback) +{ + if (uart_num < UART_NUM_MAX && p_uart_obj[uart_num]) { + p_uart_obj[uart_num]->uart_select_notif_callback = (uart_select_notif_callback_t) uart_select_notif_callback; + } +} + esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); @@ -1020,3 +1113,8 @@ esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh) UART_EXIT_CRITICAL(); return ESP_OK; } + +bool uart_is_driver_installed(uart_port_t uart_num) +{ + return uart_num < UART_NUM_MAX && (p_uart_obj[uart_num] != NULL); +} diff --git a/components/esp8266/include/driver/adc.h b/components/esp8266/include/driver/adc.h new file mode 100644 index 000000000..dbb9fb286 --- /dev/null +++ b/components/esp8266/include/driver/adc.h @@ -0,0 +1,101 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ADC working mode enumeration + */ +typedef enum { + ADC_READ_TOUT_MODE = 0, + ADC_READ_VDD_MODE, + ADC_READ_MAX_MODE +} adc_mode_t; + +/** + * @brief ADC initialization parameter structure type definition + */ +typedef struct { + adc_mode_t mode; /*!< ADC mode */ + uint8_t clk_div; /*!< ADC sample collection clock=80M/clk_div, range[8, 32] */ +} adc_config_t; + +/** + * @brief Single measurement of TOUT(ADC) pin, unit : 1/1023 V or VDD pin, uint: 1 mV + * + * @note When measuring VDD pin voltage, the TOUT(ADC) pin must be left floating. + * + * @param data Pointer to accept adc value. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL adc has not been initialized yet + */ +esp_err_t adc_read(uint16_t *data); + +/** + * @brief Measure the input voltage of TOUT(ADC) pin, unit : 1/1023 V. + * + * @note Wi-Fi and interrupts need to be turned off. + * + * @param data Pointer to accept adc value. Input voltage of TOUT(ADC) pin, unit : 1/1023 V + * @param len Receiving length of ADC value, range [1, 65535] + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL adc has not been initialized yet + */ +esp_err_t adc_read_fast(uint16_t *data, uint16_t len); + +/** + * @brief Deinit the adc + * + * @return + * - ESP_OK Success + * - ESP_FAIL adc has not been initialized yet + */ +esp_err_t adc_deinit(); + +/** + * @brief Initialize the adc + * + * @note First modify menuconfig->Component config->PHY->vdd33_const value, vdd33_const provides ADC mode settings, + * i.e. selecting system voltage or external voltage measurements. + * When measuring system voltage, it must be set to 255. + * To read the external voltage on TOUT(ADC) pin, vdd33_const need less than 255 + * When the ADC reference voltage is set to the actual VDD33 power supply voltage, the value range of vdd33_const is [18,36], the unit is 0.1V. + * When the ADC reference voltage is set to the default value of 3.3V as the supply voltage, the range of vdd33_const is [0, 18] or (36, 255). + * + * @param config Pointer to deliver initialize configuration parameter + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM malloc fail + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL adc has been initialized + */ +esp_err_t adc_init(adc_config_t *config); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/gpio.h b/components/esp8266/include/driver/gpio.h index 8784e57c3..f8fdc366e 100644 --- a/components/esp8266/include/driver/gpio.h +++ b/components/esp8266/include/driver/gpio.h @@ -133,7 +133,7 @@ typedef void *gpio_isr_handle_t; * * Configure GPIO's Mode,pull-up,PullDown,IntrType * - * @param gpio_config Pointer to GPIO configure struct + * @param gpio_cfg Pointer to GPIO configure struct * * @return * - ESP_OK success diff --git a/components/esp8266/include/driver/hspi_logic_layer.h b/components/esp8266/include/driver/hspi_logic_layer.h new file mode 100644 index 000000000..99fd1d993 --- /dev/null +++ b/components/esp8266/include/driver/hspi_logic_layer.h @@ -0,0 +1,88 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" +#include "driver/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Receive SPI data + * + * @param data Data buffer to receive + * @param len Data length + * @param xTicksToWait Ticks to wait until receive data; use portMAX_DELAY to + * never time out. + * @return + * - Actual length received + */ +uint32_t hspi_slave_logic_read_data(uint8_t*data, uint32_t len, TickType_t xTicksToWait); + +/** + * @brief Send SPI data + * + * @param data Data buffer to send + * @param len Data length + * @param xTicksToWait Ticks to wait until send data; use portMAX_DELAY to + * never time out. + * @return + * - Actual length received + */ +uint32_t hspi_slave_logic_write_data(uint8_t*data, uint32_t len, TickType_t xTicksToWait); + +/** + * @brief Create a SPI device to transmit SPI data + * + * @param trigger_pin The pin used for handshake + * @param trigger_level The number of bytes that must be in the stream + * buffer before a task that is blocked on the stream buffer to wait for data is + * moved out of the blocked state. For example, if a task is blocked on a read + * of an empty stream buffer that has a trigger level of 1 then the task will be + * unblocked when a single byte is written to the buffer or the task's block + * time expires. As another example, if a task is blocked on a read of an empty + * stream buffer that has a trigger level of 10 then the task will not be + * unblocked until the stream buffer contains at least 10 bytes or the task's + * block time expires. If a reading task's block time expires before the + * trigger level is reached then the task will still receive however many bytes + * are actually available. Setting a trigger level of 0 will result in a + * trigger level of 1 being used. It is not valid to specify a trigger level + * that is greater than the buffer size. + * @param tx_buffer_size The total number of bytes the send stream buffer will be + * able to hold at any one time. + * @param rx_buffer_size The total number of bytes the receive stream buffer will be + * able to hold at any one time. + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM No memory + */ +esp_err_t hspi_slave_logic_device_create(gpio_num_t trigger_pin, uint32_t trigger_level,uint32_t tx_buffer_size, uint32_t rx_buffer_size); + +/** + * @brief Delete the SPI slave bus + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE SPI slave already deleted + */ +esp_err_t hspi_slave_logic_device_delete(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/hw_timer.h b/components/esp8266/include/driver/hw_timer.h new file mode 100644 index 000000000..a6e328e55 --- /dev/null +++ b/components/esp8266/include/driver/hw_timer.h @@ -0,0 +1,198 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIMER_BASE_CLK APB_CLK_FREQ + +typedef void (*hw_timer_callback_t)(void *arg); + +typedef enum { + TIMER_CLKDIV_1 = 0, + TIMER_CLKDIV_16 = 4, + TIMER_CLKDIV_256 = 8 +} hw_timer_clkdiv_t; + +typedef enum { + TIMER_EDGE_INT = 0, // edge interrupt + TIMER_LEVEL_INT = 1 // level interrupt +} hw_timer_intr_type_t; + +/** + * @brief Set the frequency division coefficient of hardware timer + * + * @param clkdiv frequency division coefficient + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_set_clkdiv(hw_timer_clkdiv_t clkdiv); + +/** + * @brief Get the frequency division coefficient of hardware timer + * + * @return + * - 0 TIMER_CLKDIV_1 + * - 4 TIMER_CLKDIV_16 + * - 8 TIMER_CLKDIV_256 + */ +uint32_t hw_timer_get_clkdiv(); + +/** + * @brief Set the interrupt type of hardware timer + * + * @param intr_type interrupt type + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_set_intr_type(hw_timer_intr_type_t intr_type); + +/** + * @brief Get the interrupt type of hardware timer + * + * @return + * - 0 TIMER_EDGE_INT + * - 1 TIMER_LEVEL_INT + */ +uint32_t hw_timer_get_intr_type(); + +/** + * @brief Enable hardware timer reload + * + * @param reload false, one-shot mode; true, reload mode + * + * @return + * - ESP_OK Success + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_set_reload(bool reload); + +/** + * @brief Get the hardware timer reload status + * + * @return + * - true reload mode + * - false one-shot mode + */ +bool hw_timer_get_reload(); + +/** + * @brief Enable hardware timer + * + * @param en false, hardware timer disable; true, hardware timer enable + * + * @return + * - ESP_OK Success + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_enable(bool en); + +/** + * @brief Get the hardware timer enable status + * + * @return + * - true hardware timer has been enabled + * - false hardware timer is not yet enabled + */ +bool hw_timer_get_enable(); + +/** + * @brief Set the hardware timer load value + * + * @param load_data hardware timer load value + * - FRC1 hardware timer, range : less than 0x1000000 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_set_load_data(uint32_t load_data); + +/** + * @brief Get the hardware timer load value + * + * @return load value + */ +uint32_t hw_timer_get_load_data(); + +/** + * @brief Get the hardware timer count value + * + * @return count value + */ +uint32_t hw_timer_get_count_data(); + +/** + * @brief deinit the hardware timer + * + * @return + * - ESP_OK Success + * - ESP_FAIL hardware timer has not been initialized yet + */ +esp_err_t hw_timer_deinit(void); + +/** + * @brief Initialize the hardware timer + * + * @param callback user hardware timer callback function + * @param arg parameter for ISR handler + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL hardware timer has been initialized + */ +esp_err_t hw_timer_init(hw_timer_callback_t callback, void *arg); + +/** + * @brief Set a trigger timer us delay to enable this timer + * + * @param value + * - If reload is true, range : 50 ~ 0x199999 + * - If reload is false, range : 10 ~ 0x199999 + * @param reload false, one-shot mode; true, reload mode. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL hardware timer has not been initialized yet + */ + +esp_err_t hw_timer_alarm_us(uint32_t value, bool reload); + +/** + * @brief disable this timer + * + * @return + * - ESP_OK Success + * - ESP_FAIL hardware timer has not been initialized yet + */ +esp_err_t hw_timer_disarm(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/i2c.h b/components/esp8266/include/driver/i2c.h index d22961442..d18a07295 100644 --- a/components/esp8266/include/driver/i2c.h +++ b/components/esp8266/include/driver/i2c.h @@ -64,6 +64,7 @@ typedef struct { gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/ gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */ gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/ + uint32_t clk_stretch_tick; /*!< Clock Stretch time, depending on CPU frequency*/ } i2c_config_t; typedef void *i2c_cmd_handle_t; /*!< I2C command handle */ diff --git a/components/esp8266/include/driver/i2s.h b/components/esp8266/include/driver/i2s.h new file mode 100644 index 000000000..3b4e6056d --- /dev/null +++ b/components/esp8266/include/driver/i2s.h @@ -0,0 +1,302 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief I2S bit width per sample. + */ +typedef enum { + I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/ + I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/ + I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/ +} i2s_bits_per_sample_t; + +/** + * @brief I2S channel. + */ +typedef enum { + I2S_CHANNEL_MONO = 1, /*!< I2S 1 channel (mono)*/ + I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/ +} i2s_channel_t; + +/** + * @brief I2S communication standard format + */ +typedef enum { + I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/ + I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/ + I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/ +} i2s_comm_format_t; + +/** + * @brief I2S channel format type + */ +typedef enum { + I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00, + I2S_CHANNEL_FMT_ALL_RIGHT, + I2S_CHANNEL_FMT_ALL_LEFT, + I2S_CHANNEL_FMT_ONLY_RIGHT, + I2S_CHANNEL_FMT_ONLY_LEFT, +} i2s_channel_fmt_t; + +/** + * @brief I2S Peripheral, 0 + */ +typedef enum { + I2S_NUM_0 = 0x0, /*!< I2S 0*/ + I2S_NUM_MAX, +} i2s_port_t; + +/** + * @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX + */ +typedef enum { + I2S_MODE_MASTER = 1, + I2S_MODE_SLAVE = 2, + I2S_MODE_TX = 4, + I2S_MODE_RX = 8, +} i2s_mode_t; + +/** + * @brief I2S configuration parameters for i2s_param_config function + */ +typedef struct { + i2s_mode_t mode; /*!< I2S work mode*/ + int sample_rate; /*!< I2S sample rate*/ + i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/ + i2s_channel_fmt_t channel_format; /*!< I2S channel format */ + i2s_comm_format_t communication_format; /*!< I2S communication format */ + int dma_buf_count; /*!< I2S DMA Buffer Count */ + int dma_buf_len; /*!< I2S DMA Buffer Length */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */ +} i2s_config_t; + +/** + * @brief I2S event types + */ +typedef enum { + I2S_EVENT_DMA_ERROR, + I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/ + I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/ + I2S_EVENT_MAX, /*!< I2S event max index*/ +} i2s_event_type_t; + +/** + * @brief Event structure used in I2S event queue + */ +typedef struct { + i2s_event_type_t type; /*!< I2S event type */ + size_t size; /*!< I2S data size for I2S_DATA event*/ +} i2s_event_t; + +/** + * @brief I2S pin enable for i2s_set_pin + */ +typedef struct { + int bck_o_en; /*!< BCK out pin*/ + int ws_o_en; /*!< WS out pin*/ + int bck_i_en; /*!< BCK in pin*/ + int ws_i_en; /*!< WS in pin*/ + int data_out_en; /*!< DATA out pin*/ + int data_in_en; /*!< DATA in pin*/ +} i2s_pin_config_t; + +/** + * @brief Set I2S pin number + * + * @param i2s_num I2S_NUM_0 + * @param pin I2S Pin structure + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL IO error + */ +esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); + +/** + * @brief Install and start I2S driver. + * + * @note This function must be called before any I2S driver read/write operations. + * + * @param i2s_num I2S_NUM_0 + * @param i2s_config I2S configurations - see i2s_config_t struct + * @param queue_size I2S event queue size/depth. + * @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue); + +/** + * @brief Uninstall I2S driver. + * + * @param i2s_num I2S_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num); + +/** + * @brief Write data to I2S DMA transmit buffer. + * + * @note many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * + * @param i2s_num I2S_NUM_0 + * @param src Source address to write from + * @param size Size of data in bytes + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait); + +/** + * @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM. + * + * @note many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * Format of the data in source buffer is determined by the I2S + * configuration (see i2s_config_t). + * + * @param i2s_num I2S_NUM_0 + * @param src Source address to write from + * @param size Size of data in bytes + * @param src_bits Source audio bit + * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait); + +/** + * @brief Read data from I2S DMA receive buffer + * + * @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process, + * to prevent the data getting corrupted. + * + * @param i2s_num I2S_NUM_0 + * @param dest Destination address to read into + * @param size Size of data in bytes + * @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in. + * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait); + +/** + * @brief Set sample rate used for I2S RX and TX. + * + * @note The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample). + * `bit_clock = rate * (number of channels) * bits_per_sample` + * + * @param i2s_num I2S_NUM_0 + * @param rate I2S sample rate (ex: 8000, 44100...) + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate); + +/** + * @brief Stop I2S driver + * + * @note Disables I2S TX/RX, until i2s_start() is called. + * + * @param i2s_num I2S_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_stop(i2s_port_t i2s_num); + +/** + * @brief Start I2S driver + * + * @note It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop(). + * + * @param i2s_num I2S_NUM_0 + * +* @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_start(i2s_port_t i2s_num); + +/** + * @brief Zero the contents of the TX DMA buffer. + * + * @note Pushes zero-byte samples into the TX DMA buffer, until it is full. + * + * @param i2s_num I2S_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num); + +/** + * @brief Set clock & bit width used for I2S RX and TX. + * + * @note Similar to i2s_set_sample_rates(), but also sets bit width. + * + * @param i2s_num I2S_NUM_0 + * @param rate I2S sample rate (ex: 8000, 44100...) + * @param bits I2S bit width (I2S_BITS_PER_SAMPLE_16BIT, I2S_BITS_PER_SAMPLE_24BIT) + * @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO) + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/ir_rx.h b/components/esp8266/include/driver/ir_rx.h new file mode 100644 index 000000000..7029f4077 --- /dev/null +++ b/components/esp8266/include/driver/ir_rx.h @@ -0,0 +1,108 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Currently only supports infrared NEC code */ +/* NEC time parameter configuration */ +#define IR_RX_NEC_BIT_NUM 8 +#define IR_RX_NEC_HEADER_US 13500 +#define IR_RX_NEC_DATA0_US 1120 +#define IR_RX_NEC_DATA1_US 2250 +#define IR_RX_NEC_TM1_REP_US 20000 +#define IR_RX_NEC_TM2_REP_US 11250 +#define IR_RX_ERROR_US 200 // Used to compensate errors + +/** + * @brief ir rx initialization parameter structure type definition + */ +typedef struct { + uint32_t io_num; + uint32_t buf_len; +} ir_rx_config_t; + +/** + * @brief ir rx nec data union type definition + */ +typedef union { + struct { + uint32_t addr1: 8; + uint32_t addr2: 8; + uint32_t cmd1: 8; + uint32_t cmd2: 8; + }; + uint32_t val; /*!< union fill */ +} ir_rx_nec_data_t; + +/** + * @brief Disable the ir rx + * + * @return + * - ESP_OK Success + * - ESP_FAIL ir rx has not been initialized yet + */ +esp_err_t ir_rx_disable(); + +/** + * @brief Enable the ir rx + * + * @return + * - ESP_OK Success + * - ESP_FAIL ir rx has not been initialized yet + */ +esp_err_t ir_rx_enable(); + +/** + * @brief Receive infrared data + * + * @param data Pointer to the rx data buffer + * @param len Length of ir_rx_data, range: 0 < len < (uint16_t) + * @param timeout_ticks freertos timeout ticks + * + * @return + * - -1 error + * - length The actual length of data received + */ +int ir_rx_recv_data(ir_rx_nec_data_t *data, size_t len, uint32_t timeout_ticks); + +/** + * @brief Deinit the ir rx + * + * @return + * - ESP_OK Success + * - ESP_FAIL ir rx has not been initialized yet + */ +esp_err_t ir_rx_deinit(); + +/** + * @brief Initialize the ir rx + * + * @param config Pointer to deliver initialize configuration parameter + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM malloc fail + * - ESP_FAIL ir rx has been initialized + */ +esp_err_t ir_rx_init(ir_rx_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/driver/ir_tx.h b/components/esp8266/include/driver/ir_tx.h new file mode 100644 index 000000000..287655aa5 --- /dev/null +++ b/components/esp8266/include/driver/ir_tx.h @@ -0,0 +1,106 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Currently only supports infrared NEC code */ +/* NEC time parameter configuration */ +#define IR_TX_NEC_BIT_NUM 8 +#define IR_TX_NEC_HEADER_HIGH_US 9000 +#define IR_TX_NEC_HEADER_LOW_US 4500 +#define IR_TX_NEC_DATA_HIGH_US 560 +#define IR_TX_NEC_DATA_LOW_1_US 1690 +#define IR_TX_NEC_DATA_LOW_0_US 560 +#define IR_TX_NEC_REP_HIGH_US 9000 +#define IR_TX_NEC_REP_LOW_US 2250 +#define IR_TX_NEC_REP_STOP_US 562 +#define IR_TX_NEC_REP_CYCLE 108000 +#define IR_TX_WDEV_TIMER_ERROR_US 5 // Timing in advance to reduce errors +#define IR_TX_HW_TIMER_ERROR_US 40 // Timing in advance to reduce errors + +typedef enum { + IR_TX_WDEV_TIMER, + IR_TX_HW_TIMER, +} ir_tx_timer_t; + +/** + * @brief ir tx initialization parameter structure type definition + */ +typedef struct { + uint32_t io_num; // 2 or 14, 2: I2SO_WS 14: I2SI_WS + uint32_t freq; + ir_tx_timer_t timer; // WDEV timer will be more accurate, but PWM will not work +} ir_tx_config_t; + +/** + * @brief ir tx data union type definition + */ +typedef union { + struct { + uint32_t addr1: 8; + uint32_t addr2: 8; + uint32_t cmd1: 8; + uint32_t cmd2: 8; + }; + uint32_t val; /*!< union fill */ +} ir_tx_nec_data_t; + +/** + * @brief Send ir data + * + * @note If multiple data are identical, repeat signals will be used. + * Infrared data consumes more than 100 ms per transmission, so note the timeout_ticks parameter + * + * @param data Pointer to the tx data buffer + * @param len Length of ir_tx_data, range: 0 < len < (uint16_t) + * @param timeout_ticks freertos timeout ticks + * + * @return + * - -1 error + * - length The actual length of data sent + */ +int ir_tx_send_data(ir_tx_nec_data_t *data, size_t len, uint32_t timeout_ticks); + +/** + * @brief Deinit the ir tx + * + * @return + * - ESP_OK Success + * - ESP_FAIL ir tx has not been initialized yet + */ +esp_err_t ir_tx_deinit(); + +/** + * @brief Initialize the ir tx + * + * @note WDEV timer will be more accurate, but PWM will not work. + * + * @param config Pointer to deliver initialize configuration parameter + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM malloc fail + * - ESP_FAIL ir tx has been initialized + */ +esp_err_t ir_tx_init(ir_tx_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/driver/ledc.h b/components/esp8266/include/driver/ledc.h new file mode 100644 index 000000000..6b44bdca9 --- /dev/null +++ b/components/esp8266/include/driver/ledc.h @@ -0,0 +1,230 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#define PERIPH_LEDC_MODULE (0) +#define LEDC_APB_CLK_HZ (APB_CLK_FREQ) +#define LEDC_REF_CLK_HZ (1*1000000) +#define LEDC_ERR_DUTY (0xFFFFFFFF) +#define LEDC_ERR_VAL (-1) + +typedef enum { + LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */ + LEDC_LOW_SPEED_MODE, /*!< LEDC low speed speed_mode */ + LEDC_SPEED_MODE_MAX, /*!< LEDC speed limit */ +} ledc_mode_t; + +typedef enum { + LEDC_INTR_DISABLE = 0, /*!< Disable LEDC interrupt */ + LEDC_INTR_FADE_END, /*!< Enable LEDC interrupt */ +} ledc_intr_type_t; + +typedef enum { + LEDC_TIMER_0 = 0, /*!< LEDC timer 0 */ + LEDC_TIMER_1, /*!< LEDC timer 1 */ + LEDC_TIMER_2, /*!< LEDC timer 2 */ + LEDC_TIMER_3, /*!< LEDC timer 3 */ + LEDC_TIMER_MAX, +} ledc_timer_t; + +typedef enum { + LEDC_CHANNEL_0 = 0, /*!< LEDC channel 0 */ + LEDC_CHANNEL_1, /*!< LEDC channel 1 */ + LEDC_CHANNEL_2, /*!< LEDC channel 2 */ + LEDC_CHANNEL_3, /*!< LEDC channel 3 */ + LEDC_CHANNEL_4, /*!< LEDC channel 4 */ + LEDC_CHANNEL_5, /*!< LEDC channel 5 */ + LEDC_CHANNEL_6, /*!< LEDC channel 6 */ + LEDC_CHANNEL_7, /*!< LEDC channel 7 */ + LEDC_CHANNEL_MAX, +} ledc_channel_t; + +typedef enum { + LEDC_TIMER_1_BIT = 1, /*!< LEDC PWM duty resolution of 1 bits */ + LEDC_TIMER_2_BIT, /*!< LEDC PWM duty resolution of 2 bits */ + LEDC_TIMER_3_BIT, /*!< LEDC PWM duty resolution of 3 bits */ + LEDC_TIMER_4_BIT, /*!< LEDC PWM duty resolution of 4 bits */ + LEDC_TIMER_5_BIT, /*!< LEDC PWM duty resolution of 5 bits */ + LEDC_TIMER_6_BIT, /*!< LEDC PWM duty resolution of 6 bits */ + LEDC_TIMER_7_BIT, /*!< LEDC PWM duty resolution of 7 bits */ + LEDC_TIMER_8_BIT, /*!< LEDC PWM duty resolution of 8 bits */ + LEDC_TIMER_9_BIT, /*!< LEDC PWM duty resolution of 9 bits */ + LEDC_TIMER_10_BIT, /*!< LEDC PWM duty resolution of 10 bits */ + LEDC_TIMER_11_BIT, /*!< LEDC PWM duty resolution of 11 bits */ + LEDC_TIMER_12_BIT, /*!< LEDC PWM duty resolution of 12 bits */ + LEDC_TIMER_13_BIT, /*!< LEDC PWM duty resolution of 13 bits */ + LEDC_TIMER_14_BIT, /*!< LEDC PWM duty resolution of 14 bits */ + LEDC_TIMER_15_BIT, /*!< LEDC PWM duty resolution of 15 bits */ + LEDC_TIMER_16_BIT, /*!< LEDC PWM duty resolution of 16 bits */ + LEDC_TIMER_17_BIT, /*!< LEDC PWM duty resolution of 17 bits */ + LEDC_TIMER_18_BIT, /*!< LEDC PWM duty resolution of 18 bits */ + LEDC_TIMER_19_BIT, /*!< LEDC PWM duty resolution of 19 bits */ + LEDC_TIMER_20_BIT, /*!< LEDC PWM duty resolution of 20 bits */ + LEDC_TIMER_BIT_MAX, +} ledc_timer_bit_t; + +typedef enum { + LEDC_FADE_NO_WAIT = 0, /*!< LEDC fade function will return immediately */ + LEDC_FADE_WAIT_DONE, /*!< LEDC fade function will block until fading to the target duty */ + LEDC_FADE_MAX, +} ledc_fade_mode_t; + +/** + * @brief Configuration parameters of LEDC Timer timer for ledc_timer_config function + */ +typedef struct { + ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */ + union { + ledc_timer_bit_t duty_resolution; /*!< LEDC channel duty resolution */ + ledc_timer_bit_t bit_num __attribute__((deprecated)); /*!< Deprecated in ESP-IDF 3.0. This is an alias to 'duty_resolution' for backward compatibility with ESP-IDF 2.1 */ + }; + ledc_timer_t timer_num; /*!< The timer source of channel (0 - 3) */ + uint32_t freq_hz; /*!< LEDC timer frequency (100Hz ~ 1KHz) */ +} ledc_timer_config_t; + +/** + * @brief Configuration parameters of LEDC channel for ledc_channel_config function + */ +typedef struct { + int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */ + ledc_mode_t speed_mode; /*!< Invalid parameter, compatible with esp32 API. Configure interrupt, LEDC speed speed_mode, high-speed mode or low-speed mode */ + ledc_channel_t channel; /*!< LEDC channel (0 - 7) */ + ledc_intr_type_t intr_type; /*!< Invalid parameter, compatible with esp32 API. Configure interrupt,Fade interrupt enable or Fade interrupt disable */ + ledc_timer_t timer_sel; /*!< Invalid parameter, compatible with esp32 API. Select the timer source of channel (0 - 3) */ + uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */ + int hpoint; /*!< Invalid parameter, compatible with esp32 API.LEDC channel hpoint value, the max value is 0xfffff */ +} ledc_channel_config_t; + +/** + * @brief set ledc duty + * + * @param speed_mode unnecessary parameters, just for code unity + * @param ledc_channel ledc channel num + * @param ledc_duty set the ledc duty you want + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, uint32_t ledc_duty); + +/** + * @brief update ledc duty + * + * @param speed_mode unnecessary parameters, just for code unity + * @param ledc_channel ledc channel num + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL IO error + */ +esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t ledc_channel); + +/** + * @brief set ledc duty by fade + * + * @param speed_mode unnecessary parameters, just for code unity + * @param ledc_channel ledc channel num + * @param ledc_duty set ledc duty + * @param ledc_fade_time set ledc fade time + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, uint32_t ledc_duty, int ledc_fade_time); + +/** + * @brief start change ledc duty by fade + * @param speed_mode unnecessary parameters, just for code unity + * @param ledc_channel ledc channel num + * @param fade_mode set fade mode, for example set LEDC_FADE_NO_WAIT means LEDC fade function will return immediately + * set LEDC_FADE_WAIT_DONE means LEDC fade function will block until fading to the target duty + * + *@return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL IO error + */ +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t ledc_channel, ledc_fade_mode_t fade_mode); + +/** + * @brief LEDC channel configuration + * Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC duty resolution + * + * @param ledc_conf Pointer of LEDC channel configure struct + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf); + +/** + * @brief LEDC timer configuration + * Configure LEDC timer with the given source timer/frequency(Hz)/duty_resolution + * + * @param timer_conf Pointer of LEDC timer configure struct + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf); + +/** + * @brief Install LEDC fade function. This function will occupy interrupt of LEDC module. + * @param intr_alloc_flags unnecessary parameters, just for code unity, maybe will be used later + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Fade function already installed. + */ +esp_err_t ledc_fade_func_install(int intr_alloc_flags); + +/** + * @brief Uninstall LEDC fade function. + * + */ +esp_err_t ledc_fade_func_uninstall(void); + +/** + * @brief LEDC stop. + * Disable LEDC output, and set idle level + * + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode + * @param channel LEDC channel (0-7), select from ledc_channel_t + * @param idle_level Set output idle level after LEDC stops. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level); + +/** + * it is an empty function + */ +int periph_module_enable(int none); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/pwm.h b/components/esp8266/include/driver/pwm.h index 1387d80b0..75e236a0e 100644 --- a/components/esp8266/include/driver/pwm.h +++ b/components/esp8266/include/driver/pwm.h @@ -27,15 +27,15 @@ extern "C" { * @param period PWM period, unit: us. * e.g. For 1KHz PWM, period is 1000 us. Do not set the period below 20us. * @param duties duty cycle of each channels. - * @param pwm_channel_num PWM channel number, maximum is 8 - * @param pin_mum GPIO number of PWM channel + * @param channel_num PWM channel number, maximum is 8 + * @param pin_num GPIO number of PWM channel * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_FAIL Init error */ -esp_err_t pwm_init(uint32_t period, uint32_t *duties, uint32_t pwm_channel_num, const uint32_t *pin_mum); +esp_err_t pwm_init(uint32_t period, uint32_t *duties, uint8_t channel_num, const uint32_t *pin_num); /** * @brief PWM function uninstall @@ -145,13 +145,13 @@ esp_err_t pwm_set_duties(uint32_t *duties); * * @param channel_num PWM channel number * the channel_num cannot exceed the value initialized by pwm_init. - * @param phase The phase of this PWM channel, the phase range is (-180 ~ 180). + * @param phase The phase of this PWM channel, the phase range is (-180 ~ 180]. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase); +esp_err_t pwm_set_phase(uint8_t channel_num, float phase); /** * @brief Set the phase of all channels. @@ -164,7 +164,7 @@ esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_set_phases(int16_t *phases); +esp_err_t pwm_set_phases(float *phases); /** * @brief Get the phase of a PWM channel. @@ -177,7 +177,7 @@ esp_err_t pwm_set_phases(int16_t *phases); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p); +esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p); /** * @brief Set PWM period and duty of each PWM channel. @@ -224,4 +224,4 @@ esp_err_t pwm_clear_channel_invert(uint16_t channel_mask); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/components/esp8266/include/driver/rtc.h b/components/esp8266/include/driver/rtc.h new file mode 100644 index 000000000..504b348f8 --- /dev/null +++ b/components/esp8266/include/driver/rtc.h @@ -0,0 +1,147 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wakeup option + */ +#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup (light sleep only) +#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup + +/** + * @brief CPU frequency values + */ +typedef enum { + RTC_CPU_FREQ_80M = 0, //!< 80 MHz + RTC_CPU_FREQ_160M = 1, //!< 160 MHz +} rtc_cpu_freq_t; + +/** + * @brief Open RF hardware + */ +void phy_open_rf(void); + +/** + * @brief Close RF hardware + */ +void phy_close_rf(void); + +/** + * @brief Initialize RTC hardware + */ +void rtc_init_clk(uint8_t *init_param); + +/** + * @brief Initialize light sleep hardware + */ +void rtc_lightsleep_init(void); + +/** + * @brief Configure CPU sleep mode + */ +void pm_set_sleep_mode(uint32_t mode); + +/** + * @brief Initialize hardware when CPU wakes up from light sleep + */ +void rtc_wakeup_init(void); + +/** + * @brief Get the currently used CPU frequency configuration + * + * @return CPU frequency + */ +rtc_cpu_freq_t rtc_clk_cpu_freq_get(void); + +/** + * @brief Switch CPU frequency + * + * This function sets CPU frequency according to the given configuration + * structure. It enables PLLs, if necessary. + * + * @note This function in not intended to be called by applications in FreeRTOS + * environment. This is because it does not adjust various timers based on the + * new CPU frequency. + * + * @param cpu_freq CPU frequency + */ +void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq); + +/** + * @brief Enter light sleep mode + * + * @note CPU wakeup has 2672 ms time cost, so the real sleeping time is to_sleep_time_in_us - 2672 + * + * @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags + * combined with OR) + * @param reject_opt bit mask of sleep reject reasons: + * - RTC_CNTL_GPIO_REJECT_EN + * - RTC_CNTL_SDIO_REJECT_EN + * These flags are used to prevent entering sleep when e.g. + * an external host is communicating via SDIO slave + * @return non-zero if sleep was rejected by hardware + */ +uint32_t rtc_light_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt); +/** + * @brief Convert time interval from microseconds to RTC_CLK cycles + * + * @param time_in_us Time interval in microseconds + * @param period Period of clock in microseconds (as returned by esp_clk_cal_get) + * + * @return number of clock cycles + */ +uint32_t us_to_rtc_clk(uint32_t time_in_us, uint32_t period); + +/** + * @brief Convert time interval from RTC_CLK to microseconds + * + * @param rtc_cycles Time interval in RTC_CLK cycles + * @param period Period of clock in microseconds (as returned by esp_clk_cal_get) + * + * @return time interval in microseconds + */ +uint32_t rtc_clk_to_us(uint32_t rtc_cycles, uint32_t period); + +/** + * @brief Get the calibration value of RTC clock + * + * @return the calibration value + */ +uint32_t pm_rtc_clock_cali_proc(); + +/** + * @brief Configure CPU sleep time by RTC clock ticks + * + * @param rtc_cycles Time interval in RTC_CLK cycles + */ +void pm_set_sleep_cycles(uint32_t rtc_cycles); + +/** + * @brief Get current value of RTC counter + * + * @return current value of RTC counter + */ +uint32_t rtc_time_get(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/driver/sdmmc_types.h b/components/esp8266/include/driver/sdmmc_types.h new file mode 100644 index 000000000..1673bb5f2 --- /dev/null +++ b/components/esp8266/include/driver/sdmmc_types.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2006 Uwe Stuehler + * Adaptations to ESP-IDF Copyright (c) 2016 Espressif Systems (Shanghai) PTE LTD + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SDMMC_TYPES_H_ +#define _SDMMC_TYPES_H_ + +#include +#include +#include "esp_err.h" +#include "freertos/FreeRTOS.h" + +/** + * Decoded values from SD card Card Specific Data register + */ +typedef struct { + int csd_ver; /*!< CSD structure format */ + int mmc_ver; /*!< MMC version (for CID format) */ + int capacity; /*!< total number of sectors */ + int sector_size; /*!< sector size in bytes */ + int read_block_len; /*!< block length for reads */ + int card_command_class; /*!< Card Command Class for SD */ + int tr_speed; /*!< Max transfer speed */ +} sdmmc_csd_t; + +/** + * Decoded values from SD card Card IDentification register + */ +typedef struct { + int mfg_id; /*!< manufacturer identification number */ + int oem_id; /*!< OEM/product identification number */ + char name[8]; /*!< product name (MMC v1 has the longest) */ + int revision; /*!< product revision */ + int serial; /*!< product serial number */ + int date; /*!< manufacturing date */ +} sdmmc_cid_t; + +/** + * Decoded values from SD Configuration Register + */ +typedef struct { + int sd_spec; /*!< SD Physical layer specification version, reported by card */ + int bus_width; /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */ +} sdmmc_scr_t; + +/** + * Decoded values of Extended Card Specific Data + */ +typedef struct { + uint8_t power_class; /*!< Power class used by the card */ +} sdmmc_ext_csd_t; + +/** + * SD/MMC command response buffer + */ +typedef uint32_t sdmmc_response_t[4]; + +/** + * SD SWITCH_FUNC response buffer + */ +typedef struct { + uint32_t data[512 / 8 / sizeof(uint32_t)]; /*!< response data */ +} sdmmc_switch_func_rsp_t; + +/** + * SD/MMC command information + */ +typedef struct { + uint32_t opcode; /*!< SD or MMC command index */ + uint32_t arg; /*!< SD/MMC command argument */ + sdmmc_response_t response; /*!< response buffer */ + void* data; /*!< buffer to send or read into */ + size_t datalen; /*!< length of data buffer */ + size_t blklen; /*!< block length */ + int flags; /*!< see below */ +/** @cond */ +#define SCF_ITSDONE 0x0001 /*!< command is complete */ +#define SCF_CMD(flags) ((flags) & 0x00f0) +#define SCF_CMD_AC 0x0000 +#define SCF_CMD_ADTC 0x0010 +#define SCF_CMD_BC 0x0020 +#define SCF_CMD_BCR 0x0030 +#define SCF_CMD_READ 0x0040 /*!< read command (data expected) */ +#define SCF_RSP_BSY 0x0100 +#define SCF_RSP_136 0x0200 +#define SCF_RSP_CRC 0x0400 +#define SCF_RSP_IDX 0x0800 +#define SCF_RSP_PRESENT 0x1000 +/* response types */ +#define SCF_RSP_R0 0 /*!< none */ +#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY) +#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136) +#define SCF_RSP_R3 (SCF_RSP_PRESENT) +#define SCF_RSP_R4 (SCF_RSP_PRESENT) +#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY) +#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +/* special flags */ +#define SCF_WAIT_BUSY 0x2000 /*!< Wait for completion of card busy signal before returning */ +/** @endcond */ + esp_err_t error; /*!< error returned from transfer */ + int timeout_ms; /*!< response timeout, in milliseconds */ +} sdmmc_command_t; + +/** + * SD/MMC Host description + * + * This structure defines properties of SD/MMC host and functions + * of SD/MMC host which can be used by upper layers. + */ +typedef struct { + uint32_t flags; /*!< flags defining host properties */ +#define SDMMC_HOST_FLAG_1BIT BIT(0) /*!< host supports 1-line SD and MMC protocol */ +#define SDMMC_HOST_FLAG_4BIT BIT(1) /*!< host supports 4-line SD and MMC protocol */ +#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */ +#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */ +#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */ + int slot; /*!< slot number, to be passed to host functions */ + int max_freq_khz; /*!< max frequency supported by the host */ +#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */ +#define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */ +#define SDMMC_FREQ_PROBING 400 /*!< SD/MMC probing speed */ +#define SDMMC_FREQ_52M 52000 /*!< MMC 52MHz speed */ +#define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */ + float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */ + esp_err_t (*init)(void); /*!< Host function to initialize the driver */ + esp_err_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */ + size_t (*get_bus_width)(int slot); /*!< host function to get bus width */ + esp_err_t (*set_bus_ddr_mode)(int slot, bool ddr_enable); /*!< host function to set DDR mode */ + esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */ + esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */ + esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */ + esp_err_t (*io_int_enable)(int slot); /*!< Host function to enable SDIO interrupt line */ + esp_err_t (*io_int_wait)(int slot, TickType_t timeout_ticks); /*!< Host function to wait for SDIO interrupt line to be active */ + int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */ +} sdmmc_host_t; + +/** + * SD/MMC card information structure + */ +typedef struct { + sdmmc_host_t host; /*!< Host with which the card is associated */ + uint32_t ocr; /*!< OCR (Operation Conditions Register) value */ + union { + sdmmc_cid_t cid; /*!< decoded CID (Card IDentification) register value */ + sdmmc_response_t raw_cid; /*!< raw CID of MMC card to be decoded + after the CSD is fetched in the data transfer mode*/ + }; + sdmmc_csd_t csd; /*!< decoded CSD (Card-Specific Data) register value */ + sdmmc_scr_t scr; /*!< decoded SCR (SD card Configuration Register) value */ + sdmmc_ext_csd_t ext_csd; /*!< decoded EXT_CSD (Extended Card Specific Data) register value */ + uint16_t rca; /*!< RCA (Relative Card Address) */ + uint16_t max_freq_khz; /*!< Maximum frequency, in kHz, supported by the card */ + uint32_t is_mem : 1; /*!< Bit indicates if the card is a memory card */ + uint32_t is_sdio : 1; /*!< Bit indicates if the card is an IO card */ + uint32_t is_mmc : 1; /*!< Bit indicates if the card is MMC */ + uint32_t num_io_functions : 3; /*!< If is_sdio is 1, contains the number of IO functions on the card */ + uint32_t log_bus_width : 2; /*!< log2(bus width supported by card) */ + uint32_t is_ddr : 1; /*!< Card supports DDR mode */ + uint32_t reserved : 23; /*!< Reserved for future expansion */ +} sdmmc_card_t; + + +#endif // _SDMMC_TYPES_H_ diff --git a/components/esp8266/include/driver/sdspi_host.h b/components/esp8266/include/driver/sdspi_host.h new file mode 100644 index 000000000..56400252e --- /dev/null +++ b/components/esp8266/include/driver/sdspi_host.h @@ -0,0 +1,186 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include "esp_err.h" +#include "sdmmc_types.h" +#include "driver/gpio.h" +// #include "driver/spi_master.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Default sdmmc_host_t structure initializer for SD over SPI driver + * + * Uses SPI mode and max frequency set to 20MHz + * + * 'slot' can be set to one of HSPI_HOST, VSPI_HOST. + */ +/*#define SDSPI_HOST_DEFAULT() {\ + .flags = SDMMC_HOST_FLAG_SPI, \ + .slot = HSPI_HOST, \ + .max_freq_khz = SDMMC_FREQ_DEFAULT, \ + .io_voltage = 3.3f, \ + .init = &sdspi_host_init, \ + .set_bus_width = NULL, \ + .get_bus_width = NULL, \ + .set_bus_ddr_mode = NULL, \ + .set_card_clk = &sdspi_host_set_card_clk, \ + .do_transaction = &sdspi_host_do_transaction, \ + .deinit = &sdspi_host_deinit, \ + .io_int_enable = &sdspi_host_io_int_enable, \ + .io_int_wait = &sdspi_host_io_int_wait, \ + .command_timeout_ms = 0, \ +}*/ + +/** + * Extra configuration for SPI host + */ +typedef struct { + gpio_num_t gpio_miso; ///< GPIO number of MISO signal + gpio_num_t gpio_mosi; ///< GPIO number of MOSI signal + gpio_num_t gpio_sck; ///< GPIO number of SCK signal + gpio_num_t gpio_cs; ///< GPIO number of CS signal + gpio_num_t gpio_cd; ///< GPIO number of card detect signal + gpio_num_t gpio_wp; ///< GPIO number of write protect signal + gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card. + int dma_channel; ///< DMA channel to be used by SPI driver (1 or 2) +} sdspi_slot_config_t; + +#define SDSPI_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used +#define SDSPI_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used +#define SDSPI_SLOT_NO_INT GPIO_NUM_NC ///< indicates that interrupt line is not used + +/** + * Macro defining default configuration of SPI host + */ +#define SDSPI_SLOT_CONFIG_DEFAULT() {\ + .gpio_miso = GPIO_NUM_2, \ + .gpio_mosi = GPIO_NUM_15, \ + .gpio_sck = GPIO_NUM_14, \ + .gpio_cs = GPIO_NUM_13, \ + .gpio_cd = SDSPI_SLOT_NO_CD, \ + .gpio_wp = SDSPI_SLOT_NO_WP, \ + .gpio_int = GPIO_NUM_NC, \ + .dma_channel = 1 \ +} + +/** + * @brief Initialize SD SPI driver + * + * @note This function is not thread safe + * + * @return + * - ESP_OK on success + * - other error codes may be returned in future versions + */ +esp_err_t sdspi_host_init(void); + +/** +* @brief Initialize SD SPI driver for the specific SPI controller +* +* @note This function is not thread safe +* +* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function. +* +* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST) +* @param slot_config pointer to slot configuration structure +* +* @return +* - ESP_OK on success +* - ESP_ERR_INVALID_ARG if sdspi_init_slot has invalid arguments +* - ESP_ERR_NO_MEM if memory can not be allocated +* - other errors from the underlying spi_master and gpio drivers +*/ +esp_err_t sdspi_host_init_slot(int slot, const sdspi_slot_config_t* slot_config); + +/** + * @brief Send command to the card and get response + * + * This function returns when command is sent and response is received, + * or data is transferred, or timeout occurs. + * + * @note This function is not thread safe w.r.t. init/deinit functions, + * and bus width/clock speed configuration functions. Multiple tasks + * can call sdspi_host_do_transaction as long as other sdspi_host_* + * functions are not called. + * + * @param slot SPI controller (HSPI_HOST or VSPI_HOST) + * @param cmdinfo pointer to structure describing command and data to transfer + * @return + * - ESP_OK on success + * - ESP_ERR_TIMEOUT if response or data transfer has timed out + * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed + * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response + */ +esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo); + +/** + * @brief Set card clock frequency + * + * Currently only integer fractions of 40MHz clock can be used. + * For High Speed cards, 40MHz can be used. + * For Default Speed cards, 20MHz can be used. + * + * @note This function is not thread safe + * + * @param slot SPI controller (HSPI_HOST or VSPI_HOST) + * @param freq_khz card clock frequency, in kHz + * @return + * - ESP_OK on success + * - other error codes may be returned in the future + */ +esp_err_t sdspi_host_set_card_clk(int slot, uint32_t freq_khz); + + +/** + * @brief Release resources allocated using sdspi_host_init + * + * @note This function is not thread safe + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called + */ +esp_err_t sdspi_host_deinit(void); + +/** + * @brief Enable SDIO interrupt. + * + * @param slot SPI controller to use (HSPI_HOST or VSPI_HOST) + * + * @return + * - ESP_OK on success + */ +esp_err_t sdspi_host_io_int_enable(int slot); + +/** + * @brief Wait for SDIO interrupt until timeout. + * + * @param slot SPI controller to use (HSPI_HOST or VSPI_HOST) + * @param timeout_ticks Ticks to wait before timeout. + * + * @return + * - ESP_OK on success + */ +esp_err_t sdspi_host_io_int_wait(int slot, TickType_t timeout_ticks); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/driver/soc.h b/components/esp8266/include/driver/soc.h new file mode 100644 index 000000000..894f64e95 --- /dev/null +++ b/components/esp8266/include/driver/soc.h @@ -0,0 +1,158 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ETS_INT_MASK 0x00003FFF +#define ESP_TICKS_MAX UINT32_MAX + +typedef uint32_t esp_tick_t; +typedef uint32_t esp_irqflag_t; + +static inline esp_irqflag_t soc_save_local_irq(void) +{ + esp_irqflag_t flag; + + __asm__ __volatile__( +#ifdef BOOTLOADER_BUILD + "rsil %0, 3\n" +#else + "rsil %0, 1\n" +#endif + : "=a"(flag) + : + : "memory" + ); + + return flag; +} + +static inline void soc_restore_local_irq(esp_irqflag_t flag) +{ + __asm__ __volatile__( + "wsr %0, ps\n" + : + : "a"(flag) + : "memory" + ); +} + +static inline void soc_set_ccompare(uint32_t ticks) +{ + __asm__ __volatile__( + "wsr %0, ccompare0\n" + : + : "a"(ticks) + : "memory" + ); +} + +static inline uint32_t soc_get_ccompare(void) +{ + uint32_t ticks; + + __asm__ __volatile__( + "rsr %0, ccompare0\n" + : "=a"(ticks) + : + : "memory" + ); + + return ticks; +} + +static inline uint32_t soc_get_ccount(void) +{ + uint32_t ticks; + + __asm__ __volatile__( + "rsr %0, ccount\n" + : "=a"(ticks) + : + : "memory" + ); + + return ticks; +} + +static inline void soc_set_ccount(uint32_t ticks) +{ + __asm__ __volatile__( + "wsr %0, ccount\n" + : + : "a"(ticks) + : "memory" + ); +} + +static inline void soc_clear_int_mask(uint32_t mask) +{ + __asm__ __volatile__( + "wsr %0, intclear\n" + : + : "a"(mask) + : "memory" + ); +} + +static inline uint32_t soc_get_int_mask(void) +{ + uint32_t mask, enable; + + __asm__ __volatile__( + "rsr %0, interrupt\n" + "rsr %1, intenable\n" + "rsync\n" + : "=a"(mask), "=a"(enable) + : + : "memory" + ); + + return mask & enable & ETS_INT_MASK; +} + +static inline void soc_wait_int(void) +{ + __asm__ __volatile__( + "waiti 0\n" + : + : + : "memory" + ); +} + +static inline uint32_t soc_debug_reason(void) +{ + uint32_t tmp; + + __asm__ __volatile__( + "movi %0, 0\n" + "wsr %0, dbreakc0\n" + "rsr.debugcause %0\n" + : "=r"(tmp) + : + : "memory"); + + return tmp; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/driver/spi.h b/components/esp8266/include/driver/spi.h new file mode 100644 index 000000000..b902caa71 --- /dev/null +++ b/components/esp8266/include/driver/spi.h @@ -0,0 +1,448 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPI_NUM_MAX 2 + +/* SPI bus CPOL and CPHA definition */ +#define SPI_CPOL_LOW 0 +#define SPI_CPOL_HIGH 1 +#define SPI_CPHA_LOW 0 +#define SPI_CPHA_HIGH 1 + +/* SPI bus data sequence definition */ +#define SPI_BIT_ORDER_MSB_FIRST 1 +#define SPI_BIT_ORDER_LSB_FIRST 0 +#define SPI_BYTE_ORDER_MSB_FIRST 1 +#define SPI_BYTE_ORDER_LSB_FIRST 0 + +/* SPI default bus interface parameter definition */ +#define SPI_DEFAULT_INTERFACE 0x1C0 /* CS_EN:1, MISO_EN:1, MOSI_EN:1, BYTE_TX_ORDER:0, BYTE_TX_ORDER:0, BIT_RX_ORDER:0, BIT_TX_ORDER:0, CPHA:0, CPOL:0 */ + +/* SPI master default interrupt enable definition */ +#define SPI_MASTER_DEFAULT_INTR_ENABLE 0x10 /* TRANS_DONE: true, WRITE_STATUS: false, READ_STATUS: false, WRITE_BUFFER: false, READ_BUFFER: false */ + +/* SPI slave default interrupt enable definition */ +#define SPI_SLAVE_DEFAULT_INTR_ENABLE 0x0F /* TRANS_DONE: false, WRITE_STATUS: true, READ_STATUS: true, WRITE_BUFFER: true, READ_BUFFER: ture */ + +/* SPI event definition */ +#define SPI_INIT_EVENT 0 +#define SPI_TRANS_START_EVENT 1 +#define SPI_TRANS_DONE_EVENT 2 +#define SPI_DEINIT_EVENT 3 + +/* SPI data cmd definition */ +#define SPI_MASTER_WRITE_DATA_TO_SLAVE_CMD 2 +#define SPI_MASTER_READ_DATA_FROM_SLAVE_CMD 3 + +/* SPI status cmd definition */ +#define SPI_MASTER_WRITE_STATUS_TO_SLAVE_CMD 1 +#define SPI_MASTER_READ_STATUS_FROM_SLAVE_CMD 4 + +/* SPI slave transfer done interrupt status definition */ +#define SPI_SLV_RD_BUF_DONE (BIT(0)) +#define SPI_SLV_WR_BUF_DONE (BIT(1)) +#define SPI_SLV_RD_STA_DONE (BIT(2)) +#define SPI_SLV_WR_STA_DONE (BIT(3)) +#define SPI_TRANS_DONE (BIT(4)) + +typedef void (*spi_event_callback_t)(int event, void *arg); + +/** + * @brief SPI peripheral enumeration + * + * @note ESP8266 has two hardware SPI, CSPI and HSPI. Currently, HSPI can be used arbitrarily. + */ +typedef enum { + CSPI_HOST = 0, + HSPI_HOST +} spi_host_t; + +/** + * @brief SPI clock division factor enumeration + */ +typedef enum { + SPI_2MHz_DIV = 40, + SPI_4MHz_DIV = 20, + SPI_5MHz_DIV = 16, + SPI_8MHz_DIV = 10, + SPI_10MHz_DIV = 8, + SPI_16MHz_DIV = 5, + SPI_20MHz_DIV = 4, + SPI_40MHz_DIV = 2, + SPI_80MHz_DIV = 1, +} spi_clk_div_t; + +/** + * @brief SPI working mode enumeration + */ +typedef enum { + SPI_MASTER_MODE, + SPI_SLAVE_MODE +} spi_mode_t; + +/** + * @brief SPI interrupt enable union type definition + */ +typedef union { + struct { + uint32_t read_buffer: 1; /*!< configurate intterrupt to enable reading */ + uint32_t write_buffer: 1; /*!< configurate intterrupt to enable writing */ + uint32_t read_status: 1; /*!< configurate intterrupt to enable reading status */ + uint32_t write_status: 1; /*!< configurate intterrupt to enable writing status */ + uint32_t trans_done: 1; /*!< configurate intterrupt to enable transmission done */ + uint32_t reserved5: 27; /*!< reserved */ + }; /*!< not filled */ + uint32_t val; /*!< union fill */ +} spi_intr_enable_t; + +/** + * @brief SPI bus interface parameter union type definition + */ +typedef union { + struct { + uint32_t cpol: 1; /*!< Clock Polarity */ + uint32_t cpha: 1; /*!< Clock Phase */ + uint32_t bit_tx_order: 1; /*!< Tx bit order */ + uint32_t bit_rx_order: 1; /*!< Rx bit order */ + uint32_t byte_tx_order: 1; /*!< Tx byte order */ + uint32_t byte_rx_order: 1; /*!< Rx byte order */ + uint32_t mosi_en: 1; /*!< MOSI line enable */ + uint32_t miso_en: 1; /*!< MISO line enable */ + uint32_t cs_en: 1; /*!< CS line enable */ + uint32_t reserved9: 23; /*!< resserved */ + }; /*!< not filled */ + uint32_t val; /*!< union fill */ +} spi_interface_t; + +/** + * @brief SPI transmission parameter structure type definition + */ +typedef struct { + uint16_t *cmd; /*!< SPI transmission command */ + uint32_t *addr; /*!< SPI transmission address */ + uint32_t *mosi; /*!< SPI transmission MOSI buffer, in order to improve the transmission efficiency, it is recommended that the external incoming data is (uint32_t *) type data, do not use other type data. */ + uint32_t *miso; /*!< SPI transmission MISO buffer, in order to improve the transmission efficiency, it is recommended that the external incoming data is (uint32_t *) type data, do not use other type data. */ + union { + struct { + uint32_t cmd: 5; /*!< SPI transmission command bits */ + uint32_t addr: 7; /*!< SPI transmission address bits */ + uint32_t mosi: 10; /*!< SPI transmission MOSI buffer bits */ + uint32_t miso: 10; /*!< SPI transmission MISO buffer bits */ + }; /*!< not filled */ + uint32_t val; /*!< union fill */ + } bits; /*!< SPI transmission packet members' bits */ +} spi_trans_t; + +/** + * @brief SPI initialization parameter structure type definition + */ +typedef struct { + spi_interface_t interface; /*!< SPI bus interface */ + spi_intr_enable_t intr_enable; /*!< check if enable SPI interrupt */ + spi_event_callback_t event_cb; /*!< SPI interrupt event callback */ + spi_mode_t mode; /*!< SPI mode */ + spi_clk_div_t clk_div; /*!< SPI clock divider */ +} spi_config_t; + +/** + * @brief Get the SPI clock division factor + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param clk_div Pointer to accept clock division factor + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_clk_div(spi_host_t host, spi_clk_div_t *clk_div); + +/** + * @brief Get SPI Interrupt Enable + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param intr_enable Pointer to accept interrupt enable + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable); + +/** + * @brief Get SPI working mode + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param mode Pointer to accept working mode + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_mode(spi_host_t host, spi_mode_t *mode); + +/** + * @brief Get SPI bus interface configuration + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param interface Pointer to accept bus interface configuration + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_interface(spi_host_t host, spi_interface_t *interface); + +/** + * @brief Get the SPI event callback function + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param event_cb Pointer to accept event callback function + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_event_callback(spi_host_t host, spi_event_callback_t *event_cb); + +/** + * @brief Set the SPI clock division factor + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param clk_div Pointer to deliver clock division factor + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_clk_div(spi_host_t host, spi_clk_div_t *clk_div); + +/** + * @brief Set SPI interrupt enable + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param intr_enable Pointer to deliver interrupt enable + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable); + +/** + * @brief Set the SPI mode of operation + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param mode Pointer to deliver working mode + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_mode(spi_host_t host, spi_mode_t *mode); + +/** + * @brief Get SPI dummy bitlen + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param bitlen Pointer to accept dummy bitlen + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_get_dummy(spi_host_t host, uint16_t *bitlen); + +/** + * @brief Set SPI dummy bitlen + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param bitlen Pointer to deliver dummy bitlen + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_dummy(spi_host_t host, uint16_t *bitlen); + +/** + * @brief Set SPI bus interface configuration + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param interface Pointer to deliver bus interface configuration + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_interface(spi_host_t host, spi_interface_t *interface); + +/** + * @brief Set the SPI event callback function + * + * @note This event_cb will be called from an ISR. So there is a stack + * size limit (configurable as "ISR stack size" in menuconfig). This + * limit is smaller compared to a global SPI interrupt handler due + * to the additional level of indirection. + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param event_cb Pointer to deliver event callback function + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_set_event_callback(spi_host_t host, spi_event_callback_t *event_cb); + +/** + * @brief Get SPI slave wr_status register + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param status Pointer to accept wr_status register + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_slave_get_status(spi_host_t host, uint32_t *status); + +/** + * @brief Set SPI slave rd_status register + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param status Pointer to deliver rd_status register + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_slave_set_status(spi_host_t host, uint32_t *status); + +/** + * @brief SPI data transfer function + * + * @note If the bit of the corresponding phase in the transmission parameter is 0, its data will not work. + * For example: trans.bits.cmd = 0, cmd will not be transmitted + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param trans Pointer to transmission parameter structure + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_trans(spi_host_t host, spi_trans_t *trans); + +/** + * @brief Deinit the spi + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @return + * - ESP_OK Success + * - ESP_FAIL spi has not been initialized yet + */ +esp_err_t spi_deinit(spi_host_t host); + +/** + * @brief Initialize the spi + * + * @note SPI0 has been used by FLASH and cannot be used by the user temporarily. + * + * @param host SPI peripheral number + * - CSPI_HOST SPI0 + * - HSPI_HOST SPI1 + * + * @param config Pointer to deliver initialize configuration parameter + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM malloc fail + * - ESP_FAIL spi has been initialized + */ +esp_err_t spi_init(spi_host_t host, spi_config_t *config); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/esp8266/include/driver/spi_register.h b/components/esp8266/include/driver/spi_register.h deleted file mode 100644 index 9591c382d..000000000 --- a/components/esp8266/include/driver/spi_register.h +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SPI_REGISTER_H_INCLUDED -#define SPI_REGISTER_H_INCLUDED - -#include "esp8266/eagle_soc.h" - -#define REG_SPI_BASE(i) (0x60000200-i*0x100) -#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) - -#define SPI_FLASH_READ BIT31 -#define SPI_FLASH_WREN BIT30 -#define SPI_FLASH_WRDI BIT29 -#define SPI_FLASH_RDID BIT28 -#define SPI_FLASH_RDSR BIT27 -#define SPI_FLASH_WRSR BIT26 -#define SPI_FLASH_PP BIT25 -#define SPI_FLASH_SE BIT24 -#define SPI_FLASH_BE BIT23 -#define SPI_FLASH_CE BIT22 -#define SPI_FLASH_RES BIT20 - -#define SPI_USR (BIT(18)) - -#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) - -#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) -#define SPI_WR_BIT_ORDER (BIT(26)) -#define SPI_RD_BIT_ORDER (BIT(25)) -#define SPI_QIO_MODE (BIT(24)) -#define SPI_DIO_MODE (BIT(23)) -#define SPI_QOUT_MODE (BIT(20)) -#define SPI_DOUT_MODE (BIT(14)) -#define SPI_FASTRD_MODE (BIT(13)) - -#define SPI_CTRL1(i) (REG_SPI_BASE(i) + 0xc) -#define SPI_CS_HOLD_DELAY 0xf -#define SPI_CS_HOLD_DELAY_S 28 -#define SPI_CS_HOLD_DELAY_RES 0xfff -#define SPI_CS_HOLD_DELAY_RES_S 16 - - -#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) - -#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) - -#define SPI_CS_DELAY_NUM 0x0000000F -#define SPI_CS_DELAY_NUM_S 28 -#define SPI_CS_DELAY_MODE 0x00000003 -#define SPI_CS_DELAY_MODE_S 26 -#define SPI_MOSI_DELAY_NUM 0x00000007 -#define SPI_MOSI_DELAY_NUM_S 23 -#define SPI_MOSI_DELAY_MODE 0x00000003 -#define SPI_MOSI_DELAY_MODE_S 21 -#define SPI_MISO_DELAY_NUM 0x00000007 -#define SPI_MISO_DELAY_NUM_S 18 -#define SPI_MISO_DELAY_MODE 0x00000003 -#define SPI_MISO_DELAY_MODE_S 16 -#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) -#define SPI_CLK_EQU_SYSCLK (BIT(31)) -#define SPI_CLKDIV_PRE 0x00001FFF -#define SPI_CLKDIV_PRE_S 18 -#define SPI_CLKCNT_N 0x0000003F -#define SPI_CLKCNT_N_S 12 -#define SPI_CLKCNT_H 0x0000003F -#define SPI_CLKCNT_H_S 6 -#define SPI_CLKCNT_L 0x0000003F -#define SPI_CLKCNT_L_S 0 - -#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) -#define SPI_USR_COMMAND (BIT(31)) -#define SPI_USR_ADDR (BIT(30)) -#define SPI_USR_DUMMY (BIT(29)) -#define SPI_USR_MISO (BIT(28)) -#define SPI_USR_MOSI (BIT(27)) - -#define SPI_USR_MOSI_HIGHPART (BIT(25)) -#define SPI_USR_MISO_HIGHPART (BIT(24)) - - -#define SPI_SIO (BIT(16)) -#define SPI_FWRITE_QIO (BIT(15)) -#define SPI_FWRITE_DIO (BIT(14)) -#define SPI_FWRITE_QUAD (BIT(13)) -#define SPI_FWRITE_DUAL (BIT(12)) -#define SPI_WR_BYTE_ORDER (BIT(11)) -#define SPI_RD_BYTE_ORDER (BIT(10)) -#define SPI_CK_OUT_EDGE (BIT(7)) -#define SPI_CK_I_EDGE (BIT(6)) -#define SPI_CS_SETUP (BIT(5)) -#define SPI_CS_HOLD (BIT(4)) -#define SPI_FLASH_MODE (BIT(2)) - -#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) -#define SPI_USR_ADDR_BITLEN 0x0000003F -#define SPI_USR_ADDR_BITLEN_S 26 -#define SPI_USR_MOSI_BITLEN 0x000001FF -#define SPI_USR_MOSI_BITLEN_S 17 -#define SPI_USR_MISO_BITLEN 0x000001FF -#define SPI_USR_MISO_BITLEN_S 8 - -#define SPI_USR_DUMMY_CYCLELEN 0x000000FF -#define SPI_USR_DUMMY_CYCLELEN_S 0 - -#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) -#define SPI_USR_COMMAND_BITLEN 0x0000000F -#define SPI_USR_COMMAND_BITLEN_S 28 -#define SPI_USR_COMMAND_VALUE 0x0000FFFF -#define SPI_USR_COMMAND_VALUE_S 0 - -#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) -#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) -#define SPI_IDLE_EDGE (BIT(29)) -#define SPI_CS2_DIS (BIT(2)) -#define SPI_CS1_DIS (BIT(1)) -#define SPI_CS0_DIS (BIT(0)) - -#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) -#define SPI_SYNC_RESET (BIT(31)) -#define SPI_SLAVE_MODE (BIT(30)) -#define SPI_SLV_WR_RD_BUF_EN (BIT(29)) -#define SPI_SLV_WR_RD_STA_EN (BIT(28)) -#define SPI_SLV_CMD_DEFINE (BIT(27)) -#define SPI_TRANS_CNT 0x0000000F -#define SPI_TRANS_CNT_S 23 -#define SPI_TRANS_DONE_EN (BIT(9)) -#define SPI_SLV_WR_STA_DONE_EN (BIT(8)) -#define SPI_SLV_RD_STA_DONE_EN (BIT(7)) -#define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) -#define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) - - - -#define SLV_SPI_INT_EN 0x0000001f -#define SLV_SPI_INT_EN_S 5 - -#define SPI_TRANS_DONE (BIT(4)) -#define SPI_SLV_WR_STA_DONE (BIT(3)) -#define SPI_SLV_RD_STA_DONE (BIT(2)) -#define SPI_SLV_WR_BUF_DONE (BIT(1)) -#define SPI_SLV_RD_BUF_DONE (BIT(0)) - -#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) -#define SPI_SLV_STATUS_BITLEN 0x0000001F -#define SPI_SLV_STATUS_BITLEN_S 27 -#define SPI_SLV_BUF_BITLEN 0x000001FF -#define SPI_SLV_BUF_BITLEN_S 16 -#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F -#define SPI_SLV_RD_ADDR_BITLEN_S 10 -#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F -#define SPI_SLV_WR_ADDR_BITLEN_S 4 - -#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) -#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) -#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) -#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) - - - -#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 -#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 - -#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) -#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_WRSTA_CMD_VALUE_S 24 -#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_RDSTA_CMD_VALUE_S 16 -#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_WRBUF_CMD_VALUE_S 8 -#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_RDBUF_CMD_VALUE_S 0 - -#define SPI_W0(i) (REG_SPI_BASE(i) +0x40) -#define SPI_W1(i) (REG_SPI_BASE(i) +0x44) -#define SPI_W2(i) (REG_SPI_BASE(i) +0x48) -#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) -#define SPI_W4(i) (REG_SPI_BASE(i) +0x50) -#define SPI_W5(i) (REG_SPI_BASE(i) +0x54) -#define SPI_W6(i) (REG_SPI_BASE(i) +0x58) -#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) -#define SPI_W8(i) (REG_SPI_BASE(i) +0x60) -#define SPI_W9(i) (REG_SPI_BASE(i) +0x64) -#define SPI_W10(i) (REG_SPI_BASE(i) +0x68) -#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) -#define SPI_W12(i) (REG_SPI_BASE(i) +0x70) -#define SPI_W13(i) (REG_SPI_BASE(i) +0x74) -#define SPI_W14(i) (REG_SPI_BASE(i) +0x78) -#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) - -#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) - -#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) -#define SPI_INT_HOLD_ENA 0x00000003 -#define SPI_INT_HOLD_ENA_S 0 - -#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) -#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) - -#define SPI_ENABLE_AHB BIT17 - -#define SPI_FLASH_CLK_EQU_SYSCLK BIT12 - -//SPI flash command -#define SPI_FLASH_READ BIT31 -#define SPI_FLASH_WREN BIT30 -#define SPI_FLASH_WRDI BIT29 -#define SPI_FLASH_RDID BIT28 -#define SPI_FLASH_RDSR BIT27 -#define SPI_FLASH_WRSR BIT26 -#define SPI_FLASH_PP BIT25 -#define SPI_FLASH_SE BIT24 -#define SPI_FLASH_BE BIT23 -#define SPI_FLASH_CE BIT22 -#define SPI_FLASH_RES BIT20 -#define SPI_FLASH_DPD BIT21 -#define SPI_FLASH_HPM BIT19 - -//SPI address register -#define SPI_FLASH_BYTES_LEN 24 -#define SPI_BUFF_BYTE_NUM 32 -#define IODATA_START_ADDR BIT0 - -//SPI status register -#define SPI_FLASH_BUSY_FLAG BIT0 -#define SPI_FLASH_WRENABLE_FLAG BIT1 -#define SPI_FLASH_BP0 BIT2 -#define SPI_FLASH_BP1 BIT3 -#define SPI_FLASH_BP2 BIT4 -#define SPI_FLASH_TOP_BOT_PRO_FLAG BIT5 -#define SPI_FLASH_STATUS_PRO_FLAG BIT7 - -#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2) - -#define SPI 0 - -#define PERIPHS_SPI_FLASH_C0 SPI_W0(SPI) -#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(SPI) -#define PERIPHS_SPI_FLASH_CMD SPI_CMD(SPI) - -#endif // SPI_REGISTER_H_INCLUDED diff --git a/components/esp8266/include/driver/uart.h b/components/esp8266/include/driver/uart.h index 1532a73d1..ed144cd5b 100644 --- a/components/esp8266/include/driver/uart.h +++ b/components/esp8266/include/driver/uart.h @@ -20,6 +20,7 @@ extern "C" { #endif +#include #include "esp_err.h" #include "esp_log.h" #include "freertos/queue.h" @@ -422,12 +423,13 @@ esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *uart_intr_c * @param queue_size UART event queue size/depth. * @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide * access to UART events. If set to NULL, driver will not use an event queue. - * + * @param no_use Invalid parameters, just to fit some modules. + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue); +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int no_use); /** * @brief Uninstall UART driver. @@ -440,6 +442,18 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b */ esp_err_t uart_driver_delete(uart_port_t uart_num); +/** + * @brief Waiting for the last byte of data to be sent + * + * @param uart_num Uart port number. + * @param ticks_to_wait Timeout, count in RTOS ticks + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); + /** * @brief Send data to the UART port from a given buffer and length. * @@ -540,6 +554,17 @@ esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t *size); */ esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh); +/** + * @brief Checks whether the driver is installed or not + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return + * - true driver is installed + * - false driver is not installed + */ +bool uart_is_driver_installed(uart_port_t uart_num); + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/driver/uart_select.h b/components/esp8266/include/driver/uart_select.h new file mode 100644 index 000000000..442df0032 --- /dev/null +++ b/components/esp8266/include/driver/uart_select.h @@ -0,0 +1,49 @@ + +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _UART_SELECT_H_ +#define _UART_SELECT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/uart.h" + +typedef enum { + UART_SELECT_READ_NOTIF, + UART_SELECT_WRITE_NOTIF, + UART_SELECT_ERROR_NOTIF, +} uart_select_notif_t; + +typedef void (*uart_select_notif_callback_t)(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken); + +/** + * @brief Set notification callback function for select() events + * @param uart_num UART port number + * @param uart_select_notif_callback callback function + */ +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback); + +/** + * @brief Get mutex guarding select() notifications + */ +void *uart_get_selectlock(); + +#ifdef __cplusplus +} +#endif + +#endif //_UART_SELECT_H_ diff --git a/components/esp8266/include/esp8266/backtrace.h b/components/esp8266/include/esp8266/backtrace.h new file mode 100644 index 000000000..e2475feac --- /dev/null +++ b/components/esp8266/include/esp8266/backtrace.h @@ -0,0 +1,61 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if PC pointer locates at code section + * + * @param pc the PC pointer + * + * @return 1 if valid or 0 if invalid + */ +int xt_pc_is_valid(const void *pc); + +/** + * @brief Detected recursively and serach the previous PC and SP + * + * @param i_pc the PC address for forward recursive detection + * @param i_sp the SP address for forward recursive detection + * @param i_lr the LR address, maybe it the previous PC address + * @param o_pc the detected previous PC address + * @param o_pc the detected previous SP address + * + * @return 1 if found or 0 if not found + */ +int xt_retaddr_callee(const void *i_pc, const void *i_sp, const void *i_lr, void **o_pc, void **o_sp); + +/** + * @brief These functions may be used to get information about the callers of a function. + * + * Using this API instead of "__builtin_return_address". + * + * This function returns the return address of the current function, or of one of its callers. + * The level argument is number of frames to scan up the call stack. A value of 0 yields the + * return address of the current function, a value of 1 yields the return address of the caller + * of the current function, and so forth.. + * + * @param lvl caller level + * + * @return the return address of the current function + */ +void *xt_return_address(int lvl); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index 28d105a80..685fdf91d 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -25,7 +25,10 @@ #ifndef _EAGLE_SOC_H_ #define _EAGLE_SOC_H_ +#include "sdkconfig.h" #include +#include +#include "driver/soc.h" /* IO definitions (access restrictions to peripheral registers) */ @@ -93,6 +96,18 @@ #define APB_CLK_FREQ CPU_CLK_FREQ #define UART_CLK_FREQ APB_CLK_FREQ #define TIMER_CLK_FREQ (APB_CLK_FREQ >> 8) // divided by 256 + +#define FREQ_1MHZ (1000 * 1000) +#define FREQ_1KHZ (1000) + +#define CPU_FREQ_160MHZ (160 * 1000 * 1000) +#define CPU_FREQ_80MHz (80 * 1000 * 1000) + +#define CPU_160M_TICKS_PRT_MS (CPU_FREQ_160MHZ / FREQ_1KHZ) +#define CPU_80M_TICKS_PRT_MS (CPU_FREQ_80MHz / FREQ_1KHZ) + +#define CPU_160M_TICKS_PRT_US (CPU_FREQ_160MHZ / FREQ_1MHZ) +#define CPU_80M_TICKS_PRT_US (CPU_FREQ_80MHz / FREQ_1MHZ) //}} //Peripheral device base address define{{ @@ -116,12 +131,31 @@ //}} //Interrupt remap control registers define{{ +#define NMI_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR) #define EDGE_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR + 0x04) #define WDT_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT0) #define TM1_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) #define TM1_EDGE_INT_DISABLE() CLEAR_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) //}} +#define DPORT_CTL_REG (PERIPHS_DPORT_BASEADDR + 0x14) +#define DPORT_CTL_DOUBLE_CLK BIT0 + +#define INT_ENA_WDEV 0x3ff20c18 +#define WDEV_TSF0_REACH_INT (BIT(27)) + +#define WDEV_COUNT_REG (0x3ff20c00) + +#define WDEVTSF0_TIME_LO 0x3ff21004 +#define WDEVTSF0_TIME_HI 0x3ff21008 +#define WDEVSLEEP0_CONF 0x3ff21014 +#define WDEVTSFSW0_LO 0x3ff21018 +#define WDEVTSFSW0_HI 0x3ff2101C +#define WDEVTSF0_TIMER_LO 0x3ff2109c +#define WDEVTSF0_TIMER_HI 0x3ff210a0 +#define WDEVTSF0TIMER_ENA 0x3ff21098 +#define WDEV_TSF0TIMER_ENA BIT(31) +#define WDEV_TSFUP0_ENA BIT(31) //Watch dog reg {{ #define PERIPHS_WDT_BASEADDR 0x60000900 @@ -140,6 +174,12 @@ #define WDT_CTL_EN_LSB 0 #define WDT_FEED_VALUE 0x73 + +#define WDT_REG_READ(_reg) REG_READ(PERIPHS_WDT_BASEADDR + _reg) +#define WDT_REG_WRITE(_reg, _val) REG_WRITE(PERIPHS_WDT_BASEADDR + _reg, _val) +#define CLEAR_WDT_REG_MASK(_reg, _mask) WDT_REG_WRITE(_reg, WDT_REG_READ(_reg) & (~_mask)) +#define WDT_FEED() WDT_REG_WRITE(WDT_RST_ADDRESS, WDT_FEED_VALUE) + //}} //RTC reg {{ @@ -160,22 +200,38 @@ #define PAD_XPD_DCDC_CONF (REG_RTC_BASE + 0x0A0) //}} +#define WDEV_RAND (WDEV_COUNT_REG + 0x244) + //CACHE{{ #define CACHE_FLASH_CTRL_REG (0x3ff00000 + 0x0c) #define CACHE_READ_EN_BIT BIT8 //}} +#define ESP_CACHE1_ADDR_MAX (0x100000) +#define ESP_CACHE2_ADDR_MAX (0x200000) + #define DRAM_BASE (0x3FFE8000) #define DRAM_SIZE (96 * 1024) #define IRAM_BASE (0x40100000) -#define IRAM_SIZE (48 * 1024) +#define IRAM_SIZE (CONFIG_SOC_IRAM_SIZE) #define FLASH_BASE (0x40200000) -#define FLASH_SIZE (16 * 1024 * 1024) +#define FLASH_SIZE (1 * 1024 * 1024) + +#define RTC_SYS_BASE (0x60001000) +#define RTC_SYS_SIZE (0x200) + +#define RTC_USER_BASE (0x60001200) +#define RTC_USER_SIZE (0x200) + +#define ROM_BASE (0x40000000) +#define ROM_SIZE (0x10000) #define IS_DRAM(a) ((size_t)(a) >= DRAM_BASE && (size_t)(a) < (DRAM_BASE + DRAM_SIZE)) #define IS_IRAM(a) ((size_t)(a) >= IRAM_BASE && (size_t)(a) < (IRAM_BASE + IRAM_SIZE)) #define IS_FLASH(a) ((size_t)(a) >= FLASH_BASE && (size_t)(a) < (FLASH_BASE + FLASH_SIZE)) +#define IS_USR_RTC(a) ((size_t)(a) >= RTC_USER_BASE && (size_t)(a) < (RTC_USER_BASE + RTC_USER_SIZE)) +#define IS_ROM(a) ((size_t)(a) >= ROM_BASE && (size_t)(a) < (ROM_BASE + ROM_SIZE)) #endif //_EAGLE_SOC_H_ diff --git a/components/esp8266/include/esp8266/i2s_register.h b/components/esp8266/include/esp8266/i2s_register.h new file mode 100644 index 000000000..6e0a9c552 --- /dev/null +++ b/components/esp8266/include/esp8266/i2s_register.h @@ -0,0 +1,130 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _I2S_REGISTER_H_ +#define _I2S_REGISTER_H_ + +#include "eagle_soc.h" + +#define REG_I2S_BASE (0x60000e00) + +#define I2STXFIFO (REG_I2S_BASE + 0x0000) +#define I2SRXFIFO (REG_I2S_BASE + 0x0004) + +#define I2SCONF (REG_I2S_BASE + 0x0008) +#define I2S_BCK_DIV_NUM 0x0000003F +#define I2S_BCK_DIV_NUM_S 22 +#define I2S_CLKM_DIV_NUM 0x0000003F +#define I2S_CLKM_DIV_NUM_S 16 +#define I2S_BITS_MOD 0x0000000F +#define I2S_BITS_MOD_S 12 +#define I2S_RECE_MSB_SHIFT (BIT(11)) +#define I2S_TRANS_MSB_SHIFT (BIT(10)) +#define I2S_I2S_RX_START (BIT(9)) +#define I2S_I2S_TX_START (BIT(8)) +#define I2S_MSB_RIGHT (BIT(7)) +#define I2S_RIGHT_FIRST (BIT(6)) +#define I2S_RECE_SLAVE_MOD (BIT(5)) +#define I2S_TRANS_SLAVE_MOD (BIT(4)) +#define I2S_I2S_RX_FIFO_RESET (BIT(3)) +#define I2S_I2S_TX_FIFO_RESET (BIT(2)) +#define I2S_I2S_RX_RESET (BIT(1)) +#define I2S_I2S_TX_RESET (BIT(0)) +#define I2S_I2S_RESET_MASK 0xf + +#define I2SINT_RAW (REG_I2S_BASE + 0x000c) +#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) + + +#define I2SINT_ST (REG_I2S_BASE + 0x0010) +#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_ST (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_ST (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0)) + +#define I2SINT_ENA (REG_I2S_BASE + 0x0014) +#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) + +#define I2SINT_CLR (REG_I2S_BASE + 0x0018) +#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2)) +#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1)) +#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0)) + +#define I2STIMING (REG_I2S_BASE + 0x001c) +#define I2S_TRANS_BCK_IN_INV (BIT(22)) +#define I2S_RECE_DSYNC_SW (BIT(21)) +#define I2S_TRANS_DSYNC_SW (BIT(20)) +#define I2S_RECE_BCK_OUT_DELAY 0x00000003 +#define I2S_RECE_BCK_OUT_DELAY_S 18 +#define I2S_RECE_WS_OUT_DELAY 0x00000003 +#define I2S_RECE_WS_OUT_DELAY_S 16 +#define I2S_TRANS_SD_OUT_DELAY 0x00000003 +#define I2S_TRANS_SD_OUT_DELAY_S 14 +#define I2S_TRANS_WS_OUT_DELAY 0x00000003 +#define I2S_TRANS_WS_OUT_DELAY_S 12 +#define I2S_TRANS_BCK_OUT_DELAY 0x00000003 +#define I2S_TRANS_BCK_OUT_DELAY_S 10 +#define I2S_RECE_SD_IN_DELAY 0x00000003 +#define I2S_RECE_SD_IN_DELAY_S 8 +#define I2S_RECE_WS_IN_DELAY 0x00000003 +#define I2S_RECE_WS_IN_DELAY_S 6 +#define I2S_RECE_BCK_IN_DELAY 0x00000003 +#define I2S_RECE_BCK_IN_DELAY_S 4 +#define I2S_TRANS_WS_IN_DELAY 0x00000003 +#define I2S_TRANS_WS_IN_DELAY_S 2 +#define I2S_TRANS_BCK_IN_DELAY 0x00000003 +#define I2S_TRANS_BCK_IN_DELAY_S 0 + +#define I2S_FIFO_CONF (REG_I2S_BASE + 0x0020) +#define I2S_I2S_RX_FIFO_MOD 0x00000007 +#define I2S_I2S_RX_FIFO_MOD_S 16 +#define I2S_I2S_TX_FIFO_MOD 0x00000007 +#define I2S_I2S_TX_FIFO_MOD_S 13 +#define I2S_I2S_DSCR_EN (BIT(12)) +#define I2S_I2S_TX_DATA_NUM 0x0000003F +#define I2S_I2S_TX_DATA_NUM_S 6 +#define I2S_I2S_RX_DATA_NUM 0x0000003F +#define I2S_I2S_RX_DATA_NUM_S 0 + + +#define I2SRXEOF_NUM (REG_I2S_BASE + 0x0024) +#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF +#define I2S_I2S_RX_EOF_NUM_S 0 + +#define I2SCONF_SIGLE_DATA (REG_I2S_BASE + 0x0028) +#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF +#define I2S_I2S_SIGLE_DATA_S 0 + +#define I2SCONF_CHAN (REG_I2S_BASE + 0x002c) +#define I2S_RX_CHAN_MOD 0x00000003 +#define I2S_RX_CHAN_MOD_S 3 +#define I2S_TX_CHAN_MOD 0x00000007 +#define I2S_TX_CHAN_MOD_S 0 + +#endif diff --git a/components/esp8266/include/esp8266/i2s_struct.h b/components/esp8266/include/esp8266/i2s_struct.h new file mode 100644 index 000000000..a319a02ab --- /dev/null +++ b/components/esp8266/include/esp8266/i2s_struct.h @@ -0,0 +1,145 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ESP8266 I2S Register Definitions */ + +typedef volatile struct { + uint32_t tx_fifo; + uint32_t rx_fifo; + union { + struct { + uint32_t tx_reset: 1; + uint32_t rx_reset: 1; + uint32_t tx_fifo_reset: 1; + uint32_t rx_fifo_reset: 1; + uint32_t tx_slave_mod: 1; + uint32_t rx_slave_mod: 1; + uint32_t right_first: 1; + uint32_t msb_right: 1; + uint32_t tx_start: 1; + uint32_t rx_start: 1; + uint32_t tx_msb_shift: 1; + uint32_t rx_msb_shift: 1; + uint32_t bits_mod: 4; + uint32_t clkm_div_num: 6; + uint32_t bck_div_num: 6; + uint32_t reserved28: 4; + }; + uint32_t val; + } conf; + union { + struct { + uint32_t rx_take_data: 1; + uint32_t tx_put_data: 1; + uint32_t rx_wfull: 1; + uint32_t rx_rempty: 1; + uint32_t tx_wfull: 1; + uint32_t tx_rempty: 1; + uint32_t reserved6: 26; + }; + uint32_t val; + } int_raw; + union { + struct { + uint32_t rx_take_data: 1; + uint32_t tx_put_data: 1; + uint32_t rx_wfull: 1; + uint32_t rx_rempty: 1; + uint32_t tx_wfull: 1; + uint32_t tx_rempty: 1; + uint32_t reserved6: 26; + }; + uint32_t val; + } int_st; + union { + struct { + uint32_t rx_take_data: 1; + uint32_t tx_put_data: 1; + uint32_t rx_wfull: 1; + uint32_t rx_rempty: 1; + uint32_t tx_wfull: 1; + uint32_t tx_rempty: 1; + uint32_t reserved6: 26; + }; + uint32_t val; + } int_ena; + union { + struct { + uint32_t rx_take_data: 1; + uint32_t tx_put_data: 1; + uint32_t rx_wfull: 1; + uint32_t rx_rempty: 1; + uint32_t tx_wfull: 1; + uint32_t tx_rempty: 1; + uint32_t reserved6: 26; + }; + uint32_t val; + } int_clr; + union { + struct { + uint32_t tx_bck_in_delay: 2; + uint32_t tx_ws_in_delay: 2; + uint32_t rx_bck_in_delay: 2; + uint32_t rx_ws_in_delay: 2; + uint32_t rx_sd_in_delay: 2; + uint32_t tx_bck_out_delay: 2; + uint32_t tx_ws_out_delay: 2; + uint32_t tx_sd_out_delay: 2; + uint32_t rx_ws_out_delay: 2; + uint32_t rx_bck_out_delay: 2; + uint32_t tx_dsync_sw: 1; + uint32_t rx_dsync_sw: 1; + uint32_t tx_bck_in_inv: 1; + uint32_t reserved23: 9; + }; + uint32_t val; + } timing; + union { + struct { + uint32_t rx_data_num: 6; + uint32_t tx_data_num: 6; + uint32_t dscr_en: 1; + uint32_t tx_fifo_mod: 3; + uint32_t rx_fifo_mod: 3; + uint32_t reserved19: 13; + }; + uint32_t val; + } fifo_conf; + uint32_t rx_eof_num; + uint32_t conf_single_data; + union { + struct { + uint32_t tx_chan_mod: 3; + uint32_t rx_chan_mod: 2; + uint32_t reserved5: 27; + }; + uint32_t val; + } conf_chan; +} i2s_struct_t; + +extern volatile i2s_struct_t I2S0; + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ + diff --git a/components/esp8266/include/esp8266/pin_mux_register.h b/components/esp8266/include/esp8266/pin_mux_register.h index a78844638..06db930cb 100644 --- a/components/esp8266/include/esp8266/pin_mux_register.h +++ b/components/esp8266/include/esp8266/pin_mux_register.h @@ -151,4 +151,23 @@ SET_PERI_REG_MASK(PIN_NAME, (((FUNC & BIT2) << 2) | (FUNC & 0x3)) << PERIPHS_IO_MUX_FUNC_S); \ } while (0) +#define PERIPHS_GPIO_MUX_REG(i) \ + (i==0) ? PERIPHS_IO_MUX_GPIO0_U: \ + (i==1) ? PERIPHS_IO_MUX_U0TXD_U: \ + (i==2) ? PERIPHS_IO_MUX_GPIO2_U: \ + (i==3) ? PERIPHS_IO_MUX_U0RXD_U: \ + (i==4) ? PERIPHS_IO_MUX_GPIO4_U: \ + (i==5) ? PERIPHS_IO_MUX_GPIO5_U: \ + (i==6) ? PERIPHS_IO_MUX_SD_CLK_U: \ + (i==7) ? PERIPHS_IO_MUX_SD_DATA0_U: \ + (i==8) ? PERIPHS_IO_MUX_SD_DATA1_U: \ + (i==9) ? PERIPHS_IO_MUX_SD_DATA2_U: \ + (i==10)? PERIPHS_IO_MUX_SD_DATA3_U: \ + (i==11)? PERIPHS_IO_MUX_SD_CMD_U: \ + (i==12)? PERIPHS_IO_MUX_MTDI_U: \ + (i==13)? PERIPHS_IO_MUX_MTCK_U: \ + (i==14)? PERIPHS_IO_MUX_MTMS_U: \ + (i==15)? PERIPHS_IO_MUX_MTDO_U: \ + PAD_XPD_DCDC_CONF + #endif //_PIN_MUX_H_ diff --git a/components/esp8266/include/esp8266/rom_functions.h b/components/esp8266/include/esp8266/rom_functions.h index 6aeacb2b1..1c5a5d686 100644 --- a/components/esp8266/include/esp8266/rom_functions.h +++ b/components/esp8266/include/esp8266/rom_functions.h @@ -1,17 +1,28 @@ #ifndef _ROM_FUNCTIONS_H #define _ROM_FUNCTIONS_H +#include "sdkconfig.h" #include #include -typedef struct esp_spi_flash_chip { - uint32_t deviceId; - uint32_t chip_size; // chip size in byte - uint32_t block_size; - uint32_t sector_size; - uint32_t page_size; - uint32_t status_mask; -} esp_spi_flash_chip_t; +#ifdef CONFIG_SOC_FULL_ICACHE +#define SOC_CACHE_SIZE 1 // 32KB +#else +#define SOC_CACHE_SIZE 0 // 16KB +#endif + +#define ROM_FLASH_BUF_DECLARE(__name, __size) uint8_t __name[__size] __attribute__((aligned(4))) + +typedef struct { + uint32_t device_id; + uint32_t chip_size; // chip size in bytes + uint32_t block_size; + uint32_t sector_size; + uint32_t page_size; + uint32_t status_mask; +} esp_rom_spiflash_chip_t; + +extern esp_rom_spiflash_chip_t g_rom_flashchip; uint32_t Wait_SPI_Idle(); @@ -23,15 +34,23 @@ void system_soft_wdt_feed(); void Cache_Read_Enable_New(); -int SPI_page_program(esp_spi_flash_chip_t *chip, uint32_t dst_addr, void *pbuf, uint32_t len); -int SPI_read_data(esp_spi_flash_chip_t *chip, uint32_t dst_addr, void *pbuf, uint32_t len); -int SPI_write_enable(esp_spi_flash_chip_t *chip); -int SPI_sector_erase(esp_spi_flash_chip_t *chip, uint32_t sect_addr); -int SPI_write_status(esp_spi_flash_chip_t *chip, uint32_t status); -int SPI_read_status(esp_spi_flash_chip_t *chip, uint32_t *status); -int Enable_QMode(esp_spi_flash_chip_t *chip); +int SPI_page_program(esp_rom_spiflash_chip_t *chip, uint32_t dst_addr, void *pbuf, uint32_t len); +int SPI_read_data(esp_rom_spiflash_chip_t *chip, uint32_t dst_addr, void *pbuf, uint32_t len); +int SPI_write_enable(esp_rom_spiflash_chip_t *chip); +int SPI_sector_erase(esp_rom_spiflash_chip_t *chip, uint32_t sect_addr); +int SPI_write_status(esp_rom_spiflash_chip_t *chip, uint32_t status); +int SPI_read_status(esp_rom_spiflash_chip_t *chip, uint32_t *status); +int Enable_QMode(esp_rom_spiflash_chip_t *chip); + +int SPIWrite(uint32_t addr, const uint8_t *src, uint32_t size); +int SPIRead(uint32_t addr, void *dst, uint32_t size); +int SPIEraseSector(uint32_t sector_num); void Cache_Read_Disable(); void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); +void rom_software_reboot(void); + +void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); + #endif diff --git a/components/esp8266/include/esp8266/rtc_register.h b/components/esp8266/include/esp8266/rtc_register.h new file mode 100644 index 000000000..46e468d65 --- /dev/null +++ b/components/esp8266/include/esp8266/rtc_register.h @@ -0,0 +1,29 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +typedef enum { + NO_MEAN = 0, + POWERON_RESET = 1, /**<1, Vbat power on reset*/ + EXT_RESET = 2, /**<2, external system reset*/ + SW_RESET = 3, /**<3, Software reset digital core*/ + OWDT_RESET = 4, /**<4, Legacy watch dog reset digital core*/ + DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ + SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/ +} RESET_REASON; + +#define RTC_STORE0 (REG_RTC_BASE + 0x30) +#define RTC_STATE1 (REG_RTC_BASE + 0x14) +#define RTC_STATE2 (REG_RTC_BASE + 0x18) diff --git a/components/esp8266/include/esp8266/slc_register.h b/components/esp8266/include/esp8266/slc_register.h new file mode 100644 index 000000000..39c4342fe --- /dev/null +++ b/components/esp8266/include/esp8266/slc_register.h @@ -0,0 +1,289 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SLC_REGISTER_H_ +#define _SLC_REGISTER_H_ + +#include "eagle_soc.h" + +#define REG_SLC_BASE 0x60000B00 +//version value:32'h091700 + +#define SLC_CONF0 (REG_SLC_BASE + 0x0) +#ifndef ESP_MAC_5 +#define SLC_MODE 0x00000003 +#define SLC_MODE_S 12 +#endif +#define SLC_DATA_BURST_EN (BIT(9)) +#define SLC_DSCR_BURST_EN (BIT(8)) +#define SLC_RX_NO_RESTART_CLR (BIT(7)) +#define SLC_RX_AUTO_WRBACK (BIT(6)) +#define SLC_RX_LOOP_TEST (BIT(5)) +#define SLC_TX_LOOP_TEST (BIT(4)) +#define SLC_AHBM_RST (BIT(3)) +#define SLC_AHBM_FIFO_RST (BIT(2)) +#define SLC_RXLINK_RST (BIT(1)) +#define SLC_TXLINK_RST (BIT(0)) + +#define SLC_INT_RAW (REG_SLC_BASE + 0x4) +#define SLC_TX_DSCR_EMPTY_INT_RAW (BIT(21)) +#define SLC_RX_DSCR_ERR_INT_RAW (BIT(20)) +#define SLC_TX_DSCR_ERR_INT_RAW (BIT(19)) +#define SLC_TOHOST_INT_RAW (BIT(18)) +#define SLC_RX_EOF_INT_RAW (BIT(17)) +#define SLC_RX_DONE_INT_RAW (BIT(16)) +#define SLC_TX_EOF_INT_RAW (BIT(15)) +#define SLC_TX_DONE_INT_RAW (BIT(14)) +#define SLC_TOKEN1_1TO0_INT_RAW (BIT(13)) +#define SLC_TOKEN0_1TO0_INT_RAW (BIT(12)) +#define SLC_TX_OVF_INT_RAW (BIT(11)) +#define SLC_RX_UDF_INT_RAW (BIT(10)) +#define SLC_TX_START_INT_RAW (BIT(9)) +#define SLC_RX_START_INT_RAW (BIT(8)) +#define SLC_FRHOST_BIT7_INT_RAW (BIT(7)) +#define SLC_FRHOST_BIT6_INT_RAW (BIT(6)) +#define SLC_FRHOST_BIT5_INT_RAW (BIT(5)) +#define SLC_FRHOST_BIT4_INT_RAW (BIT(4)) +#define SLC_FRHOST_BIT3_INT_RAW (BIT(3)) +#define SLC_FRHOST_BIT2_INT_RAW (BIT(2)) +#define SLC_FRHOST_BIT1_INT_RAW (BIT(1)) +#define SLC_FRHOST_BIT0_INT_RAW (BIT(0)) + +#define SLC_INT_STATUS (REG_SLC_BASE + 0x8) +#define SLC_TX_DSCR_EMPTY_INT_ST (BIT(21)) +#define SLC_RX_DSCR_ERR_INT_ST (BIT(20)) +#define SLC_TX_DSCR_ERR_INT_ST (BIT(19)) +#define SLC_TOHOST_INT_ST (BIT(18)) +#define SLC_RX_EOF_INT_ST (BIT(17)) +#define SLC_RX_DONE_INT_ST (BIT(16)) +#define SLC_TX_EOF_INT_ST (BIT(15)) +#define SLC_TX_DONE_INT_ST (BIT(14)) +#define SLC_TOKEN1_1TO0_INT_ST (BIT(13)) +#define SLC_TOKEN0_1TO0_INT_ST (BIT(12)) +#define SLC_TX_OVF_INT_ST (BIT(11)) +#define SLC_RX_UDF_INT_ST (BIT(10)) +#define SLC_TX_START_INT_ST (BIT(9)) +#define SLC_RX_START_INT_ST (BIT(8)) +#define SLC_FRHOST_BIT7_INT_ST (BIT(7)) +#define SLC_FRHOST_BIT6_INT_ST (BIT(6)) +#define SLC_FRHOST_BIT5_INT_ST (BIT(5)) +#define SLC_FRHOST_BIT4_INT_ST (BIT(4)) +#define SLC_FRHOST_BIT3_INT_ST (BIT(3)) +#define SLC_FRHOST_BIT2_INT_ST (BIT(2)) +#define SLC_FRHOST_BIT1_INT_ST (BIT(1)) +#define SLC_FRHOST_BIT0_INT_ST (BIT(0)) + +#define SLC_INT_ENA (REG_SLC_BASE + 0xC) +#define SLC_TX_DSCR_EMPTY_INT_ENA (BIT(21)) +#define SLC_RX_DSCR_ERR_INT_ENA (BIT(20)) +#define SLC_TX_DSCR_ERR_INT_ENA (BIT(19)) +#define SLC_TOHOST_INT_ENA (BIT(18)) +#define SLC_RX_EOF_INT_ENA (BIT(17)) +#define SLC_RX_DONE_INT_ENA (BIT(16)) +#define SLC_TX_EOF_INT_ENA (BIT(15)) +#define SLC_TX_DONE_INT_ENA (BIT(14)) +#define SLC_TOKEN1_1TO0_INT_ENA (BIT(13)) +#define SLC_TOKEN0_1TO0_INT_ENA (BIT(12)) +#define SLC_TX_OVF_INT_ENA (BIT(11)) +#define SLC_RX_UDF_INT_ENA (BIT(10)) +#define SLC_TX_START_INT_ENA (BIT(9)) +#define SLC_RX_START_INT_ENA (BIT(8)) +#define SLC_FRHOST_BIT7_INT_ENA (BIT(7)) +#define SLC_FRHOST_BIT6_INT_ENA (BIT(6)) +#define SLC_FRHOST_BIT5_INT_ENA (BIT(5)) +#define SLC_FRHOST_BIT4_INT_ENA (BIT(4)) +#define SLC_FRHOST_BIT3_INT_ENA (BIT(3)) +#define SLC_FRHOST_BIT2_INT_ENA (BIT(2)) +#define SLC_FRHOST_BIT1_INT_ENA (BIT(1)) +#define SLC_FRHOST_BIT0_INT_ENA (BIT(0)) + +#define SLC_FRHOST_BIT_INT_ENA_ALL 0xff + +#define SLC_INT_CLR (REG_SLC_BASE + 0x10) +#define SLC_TX_DSCR_EMPTY_INT_CLR (BIT(21)) +#define SLC_RX_DSCR_ERR_INT_CLR (BIT(20)) +#define SLC_TX_DSCR_ERR_INT_CLR (BIT(19)) +#define SLC_TOHOST_INT_CLR (BIT(18)) +#define SLC_RX_EOF_INT_CLR (BIT(17)) +#define SLC_RX_DONE_INT_CLR (BIT(16)) +#define SLC_TX_EOF_INT_CLR (BIT(15)) +#define SLC_TX_DONE_INT_CLR (BIT(14)) +#define SLC_TOKEN1_1TO0_INT_CLR (BIT(13)) +#define SLC_TOKEN0_1TO0_INT_CLR (BIT(12)) +#define SLC_TX_OVF_INT_CLR (BIT(11)) +#define SLC_RX_UDF_INT_CLR (BIT(10)) +#define SLC_TX_START_INT_CLR (BIT(9)) +#define SLC_RX_START_INT_CLR (BIT(8)) +#define SLC_FRHOST_BIT7_INT_CLR (BIT(7)) +#define SLC_FRHOST_BIT6_INT_CLR (BIT(6)) +#define SLC_FRHOST_BIT5_INT_CLR (BIT(5)) +#define SLC_FRHOST_BIT4_INT_CLR (BIT(4)) +#define SLC_FRHOST_BIT3_INT_CLR (BIT(3)) +#define SLC_FRHOST_BIT2_INT_CLR (BIT(2)) +#define SLC_FRHOST_BIT1_INT_CLR (BIT(1)) +#define SLC_FRHOST_BIT0_INT_CLR (BIT(0)) + +#define SLC_RX_STATUS (REG_SLC_BASE + 0x14) +#define SLC_RX_EMPTY (BIT(1)) +#define SLC_RX_FULL (BIT(0)) + +#define SLC_RX_FIFO_PUSH (REG_SLC_BASE + 0x18) +#define SLC_RXFIFO_PUSH (BIT(16)) +#define SLC_RXFIFO_WDATA 0x000001FF +#define SLC_RXFIFO_WDATA_S 0 + +#define SLC_TX_STATUS (REG_SLC_BASE + 0x1C) +#define SLC_TX_EMPTY (BIT(1)) +#define SLC_TX_FULL (BIT(0)) + +#define SLC_TX_FIFO_POP (REG_SLC_BASE + 0x20) +#define SLC_TXFIFO_POP (BIT(16)) +#define SLC_TXFIFO_RDATA 0x000007FF +#define SLC_TXFIFO_RDATA_S 0 + +#define SLC_RX_LINK (REG_SLC_BASE + 0x24) +#define SLC_RXLINK_PARK (BIT(31)) +#define SLC_RXLINK_RESTART (BIT(30)) +#define SLC_RXLINK_START (BIT(29)) +#define SLC_RXLINK_STOP (BIT(28)) +#define SLC_RXLINK_DESCADDR_MASK 0x000FFFFF +#define SLC_RXLINK_ADDR_S 0 + +#define SLC_TX_LINK (REG_SLC_BASE + 0x28) +#define SLC_TXLINK_PARK (BIT(31)) +#define SLC_TXLINK_RESTART (BIT(30)) +#define SLC_TXLINK_START (BIT(29)) +#define SLC_TXLINK_STOP (BIT(28)) +#define SLC_TXLINK_DESCADDR_MASK 0x000FFFFF +#define SLC_TXLINK_ADDR_S 0 + +#define SLC_INTVEC_TOHOST (REG_SLC_BASE + 0x2C) +#define SLC_TOHOST_INTVEC 0x000000FF +#define SLC_TOHOST_INTVEC_S 0 + +#define SLC_TOKEN0 (REG_SLC_BASE + 0x30) +#define SLC_TOKEN0_MASK 0x00000FFF +#define SLC_TOKEN0_S 16 +#define SLC_TOKEN0_LOCAL_INC_MORE (BIT(14)) +#define SLC_TOKEN0_LOCAL_INC (BIT(13)) +#define SLC_TOKEN0_LOCAL_WR (BIT(12)) +#define SLC_TOKEN0_LOCAL_WDATA_MASK 0x00000FFF +#define SLC_TOKEN0_LOCAL_WDATA_S 0 + +#define SLC_TOKEN1 (REG_SLC_BASE + 0x34) +#define SLC_TOKEN1_MASK 0x00000FFF +#define SLC_TOKEN1_S 16 +#define SLC_TOKEN1_LOCAL_INC_MORE (BIT(14)) +#define SLC_TOKEN1_LOCAL_INC (BIT(13)) +#define SLC_TOKEN1_LOCAL_WR (BIT(12)) +#define SLC_TOKEN1_LOCAL_WDATA 0x00000FFF +#define SLC_TOKEN1_LOCAL_WDATA_S 0 + +#define SLC_CONF1 (REG_SLC_BASE + 0x38) +#define SLC_STATE0 (REG_SLC_BASE + 0x3C) +#define SLC_STATE1 (REG_SLC_BASE + 0x40) + +#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44) +#ifndef ESP_MAC_5 +#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF +#define SLC_TX_PUSH_IDLE_NUM_S 16 +#define SLC_TX_DUMMY_MODE (BIT(12)) +#endif +#define SLC_FIFO_MAP_ENA 0x0000000F +#define SLC_FIFO_MAP_ENA_S 8 +#define SLC_TXEOF_ENA 0x0000003F +#define SLC_TXEOF_ENA_S 0 + +#define SLC_RX_EOF_DES_ADDR (REG_SLC_BASE + 0x48) +#define SLC_TX_EOF_DES_ADDR (REG_SLC_BASE + 0x4C) +#define SLC_FROM_HOST_LAST_DESC SLC_TX_EOF_DES_ADDR +#define SLC_TO_HOST_LAST_DESC SLC_RX_EOF_DES_ADDR + +#define SLC_RX_EOF_BFR_DES_ADDR (REG_SLC_BASE + 0x50) +#define SLC_AHB_TEST (REG_SLC_BASE + 0x54) +#define SLC_AHB_TESTADDR 0x00000003 +#define SLC_AHB_TESTADDR_S 4 +#define SLC_AHB_TESTMODE 0x00000007 +#define SLC_AHB_TESTMODE_S 0 + +#define SLC_SDIO_ST (REG_SLC_BASE + 0x58) +#define SLC_BUS_ST 0x00000007 +#define SLC_BUS_ST_S 12 +#define SLC_SDIO_WAKEUP (BIT(8)) +#define SLC_FUNC_ST 0x0000000F +#define SLC_FUNC_ST_S 4 +#define SLC_CMD_ST 0x00000007 +#define SLC_CMD_ST_S 0 + +#define SLC_RX_DSCR_CONF (REG_SLC_BASE + 0x5C) +#ifdef ESP_MAC_5 +#define SLC_INFOR_NO_REPLACE (BIT(9)) +#define SLC_TOKEN_NO_REPLACE (BIT(8)) +#define SLC_POP_IDLE_CNT 0x000000FF +#else +#define SLC_RX_FILL_EN (BIT(20)) +#define SLC_RX_EOF_MODE (BIT(19)) +#define SLC_RX_FILL_MODE (BIT(18)) +#define SLC_INFOR_NO_REPLACE (BIT(17)) +#define SLC_TOKEN_NO_REPLACE (BIT(16)) // +#define SLC_POP_IDLE_CNT 0x0000FFFF +#endif +#define SLC_POP_IDLE_CNT_S 0 + +#define SLC_TXLINK_DSCR (REG_SLC_BASE + 0x60) +#define SLC_TXLINK_DSCR_BF0 (REG_SLC_BASE + 0x64) +#define SLC_TXLINK_DSCR_BF1 (REG_SLC_BASE + 0x68) +#define SLC_RXLINK_DSCR (REG_SLC_BASE + 0x6C) +#define SLC_RXLINK_DSCR_BF0 (REG_SLC_BASE + 0x70) +#define SLC_RXLINK_DSCR_BF1 (REG_SLC_BASE + 0x74) +#define SLC_DATE (REG_SLC_BASE + 0x78) +#define SLC_ID (REG_SLC_BASE + 0x7C) + +#define SLC_HOST_CONF_W0 (REG_SLC_BASE + 0x80 + 0x14) +#define SLC_HOST_CONF_W1 (REG_SLC_BASE + 0x80 + 0x18) +#define SLC_HOST_CONF_W2 (REG_SLC_BASE + 0x80 + 0x20) +#define SLC_HOST_CONF_W3 (REG_SLC_BASE + 0x80 + 0x24) +#define SLC_HOST_CONF_W4 (REG_SLC_BASE + 0x80 + 0x28) + +#define SLC_HOST_INTR_ST (REG_SLC_BASE + 0x80 + 0x1c) +#define SLC_HOST_INTR_CLR (REG_SLC_BASE + 0x80 + 0x30) +#define SLC_HOST_INTR_SOF_BIT (BIT(12)) + +#define SLC_HOST_INTR_ENA (REG_SLC_BASE + 0x80 + 0x34) +#define SLC_RX_NEW_PACKET_INT_ENA (BIT23) +#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT0) +#define SLC_HOST_CONF_W5 (REG_SLC_BASE + 0x80 + 0x3C) +#define SLC_HOST_INTR_RAW (REG_SLC_BASE + 0x80 + 0x8) +#define SLC_HOST_INTR_ENA_BIT (BIT(23)) +//[15:12]: 0x3ff9xxxx -- 0b01 from_host +// 0x3ffaxxxx -- 0b10 general +// 0x3ffbxxxx -- 0b11 to_host +#define SLC_DATA_ADDR_CLEAR_MASK (~(0xf<<12)) +#define SLC_FROM_HOST_ADDR_MASK (0x1<<12) +#define SLC_TO_HOST_ADDR_MASK (0x3<<12) + +#define SLC_SET_FROM_HOST_ADDR_MASK(v) do { \ + (v) &= SLC_DATA_ADDR_CLEAR_MASK; \ + (v) |= SLC_FROM_HOST_ADDR_MASK; \ + } while(0); + +#define SLC_SET_TO_HOST_ADDR_MASK(v) do { \ + (v) &= SLC_DATA_ADDR_CLEAR_MASK; \ + (v) |= SLC_TO_HOST_ADDR_MASK; \ + } while(0); + + +#define SLC_TX_DESC_DEBUG_REG 0x3ff0002c //[15:0] set to 0xcccc + +#endif diff --git a/components/esp8266/include/esp8266/slc_struct.h b/components/esp8266/include/esp8266/slc_struct.h new file mode 100644 index 000000000..2aaf25ae6 --- /dev/null +++ b/components/esp8266/include/esp8266/slc_struct.h @@ -0,0 +1,348 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ESP8266 SLC Register Definitions */ + +typedef struct { + union { + struct { + uint32_t tx_rst: 1; + uint32_t rx_rst: 1; + uint32_t ahbm_fifo_rst: 1; + uint32_t ahbm_rst: 1; + uint32_t tx_loop_test: 1; + uint32_t rx_loop_test: 1; + uint32_t rx_auto_wrback: 1; + uint32_t rx_no_restart_clr: 1; + uint32_t rxdscr_burst_en: 1; + uint32_t rxdata_burst_en: 1; + uint32_t rxlink_auto_ret: 1; + uint32_t txlink_auto_ret: 1; + uint32_t txdscr_burst_en: 1; + uint32_t txdata_burst_en: 1; + uint32_t reserved14: 18; + }; + uint32_t val; + } conf0; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t reserved22: 10; + }; + uint32_t val; + } int_raw; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t reserved22: 10; + }; + uint32_t val; + } int_st; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t reserved22: 10; + }; + uint32_t val; + } int_ena; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t reserved22: 10; + }; + uint32_t val; + } int_clr; + union { + struct { + uint32_t rx_full: 1; + uint32_t rx_empty: 1; + uint32_t reserved2: 30; + }; + uint32_t val; + } rx_status; + union { + struct { + uint32_t rxfifo_wdata: 9; + uint32_t reserved9: 7; + uint32_t rxfifo_push: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } rxfifo_push; + union { + struct { + uint32_t tx_full: 1; + uint32_t tx_empty: 1; + uint32_t reserved2: 30; + }; + uint32_t val; + } tx_status; + union { + struct { + uint32_t txfifo_rdata: 11; + uint32_t reserved11: 5; + uint32_t txfifo_pop: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } txfifo_pop; + union { + struct { + uint32_t addr: 20; + uint32_t reserved20: 8; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } rx_link; + union { + struct { + uint32_t addr: 20; + uint32_t reserved20: 8; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } tx_link; + union { + struct { + uint32_t intvec: 8; + uint32_t reserved8: 24; + }; + uint32_t val; + } intvec_tohost; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token0: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } token0; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token1: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } token1; + uint32_t conf1; + uint32_t state0; + uint32_t state1; + union { + struct { + uint32_t txeof_ena: 6; + uint32_t reserved6: 2; + uint32_t fifo_map_ena: 4; + uint32_t tx_dummy_mode: 1; + uint32_t reserved13: 3; + uint32_t tx_push_idle_num: 16; + }; + uint32_t val; + } bridge_conf; + uint32_t rx_eof_des_addr; + uint32_t tx_eof_des_addr; + uint32_t to_eof_bfr_des_addr; + union { + struct { + uint32_t mode: 3; + uint32_t reserved3: 1; + uint32_t addr: 2; + uint32_t reserved6: 26; + }; + uint32_t val; + } ahb_test; + union { + struct { + uint32_t cmd_st: 3; + uint32_t reserved3: 1; + uint32_t func_st: 4; + uint32_t sdio_wakeup: 1; + uint32_t reserved9: 3; + uint32_t bus_st: 3; + uint32_t reserved15: 17; + }; + uint32_t val; + } sdio_st; + union { + struct { + uint32_t pop_idle_cnt: 16; + uint32_t token_no_replace: 1; + uint32_t infor_no_replace: 1; + uint32_t rx_fill_mode: 1; + uint32_t rx_eof_mode: 1; + uint32_t rx_fill_en: 1; + uint32_t reserved21: 11; + }; + uint32_t val; + } rx_dscr_conf; + uint32_t txlink_dscr; + uint32_t txlink_dscr_bf0; + uint32_t txlink_dscr_bf1; + uint32_t rxlink_dscr; + uint32_t rxlink_dscr_bf0; + uint32_t rxlink_dscr_bf1; + uint32_t date; + uint32_t id; + uint32_t reserved_80[2]; + union { + struct { + uint32_t reserved0: 23; + uint32_t intr_ena: 1; + uint32_t reserved24: 8; + }; + uint32_t val; + } host_intr_raw; + uint32_t reserved_8C[2]; + uint32_t host_conf_w0; + uint32_t host_conf_w1; + uint32_t host_intr_status; + uint32_t host_conf_w2; + uint32_t host_conf_w3; + uint32_t host_conf_w4; + uint32_t reserved_AC[1]; + union { + struct { + uint32_t reserved0: 12; + uint32_t sof_bit: 1; + uint32_t reserved13: 19; + }; + uint32_t val; + } host_intr_clr; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t reserved1: 22; + uint32_t rx_new_packet: 1; + uint32_t reserved24: 8; + }; + uint32_t val; + } host_intr_ena; + uint32_t reserved_BC[1]; + uint32_t host_conf_w5; +} slc_struct_t; + +extern volatile slc_struct_t SLC0; + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ + diff --git a/components/esp8266/include/esp8266/spi_register.h b/components/esp8266/include/esp8266/spi_register.h index 1db10f432..1bf5eeb3b 100644 --- a/components/esp8266/include/esp8266/spi_register.h +++ b/components/esp8266/include/esp8266/spi_register.h @@ -1,195 +1,276 @@ -/* - * ESPRSSIF MIT License - * - * Copyright (c) 2015 - * - * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, - * it is free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SPI_REGISTER_H_INCLUDED -#define SPI_REGISTER_H_INCLUDED - -#include "eagle_soc.h" - -#define REG_SPI_BASE(i) (0x60000200 - i*0x100) - -#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) -#define SPI_USR (BIT(18)) - -#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) - -#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) -#define SPI_WR_BIT_ORDER (BIT(26)) -#define SPI_RD_BIT_ORDER (BIT(25)) -#define SPI_QIO_MODE (BIT(24)) -#define SPI_DIO_MODE (BIT(23)) -#define SPI_QOUT_MODE (BIT(20)) -#define SPI_DOUT_MODE (BIT(14)) -#define SPI_FASTRD_MODE (BIT(13)) - -#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) - -#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) -#define SPI_CS_DELAY_NUM 0x0000000F -#define SPI_CS_DELAY_NUM_S 28 -#define SPI_CS_DELAY_MODE 0x00000003 -#define SPI_CS_DELAY_MODE_S 26 -#define SPI_MOSI_DELAY_NUM 0x00000007 -#define SPI_MOSI_DELAY_NUM_S 23 -#define SPI_MOSI_DELAY_MODE 0x00000003 -#define SPI_MOSI_DELAY_MODE_S 21 -#define SPI_MISO_DELAY_NUM 0x00000007 -#define SPI_MISO_DELAY_NUM_S 18 -#define SPI_MISO_DELAY_MODE 0x00000003 -#define SPI_MISO_DELAY_MODE_S 16 - -#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) -#define SPI_CLK_EQU_SYSCLK (BIT(31)) -#define SPI_CLKDIV_PRE 0x00001FFF -#define SPI_CLKDIV_PRE_S 18 -#define SPI_CLKCNT_N 0x0000003F -#define SPI_CLKCNT_N_S 12 -#define SPI_CLKCNT_H 0x0000003F -#define SPI_CLKCNT_H_S 6 -#define SPI_CLKCNT_L 0x0000003F -#define SPI_CLKCNT_L_S 0 - -#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) -#define SPI_USR_COMMAND (BIT(31)) -#define SPI_USR_ADDR (BIT(30)) -#define SPI_USR_DUMMY (BIT(29)) -#define SPI_USR_MISO (BIT(28)) -#define SPI_USR_MOSI (BIT(27)) -#define SPI_USR_MOSI_HIGHPART (BIT(25)) -#define SPI_USR_MISO_HIGHPART (BIT(24)) -#define SPI_SIO (BIT(16)) -#define SPI_FWRITE_QIO (BIT(15)) -#define SPI_FWRITE_DIO (BIT(14)) -#define SPI_FWRITE_QUAD (BIT(13)) -#define SPI_FWRITE_DUAL (BIT(12)) -#define SPI_WR_BYTE_ORDER (BIT(11)) -#define SPI_RD_BYTE_ORDER (BIT(10)) -#define SPI_CK_OUT_EDGE (BIT(7)) -#define SPI_CK_I_EDGE (BIT(6)) -#define SPI_CS_SETUP (BIT(5)) -#define SPI_CS_HOLD (BIT(4)) -#define SPI_FLASH_MODE (BIT(2)) - -#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) -#define SPI_USR_ADDR_BITLEN 0x0000003F -#define SPI_USR_ADDR_BITLEN_S 26 -#define SPI_USR_MOSI_BITLEN 0x000001FF -#define SPI_USR_MOSI_BITLEN_S 17 -#define SPI_USR_MISO_BITLEN 0x000001FF -#define SPI_USR_MISO_BITLEN_S 8 -#define SPI_USR_DUMMY_CYCLELEN 0x000000FF -#define SPI_USR_DUMMY_CYCLELEN_S 0 - -#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) -#define SPI_USR_COMMAND_BITLEN 0x0000000F -#define SPI_USR_COMMAND_BITLEN_S 28 -#define SPI_USR_COMMAND_VALUE 0x0000FFFF -#define SPI_USR_COMMAND_VALUE_S 0 - -#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) - -#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) -#define SPI_CS2_DIS (BIT(2)) -#define SPI_CS1_DIS (BIT(1)) -#define SPI_CS0_DIS (BIT(0)) - -#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) -#define SPI_SYNC_RESET (BIT(31)) -#define SPI_SLAVE_MODE (BIT(30)) -#define SPI_SLV_WR_RD_BUF_EN (BIT(29)) -#define SPI_SLV_WR_RD_STA_EN (BIT(28)) -#define SPI_SLV_CMD_DEFINE (BIT(27)) -#define SPI_TRANS_CNT 0x0000000F -#define SPI_TRANS_CNT_S 23 -#define SPI_TRANS_DONE_EN (BIT(9)) -#define SPI_SLV_WR_STA_DONE_EN (BIT(8)) -#define SPI_SLV_RD_STA_DONE_EN (BIT(7)) -#define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) -#define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) -#define SLV_SPI_INT_EN 0x0000001f -#define SLV_SPI_INT_EN_S 5 -#define SPI_TRANS_DONE (BIT(4)) -#define SPI_SLV_WR_STA_DONE (BIT(3)) -#define SPI_SLV_RD_STA_DONE (BIT(2)) -#define SPI_SLV_WR_BUF_DONE (BIT(1)) -#define SPI_SLV_RD_BUF_DONE (BIT(0)) - -#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) -#define SPI_SLV_STATUS_BITLEN 0x0000001F -#define SPI_SLV_STATUS_BITLEN_S 27 -#define SPI_SLV_BUF_BITLEN 0x000001FF -#define SPI_SLV_BUF_BITLEN_S 16 -#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F -#define SPI_SLV_RD_ADDR_BITLEN_S 10 -#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F -#define SPI_SLV_WR_ADDR_BITLEN_S 4 -#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) -#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) -#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) -#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) - -#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0x000000FF -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0x000000FF -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 -#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0x000000FF +// Copyright 2010-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define REG_SPI_BASE(i) (0x60000200-i*0x100) +#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) + +#define SPI_FLASH_READ BIT31 +#define SPI_FLASH_WREN BIT30 +#define SPI_FLASH_WRDI BIT29 +#define SPI_FLASH_RDID BIT28 +#define SPI_FLASH_RDSR BIT27 +#define SPI_FLASH_WRSR BIT26 +#define SPI_FLASH_PP BIT25 +#define SPI_FLASH_SE BIT24 +#define SPI_FLASH_BE BIT23 +#define SPI_FLASH_CE BIT22 +#define SPI_FLASH_RES BIT20 + +#define SPI_USR (BIT(18)) + +#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) + +#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) +#define SPI_WR_BIT_ORDER (BIT(26)) +#define SPI_RD_BIT_ORDER (BIT(25)) +#define SPI_QIO_MODE (BIT(24)) +#define SPI_DIO_MODE (BIT(23)) +#define SPI_QOUT_MODE (BIT(20)) +#define SPI_DOUT_MODE (BIT(14)) +#define SPI_FASTRD_MODE (BIT(13)) + +#define SPI_CTRL1(i) (REG_SPI_BASE(i) + 0xc) +#define SPI_CS_HOLD_DELAY 0xf +#define SPI_CS_HOLD_DELAY_S 28 +#define SPI_CS_HOLD_DELAY_RES 0xfff +#define SPI_CS_HOLD_DELAY_RES_S 16 + + +#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) + +#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) + +#define SPI_CS_DELAY_NUM 0x0000000F +#define SPI_CS_DELAY_NUM_S 28 +#define SPI_CS_DELAY_MODE 0x00000003 +#define SPI_CS_DELAY_MODE_S 26 +#define SPI_MOSI_DELAY_NUM 0x00000007 +#define SPI_MOSI_DELAY_NUM_S 23 +#define SPI_MOSI_DELAY_MODE 0x00000003 +#define SPI_MOSI_DELAY_MODE_S 21 +#define SPI_MISO_DELAY_NUM 0x00000007 +#define SPI_MISO_DELAY_NUM_S 18 +#define SPI_MISO_DELAY_MODE 0x00000003 +#define SPI_MISO_DELAY_MODE_S 16 +#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) +#define SPI_CLK_EQU_SYSCLK (BIT(31)) +#define SPI_CLKDIV_PRE 0x00001FFF +#define SPI_CLKDIV_PRE_S 18 +#define SPI_CLKCNT_N 0x0000003F +#define SPI_CLKCNT_N_S 12 +#define SPI_CLKCNT_H 0x0000003F +#define SPI_CLKCNT_H_S 6 +#define SPI_CLKCNT_L 0x0000003F +#define SPI_CLKCNT_L_S 0 + +#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) +#define SPI_USR_COMMAND (BIT(31)) +#define SPI_USR_ADDR (BIT(30)) +#define SPI_USR_DUMMY (BIT(29)) +#define SPI_USR_MISO (BIT(28)) +#define SPI_USR_MOSI (BIT(27)) + +#define SPI_USR_MOSI_HIGHPART (BIT(25)) +#define SPI_USR_MISO_HIGHPART (BIT(24)) + + +#define SPI_SIO (BIT(16)) +#define SPI_FWRITE_QIO (BIT(15)) +#define SPI_FWRITE_DIO (BIT(14)) +#define SPI_FWRITE_QUAD (BIT(13)) +#define SPI_FWRITE_DUAL (BIT(12)) +#define SPI_WR_BYTE_ORDER (BIT(11)) +#define SPI_RD_BYTE_ORDER (BIT(10)) +#define SPI_CK_OUT_EDGE (BIT(7)) +#define SPI_CK_I_EDGE (BIT(6)) +#define SPI_CS_SETUP (BIT(5)) +#define SPI_CS_HOLD (BIT(4)) +#define SPI_FLASH_MODE (BIT(2)) + +#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) +#define SPI_USR_ADDR_BITLEN 0x0000003F +#define SPI_USR_ADDR_BITLEN_S 26 +#define SPI_USR_MOSI_BITLEN 0x000001FF +#define SPI_USR_MOSI_BITLEN_S 17 +#define SPI_USR_MISO_BITLEN 0x000001FF +#define SPI_USR_MISO_BITLEN_S 8 + +#define SPI_USR_DUMMY_CYCLELEN 0x000000FF +#define SPI_USR_DUMMY_CYCLELEN_S 0 + +#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) +#define SPI_USR_COMMAND_BITLEN 0x0000000F +#define SPI_USR_COMMAND_BITLEN_S 28 +#define SPI_USR_COMMAND_VALUE 0x0000FFFF +#define SPI_USR_COMMAND_VALUE_S 0 + +#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) +#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) +#define SPI_IDLE_EDGE (BIT(29)) +#define SPI_CS2_DIS (BIT(2)) +#define SPI_CS1_DIS (BIT(1)) +#define SPI_CS0_DIS (BIT(0)) + +#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) +#define SPI_SYNC_RESET (BIT(31)) +#define SPI_SLAVE_MODE (BIT(30)) +#define SPI_SLV_WR_RD_BUF_EN (BIT(29)) +#define SPI_SLV_WR_RD_STA_EN (BIT(28)) +#define SPI_SLV_CMD_DEFINE (BIT(27)) +#define SPI_TRANS_CNT 0x0000000F +#define SPI_TRANS_CNT_S 23 +#define SPI_TRANS_DONE_EN (BIT(9)) +#define SPI_SLV_WR_STA_DONE_EN (BIT(8)) +#define SPI_SLV_RD_STA_DONE_EN (BIT(7)) +#define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) +#define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) + + + +#define SLV_SPI_INT_EN 0x0000001f +#define SLV_SPI_INT_EN_S 5 + +#define SPI_TRANS_DONE (BIT(4)) +#define SPI_SLV_WR_STA_DONE (BIT(3)) +#define SPI_SLV_RD_STA_DONE (BIT(2)) +#define SPI_SLV_WR_BUF_DONE (BIT(1)) +#define SPI_SLV_RD_BUF_DONE (BIT(0)) + +#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) +#define SPI_SLV_STATUS_BITLEN 0x0000001F +#define SPI_SLV_STATUS_BITLEN_S 27 +#define SPI_SLV_BUF_BITLEN 0x000001FF +#define SPI_SLV_BUF_BITLEN_S 16 +#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F +#define SPI_SLV_RD_ADDR_BITLEN_S 10 +#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F +#define SPI_SLV_WR_ADDR_BITLEN_S 4 + +#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) +#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) +#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) +#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) + + + +#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) +#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF +#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 +#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF +#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 +#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF #define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 - -#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) -#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_WRSTA_CMD_VALUE_S 24 -#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_RDSTA_CMD_VALUE_S 16 -#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_WRBUF_CMD_VALUE_S 8 -#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_RDBUF_CMD_VALUE_S 0 - -#define SPI_W0(i) (REG_SPI_BASE(i) + 0x40) -#define SPI_W1(i) (REG_SPI_BASE(i) + 0x44) -#define SPI_W2(i) (REG_SPI_BASE(i) + 0x48) -#define SPI_W3(i) (REG_SPI_BASE(i) + 0x4C) -#define SPI_W4(i) (REG_SPI_BASE(i) + 0x50) -#define SPI_W5(i) (REG_SPI_BASE(i) + 0x54) -#define SPI_W6(i) (REG_SPI_BASE(i) + 0x58) -#define SPI_W7(i) (REG_SPI_BASE(i) + 0x5C) -#define SPI_W8(i) (REG_SPI_BASE(i) + 0x60) -#define SPI_W9(i) (REG_SPI_BASE(i) + 0x64) -#define SPI_W10(i) (REG_SPI_BASE(i) + 0x68) -#define SPI_W11(i) (REG_SPI_BASE(i) + 0x6C) -#define SPI_W12(i) (REG_SPI_BASE(i) + 0x70) -#define SPI_W13(i) (REG_SPI_BASE(i) + 0x74) -#define SPI_W14(i) (REG_SPI_BASE(i) + 0x78) -#define SPI_W15(i) (REG_SPI_BASE(i) + 0x7C) - -#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) - -#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) -#define SPI_INT_HOLD_ENA 0x00000003 -#define SPI_INT_HOLD_ENA_S 0 - -#endif // SPI_REGISTER_H_INCLUDED +#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF +#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 + +#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) +#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF +#define SPI_SLV_WRSTA_CMD_VALUE_S 24 +#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF +#define SPI_SLV_RDSTA_CMD_VALUE_S 16 +#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF +#define SPI_SLV_WRBUF_CMD_VALUE_S 8 +#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF +#define SPI_SLV_RDBUF_CMD_VALUE_S 0 + +#define SPI_W0(i) (REG_SPI_BASE(i) +0x40) +#define SPI_W1(i) (REG_SPI_BASE(i) +0x44) +#define SPI_W2(i) (REG_SPI_BASE(i) +0x48) +#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) +#define SPI_W4(i) (REG_SPI_BASE(i) +0x50) +#define SPI_W5(i) (REG_SPI_BASE(i) +0x54) +#define SPI_W6(i) (REG_SPI_BASE(i) +0x58) +#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) +#define SPI_W8(i) (REG_SPI_BASE(i) +0x60) +#define SPI_W9(i) (REG_SPI_BASE(i) +0x64) +#define SPI_W10(i) (REG_SPI_BASE(i) +0x68) +#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) +#define SPI_W12(i) (REG_SPI_BASE(i) +0x70) +#define SPI_W13(i) (REG_SPI_BASE(i) +0x74) +#define SPI_W14(i) (REG_SPI_BASE(i) +0x78) +#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) + +#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) + +#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) +#define SPI_INT_HOLD_ENA 0x00000003 +#define SPI_INT_HOLD_ENA_S 0 + +#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) +#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) + +#define SPI_ENABLE_AHB BIT17 + +#define SPI_FLASH_CLK_EQU_SYSCLK BIT12 + +//SPI flash command +#define SPI_FLASH_READ BIT31 +#define SPI_FLASH_WREN BIT30 +#define SPI_FLASH_WRDI BIT29 +#define SPI_FLASH_RDID BIT28 +#define SPI_FLASH_RDSR BIT27 +#define SPI_FLASH_WRSR BIT26 +#define SPI_FLASH_PP BIT25 +#define SPI_FLASH_SE BIT24 +#define SPI_FLASH_BE BIT23 +#define SPI_FLASH_CE BIT22 +#define SPI_FLASH_RES BIT20 +#define SPI_FLASH_DPD BIT21 +#define SPI_FLASH_HPM BIT19 + +//SPI address register +#define SPI_FLASH_BYTES_LEN 24 +#define SPI_BUFF_BYTE_NUM 32 +#define IODATA_START_ADDR BIT0 + +//SPI status register +#define SPI_FLASH_BUSY_FLAG BIT0 +#define SPI_FLASH_WRENABLE_FLAG BIT1 +#define SPI_FLASH_BP0 BIT2 +#define SPI_FLASH_BP1 BIT3 +#define SPI_FLASH_BP2 BIT4 +#define SPI_FLASH_TOP_BOT_PRO_FLAG BIT5 +#define SPI_FLASH_STATUS_PRO_FLAG BIT7 + +#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2) + +#define SPI 0 + +#define PERIPHS_SPI_FLASH_C0 SPI_W0(SPI) +#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(SPI) +#define PERIPHS_SPI_FLASH_CMD SPI_CMD(SPI) + +#define SPI0_CLK_EQU_SYSCLK BIT8 + +#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c) + +#define CACHE_MAP_1M_HIGH BIT25 +#define CACHE_MAP_2M BIT24 +#define CACHE_MAP_SEGMENT_S 16 +#define CACHE_MAP_SEGMENT_MASK 0x3 +#define CACHE_BASE_ADDR 0x40200000 +#define CACHE_2M_SIZE 0x00200000 +#define CACHE_1M_SIZE 0x00100000 + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp8266/spi_struct.h b/components/esp8266/include/esp8266/spi_struct.h new file mode 100644 index 000000000..fd60cd272 --- /dev/null +++ b/components/esp8266/include/esp8266/spi_struct.h @@ -0,0 +1,236 @@ +// Copyright 2010-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile struct { + union { + struct { + uint32_t reserved0: 18; /*reserved*/ + uint32_t usr: 1; /*User define command enable. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_hpm: 1; /*Drive Flash into high performance mode. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_res: 1; /*This bit combined with reg_resandres bit releases Flash from the power-down state or high performance mode and obtains the devices ID. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_dp: 1; /*Drive Flash into power down. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_ce: 1; /*Chip erase enable. Chip erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_be: 1; /*Block erase enable(32KB) . Block erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_se: 1; /*Sector erase enable(4KB). Sector erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_pp: 1; /*Page program enable(1 byte ~256 bytes data to be programmed). Page program operation will be triggered when the bit is set. The bit will be cleared once the operation done .1: enable 0: disable.*/ + uint32_t flash_wrsr: 1; /*Write status register enable. Write status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_rdsr: 1; /*Read status register-1. Read status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/ + uint32_t flash_rdid: 1; /*Read JEDEC ID . Read ID command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/ + uint32_t flash_wrdi: 1; /*Write flash disable. Write disable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/ + uint32_t flash_wren: 1; /*Write flash enable. Write enable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/ + uint32_t flash_read: 1; /*Read flash enable. Read flash operation will be triggered when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/ + }; + uint32_t val; + } cmd; + uint32_t addr; /*addr to slave / from master. SPI transfer from the MSB to the LSB. If length > 32 bits, then address continues from MSB of wr_status.*/ + union { + struct { + uint32_t clkcnt_l: 4; + uint32_t clkcnt_h: 4; + uint32_t clkcnt_n: 4; + uint32_t clk_equ_sysclk: 1; + uint32_t fastrd_mode: 1; /*This bit enable the bits: spi_fread_qio spi_fread_dio spi_fread_qout and spi_fread_dout. 1: enable 0: disable.*/ + uint32_t fread_dual: 1; /*In the read operations read-data phase apply 2 signals. 1: enable 0: disable.*/ + uint32_t reserved15: 5; /*reserved*/ + uint32_t fread_quad: 1; /*In the read operations read-data phase apply 4 signals. 1: enable 0: disable.*/ + uint32_t reserved21: 2; /*reserved*/ + uint32_t fread_dio: 1; /*In the read operations address phase and read-data phase apply 2 signals. 1: enable 0: disable.*/ + uint32_t fread_qio: 1; /*In the read operations address phase and read-data phase apply 4 signals. 1: enable 0: disable.*/ + uint32_t rd_bit_order: 1; /*In read-data (MISO) phase 1: LSB first 0: MSB first*/ + uint32_t wr_bit_order: 1; /*In command address write-data (MOSI) phases 1: LSB firs 0: MSB first*/ + uint32_t reserved27: 5; /*reserved*/ + }; + uint32_t val; + } ctrl; + union { + struct { + uint32_t reserved0: 16; /*reserved*/ + uint32_t cs_hold_delay_res: 12; /*Delay cycles of resume Flash when resume Flash is enable by spi clock.*/ + uint32_t cs_hold_delay: 4; /*SPI cs signal is delayed by spi clock cycles*/ + }; + uint32_t val; + } ctrl1; + union { + struct { + uint32_t status: 16; /*In the slave mode, it is the status for master to read out.*/ + uint32_t wb_mode: 8; /*Mode bits in the flash fast read mode, it is combined with spi_fastrd_mode bit.*/ + uint32_t status_ext: 8; /*In the slave mode,it is the status for master to read out.*/ + }; + uint32_t val; + } rd_status; /*In the slave mode, this register are the status register for the master to read out.*/ + union { + struct { + uint32_t reserved0: 16; /*reserved*/ + uint32_t miso_delay_mode: 2; /*MISO signals are delayed by spi_clk. 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/ + uint32_t miso_delay_num: 3; /*MISO signals are delayed by system clock cycles*/ + uint32_t mosi_delay_mode: 2; /*MOSI signals are delayed by spi_clk. 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/ + uint32_t mosi_delay_num: 3; /*MOSI signals are delayed by system clock cycles*/ + uint32_t cs_delay_mode: 2; /*spi_cs signal is delayed by spi_clk . 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/ + uint32_t cs_delay_num: 4; /*spi_cs signal is delayed by system clock cycles*/ + }; + uint32_t val; + } ctrl2; + union { + struct { + uint32_t clkcnt_l: 6; /*In the master mode it must be equal to spi_clkcnt_n. In the slave mode it must be 0.*/ + uint32_t clkcnt_h: 6; /*In the master mode it must be floor((spi_clkcnt_n+1)/2-1). In the slave mode it must be 0.*/ + uint32_t clkcnt_n: 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_n+1)*/ + uint32_t clkdiv_pre: 13; /*In the master mode it is pre-divider of spi_clk.*/ + uint32_t clk_equ_sysclk: 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/ + }; + uint32_t val; + } clock; + union { + struct { + uint32_t duplex: 1; + uint32_t reserved1: 1; /*reserved*/ + uint32_t flash_mode: 1; + uint32_t reserved3: 1; /*reserved*/ + uint32_t cs_hold: 1; /*spi cs keep low when spi is in done phase. 1: enable 0: disable.*/ + uint32_t cs_setup: 1; /*spi cs is enable when spi is in prepare phase. 1: enable 0: disable.*/ + uint32_t ck_i_edge: 1; /*In the slave mode the bit is same as spi_ck_out_edge in master mode. It is combined with spi_miso_delay_mode bits.*/ + uint32_t ck_out_edge: 1; /*the bit combined with spi_mosi_delay_mode bits to set mosi signal delay mode.*/ + uint32_t reserved8: 2; /*reserved*/ + uint32_t rd_byte_order: 1; /*In read-data (MISO) phase 1: big-endian 0: little_endian*/ + uint32_t wr_byte_order: 1; /*In command address write-data (MOSI) phases 1: big-endian 0: litte_endian*/ + uint32_t fwrite_dual: 1; /*In the write operations write-data phase apply 2 signals*/ + uint32_t fwrite_quad: 1; /*In the write operations write-data phase apply 4 signals*/ + uint32_t fwrite_dio: 1; /*In the write operations address phase and write-data phase apply 2 signals.*/ + uint32_t fwrite_qio: 1; /*In the write operations address phase and write-data phase apply 4 signals.*/ + uint32_t sio: 1; /*Set the bit to enable 3-line half duplex communication mosi and miso signals share the same pin. 1: enable 0: disable.*/ + uint32_t reserved17: 7; /*reserved*/ + uint32_t usr_miso_highpart: 1; /*read-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable.*/ + uint32_t usr_mosi_highpart: 1; /*write-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable.*/ + uint32_t reserved26: 1; /*reserved*/ + uint32_t usr_mosi: 1; /*This bit enable the write-data phase of an operation.*/ + uint32_t usr_miso: 1; /*This bit enable the read-data phase of an operation.*/ + uint32_t usr_dummy: 1; /*This bit enable the dummy phase of an operation.*/ + uint32_t usr_addr: 1; /*This bit enable the address phase of an operation.*/ + uint32_t usr_command: 1; /*This bit enable the command phase of an operation.*/ + }; + uint32_t val; + } user; + union { + struct { + uint32_t usr_dummy_cyclelen: 8; /*The length in spi_clk cycles of dummy phase. The register value shall be (cycle_num-1).*/ + uint32_t usr_miso_bitlen: 9; /*The length in bits of read-data. The register value shall be (bit_num-1).*/ + uint32_t usr_mosi_bitlen: 9; /*The length in bits of write-data. The register value shall be (bit_num-1).*/ + uint32_t usr_addr_bitlen: 6; /*The length in bits of address phase. The register value shall be (bit_num-1).*/ + }; + uint32_t val; + } user1; + union { + struct { + uint32_t usr_command_value: 16; /*The value of command. Output sequence: bit 7-0 and then 15-8.*/ + uint32_t reserved16: 12; /*reserved*/ + uint32_t usr_command_bitlen: 4; /*The length in bits of command phase. The register value shall be (bit_num-1)*/ + }; + uint32_t val; + } user2; + uint32_t wr_status; /*In the slave mode this register are the status register for the master to write into. In the master mode this register are the higher 32bits in the 64 bits address condition.*/ + union { + struct { + uint32_t cs0_dis: 1; /*SPI CS0 pin enable, 1: disable CS0, 0: spi_cs0 signal is from/to CS0 pin*/ + uint32_t cs1_dis: 1; /*SPI CS1 pin enable, 1: disable CS1, 0: spi_cs1 signal is from/to CS1 pin*/ + uint32_t cs2_dis: 1; /*SPI CS2 pin enable, 1: disable CS2, 0: spi_cs2 signal is from/to CS2 pin*/ + uint32_t reserved3: 16; /*reserved*/ + uint32_t slave_mode: 1; /*1: Both CLK and CS are input, 0: Both CLK and CS are output*/ + uint32_t reserved20: 9; /*reserved*/ + uint32_t ck_idle_edge: 1; /*1: spi clk line is high when idle 0: spi clk line is low when idle*/ + uint32_t reserved30: 2; /*reserved*/ + }; + uint32_t val; + } pin; + union { + struct { + uint32_t rd_buf_done: 1; /*The interrupt raw bit for the completion of read-buffer operation in the slave mode.*/ + uint32_t wr_buf_done: 1; /*The interrupt raw bit for the completion of write-buffer operation in the slave mode.*/ + uint32_t rd_sta_done: 1; /*The interrupt raw bit for the completion of read-status operation in the slave mode.*/ + uint32_t wr_sta_done: 1; /*The interrupt raw bit for the completion of write-status operation in the slave mode.*/ + uint32_t trans_done: 1; /*The interrupt raw bit for the completion of any operation in both the master mode and the slave mode.*/ + uint32_t rd_buf_inten: 1; /*The interrupt enable bit for the completion of read-buffer operation in the slave mode.*/ + uint32_t wr_buf_inten: 1; /*The interrupt enable bit for the completion of write-buffer operation in the slave mode.*/ + uint32_t rd_sta_inten: 1; /*The interrupt enable bit for the completion of read-status operation in the slave mode.*/ + uint32_t wr_sta_inten: 1; /*The interrupt enable bit for the completion of write-status operation in the slave mode.*/ + uint32_t trans_inten: 1; /*The interrupt enable bit for the completion of any operation in both the master mode and the slave mode.*/ + uint32_t reserved10: 13; /*reserved*/ + uint32_t trans_cnt: 4; /*The operations counter in both the master mode and the slave mode.*/ + uint32_t cmd_define: 1; /*1: slave mode commands are defined in SPI_SLAVE3. 0: slave mode commands are fixed as: 1: write-status 2: write-buffer and 3: read-buffer 4: read-status*/ + uint32_t wr_rd_sta_en: 1; /*write and read status enable in the slave mode*/ + uint32_t wr_rd_buf_en: 1; /*write and read buffer enable in the slave mode*/ + uint32_t slave_mode: 1; /*1: slave mode 0: master mode.*/ + uint32_t sync_reset: 1; /*Software reset enable, reset the spi clock line cs line and data lines.*/ + }; + uint32_t val; + } slave; + union { + struct { + uint32_t rdbuf_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for read-buffer operations.*/ + uint32_t wrbuf_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for write-buffer operations.*/ + uint32_t rdsta_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for read-status operations.*/ + uint32_t wrsta_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for write-status operations.*/ + uint32_t wr_addr_bitlen: 6; /*In the slave mode it is the address length in bits for write-buffer operation. The register value shall be (bit_num-1).*/ + uint32_t rd_addr_bitlen: 6; /*In the slave mode it is the address length in bits for read-buffer operation. The register value shall be (bit_num-1).*/ + uint32_t buf_bitlen: 9; /*In the slave mode it is the length of buffer bit.*/ + uint32_t status_readback: 1; /*In the slave mode it is the bit decide whether master reads rd_status register or wr_status register data. 0: rd_status: 1: wr_status*/ + uint32_t reserved25: 1; /*reserved*/ + uint32_t status_bitlen: 5; /*In the slave mode it is the length of status bit.*/ + }; + uint32_t val; + } slave1; + union { + struct { + uint32_t rdsta_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for read-status operations. The register value shall be (cycle_num-1).*/ + uint32_t wrsta_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for write-status operations. The register value shall be (cycle_num-1).*/ + uint32_t rdbuf_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for read-buffer operations. The register value shall be (cycle_num-1).*/ + uint32_t wrbuf_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for write-buffer operations. The register value shall be (cycle_num-1).*/ + }; + uint32_t val; + } slave2; + union { + struct { + uint32_t rdbuf_cmd_value: 8; /*In the slave mode it is the value of read-buffer command.*/ + uint32_t wrbuf_cmd_value: 8; /*In the slave mode it is the value of write-buffer command.*/ + uint32_t rdsta_cmd_value: 8; /*In the slave mode it is the value of read-status command.*/ + uint32_t wrsta_cmd_value: 8; /*In the slave mode it is the value of write-status command.*/ + }; + uint32_t val; + } slave3; + uint32_t data_buf[16]; /*data buffer*/ + uint32_t reserved_80[30]; + uint32_t ext2; + union { + struct { + uint32_t int_hold_ena: 2; /*This register is for two SPI masters to share the same cs clock and data signals. The bits of one SPI are set if the other SPI is busy the SPI will be hold. 1(3): hold at ,idle, phase 2: hold at ,prepare, phase.*/ + uint32_t reserved2: 30; /*reserved*/ + }; + uint32_t val; + } ext3; +} spi_dev_t; + +extern spi_dev_t SPI0; +extern spi_dev_t SPI1; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp8266/timer_struct.h b/components/esp8266/include/esp8266/timer_struct.h new file mode 100644 index 000000000..518c5b0a4 --- /dev/null +++ b/components/esp8266/include/esp8266/timer_struct.h @@ -0,0 +1,70 @@ +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp8266/eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ESP8266 FRC Register Definitions */ + +// FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero. +typedef struct { + union { + struct { + uint32_t data: 23; + uint32_t reserved23: 9; + }; + uint32_t val; + } load; + + union { + struct { + uint32_t data: 23; + uint32_t reserved23: 9; + }; + uint32_t val; + } count; + + union { + struct { + uint32_t div: 6; + uint32_t reload: 1; + uint32_t en: 1; + uint32_t intr_type: 1; + uint32_t reserved24: 23; + }; + uint32_t val; + } ctrl; + + union { + struct { + uint32_t clr: 1; + uint32_t reserved1: 31; + }; + uint32_t val; + } intr; +} frc1_struct_t; + +extern volatile frc1_struct_t frc1; + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ + diff --git a/components/esp8266/include/esp_attr.h b/components/esp8266/include/esp_attr.h index 61d73236d..d5b14d38b 100644 --- a/components/esp8266/include/esp_attr.h +++ b/components/esp8266/include/esp_attr.h @@ -26,10 +26,10 @@ #define ICACHE_RODATA_ATTR // Forces code into IRAM instead of flash. -#define IRAM_ATTR __attribute__((section(".iram1"))) +#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__) // Forces data into DRAM instead of flash -#define DRAM_ATTR __attribute__((section(".dram0"))) +#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram0", __COUNTER__) // Forces data to be 4 bytes aligned #define WORD_ALIGNED_ATTR __attribute__((aligned(4))) @@ -41,9 +41,37 @@ // Forces data into RTC memory. // Any variable marked with this attribute will keep its value // during a deep sleep / wake cycle. -#define RTC_DATA_ATTR __attribute__((section(".rtc.data"))) +#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__) // Forces read-only data into RTC memory. -#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata"))) +#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__) + +// Forces data into RTC memory of .noinit section. +// Any variable marked with this attribute will keep its value +// after restart or during a deep sleep / wake cycle. +#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__) + +// Forces data into noinit section to avoid initialization after restart. +#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__) + +// Forces to put some user defined data in the binary file header, the offset is 0x10. +#define USER_DATA_ATTR _SECTION_ATTR_IMPL(".user.data", __COUNTER__) + +// Implementation for a unique custom section +// +// This prevents gcc producing "x causes a section type conflict with y" +// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section +// +// Using unique sections also means --gc-sections can remove unused +// data with a custom section type set +#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER)))) + +#define _COUNTER_STRINGIFY(COUNTER) #COUNTER + +#ifdef IDF_CI_BUILD +#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON))) +#else +#define IDF_DEPRECATED(REASON) +#endif #endif /* __ESP_ATTR_H__ */ diff --git a/components/esp8266/include/esp_clk.h b/components/esp8266/include/esp_clk.h new file mode 100644 index 000000000..7298b090e --- /dev/null +++ b/components/esp8266/include/esp_clk.h @@ -0,0 +1,25 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @brief Return current CPU clock frequency + * When frequency switching is performed, this frequency may change. + * However it is guaranteed that the frequency never changes with a critical + * section. + * + * @return CPU clock frequency, in Hz + */ +int esp_clk_cpu_freq(void); diff --git a/components/util/include/crc.h b/components/esp8266/include/esp_crc.h similarity index 100% rename from components/util/include/crc.h rename to components/esp8266/include/esp_crc.h diff --git a/components/esp8266/include/esp_err.h b/components/esp8266/include/esp_err.h deleted file mode 100644 index f1fd783d1..000000000 --- a/components/esp8266/include/esp_err.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int32_t esp_err_t; - -/* Definitions for error constants. */ - -#define ESP_OK 0 -#define ESP_FAIL -1 - -#define ESP_ERR_NO_MEM 0x101 -#define ESP_ERR_INVALID_ARG 0x102 -#define ESP_ERR_INVALID_STATE 0x103 -#define ESP_ERR_INVALID_SIZE 0x104 -#define ESP_ERR_NOT_FOUND 0x105 -#define ESP_ERR_NOT_SUPPORTED 0x106 -#define ESP_ERR_TIMEOUT 0x107 -#define ESP_ERR_INVALID_RESPONSE 0x108 -#define ESP_ERR_INVALID_CRC 0x109 -#define ESP_ERR_INVALID_VERSION 0x10A -#define ESP_ERR_INVALID_MAC 0x10B - -#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */ -#define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */ - -/** - * @brief Returns string for esp_err_t error codes - * - * This function finds the error code in a pre-generated lookup-table and - * returns its string representation. - * - * The function is generated by the Python script - * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t - * error is modified, created or removed from the IDF project. - * - * @param code esp_err_t error code - * @return string error message - */ -const char *esp_err_to_name(esp_err_t code); - -/** - * @brief Returns string for esp_err_t and system error codes - * - * This function finds the error code in a pre-generated lookup-table of - * esp_err_t errors and returns its string representation. If the error code - * is not found then it is attempted to be found among system errors. - * - * The function is generated by the Python script - * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t - * error is modified, created or removed from the IDF project. - * - * @param code esp_err_t error code - * @param[out] buf buffer where the error message should be written - * @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte). - * @return buf containing the string error message - */ -const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen); - -void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn)); - -#ifndef __ASSERT_FUNC -/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which - uses /usr/include/assert.h or equivalent. -*/ -#ifdef __ASSERT_FUNCTION -#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */ -#else -#define __ASSERT_FUNC "??" -#endif -#endif - -/** - * Macro which can be used to check the error code, - * and terminate the program in case the code is not ESP_OK. - * Prints the error code, error location, and the failed statement to serial output. - * - * Disabled if assertions are disabled. - */ -#ifdef NDEBUG -#define ESP_ERROR_CHECK(x) do { \ - esp_err_t __err_rc = (x); \ - (void) sizeof(__err_rc); \ - } while(0); -#else -#define ESP_ERROR_CHECK(x) do { \ - esp_err_t __err_rc = (x); \ - if (__err_rc != ESP_OK) { \ - _esp_error_check_failed(__err_rc, __ESP_FILE__, __LINE__, \ - __ASSERT_FUNC, #x); \ - } \ - } while(0); -#endif - -#ifdef __cplusplus -} -#endif diff --git a/components/esp8266/include/esp_event.h b/components/esp8266/include/esp_event.h deleted file mode 100644 index 0a792bc25..000000000 --- a/components/esp8266/include/esp_event.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __ESP_EVENT_H__ -#define __ESP_EVENT_H__ - -#include -#include - -#include "esp_err.h" -#include "esp_wifi_types.h" -#include "lwip/ip_addr.h" -#include "tcpip_adapter.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ESP_EVENT_IPV6 LWIP_IPV6 - -typedef enum { - SYSTEM_EVENT_WIFI_READY = 0, /**< ESP8266 WiFi ready */ - SYSTEM_EVENT_SCAN_DONE, /**< ESP8266 finish scanning AP */ - SYSTEM_EVENT_STA_START, /**< ESP8266 station start */ - SYSTEM_EVENT_STA_STOP, /**< ESP8266 station stop */ - SYSTEM_EVENT_STA_CONNECTED, /**< ESP8266 station connected to AP */ - SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP8266 station disconnected from AP */ - SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP8266 station changed */ - SYSTEM_EVENT_STA_GOT_IP, /**< ESP8266 station got IP from connected AP */ - SYSTEM_EVENT_STA_LOST_IP, /**< ESP8266 station lost IP and the IP is reset to 0 */ - SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /**< ESP8266 station wps succeeds in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP8266 station wps fails in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP8266 station wps timeout in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP8266 station wps pin code in enrollee mode */ - SYSTEM_EVENT_AP_START, /**< ESP8266 soft-AP start */ - SYSTEM_EVENT_AP_STOP, /**< ESP8266 soft-AP stop */ - SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP8266 soft-AP */ - SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP8266 soft-AP */ - SYSTEM_EVENT_AP_STAIPASSIGNED, /**< ESP8266 soft-AP assign an IP to a connected station */ - SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ - SYSTEM_EVENT_GOT_IP6, /**< ESP8266 station or ap or ethernet interface v6IP addr is preferred */ - SYSTEM_EVENT_ETH_START, /**< ESP8266 ethernet start */ - SYSTEM_EVENT_ETH_STOP, /**< ESP8266 ethernet stop */ - SYSTEM_EVENT_ETH_CONNECTED, /**< ESP8266 ethernet phy link up */ - SYSTEM_EVENT_ETH_DISCONNECTED, /**< ESP8266 ethernet phy link down */ - SYSTEM_EVENT_ETH_GOT_IP, /**< ESP8266 ethernet got IP from connected AP */ - SYSTEM_EVENT_MAX -} system_event_id_t; - -/* add this macro define for compatible with old IDF version */ -#ifndef SYSTEM_EVENT_AP_STA_GOT_IP6 -#define SYSTEM_EVENT_AP_STA_GOT_IP6 SYSTEM_EVENT_GOT_IP6 -#endif - -typedef enum { - WPS_FAIL_REASON_NORMAL = 0, /**< ESP8266 WPS normal fail reason */ - WPS_FAIL_REASON_RECV_M2D, /**< ESP8266 WPS receive M2D frame */ - WPS_FAIL_REASON_MAX -}system_event_sta_wps_fail_reason_t; - -typedef struct { - uint32_t status; /**< status of scanning APs */ - uint8_t number; - uint8_t scan_id; -} system_event_sta_scan_done_t; - -typedef struct { - uint8_t ssid[32]; /**< SSID of connected AP */ - uint8_t ssid_len; /**< SSID length of connected AP */ - uint8_t bssid[6]; /**< BSSID of connected AP*/ - uint8_t channel; /**< channel of connected AP*/ - wifi_auth_mode_t authmode; -} system_event_sta_connected_t; - -typedef struct { - uint8_t ssid[32]; /**< SSID of disconnected AP */ - uint8_t ssid_len; /**< SSID length of disconnected AP */ - uint8_t bssid[6]; /**< BSSID of disconnected AP */ - uint8_t reason; /**< reason of disconnection */ -} system_event_sta_disconnected_t; - -typedef struct { - wifi_auth_mode_t old_mode; /**< the old auth mode of AP */ - wifi_auth_mode_t new_mode; /**< the new auth mode of AP */ -} system_event_sta_authmode_change_t; - -typedef struct { - tcpip_adapter_ip_info_t ip_info; - bool ip_changed; -} system_event_sta_got_ip_t; - -typedef struct { - uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ -} system_event_sta_wps_er_pin_t; - -typedef struct { - tcpip_adapter_if_t if_index; - tcpip_adapter_ip6_info_t ip6_info; -} system_event_got_ip6_t; - -typedef struct { - uint8_t mac[6]; /**< MAC address of the station connected to ESP8266 soft-AP */ - uint8_t aid; /**< the aid that ESP8266 soft-AP gives to the station connected to */ -} system_event_ap_staconnected_t; - -typedef struct { - uint8_t mac[6]; /**< MAC address of the station disconnects to ESP8266 soft-AP */ - uint8_t aid; /**< the aid that ESP8266 soft-AP gave to the station disconnects to */ -} system_event_ap_stadisconnected_t; - -typedef struct { - int rssi; /**< Received probe request signal strength */ - uint8_t mac[6]; /**< MAC address of the station which send probe request */ -} system_event_ap_probe_req_rx_t; - -typedef union { - system_event_sta_connected_t connected; /**< ESP8266 station connected to AP */ - system_event_sta_disconnected_t disconnected; /**< ESP8266 station disconnected to AP */ - system_event_sta_scan_done_t scan_done; /**< ESP8266 station scan (APs) done */ - system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP8266 station connected to changed */ - system_event_sta_got_ip_t got_ip; /**< ESP8266 station got IP, first time got IP or when IP is changed */ - system_event_sta_wps_er_pin_t sta_er_pin; /**< ESP8266 station WPS enrollee mode PIN code received */ - system_event_sta_wps_fail_reason_t sta_er_fail_reason;/**< ESP8266 station WPS enrollee mode failed reason code received */ - system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP8266 soft-AP */ - system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP8266 soft-AP */ - system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP8266 soft-AP receive probe request packet */ - system_event_got_ip6_t got_ip6; /**< ESP8266 station or ap or ethernet ipv6 addr state change to preferred */ -} system_event_info_t; - -typedef struct { - system_event_id_t event_id; /**< event ID */ - system_event_info_t event_info; /**< event information */ -} system_event_t; - -typedef esp_err_t (*system_event_handler_t)(system_event_t *event); - -/** - * @brief Send a event to event task - * - * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task - * - * @param system_event_t * event : event - * - * @return ESP_OK : succeed - * @return others : fail - */ -esp_err_t esp_event_send(system_event_t *event); - -/** - * @brief Default event handler for system events - * - * This function performs default handling of system events. - * When using esp_event_loop APIs, it is called automatically before invoking the user-provided - * callback function. - * - * Applications which implement a custom event loop must call this function - * as part of event processing. - * - * @param event pointer to event to be handled - * @return ESP_OK if an event was handled successfully - */ -esp_err_t esp_event_process_default(system_event_t *event); - -/** - * @brief Install default event handlers for Wi-Fi interfaces (station and AP) - * - */ -void esp_event_set_default_wifi_handlers(); - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_EVENT_H__ */ diff --git a/components/esp8266/include/esp_event_loop.h b/components/esp8266/include/esp_event_loop.h deleted file mode 100644 index 0e582b90a..000000000 --- a/components/esp8266/include/esp_event_loop.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __ESP_EVENT_LOOP_H__ -#define __ESP_EVENT_LOOP_H__ - -#include -#include - -#include "esp_err.h" -#include "esp_event.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" - -#define EVENT_LOOP_STACKSIZE CONFIG_EVENT_LOOP_STACK_SIZE - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Application specified event callback function - * - * @param void *ctx : reserved for user - * @param system_event_t *event : event type defined in this file - * - * @return ESP_OK : succeed - * @return others : fail - */ -typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); - -/** - * @brief Initialize event loop - * Create the event handler and task - * - * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb - * @param void *ctx : reserved for user - * - * @return ESP_OK : succeed - * @return others : fail - */ -esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx); - -/** - * @brief Set application specified event callback function - * - * @attention 1. If cb is NULL, means application don't need to handle - * If cb is not NULL, it will be call when an event is received, after the default event callback is completed - * - * @param system_event_cb_t cb : callback - * @param void *ctx : reserved for user - * - * @return system_event_cb_t : old callback - */ -system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx); - -/** - * @brief Get the queue used by event loop - * - * @attention : currently this API is used to initialize "q" parameter - * of wifi_init structure. - * - * @return QueueHandle_t : event queue handle - */ -QueueHandle_t esp_event_loop_get_queue(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_EVENT_LOOP_H__ */ diff --git a/components/esp8266/include/esp_fast_boot.h b/components/esp8266/include/esp_fast_boot.h new file mode 100644 index 000000000..7aca7ec4b --- /dev/null +++ b/components/esp8266/include/esp_fast_boot.h @@ -0,0 +1,87 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifndef BOOTLOADER_BUILD +#include "esp_partition.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BOOTLOADER_BUILD +/** + * @brief Setting target partition as fast boot partition and enable fast boot function. + * + * @param partition partition which has image to be booted + * + * @return + * - 0 on success + * - -EINVAL parameter error + * - -EIO read flash error + */ +int esp_fast_boot_enable_partition(const esp_partition_t *partition); + +/** + * @brief Setting current running partition as fast boot partition and enable fast boot function. + * + * @return + * - 0 on success + * - -EINVAL current running partition information error + * - -EIO read flash error + */ +int esp_fast_boot_enable(void); + +/** + * @brief Directly running the image which is to be booted after restart. + * + * @note It is just like jumping directly from one APP to another one without running ROM bootloader and level 2 bootloader. + * Using this API, system starting up is fastest. + * + * @return + * - 0 on success + * - -EINVAL booted partition information error + * - -EIO read flash error + */ +int esp_fast_boot_restart(void); +#endif + +/** + * @brief Disabling fast boot function and bootloader will not boot fast. + */ +void esp_fast_boot_disable(void); + +/** + * @brief Getting fast boot information. + * + * @param image_start image startting address in the SPI Flash + * @param image_size image max size in the SPI Flash + * @param image_entry image entry address in the SPI Flash + * + * @return + * - 0 on success + * - -EINVAL fast boot information error + */ +int esp_fast_boot_get_info(uint32_t *image_start, uint32_t *image_size, uint32_t *image_entry); + +/** + * @brief Printing fast boot information. + */ +void esp_fast_boot_print_info(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp_idf_version.h b/components/esp8266/include/esp_idf_version.h new file mode 100644 index 000000000..f1fced226 --- /dev/null +++ b/components/esp8266/include/esp_idf_version.h @@ -0,0 +1,58 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** Major version number (X.x.x) */ +#define ESP_IDF_VERSION_MAJOR 3 +/** Minor version number (x.X.x) */ +#define ESP_IDF_VERSION_MINOR 4 +/** Patch version number (x.x.X) */ +#define ESP_IDF_VERSION_PATCH 0 + +/** + * Macro to convert IDF version number into an integer + * + * To be used in comparisons, such as ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) + */ +#define ESP_IDF_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) + +/** + * Current IDF version, as an integer + * + * To be used in comparisons, such as ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) + */ +#define ESP_IDF_VERSION ESP_IDF_VERSION_VAL(ESP_IDF_VERSION_MAJOR, \ + ESP_IDF_VERSION_MINOR, \ + ESP_IDF_VERSION_PATCH) + +/** + * Return full IDF version string, same as 'git describe' output. + * + * @note If you are printing the ESP-IDF version in a log file or other information, + * this function provides more information than using the numerical version macros. + * For example, numerical version macros don't differentiate between development, + * pre-release and release versions, but the output of this function does. + * + * @return constant string from IDF_VER + */ +const char* esp_get_idf_version(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp_libc.h b/components/esp8266/include/esp_libc.h index e9e018282..d77ea28a4 100644 --- a/components/esp8266/include/esp_libc.h +++ b/components/esp8266/include/esp_libc.h @@ -29,6 +29,7 @@ #include #include #include +#include "rom/ets_sys.h" #ifndef BOOTLOADER_BUILD #include "esp_heap_caps.h" #endif @@ -60,18 +61,6 @@ int ets_putc(int c); */ int ets_vprintf(const char *fmt, va_list ap); -/** - * @brief Printf the strings to uart or other devices, similar with printf, simple than printf. - * Can not print float point data format, or longlong data format. - * - * @param const char *fmt : See printf. - * - * @param ... : See printf. - * - * @return int : the length printed to the output device. - */ -int ets_printf(const char *fmt, ...); - #ifndef os_printf #define os_printf printf #endif diff --git a/components/esp8266/include/esp_module.h b/components/esp8266/include/esp_module.h deleted file mode 100644 index 9818f2feb..000000000 --- a/components/esp8266/include/esp_module.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESP_MODULE_H -#define _ESP_MODULE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define __EXPORT_SYMBOL_NAME(sec) "ksymatab"sec - -#define __EXPORT_SYMBOL(sym, sec) \ - static const typeof(sym) *__ksymtab_##sym \ - __attribute__((used,section("ksymatab"sec))) \ - = &sym - -#define __DECLARE_SYMBOL_NAME(sec) __EXPORT_SYMBOL_NAME(sec) - -#define __DECLARE_SYMBOL(type, sym, sec) \ - static const type sym __attribute__((used,section("ksymatab"sec),aligned(sizeof(void *)))) - -#ifdef __cplusplus -} -#endif - -#endif /* _ESP_MODULE_H */ diff --git a/components/esp8266/include/esp_phy_init.h b/components/esp8266/include/esp_phy_init.h index fb61519d9..19c666a58 100644 --- a/components/esp8266/include/esp_phy_init.h +++ b/components/esp8266/include/esp_phy_init.h @@ -14,7 +14,7 @@ #pragma once #include - +#include "sdkconfig.h" #include "esp_err.h" #ifdef __cplusplus @@ -75,6 +75,15 @@ typedef enum { PHY_MODULE_COUNT //!< Number of items } phy_rf_module_t; +/** + * @brief Outside XTAL 40MHz: 0, 26MHz: 1 + */ +#ifdef CONFIG_ESP8266_XTAL_FREQ_40 +#define ESP8266_XTAL_FLAG (0) +#elif defined(CONFIG_ESP8266_XTAL_FREQ_26) +#define ESP8266_XTAL_FLAG (1) +#endif + /** * @brief Get PHY init data * @@ -165,6 +174,11 @@ esp_err_t esp_phy_rf_deinit(phy_rf_module_t module); */ void esp_phy_load_cal_and_init(phy_rf_module_t module); +/** + * @brief Initializing system hardware clock. + */ +void esp_phy_init_clk(void); + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/esp_private/esp_system_internal.h b/components/esp8266/include/esp_private/esp_system_internal.h new file mode 100644 index 000000000..ff468302b --- /dev/null +++ b/components/esp8266/include/esp_private/esp_system_internal.h @@ -0,0 +1,108 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTC_SYS_RAM_SIZE 256 +#define ESP_SYSTEM_FAST_BOOT_IMAGE 0x5aa5a55a + +/** + * @brief Station's AP base information of old SDK + */ +struct old_ap_ssid { + uint32_t len; //!< SSID length + uint8_t ssid[32]; //!< SSID data + uint8_t passwd[64]; //!< password data +} __attribute__((packed)); + +/** + * @brief System information of old SDK + */ +struct old_sysconf { + uint8_t reserved_1[0x13C]; //!< reserved data + uint8_t ap_number; //!< number of stored AP + uint8_t ap_index; //!< index of current used AP + uint8_t reserved_2[0x2]; //!< reserved data + struct old_ap_ssid ap_ssid[5]; //!< station's AP base information +} __attribute__((packed)); + +/** + * The size of structure must not be larger than 256 bytes and all member varible must be uint32_t type + */ +struct _rtc_sys_info { + uint32_t hint; // software reset reason + uint32_t old_sysconf_addr; /* high) ? high : val) #define PHY_INIT_MAGIC "PHYINIT" static const char phy_init_magic_pre[] = PHY_INIT_MAGIC; @@ -59,12 +61,12 @@ static const esp_phy_init_data_t phy_init_data= { { 0x00, 0xf8, 0xf8, - 0x52, - 0x4e, - 0x4a, - 0x44, - 0x40, - 0x38, + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x52), + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x4e), + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x4a), + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x44), + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x40), + LIMIT(CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER * 4, 0, 0x38), 0x00, 0x00, 0x01, @@ -73,7 +75,7 @@ static const esp_phy_init_data_t phy_init_data= { { 0x03, 0x04, 0x05, - 0x01, + ESP8266_XTAL_FLAG, 0x00, 0x00, 0x00, @@ -132,7 +134,11 @@ static const esp_phy_init_data_t phy_init_data= { { 0x00, 0x00, 0x00, +#ifdef CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST + CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST, +#else 0x00, +#endif 0x00, 0x00, 0x00, diff --git a/components/esp8266/include/esp_private/wifi.h b/components/esp8266/include/esp_private/wifi.h new file mode 100644 index 000000000..841540380 --- /dev/null +++ b/components/esp8266/include/esp_private/wifi.h @@ -0,0 +1,278 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_WIFI_INTERNAL_H +#define _ESP_WIFI_INTERNAL_H + +#include "esp_wifi_types.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_smartconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + WIFI_RX_PBUF_IRAM, /** save rx buffer to iram and upload to tcpip*/ + WIFI_RX_PBUF_DRAM, /** save rx buffer to dram and upload to tcpip */ +} wifi_rx_pbuf_mem_type_t; + +/** + * @brief WiFi log level + * + */ +typedef enum { + WIFI_LOG_ERROR = 0, /*enabled by default*/ + WIFI_LOG_WARNING, /*can be set in menuconfig*/ + WIFI_LOG_INFO, /*can be set in menuconfig*/ + WIFI_LOG_DEBUG, /*can be set in menuconfig*/ + WIFI_LOG_VERBOSE, /*can be set in menuconfig*/ +} wifi_log_level_t; + +/** + * @brief WiFi log submodule definition + * + */ +#define WIFI_LOG_SUBMODULE_NULL (0) +#define WIFI_LOG_SUBMODULE_CORE (1<<0) +#define WIFI_LOG_SUBMODULE_SCAN (1<<1) +#define WIFI_LOG_SUBMODULE_PM (1<<2) +#define WIFI_LOG_SUBMODULE_NVS (1<<3) +#define WIFI_LOG_SUBMODULE_TRC (1<<4) +#define WIFI_LOG_SUBMODULE_EBUF (1<<5) +#define WIFI_LOG_SUBMODULE_NET80211 (1<<6) +#define WIFI_LOG_SUBMODULE_TIMER (1<<7) +#define WIFI_LOG_SUBMODULE_ESPNOW (1<<8) +#define WIFI_LOG_SUBMODULE_MAC (1<<9) +#define WIFI_LOG_SUBMODULE_WPA (1<<10) +#define WIFI_LOG_SUBMODULE_WPS (1<<11) +#define WIFI_LOG_SUBMODULE_AMPDU (1<<12) +#define WIFI_LOG_SUBMODULE_AMSDU (1<<13) +#define WIFI_LOG_SUBMODULE_FRAG (1<<14) +#define WIFI_LOG_SUBMODULE_WPA2 (1<<15) + + +/** + * @brief Initialize Wi-Fi Driver + * Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, + * WiFi NVS structure among others. + * + * For the most part, you need not call this function directly. It gets called + * from esp_wifi_init(). + * + * This function may be called, if you only need to initialize the Wi-Fi driver + * without having to use the network stack on top. + * + * @param config provide WiFi init configuration + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_NO_MEM: out of memory + * - others: refer to error code esp_err.h + */ +esp_err_t esp_wifi_init_internal(const wifi_init_config_t* config); + +/** + * @brief Deinitialize Wi-Fi Driver + * Free resource for WiFi driver, such as WiFi control structure, RX/TX buffer, + * WiFi NVS structure among others. + * + * For the most part, you need not call this function directly. It gets called + * from esp_wifi_deinit(). + * + * This function may be called, if you call esp_wifi_init_internal to initialize + * WiFi driver. + * + * @return + * - ESP_OK: succeed + * - others: refer to error code esp_err.h + */ +esp_err_t esp_wifi_deinit_internal(void); + +/** + * @brief Set WIFI received TCP/IP data cache ram type + * + * @param type if use dram + */ +void esp_wifi_set_rx_pbuf_mem_type(wifi_rx_pbuf_mem_type_t type); + +/** + * @brief get WIFI received TCP/IP data cache ram type + * + * @return true if use dram or false + */ +wifi_rx_pbuf_mem_type_t esp_wifi_get_rx_pbuf_mem_type(void); + +int8_t esp_wifi_get_ap_rssi(void); + +/** + * @brief The RX callback function when receive probe request packet. + * When probe request packet is received, the callback function will be called. + * + * @param frame Data of received probe request. + * @param len length of received probe request. + * @param rssi rssi of received probe request. + */ +typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t* frame, int len, int rssi); + +/** + * @brief Register the RX callback function when receive probe request. + * + * When probe request packet is received, the registered callback function will be called. + * + * @param cb callback + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + */ +esp_err_t esp_wifi_set_sta_rx_probe_req(wifi_sta_rx_probe_req_t cb); + +/** + * @brief free the rx buffer which allocated by wifi driver + * + * @param void* buffer: rx buffer pointer + */ +void esp_wifi_internal_free_rx_buffer(void* buffer); + +/** + * @brief transmit the buffer via wifi driver + * + * @param wifi_interface_t wifi_if : wifi interface id + * @param void *buffer : the buffer to be tansmit + * @param uint16_t len : the length of buffer + * + * @return + * - ERR_OK : Successfully transmit the buffer to wifi driver + * - ERR_MEM : Out of memory + * - ERR_IF : WiFi driver error + * - ERR_ARG : Invalid argument + */ +int esp_wifi_internal_tx(wifi_interface_t wifi_if, void* buffer, uint16_t len); + +/** + * @brief The WiFi RX callback function + * + * Each time the WiFi need to forward the packets to high layer, the callback function will be called + */ +typedef esp_err_t (*wifi_rxcb_t)(void* buffer, uint16_t len, void* eb); + +/** + * @brief Set the WiFi RX callback + * + * @attention 1. Currently we support only one RX callback for each interface + * + * @param wifi_interface_t ifx : interface + * @param wifi_rxcb_t fn : WiFi RX callback + * + * @return + * - ESP_OK : succeed + * - others : fail + */ +esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); + +/** + * @brief Set current WiFi log level + * + * @param level Log level. + * + * @return + * - ESP_OK: succeed + * - ESP_FAIL: level is invalid + */ +esp_err_t esp_wifi_internal_set_log_level(wifi_log_level_t level); + +/** + * @brief Set current log module and submodule + * + * @param module Log module + * @param submodule Log submodule + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_internal_set_log_mod(uint32_t submodule); + +/** + * @brief Get current WiFi log info + * + * @param log_level the return log level. + * @param log_mod the return log module and submodule + * + * @return + * - ESP_OK: succeed + */ +esp_err_t esp_wifi_internal_get_log(wifi_log_level_t* log_level, uint32_t* log_mod); + +/** + * @brief get wifi power management config. + * + * @param ps_config power management config + */ +void esp_wifi_set_pm_config(esp_pm_config_t* pm_config); + +/** + * @brief set wifi power management config. + * + * @param ps_config power management config + */ +void esp_wifi_get_pm_config(esp_pm_config_t* pm_config); + +/** + * @brief Start SmartConfig, config ESP device to connect AP. You need to broadcast information by phone APP. + * Device sniffer special packets from the air that containing SSID and password of target AP. + * + * @attention 1. This API can be called in station or softAP-station mode. + * @attention 2. Can not call esp_smartconfig_start twice before it finish, please call + * esp_smartconfig_stop first. + * + * @param config pointer to smartconfig start configure structure + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_smartconfig_internal_start(const smartconfig_start_config_t* config); + +/** + * @brief Stop SmartConfig, free the buffer taken by esp_smartconfig_start. + * + * @attention Whether connect to AP succeed or not, this API should be called to free + * memory taken by smartconfig_start. + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_smartconfig_internal_stop(void); + +/** + * @brief Stop close RF when station connect to ap. + */ +void esp_wifi_ps_lock(void); + + +/** + * @brief Do normal sleep when station connect to ap. + */ +void esp_wifi_ps_unlock(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ESP_WIFI_INTERNAL_H */ diff --git a/components/esp8266/include/esp_sha.h b/components/esp8266/include/esp_sha.h new file mode 100644 index 000000000..238d1be12 --- /dev/null +++ b/components/esp8266/include/esp_sha.h @@ -0,0 +1,202 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t state[5]; + uint32_t total[2]; + uint8_t buffer[64]; +} esp_sha1_t; + +typedef struct { + uint32_t total[2]; + uint32_t state[8]; + uint8_t buffer[64]; + + int is224; +} esp_sha256_t; + +typedef struct { + uint64_t total[2]; + uint64_t state[8]; + uint8_t buffer[128]; + + int is384; +} esp_sha512_t; + +typedef esp_sha256_t esp_sha224_t; + +typedef esp_sha512_t esp_sha384_t; + +/** + * @brief initialize the SHA1 contex + * + * @param ctx SHA1 contex pointer + * + * @return 0 if success or fail + */ +int esp_sha1_init(esp_sha1_t *ctx); + +/** + * @brief initialize the SHA224 contex + * + * @param ctx SHA224 contex pointer + * + * @return 0 if success or fail + */ +int esp_sha224_init(esp_sha224_t *ctx); + +/** + * @brief initialize the SHA256 contex + * + * @param ctx SHA256 contex pointer + * + * @return 0 if success or fail + */ +int esp_sha256_init(esp_sha256_t *ctx); + +/** + * @brief initialize the SHA384 contex + * + * @param ctx SHA384 contex pointer + * + * @return 0 if success or fail + */ +int esp_sha384_init(esp_sha384_t *ctx); + +/** + * @brief initialize the SHA512 contex + * + * @param ctx SHA512 contex pointer + * + * @return 0 if success or fail + */ +int esp_sha512_init(esp_sha512_t *ctx); + +/** + * @brief calculate input data for SHA1 + * + * @param ctx SHA1 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int esp_sha1_update(esp_sha1_t *ctx, const void *src, size_t size); + +/** + * @brief calculate input data for SHA224 + * + * @param ctx SHA224 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int esp_sha224_update(esp_sha224_t *ctx, const void *src, size_t size); + +/** + * @brief calculate input data for SHA256 + * + * @param ctx SHA256 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int esp_sha256_update(esp_sha256_t *ctx, const void *src, size_t size); + +/** + * @brief calculate input data for SHA384 + * + * @param ctx SHA384 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int esp_sha384_update(esp_sha384_t *ctx, const void *src, size_t size); + +/** + * @brief calculate input data for SHA512 + * + * @param ctx SHA512 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int esp_sha512_update(esp_sha512_t *ctx, const void *src, size_t size); + +/** + * @brief output SHA1 calculation result + * + * @param ctx SHA1 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int esp_sha1_finish(esp_sha1_t *ctx, void *dest); + +/** + * @brief output SHA224 calculation result + * + * @param ctx SHA224 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int esp_sha224_finish(esp_sha224_t *ctx, void *dest); + +/** + * @brief output SHA256 calculation result + * + * @param ctx SHA256 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int esp_sha256_finish(esp_sha256_t *ctx, void *dest); + +/** + * @brief output SHA384 calculation result + * + * @param ctx SHA384 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int esp_sha384_finish(esp_sha384_t *ctx, void *dest); + +/** + * @brief output SHA512 calculation result + * + * @param ctx SHA512 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int esp_sha512_finish(esp_sha512_t *ctx, void *dest); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp8266/include/esp_sleep.h b/components/esp8266/include/esp_sleep.h index 08bc1a308..fbc2206df 100644 --- a/components/esp8266/include/esp_sleep.h +++ b/components/esp8266/include/esp_sleep.h @@ -12,23 +12,42 @@ // See the License for the specific language governing permissions and // limitations under the License. +#pragma once + #include +#include #include "esp_err.h" +#include "driver/gpio.h" #ifdef __cplusplus extern "C" { #endif -/** \defgroup System_Sleep_APIs System Sleep APIs - * @brief System Sleep APIs - */ +typedef enum { + WIFI_NONE_SLEEP_T = 0, + WIFI_LIGHT_SLEEP_T, + WIFI_MODEM_SLEEP_T +} wifi_sleep_type_t; -/** @addtogroup System_Sleep_APIs - * @{ - */ +typedef enum esp_sleep_mode { + ESP_CPU_WAIT = 0, + ESP_CPU_LIGHTSLEEP, +} esp_sleep_mode_t; + +typedef void (*fpm_wakeup_cb)(void); /** - * @brief Set the chip to deep-sleep mode. + * @brief Sleep wakeup cause + */ +typedef enum { + ESP_SLEEP_WAKEUP_UNDEFINED, //!< In case of deep sleep, reset was not caused by exit from deep sleep + ESP_SLEEP_WAKEUP_ALL, //!< Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source + ESP_SLEEP_WAKEUP_TIMER, //!< Wakeup caused by timer + ESP_SLEEP_WAKEUP_GPIO, //!< Wakeup caused by GPIO (light sleep only) +} esp_sleep_source_t; + +/** + * @brief Enter deep-sleep mode. * * The device will automatically wake up after the deep-sleep time set * by the users. Upon waking up, the device boots up from user_init. @@ -38,13 +57,25 @@ extern "C" { * @attention 2. system_deep_sleep(0): there is no wake up timer; in order to wake * up, connect a GPIO to pin RST, the chip will wake up by a falling-edge * on pin RST + * @attention 3. esp_deep_sleep does not shut down WiFi and higher level protocol + * connections gracefully. Make sure esp_wifi_stop are called to close any + * connections and deinitialize the peripherals. * - * @param uint32 time_in_us : deep-sleep time, unit: microsecond + * @param time_in_us deep-sleep time, unit: microsecond * * @return null */ -void esp_deep_sleep(uint32_t time_in_us); +void esp_deep_sleep(uint64_t time_in_us); +/** + * @brief Set implementation-specific power management configuration + * @param config pointer to implementation-specific configuration structure (e.g. esp_pm_config_esp32) + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the configuration values are not correct + * - ESP_ERR_NOT_SUPPORTED if certain combination of values is not supported. + */ +esp_err_t esp_pm_configure(const void* config); /** * @brief Call this API before esp_deep_sleep and esp_wifi_init to set the activity after the @@ -52,67 +83,36 @@ void esp_deep_sleep(uint32_t time_in_us); * * If this API is not called, default to be esp_deep_sleep_set_rf_option(1). * - * @param uint8 option : - * @param 0 : Radio calibration after the deep-sleep wakeup is decided by byte - * 108 of esp_init_data_default.bin (0~127byte). - * @param 1 : Radio calibration will be done after the deep-sleep wakeup. This - * will lead to stronger current. - * @param 2 : Radio calibration will not be done after the deep-sleep wakeup. - * This will lead to weaker current. - * @param 4 : Disable radio calibration after the deep-sleep wakeup (the same - * as modem-sleep). This will lead to the weakest current, but the device - * can't receive or transmit data after waking up. + * @param option radio option + * 0 : Radio calibration after the deep-sleep wakeup is decided by byte + * 108 of esp_init_data_default.bin (0~127byte). + * 1 : Radio calibration will be done after the deep-sleep wakeup. This + * will lead to stronger current. + * 2 : Radio calibration will not be done after the deep-sleep wakeup. + * This will lead to weaker current. + * 4 : Disable radio calibration after the deep-sleep wakeup (the same + * as modem-sleep). This will lead to the weakest current, but the device + * can't receive or transmit data after waking up. * * @return null */ void esp_deep_sleep_set_rf_option(uint8_t option); -/** \defgroup WiFi_Sleep_Type_APIs Sleep Type APIs - * @brief WiFi Sleep APIs - */ - -/** @addtogroup WiFi_Sleep_Type_APIs - * @{ - */ - -typedef enum { - WIFI_NONE_SLEEP_T = 0, - WIFI_LIGHT_SLEEP_T, - WIFI_MODEM_SLEEP_T -} wifi_sleep_type_t; - -/** - * @} - */ - - -/** \defgroup WiFi_Force_Sleep_APIs Force Sleep APIs - * @brief WiFi Force Sleep APIs - */ - -/** @addtogroup WiFi_Force_Sleep_APIs - * @{ - */ - /** * @brief Enable force sleep function. * * @attention Force sleep function is disabled by default. * - * @param null - * * @return null */ -void esp_wifi_fpm_open(void); +void esp_wifi_fpm_open(void) __attribute__ ((deprecated)); /** * @brief Disable force sleep function. * - * @param null - * * @return null */ -void esp_wifi_fpm_close(void); +void esp_wifi_fpm_close(void) __attribute__ ((deprecated)); /** * @brief Wake ESP8266 up from MODEM_SLEEP_T force sleep. @@ -121,13 +121,9 @@ void esp_wifi_fpm_close(void); * is enabled, after calling wifi_fpm_open. * This API can not be called after calling wifi_fpm_close. * - * @param null - * * @return null */ -void esp_wifi_fpm_do_wakeup(void); - -typedef void (*fpm_wakeup_cb)(void); +void esp_wifi_fpm_do_wakeup(void) __attribute__ ((deprecated)); /** * @brief Set a callback of waken up from force sleep because of time out. @@ -140,11 +136,11 @@ typedef void (*fpm_wakeup_cb)(void); * @attention 3. fpm_wakeup_cb_func will not be called if woke up by wifi_fpm_do_wakeup * from MODEM_SLEEP_T type force sleep. * - * @param void (*fpm_wakeup_cb_func)(void) : callback of waken up + * @param cb callback of waken up * * @return null */ -void esp_wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb); +void esp_wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb) __attribute__ ((deprecated)); /** * @brief Force ESP8266 enter sleep mode, and it will wake up automatically when time out. @@ -156,41 +152,131 @@ void esp_wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb); * in the system idle task. Please do not call other WiFi related function right * after calling this API. * - * @param uint32 sleep_time_in_us : sleep time, ESP8266 will wake up automatically - * when time out. Unit: us. Range: 10000 ~ 268435455(0xFFFFFFF). - * - If sleep_time_in_us is 0xFFFFFFF, the ESP8266 will sleep till - * - if wifi_fpm_set_sleep_type is set to be LIGHT_SLEEP_T, ESP8266 can wake up by GPIO. - * - if wifi_fpm_set_sleep_type is set to be MODEM_SLEEP_T, ESP8266 can wake up by wifi_fpm_do_wakeup. + * @param sleep_time_in_us sleep time, ESP8266 will wake up automatically + * when time out. Unit: us. Range: 10000 ~ 268435455(0xFFFFFFF). + * - If sleep_time_in_us is 0xFFFFFFF, the ESP8266 will sleep till + * - if wifi_fpm_set_sleep_type is set to be LIGHT_SLEEP_T, ESP8266 can wake up by GPIO. + * - if wifi_fpm_set_sleep_type is set to be MODEM_SLEEP_T, ESP8266 can wake up by wifi_fpm_do_wakeup. * - * @return 0, setting succeed; - * @return -1, fail to sleep, sleep status error; - * @return -2, fail to sleep, force sleep function is not enabled. + * @return ESP_OK, setting succeed; + * @return ESP_ERR_WIFI_FPM_MODE, fail to sleep, force sleep function is not enabled. + * @return ESP_ERR_WIFI_PM_MODE_OPEN, fail to sleep, Please call esp_wifi_set_ps(WIFI_PS_NONE) first. + * @return ESP_ERR_WIFI_MODE, fail to sleep, Please call esp_wifi_set_mode(WIFI_MODE_NULL) first. */ -esp_err_t esp_wifi_fpm_do_sleep(uint32_t sleep_time_in_us); +esp_err_t esp_wifi_fpm_do_sleep(uint32_t sleep_time_in_us) __attribute__ ((deprecated)); /** * @brief Set sleep type for force sleep function. * * @attention This API can only be called before wifi_fpm_open. * - * @param wifi_sleep_type_t type : sleep type + * @param type sleep type * * @return null */ -void esp_wifi_fpm_set_sleep_type(wifi_sleep_type_t type); +void esp_wifi_fpm_set_sleep_type(wifi_sleep_type_t type) __attribute__ ((deprecated)); /** * @brief Get sleep type of force sleep function. * - * @param null - * * @return sleep type */ -wifi_sleep_type_t esp_wifi_fpm_get_sleep_type(void); +wifi_sleep_type_t esp_wifi_fpm_get_sleep_type(void) __attribute__ ((deprecated)); /** - * @} + * @brief Set a GPIO to wake the ESP8266 up from light-sleep mode + * ESP8266 will be wakened from Light-sleep, when the GPIO is in low-level. + * + * If the ESP8266 enters light-sleep automatically(esp_wifi_set_sleep_type(LIGHT_SLEEP_T);), + * after being waken up by GPIO, when the chip attempts to sleep again, it will check the status of the GPIO: + * Note: + * • If the GPIO is still in the wakeup status, the EP8266 will enter modem-sleep mode instead; + * • If the GPIO is NOT in the wakeup status, the ESP8266 will enter light-sleep mode + * + * @param gpio_num GPIO number, range: [0, 15]. + * gpio_int_type_t intr_status: status of GPIO interrupt to trigger the wakeup process. + * - if esp_wifi_fpm_set_sleep_type is set to be LIGHT_SLEEP_T, ESP8266 can wake up by GPIO. + * - if esp_wifi_fpm_set_sleep_type is set to be MODEM_SLEEP_T, ESP8266 can wake up by esp_wifi_fpm_do_wakeup. + * @param intr_status GPIO interrupt type + * + * @return null */ +void esp_wifi_enable_gpio_wakeup(uint32_t gpio_num, gpio_int_type_t intr_status) __attribute__ ((deprecated)); + +/** + * @brief Disable the function that the GPIO can wake the ESP8266 up from light-sleep mode. + */ +void esp_wifi_disable_gpio_wakeup(void) __attribute__ ((deprecated)); + +/** + * @brief Enable wakeup by timer + * @param time_in_us time before wakeup, in microseconds + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if value is out of range (TBD) + */ +esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us); + +/** + * @brief Enter light sleep with the configured wakeup options + * + * @attention esp_deep_sleep does not shut down WiFi and higher level protocol + * connections gracefully. Make sure esp_wifi_stop are called to close any + * connections and deinitialize the peripherals. + * @return + * - ESP_OK on success (returned after wakeup) + * - ESP_ERR_INVALID_STATE if WiFi is not stopped + */ +esp_err_t esp_light_sleep_start(void); + +/** + * @brief Operation system start check time and enter sleep + * + * @note This function is called by system, user should not call this + */ +void esp_sleep_start(void); + +/** + * @brief Enable wakeup from light sleep using GPIOs + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if wakeup triggers conflict + */ +esp_err_t esp_sleep_enable_gpio_wakeup(void); + +/** + * @brief Disable wakeup source + * + * This function is used to deactivate wake up trigger for source + * defined as parameter of the function. + * + * @note This function does not modify wake up configuration in RTC. + * It will be performed in esp_sleep_start function. + * + * @param source - number of source to disable of type esp_sleep_source_t + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if trigger was not active + */ +esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source); + +/** + * @brief Print power consumption information + * + * @note This function is used to print power consumption data. The current + * when the RF and CPU are both turned on is 70 mA. The current when + * only the CPU is turned on is 18 mA. 900uA when both CPU and RF are off. + * There may be some errors compared to the actual power consumption. + * The power consumption is based on the actual measurement, and the printing + * in the function is for reference only. + * + * @param clear_old_data - Recalculate power consumption info or not. + * + * @return null + */ +void esp_power_consumption_info(bool clear_old_data); #ifdef __cplusplus } diff --git a/components/esp8266/include/esp_smartconfig.h b/components/esp8266/include/esp_smartconfig.h index f7b8e431b..c0f796b79 100644 --- a/components/esp8266/include/esp_smartconfig.h +++ b/components/esp8266/include/esp_smartconfig.h @@ -18,37 +18,53 @@ #include #include #include "esp_err.h" +#include "esp_event_base.h" #ifdef __cplusplus extern "C" { #endif -typedef enum { - SC_STATUS_WAIT = 0, /**< Waiting to start connect */ - SC_STATUS_FIND_CHANNEL, /**< Finding target channel */ - SC_STATUS_GETTING_SSID_PSWD, /**< Getting SSID and password of target AP */ - SC_STATUS_LINK, /**< Connecting to target AP */ - SC_STATUS_LINK_OVER, /**< Connected to AP successfully */ -} smartconfig_status_t; - typedef enum { SC_TYPE_ESPTOUCH = 0, /**< protocol: ESPTouch */ SC_TYPE_AIRKISS, /**< protocol: AirKiss */ SC_TYPE_ESPTOUCH_AIRKISS, /**< protocol: ESPTouch and AirKiss */ + SC_TYPE_ESPTOUCH_V2, /**< protocol: ESPTouch V2*/ } smartconfig_type_t; -/** - * @brief The callback of SmartConfig, executed when smart-config status changed. - * - * @param status Status of SmartConfig: - * - SC_STATUS_GETTING_SSID_PSWD : pdata is a pointer of smartconfig_type_t, means config type. - * - SC_STATUS_LINK : pdata is a pointer of struct station_config. - * - SC_STATUS_LINK_OVER : pdata is a pointer of phone's IP address(4 bytes) if pdata unequal NULL. - * - otherwise : parameter void *pdata is NULL. - * @param pdata According to the different status have different values. - * - */ -typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata); +/** Smartconfig event declarations */ +typedef enum { + SC_EVENT_SCAN_DONE, /*!< ESP32 station smartconfig has finished to scan for APs */ + SC_EVENT_FOUND_CHANNEL, /*!< ESP32 station smartconfig has found the channel of the target AP */ + SC_EVENT_GOT_SSID_PSWD, /*!< ESP32 station smartconfig got the SSID and password */ + SC_EVENT_SEND_ACK_DONE, /*!< ESP32 station smartconfig has sent ACK to cellphone */ +} smartconfig_event_t; + +/** @brief smartconfig event base declaration */ +ESP_EVENT_DECLARE_BASE(SC_EVENT); + +/** Argument structure for SC_EVENT_GOT_SSID_PSWD event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of the AP. Null terminated string. */ + uint8_t password[64]; /**< Password of the AP. Null terminated string. */ + bool bssid_set; /**< whether set MAC address of target AP or not. */ + uint8_t bssid[6]; /**< MAC address of target AP. */ + smartconfig_type_t type; /**< Type of smartconfig(ESPTouch or AirKiss). */ + uint8_t token; /**< Token from cellphone which is used to send ACK to cellphone. */ + uint8_t cellphone_ip[4]; /**< IP address of cellphone. */ +} smartconfig_event_got_ssid_pswd_t; + +/** Configure structure for esp_smartconfig_start */ +typedef struct { + bool enable_log; /**< Enable smartconfig logs. */ + bool esp_touch_v2_enable_crypt; /**< Enable ESPTOUCH V2 crypt. */ + char* esp_touch_v2_key; /**< ESPTOUCH V2 crypt key, len should be 16. */ +} smartconfig_start_config_t; + +#define SMARTCONFIG_START_CONFIG_DEFAULT() { \ + .enable_log = false, \ + .esp_touch_v2_enable_crypt = false,\ + .esp_touch_v2_key = NULL \ +}; /** * @brief Get the version of SmartConfig. @@ -56,24 +72,23 @@ typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata); * @return * - SmartConfig version const char. */ -const char *esp_smartconfig_get_version(void); +const char* esp_smartconfig_get_version(void); /** * @brief Start SmartConfig, config ESP device to connect AP. You need to broadcast information by phone APP. * Device sniffer special packets from the air that containing SSID and password of target AP. * - * @attention 1. This API can be called in station or softAP-station mode. + * @attention 1. This API can be called in station mode. * @attention 2. Can not call esp_smartconfig_start twice before it finish, please call * esp_smartconfig_stop first. * - * @param cb SmartConfig callback function. - * @param ... log 1: UART output logs; 0: UART only outputs the result. + * @param config pointer to smartconfig start configure structure * * @return * - ESP_OK: succeed * - others: fail */ -esp_err_t esp_smartconfig_start(sc_callback_t cb, ...); +esp_err_t esp_smartconfig_start(const smartconfig_start_config_t* config); /** * @brief Stop SmartConfig, free the buffer taken by esp_smartconfig_start. @@ -129,6 +144,18 @@ esp_err_t esp_smartconfig_set_type(smartconfig_type_t type); */ esp_err_t esp_smartconfig_fast_mode(bool enable); +/** + * @brief Get reserved data of ESPTouch_v2. + * + * @param rvd_data reserved data + * @param len length of reserved data + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_smartconfig_get_rvd_data(uint8_t* rvd_data, uint8_t len); + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/esp_socket.h b/components/esp8266/include/esp_socket.h deleted file mode 100644 index 5b5ee1f47..000000000 --- a/components/esp8266/include/esp_socket.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESP_SOCKET_H -#define _ESP_SOCKET_H - -#include - -#include "esp_aio.h" -#include "esp_module.h" -#include "net/if_packet.h" -#include "net/if_socket.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* used for socket link */ -#define ESP_SOCKET_METHOD_BASENAME "esp_socket" -#define ESP_SOCKET_METHOD_NAME(sec) __DECLARE_SYMBOL_NAME(ESP_SOCKET_METHOD_BASENAME) -#define ESP_SOCKET_METHOD_DECLARE(sym) __DECLARE_SYMBOL(esp_socket_method_t, sym, ESP_SOCKET_METHOD_BASENAME) - -#ifndef socklen_t -typedef uint32_t socklen_t; -#endif - -#define esp_socket_va_start(va, arg) va = (va_list)arg - -/* - * socket async event - */ -enum esp_socket_event_type { - ESP_SOCKET_CONNECT_EVENT = 0, - ESP_SOCKET_ACCEPT_EVENT = ESP_SOCKET_CONNECT_EVENT, - ESP_SOCKET_RECV_EVENT = 1, - ESP_SOCKET_ERROR_EVENT = 2, - - ESP_SOCKET_MAX_EVENT -}; - -/* - * socket information object - */ -typedef struct esp_socket_info { - int domain; - int type; - int protocol; -} esp_socket_info_t; - -/* - * socket method object - */ -typedef struct esp_socket_method { - /* - * socket method name - */ - const char *name; - - /* - * @brief open lowlevel socket module - * - * @param info socket information - * - * @return return lowlevel socket index if successfully, otherwise return NULL - * and you can get the real fail reason by "errno" - */ - void* (*open)(esp_socket_info_t *info); - - /* - * @brief send a block of data asynchronously and receive result by callback function - * - * @param index lowlevel index - * @param aio asynchronous I/O controlling block - * @param to target address with lowlevel address data format - * @param len target address data length - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ - int (*aio_sendto)(void *index, esp_aio_t *aio, const struct sockaddr_ll *to, socklen_t len); - - /* - * @brief register an event and its callback function to lowlevel socket module - * - * @param index lowlevel index - * @param event asynchronous I/O event - * @param cb callback function - * @param arg callback function parameter - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ - int (*aio_event)(void *index, unsigned int event, esp_aio_cb_t cb, void *arg); - - /* - * @brief free buffer taken from event callback - * - * @param index lowlevel index - * @param pbuf buffer pointer - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ - int (*free_pbuf)(void *index, void *pbuf); - - /* - * @brief send request command to lowlevel socket module and get the result synchronously - * - * @param index lowlevel index - * @param cmd request command - * @param arg start address to variable parameters - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ - int (*ioctl)(void *index, unsigned int cmd, void *arg); - - /* - * @brief close lowlevel socket module - * - * @param index lowlevel index - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ - int (*close)(void *index); -} esp_socket_method_t; - -/* - * @brief free an aio control block by calling the callback function - * - * @param aio asynchronous I/O controlling block - * @param aio data handling result - * - * @return none - */ -static inline void esp_aio_free(esp_aio_t *aio, int status) -{ - if (aio->cb) { - aio->ret = status; - aio->cb(aio); - } -} - -/* - * @brief drop an aio control block by disable "pbuf" and "cb" - * and then the aio control block has no meaning - * - * @param aio asynchronous I/O controlling block - * - * @return none - */ -static inline void esp_aio_drop(esp_aio_t *aio) -{ - aio->pbuf = NULL; - aio->cb = NULL; -} - -/* - * @brief create a socket file description - * - * @param domain protocal domain and it must be "AF_PACKET" now - * @param type socket type and it must be "SOCK_RAW" now - * @param protocol target protocol and it must be "ETH_P_ALL" now - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - * - * @note using "AF_PACKET", "SOCK_RAW" and "ETH_P_ALL" means that you receive and send full - * ethernet II type message with full message head: " destination mac | source mac | type" - */ -int esp_socket(int domain, int type, int protocol); - -/* - * @brief send a block of data asynchronously and receive result by callback function - * - * @param aio asynchronous I/O controlling block - * @param to target address with lowlevel address data format - * @param len target address data length - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_aio_sendto(esp_aio_t *aio, const struct sockaddr_ll *to, socklen_t len); - -/* - * @brief register an event and its callback function to target of file description - * - * @param fd file description - * @param event asynchronous I/O event - * @param cb callback function - * @param arg callback function parameter - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_aio_event(int fd, unsigned int event, esp_aio_cb_t cb, void *arg); - -/* - * @brief lowlevel socket module upload event and its data - * - * @param index lowlevel index - * @param info socket information - * @param event asynchronous I/O event - * @param aio asynchronous I/O controlling block - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_upload_event(void *index, esp_socket_info_t *info, unsigned int event, esp_aio_data_t *aio_data); - -/* - * @brief free buffer taken from event callback - * - * @param fd file description - * @param pbuf buffer pointer - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_free_pbuf(int fd, void *pbuf); - -/* - * @brief send request command to target by file description and get the result synchronously - * - * @param fd file description - * @param cmd request command - * @param ... realy command parameters and it must be related to realy object of lowlevel - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_ioctl(int fd, unsigned int cmd, ...); - -/* - * @brief close target of file description - * - * @param fd file description - * - * @return return 0 if successfully, otherwise return -1 and you can get the real fail - * reason by "errno" - */ -int esp_close(int fd); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESP_SOCKET_H */ diff --git a/components/esp8266/include/esp_system.h b/components/esp8266/include/esp_system.h index 45ccb23af..e5600b272 100644 --- a/components/esp8266/include/esp_system.h +++ b/components/esp8266/include/esp_system.h @@ -19,15 +19,40 @@ #include #include "esp_err.h" +#include "sdkconfig.h" + +#include "esp_idf_version.h" + #ifdef __cplusplus extern "C" { #endif +#define CRYSTAL_USED CONFIG_ESP8266_XTAL_FREQ + typedef enum { ESP_MAC_WIFI_STA, ESP_MAC_WIFI_SOFTAP, } esp_mac_type_t; + +/** + * @brief Reset reasons + */ +typedef enum { + ESP_RST_UNKNOWN = 0, //!< Reset reason can not be determined + ESP_RST_POWERON, //!< Reset due to power-on event + ESP_RST_EXT, //!< Reset by external pin (not applicable for ESP8266) + ESP_RST_SW, //!< Software reset via esp_restart + ESP_RST_PANIC, //!< Software reset due to exception/panic + ESP_RST_INT_WDT, //!< Reset (software or hardware) due to interrupt watchdog + ESP_RST_TASK_WDT, //!< Reset due to task watchdog + ESP_RST_WDT, //!< Reset due to other watchdogs + ESP_RST_DEEPSLEEP, //!< Reset after exiting deep sleep mode + ESP_RST_BROWNOUT, //!< Brownout reset (software or hardware) + ESP_RST_SDIO, //!< Reset over SDIO + ESP_RST_FAST_SW, //!< Fast reboot +} esp_reset_reason_t; + /** * @brief Set base MAC address with the MAC address which is stored in EFUSE or * external storage e.g. flash and EEPROM. @@ -95,9 +120,9 @@ esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac) * @brief CPU frequency values */ typedef enum { - RTC_CPU_FREQ_80M = 1, //!< 80 MHz - RTC_CPU_FREQ_160M = 2, //!< 160 MHz -} rtc_cpu_freq_t; + ESP_CPU_FREQ_80M = 1, //!< 80 MHz + ESP_CPU_FREQ_160M = 2, //!< 160 MHz +} esp_cpu_freq_t; /** * @brief Switch CPU frequency @@ -109,7 +134,7 @@ typedef enum { * * @param cpu_freq new CPU frequency */ -void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq); +void esp_set_cpu_freq(esp_cpu_freq_t cpu_freq); /** * @brief Reset to default settings. @@ -123,6 +148,12 @@ void system_restore(void) __attribute__ ((noreturn)); */ void esp_restart(void) __attribute__ ((noreturn)); +/** + * @brief Get reason of last reset + * @return See description of esp_reset_reason_t for explanation of each value. + */ +esp_reset_reason_t esp_reset_reason(void); + /** * @brief Get the size of available heap. * @@ -148,11 +179,21 @@ uint32_t esp_get_minimum_free_heap_size( void ); uint32_t esp_random(void); /** - * Get IDF version + * @brief Fill a buffer with random bytes from hardware RNG + * + * @note This function has the same restrictions regarding available entropy as esp_random() * - * @return constant string from IDF_VER + * @param buf Pointer to buffer to fill with random numbers. + * @param len Length of buffer in bytes */ -const char* esp_get_idf_version(void); +void esp_fill_random(void *buf, size_t len); + +/** + * @brief Initialize MAC address + * + * @return 0 if sucess or others failed + */ +esp_err_t esp_mac_init(void); typedef enum { FLASH_SIZE_4M_MAP_256_256 = 0, /**< Flash size : 4Mbits. Map : 256KBytes + 256KBytes */ @@ -174,13 +215,17 @@ typedef enum { * @brief Chip models */ typedef enum { - CHIP_ESP8266 = 1, //!< ESP8266 + CHIP_ESP8266 = 0, //!< ESP8266 + CHIP_ESP32 = 1, //!< ESP32 } esp_chip_model_t; /** * Chip feature flags, used in esp_chip_info_t */ -#define CHIP_FEATURE_WIFI_BGN (1 << 0) +#define CHIP_FEATURE_EMB_FLASH BIT(0) //!< Chip has embedded flash memory +#define CHIP_FEATURE_WIFI_BGN BIT(1) //!< Chip has 2.4GHz WiFi +#define CHIP_FEATURE_BLE BIT(4) //!< Chip has Bluetooth LE +#define CHIP_FEATURE_BT BIT(5) //!< Chip has Bluetooth Classic /** * @brief The structure represents information about the chip @@ -204,8 +249,6 @@ void esp_chip_info(esp_chip_info_t* out_info); * Flash map depends on the selection when compiling, more details in document * "2A-ESP8266__IOT_SDK_User_Manual" * - * @param null - * * @return enum flash_size_map */ flash_size_map system_get_flash_size_map(void); diff --git a/components/esp8266/include/esp_timer.h b/components/esp8266/include/esp_timer.h index c6b606c02..5e1d01aff 100644 --- a/components/esp8266/include/esp_timer.h +++ b/components/esp8266/include/esp_timer.h @@ -187,6 +187,13 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer); */ esp_err_t esp_timer_delete(esp_timer_handle_t timer); +/** + * @brief Get time in microseconds since RTOS starts + * @return number of microseconds since RTOS starts starts (this normally + * happens much early during application startup). + */ +int64_t esp_timer_get_time(); + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/esp_wifi.h b/components/esp8266/include/esp_wifi.h index 314b3764b..9344a1c78 100644 --- a/components/esp8266/include/esp_wifi.h +++ b/components/esp8266/include/esp_wifi.h @@ -65,27 +65,28 @@ #include "esp_err.h" #include "esp_wifi_types.h" #include "esp_event.h" -#include "esp_wifi_os_adapter.h" #ifdef __cplusplus extern "C" { #endif -#define ESP_ERR_WIFI_NOT_INIT (ESP_ERR_WIFI_BASE + 1) /*!< WiFi driver was not installed by esp_wifi_init */ -#define ESP_ERR_WIFI_NOT_STARTED (ESP_ERR_WIFI_BASE + 2) /*!< WiFi driver was not started by esp_wifi_start */ -#define ESP_ERR_WIFI_NOT_STOPPED (ESP_ERR_WIFI_BASE + 3) /*!< WiFi driver was not stopped by esp_wifi_stop */ -#define ESP_ERR_WIFI_IF (ESP_ERR_WIFI_BASE + 4) /*!< WiFi interface error */ -#define ESP_ERR_WIFI_MODE (ESP_ERR_WIFI_BASE + 5) /*!< WiFi mode error */ -#define ESP_ERR_WIFI_STATE (ESP_ERR_WIFI_BASE + 6) /*!< WiFi internal state error */ -#define ESP_ERR_WIFI_CONN (ESP_ERR_WIFI_BASE + 7) /*!< WiFi internal control block of station or soft-AP error */ -#define ESP_ERR_WIFI_NVS (ESP_ERR_WIFI_BASE + 8) /*!< WiFi internal NVS module error */ -#define ESP_ERR_WIFI_MAC (ESP_ERR_WIFI_BASE + 9) /*!< MAC address is invalid */ -#define ESP_ERR_WIFI_SSID (ESP_ERR_WIFI_BASE + 10) /*!< SSID is invalid */ -#define ESP_ERR_WIFI_PASSWORD (ESP_ERR_WIFI_BASE + 11) /*!< Password is invalid */ -#define ESP_ERR_WIFI_TIMEOUT (ESP_ERR_WIFI_BASE + 12) /*!< Timeout error */ -#define ESP_ERR_WIFI_WAKE_FAIL (ESP_ERR_WIFI_BASE + 13) /*!< WiFi is in sleep state(RF closed) and wakeup fail */ -#define ESP_ERR_WIFI_WOULD_BLOCK (ESP_ERR_WIFI_BASE + 14) /*!< The caller would block */ -#define ESP_ERR_WIFI_NOT_CONNECT (ESP_ERR_WIFI_BASE + 15) /*!< Station still in disconnect status */ +#define ESP_ERR_WIFI_NOT_INIT (ESP_ERR_WIFI_BASE + 1) /*!< WiFi driver was not installed by esp_wifi_init */ +#define ESP_ERR_WIFI_NOT_STARTED (ESP_ERR_WIFI_BASE + 2) /*!< WiFi driver was not started by esp_wifi_start */ +#define ESP_ERR_WIFI_NOT_STOPPED (ESP_ERR_WIFI_BASE + 3) /*!< WiFi driver was not stopped by esp_wifi_stop */ +#define ESP_ERR_WIFI_IF (ESP_ERR_WIFI_BASE + 4) /*!< WiFi interface error */ +#define ESP_ERR_WIFI_MODE (ESP_ERR_WIFI_BASE + 5) /*!< WiFi mode error */ +#define ESP_ERR_WIFI_STATE (ESP_ERR_WIFI_BASE + 6) /*!< WiFi internal state error */ +#define ESP_ERR_WIFI_CONN (ESP_ERR_WIFI_BASE + 7) /*!< WiFi internal control block of station or soft-AP error */ +#define ESP_ERR_WIFI_NVS (ESP_ERR_WIFI_BASE + 8) /*!< WiFi internal NVS module error */ +#define ESP_ERR_WIFI_MAC (ESP_ERR_WIFI_BASE + 9) /*!< MAC address is invalid */ +#define ESP_ERR_WIFI_SSID (ESP_ERR_WIFI_BASE + 10) /*!< SSID is invalid */ +#define ESP_ERR_WIFI_PASSWORD (ESP_ERR_WIFI_BASE + 11) /*!< Password is invalid */ +#define ESP_ERR_WIFI_TIMEOUT (ESP_ERR_WIFI_BASE + 12) /*!< Timeout error */ +#define ESP_ERR_WIFI_WAKE_FAIL (ESP_ERR_WIFI_BASE + 13) /*!< WiFi is in sleep state(RF closed) and wakeup fail */ +#define ESP_ERR_WIFI_WOULD_BLOCK (ESP_ERR_WIFI_BASE + 14) /*!< The caller would block */ +#define ESP_ERR_WIFI_NOT_CONNECT (ESP_ERR_WIFI_BASE + 15) /*!< Station still in disconnect status */ +#define ESP_ERR_WIFI_PM_MODE_OPEN (ESP_ERR_WIFI_BASE + 18) /*!< Wifi is in min/max modem sleep mode */ +#define ESP_ERR_WIFI_FPM_MODE (ESP_ERR_WIFI_BASE + 19) /*!< Have not enable fpm mode */ #define ESP_WIFI_PARAM_USE_NVS 0 @@ -93,41 +94,85 @@ extern "C" { * @brief WiFi stack configuration parameters passed to esp_wifi_init call. */ typedef struct { - system_event_handler_t event_handler; /**< WiFi event handler */ - wifi_osi_funcs_t* osi_funcs; /**< WiFi OS functions */ - int static_rx_buf_num; /**< WiFi static RX buffer number */ - int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */ - int tx_buf_type; /**< WiFi TX buffer type */ - int static_tx_buf_num; /**< WiFi static TX buffer number */ - int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */ - int csi_enable; /**< WiFi channel state information enable flag */ - int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */ - int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */ - int nvs_enable; /**< WiFi NVS flash enable flag */ - int nano_enable; /**< Nano option for printf/scan family enable flag */ - int tx_ba_win; /**< WiFi Block Ack TX window size */ - int rx_ba_win; /**< WiFi Block Ack RX window size */ - int magic; /**< WiFi init magic number, it should be the last field */ + system_event_handler_t event_handler; /**< WiFi event handler */ + void* osi_funcs; /**< WiFi OS functions */ + uint8_t qos_enable; /**< WiFi QOS feature enable flag */ + uint8_t ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */ + uint8_t rx_ba_win; /**< WiFi Block Ack RX window size */ + uint8_t rx_ampdu_buf_num; /**< WiFi AMPDU RX buffer number */ + uint32_t rx_ampdu_buf_len; /**< WiFi AMPDU RX buffer length */ + uint32_t rx_max_single_pkt_len; /**< WiFi RX max single packet size */ + uint32_t rx_buf_len; /**< WiFi RX buffer size */ + uint8_t amsdu_rx_enable; /**< WiFi AMSDU RX feature enable flag */ + uint8_t rx_buf_num; /**< WiFi RX buffer number */ + uint8_t rx_pkt_num; /**< WiFi RX packet number */ + uint8_t left_continuous_rx_buf_num; /**< WiFi Rx left continuous rx buffer number */ + uint8_t tx_buf_num; /**< WiFi TX buffer number */ + uint8_t nvs_enable; /**< WiFi NVS flash enable flag */ + uint8_t nano_enable; /**< Nano option for printf/scan family enable flag */ + uint8_t wpa3_sae_enable; /**< WiFi WPA3 feature enable flag*/ + uint32_t magic; /**< WiFi init magic number, it should be the last field */ } wifi_init_config_t; +#if CONFIG_ESP8266_WIFI_AMPDU_RX_ENABLED +#define WIFI_AMPDU_RX_ENABLED 1 +#define WIFI_AMPDU_RX_BA_WIN CONFIG_ESP8266_WIFI_RX_BA_WIN_SIZE +#define WIFI_RX_MAX_SINGLE_PKT_LEN 1600 +#else +#define WIFI_AMPDU_RX_ENABLED 0 +#define WIFI_AMPDU_RX_BA_WIN 0 /* unused if ampdu_rx_enable == false */ +#define WIFI_RX_MAX_SINGLE_PKT_LEN (1600 - 524) +#endif +#define WIFI_AMPDU_RX_AMPDU_BUF_LEN 256 +#define WIFI_AMPDU_RX_AMPDU_BUF_NUM 5 +#define WIFI_HW_RX_BUFFER_LEN 524 + +#if CONFIG_ESP8266_WIFI_QOS_ENABLED +#define WIFI_QOS_ENABLED 1 +#else +#define WIFI_QOS_ENABLED 0 +#endif + +#if CONFIG_ESP8266_WIFI_AMSDU_ENABLED +#define WIFI_AMSDU_RX_ENABLED 1 +#undef WIFI_RX_MAX_SINGLE_PKT_LEN +#define WIFI_RX_MAX_SINGLE_PKT_LEN 3000 +#else +#define WIFI_AMSDU_RX_ENABLED 0 +#endif + +#if CONFIG_ESP8266_WIFI_NVS_ENABLED +#define WIFI_NVS_ENABLED 1 +#else +#define WIFI_NVS_ENABLED 0 +#endif + +#if CONFIG_ESP8266_WIFI_ENABLE_WPA3_SAE +#define WIFI_WPA3_ENABLED 1 +#else +#define WIFI_WPA3_ENABLED 0 +#endif + #define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F -extern wifi_osi_funcs_t s_wifi_osi_funcs; #define WIFI_INIT_CONFIG_DEFAULT() { \ .event_handler = &esp_event_send, \ - .osi_funcs = &s_wifi_osi_funcs, \ - .static_rx_buf_num = 5,\ - .dynamic_rx_buf_num = 0,\ - .tx_buf_type = 0,\ - .static_tx_buf_num = 6,\ - .dynamic_tx_buf_num = 0,\ - .csi_enable = 0,\ - .ampdu_rx_enable = 0,\ - .ampdu_tx_enable = 0,\ - .nvs_enable = 1,\ + .osi_funcs = NULL, \ + .qos_enable = WIFI_QOS_ENABLED,\ + .ampdu_rx_enable = WIFI_AMPDU_RX_ENABLED,\ + .rx_ba_win = WIFI_AMPDU_RX_BA_WIN,\ + .rx_ampdu_buf_num = WIFI_AMPDU_RX_AMPDU_BUF_NUM,\ + .rx_ampdu_buf_len = WIFI_AMPDU_RX_AMPDU_BUF_LEN,\ + .rx_max_single_pkt_len = WIFI_RX_MAX_SINGLE_PKT_LEN,\ + .rx_buf_len = WIFI_HW_RX_BUFFER_LEN,\ + .amsdu_rx_enable = WIFI_AMSDU_RX_ENABLED,\ + .rx_buf_num = CONFIG_ESP8266_WIFI_RX_BUFFER_NUM,\ + .rx_pkt_num = CONFIG_ESP8266_WIFI_RX_PKT_NUM,\ + .left_continuous_rx_buf_num = CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM,\ + .tx_buf_num = CONFIG_ESP8266_WIFI_TX_PKT_NUM,\ + .nvs_enable = WIFI_NVS_ENABLED,\ .nano_enable = 0,\ - .tx_ba_win = 0,\ - .rx_ba_win = 0,\ + .wpa3_sae_enable = WIFI_WPA3_ENABLED, \ .magic = WIFI_INIT_CONFIG_MAGIC\ }; @@ -386,10 +431,11 @@ esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); /** * @brief Set protocol type of specified interface - * The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N) + * The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G) * * @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode - * + * @attention Please call this API in SYSTEM_EVENT_STA_START event + * * @param ifx interfaces * @param protocol_bitmap WiFi protocol bitmap * @@ -650,6 +696,31 @@ esp_err_t esp_wifi_get_promiscuous_filter(wifi_promiscuous_filter_t *filter); */ esp_err_t esp_wifi_set_config(wifi_interface_t interface, wifi_config_t *conf); +/** + * @brief Enable subtype filter of the control packet in promiscuous mode. + * + * @note The default filter is to filter none control packet. + * + * @param filter the subtype of the control packet filtered in promiscuous mode. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + */ +esp_err_t esp_wifi_set_promiscuous_ctrl_filter(const wifi_promiscuous_filter_t *filter); + +/** + * @brief Get the subtype filter of the control packet in promiscuous mode. + * + * @param[out] filter store the current status of subtype filter of the control packet in promiscuous mode + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_get_promiscuous_ctrl_filter(wifi_promiscuous_filter_t *filter); + /** * @brief Get configuration of specified interface * @@ -767,6 +838,7 @@ esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx); /** * @brief Set maximum WiFi transmiting power * + * @attention Please Call this API after calling esp_wifi_start() * @attention WiFi transmiting power is divided to six levels in phy init data. * Level0 represents highest transmiting power and level5 represents lowest * transmiting power. Packets of different rates are transmitted in @@ -778,18 +850,18 @@ esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx); * whether to use phy init data in partition or not) will be used. Default * value is level0. Values passed in power are mapped to transmit power * levels as follows: - * - [78, 127]: level0 - * - [76, 77]: level1 - * - [74, 75]: level2 - * - [68, 73]: level3 - * - [60, 67]: level4 - * - [52, 59]: level5 - * - [44, 51]: level5 - 2dBm - * - [34, 43]: level5 - 4.5dBm - * - [28, 33]: level5 - 6dBm - * - [20, 27]: level5 - 8dBm - * - [8, 19]: level5 - 11dBm - * - [-128, 7]: level5 - 14dBm + * - [82, 127]: level0 + * - [78, 81]: level1 + * - [74, 77]: level2 + * - [68, 73]: level3 + * - [64, 67]: level4 + * - [56, 63]: level5 + * - [49, 55]: level5 - 2dBm + * - [33, 48]: level5 - 6dBm + * - [25, 32]: level5 - 8dBm + * - [13, 24]: level5 - 11dBm + * - [ 1, 12]: level5 - 14dBm + * - [-128, 0]: level5 - 17.5dBm * * @param power Maximum WiFi transmiting power. * @@ -800,6 +872,32 @@ esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx); */ esp_err_t esp_wifi_set_max_tx_power(int8_t power); +/** + * @brief Adjust RF Tx Power according to VDD33; unit : 1/1024 V. + * + * @attention When TOUT pin is suspended, VDD33 can be got by esp_wifi_get_vdd33. + * When TOUT pin is wired to external circuitry, esp_wifi_get_vdd33 can not be used. + * @attention This api only worked when it is called, please call this api every day or hour + * according to power consumption. + * + * @param vdd33 unit is 1/1024V, range [1900, 3300]. + */ +void esp_wifi_set_max_tx_power_via_vdd33(uint16_t vdd33); + +/** + * @brief Measure the power voltage of VDD3P3 pin 3 and 4; unit: 1/1024 V + * + * @attention esp_wifi_get_vdd33 can only be called when TOUT pin is suspended. + * @attention The 107th byte in esp_init_data_default.bin (0 ~ 127 bytes) is named as + * vdd33_const. When TOUT pin is suspended, vdd33_const must be set as + * 0xFF, which is 255. + * @attention The return value of esp_wifi_get_vdd33 may be different in different Wi-Fi + * modes, for example, in Modem-sleep mode or in normal Wi-Fi working mode. + * + * @return the power voltage of vdd33 pin 3 and 4 + */ +uint16_t esp_wifi_get_vdd33(void); + /** * @brief Get maximum WiFi transmiting power * @@ -870,16 +968,89 @@ esp_err_t esp_wifi_get_event_mask(uint32_t *mask); * the next packet is allowed to send. Otherwise, wifi_send_pkt_freedom * will return fail. * - * @param uint8 *buf : pointer of packet - * @param uint16 len : packet length - * @param bool sys_seq : follow the system's 802.11 packets sequence number or not, - * if it is true, the sequence number will be increased 1 every - * time a packet sent. + * @param ifx interface if the Wi-Fi mode is Station, the ifx should be WIFI_IF_STA. If the Wi-Fi + * mode is SoftAP, the ifx should be WIFI_IF_AP. If the Wi-Fi mode is Station+SoftAP, the + * ifx should be WIFI_IF_STA or WIFI_IF_AP. If the ifx is wrong, the API returns ESP_ERR_WIFI_IF. + * @param buffer pointer of packet + * @param len packet length + * @param en_sys_seq follow the system's 802.11 packets sequence number or not, + * if it is true, the sequence number will be increased 1 every + * time a packet sent. * * @return ESP_OK, succeed; * @return ESP_FAIL, fail. */ -esp_err_t esp_wifi_send_pkt_freedom(uint8_t *buf, int32_t len, bool sys_seq); +esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq); + +/** + * @brief Operation system start check time and enter sleep + * + * @note This function is called by system, user should not call this + * + * @return + * - wifi state + */ +wifi_state_t esp_wifi_get_state(void); + +/** + * @brief Set RSSI threshold below which APP will get an event + * + * @attention This API needs to be called every time after WIFI_EVENT_STA_BSS_RSSI_LOW event is received. + * + * @param rssi threshold value in dbm between -100 to 0 + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_set_rssi_threshold(int32_t rssi); + +/** + * @brief Get the TSF time + * In Station mode or SoftAP+Station mode if station is not connected or station doesn't receive at least + * one beacon after connected, will return 0 + * + * @attention Enabling power save may cause the return value inaccurate, except WiFi modem sleep + * + * @param interface The interface whose tsf_time is to be retrieved. + * + * @return 0 or the TSF time + */ +int64_t esp_wifi_get_tsf_time(wifi_interface_t interface); + +/** + * @brief Set the inactive time of the ESP32 STA or AP + * + * @attention 1. For Station, If the station does not receive a beacon frame from the connected SoftAP during the inactive time, + * disconnect from SoftAP. Default 6s. + * @attention 2. For SoftAP, If the softAP doesn't receive any data from the connected STA during inactive time, + * the softAP will force deauth the STA. Default is 300s. + * @attention 3. The inactive time configuration is not stored into flash + * + * @param ifx interface to be configured. + * @param sec Inactive time. Unit seconds. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start + * - ESP_ERR_WIFI_ARG: invalid argument, For Station, if sec is less than 3. For SoftAP, if sec is less than 10. + */ +esp_err_t esp_wifi_set_inactive_time(wifi_interface_t ifx, uint16_t sec); + +/** + * @brief Get inactive time of specified interface + * + * @param ifx Interface to be configured. + * @param sec Inactive time. Unit seconds. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_get_inactive_time(wifi_interface_t ifx, uint16_t *sec); #ifdef __cplusplus } diff --git a/components/esp8266/include/esp_wifi_crypto_types.h b/components/esp8266/include/esp_wifi_crypto_types.h new file mode 100644 index 000000000..efe768664 --- /dev/null +++ b/components/esp8266/include/esp_wifi_crypto_types.h @@ -0,0 +1,835 @@ +// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef __ESP_WIFI_CRYPTO_TYPES_H__ +#define __ESP_WIFI_CRYPTO_TYPES_H__ + +/* This is an internal API header for configuring the implementation used for WiFi cryptographic + operations. + + During normal operation, you don't need to use any of these types or functions in this header. + See esp_wifi.h & esp_wifi_types.h instead. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_WIFI_CRYPTO_VERSION 0x00000001 + +/* + * Enumeration for hash operations. + * When WPA2 is connecting, this enum is used to + * request a hash algorithm via crypto_hash_xxx functions. + */ +typedef enum { + ESP_CRYPTO_HASH_ALG_MD5, ESP_CRYPTO_HASH_ALG_SHA1, + ESP_CRYPTO_HASH_ALG_HMAC_MD5, ESP_CRYPTO_HASH_ALG_HMAC_SHA1, + ESP_CRYPTO_HASH_ALG_SHA256, ESP_CRYPTO_HASH_ALG_HMAC_SHA256 +}esp_crypto_hash_alg_t; + +/* + * Enumeration for block cipher operations. + * When WPA2 is connecting, this enum is used to request a block + * cipher algorithm via crypto_cipher_xxx functions. + */ +typedef enum { + ESP_CRYPTO_CIPHER_NULL, ESP_CRYPTO_CIPHER_ALG_AES, ESP_CRYPTO_CIPHER_ALG_3DES, + ESP_CRYPTO_CIPHER_ALG_DES, ESP_CRYPTO_CIPHER_ALG_RC2, ESP_CRYPTO_CIPHER_ALG_RC4 +} esp_crypto_cipher_alg_t; + +/* + * This structure is about the algorithm when do crypto_hash operation, for detail, + * please reference to the structure crypto_hash. + */ +typedef struct crypto_hash esp_crypto_hash_t; + +/* + * This structure is about the algorithm when do crypto_cipher operation, for detail, + * please reference to the structure crypto_cipher. + */ +typedef struct crypto_cipher esp_crypto_cipher_t; + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Initialize a esp_crypto_hash_t structure. + * + * @param alg Hash algorithm. + * @param key Key for keyed hash (e.g., HMAC) or %NULL if not needed. + * @param key_len Length of the key in bytes + * + */ +typedef esp_crypto_hash_t * (*esp_crypto_hash_init_t)(esp_crypto_hash_alg_t alg, const unsigned char *key, int key_len); + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Add data to hash calculation. + * + * @param ctz Context pointer from esp_crypto_hash_init_t function. + * @param data Data buffer to add. + * @param len Length of the buffer. + * + */ +typedef void (*esp_crypto_hash_update_t)(esp_crypto_hash_t *ctx, const unsigned char *data, int len); + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Complete hash calculation. + * + * @param ctz Context pointer from esp_crypto_hash_init_t function. + * @param hash Buffer for hash value or %NULL if caller is just freeing the hash + * context. + * @param len Pointer to length of the buffer or %NULL if caller is just freeing the + * hash context; on return, this is set to the actual length of the hash value + * Returns: 0 on success, -1 if buffer is too small (len set to needed length), + * or -2 on other failures (including failed crypto_hash_update() operations) + * + */ +typedef int (*esp_crypto_hash_finish_t)(esp_crypto_hash_t *ctx, unsigned char *hash, int *len); + +/** + * @brief The AES callback function when do WPS connect. + * + * @param key Encryption key. + * @param iv Encryption IV for CBC mode (16 bytes). + * @param data Data to encrypt in-place. + * @param data_len Length of data in bytes (must be divisible by 16) + */ +typedef int (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len); + +/** + * @brief The AES callback function when do WPS connect. + * + * @param key Decryption key. + * @param iv Decryption IV for CBC mode (16 bytes). + * @param data Data to decrypt in-place. + * @param data_len Length of data in bytes (must be divisible by 16) + * + */ +typedef int (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len); + +/** + * @brief The AES callback function when do STA connect. + * + * @param kek 16-octet Key encryption key (KEK). + * @param n Length of the plaintext key in 64-bit units; + * @param plain Plaintext key to be wrapped, n * 64 bits + * @param cipher Wrapped key, (n + 1) * 64 bits + * + */ +typedef int (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher); + +/** + * @brief The AES callback function when do STA connect. + * + * @param kek 16-octet Key decryption key (KEK). + * @param n Length of the plaintext key in 64-bit units; + * @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits + * @param plain Plaintext key, n * 64 bits + * + */ +typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain); + +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Initialize a esp_crypto_cipher_t structure. + * + * @param alg cipher algorithm. + * @param iv Initialization vector for block ciphers or %NULL for stream ciphers. + * @param key Cipher key + * @param key_len Length of key in bytes + * + */ +typedef esp_crypto_cipher_t * (*esp_crypto_cipher_init_t)(esp_crypto_cipher_alg_t alg, const unsigned char *iv, const unsigned char *key, int key_len); + +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Cipher encrypt. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * @param plain Plaintext to cipher. + * @param crypt Resulting ciphertext. + * @param len Length of the plaintext. + * + */ +typedef int (*esp_crypto_cipher_encrypt_t)(esp_crypto_cipher_t *ctx, + const unsigned char *plain, unsigned char *crypt, int len); +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Cipher decrypt. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * @param crypt Ciphertext to decrypt. + * @param plain Resulting plaintext. + * @param len Length of the cipher text. + * + */ +typedef int (*esp_crypto_cipher_decrypt_t)(esp_crypto_cipher_t *ctx, + const unsigned char *crypt, unsigned char *plain, int len); +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Free cipher context. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * + */ +typedef void (*esp_crypto_cipher_deinit_t)(esp_crypto_cipher_t *ctx); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param key Key for HMAC operations. + * @param key_len Length of the key in bytes. + * @param data Pointers to the data area. + * @param data_len Length of the data area. + * @param mac Buffer for the hash (20 bytes). + * + */ +typedef void (*esp_hmac_sha256_t)(const unsigned char *key, int key_len, const unsigned char *data, + int data_len, unsigned char *mac); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param key Key for HMAC operations. + * @param key_len Length of the key in bytes. + * @param num_elem Number of elements in the data vector. + * @param addr Pointers to the data areas. + * @param len Lengths of the data blocks. + * @param mac Buffer for the hash (32 bytes). + * + */ +typedef void (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len, int num_elem, + const unsigned char *addr[], const int *len, unsigned char *mac); + +/** + * @brief The AES callback function when do STA connect. + * + * @param key Key for PRF. + * @param key_len Length of the key in bytes. + * @param label A unique label for each purpose of the PRF. + * @param data Extra data to bind into the key. + * @param data_len Length of the data. + * @param buf Buffer for the generated pseudo-random key. + * @param buf_len Number of bytes of key to generate. + * + */ +typedef void (*esp_sha256_prf_t)(const unsigned char *key, int key_len, const char *label, + const unsigned char *data, int data_len, unsigned char *buf, int buf_len); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param num_elem Number of elements in the data vector. + * @param addr Pointers to the data areas. + * @param len Lengths of the data blocks. + * @paramac Buffer for the hash. + * + */ +typedef int (*esp_sha256_vector_t)(int num_elem, const unsigned char *addr[], const int *len, + unsigned char *mac); + +/** + * @brief The bignum calculate callback function used when do connect. + * In WPS process, it used to calculate public key and private key. + * + * @param base Base integer (big endian byte array). + * @param base_len Length of base integer in bytes. + * @param power Power integer (big endian byte array). + * @param power_len Length of power integer in bytes. + * @param modulus Modulus integer (big endian byte array). + * @param modulus_len Length of modulus integer in bytes. + * @param result Buffer for the result. + * @param result_len Result length (max buffer size on input, real len on output). + * + */ +typedef int (*esp_crypto_mod_exp_t)(const unsigned char *base, int base_len, + const unsigned char *power, int power_len, + const unsigned char *modulus, int modulus_len, + unsigned char *result, unsigned int *result_len); + +/** + * @brief HMAC-MD5 over data buffer (RFC 2104)' + * + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_md5_t)(const unsigned char *key, unsigned int key_len, const unsigned char *data, + unsigned int data_len, unsigned char *mac); + +/** + * @brief HMAC-MD5 over data vector (RFC 2104) + * + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_md5_vector_t)(const unsigned char *key, unsigned int key_len, unsigned int num_elem, + const unsigned char *addr[], const unsigned int *len, unsigned char *mac); + +/** + * @brief HMAC-SHA1 over data buffer (RFC 2104) + * + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (20 bytes) + * Returns: 0 on success, -1 of failure + */ +typedef int (*esp_hmac_sha1_t)(const unsigned char *key, unsigned int key_len, const unsigned char *data, + unsigned int data_len, unsigned char *mac); + +/** + * @brief HMAC-SHA1 over data vector (RFC 2104) + * + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (20 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_sha1_vector_t)(const unsigned char *key, unsigned int key_len, unsigned int num_elem, + const unsigned char *addr[], const unsigned int *len, unsigned char *mac); + +/** + * @brief SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) + * + * @key: Key for PRF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bytes of key to generate + * Returns: 0 on success, -1 of failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key (e.g., PMK in IEEE 802.11i). + */ +typedef int (*esp_sha1_prf_t)(const unsigned char *key, unsigned int key_len, const char *label, + const unsigned char *data, unsigned int data_len, unsigned char *buf, unsigned int buf_len); + +/** + * @brief SHA-1 hash for data vector + * + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_sha1_vector_t)(unsigned int num_elem, const unsigned char *addr[], const unsigned int *len, + unsigned char *mac); + +/** + * @brief SHA1-based key derivation function (PBKDF2) for IEEE 802.11i + * + * @passphrase: ASCII passphrase + * @ssid: SSID + * @ssid_len: SSID length in bytes + * @iterations: Number of iterations to run + * @buf: Buffer for the generated key + * @buflen: Length of the buffer in bytes + * Returns: 0 on success, -1 of failure + * + * This function is used to derive PSK for WPA-PSK. For this protocol, + * iterations is set to 4096 and buflen to 32. This function is described in + * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. + */ +typedef int (*esp_pbkdf2_sha1_t)(const char *passphrase, const char *ssid, unsigned int ssid_len, + int iterations, unsigned char *buf, unsigned int buflen); + +/** + * @brief XOR RC4 stream to given data with skip-stream-start + * + * @key: RC4 key + * @keylen: RC4 key length + * @skip: number of bytes to skip from the beginning of the RC4 stream + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ +typedef int (*esp_rc4_skip_t)(const unsigned char *key, unsigned int keylen, unsigned int skip, + unsigned char *data, unsigned int data_len); + +/** + * @brief MD5 hash for data vector + * + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_md5_vector_t)(unsigned int num_elem, const unsigned char *addr[], const unsigned int *len, + unsigned char *mac); + +/** + * @brief Encrypt one AES block + * + * @ctx: Context pointer from aes_encrypt_init() + * @plain: Plaintext data to be encrypted (16 bytes) + * @crypt: Buffer for the encrypted data (16 bytes) + */ +typedef void (*esp_aes_encrypt_t)(void *ctx, const unsigned char *plain, unsigned char *crypt); + +/** + * @brief Initialize AES for encryption + * + * @key: Encryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +typedef void * (*esp_aes_encrypt_init_t)(const unsigned char *key, unsigned int len); + +/** + * @brief Deinitialize AES encryption + * + * @ctx: Context pointer from aes_encrypt_init() + */ +typedef void (*esp_aes_encrypt_deinit_t)(void *ctx); + +/** + * @brief Decrypt one AES block + * + * @ctx: Context pointer from aes_encrypt_init() + * @crypt: Encrypted data (16 bytes) + * @plain: Buffer for the decrypted data (16 bytes) + */ +typedef void (*esp_aes_decrypt_t)(void *ctx, const unsigned char *crypt, unsigned char *plain); + +/** + * @brief Initialize AES for decryption + * + * @key: Decryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +typedef void * (*esp_aes_decrypt_init_t)(const unsigned char *key, unsigned int len); + +/** + * @brief One-Key CBC MAC (OMAC1) hash with AES-128 for MIC computation + * + * @key: 128-bit key for the hash operation + * @data: Data buffer for which a MIC is computed + * @data_len: Length of data buffer in bytes + * @mic: Buffer for MIC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_omac1_aes_128_t)(const uint8_t *key, const uint8_t *data, size_t data_len, + uint8_t *mic); + +/** + * @brief Decrypt data using CCMP (Counter Mode CBC-MAC Protocol OR + * Counter Mode Cipher Block Chaining Message Authentication + * Code Protocol) which is used in IEEE 802.11i RSN standard. + * @tk: 128-bit Temporal Key for obtained during 4-way handshake + * @hdr: Pointer to IEEE802.11 frame headeri needed for AAD + * @data: Pointer to encrypted data buffer + * @data_len: Encrypted data length in bytes + * @decrypted_len: Length of decrypted data + * @espnow_pkt: Indicates if it's an ESPNOW packet + * Returns: Pointer to decrypted data on success, NULL on failure + */ +typedef uint8_t * (*esp_ccmp_decrypt_t)(const uint8_t *tk, const uint8_t *ieee80211_hdr, + const uint8_t *data, size_t data_len, + size_t *decrypted_len, bool espnow_pkt); + +/** + * @brief Encrypt data using CCMP (Counter Mode CBC-MAC Protocol OR + * Counter Mode Cipher Block Chaining Message Authentication + * Code Protocol) which is used in IEEE 802.11i RSN standard. + * @tk: 128-bit Temporal Key for obtained during 4-way handshake + * @frame: Pointer to IEEE802.11 frame including header + * @len: Length of the frame including header + * @hdrlen: Length of the header + * @pn: Packet Number counter + * @keyid: Key ID to be mentioned in CCMP Vector + * @encrypted_len: Length of the encrypted frame including header + */ +typedef uint8_t * (*esp_ccmp_encrypt_t)(const uint8_t *tk, uint8_t *frame, size_t len, size_t hdrlen, + uint8_t *pn, int keyid, size_t *encrypted_len); + +/** + * @brief Deinitialize AES decryption + * + * @ctx: Context pointer from aes_encrypt_init() + */ +typedef void (*esp_aes_decrypt_deinit_t)(void *ctx); + +/** + * @brief Initialize TLS library + * + * @conf: Configuration data for TLS library + * Returns: Context data to be used as tls_ctx in calls to other functions, + * or %NULL on failure. + * + * Called once during program startup and once for each RSN pre-authentication + * session. In other words, there can be two concurrent TLS contexts. If global + * library initialization is needed (i.e., one that is shared between both + * authentication types), the TLS library wrapper should maintain a reference + * counter and do global initialization only when moving from 0 to 1 reference. + */ +typedef void * (*esp_tls_init_t)(void); + +/** + * @brief Deinitialize TLS library + * + * @tls_ctx: TLS context data from tls_init() + * + * Called once during program shutdown and once for each RSN pre-authentication + * session. If global library deinitialization is needed (i.e., one that is + * shared between both authentication types), the TLS library wrapper should + * maintain a reference counter and do global deinitialization only when moving + * from 1 to 0 references. + */ +typedef void (*esp_tls_deinit_t)(void *tls_ctx); + +/** + * @brief Add certificate and private key for connect + + * @sm: eap state machine + * + * Returns: 0 for success, -1 state machine didn't exist, -2 short of certificate or key + */ +typedef int (*esp_eap_peer_blob_init_t)(void *sm); + +/** + * @brief delete the certificate and private + * + * @sm: eap state machine + * + */ +typedef void (*esp_eap_peer_blob_deinit_t)(void *sm); + +/** + * @brief Initialize the eap state machine + * + * @sm: eap state machine + * @private_key_passwd: the start address of private_key_passwd + * @private_key_passwd_len: length of private_key_password + * + * Returns: 0 is success, -1 state machine didn't exist, -2 short of parameters + * + */ +typedef int (*esp_eap_peer_config_init_t)(void *sm, unsigned char *private_key_passwd,int private_key_passwd_len); + +/** + * @brief Deinit the eap state machine + * + * @sm: eap state machine + * + */ +typedef void (*esp_eap_peer_config_deinit_t)(void *sm); + +/** + * @brief Register the eap method + * + * Note: ESP32 only support PEAP/TTLS/TLS three eap methods now. + * + */ +typedef int (*esp_eap_peer_register_methods_t)(void); + +/** + * @brief remove the eap method + * + * Note: ESP32 only support PEAP/TTLS/TLS three eap methods now. + * + */ +typedef void (*esp_eap_peer_unregister_methods_t)(void); + +/** + * @brief remove the eap method before build new connect + * + * @sm: eap state machine + * @txt: not used now + */ +typedef void (*esp_eap_deinit_prev_method_t)(void *sm, const char *txt); + +/** + * @brief Get EAP method based on type number + * + * @vendor: EAP Vendor-Id (0 = IETF) + * @method: EAP type number + * Returns: Pointer to EAP method or %NULL if not found + */ +typedef const void * (*esp_eap_peer_get_eap_method_t)(int vendor, int method); + +/** + * @brief Abort EAP authentication + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * + * Release system resources that have been allocated for the authentication + * session without fully deinitializing the EAP state machine. + */ +typedef void (*esp_eap_sm_abort_t)(void *sm); + +/** + * @brief Build EAP-NAK for the current network + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @type: EAP type of the fail reason + * @id: EAP identifier for the packet + * + * This function allocates and builds a nak packet for the + * current network. The caller is responsible for freeing the returned data. + */ +typedef void * (*esp_eap_sm_build_nak_t)(void *sm, int type, unsigned char id); + +/** + * @brief Build EAP-Identity/Response for the current network + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @id: EAP identifier for the packet + * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2) + * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on + * failure + * + * This function allocates and builds an EAP-Identity/Response packet for the + * current network. The caller is responsible for freeing the returned data. + */ +typedef void * (*esp_eap_sm_build_identity_resp_t)(void *sm, unsigned char id, int encrypted); + +/** + * @brief Allocate a buffer for an EAP message + * + * @vendor: Vendor-Id (0 = IETF) + * @type: EAP type + * @payload_len: Payload length in bytes (data after Type) + * @code: Message Code (EAP_CODE_*) + * @identifier: Identifier + * Returns: Pointer to the allocated message buffer or %NULL on error + * + * This function can be used to allocate a buffer for an EAP message and fill + * in the EAP header. This function is automatically using expanded EAP header + * if the selected Vendor-Id is not IETF. In other words, most EAP methods do + * not need to separately select which header type to use when using this + * function to allocate the message buffers. The returned buffer has room for + * payload_len bytes and has the EAP header and Type field already filled in. + */ +typedef void * (*esp_eap_msg_alloc_t)(int vendor, int type, unsigned int payload_len, + unsigned char code, unsigned char identifier); + +/** + * @brief get the enrollee mac address + * @mac_addr: instore the mac address of enrollee + * @uuid: Universally Unique Identifer of the enrollee + * + */ +typedef void (*esp_uuid_gen_mac_addr_t)(const unsigned char *mac_addr, unsigned char *uuid); + +/** + * @brief free the message after finish DH + * + */ +typedef void (*esp_dh5_free_t)(void *ctx); + +/** + * @brief Build WPS IE for (Re)Association Request + * + * @req_type: Value for Request Type attribute + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_assoc_req_ie_t)(int req_type); + +/** + * @brief Build WPS IE for (Re)Association Response + * + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_assoc_resp_ie_t)(void); + +/** + * @brief Build WPS IE for Probe Request + * + * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for + * most other use cases) + * @dev: Device attributes + * @uuid: Own UUID + * @req_type: Value for Request Type attribute + * @num_req_dev_types: Number of requested device types + * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or + * %NULL if none + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_probe_req_ie_t)(uint16_t pw_id, void *dev, const unsigned char *uuid, + int req_type, unsigned int num_req_dev_types, const unsigned char *req_dev_types); + +/** + * @brief build public key for exchange in M1 + * + * + */ +typedef int (*esp_wps_build_public_key_t)(void *wps, void *msg, int mode); + + +/** + * @brief get the wps information in exchange password + * + * + */ +typedef void * (*esp_wps_enrollee_get_msg_t)(void *wps, void *op_code); + +/** + * @brief deal with the wps information in exchange password + * + * + */ +typedef int (*esp_wps_enrollee_process_msg_t)(void *wps, int op_code, const void *msg); + +/** + * @brief Generate a random PIN + * + * Returns: Eight digit PIN (i.e., including the checksum digit) + */ +typedef unsigned int (*esp_wps_generate_pin_t)(void); + +/** + * @brief Check whether WPS IE indicates active PIN + * + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PIN Registrar is active, 0 if not + */ +typedef int (*esp_wps_is_selected_pin_registrar_t)(const void *msg, unsigned char *bssid); + +/** + * @brief Check whether WPS IE indicates active PBC + * + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PBC Registrar is active, 0 if not + */ +typedef int (*esp_wps_is_selected_pbc_registrar_t)(const void *msg, unsigned char *bssid); + +/** + * @brief The crypto callback function structure used when do station security connect. + * The structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct { + uint32_t size; + uint32_t version; + esp_aes_wrap_t aes_wrap; /**< station connect function used when send EAPOL frame */ + esp_aes_unwrap_t aes_unwrap; /**< station connect function used when decrypt key data */ + esp_hmac_sha256_vector_t hmac_sha256_vector; /**< station connect function used when check MIC */ + esp_sha256_prf_t sha256_prf; /**< station connect function used when check MIC */ + esp_hmac_md5_t hmac_md5; + esp_hmac_md5_vector_t hamc_md5_vector; + esp_hmac_sha1_t hmac_sha1; + esp_hmac_sha1_vector_t hmac_sha1_vector; + esp_sha1_prf_t sha1_prf; + esp_sha1_vector_t sha1_vector; + esp_pbkdf2_sha1_t pbkdf2_sha1; + esp_rc4_skip_t rc4_skip; + esp_md5_vector_t md5_vector; + esp_aes_encrypt_t aes_encrypt; + esp_aes_encrypt_init_t aes_encrypt_init; + esp_aes_encrypt_deinit_t aes_encrypt_deinit; + esp_aes_decrypt_t aes_decrypt; + esp_aes_decrypt_init_t aes_decrypt_init; + esp_aes_decrypt_deinit_t aes_decrypt_deinit; + esp_aes_128_encrypt_t aes_128_encrypt; + esp_aes_128_decrypt_t aes_128_decrypt; + esp_omac1_aes_128_t omac1_aes_128; + esp_ccmp_decrypt_t ccmp_decrypt; + esp_ccmp_encrypt_t ccmp_encrypt; +}wpa_crypto_funcs_t; + +/** + * @brief The crypto callback function structure used when do WPS process. The + * structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct{ + uint32_t size; + uint32_t version; + esp_aes_128_encrypt_t aes_128_encrypt; /**< function used to process message when do WPS */ + esp_aes_128_decrypt_t aes_128_decrypt; /**< function used to process message when do WPS */ + esp_crypto_mod_exp_t crypto_mod_exp; /**< function used to calculate public key and private key */ + esp_hmac_sha256_t hmac_sha256; /**< function used to get attribute */ + esp_hmac_sha256_vector_t hmac_sha256_vector; /**< function used to process message when do WPS */ + esp_sha256_vector_t sha256_vector; /**< function used to process message when do WPS */ + esp_uuid_gen_mac_addr_t uuid_gen_mac_addr; + esp_dh5_free_t dh5_free; + esp_wps_build_assoc_req_ie_t wps_build_assoc_req_ie; + esp_wps_build_assoc_resp_ie_t wps_build_assoc_resp_ie; + esp_wps_build_probe_req_ie_t wps_build_probe_req_ie; + esp_wps_build_public_key_t wps_build_public_key; + esp_wps_enrollee_get_msg_t wps_enrollee_get_msg; + esp_wps_enrollee_process_msg_t wps_enrollee_process_msg; + esp_wps_generate_pin_t wps_generate_pin; + esp_wps_is_selected_pin_registrar_t wps_is_selected_pin_registrar; + esp_wps_is_selected_pbc_registrar_t wps_is_selected_pbc_registrar; + esp_eap_msg_alloc_t eap_msg_alloc; +}wps_crypto_funcs_t; + +/** + * @brief The crypto callback function structure used when do WPA enterprise connect. + * The structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct { + uint32_t size; + uint32_t version; + esp_crypto_hash_init_t crypto_hash_init; /**< function used to initialize a crypto_hash structure when use TLSV1 */ + esp_crypto_hash_update_t crypto_hash_update; /**< function used to calculate hash data when use TLSV1 */ + esp_crypto_hash_finish_t crypto_hash_finish; /**< function used to finish the hash calculate when use TLSV1 */ + esp_crypto_cipher_init_t crypto_cipher_init; /**< function used to initialize a crypt_cipher structure when use TLSV1 */ + esp_crypto_cipher_encrypt_t crypto_cipher_encrypt; /**< function used to encrypt cipher when use TLSV1 */ + esp_crypto_cipher_decrypt_t crypto_cipher_decrypt; /**< function used to decrypt cipher when use TLSV1 */ + esp_crypto_cipher_deinit_t crypto_cipher_deinit; /**< function used to free context when use TLSV1 */ + esp_crypto_mod_exp_t crypto_mod_exp; /**< function used to do key exchange when use TLSV1 */ + esp_sha256_vector_t sha256_vector; /**< function used to do X.509v3 certificate parsing and processing */ + esp_tls_init_t tls_init; + esp_tls_deinit_t tls_deinit; + esp_eap_peer_blob_init_t eap_peer_blob_init; + esp_eap_peer_blob_deinit_t eap_peer_blob_deinit; + esp_eap_peer_config_init_t eap_peer_config_init; + esp_eap_peer_config_deinit_t eap_peer_config_deinit; + esp_eap_peer_register_methods_t eap_peer_register_methods; + esp_eap_peer_unregister_methods_t eap_peer_unregister_methods; + esp_eap_deinit_prev_method_t eap_deinit_prev_method; + esp_eap_peer_get_eap_method_t eap_peer_get_eap_method; + esp_eap_sm_abort_t eap_sm_abort; + esp_eap_sm_build_nak_t eap_sm_build_nak; + esp_eap_sm_build_identity_resp_t eap_sm_build_identity_resp; + esp_eap_msg_alloc_t eap_msg_alloc; +} wpa2_crypto_funcs_t; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/esp8266/include/esp_wifi_os_adapter.h b/components/esp8266/include/esp_wifi_os_adapter.h deleted file mode 100644 index 1605197cb..000000000 --- a/components/esp8266/include/esp_wifi_os_adapter.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ESP_WIFI_OS_ADAPTER_H_ -#define ESP_WIFI_OS_ADAPTER_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000001 -#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF - -#define OSI_FUNCS_TIME_BLOCKING 0xffffffff - -#define OSI_QUEUE_SEND_FRONT 0 -#define OSI_QUEUE_SEND_BACK 1 -#define OSI_QUEUE_SEND_OVERWRITE 2 - -#define OSI_MALLOC_CAP_32BIT (1 << 1) -#define OSI_MALLOC_CAP_8BIT (1 << 2) -#define OSI_MALLOC_CAP_DMA (1 << 3) - -typedef struct { - int32_t version; - - void *(*task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio); - void (*task_delete)(void *task_handle); - void (*task_yield)(void); - void (*task_yield_from_isr)(void); - void (*task_delay)(uint32_t tick); - void *(*task_get_current_task)(void); - uint32_t (*task_get_max_priority)(void); - - uint32_t (*task_ms_to_tick)(uint32_t ms); - - void (*task_suspend_all)(void); - void (*task_resume_all)(void); - - void (*os_init)(void); - void (*os_start)(void); - - void *(*semphr_create)(uint32_t max, uint32_t init); - void (*semphr_delete)(void *semphr); - bool (*semphr_take_from_isr)(void *semphr, int *hptw); - bool (*semphr_give_from_isr)(void *semphr, int *hptw); - bool (*semphr_take)(void *semphr, uint32_t block_time_tick); - bool (*semphr_give)(void *semphr); - - void *(*mutex_create)(void); - void (*mutex_delete)(void *mutex); - bool (*mutex_lock)(void *mutex); - bool (*mutex_unlock)(void *mutex); - - void *(*queue_create)(uint32_t queue_len, uint32_t item_size); - void (*queue_delete)(void *queue); - bool (*queue_send)(void *queue, void *item, uint32_t block_time_tick, uint32_t pos); - bool (*queue_send_from_isr)(void *queue, void *item, int *hptw); - bool (*queue_recv)(void *queue, void *item, uint32_t block_time_tick); - bool (*queue_recv_from_isr)(void *queue, void *item, int *hptw); - uint32_t (*queue_msg_waiting)(void *queue); - - void *(*timer_create)(const char *name, uint32_t period_ticks, bool auto_load, void *arg, void (*cb)(void *timer)); - void *(*timer_get_arg)(void *timer); - bool (*timer_reset)(void *timer, uint32_t ticks); - bool (*timer_stop)(void *timer, uint32_t ticks); - bool (*timer_delete)(void *timer, uint32_t ticks); - - void *(*malloc)(uint32_t size, uint32_t cap, const char *file, size_t line); - void *(*zalloc)(uint32_t size, uint32_t cap, const char *file, size_t line); - void *(*realloc)(void *ptr, uint32_t size, uint32_t cap, const char *file, size_t line); - void *(*calloc)(uint32_t cnt, uint32_t size, uint32_t cap, const char *file, size_t line); - void (*free)(void *p, const char *file, size_t line); - uint32_t (*get_free_heap_size)(void); - - void (*srand)(uint32_t seed); - int32_t (*rand)(void); - - int32_t (* nvs_set_i8)(uint32_t handle, const char* key, int8_t value); - int32_t (* nvs_get_i8)(uint32_t handle, const char* key, int8_t* out_value); - int32_t (* nvs_set_u8)(uint32_t handle, const char* key, uint8_t value); - int32_t (* nvs_get_u8)(uint32_t handle, const char* key, uint8_t* out_value); - int32_t (* nvs_set_u16)(uint32_t handle, const char* key, uint16_t value); - int32_t (* nvs_get_u16)(uint32_t handle, const char* key, uint16_t* out_value); - int32_t (* nvs_open)(const char* name, uint32_t open_mode, uint32_t *out_handle); - void (* nvs_close)(uint32_t handle); - int32_t (* nvs_commit)(uint32_t handle); - int32_t (* nvs_set_blob)(uint32_t handle, const char* key, const void* value, size_t length); - int32_t (* nvs_get_blob)(uint32_t handle, const char* key, void* out_value, size_t* length); - int32_t (* nvs_erase_key)(uint32_t handle, const char* key); - - int32_t magic; -} wifi_osi_funcs_t; - -#ifdef __cplusplus -} -#endif - -#endif /* ESP_WIFI_OS_ADAPTER_H_ */ diff --git a/components/esp8266/include/esp_wifi_osi.h b/components/esp8266/include/esp_wifi_osi.h index bb2fb92d8..8fc40fca0 100644 --- a/components/esp8266/include/esp_wifi_osi.h +++ b/components/esp8266/include/esp_wifi_osi.h @@ -15,141 +15,18 @@ #ifndef ESP_WIFI_OSI_H_ #define ESP_WIFI_OSI_H_ -#include "esp_wifi_os_adapter.h" - #ifdef __cplusplus extern "C" { #endif -extern wifi_osi_funcs_t s_wifi_osi_funcs; - -#define wifi_task_create(func, name, depth, param, pri) \ - s_wifi_osi_funcs.task_create(func, name, depth, param, pri) - -#define wifi_task_delete(h) \ - s_wifi_osi_funcs.task_delete(h) - -#define wifi_task_yield() \ - s_wifi_osi_funcs.task_yield() - -#define wifi_task_yield_from_isr() \ - s_wifi_osi_funcs.task_yield_from_isr() - -#define wifi_task_delay(t) \ - s_wifi_osi_funcs.task_delay(t) - -#define wifi_task_get_current_task() \ - s_wifi_osi_funcs.task_get_current_task() - -#define wifi_task_get_max_priority() \ - s_wifi_osi_funcs.task_get_max_priority() - -#define wifi_task_ms_to_ticks(t) \ - s_wifi_osi_funcs.task_ms_to_tick(t) - -#define wifi_task_suspend_all() \ - s_wifi_osi_funcs.task_suspend_all() - -#define wifi_task_resume_all() \ - s_wifi_osi_funcs.task_resume_all() - -#define wifi_os_init() \ - s_wifi_osi_funcs.os_init() - -#define wifi_os_start() \ - s_wifi_osi_funcs.os_start() - -#define wifi_semphr_create(m, i) \ - s_wifi_osi_funcs.semphr_create(m, i) - -#define wifi_semphr_delete(s) \ - s_wifi_osi_funcs.semphr_delete(s) - -#define wifi_semphr_take_from_isr(s, r) \ - s_wifi_osi_funcs.semphr_take_from_isr(s, r) - -#define wifi_semphr_give_from_isr(s, r) \ - s_wifi_osi_funcs.semphr_give_from_isr(s, r) - -#define wifi_semphr_take(s, t) \ - s_wifi_osi_funcs.semphr_take(s, t) - -#define wifi_semphr_give(s) \ - s_wifi_osi_funcs.semphr_give(s) - -#define wifi_mutex_create() \ - s_wifi_osi_funcs.mutex_create() - -#define wifi_mutex_delete(m) \ - s_wifi_osi_funcs.mutex_delete(m) - -#define wifi_mutex_lock(m) \ - s_wifi_osi_funcs.mutex_lock(m) - -#define wifi_mutex_unlock(m) \ - s_wifi_osi_funcs.mutex_unlock(m) - -#define wifi_queue_create(ql, is) \ - s_wifi_osi_funcs.queue_create(ql, is) - -#define wifi_queue_delete(q) \ - s_wifi_osi_funcs.queue_delete(q) - -#define wifi_queue_send(q, i, t, p) \ - s_wifi_osi_funcs.queue_send(q, i, t, p) - -#define wifi_queue_send_from_isr(q, i, r) \ - s_wifi_osi_funcs.queue_send_from_isr(q, i, r) - -#define wifi_queue_recv(q, i, t) \ - s_wifi_osi_funcs.queue_recv(q, i, t) - -#define wifi_queue_recv_from_isr(q, i, r) \ - s_wifi_osi_funcs.queue_recv_from_isr(q, i, r) - -#define wifi_queue_msg_waiting(q) \ - s_wifi_osi_funcs.queue_msg_waiting(q) - -#define wifi_timer_create(n, p, al, ag, cb) \ - s_wifi_osi_funcs.timer_create(n, p, al, ag, cb) - -#define wifi_timer_get_arg(t) \ - s_wifi_osi_funcs.timer_get_arg(t) - -#define wifi_timer_reset(t, tk) \ - s_wifi_osi_funcs.timer_reset(t, tk) - -#define wifi_timer_stop(t, tk) \ - s_wifi_osi_funcs.timer_stop(t, tk) - -#define wifi_timer_delete(t, tk) \ - s_wifi_osi_funcs.timer_delete(t, tk) - -#define wifi_malloc(s, c) \ - s_wifi_osi_funcs.malloc(s, c, __ESP_FILE__, __LINE__) - -#define wifi_zalloc(s, c) \ - s_wifi_osi_funcs.zalloc(s, c, __ESP_FILE__, __LINE__) - -#define wifi_calloc(cnt, s, c) \ - s_wifi_osi_funcs.calloc(cnt, s, c, __ESP_FILE__, __LINE__) - -#define wifi_realloc(ptr, s, c) \ - s_wifi_osi_funcs.realloc(ptr, s, c, __ESP_FILE__, __LINE__) - -#define wifi_free(p) \ - s_wifi_osi_funcs.free(p, __ESP_FILE__, __LINE__) - -#define wifi_get_free_heap_size() \ - s_wifi_osi_funcs.get_free_heap_size() - -#define wifi_srand(s) \ - s_wifi_osi_funcs.srand(s) +#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000001 +#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF -#define wifi_rand() \ - s_wifi_osi_funcs.rand() +#define OSI_FUNCS_TIME_BLOCKING 0xffffffff -void *osi_task_top_sp(void); +#define OSI_QUEUE_SEND_FRONT 0 +#define OSI_QUEUE_SEND_BACK 1 +#define OSI_QUEUE_SEND_OVERWRITE 2 #ifdef __cplusplus } diff --git a/components/esp8266/include/esp_wifi_types.h b/components/esp8266/include/esp_wifi_types.h index 758edda24..900ececd4 100755 --- a/components/esp8266/include/esp_wifi_types.h +++ b/components/esp8266/include/esp_wifi_types.h @@ -18,8 +18,10 @@ #include #include +#include #include "esp_err.h" #include "esp_interface.h" +#include "esp_event_base.h" #ifdef __cplusplus extern "C" { @@ -59,6 +61,8 @@ typedef enum { WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */ WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */ WIFI_AUTH_WPA2_ENTERPRISE, /**< authenticate mode : WPA2_ENTERPRISE */ + WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */ + WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */ WIFI_AUTH_MAX } wifi_auth_mode_t; @@ -87,11 +91,16 @@ typedef enum { WIFI_REASON_802_1X_AUTH_FAILED = 23, WIFI_REASON_CIPHER_SUITE_REJECTED = 24, + WIFI_REASON_INVALID_PMKID = 53, + WIFI_REASON_BEACON_TIMEOUT = 200, WIFI_REASON_NO_AP_FOUND = 201, WIFI_REASON_AUTH_FAIL = 202, WIFI_REASON_ASSOC_FAIL = 203, WIFI_REASON_HANDSHAKE_TIMEOUT = 204, + WIFI_REASON_CONNECTION_FAIL = 205, + WIFI_REASON_AP_TSF_RESET = 206, + WIFI_REASON_BASIC_RATE_NOT_SUPPORT = 207, } wifi_err_reason_t; typedef enum { @@ -136,6 +145,7 @@ typedef enum { WIFI_CIPHER_TYPE_TKIP, /**< the cipher type is TKIP */ WIFI_CIPHER_TYPE_CCMP, /**< the cipher type is CCMP */ WIFI_CIPHER_TYPE_TKIP_CCMP, /**< the cipher type is TKIP and CCMP */ + WIFI_CIPHER_TYPE_AES_CMAC128,/**< the cipher type is AES-CMAC-128 */ WIFI_CIPHER_TYPE_UNKNOWN, /**< the cipher type is unknown */ } wifi_cipher_type_t; @@ -152,6 +162,7 @@ typedef struct { uint8_t primary; /**< channel of AP */ wifi_second_chan_t second; /**< secondary channel of AP */ int8_t rssi; /**< signal strength of AP */ + int16_t freq_offset; /**< frequency offset of AP */ wifi_auth_mode_t authmode; /**< authmode of AP */ wifi_cipher_type_t pairwise_cipher; /**< pairwise cipher of AP */ wifi_cipher_type_t group_cipher; /**< group cipher of AP */ @@ -181,12 +192,46 @@ typedef struct { wifi_auth_mode_t authmode; /**< The weakest authmode to accept in the fast scan mode */ } wifi_fast_scan_threshold_t; +typedef enum { + WIFI_STATE_DEINIT=0, + WIFI_STATE_INIT, + WIFI_STATE_START +}wifi_state_t; + typedef enum { WIFI_PS_NONE, /**< No power save */ - WIFI_PS_MAX_MODEM, /**< Maximum modem power saving. In this mode, station close cpu and RF in DTIM period */ - WIFI_PS_MIN_MODEM, /**< Minimum modem power saving. In this mode, station close RF in DTIM period */ + WIFI_PS_MIN_MODEM, /**< Minimum modem power saving. In this mode, station wakes up to receive beacon every DTIM period */ + WIFI_PS_MAX_MODEM, /**< Maximum modem power saving. In this mode, interval to receive beacons is determined by the listen_interval + parameter in wifi_sta_config_t. + Attention: Using this option may cause ping failures. Not recommended */ } wifi_ps_type_t; +/** + * @brief Wi-Fi Power management config for ESP8266 + * + * Pass a pointer to this structure as an argument to esp_wifi_set_pm_config function. + */ +typedef struct { + uint8_t max_bcn_early_ms; /**< max beacon early time(2~15ms), default 4ms. */ + uint8_t max_bcn_timeout_ms; /**< max beacon timeout time(12~32ms), default 24ms. */ + uint8_t wait_time; /**< wait time before close RF (10~100ms), default 20ms. */ + uint8_t wait_tx_cnt; /**< wait cnt after tx packet done(1~20), default 2, real time = wait_tx_cnt * wait_time. */ + uint8_t wait_rx_bdata_cnt; /**< wait cnt after rx broadcast packet(1~100), default 2, real time = wait_tx_cnt * wait_time. */ + uint8_t wait_rx_udata_cnt; /**< wait cnt after rx unicast packet(1~100), default 4, real time = wait_tx_cnt * wait_time. */ + bool recv_bdata; /**< Receive broadcast/multicast packet or not when WiFi in power save. default true(receive broadcast/multicast packet)*/ +} esp_pm_config_t; + +/** + * @brief Power management config for ESP8266 + * + * Pass a pointer to this structure as an argument to esp_pm_configure function. + */ +typedef struct { + int max_freq_mhz; /*!< Not used in ESP8266 */ + int min_freq_mhz; /*!< Not used in ESP8266 */ + bool light_sleep_enable; /*!< Enter light sleep when no locks are taken */ +} esp_pm_config_esp8266_t; + #define WIFI_PS_MODEM WIFI_PS_MIN_MODEM /**< @deprecated Use WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM instead */ #define WIFI_PROTOCOL_11B 1 @@ -199,6 +244,12 @@ typedef enum { WIFI_BW_HT40, /* Bandwidth is HT40 */ } wifi_bandwidth_t; +/** Configuration structure for Protected Management Frame */ +typedef struct { + bool capable; /**< Advertizes support for Protected Management Frame. Device will prefer to connect in PMF mode if other device also advertizes PMF capability. */ + bool required; /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */ +} wifi_pmf_config_t; + /** @brief Soft-AP configuration settings for the ESP8266 */ typedef struct { uint8_t ssid[32]; /**< SSID of ESP8266 soft-AP */ @@ -222,6 +273,10 @@ typedef struct { uint16_t listen_interval; /**< Listen interval for ESP8266 station to receive beacon when WIFI_PS_MAX_MODEM is set. Units: AP beacon intervals. Defaults to 3 if set to 0. */ wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */ wifi_fast_scan_threshold_t threshold; /**< When scan_method is set to WIFI_FAST_SCAN, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */ + wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */ + uint32_t rm_enabled:1; /**< Whether radio measurements are enabled for the connection */ + uint32_t btm_enabled:1; /**< Whether BTM is enabled for the connection */ + uint32_t reserved:30; /**< Reserved for future feature set */ } wifi_sta_config_t; /** @brief Configuration data for ESP8266 AP or STA. @@ -300,17 +355,17 @@ typedef struct { typedef struct { signed rssi: 8; /**< signal intensity of packet */ unsigned rate: 4; /**< data rate */ - unsigned is_group: 1; + unsigned is_group: 1; /**< usually not used */ unsigned : 1; /**< reserve */ unsigned sig_mode: 2; /**< 0:is not 11n packet; 1:is 11n packet */ - unsigned legacy_length: 12; - unsigned damatch0: 1; - unsigned damatch1: 1; - unsigned bssidmatch0: 1; - unsigned bssidmatch1: 1; + unsigned legacy_length: 12; /**< Length of 11bg mode packet */ + unsigned damatch0: 1; /**< usually not used */ + unsigned damatch1: 1; /**< usually not used */ + unsigned bssidmatch0: 1; /**< usually not used */ + unsigned bssidmatch1: 1; /**< usually not used */ unsigned mcs: 7; /**< if is 11n packet, shows the modulation(range from 0 to 76) */ unsigned cwb: 1; /**< if is 11n packet, shows if is HT40 packet or not */ - unsigned HT_length: 16; /**< reserve */ + unsigned HT_length: 16; /**< Length of 11n mode packet */ unsigned smoothing: 1; /**< reserve */ unsigned not_sounding: 1; /**< reserve */ unsigned : 1; /**< reserve */ @@ -318,18 +373,20 @@ typedef struct { unsigned stbc: 2; /**< STBC */ unsigned fec_coding: 1; /**< Flag is set for 11n packets which are LDPC */ unsigned sgi: 1; /**< SGI */ - unsigned rxend_state: 8; + unsigned rxend_state: 8; /**< usually not used */ unsigned ampdu_cnt: 8; /**< ampdu cnt */ unsigned channel: 4; /**< which channel this packet in */ unsigned : 4; /**< reserve */ - signed noise_floor: 8; + signed noise_floor: 8; /**< usually not used */ } wifi_pkt_rx_ctrl_t; /** @brief Payload passed to 'buf' parameter of promiscuous mode RX callback. */ typedef struct { wifi_pkt_rx_ctrl_t rx_ctrl; /**< metadata header */ - uint8_t payload[0]; /**< Data or management payload. Length of payload is described by rx_ctrl.sig_len. Type of content determined by packet type argument of callback. */ + uint8_t payload[0]; /**< Data or management frame payload. Length of payload is + min(112, (pkt->rx_ctrl.sig_mode ? pkt->rx_ctrl.HT_length : pkt->rx_ctrl.legacy_length)) + Type of content determined by packet type argument of callback. */ } wifi_promiscuous_pkt_t; /** @@ -372,6 +429,9 @@ typedef struct { #define WIFI_EVENT_MASK_NONE (0) /**< mask none of the WiFi events */ #define WIFI_EVENT_MASK_AP_PROBEREQRECVED (BIT(0)) /**< mask SYSTEM_EVENT_AP_PROBEREQRECVED event */ +/** + * @brief WIFI hardware TX result code + */ typedef enum { TX_STATUS_SUCCESS = 1, TX_STATUS_SRC_EXCEED, @@ -379,6 +439,9 @@ typedef enum { TX_STATUS_DISCARD, } wifi_tx_result_t; +/** + * @brief WIFI hardware TX rate + */ typedef enum { PHY_RATE_1_LONG, PHY_RATE_2_LONG, @@ -398,14 +461,112 @@ typedef enum { PHY_RATE_9, } wifi_tx_rate_t; +/** + * @brief WIFI hardware TX status + */ typedef struct { - unsigned wifi_tx_result: 8; - unsigned wifi_tx_src: 6; - unsigned wifi_tx_lrc: 6; - unsigned wifi_tx_rate: 8; - unsigned unused: 4; + unsigned wifi_tx_result: 8; /*!< TX status code, descripted by "wifi_tx_result_t" */ + unsigned wifi_tx_src: 6; /*!< TX status SRC */ + unsigned wifi_tx_lrc: 6; /*!< TX status LRC */ + unsigned wifi_tx_rate: 8; /*!< TX rate, descripted by "wifi_tx_rate_t" */ + unsigned unused: 4; /*!< Resolved */ } wifi_tx_status_t; +/** @cond **/ +/** @brief WiFi event base declaration */ +ESP_EVENT_DECLARE_BASE(WIFI_EVENT); +/** @endcond **/ + +/** WiFi event declarations */ +typedef enum { + WIFI_EVENT_WIFI_READY = 0, /**< WiFi ready */ + WIFI_EVENT_SCAN_DONE, /**< finish scanning AP */ + WIFI_EVENT_STA_START, /**< station start */ + WIFI_EVENT_STA_STOP, /**< station stop */ + WIFI_EVENT_STA_CONNECTED, /**< station connected to AP */ + WIFI_EVENT_STA_DISCONNECTED, /**< station disconnected from AP */ + WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by station changed */ + WIFI_EVENT_STA_BSS_RSSI_LOW, /**< AP's RSSI crossed configured threshold */ + WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< station wps succeeds in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_FAILED, /**< station wps fails in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< station wps timeout in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_PIN, /**< station wps pin code in enrollee mode */ + WIFI_EVENT_AP_START, /**< soft-AP start */ + WIFI_EVENT_AP_STOP, /**< soft-AP stop */ + WIFI_EVENT_AP_STACONNECTED, /**< a station connected to soft-AP */ + WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from soft-AP */ + WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ +} wifi_event_t; + +/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */ +typedef enum { + WPS_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */ + WPS_FAIL_REASON_RECV_M2D, /**< WPS receive M2D frame */ + WPS_FAIL_REASON_MAX +} wifi_event_sta_wps_fail_reason_t; + +/** Argument structure for WIFI_EVENT_SCAN_DONE event */ +typedef struct { + uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */ + uint8_t number; /**< number of scan results */ + uint8_t scan_id; /**< scan sequence number, used for block scan */ +} wifi_event_sta_scan_done_t; + +/** Argument structure for WIFI_EVENT_STA_CONNECTED event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of connected AP */ + uint8_t ssid_len; /**< SSID length of connected AP */ + uint8_t bssid[6]; /**< BSSID of connected AP*/ + uint8_t channel; /**< channel of connected AP*/ + wifi_auth_mode_t authmode;/**< authentication mode used by AP*/ +} wifi_event_sta_connected_t; + +/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */ +typedef struct { + wifi_auth_mode_t old_mode; /**< the old auth mode of AP */ + wifi_auth_mode_t new_mode; /**< the new auth mode of AP */ +} wifi_event_sta_authmode_change_t; + +#define MAX_SSID_LEN 32 +#define MAX_PASSPHRASE_LEN 64 +#define MAX_WPS_AP_CRED 3 + +/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */ +typedef struct { + uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ +} wifi_event_sta_wps_er_pin_t; + +/** Argument structure for WIFI_EVENT_AP_STACONNECTED event */ +typedef struct { + uint8_t mac[6]; /**< MAC address of the station connected to soft-AP */ + uint8_t aid; /**< the aid that soft-AP gives to the station connected to */ +} wifi_event_ap_staconnected_t; + +/** Argument structure for WIFI_EVENT_AP_STADISCONNECTED event */ +typedef struct { + uint8_t mac[6]; /**< MAC address of the station disconnects to soft-AP */ + uint8_t aid; /**< the aid that soft-AP gave to the station disconnects to */ +} wifi_event_ap_stadisconnected_t; + +/** Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event */ +typedef struct { + int rssi; /**< Received probe request signal strength */ + uint8_t mac[6]; /**< MAC address of the station which send probe request */ +} wifi_event_ap_probe_req_rx_t; + +/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of disconnected AP */ + uint8_t ssid_len; /**< SSID length of disconnected AP */ + uint8_t bssid[6]; /**< BSSID of disconnected AP */ + uint8_t reason; /**< reason of disconnection */ +} wifi_event_sta_disconnected_t; + +/** Argument structure for WIFI_EVENT_STA_BSS_RSSI_LOW event */ +typedef struct { + int32_t rssi; /**< RSSI value of bss */ +} wifi_event_bss_rssi_low_t; + #ifdef __cplusplus } #endif diff --git a/components/esp8266/include/ibus_data.h b/components/esp8266/include/ibus_data.h new file mode 100644 index 000000000..787f5ef47 --- /dev/null +++ b/components/esp8266/include/ibus_data.h @@ -0,0 +1,99 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +/** + * @brief ESP8266's IBus(instruction bus) only can read data of word type by 4 bytes align, + * so if users' code read a bytes or half word from IBus, an load/store exception will occure. + * + * The exception function will read the word by align and transform it to be the right + * data that users' code want to read. + * + * CPU read data from IRAM or flash by IBus. And "const" type value or string will locate at flash by default. + * So users' code read "const" type data whose type is byte or half word should lead to exception, + * and the exception operation is so slow. + * + * For example: + * + * static const char s_output[] = "123456789"; + * + * char get_byte(int index) + * { + * return s_output(index); + * } + * + * By above way, reading data may be not by 4 bytes align and word type. + * + * For this reason, we add the following function to read byte or half word without leading to exception. Firstly the function reads + * a word and then transform it to be the right data that users' code want to read. Users can modify above code to be following: + * + * static const char s_output[] = "123456789"; + * + * char get_byte(int index) + * { + * return ESP_IBUS_GET_U8_DATA(index, s_output); + * } + */ + +#ifdef USING_IBUS_FASTER_GET + +#include "esp_attr.h" + +#ifndef DISABLE_IBUS_INLINE_FUNC +#define IBUS_INLINE inline +#else +#define IBUS_INLINE +#endif + +typedef union _ibus_data { + uint32_t u32_data[1]; + uint16_t u16_data[2]; + uint8_t u8_data[4]; +} ibus_data_t; + +#define __ESP_IBUS_GET_DATA(_type) \ + static IBUS_INLINE _type __esp_ibus_get_## _type ## _data(size_t index, const void *pbuf) \ + { \ + ibus_data_t data; \ + const uint8_t num = index / (sizeof(uint32_t) / sizeof(_type)); \ + const uint8_t off = index % (sizeof(uint32_t) / sizeof(_type)); \ + const uint32_t *ptable = (const uint32_t *)pbuf; \ + \ + data.u32_data[0] = ptable[num]; \ + \ + if (sizeof(_type) == sizeof(uint8_t)) \ + return data.u8_data[off]; \ + else if (sizeof(_type) == sizeof(uint16_t)) \ + return data.u16_data[off]; \ + } + +__ESP_IBUS_GET_DATA(uint8_t) +__ESP_IBUS_GET_DATA(uint16_t) + +#define ESP_IBUS_ATTR WORD_ALIGNED_ATTR + +#define ESP_IBUS_GET_U8_DATA(_index, _pbuf) __esp_ibus_get_uint8_t_data(_index, _pbuf) +#define ESP_IBUS_GET_U16_DATA(_index, _pbuf) __esp_ibus_get_uint16_t_data(_index, _pbuf) +#else +#define ESP_IBUS_ATTR + +#define ESP_IBUS_GET_U8_DATA(_index, _pbuf) ((const uint8_t *)_pbuf)[_index] +#define ESP_IBUS_GET_U16_DATA(_index, _pbuf) ((const uint16_t *)_pbuf)[_index] +#endif + + diff --git a/components/esp8266/include/internal/esp_wifi_internal.h b/components/esp8266/include/internal/esp_wifi_internal.h deleted file mode 100644 index 97ea9ad0a..000000000 --- a/components/esp8266/include/internal/esp_wifi_internal.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESP_WIFI_INTERNAL_H -#define _ESP_WIFI_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - WIFI_RX_PBUF_IRAM, /** save rx buffer to iram and upload to tcpip*/ - WIFI_RX_PBUF_DRAM, /** save rx buffer to dram and upload to tcpip */ -} wifi_rx_pbuf_mem_type_t; - -/** - * @brief Set WIFI received TCP/IP data cache ram type - * - * @param type if use dram - */ -void esp_wifi_set_rx_pbuf_mem_type(wifi_rx_pbuf_mem_type_t type); - -/** - * @brief get WIFI received TCP/IP data cache ram type - * - * @return true if use dram or false - */ -wifi_rx_pbuf_mem_type_t esp_wifi_get_rx_pbuf_mem_type(void); - -int8_t esp_wifi_get_ap_rssi(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESP_WIFI_INTERNAL_H */ diff --git a/components/esp8266/include/net/if_packet.h b/components/esp8266/include/net/if_packet.h deleted file mode 100644 index 114cb5778..000000000 --- a/components/esp8266/include/net/if_packet.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _IF_PACKET_H -#define _IF_PACKET_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * socket II type address used by low-level module whose address is base on MAC address - * - * Note: Now it just support 802.3 and 802.11 protocol, so only "sll_addr" works here - */ -struct sockaddr_ll { - unsigned short sll_family; // it must be AF_PACKET - unsigned short sll_protocol; // physics level protocol - int sll_ifindex; // interface index not socket ID - unsigned short sll_hatype; // ARP hardware address type - unsigned char sll_pkttype; // packet type - unsigned char sll_halen; // hardware address length - unsigned char sll_addr[8]; // address data -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _IF_PACKET_H */ diff --git a/components/esp8266/include/net/if_socket.h b/components/esp8266/include/net/if_socket.h deleted file mode 100644 index 389fef448..000000000 --- a/components/esp8266/include/net/if_socket.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _IF_ETHER_H -#define _IF_ETHER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * undefine some global macro - */ -#undef ETH_P_ALL -#undef ETH_P_ARP -#undef ETH_P_IP - -#undef AF_PACKET - -#undef SOCK_RAW - -/* - * socket domain - */ -#define AF_PACKET 0 - -/* - * socket type - */ -#define SOCK_RAW 0 - -/* - * use 16(2^4) type for socket - */ -#define IF_SOCK_SHIFT 4 -#define IF_SOCK_TYPE(d) (d & 0xf) -#define IF_SOCK_DATA(t, s) ((1 << (s + IF_SOCK_SHIFT)) + t) - -enum if_sock_type { - IF_SOCK_ETH = 0, - IF_SOCK_WIFI, - - IF_SOCK_MAX, -}; - -#define IF_ETH_DATA(s) IF_SOCK_DATA(IF_SOCK_ETH, s) -#define IF_WIFI_DATA(s) IF_SOCK_DATA(IF_SOCK_WIFI, s) - -/* - * socket protocol - */ -#define ETH_P_IP IF_ETH_DATA(0) -#define ETH_P_ARP IF_ETH_DATA(1) -#define ETH_P_ALL ETH_P_IP | ETH_P_ARP - -#define WIFI_P_MNG IF_WIFI_DATA(0) -#define WIFI_P_CTL IF_WIFI_DATA(1) -#define WIFI_P_DAT IF_WIFI_DATA(2) -#define WIFI_P_ALL WIFI_P_MNG | WIFI_P_CTL | WIFI_P_DAT - -#ifdef __cplusplus -} -#endif - -#endif /* _IF_ETHER_H */ diff --git a/components/esp8266/include/net/sockio.h b/components/esp8266/include/net/sockio.h deleted file mode 100644 index 8132a8b26..000000000 --- a/components/esp8266/include/net/sockio.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _SOCKIO_H -#define _SOCKIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* espressif specific socket ioctls */ -#define SIOESPSTART 0x5500 /* start of espressif specific code */ - -/* routing table calls. */ -#define SIOCADDRT 0x890B /* add routing table entry */ -#define SIOCDELRT 0x890C /* delete routing table entry */ -#define SIOCRTMSG 0x890D /* call to routing system */ - -/* socket configuration controls. */ -#define SIOCGIFADDR 0x8915 /* get PA address */ -#define SIOCSIFADDR 0x8916 /* set PA address */ -#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ -#define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ -#define SIOCGIFNETMASK 0x891b /* get network PA mask */ -#define SIOCSIFNETMASK 0x891c /* set network PA mask */ -#define SIOCSIFHWADDR 0x8924 /* set hardware address */ -#define SIOCGIFHWADDR 0x8927 /* Get hardware address */ -#define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ -#define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SOCKIO_H */ diff --git a/components/esp8266/include/rom/crc.h b/components/esp8266/include/rom/crc.h new file mode 100644 index 000000000..9f07da3bb --- /dev/null +++ b/components/esp8266/include/rom/crc.h @@ -0,0 +1,4 @@ + +#pragma once + +#include "esp_crc.h" diff --git a/components/esp8266/include/rom/ets_sys.h b/components/esp8266/include/rom/ets_sys.h index b5cbf0a5a..136a2167e 100644 --- a/components/esp8266/include/rom/ets_sys.h +++ b/components/esp8266/include/rom/ets_sys.h @@ -35,6 +35,7 @@ extern "C" { #endif /* interrupt related */ +#define ETS_SLC_INUM 1 #define ETS_SPI_INUM 2 #define ETS_GPIO_INUM 4 #define ETS_UART_INUM 5 @@ -42,52 +43,33 @@ extern "C" { #define ETS_SOFT_INUM 7 #define ETS_WDT_INUM 8 #define ETS_FRC_TIMER1_INUM 9 +#define ETS_INT_MAX 14 -extern char NMIIrqIsOn; -extern uint32_t WDEV_INTEREST_EVENT; - -#define INT_ENA_WDEV 0x3ff20c18 -#define WDEV_TSF0_REACH_INT (BIT(27)) - -#define ETS_NMI_LOCK() \ - do { \ - char m = 10; \ - do { \ - REG_WRITE(INT_ENA_WDEV, 0); \ - m = 10; \ - for (; m > 0; m--) {} \ - REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT); \ - } while(0); \ - } while (0) - -#define ETS_NMI_UNLOCK() \ - do { \ - REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT); \ - } while (0) - -#define ETS_INTR_LOCK() do { \ - if (NMIIrqIsOn == 0) { \ - vPortEnterCritical(); \ - char m = 10; \ - do { \ - REG_WRITE(INT_ENA_WDEV, 0); \ - m = 10; \ - for (; m > 0; m--) {} \ - REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT); \ - } while(0); \ - } \ - } while(0) - -#define ETS_INTR_UNLOCK() do { \ - if (NMIIrqIsOn == 0) { \ - REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT); \ - vPortExitCritical(); \ - } \ - } while(0) +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + +void vPortETSIntrLock(void); + +void vPortETSIntrUnlock(void); #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +typedef uint32_t ETSSignal; +typedef uint32_t ETSParam; + +typedef struct ETSEventTag ETSEvent; /**< Event transmit/receive in ets*/ + +struct ETSEventTag { + ETSSignal sig; /**< Event signal, in same task, different Event with different signal*/ + ETSParam par; /**< Event parameter, sometimes without usage, then will be set as 0*/ +}; + /** * @brief Delay function, maximum value: 65535 us. * @@ -107,6 +89,18 @@ void os_delay_us(uint16_t us); */ void ets_delay_us(uint32_t us); +/** + * @brief Printf the strings to uart or other devices, similar with printf, simple than printf. + * Can not print float point data format, or longlong data format. + * + * @param const char *fmt : See printf. + * + * @param ... : See printf. + * + * @return int : the length printed to the output device. + */ +int ets_printf(const char *fmt, ...); + /** * @brief Register the print output function. * @@ -190,6 +184,16 @@ void os_timer_arm(os_timer_t *ptimer, uint32_t msec, bool repeat_flag); */ void os_timer_disarm(os_timer_t *ptimer); +/* redefine esp-idf name to esp8266 */ +#define ets_delay_us os_delay_us +#define ETSTimer os_timer_t +#define ETSTimerFunc os_timer_func_t +#define ets_timer_disarm os_timer_disarm +#define ets_timer_setfn os_timer_setfn +#define ets_timer_arm os_timer_arm + +void ets_timer_done(os_timer_t *ptimer); + /** * @} */ diff --git a/components/esp8266/include/rom/gpio.h b/components/esp8266/include/rom/gpio.h new file mode 100644 index 000000000..2ea50ca9d --- /dev/null +++ b/components/esp8266/include/rom/gpio.h @@ -0,0 +1,102 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_GPIO_H_ +#define _ROM_GPIO_H_ + +#include + +#include "esp8266/pin_mux_register.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup gpio_apis, uart configuration and communication related apis + * @brief gpio apis + */ + +/** @addtogroup gpio_apis + * @{ + */ + +#define GPIO_INPUT_GET(gpio_no) ((gpio_input_get() >> (gpio_no)) & BIT0) + +/** + * @brief Change GPIO(0-15) pin output by setting, clearing, or disabling pins, GPIO0<->BIT(0). + * There is no particular ordering guaranteed; so if the order of writes is significant, + * calling code should divide a single call into multiple calls. + * + * @param uint32_t set_mask : the gpios that need high level. + * + * @param uint32_t clear_mask : the gpios that need low level. + * + * @param uint32_t enable_mask : the gpios that need be changed. + * + * @param uint32_t disable_mask : the gpios that need diable output. + * + * @return None + */ +void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask); + +/** + * @brief Sample the value of GPIO input pins(0-31) and returns a bitmask. + * + * @param None + * + * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO0. + */ +uint32_t gpio_input_get(void); + +/** + * @brief Select pad as a gpio function from IOMUX. + * + * @param uint32_t gpio_num : gpio number, 0~15 + * + * @return None + */ +static inline void gpio_pad_select_gpio(uint32_t gpio_num) +{ + uint32_t gpio_mux_reg = PERIPHS_GPIO_MUX_REG(gpio_num); + + if (gpio_num == 0 || gpio_num == 2 || gpio_num == 4 || gpio_num == 5) { + PIN_FUNC_SELECT(gpio_mux_reg, 0); + } else { + PIN_FUNC_SELECT(gpio_mux_reg, 3); + } +} + +/** + * @brief Pull up the pad from gpio number. + * + * @param uint32_t gpio_num : gpio number, 0~15 + * + * @return None + */ +static inline void gpio_pad_pullup(uint32_t gpio_num) +{ + uint32_t gpio_mux_reg = PERIPHS_GPIO_MUX_REG(gpio_num); + + PIN_PULLUP_EN(gpio_mux_reg); +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_GPIO_H_ */ diff --git a/components/esp8266/include/rom/md5_hash.h b/components/esp8266/include/rom/md5_hash.h new file mode 100644 index 000000000..9111a0e32 --- /dev/null +++ b/components/esp8266/include/rom/md5_hash.h @@ -0,0 +1,42 @@ +/* + * MD5 internal definitions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef _ROM_MD5_HASH_H_ +#define _ROM_MD5_HASH_H_ + +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_ESP_MD5 +#include "esp_md5.h" +#else +struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + uint8_t in[64]; +}; +#endif +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_MD5_HASH_H_ */ diff --git a/components/newlib/newlib/include/sys/queue.h b/components/esp8266/include/rom/queue.h similarity index 91% rename from components/newlib/newlib/include/sys/queue.h rename to components/esp8266/include/rom/queue.h index 4bc7dac0e..29ee67060 100644 --- a/components/newlib/newlib/include/sys/queue.h +++ b/components/esp8266/include/rom/queue.h @@ -31,10 +31,14 @@ */ #ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ #include +#ifdef __cplusplus +extern "C" { +#endif + /* * This file defines four types of data structures: singly-linked lists, * singly-linked tail queues, lists and tail queues. @@ -65,7 +69,7 @@ * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list - * may be traversed in either direction. + * may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly @@ -85,7 +89,7 @@ * _EMPTY + + + + * _FIRST + + + + * _NEXT + + + + - * _PREV - + - + + * _PREV - - - + * _LAST - - + + * _FOREACH + + + + * _FOREACH_SAFE + + + + @@ -99,20 +103,18 @@ * _REMOVE_AFTER + - + - * _REMOVE_HEAD + - + - * _REMOVE + + + + - * _SWAP + + + + * */ #ifdef QUEUE_MACRO_DEBUG /* Store the last 2 places the queue element or head was altered */ struct qm_trace { - unsigned long lastline; - unsigned long prevline; - const char *lastfile; - const char *prevfile; + char * lastfile; + int lastline; + char * prevfile; + int prevline; }; #define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } , #define TRASHIT(x) do {(x) = (void *)-1;} while (0) #define QMD_SAVELINK(name, link) void **name = (void *)&(link) @@ -135,7 +137,6 @@ struct qm_trace { #define QMD_TRACE_HEAD(head) #define QMD_SAVELINK(name, link) #define TRACEBUF -#define TRACEBUF_INITIALIZER #define TRASHIT(x) #endif /* QUEUE_MACRO_DEBUG */ @@ -216,12 +217,6 @@ struct { \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ } while (0) -#define SLIST_SWAP(head1, head2, type) do { \ - struct type *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) - /* * Singly-linked Tail queue declarations. */ @@ -289,8 +284,10 @@ struct { \ } while (0) #define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? NULL : \ - __containerof((head)->stqh_last, struct type, field.stqe_next)) + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) @@ -308,21 +305,16 @@ struct { \ TRASHIT(*oldnext); \ } while (0) -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - #define STAILQ_REMOVE_HEAD(head, field) do { \ if ((STAILQ_FIRST((head)) = \ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) -#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ - if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) #define STAILQ_SWAP(head1, head2, type) do { \ @@ -338,6 +330,13 @@ struct { \ (head2)->stqh_last = &STAILQ_FIRST(head2); \ } while (0) +#define STAILQ_INSERT_CHAIN_HEAD(head, elm_chead, elm_ctail, field) do { \ + if ((STAILQ_NEXT(elm_ctail, field) = STAILQ_FIRST(head)) == NULL ) { \ + (head)->stqh_last = &STAILQ_NEXT(elm_ctail, field); \ + } \ + STAILQ_FIRST(head) = (elm_chead); \ +} while (0) + /* * List declarations. @@ -430,10 +429,6 @@ struct { \ #define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_PREV(elm, head, type, field) \ - ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ - __containerof((elm)->field.le_prev, struct type, field.le_next)) - #define LIST_REMOVE(elm, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.le_next); \ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ @@ -468,7 +463,7 @@ struct name { \ } #define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + { NULL, &(head).tqh_first } #define TAILQ_ENTRY(type) \ struct { \ @@ -643,49 +638,8 @@ struct { \ (head2)->tqh_last = &(head2)->tqh_first; \ } while (0) -#ifdef _KERNEL - -/* - * XXX insque() and remque() are an old way of handling certain queues. - * They bogusly assumes that all queue heads look alike. - */ - -struct quehead { - struct quehead *qh_link; - struct quehead *qh_rlink; -}; - -#ifdef __GNUC__ - -static __inline void -insque(void *a, void *b) -{ - struct quehead *element = (struct quehead *)a, - *head = (struct quehead *)b; - - element->qh_link = head->qh_link; - element->qh_rlink = head; - head->qh_link = element; - element->qh_link->qh_rlink = element; -} - -static __inline void -remque(void *a) -{ - struct quehead *element = (struct quehead *)a; - - element->qh_link->qh_rlink = element->qh_rlink; - element->qh_rlink->qh_link = element->qh_link; - element->qh_rlink = 0; +#ifdef __cplusplus } - -#else /* !__GNUC__ */ - -void insque(void *a, void *b); -void remque(void *a); - -#endif /* __GNUC__ */ - -#endif /* _KERNEL */ +#endif #endif /* !_SYS_QUEUE_H_ */ diff --git a/components/esp8266/include/rom/spi_flash.h b/components/esp8266/include/rom/spi_flash.h new file mode 100644 index 000000000..c3d0d1001 --- /dev/null +++ b/components/esp8266/include/rom/spi_flash.h @@ -0,0 +1,25 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_SPI_FLASH_H_ +#define _ROM_SPI_FLASH_H_ + +#include +#include + +#include "esp_attr.h" + +#include "esp8266/rom_functions.h" + +#endif /* _ROM_SPI_FLASH_H_ */ diff --git a/components/esp8266/include/rom/uart.h b/components/esp8266/include/rom/uart.h new file mode 100644 index 000000000..8a99f37b6 --- /dev/null +++ b/components/esp8266/include/rom/uart.h @@ -0,0 +1,117 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_UART_H_ +#define _ROM_UART_H_ + +#include "esp_types.h" +#include "esp_attr.h" +#include "ets_sys.h" + +#include "esp8266/uart_struct.h" +#include "esp8266/uart_register.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/rom_functions.h" + +#include "driver/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup uart_apis, uart configuration and communication related apis + * @brief uart apis + */ + +/** @addtogroup uart_apis + * @{ + */ + +/** + * @brief Wait until uart tx full empty and the last char send ok. + * + * @param uart_no : 0 for UART0, 1 for UART1, 2 for UART2 + * + * The function defined in ROM code has a bug, so we define the correct version + * here for compatibility. + */ +void uart_tx_wait_idle(uint8_t uart_no); + +/** + * @brief Output a char to printf channel, wait until fifo not full. + * + * @param None + * + * @return OK. + */ +STATUS uart_tx_one_char(uint8_t TxChar); + +/** + * @brief Get an input char from message channel. + * Please do not call this function in SDK. + * + * @param uint8_t *pRxChar : the pointer to store the char. + * + * @return OK for successful. + * FAIL for failed. + */ +STATUS uart_rx_one_char(uint8_t *pRxChar); + +/** + * @brief Get an input string line from message channel. + * Please do not call this function in SDK. + * + * @param uint8_t *pString : the pointer to store the string. + * + * @param uint8_t MaxStrlen : the max string length, incude '\0'. + * + * @return OK. + */ +static inline STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen) +{ + int rx_bytes = 0; + + while(1) { + uint8_t data; + + while (uart_rx_one_char(&data) != OK); + + if (data == '\n' || data == '\r') + data = '\0'; + + pString[rx_bytes++] = data; + if (data == '\0') + return OK; + if (rx_bytes >= MaxStrlen) + return FAIL; + } + + return OK; +} + +/** + * @brief Disable UART0 I/O swap and don't care about if TX FIFO is empty + */ +void uart_disable_swap_io(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_UART_H_ */ diff --git a/components/esp8266/include/smartconfig_ack.h b/components/esp8266/include/smartconfig_ack.h new file mode 100644 index 000000000..2e3d24320 --- /dev/null +++ b/components/esp8266/include/smartconfig_ack.h @@ -0,0 +1,44 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SMARTCONFIG_ACK_H +#define SMARTCONFIG_ACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Send smartconfig ACK to cellphone. + * + * @attention The API can only be used when receiving SC_EVENT_GOT_SSID_PSWD event. + * + * @param type: smartconfig type(ESPTouch or AirKiss); + * token: token from the cellphone; + * cellphone_ip: IP address of the cellphone; + * + * @retuen ESP_OK: succeed + * others: fail + */ +esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t* cellphone_ip); + +/** + * @brief Stop sending smartconfig ACK to cellphone. + */ +void sc_send_ack_stop(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/esp8266/include/soc/cpu.h b/components/esp8266/include/soc/cpu.h new file mode 100644 index 000000000..2249e06b3 --- /dev/null +++ b/components/esp8266/include/soc/cpu.h @@ -0,0 +1,40 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SOC_CPU_H +#define _SOC_CPU_H + +#include +#include +#include +#include "xtensa/corebits.h" +#include "xtensa/config/core.h" + +/* C macros for xtensa special register read/write/exchange */ + +#define RSR(reg, curval) asm volatile ("rsr %0, " #reg : "=r" (curval)); +#define WSR(reg, newval) asm volatile ("wsr %0, " #reg : : "r" (newval)); +#define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval)); + +/** @brief Read current stack pointer address + * + */ +static inline void *get_sp() +{ + void *sp; + asm volatile ("mov %0, sp;" : "=r" (sp)); + return sp; +} + +#endif diff --git a/components/esp8266/include/util_assert.h b/components/esp8266/include/util_assert.h new file mode 100644 index 000000000..83578bb6a --- /dev/null +++ b/components/esp8266/include/util_assert.h @@ -0,0 +1,24 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "sdkconfig.h" +#include "assert.h" + +#ifdef CONFIG_UTIL_ASSERT +#define util_assert(_e) assert(_e) +#else +#define util_assert(_e) +#endif diff --git a/components/esp8266/ld/esp8266.common.ld b/components/esp8266/ld/esp8266.common.ld deleted file mode 100644 index 514c6def6..000000000 --- a/components/esp8266/ld/esp8266.common.ld +++ /dev/null @@ -1,249 +0,0 @@ -/* This linker script generated from xt-genldscripts.tpp for LSP . */ -/* Linker Script for ld -N */ - -#include "sdkconfig.h" - -PHDRS -{ - dport0_0_phdr PT_LOAD; - dram0_0_phdr PT_LOAD; - dram0_0_bss_phdr PT_LOAD; - iram1_0_phdr PT_LOAD; - irom0_0_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(call_user_start) -EXTERN(_DebugExceptionVector) -EXTERN(_DoubleExceptionVector) -EXTERN(_KernelExceptionVector) -EXTERN(_NMIExceptionVector) -EXTERN(_UserExceptionVector) -PROVIDE(_memmap_vecbase_reset = 0x40000000); -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wb_base = 0x00000110; -_memmap_cacheattr_wt_base = 0x00000110; -_memmap_cacheattr_bp_base = 0x00000220; -_memmap_cacheattr_unused_mask = 0xFFFFF00F; -_memmap_cacheattr_wb_trapnull = 0x2222211F; -_memmap_cacheattr_wba_trapnull = 0x2222211F; -_memmap_cacheattr_wbna_trapnull = 0x2222211F; -_memmap_cacheattr_wt_trapnull = 0x2222211F; -_memmap_cacheattr_bp_trapnull = 0x2222222F; -_memmap_cacheattr_wb_strict = 0xFFFFF11F; -_memmap_cacheattr_wt_strict = 0xFFFFF11F; -_memmap_cacheattr_bp_strict = 0xFFFFF22F; -_memmap_cacheattr_wb_allvalid = 0x22222112; -_memmap_cacheattr_wt_allvalid = 0x22222112; -_memmap_cacheattr_bp_allvalid = 0x22222222; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); - -SECTIONS -{ - .dport0.rodata : ALIGN(4) - { - _dport0_rodata_start = ABSOLUTE(.); - *(.dport0.rodata) - *(.dport.rodata) - _dport0_rodata_end = ABSOLUTE(.); - } >dport0_0_seg :dport0_0_phdr - - .dport0.literal : ALIGN(4) - { - _dport0_literal_start = ABSOLUTE(.); - *(.dport0.literal) - *(.dport.literal) - _dport0_literal_end = ABSOLUTE(.); - } >dport0_0_seg :dport0_0_phdr - - .dport0.data : ALIGN(4) - { - _dport0_data_start = ABSOLUTE(.); - *(.dport0.data) - *(.dport.data) - _dport0_data_end = ABSOLUTE(.); - } >dport0_0_seg :dport0_0_phdr - - /* RTC memory holds user's data/rodata */ - .rtc.data : - { - _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) - _rtc_data_end = ABSOLUTE(.); - } > rtc_seg - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - LONG(_text_start) - . = ALIGN(16); - *(.DebugExceptionVector.text) - . = ALIGN(16); - *(.NMIExceptionVector.text) - . = ALIGN(16); - *(.KernelExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN(16); - *(.UserExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN(16); - *(.DoubleExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.init) - *(.iram1 .iram1.*) - *libspi_flash.a:spi_flash_raw.o(.literal .text .literal.* .text.*) - *(.literal .text .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.fini.literal) - *(.fini) - *(.gnu.version) - -#ifdef CONFIG_LWIP_GLOBAL_DATA_LINK_IRAM - *liblwip.a:(.bss .data .bss.* .data.* COMMON) -#endif - -#ifdef CONFIG_TCPIP_ADAPTER_GLOBAL_DATA_LINK_IRAM - *libtcpip_adapter.a:(.bss .data .bss.* .data.* COMMON) -#endif - -#ifdef CONFIG_ESP8266_CORE_GLOBAL_DATA_LINK_IRAM - *libcore.a:(.bss .data .bss.* .data.* COMMON) -#endif - -#ifdef CONFIG_FREERTOS_GLOBAL_DATA_LINK_IRAM - *libfreertos.a:tasks.o(.bss .data .bss.* .data.* COMMON) - *libfreertos.a:timers.o(.bss .data .bss.* .data.* COMMON) - *libfreertos.a:freertos_hooks.o(.bss .data .bss.* .data.* COMMON) -#endif - - _text_end = ABSOLUTE(.); - _etext = .; - } >iram1_0_seg :iram1_0_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.dram0) - *(.gnu.linkonce.d.*) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - _data_end = ABSOLUTE(.); - } >dram0_0_seg :dram0_0_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *libpp.a:(.rodata.* .rodata) - *liblog.a:(.rodata.* .rodata) - *(.gnu.linkonce.r.*) - *(.rodata1) - __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - *(.eh_frame) - . = (. + 3) & ~ 3; - /* C++ constructor and destructor tables, properly ordered: */ - __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - . = ALIGN(4); /* this table MUST be 4-byte aligned */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >dram0_0_seg :dram0_0_phdr - - .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >dram0_0_seg :dram0_0_phdr - - .bss ALIGN(8) (NOLOAD) : ALIGN(4) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - _heap_start = ABSOLUTE(.); -/* _stack_sentry = ALIGN(0x8); */ - } >dram0_0_seg :dram0_0_bss_phdr -/* __stack = 0x3ffc8000; */ - - .irom0.text : ALIGN(4) - { - _irom0_text_start = ABSOLUTE(.); - *(.rodata.* .rodata .irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) - *(.literal.* .text.*) - - . = ALIGN(16); - __start_ksymatabesp_socket = .; - *(ksymatabesp_socket) - __stop_ksymatabesp_socket = .; - - _irom0_text_end = ABSOLUTE(.); - } >irom0_0_seg :irom0_0_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >iram1_0_seg :iram1_0_phdr - -} diff --git a/components/esp8266/ld/esp8266.ld b/components/esp8266/ld/esp8266.ld index cd950b98a..6d31835a7 100644 --- a/components/esp8266/ld/esp8266.ld +++ b/components/esp8266/ld/esp8266.ld @@ -1,34 +1,44 @@ -/* user1.bin @ 0x1000, user2.bin @ 0x10000 */ - -/* Flash Map (1024KB + 1024KB), support 2MB/4MB SPI Flash */ -/* |..|........................|.....|.....|..|........................|.....|....| */ -/* ^ ^ ^ ^ ^ ^ ^ ^ */ -/* |_boot start(0x0000) | | |_pad start(0x100000) | | */ -/* |_user1 start(0x1000) |_user1 end |_user2 start(0x101000) |_user2 end */ -/* |_system param symmetric area(0xfb000) |_system param area(0x1fb000) */ - -/* NOTICE: */ -/* 1. You can change irom0 len, but MUST make sure user1 end not overlap system param symmetric area. */ -/* 2. Space between user1 end and pad start can be used as user param area. */ -/* 3. Space between user2 end and system param area can be used as user param area. */ -/* 4. Don't change any other seg. */ -/* 5. user1.bin and user2.bin are same in this mode, so upgrade only need one of them. */ +/* ESP8266 Linker Script Memory Layout + This file describes the memory layout (memory blocks). + + esp8266.project.ld contains output sections to link compiler output + into these memory blocks. + + *** + + This linker script is passed through the C preprocessor to include + configuration options. + + Please use preprocessor features sparingly! Restrict + to simple macros with numeric values, and/or #if/#endif blocks. +*/ #include "sdkconfig.h" + MEMORY { - dport0_0_seg : org = 0x3FF00000, len = 0x10 + /* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + of the various regions. */ + + /* IRAM for cpu. The length is due to the cache mode which is able to be set half or full mode. */ + iram0_0_seg (RX) : org = 0x40100000, len = CONFIG_SOC_IRAM_SIZE + + /* Even though the segment name is iram, it is actually mapped to flash and mapped constant data */ + iram0_2_seg (RX) : org = 0x40200010 + (APP_OFFSET & (0x100000 - 1)), + len = APP_SIZE - 0x10 + + /* + (0x18 offset above is a convenience for the app binary image generation. The .bin file which is flashed + to the chip has a 0x10 byte file header. Setting this offset makes it simple to meet the flash cache.) + */ - /* All .data/.bss/heap are in this segment. */ - dram0_0_seg : org = 0x3FFE8000, len = 0x18000 - /* Functions which are critical should be put in this segment. */ - iram1_0_seg : org = 0x40100000, len = CONFIG_SOC_IRAM_SIZE + /* Length of this section is 96KB */ + dram0_0_seg (RW) : org = 0x3FFE8000, len = 0x18000 - /* It is actually mapped to flash. */ - irom0_0_seg : org = 0x40200010 + APP_OFFSET, len = APP_SIZE - 0x10 - APP_OFFSET + /* (See iram0_2_seg for meaning of 0x10 offset in the above.) */ - /* RTC memory, persists over deep sleep. */ - rtc_seg : org = 0x60001200, len = 0x200 + /* RTC memory. Persists over deep sleep */ + rtc_data_seg(RW) : org = 0x60001200, len = 0x200 } diff --git a/components/esp8266/ld/esp8266.peripherals.ld b/components/esp8266/ld/esp8266.peripherals.ld index 57329602e..09426d8f3 100644 --- a/components/esp8266/ld/esp8266.peripherals.ld +++ b/components/esp8266/ld/esp8266.peripherals.ld @@ -1,4 +1,14 @@ PROVIDE ( GPIO = 0x60000300); PROVIDE ( uart0 = 0x60000000 ); -PROVIDE ( uart1 = 0x60000f00 ); \ No newline at end of file +PROVIDE ( uart1 = 0x60000f00 ); + +PROVIDE ( frc1 = 0x60000600 ); + +PROVIDE ( rtc_sys_info = 0x60001100 ); + +PROVIDE ( SLC0 = 0x60000B00 ); +PROVIDE ( I2S0 = 0x60000e00 ); + +PROVIDE ( SPI1 = 0x60000100 ); +PROVIDE ( SPI0 = 0x60000200 ); diff --git a/components/esp8266/ld/esp8266.project.ld.in b/components/esp8266/ld/esp8266.project.ld.in new file mode 100644 index 000000000..54d7bb48b --- /dev/null +++ b/components/esp8266/ld/esp8266.project.ld.in @@ -0,0 +1,257 @@ +/* Default entry point: */ +ENTRY(call_start_cpu); + +SECTIONS +{ + /* RTC data section holds RTC wake data/rodata + marked with RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + mapping[rtc_data] + + _rtc_data_end = ABSOLUTE(.); + } > rtc_data_seg + + /* RTC bss */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + + mapping[rtc_bss] + + _rtc_bss_end = ABSOLUTE(.); + } > rtc_data_seg + + /* This section holds data that should not be initialized at power up + and will be retained during deep sleep. + User data marked with RTC_NOINIT_ATTR will be placed + into this section. See the file "esp_attr.h" for more information. + */ + .rtc_noinit (NOLOAD): + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } > rtc_data_seg + + ASSERT(((_rtc_noinit_end - ORIGIN(rtc_data_seg)) <= LENGTH(rtc_data_seg)), + "RTC segment data does not fit.") + + /* Send .iram0 code to iram */ + .iram0.vectors : + { + _iram_start = ABSOLUTE(.); + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + KEEP(*(.SystemInfoVector.text)); + . = 0x10; + KEEP(*(.DebugExceptionVector.text)); + . = 0x20; + KEEP(*(.NMIExceptionVector.text)); + . = 0x30; + KEEP(*(.KernelExceptionVector.text)); + . = 0x50; + KEEP(*(.UserExceptionVector.text)); + . = 0x70; + KEEP(*(.DoubleExceptionVector.text)); + + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + mapping[iram0_text] + + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.bss : + { + . = ALIGN (4); + /* Code marked as runnning out of IRAM */ + _iram_bss_start = ABSOLUTE(.); + + mapping[iram0_bss] + + . = ALIGN (4); + _iram_bss_end = ABSOLUTE(.); + _iram_end = ABSOLUTE(.); + } > iram0_0_seg + + ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") + + .dram0.data : + { + _data_start = ABSOLUTE(.); + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + *(.dram0 .dram0.*) + + mapping[dram0_data] + + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } > dram0_0_seg + + /*This section holds data that should not be initialized at power up. + The section located in Internal SRAM memory region. The macro _NOINIT + can be used as attribute to place data into this section. + See the esp_attr.h file for more information. + */ + .noinit (NOLOAD): + { + . = ALIGN(4); + _noinit_start = ABSOLUTE(.); + *(.noinit .noinit.*) + . = ALIGN(4) ; + _noinit_end = ABSOLUTE(.); + } > dram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + + mapping[dram0_bss] + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.share.mem) + *(.gnu.linkonce.b.*) + + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } > dram0_0_seg + + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + + mapping[flash_text] + + /* For ESP8266 library function */ + *(.irom0.literal .irom0.text) + *(.irom.literal .irom.text .irom.text.literal) + *(.text2 .text2.* .literal2 .literal2.*) + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + resolved by addr2line in preference to the first symbol in + the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } >iram0_2_seg + + .flash.rodata ALIGN(4) : + { + _rodata_start = ABSOLUTE(.); + + /** + Insert 8 bytes data to make realy rodata section's link address offset to be 0x8, + esptool will remove these data and add real segment header + */ + . = 0x8; + + *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ + *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + + *(.rodata2 .rodata2.*) /* For ESP8266 library function */ + + mapping[flash_rodata] + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + /* C++ constructor and destructor tables + + Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt + */ + __init_array_start = ABSOLUTE(.); + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors .ctors.*)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + /* Addresses of memory regions reserved via + SOC_RESERVE_MEMORY_REGION() */ + soc_reserved_memory_region_start = ABSOLUTE(.); + KEEP (*(.reserved_memory_address)) + soc_reserved_memory_region_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } >iram0_2_seg +} diff --git a/components/esp8266/ld/esp8266.rom.ld b/components/esp8266/ld/esp8266.rom.ld index 49f6dd718..c2262e881 100644 --- a/components/esp8266/ld/esp8266.rom.ld +++ b/components/esp8266/ld/esp8266.rom.ld @@ -15,46 +15,54 @@ PROVIDE ( lldesc_build_chain = 0x40004f40 ); PROVIDE ( lldesc_num2link = 0x40005050 ); PROVIDE ( lldesc_set_owner = 0x4000507c ); -PROVIDE ( __adddf3 = 0x4000c538 ); -PROVIDE ( __addsf3 = 0x4000c180 ); -PROVIDE ( __divdf3 = 0x4000cb94 ); -PROVIDE ( __divdi3 = 0x4000ce60 ); -PROVIDE ( __divsi3 = 0x4000dc88 ); -PROVIDE ( __extendsfdf2 = 0x4000cdfc ); -PROVIDE ( __fixdfsi = 0x4000ccb8 ); -PROVIDE ( __fixunsdfsi = 0x4000cd00 ); -PROVIDE ( __fixunssfsi = 0x4000c4c4 ); -PROVIDE ( __floatsidf = 0x4000e2f0 ); -PROVIDE ( __floatsisf = 0x4000e2ac ); -PROVIDE ( __floatunsidf = 0x4000e2e8 ); -PROVIDE ( __floatunsisf = 0x4000e2a4 ); -PROVIDE ( __muldf3 = 0x4000c8f0 ); -PROVIDE ( __muldi3 = 0x40000650 ); -PROVIDE ( __mulsf3 = 0x4000c3dc ); -PROVIDE ( __subdf3 = 0x4000c688 ); -PROVIDE ( __subsf3 = 0x4000c268 ); -PROVIDE ( __truncdfsf2 = 0x4000cd5c ); -PROVIDE ( __udivdi3 = 0x4000d310 ); -PROVIDE ( __udivsi3 = 0x4000e21c ); -PROVIDE ( __umoddi3 = 0x4000d770 ); -PROVIDE ( __umodsi3 = 0x4000e268 ); -PROVIDE ( __umulsidi3 = 0x4000dcf0 ); - -PROVIDE ( bzero = 0x4000de84 ); -PROVIDE ( memcmp = 0x4000dea8 ); -PROVIDE ( memcpy = 0x4000df48 ); -PROVIDE ( memmove = 0x4000e04c ); -PROVIDE ( memset = 0x4000e190 ); - -PROVIDE ( strcmp = 0x4000bdc8 ); -PROVIDE ( strcpy = 0x4000bec8 ); -PROVIDE ( strlen = 0x4000bf4c ); -PROVIDE ( strncmp = 0x4000bfa8 ); -PROVIDE ( strncpy = 0x4000c0a0 ); -PROVIDE ( strstr = 0x4000e1e0 ); +__adddf3 = 0x4000c538; +__addsf3 = 0x4000c180; +__divdf3 = 0x4000cb94; +__divdi3 = 0x4000ce60; +__divsi3 = 0x4000dc88; +__extendsfdf2 = 0x4000cdfc; +__fixdfsi = 0x4000ccb8; +__fixunsdfsi = 0x4000cd00; +__fixunssfsi = 0x4000c4c4; +__floatsidf = 0x4000e2f0; +__floatsisf = 0x4000e2ac; +__floatunsidf = 0x4000e2e8; +__floatunsisf = 0x4000e2a4; +__muldf3 = 0x4000c8f0; +__muldi3 = 0x40000650; +__mulsf3 = 0x4000c3dc; +__subdf3 = 0x4000c688; +__subsf3 = 0x4000c268; +__truncdfsf2 = 0x4000cd5c; +__udivdi3 = 0x4000d310; +__udivsi3 = 0x4000e21c; +__umoddi3 = 0x4000d770; +__umodsi3 = 0x4000e268; +__umulsidi3 = 0x4000dcf0; + +bzero = 0x4000de84; +memcmp = 0x4000dea8; +memcpy = 0x4000df48; +memmove = 0x4000e04c; +memset = 0x4000e190; + +strcmp = 0x4000bdc8; +strcpy = 0x4000bec8; +strlen = 0x4000bf4c; +strncmp = 0x4000bfa8; +strncpy = 0x4000c0a0; +strstr = 0x4000e1e0; PROVIDE ( gpio_input_get = 0x40004cf0 ); PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 ); PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 ); -PROVIDE ( ets_io_vprintf = 0x40001f00 ); \ No newline at end of file +PROVIDE ( ets_io_vprintf = 0x40001f00 ); +PROVIDE ( uart_rx_one_char = 0x40003b8c ); + +PROVIDE ( rom_i2c_readReg = 0x40007268 ); +PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c ); +PROVIDE ( rom_i2c_writeReg = 0x400072d8 ); +PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c ); + +PROVIDE ( rom_software_reboot = 0x40000080 ); diff --git a/components/esp8266/ld/esp8266_bss_fragments.lf b/components/esp8266/ld/esp8266_bss_fragments.lf new file mode 100644 index 000000000..a69ce6941 --- /dev/null +++ b/components/esp8266/ld/esp8266_bss_fragments.lf @@ -0,0 +1,5 @@ + +[scheme:iram_bss] +entries: + bss -> iram0_bss + common -> iram0_bss diff --git a/components/esp8266/ld/esp8266_fragments.lf b/components/esp8266/ld/esp8266_fragments.lf new file mode 100644 index 000000000..af21ea2ac --- /dev/null +++ b/components/esp8266/ld/esp8266_fragments.lf @@ -0,0 +1,99 @@ +[sections:text_0] +entries: + .text + .literal + +[sections:text] +entries: + .text+ + .literal+ + +[sections:data] +entries: + .data+ + +[sections:bss] +entries: + .bss+ + +[sections:common] +entries: + COMMON + +[sections:rodata] +entries: + .rodata+ + +[sections:rtc_text] +entries: + .rtc.text+ + .rtc.literal + +[sections:rtc_data] +entries: + .rtc.data+ + +[sections:rtc_rodata] +entries: + .rtc.rodata+ + +[sections:rtc_bss] +entries: + .rtc.bss + +[sections:iram] +entries: + .iram1+ + +[sections:dram] +entries: + .dram1+ + +[sections:wifi_iram] +entries: + .wifi0iram+ + +[scheme:default] +entries: + text_0 -> iram0_text + text -> flash_text + rodata -> flash_rodata + data -> dram0_data + bss -> dram0_bss + common -> dram0_bss + iram -> iram0_text + dram -> dram0_data + rtc_text -> rtc_text + rtc_data -> rtc_data + rtc_rodata -> rtc_data + rtc_bss -> rtc_bss + wifi_iram -> flash_text + +[scheme:rtc] +entries: + text -> rtc_text + data -> rtc_data + rodata -> rtc_data + bss -> rtc_bss + common -> rtc_bss + +[scheme:noflash] +entries: + text -> iram0_text + rodata -> dram0_data + +[scheme:noflash_data] +entries: + rodata -> dram0_data + +[scheme:noflash_text] +entries: + text -> iram0_text + +[scheme:wifi_iram] +entries: + wifi_iram -> iram0_text + +[scheme:inflash_text] +entries: + text -> flash_text diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index f6bdb5e9a..2873e0c84 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,10 +1,8 @@ gwen: - core: 4e2372f - net80211: 4e2372f - pp: 0726f0a - smartconfig:4e2372f - wpa: 4e2372f - espnow: 4e2372f - wps: 4e2372f + core: 231e0e2 + net80211: 9ad2f23 + pp: 25e5ef2 + espnow: 231e0e2 - phy: 1055_8 \ No newline at end of file + smartconfig: 3.0.0/af78f443 + phy: 1166.0 diff --git a/components/esp8266/lib/fix_printf.sh b/components/esp8266/lib/fix_printf.sh new file mode 100755 index 000000000..63f6bc944 --- /dev/null +++ b/components/esp8266/lib/fix_printf.sh @@ -0,0 +1,2 @@ +#!/bin/bash +xtensa-lx106-elf-objcopy --redefine-sym ets_printf=phy_printf libphy.a diff --git a/components/esp8266/lib/libclk.a b/components/esp8266/lib/libclk.a new file mode 100755 index 000000000..fb911f79f Binary files /dev/null and b/components/esp8266/lib/libclk.a differ diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a old mode 100644 new mode 100755 index 716506330..8beb25fae Binary files a/components/esp8266/lib/libcore.a and b/components/esp8266/lib/libcore.a differ diff --git a/components/esp8266/lib/libcore_dbg.a b/components/esp8266/lib/libcore_dbg.a new file mode 100755 index 000000000..45b00afe0 Binary files /dev/null and b/components/esp8266/lib/libcore_dbg.a differ diff --git a/components/esp8266/lib/libespnow.a b/components/esp8266/lib/libespnow.a old mode 100644 new mode 100755 index 22186bd58..e1af2020a Binary files a/components/esp8266/lib/libespnow.a and b/components/esp8266/lib/libespnow.a differ diff --git a/components/esp8266/lib/libespnow_dbg.a b/components/esp8266/lib/libespnow_dbg.a new file mode 100755 index 000000000..2c7346c7b Binary files /dev/null and b/components/esp8266/lib/libespnow_dbg.a differ diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a index 87dd4850a..a6da69b90 100644 Binary files a/components/esp8266/lib/libnet80211.a and b/components/esp8266/lib/libnet80211.a differ diff --git a/components/esp8266/lib/libnet80211_dbg.a b/components/esp8266/lib/libnet80211_dbg.a new file mode 100644 index 000000000..d74f6f5c7 Binary files /dev/null and b/components/esp8266/lib/libnet80211_dbg.a differ diff --git a/components/esp8266/lib/libphy.a b/components/esp8266/lib/libphy.a index 12ce50f71..6f3b75e93 100644 Binary files a/components/esp8266/lib/libphy.a and b/components/esp8266/lib/libphy.a differ diff --git a/components/esp8266/lib/libpp.a b/components/esp8266/lib/libpp.a index 5e51ef3c2..de9333380 100644 Binary files a/components/esp8266/lib/libpp.a and b/components/esp8266/lib/libpp.a differ diff --git a/components/esp8266/lib/libpp_dbg.a b/components/esp8266/lib/libpp_dbg.a new file mode 100644 index 000000000..89786fcc4 Binary files /dev/null and b/components/esp8266/lib/libpp_dbg.a differ diff --git a/components/esp8266/lib/librtc.a b/components/esp8266/lib/librtc.a new file mode 100644 index 000000000..8a809ee92 Binary files /dev/null and b/components/esp8266/lib/librtc.a differ diff --git a/components/esp8266/lib/libsmartconfig.a b/components/esp8266/lib/libsmartconfig.a old mode 100644 new mode 100755 index 1fdda70f1..cdadb3a39 Binary files a/components/esp8266/lib/libsmartconfig.a and b/components/esp8266/lib/libsmartconfig.a differ diff --git a/components/esp8266/lib/libssc.a b/components/esp8266/lib/libssc.a index 571458311..b9918d997 100644 Binary files a/components/esp8266/lib/libssc.a and b/components/esp8266/lib/libssc.a differ diff --git a/components/esp8266/lib/libwpa.a b/components/esp8266/lib/libwpa.a deleted file mode 100644 index c337f36c7..000000000 Binary files a/components/esp8266/lib/libwpa.a and /dev/null differ diff --git a/components/esp8266/lib/libwps.a b/components/esp8266/lib/libwps.a deleted file mode 100644 index a35f96086..000000000 Binary files a/components/esp8266/lib/libwps.a and /dev/null differ diff --git a/components/esp8266/linker.lf b/components/esp8266/linker.lf new file mode 100644 index 000000000..5b5ff5742 --- /dev/null +++ b/components/esp8266/linker.lf @@ -0,0 +1,29 @@ +[mapping:pp] +archive: libpp.a +entries: + if ESP8266_WIFI_DEBUG_LOG_ENABLE = n: + * (noflash_text) + +[mapping:pp_dbg] +archive: libpp_dbg.a +entries: + if ESP8266_WIFI_DEBUG_LOG_ENABLE = y: + * (noflash_text) + +[mapping:phy] +archive: libphy.a +entries: + * (noflash_text) + +[mapping:core] +archive: libcore.a +entries: + if ESP8266_CORE_GLOBAL_DATA_LINK_IRAM = y: + * (iram_bss) + +[mapping:gcc] +archive: libgcc.a +entries: + unwind-dw2 (inflash_text) + unwind-dw2-fde (inflash_text) + diff --git a/components/esp8266/project_include.cmake b/components/esp8266/project_include.cmake deleted file mode 100644 index d760d9597..000000000 --- a/components/esp8266/project_include.cmake +++ /dev/null @@ -1,162 +0,0 @@ -set(BOOTLOADER_FIRMWARE_DIR ${CMAKE_CURRENT_LIST_DIR}/firmware) - -#configurate downloading parameters -set(ESPTOOLPY_FLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) -set(ESPTOOLPY_FLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) -set(ESPTOOLPY_FLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) - -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "512KB") -set(BLANK_BIN_OFFSET1 0x7B000) -set(BLANK_BIN_OFFSET2 0x7E000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x7C000) -set(ESP8266_SIZEMAP 0) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "1MB") -set(BLANK_BIN_OFFSET1 0xFB000) -set(BLANK_BIN_OFFSET2 0xFE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0xFC000) -set(ESP8266_SIZEMAP 2) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "2MB") -set(BLANK_BIN_OFFSET1 0x1FB000) -set(BLANK_BIN_OFFSET2 0x1FE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x1FC000) -set(ESP8266_SIZEMAP 3) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "2MB-c1") -set(BLANK_BIN_OFFSET1 0x1FB000) -set(BLANK_BIN_OFFSET2 0x1FE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x1FC000) -set(ESP8266_SIZEMAP 5) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "4MB") -set(BLANK_BIN_OFFSET1 0x3FB000) -set(BLANK_BIN_OFFSET2 0x3FE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x3FC000) -set(ESP8266_SIZEMAP 4) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "4MB-c1") -set(BLANK_BIN_OFFSET1 0x3FB000) -set(BLANK_BIN_OFFSET2 0x3FE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x3FC000) -set(ESP8266_SIZEMAP 6) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "8MB") -set(BLANK_BIN_OFFSET1 0x7FB000) -set(BLANK_BIN_OFFSET2 0x7FE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0x7FC000) -set(ESP8266_SIZEMAP 8) -endif() -if(${ESPTOOLPY_FLASHSIZE} STREQUAL "16MB") -set(BLANK_BIN_OFFSET1 0xFFB000) -set(BLANK_BIN_OFFSET2 0xFFE000) -set(ESP_INIT_DATA_DEFAULT_BIN_OFFSET 0xFFC000) -set(ESP8266_SIZEMAP 9) -endif() - -set(BOOTLOADER_BIN_OFFSET 0) -set(APP_OFFSET 0x1000) - -set(ESP8266_BOOTMODE 2) # always be 2 - -if(${ESPTOOLPY_FLASHMODE} STREQUAL "qio") -set(ESP8266_FLASHMODE 0) -endif() -if(${ESPTOOLPY_FLASHMODE} STREQUAL "qout") -set(ESP8266_FLASHMODE 1) -endif() -if(${ESPTOOLPY_FLASHMODE} STREQUAL "dio") -set(ESP8266_FLASHMODE 2) -endif() -if(${ESPTOOLPY_FLASHMODE} STREQUAL "dout") -set(ESP8266_FLASHMODE 3) -endif() - -if(${ESPTOOLPY_FLASHFREQ} STREQUAL "20m") -set(ESP8266_FREQDIV 2) -endif() -if(${ESPTOOLPY_FLASHFREQ} STREQUAL "26m") -set(ESP8266_FREQDIV 1) -endif() -if(${ESPTOOLPY_FLASHFREQ} STREQUAL "40m") -set(ESP8266_FREQDIV 0) -endif() -if(${ESPTOOLPY_FLASHFREQ} STREQUAL "80m") -set(ESP8266_FREQDIV 15) -endif() - -set(ESP8266_BINSCRIPT ${PYTHON} $(IDF_PATH)/tools/gen_appbin.py) - -# -# Add 'app.bin' target - generates with elf2image -# -add_custom_command(OUTPUT ${PROJECT_NAME}.bin - COMMAND ${CMAKE_OBJCOPY_COMPILER} --only-section .text -O binary ${PROJECT_NAME}.elf eagle.app.v6.text.bin - COMMAND ${CMAKE_OBJCOPY_COMPILER} --only-section .data -O binary ${PROJECT_NAME}.elf eagle.app.v6.data.bin - COMMAND ${CMAKE_OBJCOPY_COMPILER} --only-section .rodata -O binary ${PROJECT_NAME}.elf eagle.app.v6.rodata.bin - COMMAND ${CMAKE_OBJCOPY_COMPILER} --only-section .irom0.text -O binary ${PROJECT_NAME}.elf eagle.app.v6.irom0text.bin - COMMAND ${ESP8266_BINSCRIPT} ${PROJECT_NAME}.elf ${ESP8266_BOOTMODE} ${ESP8266_FLASHMODE} ${ESP8266_FREQDIV} ${ESP8266_SIZEMAP} - COMMAND mv eagle.app.flash.bin ${PROJECT_NAME}.bin - COMMAND rm eagle.app.v6.text.bin eagle.app.v6.data.bin eagle.app.v6.rodata.bin eagle.app.v6.irom0text.bin - DEPENDS ${PROJECT_NAME}.elf - VERBATIM - ) -add_custom_target(app ALL DEPENDS ${PROJECT_NAME}.bin) - -set(BLANK_BIN ${BOOTLOADER_FIRMWARE_DIR}/blank.bin) -set(ESP_INIT_DATA_DEFAULT_BIN ${BOOTLOADER_FIRMWARE_DIR}/esp_init_data_default.bin) -set(BOOTLOADER_BIN ${BOOTLOADER_FIRMWARE_DIR}/boot_v1.7.bin) - -set(PYTHON ${CONFIG_PYTHON}) -set(ESPTOOLPY_SRC $(IDF_PATH)/components/esptool_py/esptool/esptool.py) - -set(CHIP esp8266) -set(ESPPORT ${CONFIG_ESPTOOLPY_PORT}) -set(ESPBAUD ${CONFIG_ESPTOOLPY_BAUD}) -set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) -set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) -set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) -set(ESPTOOLPY ${PYTHON} ${ESPTOOLPY_SRC} --chip ${CHIP}) - -set(ESPTOOL_WRITE_FLASH_OPTIONS --flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} --flash_size ${ESPFLASHSIZE}) - -set(ESPTOOLPY_SERIAL ${ESPTOOLPY} --port ${ESPPORT} --baud ${ESPBAUD} --before ${CONFIG_ESPTOOLPY_BEFORE} --after ${CONFIG_ESPTOOLPY_AFTER}) - -set(ESPTOOLPY_WRITE_FLASH ${ESPTOOLPY_SERIAL} write_flash -z ${ESPTOOL_WRITE_FLASH_OPTIONS}) - -set(APP_BIN ${PROJECT_NAME}.bin) - -set(ESPTOOL_ALL_FLASH_ARGS ${BOOTLOADER_BIN_OFFSET} ${BOOTLOADER_BIN} - ${APP_OFFSET} ${APP_BIN} - ${ESP_INIT_DATA_DEFAULT_BIN_OFFSET} ${ESP_INIT_DATA_DEFAULT_BIN} - ${BLANK_BIN_OFFSET1} ${BLANK_BIN} - ${BLANK_BIN_OFFSET2} ${BLANK_BIN}) - -add_custom_target(flash DEPENDS ${PROJECT_NAME}.bin - COMMAND echo "Flashing binaries to serial port ${ESPPORT} app at offset ${APP_OFFSET}..." - COMMAND echo ${ESPTOOL_ALL_FLASH_ARGS} - COMMAND ${ESPTOOLPY_WRITE_FLASH} ${ESPTOOL_ALL_FLASH_ARGS} - COMMAND echo "success" - ) - -add_custom_target(erase_flash DEPENDS "" - COMMAND echo "Erasing entire flash..." - COMMAND ${ESPTOOLPY_SERIAL} erase_flash - COMMAND echo "success" - ) - -set(MONITOR_PYTHON ${PYTHON}) -set(MONITORBAUD ${CONFIG_MONITOR_BAUD}) -set(APP_ELF ${PROJECT_NAME}.elf) -set(MONITOR_OPTS --baud ${MONITORBAUD} --port ${ESPPORT} --toolchain-prefix ${CONFIG_TOOLPREFIX} ${APP_ELF}) - -function(esp_monitor func dependencies) - add_custom_target(${func} DEPENDS ${dependencies} - COMMAND echo "start monitor ... " - COMMAND echo $(MONITOR_PYTHON) ${IDF_PATH}/tools/idf_monitor.py ${MONITOR_OPTS} - COMMAND $(MONITOR_PYTHON) ${IDF_PATH}/tools/idf_monitor.py ${MONITOR_OPTS} - COMMAND echo "idf monitor exit" - ) -endfunction() - -esp_monitor(monitor "") diff --git a/components/esp8266/sdkconfig.rename b/components/esp8266/sdkconfig.rename new file mode 100644 index 000000000..1f1159b19 --- /dev/null +++ b/components/esp8266/sdkconfig.rename @@ -0,0 +1,17 @@ +# sdkconfig replacement configurations for deprecated options formatted as +# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION + +CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +CONFIG_CONSOLE_UART CONFIG_ESP_CONSOLE_UART +CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +CONFIG_CONSOLE_UART_CUSTOM CONFIG_ESP_CONSOLE_UART_CUSTOM +CONFIG_CONSOLE_UART_NONE CONFIG_ESP_CONSOLE_UART_NONE +CONFIG_CONSOLE_UART_NUM CONFIG_ESP_CONSOLE_UART_NUM +CONFIG_CONSOLE_UART_CUSTOM_NUM_0 CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0 +CONFIG_CONSOLE_UART_CUSTOM_NUM_1 CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1 +CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +CONFIG_UART0_SWAP_IO CONFIG_ESP_UART0_SWAP_IO + +CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +CONFIG_TASK_WDT_PANIC CONFIG_ESP_TASK_WDT_PANIC +CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S \ No newline at end of file diff --git a/components/esp8266/source/backtrace.c b/components/esp8266/source/backtrace.c new file mode 100644 index 000000000..053ca7715 --- /dev/null +++ b/components/esp8266/source/backtrace.c @@ -0,0 +1,126 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp8266/eagle_soc.h" + +static uint32_t prev_text_size(const uint32_t pc) +{ + uint32_t size; + extern uint32_t _text_start, _text_end; + + if (pc > (uint32_t)&_text_start && pc < (uint32_t)&_text_end) { + size = pc - (uint32_t )&_text_start; + } else if (IS_IRAM(pc)) { + size = pc - IRAM_BASE; + } else if (IS_ROM(pc)) { + size = pc - ROM_BASE; + } else { + size = 0; + } + + return size; +} + +int xt_pc_is_valid(const void *pc) +{ + return prev_text_size((uint32_t)pc) ? 1 : 0; +} + +int xt_retaddr_callee(const void *i_pc, const void *i_sp, const void *i_lr, void **o_pc, void **o_sp) +{ + uint32_t lr = (uint32_t)i_lr; + uint32_t pc = (uint32_t)i_pc; + uint32_t sp = (uint32_t)i_sp; + + uint32_t off = 0; + const uint32_t text_size = prev_text_size(pc); + + for (; off < text_size; off++) { + if ((*(uint8_t *)(pc - off) == 0x12) && + (*(uint8_t *)(pc - off + 1) == 0xc1)) { + const int8_t stk_size = *(int8_t *)(pc - off + 2); + + if (stk_size >= 0 || stk_size % 16 != 0) { + continue; + } + + sp -= stk_size; + + if (off <= 3) { + pc = lr; + } else { + pc = *(uint32_t *)(sp - 4); + } + + *o_sp = (void *)sp; + *o_pc = (void *)pc; + + break; + } else if ((*(uint8_t *)(pc - off) == 0x92) && + (((*(uint8_t *)(pc - off + 1)) & 0xf0) == 0xa0) && + (*(uint8_t *)(pc - off + 3) == 0x90) && + (*(uint8_t *)(pc - off + 4) == 0x11) && + (*(uint8_t *)(pc - off + 5) == 0xc0)) { + const uint16_t stk_size = ((*(uint8_t *)(pc - off + 1)) & 0x0f) + (*(uint8_t *)(pc - off + 2)); + + if (!stk_size || stk_size >= 2048) { + continue; + } + + sp += stk_size; + pc = *(uint32_t *)(sp - 4); + + *o_sp = (void *)sp; + *o_pc = (void *)pc; + + break; + } else if ((*(uint8_t *)(pc - off) == 0x0d) && + (*(uint8_t *)(pc - off + 1) == 0xf0)) { + pc = lr; + + *o_sp = (void *)sp; + *o_pc = (void *)pc; + + break; + } + } + + return off < text_size ? (xt_pc_is_valid(*o_pc) ? 1 : 0) : 0; +} + +void *xt_return_address(int lvl) +{ + void *i_sp; + void *i_lr = NULL; + void *i_pc = (void *)((uint32_t)xt_return_address + 32); + + void *o_pc = NULL; + void *o_sp; + + __asm__ __volatile__( + "mov %0, a1\n" + : "=a"(i_sp) + : + : "memory" + ); + + lvl += 2; + while(lvl-- && xt_retaddr_callee(i_pc, i_sp, i_lr, &o_pc, &o_sp)) { + i_pc = o_pc; + i_sp = o_sp; + } + + return xt_pc_is_valid(o_pc) ? o_pc : NULL; +} diff --git a/components/esp8266/source/chip_boot.c b/components/esp8266/source/chip_boot.c index 0ca7ff5b0..9ced76200 100644 --- a/components/esp8266/source/chip_boot.c +++ b/components/esp8266/source/chip_boot.c @@ -13,86 +13,17 @@ // limitations under the License. #include "sdkconfig.h" -#include "esp_attr.h" -#include "spi_flash.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp8266/eagle_soc.h" -#include "esp8266/rom_functions.h" -#include "esp_image_format.h" - -#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c) -#define PERIPHS_SPI_FLASH_CTRL (0x60000200 + 0x08) -#define PERIPHS_IO_MUX_CONF_U (0x60000800) - -#define SPI0_CLK_EQU_SYSCLK BIT8 -#define SPI_FLASH_CLK_EQU_SYSCLK BIT12 -static const char *TAG = "chip_boot"; +#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH +#include "spi_flash.h" /* - * @brief initialize the chip including flash I/O and chip cache according to - * boot parameters which are stored at the flash + * @brief initialize the chip */ -void chip_boot(size_t start_addr) +void chip_boot(void) { - int ret; - uint32_t freqdiv, flash_size; - uint32_t freqbits; - esp_image_header_t fhdr; - - uint32_t flash_map_table[FALSH_SIZE_MAP_MAX] = { - 1 * 1024 * 1024, - 2 * 1024 * 1024, - 4 * 1024 * 1024, - 8 * 1024 * 1024, - 16 * 1024 * 1024 - }; - uint32_t flash_map_table_size = sizeof(flash_map_table) / sizeof(flash_map_table[0]); - - extern esp_spi_flash_chip_t flashchip; - extern void phy_get_bb_evm(void); - extern void cache_init(uint8_t); - extern void user_spi_flash_dio_to_qio_pre_init(void); - - phy_get_bb_evm(); - - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_USRREG, BIT5); - - ret = spi_flash_read(start_addr, &fhdr, sizeof(esp_image_header_t)); - if (ret) { - ESP_EARLY_LOGE(TAG, "SPI flash read result %d\n", ret); - } - - if (3 > fhdr.spi_speed) - freqdiv = fhdr.spi_speed + 2; - else if (0x0F == fhdr.spi_speed) - freqdiv = 1; - else - freqdiv = 2; - - if (fhdr.spi_size < flash_map_table_size) { - flash_size = flash_map_table[fhdr.spi_size]; - ESP_EARLY_LOGD(TAG, "SPI flash size is %d\n", flash_size); - } else { - flash_size = 0; - ESP_EARLY_LOGE(TAG, "SPI size error is %d\n", fhdr.spi_size); - } - flashchip.chip_size = flash_size; - - if (1 >= freqdiv) { - freqbits = SPI_FLASH_CLK_EQU_SYSCLK; - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); - SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); - } else { - freqbits = ((freqdiv - 1) << 8) + ((freqdiv / 2 - 1) << 4) + (freqdiv - 1); - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); - CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); - } - SET_PERI_REG_BITS(PERIPHS_SPI_FLASH_CTRL, 0xfff, freqbits, 0); + extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode); - if (fhdr.spi_mode == ESP_IMAGE_SPI_MODE_QIO) { - ESP_EARLY_LOGD(TAG, "SPI flash enable QIO mode\n"); - user_spi_flash_dio_to_qio_pre_init(); - } + esp_spi_flash_init(CONFIG_SPI_FLASH_FREQ, CONFIG_SPI_FLASH_MODE); } +#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */ diff --git a/components/util/src/crc.c b/components/esp8266/source/crc.c similarity index 96% rename from components/util/src/crc.c rename to components/esp8266/source/crc.c index 6bf5cfaed..e3ea8480e 100644 --- a/components/util/src/crc.c +++ b/components/esp8266/source/crc.c @@ -14,7 +14,8 @@ #include -#include "crc.h" +#include "rom/crc.h" +#include "ibus_data.h" static const uint32_t crc32_le_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, @@ -52,7 +53,7 @@ static const uint32_t crc32_le_table[256] = { 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; -static const uint16_t crc16_le_table[256] = { +static const uint16_t crc16_le_table[256] ESP_IBUS_ATTR = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, @@ -87,7 +88,7 @@ static const uint16_t crc16_le_table[256] = { 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; -static const uint8_t crc8_le_table[] = { +static const uint8_t crc8_le_table[] ESP_IBUS_ATTR = { 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41, 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, @@ -113,7 +114,7 @@ uint16_t crc16_le(uint16_t crc, const uint8_t* buf, uint32_t len) crc = ~crc; for (i = 0; i < len; i++) { - crc = crc16_le_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); + crc = ESP_IBUS_GET_U16_DATA((crc ^ buf[i]) & 0xff, crc16_le_table) ^ (crc >> 8); } return ~crc; @@ -137,7 +138,7 @@ uint8_t esp_crc8(uint8_t const* p, uint32_t len) uint8_t crc = 0x00; while (len--) { - crc = crc8_le_table[crc ^ *p++]; + crc = ESP_IBUS_GET_U8_DATA(crc ^ *p++, crc8_le_table); } return crc; diff --git a/components/esp8266/source/esp_fast_boot.c b/components/esp8266/source/esp_fast_boot.c new file mode 100644 index 000000000..7fe73c726 --- /dev/null +++ b/components/esp8266/source/esp_fast_boot.c @@ -0,0 +1,205 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// #define LOG_LOCAL_LEVEL ESP_LOG_ERROR + +#include +#include +#include +#include "esp_log.h" +#include "rom/crc.h" +#include "esp_private/esp_system_internal.h" +#include "esp_fast_boot.h" +#ifndef BOOTLOADER_BUILD +#include "esp_ota_ops.h" +#include "esp_image_format.h" +#include "esp_wifi.h" +#include "esp_system.h" +#include "esp8266/rom_functions.h" +#include "esp8266/eagle_soc.h" +#include "rom/uart.h" +#include "esp_spi_flash.h" +#include "FreeRTOS.h" +#include "task.h" +#endif + +static char *TAG = "fast_boot"; + +#ifndef BOOTLOADER_BUILD +int esp_fast_boot_enable_partition(const esp_partition_t *partition) +{ + int ret; + esp_image_header_t image; + + if (!partition || partition->type != ESP_PARTITION_TYPE_APP) + return -EINVAL; + + ret = spi_flash_read(partition->address, &image, sizeof(esp_image_header_t)); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "read image head from spi flash error"); + return -EIO; + } + + rtc_sys_info.fast_boot.image_start = partition->address; + rtc_sys_info.fast_boot.image_size = partition->size - 4; + rtc_sys_info.fast_boot.image_entry = image.entry_addr; + rtc_sys_info.fast_boot.magic = ESP_SYSTEM_FAST_BOOT_IMAGE; + rtc_sys_info.fast_boot.crc32 = crc32_le(UINT32_MAX, (uint8_t *)&rtc_sys_info.fast_boot, sizeof(rtc_sys_info.fast_boot) - 4); + + return 0; +} + +int esp_fast_boot_enable(void) +{ + const esp_partition_t *running = esp_ota_get_running_partition(); + + return esp_fast_boot_enable_partition(running); +} + +void IRAM_ATTR esp_fast_boot_restart_app(uint32_t image_start, uint32_t entry_addr, uint8_t region, uint8_t sub_region) +{ + const uint32_t sp = DRAM_BASE + DRAM_SIZE - 16; + void (*user_start)(size_t start_addr); + + Cache_Read_Disable(); + Cache_Read_Enable(sub_region, region, SOC_CACHE_SIZE); + + __asm__ __volatile__( + "mov a1, %0\n" + : : "a"(sp) : "memory" + ); + + user_start = (void *)entry_addr; + user_start(image_start); +} + +int esp_fast_boot_restart(void) +{ + extern void pm_goto_rf_on(void); + extern void clockgate_watchdog(int on); + + int ret; + uint8_t region, sub_region; + uint32_t image_start, image_size, image_entry, image_mask; + const esp_partition_t *to_boot; + esp_image_header_t image; + + to_boot = esp_ota_get_boot_partition(); + if (!to_boot) { + ESP_LOGI(TAG, "no OTA boot partition"); + to_boot = esp_ota_get_running_partition(); + if (!to_boot) { + ESP_LOGE(TAG, "ERROR: Fail to get running partition"); + return -EINVAL; + } + } + + image_start = to_boot->address; + image_size = to_boot->size - 4; + + ret = spi_flash_read(image_start, &image, sizeof(esp_image_header_t)); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "ERROR: Fail to read image head from spi flash error=%d", ret); + return -EIO; + } + + image_entry = image.entry_addr; + + if (image_start < 0x200000) { + region = 0; + } else if (image_start < 0x400000) { + region = 1; + } else if (image_start < 0x600000) { + region = 2; + } else if (image_start < 0x800000) { + region = 3; + } else { + ESP_LOGE(TAG, "ERROR: App bin error, start_addr 0x%08x image_len %d\n", image_start, image_size); + return -EINVAL; + } + + image_mask = image_start & 0x1fffff; + if (image_mask < 0x100000) { + sub_region = 0; + } else { + sub_region = 1; + } + + if (esp_wifi_stop() != ESP_OK) { + ESP_LOGD(TAG, "ERROR: Fail to stop Wi-Fi"); + } + + uart_tx_wait_idle(1); + uart_tx_wait_idle(0); + + vTaskDelay(40 / portTICK_RATE_MS); + + pm_goto_rf_on(); + clockgate_watchdog(0); + REG_WRITE(0x3ff00018, 0xffff00ff); + SET_PERI_REG_MASK(0x60000D48, BIT1); + CLEAR_PERI_REG_MASK(0x60000D48, BIT1); + + /* Get startup time */ + //ets_printf("\nets\n"); + + uart_disable_swap_io(); + + vPortEnterCritical(); + REG_WRITE(INT_ENA_WDEV, 0); + _xt_isr_mask(UINT32_MAX); + + esp_reset_reason_set_hint(ESP_RST_FAST_SW); + + esp_fast_boot_restart_app(image_start, image_entry, region, sub_region); + + return 0; +} +#endif + +void esp_fast_boot_disable(void) +{ + memset(&rtc_sys_info.fast_boot, 0, sizeof(rtc_sys_info.fast_boot)); +} + +int esp_fast_boot_get_info(uint32_t *image_start, uint32_t *image_size, uint32_t *image_entry) +{ + if (rtc_sys_info.fast_boot.magic != ESP_SYSTEM_FAST_BOOT_IMAGE) { + ESP_LOGE(TAG, "magic error"); + return -EINVAL; + } + + if (rtc_sys_info.fast_boot.crc32 != crc32_le(UINT32_MAX, (uint8_t *)&rtc_sys_info.fast_boot, sizeof(rtc_sys_info.fast_boot) - 4)) { + ESP_LOGE(TAG, "CRC32 error"); + esp_fast_boot_disable(); + return -EINVAL; + } + + *image_start = rtc_sys_info.fast_boot.image_start; + *image_size = rtc_sys_info.fast_boot.image_size; + *image_entry = rtc_sys_info.fast_boot.image_entry; + + esp_fast_boot_disable(); + + return 0; +} + +void esp_fast_boot_print_info(void) +{ + ets_printf("\nmagic is %x\n", rtc_sys_info.fast_boot.magic); + ets_printf("image start is %x\n", rtc_sys_info.fast_boot.image_start); + ets_printf("image size is %x\n", rtc_sys_info.fast_boot.image_size); + ets_printf("image entry is %x\n", rtc_sys_info.fast_boot.image_entry); + ets_printf("CRC32 is %x\n", rtc_sys_info.fast_boot.crc32); +} diff --git a/components/esp8266/source/esp_fsleep.c b/components/esp8266/source/esp_fsleep.c new file mode 100644 index 000000000..e0bb404cb --- /dev/null +++ b/components/esp8266/source/esp_fsleep.c @@ -0,0 +1,65 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_sleep.h" +#include "esp_log.h" + +static const char* TAG = "FPM"; + +void esp_wifi_fpm_open(void) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +void esp_wifi_fpm_close(void) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +void esp_wifi_fpm_do_wakeup(void) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +void esp_wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +esp_err_t esp_wifi_fpm_do_sleep(uint32_t sleep_time_in_us) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); + return ESP_FAIL; +} + +void esp_wifi_fpm_set_sleep_type(wifi_sleep_type_t type) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +wifi_sleep_type_t esp_wifi_fpm_get_sleep_type(void) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); + return WIFI_NONE_SLEEP_T; +} + +void esp_wifi_enable_gpio_wakeup(uint32_t gpio_num, gpio_int_type_t intr_status) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} + +void esp_wifi_disable_gpio_wakeup(void) +{ + ESP_LOGE(TAG, "We have removed this api, please do not call"); +} diff --git a/components/esp8266/source/esp_sleep.c b/components/esp8266/source/esp_sleep.c new file mode 100644 index 000000000..bf0e0a256 --- /dev/null +++ b/components/esp8266/source/esp_sleep.c @@ -0,0 +1,437 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_timer.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_sleep.h" +#include "esp_wifi.h" +#include "FreeRTOS.h" +#include "freertos/task.h" +#include "driver/soc.h" +#include "driver/gpio.h" +#include "esp8266/timer_struct.h" +#include "esp8266/gpio_struct.h" +#include "esp8266/rom_functions.h" +#include "driver/rtc.h" +#include "rom/uart.h" +#include "esp_private/phy_init_data.h" + +#define FRC2_LOAD (0x60000620) +#define FRC2_COUNT (0x60000624) +#define FRC2_CTL (0x60000628) +#define FRC2_ALARM (0x60000630) + +#define FRC2_CNTL_ENABLE BIT7 + +#define FRC2_TICKS_PER_US (5) +#define FRC2_TICKS_MAX (UINT32_MAX / 4) + +#define SLEEP_PROC_TIME (2735) +#define WAKEUP_EARLY_TICKS (264) // PLL and STAL wait ticks +#define MIN_SLEEP_US (6500) +#define RTC_TICK_CAL (100) +#define RTC_TICK_OFF (1245 + RTC_TICK_CAL) + +#define TAG "esp8266_pm" + +typedef struct pm_soc_clk { + uint32_t ccount; + + uint32_t frc2_enable; + uint32_t frc2_cnt; + + uint32_t wdev_cnt; + + uint32_t rtc_val; + uint32_t cal_period; + + uint32_t sleep_us; +} pm_soc_clk_t; + +typedef struct sleep_proc { + uint32_t sleep_us; // sleep microsecond + + uint32_t wait_int : 1; // wait interrupt + uint32_t check_mode : 1; // check sleep mode + uint32_t flush_uart : 1; // flush UART +} sleep_proc_t; + +static uint16_t s_lock_cnt = 1; +static esp_sleep_mode_t s_sleep_mode = ESP_CPU_WAIT; +static uint32_t s_sleep_wakup_triggers; +static uint32_t s_sleep_duration; + +static inline uint32_t save_local_wdev(void) +{ + extern uint32_t WDEV_INTEREST_EVENT; + + uint32_t reg = WDEV_INTEREST_EVENT; + + REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT); + + return reg; +} + +static inline void restore_local_wdev(uint32_t reg) +{ + REG_WRITE(INT_ENA_WDEV, reg); +} + +uint32_t rtc_clk_to_us(uint32_t rtc_cycles, uint32_t period) +{ + return (uint64_t)rtc_cycles * period / 4096; +} + +uint32_t rtc_us_to_clk(uint32_t us, uint32_t period) +{ + return (uint64_t)us * 4096 / period; +} + +static inline void save_soc_clk(pm_soc_clk_t *clk) +{ + clk->rtc_val = REG_READ(RTC_SLP_CNT_VAL); + + clk->ccount = soc_get_ccount(); + + clk->frc2_enable = REG_READ(FRC2_CTL) & FRC2_CNTL_ENABLE; + if (clk->frc2_enable) + clk->frc2_cnt = REG_READ(FRC2_COUNT); + + clk->wdev_cnt = REG_READ(WDEV_COUNT_REG); +} + +static inline uint32_t min_sleep_us(pm_soc_clk_t *clk) +{ + const uint32_t os_idle_ticks = prvGetExpectedIdleTime(); + const int32_t os_sleep_us = ((int32_t)soc_get_ccompare() - (int32_t)clk->ccount) / g_esp_ticks_per_us + + (os_idle_ticks ? os_idle_ticks - 1 : 0) * portTICK_RATE_MS * 1000; + const uint32_t ccompare_sleep_us = os_sleep_us > 0 ? os_sleep_us : 0; + + if (clk->frc2_enable) { + const uint32_t frc2_sleep_ticks = REG_READ(FRC2_ALARM) - clk->frc2_cnt; + const uint32_t frc2_sleep_us = frc2_sleep_ticks < FRC2_TICKS_MAX ? frc2_sleep_ticks / FRC2_TICKS_PER_US : 0; + + clk->sleep_us = MIN(ccompare_sleep_us, frc2_sleep_us); + } else { + clk->sleep_us = ccompare_sleep_us; + } + + return clk->sleep_us; +} + +static inline uint32_t sleep_rtc_ticks(pm_soc_clk_t *clk) +{ + uint32_t rtc_ticks; + + clk->cal_period = pm_rtc_clock_cali_proc(); + + rtc_ticks = rtc_us_to_clk(clk->sleep_us - SLEEP_PROC_TIME, clk->cal_period); + + return rtc_ticks; +} + +static inline void update_soc_clk(pm_soc_clk_t *clk) +{ + extern uint64_t WdevTimOffSet; + + uint32_t slept_us; + + if (s_sleep_wakup_triggers & RTC_GPIO_TRIG_EN) { + uint32_t total_rtc = 0, end_rtc = REG_READ(RTC_SLP_CNT_VAL); + + if (end_rtc > clk->rtc_val) + total_rtc = end_rtc - clk->rtc_val; + else + total_rtc = UINT32_MAX - clk->rtc_val + end_rtc; + slept_us = rtc_clk_to_us(total_rtc, clk->cal_period) + RTC_TICK_OFF; + + if (slept_us >= clk->sleep_us) + slept_us = clk->sleep_us; + else + slept_us -= RTC_TICK_CAL; + } else { + slept_us = clk->sleep_us; + } + + const uint32_t os_ccount = slept_us * g_esp_ticks_per_us + clk->ccount; + + if (os_ccount >= _xt_tick_divisor) + soc_set_ccompare(os_ccount + 32); + soc_set_ccount(os_ccount); + + if (clk->frc2_enable) { + const uint32_t frc2_cnt = slept_us * FRC2_TICKS_PER_US + clk->frc2_cnt - 1; + + REG_WRITE(FRC2_LOAD, frc2_cnt); + } + + uint32_t wdev_us; + uint32_t wdev_cnt = REG_READ(WDEV_COUNT_REG); + + if (clk->wdev_cnt < wdev_cnt) + wdev_us = slept_us - (wdev_cnt - clk->wdev_cnt); + else + wdev_us = slept_us - (UINT32_MAX - clk->wdev_cnt + wdev_cnt); + + WdevTimOffSet += wdev_us; +} + +static int cpu_is_wait_mode(void) +{ + return (s_sleep_mode == ESP_CPU_WAIT) || s_lock_cnt; +} + +static int cpu_reject_sleep(void) +{ + int ret = 0; + + if (s_sleep_wakup_triggers & RTC_GPIO_TRIG_EN) { + for (int gpio = 0; gpio < 16; gpio++) { + if (!GPIO.pin[gpio].wakeup_enable) + continue; + + if (GPIO.pin[gpio].int_type == GPIO_INTR_LOW_LEVEL) { + if (!((GPIO.in >> gpio) & 1)) { + ret = 1; + break; + } + } else if (GPIO.pin[gpio].int_type == GPIO_INTR_HIGH_LEVEL) { + if ((GPIO.in >> gpio) & 1) { + ret = 1; + break; + } + } + } + } + + return ret; +} + +rtc_cpu_freq_t rtc_clk_cpu_freq_get(void) +{ + rtc_cpu_freq_t freq; + uint32_t reg = REG_READ(DPORT_CTL_REG); + + if (reg & DPORT_CTL_DOUBLE_CLK) + freq = RTC_CPU_FREQ_160M; + else + freq = RTC_CPU_FREQ_80M; + + return freq; +} + +void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq) +{ + if (RTC_CPU_FREQ_80M == cpu_freq) + REG_CLR_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); + else + REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); +} + +esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us) +{ + if (time_in_us <= MIN_SLEEP_US) + return ESP_ERR_INVALID_ARG; + + s_sleep_duration = time_in_us; + s_sleep_wakup_triggers |= RTC_TIMER_TRIG_EN; + + return ESP_OK; +} + +esp_err_t esp_sleep_enable_gpio_wakeup(void) +{ + s_sleep_wakup_triggers |= RTC_GPIO_TRIG_EN; + + return ESP_OK; +} + +esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) +{ + // For most of sources it is enough to set trigger mask in local + // configuration structure. The actual RTC wake up options + // will be updated by esp_sleep_start(). + if (source == ESP_SLEEP_WAKEUP_ALL) { + s_sleep_wakup_triggers = 0; + } else if (ESP_SLEEP_WAKEUP_TIMER == source) { + s_sleep_wakup_triggers &= ~RTC_TIMER_TRIG_EN; + s_sleep_duration = 0; + } else if (ESP_SLEEP_WAKEUP_GPIO == source) { + s_sleep_wakup_triggers &= ~RTC_GPIO_TRIG_EN; + } else { + ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source); + return ESP_ERR_INVALID_STATE; + } + + return ESP_OK; +} + +static int esp_light_sleep_internal(const sleep_proc_t *proc) +{ + pm_soc_clk_t clk; + esp_irqflag_t irqflag; + uint32_t wdevflag; + uint32_t sleep_us; + uint64_t start_us; + int ret = ESP_OK; + int cpu_wait = proc->wait_int; + + start_us = esp_timer_get_time(); + + if (proc->check_mode && cpu_is_wait_mode()) { + if (proc->wait_int) + soc_wait_int(); + return ESP_ERR_INVALID_ARG; + } + + if (cpu_reject_sleep()) { + if (proc->wait_int) + soc_wait_int(); + return ESP_ERR_INVALID_STATE; + } + + if (proc->flush_uart) { + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); + } + + irqflag = soc_save_local_irq(); + wdevflag = save_local_wdev(); + + if (proc->check_mode && cpu_is_wait_mode()) { + ret = ESP_ERR_INVALID_ARG; + goto exit; + } + + if (cpu_reject_sleep()) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + save_soc_clk(&clk); + if (!proc->sleep_us) + sleep_us = min_sleep_us(&clk); + else { + uint64_t total_us = esp_timer_get_time() - start_us; + + if (total_us >= proc->sleep_us) { + ret = ESP_ERR_INVALID_ARG; + goto exit; + } else + sleep_us = clk.sleep_us = proc->sleep_us - total_us; + } + + if (sleep_us > MIN_SLEEP_US) { + uint32_t rtc_ticks = sleep_rtc_ticks(&clk); + + if (rtc_ticks > WAKEUP_EARLY_TICKS + 1) { + rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get(); + + pm_set_sleep_mode(2); + pm_set_sleep_cycles(rtc_ticks - WAKEUP_EARLY_TICKS); + rtc_light_sleep_start(s_sleep_wakup_triggers | RTC_TIMER_TRIG_EN, 0); + rtc_wakeup_init(); + + rtc_clk_cpu_freq_set(cpu_freq); + + update_soc_clk(&clk); + + cpu_wait = 0; + } else + ret = ESP_ERR_INVALID_ARG; + } else + ret = ESP_ERR_INVALID_ARG; + +exit: + restore_local_wdev(wdevflag); + soc_restore_local_irq(irqflag); + + if (cpu_wait) + soc_wait_int(); + + return ret; +} + +esp_err_t esp_light_sleep_start(void) +{ + const sleep_proc_t proc = { + .sleep_us = s_sleep_duration, + .wait_int = 0, + .check_mode = 0, + .flush_uart = 1 + }; + + if (esp_wifi_get_state() >= WIFI_STATE_START) { + return ESP_ERR_INVALID_STATE; + } + + return esp_light_sleep_internal(&proc); +} + +void esp_sleep_lock(void) +{ + const esp_irqflag_t irqflag = soc_save_local_irq(); + s_lock_cnt++; + soc_restore_local_irq(irqflag); +} + +void esp_sleep_unlock(void) +{ + const esp_irqflag_t irqflag = soc_save_local_irq(); + s_lock_cnt--; + soc_restore_local_irq(irqflag); +} + +void esp_sleep_set_mode(esp_sleep_mode_t mode) +{ + s_sleep_mode = mode; +} + +void esp_sleep_start(void) +{ + const sleep_proc_t proc = { + .sleep_us = 0, + .wait_int = 1, + .check_mode = 1, + .flush_uart = 1, + }; + + esp_light_sleep_internal(&proc); +} + +esp_err_t esp_pm_configure(const void* vconfig) +{ +#ifndef CONFIG_PM_ENABLE + return ESP_ERR_NOT_SUPPORTED; +#endif + + extern void reset_noise_timer(uint16_t interval); + const esp_pm_config_esp8266_t* config = (const esp_pm_config_esp8266_t*) vconfig; + if (config->light_sleep_enable) { + reset_noise_timer(3000); + s_sleep_mode = ESP_CPU_LIGHTSLEEP; + } else { + reset_noise_timer(100); + s_sleep_mode = ESP_CPU_WAIT; + } + return ESP_OK; +} + +uint32_t rtc_time_get(void) +{ + return REG_READ(RTC_SLP_CNT_VAL); +} diff --git a/components/esp8266/source/esp_socket.c b/components/esp8266/source/esp_socket.c deleted file mode 100644 index 74d2def56..000000000 --- a/components/esp8266/source/esp_socket.c +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include "esp_socket.h" -#include "net/sockio.h" - -#define CRITICAL_DECLARE(t) -#define CRITICAL_ENTER(t) -#define CRITICAL_EXIT(t) - -#ifndef ESP_SOCKET_MAX -#define ESP_SOCKET_MAX 2 -#endif - -#define SET_ERR(err) errno = err - -#define CHECK_FD(s) \ - if (s >= ESP_SOCKET_MAX \ - || !s_socket[s].info) { \ - SET_ERR(EINVAL); \ - return -1; \ - } - -#define CHECK_METHOD(s, io) \ - CHECK_FD(s) \ - if (!s_socket[s].method \ - || !s_socket[s].method->io) { \ - SET_ERR(ESRCH); \ - return -1; \ - } - -#define SOCKET_IO_METHOD(s, io, ...) \ - s_socket[s].method->io(s_socket[s].index, ##__VA_ARGS__) - -/* - * socket event object - */ -typedef struct esp_socket_event { - esp_aio_cb_t cb; - void *arg; -} esp_socket_event_t; - -/* - * socket object - */ -typedef struct esp_socket { - esp_socket_info_t *info; - - /* - * lowlevel socket module index - */ - void *index; - - /* - * lowlevel socket module method - */ - const esp_socket_method_t *method; - - esp_socket_event_t event[ESP_SOCKET_MAX_EVENT]; -} esp_socket_t; - -static esp_socket_t s_socket[ESP_SOCKET_MAX]; - -static inline int event_is_used(int s, int e) -{ - return s_socket[s].event[e].cb != NULL; -} - -static inline int alloc_event(int s, int e) -{ - CRITICAL_DECLARE(t); - - if (e >= ESP_SOCKET_MAX_EVENT) - return -1; - - CRITICAL_ENTER(t); - if (event_is_used(s, e)) { - e = ESP_SOCKET_MAX_EVENT; - } - CRITICAL_EXIT(t); - - return e < ESP_SOCKET_MAX_EVENT ? e : -1; -} - -static inline void free_event(int s, int e) -{ - s_socket[s].event[e].cb = NULL; -} - -static inline int alloc_socket(void) -{ - int s; - CRITICAL_DECLARE(t); - - CRITICAL_ENTER(t); - for (s = 0; s < ESP_SOCKET_MAX; s++) { - if (s_socket[s].info == NULL) { - s_socket[s].info = (void *)1; - break; - } - } - CRITICAL_EXIT(t); - - return s < ESP_SOCKET_MAX ? s : -1; -} - -static inline void free_socket(int s) -{ - int e; - - s_socket[s].info = NULL; - for (e = 0; e < ESP_SOCKET_MAX_EVENT; e++) { - free_event(s, e); - } -} - -/* - * @brief create a socket file description - */ -int esp_socket(int domain, int type, int protocol) -{ - int s; - - s = alloc_socket(); - if (s < 0) { - SET_ERR(ENOMEM); - return -1; - } - - s_socket[s].info = malloc(sizeof(esp_socket_info_t)); - if (!s_socket[s].info) { - free_socket(s); - SET_ERR(ENOMEM); - return -1; - } - - s_socket[s].info->domain = domain; - s_socket[s].info->type = type; - s_socket[s].info->protocol = protocol; - - s_socket[s].index = NULL; - s_socket[s].method = NULL; - - return s; -} - -/* - * @brief send a block of data asynchronously and receive result by callback function - */ -int esp_aio_sendto(esp_aio_t *aio, const struct sockaddr_ll *to, socklen_t len) -{ - int s = aio->fd; - - CHECK_METHOD(s, aio_sendto); - - return SOCKET_IO_METHOD(s, aio_sendto, aio, to, len); -} - -/* - * @brief register a event and its callback function to target of file description - */ -int esp_aio_event(int fd, unsigned int event, esp_aio_cb_t cb, void *arg) -{ - int e; - int ret; - int s = fd; - - CHECK_METHOD(s, aio_event); - - e = alloc_event(s, event); - if (e < 0) { - SET_ERR(ENOMEM); - return -1; - } - - ret = SOCKET_IO_METHOD(s, aio_event, event, cb, arg); - if (ret) { - free_event(s, e); - return -1; - } - - s_socket[s].event[e].cb = cb; - s_socket[s].event[e].arg = arg; - - return 0; -} - -/* - * @brief lowlevel socket module upload event and its data - */ -int esp_upload_event(void *index, esp_socket_info_t *info, unsigned int event, esp_aio_data_t *aio_data) -{ - int ret; - int s; - - if (event >= ESP_SOCKET_MAX_EVENT) - return -EINVAL; - - for (s = 0; s < ESP_SOCKET_MAX; s++) { - if (s_socket[s].index == index && event_is_used(s, event)) { - esp_aio_t aio; - - aio.fd = s; - aio.cb = s_socket[s].event[event].cb; - aio.arg = s_socket[s].event[event].arg; - - aio.pbuf = aio_data->pbuf; - aio.len = aio_data->len; - aio.ret = aio_data->status; - - ret = s_socket[s].event[event].cb(&aio); - if (ret) - return ret; - } - } - - return 0; -} - -/* - * @brief free buffer taken from event callback - */ -int esp_free_pbuf(int fd, void *pbuf) -{ - int ret; - int s = fd; - - CHECK_METHOD(s, free_pbuf); - - ret = SOCKET_IO_METHOD(s, free_pbuf, pbuf); - if (ret) - return -1; - - return 0; -} - -/* - * @brief map real lowlevel socket object to virtual socket - */ -static int map_socket_ll(int fd, const char *name) -{ - int s = fd; - const esp_socket_method_t *p; - extern const esp_socket_method_t __start_ksymatabesp_socket, __stop_ksymatabesp_socket; - - for (p = &__start_ksymatabesp_socket; p != &__stop_ksymatabesp_socket; p++) { - if (!strcmp(name, p->name)) - break; - } - if (p >= &__stop_ksymatabesp_socket) { - SET_ERR(ENXIO); - return -1; - } - - s_socket[s].index = p->open(s_socket[s].info); - if (!s_socket[s].index) - return -1; - s_socket[s].method = p; - - return 0; -} - -/* - * @brief send requset command to target by file description and get the result synchronously - */ -int esp_ioctl(int fd, unsigned int cmd, ...) -{ - int ret; - va_list va; - int s = fd; - - va_start(va, cmd); - - switch(cmd) { -#if SIOCGIFINDEX != SIOGIFINDEX - case SIOGIFINDEX: -#endif - case SIOCGIFINDEX: { - const char *name; - - name = va_arg(va, const char *); - ret = map_socket_ll(fd, name); - break; - } - default: { - int *arg = ((int *)&cmd) + 1; - - CHECK_METHOD(s, ioctl); - ret = SOCKET_IO_METHOD(s, ioctl, cmd, arg); - break; - } - } - - va_end(va); - - return ret; -} - -/* - * @brief close target of file description - */ -int esp_close(int fd) -{ - int ret; - int s = fd; - - CHECK_METHOD(s, close); - - ret = SOCKET_IO_METHOD(s, close); - if (ret) - return -1; - - free(s_socket[s].info); - free_socket(s); - - return 0; -} diff --git a/components/esp8266/source/esp_timer.c b/components/esp8266/source/esp_timer.c index a2e1ccc22..5661b3474 100644 --- a/components/esp8266/source/esp_timer.c +++ b/components/esp8266/source/esp_timer.c @@ -18,9 +18,18 @@ #include "FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" +#include "driver/soc.h" #define ESP_TIMER_HZ CONFIG_FREERTOS_HZ +typedef enum { + ESP_TIMER_INIT = 0, + ESP_TIMER_ONCE, + ESP_TIMER_CYCLE, + ESP_TIMER_STOP, + ESP_TIMER_DELETE, +} esp_timer_state_t; + struct esp_timer { TimerHandle_t os_timer; @@ -28,26 +37,64 @@ struct esp_timer { void *arg; - TickType_t period_ticks; + esp_timer_state_t state; }; static const char *TAG = "esp_timer"; +static esp_err_t delete_timer(esp_timer_handle_t timer) +{ + BaseType_t ret = xTimerDelete(timer->os_timer, portMAX_DELAY); + if (ret == pdPASS) + heap_caps_free(timer); + + return ret == pdPASS ? ESP_OK : ESP_ERR_NO_MEM; +} + /** * @brief FreeRTOS callback function */ static void esp_timer_callback(TimerHandle_t xTimer) { - BaseType_t os_ret; struct esp_timer *timer = (struct esp_timer *)pvTimerGetTimerID(xTimer); timer->cb(timer->arg); - if (!timer->period_ticks) { - os_ret = xTimerStop(timer->os_timer, 0); - if (os_ret != pdPASS) { - ESP_LOGE(TAG, "Set timer from periodic to once error"); + switch (timer->state) { + case ESP_TIMER_INIT: + case ESP_TIMER_STOP: + break; + case ESP_TIMER_CYCLE: { + BaseType_t ret = xTimerReset(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "start timer at callback error"); + } else { + ESP_LOGD(TAG, "start timer at callback OK"); + } + break; } + case ESP_TIMER_ONCE: { + BaseType_t ret = xTimerStop(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "stop timer at callback error"); + } else { + timer->state = ESP_TIMER_STOP; + ESP_LOGD(TAG, "stop timer at callback OK"); + } + break; + } + case ESP_TIMER_DELETE: { + esp_err_t ret = delete_timer(timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "delete timer at callback error"); + } else { + ESP_LOGD(TAG, "delete timer at callback OK"); + } + break; + } + default: + ESP_LOGE(TAG, "timer state error is %d", timer->state); + break; } } @@ -83,17 +130,16 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, if (!esp_timer) return ESP_ERR_NO_MEM; - esp_timer->cb = create_args->callback; - esp_timer->arg = create_args->arg; - esp_timer->period_ticks = 0; - os_timer = xTimerCreate(create_args->name, portMAX_DELAY, - pdTRUE, + pdFALSE, esp_timer, esp_timer_callback); if (os_timer) { esp_timer->os_timer = os_timer; + esp_timer->cb = create_args->callback; + esp_timer->arg = create_args->arg; + esp_timer->state = ESP_TIMER_INIT; *out_handle = (esp_timer_handle_t)esp_timer; } else { heap_caps_free(esp_timer); @@ -120,14 +166,7 @@ esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = 0; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_ONCE; } else { return ESP_ERR_INVALID_STATE; } @@ -152,14 +191,7 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = ticks; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_CYCLE; } else { return ESP_ERR_INVALID_STATE; } @@ -178,6 +210,8 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) BaseType_t os_ret; os_ret = xTimerStop(os_timer, portMAX_DELAY); + if (os_ret == pdPASS) + timer->state = ESP_TIMER_STOP; return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; } @@ -187,14 +221,32 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) */ esp_err_t esp_timer_delete(esp_timer_handle_t timer) { + esp_err_t ret; + assert(timer); - TimerHandle_t os_timer = timer->os_timer; - BaseType_t os_ret; + if (xTimerGetTimerDaemonTaskHandle() == xTaskGetCurrentTaskHandle()) { + timer->state = ESP_TIMER_DELETE; + ret = ESP_OK; + } else { + UBaseType_t prio = uxTaskPriorityGet(NULL); + if (prio >= configTIMER_TASK_PRIORITY) + vTaskPrioritySet(NULL, configTIMER_TASK_PRIORITY - 1); + else + prio = 0; - os_ret = xTimerDelete(os_timer, portMAX_DELAY); - if (os_ret == pdPASS) - heap_caps_free(timer); + ret = delete_timer(timer); + + if (prio) + vTaskPrioritySet(NULL, prio); + } + + return ret; +} + +int64_t esp_timer_get_time(void) +{ + extern uint64_t g_esp_os_us; - return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; + return (int64_t)(g_esp_os_us + soc_get_ccount() / g_esp_ticks_per_us); } diff --git a/components/esp8266/source/esp_wifi.c b/components/esp8266/source/esp_wifi.c index a7c3d9ba7..5524c3431 100644 --- a/components/esp8266/source/esp_wifi.c +++ b/components/esp8266/source/esp_wifi.c @@ -12,18 +12,121 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include +#include #include "sdkconfig.h" #include "esp_libc.h" #include "esp_system.h" #include "esp_wifi.h" -#include "internal/esp_wifi_internal.h" -#include "esp_socket.h" -#include "net/sockio.h" +#include "esp_log.h" +#include "esp_private/wifi.h" #include "phy.h" +#include "esp_supplicant/esp_wpa.h" +#include "esp_aio.h" + +#define TAG "wifi_init" const size_t _g_esp_wifi_ppt_task_stk_size = CONFIG_WIFI_PPT_TASKSTACK_SIZE; -esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); +#if CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET +const bool _g_esp_wifi_connect_open_router_when_pwd_is_set = true; +#else +const bool _g_esp_wifi_connect_open_router_when_pwd_is_set = false; +#endif + +#define EP_OFFSET 36 +int ieee80211_output_pbuf(esp_aio_t *aio); + +esp_err_t mac_init(void); + +ESP_EVENT_DEFINE_BASE(WIFI_EVENT); + +static void esp_wifi_set_debug_log() +{ + /* set WiFi log level and module */ +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE + uint32_t wifi_log_level = WIFI_LOG_ERROR; + uint32_t wifi_log_submodule = WIFI_LOG_SUBMODULE_NULL; +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_WARNING + wifi_log_level = WIFI_LOG_WARNING; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_INFO + wifi_log_level = WIFI_LOG_INFO; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_DEBUG + wifi_log_level = WIFI_LOG_DEBUG; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_VERBOSE + wifi_log_level = WIFI_LOG_VERBOSE; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_CORE + wifi_log_submodule |= WIFI_LOG_SUBMODULE_CORE; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_SCAN + wifi_log_submodule |= WIFI_LOG_SUBMODULE_SCAN; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_PM + wifi_log_submodule |= WIFI_LOG_SUBMODULE_PM; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_NVS + wifi_log_submodule |= WIFI_LOG_SUBMODULE_NVS; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_TRC + wifi_log_submodule |= WIFI_LOG_SUBMODULE_TRC; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_EBUF + wifi_log_submodule |= WIFI_LOG_SUBMODULE_EBUF; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_NET80211 + wifi_log_submodule |= WIFI_LOG_SUBMODULE_NET80211; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_TIMER + wifi_log_submodule |= WIFI_LOG_SUBMODULE_TIMER; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_ESPNOW + wifi_log_submodule |= WIFI_LOG_SUBMODULE_ESPNOW; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_MAC + wifi_log_submodule |= WIFI_LOG_SUBMODULE_MAC; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPA + wifi_log_submodule |= WIFI_LOG_SUBMODULE_WPA; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPS + wifi_log_submodule |= WIFI_LOG_SUBMODULE_WPS; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_AMPDU + wifi_log_submodule |= WIFI_LOG_SUBMODULE_AMPDU; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_AMSDU + wifi_log_submodule |= WIFI_LOG_SUBMODULE_AMSDU; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_FRAG + wifi_log_submodule |= WIFI_LOG_SUBMODULE_FRAG; +#endif +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_SUBMODULE_WPA2 + wifi_log_submodule |= WIFI_LOG_SUBMODULE_WPA2; +#endif + esp_wifi_internal_set_log_level(wifi_log_level); + esp_wifi_internal_set_log_mod(wifi_log_submodule); +#else + esp_wifi_internal_set_log_level(WIFI_LOG_ERROR); + esp_wifi_internal_set_log_mod(WIFI_LOG_SUBMODULE_NULL); +#endif /* CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE*/ +} + +esp_err_t esp_wifi_deinit(void) +{ + esp_err_t err = ESP_OK; + + esp_supplicant_deinit(); + err = esp_wifi_deinit_internal(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to deinit Wi-Fi driver (0x%x)", err); + return err; + } + return err; +} /** * @brief Init WiFi @@ -46,8 +149,31 @@ esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); */ esp_err_t esp_wifi_init(const wifi_init_config_t *config) { - esp_event_set_default_wifi_handlers(); - return esp_wifi_init_internal(config); + mac_init(); + + esp_wifi_set_rx_pbuf_mem_type(WIFI_RX_PBUF_DRAM); + + esp_err_t result = esp_wifi_init_internal(config); + if (result == ESP_OK) { + esp_wifi_set_debug_log(); + result = esp_supplicant_init(); + if (result != ESP_OK) { + ESP_LOGE(TAG, "Failed to init supplicant (0x%x)", result); + esp_err_t deinit_ret = esp_wifi_deinit(); + if (deinit_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to deinit Wi-Fi (0x%x)", deinit_ret); + } + + return result; + } + } + + result = tcpip_adapter_set_default_wifi_handlers(); + if (result != ESP_OK) { + ESP_LOGW(TAG, "Failed to set default Wi-Fi event handlers (0x%x)", result); + } + + return result; } void esp_deep_sleep_set_rf_option(uint8_t option) @@ -71,4 +197,43 @@ bool IRAM_ATTR esp_wifi_try_rate_from_high(void) { } #endif return false; -} \ No newline at end of file +} + +int wifi_internal_send_cb(esp_aio_t* aio) +{ + char* pb = (char*)aio->arg; + + if (pb) { + os_free(pb); + pb = NULL; + } + + return ESP_OK; +} + +int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, uint16_t len) +{ + esp_aio_t aio; + esp_err_t ret = ESP_OK; + uint8_t *dram_buffer = (uint8_t *)heap_caps_malloc(len + EP_OFFSET, MALLOC_CAP_8BIT); + if (!dram_buffer) { + return ESP_ERR_NO_MEM; + } + dram_buffer = ((uint8_t *)dram_buffer + EP_OFFSET); + memcpy(dram_buffer, buffer, len); + + aio.arg = (char *)dram_buffer - EP_OFFSET; + aio.cb = wifi_internal_send_cb; + aio.fd = wifi_if; + aio.pbuf = (char *)dram_buffer; + aio.len = len; + aio.ret = 0; + ret = ieee80211_output_pbuf(&aio); + + if(ret != 0) { + os_free(aio.arg); + } + + return ret; +} + diff --git a/components/esp8266/source/esp_wifi_os_adapter.c b/components/esp8266/source/esp_wifi_os_adapter.c index 519dc899f..f45cb89a4 100644 --- a/components/esp8266/source/esp_wifi_os_adapter.c +++ b/components/esp8266/source/esp_wifi_os_adapter.c @@ -17,7 +17,7 @@ #include "esp_libc.h" #include "esp_system.h" #include "esp_attr.h" -#include "esp_wifi_os_adapter.h" +#include "esp_wifi_osi.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -27,11 +27,7 @@ #include "nvs.h" -#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) -#include "esp_newlib.h" -#endif - -static void *task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio) +void *__wifi_task_create(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio) { portBASE_TYPE ret; xTaskHandle handle; @@ -40,152 +36,52 @@ static void *task_create_wrapper(void *task_func, const char *name, uint32_t sta return ret == pdPASS ? handle : NULL; } -static void task_delete_wrapper(void *task_handle) -{ - vTaskDelete(task_handle); -} - -static void task_yield_wrapper(void) +void __wifi_task_delete(void *task) { - portYIELD(); + vTaskDelete(task); } -static void task_yield_from_isr_wrapper(void) +void __wifi_task_yield_from_isr(void) { - portYIELD(); + portYIELD_FROM_ISR(); } -static void task_delay_wrapper(uint32_t tick) +void __wifi_task_delay(uint32_t tick) { vTaskDelay(tick); } -static void* task_get_current_task_wrapper(void) -{ - return (void *)xTaskGetCurrentTaskHandle(); -} - -static uint32_t task_get_max_priority_wrapper(void) +uint32_t __wifi_task_get_max_priority(void) { return (uint32_t)(configMAX_PRIORITIES); } -static uint32_t task_ms_to_tick_wrapper(uint32_t ms) +uint32_t __wifi_task_ms_to_ticks(uint32_t ms) { return (uint32_t)(ms / portTICK_RATE_MS); } -static void task_suspend_all_wrapper(void) +void __wifi_task_suspend_all(void) { vTaskSuspendAll(); } -static void task_resume_all_wrapper(void) +void __wifi_task_resume_all(void) { xTaskResumeAll(); } -static void os_init_wrapper(void) -{ -#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) - esp_newlib_init(); -#endif -} - -static void os_start_wrapper(void) -{ - vTaskStartScheduler(); -} - -static void *semphr_create_wrapper(uint32_t max, uint32_t init) -{ - return (void *)xSemaphoreCreateCounting(max, init); -} - -static void semphr_delete_wrapper(void *semphr) -{ - vSemaphoreDelete(semphr); -} - -static bool semphr_take_from_isr_wrapper(void *semphr, int *hptw) -{ - signed portBASE_TYPE ret; - - ret = xSemaphoreTakeFromISR(semphr, (signed portBASE_TYPE *)hptw); - - return ret == pdPASS ? true : false; -} - -static bool semphr_give_from_isr_wrapper(void *semphr, int *hptw) -{ - signed portBASE_TYPE ret; - - ret = xSemaphoreGiveFromISR(semphr, (signed portBASE_TYPE *)hptw); - - return ret == pdPASS ? true : false; -} - -static bool semphr_take_wrapper(void *semphr, uint32_t block_time_tick) -{ - signed portBASE_TYPE ret; - - if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { - ret = xSemaphoreTake(semphr, portMAX_DELAY); - } else { - ret = xSemaphoreTake(semphr, block_time_tick); - } - - return ret == pdPASS ? true : false; -} - -static bool semphr_give_wrapper(void *semphr) -{ - signed portBASE_TYPE ret; - - ret = xSemaphoreGive(semphr); - - return ret == pdPASS ? true : false; -} - -static void *mutex_create_wrapper(void) -{ - return (void *)xSemaphoreCreateRecursiveMutex(); -} - -static void mutex_delete_wrapper(void *mutex) -{ - vSemaphoreDelete(mutex); -} - -static bool mutex_lock_wrapper(void *mutex) -{ - signed portBASE_TYPE ret; - - ret = xSemaphoreTakeRecursive(mutex, portMAX_DELAY); - - return ret == pdPASS ? true : false; -} - -static bool mutex_unlock_wrapper(void *mutex) -{ - signed portBASE_TYPE ret; - - ret = xSemaphoreGiveRecursive(mutex); - - return ret == pdPASS ? true : false; -} - -static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size) +void *__wifi_queue_create(uint32_t queue_len, uint32_t item_size) { return (void *)xQueueCreate(queue_len, item_size); } -static void queue_delete_wrapper(void *queue) +void __wifi_queue_delete(void *queue) { vQueueDelete(queue); } -static bool queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick, uint32_t pos) +int __wifi_queue_send(void *queue, void *item, uint32_t block_time_tick, uint32_t pos) { signed portBASE_TYPE ret; BaseType_t os_pos; @@ -206,7 +102,7 @@ static bool queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick return ret == pdPASS ? true : false; } -static bool queue_send_from_isr_wrapper(void *queue, void *item, int *hptw) +int __wifi_queue_send_from_isr(void *queue, void *item, int *hptw) { signed portBASE_TYPE ret; @@ -215,7 +111,7 @@ static bool queue_send_from_isr_wrapper(void *queue, void *item, int *hptw) return ret == pdPASS ? true : false; } -static bool queue_recv_wrapper(void *queue, void *item, uint32_t block_time_tick) +int __wifi_queue_recv(void *queue, void *item, uint32_t block_time_tick) { signed portBASE_TYPE ret; @@ -228,187 +124,53 @@ static bool queue_recv_wrapper(void *queue, void *item, uint32_t block_time_tick return ret == pdPASS ? true : false; } -static bool queue_recv_from_isr_wrapper(void *queue, void *item, int *hptw) +uint32_t __wifi_queue_msg_num(void *queue) { - signed portBASE_TYPE ret; - - ret = xQueueReceiveFromISR(queue, item, (signed portBASE_TYPE *)hptw); - - return ret == pdPASS ? true : false; + return (uint32_t)uxQueueMessagesWaiting((const QueueHandle_t)queue); } -static uint32_t queue_msg_waiting_wrapper(void *queue) -{ - return (uint32_t)uxQueueMessagesWaiting(queue); -} - -static uint32_t get_free_heap_size_wrapper(void) -{ - return (uint32_t)esp_get_free_heap_size(); -} - -static void *timer_create_wrapper(const char *name, uint32_t period_ticks, bool auto_load, void *arg, void (*cb)(void *timer)) +void *__wifi_timer_create(const char *name, uint32_t period_ticks, bool auto_load, void *arg, void (*cb)(void *timer)) { return xTimerCreate(name, period_ticks, auto_load, arg, (tmrTIMER_CALLBACK)cb); } -static void *timer_get_arg_wrapper(void *timer) -{ - return pvTimerGetTimerID(timer); -} - -static bool timer_reset_wrapper(void *timer, uint32_t ticks) +int __wifi_timer_reset(void *timer, uint32_t ticks) { return xTimerReset(timer, ticks); } -static bool timer_stop_wrapper(void *timer, uint32_t ticks) +int __wifi_timer_stop(void *timer, uint32_t ticks) { return xTimerStop(timer, ticks); } -static bool timer_delete_wrapper(void *timer, uint32_t ticks) -{ - return xTimerDelete(timer, ticks); -} - -static void *malloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) -{ - uint32_t os_caps; - - if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) - os_caps = MALLOC_CAP_8BIT | MALLOC_CAP_DMA; - else - os_caps = MALLOC_CAP_32BIT; - - return _heap_caps_malloc(s, os_caps, file, line); -} - -static void *zalloc_wrapper(uint32_t s, uint32_t cap, const char *file, size_t line) +void *__wifi_task_top_sp(void) { - uint32_t os_caps; - - if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) - os_caps = MALLOC_CAP_8BIT | MALLOC_CAP_DMA; - else - os_caps = MALLOC_CAP_32BIT; - - return _heap_caps_zalloc(s, os_caps, file, line); -} - -static void *realloc_wrapper(void *ptr, uint32_t s, uint32_t cap, const char *file, size_t line) -{ - uint32_t os_caps; - - if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) - os_caps = MALLOC_CAP_8BIT | MALLOC_CAP_DMA; - else - os_caps = MALLOC_CAP_32BIT; - - return _heap_caps_realloc(ptr, s, os_caps, file, line); -} - -static void *calloc_wrapper(uint32_t cnt, uint32_t s, uint32_t cap, const char *file, size_t line) -{ - uint32_t os_caps; - - if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) - os_caps = MALLOC_CAP_8BIT | MALLOC_CAP_DMA; - else - os_caps = MALLOC_CAP_32BIT; + extern uint32_t **pxCurrentTCB; - return _heap_caps_calloc(cnt , s, os_caps, file, line); + return pxCurrentTCB[0]; } -static void free_wrapper(void *ptr, const char *file, size_t line) +void* __wifi_semphr_create(uint32_t max, uint32_t init) { - _heap_caps_free(ptr, file, line); + return (void*)xSemaphoreCreateCounting(max, init); } -static void srand_wrapper(uint32_t seed) +void __wifi_semphr_delete(void* semphr) { - /* empty function */ + vSemaphoreDelete(semphr); } -static int32_t rand_wrapper(void) +int32_t __wifi_semphr_take(void* semphr, uint32_t block_time_tick) { - return (int32_t)esp_random(); + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { + return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY); + } else { + return (int32_t)xSemaphoreTake(semphr, block_time_tick); + } } -void *osi_task_top_sp(void) +int32_t __wifi_semphr_give(void* semphr) { - extern uint32_t **pxCurrentTCB; - - return pxCurrentTCB[0]; -} - -const wifi_osi_funcs_t s_wifi_osi_funcs = { - .version = ESP_WIFI_OS_ADAPTER_VERSION, - - .task_create = task_create_wrapper, - .task_delete = task_delete_wrapper, - .task_yield = task_yield_wrapper, - .task_yield_from_isr = task_yield_from_isr_wrapper, - .task_delay = task_delay_wrapper, - .task_get_current_task = task_get_current_task_wrapper, - .task_get_max_priority = task_get_max_priority_wrapper, - - .task_ms_to_tick = task_ms_to_tick_wrapper, - - .task_suspend_all = task_suspend_all_wrapper, - .task_resume_all = task_resume_all_wrapper, - - .os_init = os_init_wrapper, - .os_start = os_start_wrapper, - - .semphr_create = semphr_create_wrapper, - .semphr_delete = semphr_delete_wrapper, - .semphr_take_from_isr = semphr_take_from_isr_wrapper, - .semphr_give_from_isr = semphr_give_from_isr_wrapper, - .semphr_take = semphr_take_wrapper, - .semphr_give = semphr_give_wrapper, - - .mutex_create = mutex_create_wrapper, - .mutex_delete = mutex_delete_wrapper, - .mutex_lock = mutex_lock_wrapper, - .mutex_unlock = mutex_unlock_wrapper, - - .queue_create = queue_create_wrapper, - .queue_delete = queue_delete_wrapper, - .queue_send = queue_send_wrapper, - .queue_send_from_isr = queue_send_from_isr_wrapper, - .queue_recv = queue_recv_wrapper, - .queue_recv_from_isr = queue_recv_from_isr_wrapper, - .queue_msg_waiting = queue_msg_waiting_wrapper, - - .timer_create = timer_create_wrapper, - .timer_get_arg = timer_get_arg_wrapper, - .timer_reset = timer_reset_wrapper, - .timer_stop = timer_stop_wrapper, - .timer_delete = timer_delete_wrapper, - - .malloc = malloc_wrapper, - .zalloc = zalloc_wrapper, - .realloc = realloc_wrapper, - .calloc = calloc_wrapper, - .free = free_wrapper, - .get_free_heap_size = get_free_heap_size_wrapper, - - .srand = srand_wrapper, - .rand = rand_wrapper, - - .nvs_set_i8 = nvs_set_i8, - .nvs_get_i8 = nvs_get_i8, - .nvs_set_u8 = nvs_set_u8, - .nvs_get_u8 = nvs_get_u8, - .nvs_set_u16 = nvs_set_u16, - .nvs_get_u16 = nvs_get_u16, - .nvs_open = nvs_open, - .nvs_close = nvs_close, - .nvs_commit = nvs_commit, - .nvs_set_blob = nvs_set_blob, - .nvs_get_blob = nvs_get_blob, - .nvs_erase_key = nvs_erase_key, - - .magic = ESP_WIFI_OS_ADAPTER_MAGIC, -}; \ No newline at end of file + return (int32_t)xSemaphoreGive(semphr); +} \ No newline at end of file diff --git a/components/esp8266/source/ets_printf.c b/components/esp8266/source/ets_printf.c index 06e90c46c..0df4e11bd 100644 --- a/components/esp8266/source/ets_printf.c +++ b/components/esp8266/source/ets_printf.c @@ -13,6 +13,8 @@ // limitations under the License. #include +#include +#include #include "sdkconfig.h" @@ -22,33 +24,286 @@ #include "esp8266/uart_register.h" #include "esp8266/rom_functions.h" -int IRAM_ATTR ets_putc(int c) +#ifdef CONFIG_ETS_PRINTF_EXIT_WHEN_FLASH_RW +#define ETS_PRINTF_ATTR IRAM_ATTR +#else +#define ETS_PRINTF_ATTR +#endif + +#ifndef CONFIG_ESP_CONSOLE_UART_NONE +static void uart_putc(int c) { while (1) { - uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(CONFIG_CONSOLE_UART_NUM)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); + uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(CONFIG_ESP_CONSOLE_UART_NUM)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) break; } - WRITE_PERI_REG(UART_FIFO(CONFIG_CONSOLE_UART_NUM) , c); + WRITE_PERI_REG(UART_FIFO(CONFIG_ESP_CONSOLE_UART_NUM) , c); +} +#else +#define uart_putc(_c) { } +#endif + +int __attribute__ ((weak)) ets_putc(int c) +{ +#ifdef CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF + if (c == '\n') + uart_putc('\r'); +#elif defined(CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR) + if (c == '\n') + c = '\r'; +#endif + + uart_putc(c); return c; } -int IRAM_ATTR ets_vprintf(const char *fmt, va_list ap) +#if defined(CONFIG_USING_NEW_ETS_VPRINTF) && !defined(BOOTLOADER_BUILD) + +#define FILL_0 0x01 +#define FILL_LEFT 0x02 +#define POINTOR 0x04 +#define ALTERNATE 0x08 +#define OUPUT_INT 0x10 +#define START 0x20 +#define END 0x40 + +#define VINT_STR_MAX 10 + +typedef union _val_cache { + uint8_t val8; + int32_t val32; + uint32_t val32u; + const char *valcp; +} val_cache_t; + +typedef struct _val_attr { + uint8_t type; + uint8_t state; + uint8_t fillbytes; + uint8_t precision; + + val_cache_t value; +} val_attr_t; + +#define isdigit(_c) ((_c <= '9') && (_c >= '0')) +#define fill_num(_attr) ((attr)->fillbytes) +#define isfill_0(_attr) (fill_num(_attr) && ((_attr)->state & FILL_0)) +#define isfill_left(_attr) (fill_num(_attr) && ((_attr)->state & FILL_LEFT)) +#define isstart(_attr) ((_attr)->state & START) + +static inline void ets_printf_ch_mutlti(uint32_t c, uint32_t len) +{ + while (len--) + ets_putc(c); +} + +static inline void ets_printf_buf(const char *s, uint32_t len) +{ + while (len--) + ets_putc(*s++); +} + +static int ets_printf_str(const val_attr_t * const attr) +{ + const char *s = attr->value.valcp; + s = s == NULL ? "" : s; + + if (fill_num(attr)) { + unsigned char left; + unsigned char len; + + while (*s != '\0') + s++; + len = s - attr->value.valcp; + left = fill_num(attr) > len ? fill_num(attr) - len : 0; + + if (!isfill_left(attr)) { + ets_printf_ch_mutlti(' ', left); + } + + ets_printf_buf(attr->value.valcp, len); + + if (isfill_left(attr)) { + ets_printf_ch_mutlti(' ', left); + } + } else { + while (*s != '\0') + ets_putc(*s++); + } + + return 0; +} + +static int ets_printf_int(val_attr_t * const attr, uint8_t hex) +{ + char buf[VINT_STR_MAX]; + unsigned char offset = VINT_STR_MAX; + + if (attr->value.val32u != 0) { + for (; attr->value.val32u > 0; attr->value.val32u /= hex) { + unsigned char c = attr->value.val32u % hex; + if (c < 10) + buf[--offset] = c + '0'; + else + buf[--offset] = c + 'a' - 10; + } + } else + buf[--offset] = '0'; + + if (fill_num(attr)) { + char fill_data = isfill_0(attr) ? '0' : ' '; + unsigned char len = fill_num(attr) - (VINT_STR_MAX - offset); + unsigned char left = fill_num(attr) > (VINT_STR_MAX - offset) ? len : 0; + + if (!isfill_left(attr)) { + ets_printf_ch_mutlti(fill_data, left); + } + + ets_printf_buf(&buf[offset], VINT_STR_MAX - offset); + + if (isfill_left(attr)) { + fill_data = ' '; + ets_printf_ch_mutlti(fill_data, left); + } + } else { + ets_printf_buf(&buf[offset], VINT_STR_MAX - offset); + } + + return 0; +} + +int ets_vprintf(const char *fmt, va_list va) +{ + for (; ;) { + const char *ps = fmt; + val_attr_t attr; + + while (*ps != '\0' && *ps != '%') + ets_putc(*ps++); + + if (*ps == '\0') + break; + + fmt = ps; + + memset(&attr, 0, sizeof(val_attr_t)); + + for (; ;) { + switch (*++ps) { + case '#': + attr.state |= ALTERNATE; + ps++; + break; + case '0'...'9': + if ((!isstart(&attr) || *(ps - 1) == '-') && *ps == '0') { + attr.state |= FILL_0; + } else { + if (attr.state & POINTOR) + attr.precision = attr.precision * 10 + *ps - '0'; + else + attr.fillbytes = attr.fillbytes * 10 + *ps - '0'; + } + break; + case '.': + attr.state |= POINTOR; + break; + case '-': + attr.state |= FILL_LEFT; + break; + default: + attr.type = *ps++; + attr.state |= END; + break; + } + + if (attr.state & END) + break; + + attr.state |= START; + } + + switch (attr.type) { + case 'c': + attr.value.val8 = (char)va_arg(va, int); + ets_putc(attr.value.val8); + break; + case 's': + attr.value.valcp = va_arg(va, const char *); + ets_printf_str(&attr); + break; + case 'i': + case 'd': + attr.value.val32 = va_arg(va, int); + if (attr.value.val32 < 0) { + ets_putc('-'); + attr.value.val32 = -attr.value.val32; + } + ets_printf_int(&attr, 10); + break; + case 'u': + attr.value.val32u = va_arg(va, unsigned int); + ets_printf_int(&attr, 10); + break; + case 'x': + attr.value.val32u = va_arg(va, unsigned int); + ets_printf_int(&attr, 16); + break; + case 'p': + ets_printf_buf("0x", 2); + attr.value.valcp = va_arg(va, const char *); + ets_printf_int(&attr, 16); + break; + case '%': + ets_putc('%'); + break; + default: + ets_putc('%'); + ps = fmt + 1; + break; + } + + fmt = ps; + } + + return 0; +} + +#else /* defined(CONFIG_USING_NEW_ETS_VPRINTF) && !defined(BOOTLOADER_BUILD) */ + +int ets_vprintf(const char *fmt, va_list ap) { return ets_io_vprintf(ets_putc, fmt, ap); } -/* Re-write ets_printf in SDK side, since ets_printf in ROM will use a global +#endif /* defined(CONFIG_USING_NEW_ETS_VPRINTF) && !defined(BOOTLOADER_BUILD) */ + +/** + * Re-write ets_printf in SDK side, since ets_printf in ROM will use a global * variable which address is in heap region of SDK side. If use ets_printf in ROM, - * this variable maybe re-write when heap alloc and modification.*/ -int IRAM_ATTR ets_printf(const char* fmt, ...) + * this variable maybe re-write when heap alloc and modification. + * + * Using new "ets_vprintf" costs stack without alignment and accuracy: + * just "fmt": 136 Bytes + * "%s": 172 Bytes + * "%p", "%d, "%i, "%u", "%x": 215 Bytes + */ +int ETS_PRINTF_ATTR ets_printf(const char *fmt, ...) { va_list ap; int ret; +#ifdef CONFIG_ETS_PRINTF_EXIT_WHEN_FLASH_RW + extern uint8_t FlashIsOnGoing; + + if (FlashIsOnGoing) { + return -1; + } +#endif + va_start(ap, fmt); ret = ets_vprintf(fmt, ap); va_end(ap); diff --git a/components/esp8266/source/event_default_handlers.c b/components/esp8266/source/event_default_handlers.c deleted file mode 100644 index a3ef8732d..000000000 --- a/components/esp8266/source/event_default_handlers.c +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "rom/ets_sys.h" - -#include "esp_err.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_event_loop.h" -#include "esp_system.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" - -#include "tcpip_adapter.h" -#include "esp_log.h" - -static const char* TAG = "event"; - -#define WIFI_API_CALL_CHECK(info, api_call, ret) \ -do{\ - esp_err_t __err = (api_call);\ - if ((ret) != __err) {\ - ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ - return __err;\ - }\ -} while(0) - -typedef esp_err_t (*system_event_handler_t)(system_event_t *e); - -static esp_err_t system_event_ap_start_handle_default(system_event_t *event); -static esp_err_t system_event_ap_stop_handle_default(system_event_t *event); -static esp_err_t system_event_sta_start_handle_default(system_event_t *event); -static esp_err_t system_event_sta_stop_handle_default(system_event_t *event); -static esp_err_t system_event_sta_connected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_got_ip_default(system_event_t *event); -static esp_err_t system_event_sta_lost_ip_default(system_event_t *event); - -/* Default event handler functions - - Any entry in this table which is disabled by config will have a NULL handler. -*/ -static system_event_handler_t default_event_handlers[SYSTEM_EVENT_MAX] = { 0 }; - -static esp_err_t system_event_sta_got_ip_default(system_event_t *event) -{ - ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, - IP2STR(&event->event_info.got_ip.ip_info.ip), - IP2STR(&event->event_info.got_ip.ip_info.netmask), - IP2STR(&event->event_info.got_ip.ip_info.gw)); - - return ESP_OK; -} - -static esp_err_t system_event_sta_lost_ip_default(system_event_t *event) -{ - ESP_LOGI(TAG, "station ip lost"); - return ESP_OK; -} - -esp_err_t system_event_ap_start_handle_default(system_event_t *event) -{ - tcpip_adapter_ip_info_t ap_ip; - uint8_t ap_mac[6]; - - WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); - tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, ap_mac, &ap_ip); - - return ESP_OK; -} - -esp_err_t system_event_ap_stop_handle_default(system_event_t *event) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); - - return ESP_OK; -} - -esp_err_t system_event_sta_start_handle_default(system_event_t *event) -{ - tcpip_adapter_ip_info_t sta_ip; - uint8_t sta_mac[6]; - - WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, sta_mac, &sta_ip); - - return ESP_OK; -} - -esp_err_t system_event_sta_stop_handle_default(system_event_t *event) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); - - return ESP_OK; -} - -esp_err_t system_event_sta_connected_handle_default(system_event_t *event) -{ - tcpip_adapter_dhcp_status_t status; - - tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status); - - if (status == TCPIP_ADAPTER_DHCP_INIT) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { - tcpip_adapter_ip_info_t sta_ip; - tcpip_adapter_ip_info_t sta_old_ip; - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip); - - if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask) || ip4_addr_isany_val(sta_ip.gw))) { - system_event_t evt; - - evt.event_id = SYSTEM_EVENT_STA_GOT_IP; - evt.event_info.got_ip.ip_changed = false; - - if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) { - evt.event_info.got_ip.ip_changed = true; - } - - memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); - tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - - esp_event_send(&evt); - ESP_LOGD(TAG, "static ip: ip changed=%d", evt.event_info.got_ip.ip_changed); - } else { - ESP_LOGE(TAG, "invalid static ip"); - } - } - - return ESP_OK; -} - -esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) -{ - tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); - return ESP_OK; -} - -static esp_err_t esp_system_event_debug(system_event_t *event) -{ - if (event == NULL) { - ESP_LOGE(TAG, "event is null!"); - printf("event is null!"); - return ESP_FAIL; - } - - switch (event->event_id) { - case SYSTEM_EVENT_WIFI_READY: { - ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY"); - break; - } - case SYSTEM_EVENT_SCAN_DONE: { - system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done; - ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d", scan_done->status, scan_done->number); - break; - } - case SYSTEM_EVENT_STA_START: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START"); - break; - } - case SYSTEM_EVENT_STA_STOP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP"); - break; - } - case SYSTEM_EVENT_STA_CONNECTED: { - system_event_sta_connected_t *connected = &event->event_info.connected; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \ - connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode); - break; - } - case SYSTEM_EVENT_STA_DISCONNECTED: { - system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d", \ - disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason); - break; - } - case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { - system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode); - break; - } - case SYSTEM_EVENT_STA_GOT_IP: { - system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR, - IP2STR(&got_ip->ip_info.ip), - IP2STR(&got_ip->ip_info.netmask), - IP2STR(&got_ip->ip_info.gw)); - break; - } - case SYSTEM_EVENT_STA_LOST_IP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_FAILED: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_PIN: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); - break; - } - case SYSTEM_EVENT_AP_START: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START"); - break; - } - case SYSTEM_EVENT_AP_STOP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP"); - break; - } - case SYSTEM_EVENT_AP_STACONNECTED: { - system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \ - MAC2STR(staconnected->mac), staconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STADISCONNECTED: { - system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \ - MAC2STR(stadisconnected->mac), stadisconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STAIPASSIGNED: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED"); - break; - } - case SYSTEM_EVENT_AP_PROBEREQRECVED: { - system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ - ap_probereqrecved->rssi, \ - MAC2STR(ap_probereqrecved->mac)); - break; - } -#if ESP_EVENT_IPV6 - case SYSTEM_EVENT_GOT_IP6: { - ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - IP6_ADDR_BLOCK1(addr), - IP6_ADDR_BLOCK2(addr), - IP6_ADDR_BLOCK3(addr), - IP6_ADDR_BLOCK4(addr), - IP6_ADDR_BLOCK5(addr), - IP6_ADDR_BLOCK6(addr), - IP6_ADDR_BLOCK7(addr), - IP6_ADDR_BLOCK8(addr)); - break; - } -#endif - - default: { - ESP_LOGW(TAG, "unexpected system event %d!", event->event_id); - break; - } - } - - return ESP_OK; -} - -esp_err_t esp_event_process_default(system_event_t *event) -{ - if (event == NULL) { - ESP_LOGE(TAG, "Error: event is null!"); - return ESP_FAIL; - } - - esp_system_event_debug(event); - if ((event->event_id < SYSTEM_EVENT_MAX)) { - if (default_event_handlers[event->event_id] != NULL) { - ESP_LOGV(TAG, "enter default callback"); - default_event_handlers[event->event_id](event); - ESP_LOGV(TAG, "exit default callback"); - } - } else { - ESP_LOGE(TAG, "mismatch or invalid event, id=%d", event->event_id); - return ESP_FAIL; - } - return ESP_OK; -} - -void esp_event_set_default_wifi_handlers() -{ - default_event_handlers[SYSTEM_EVENT_STA_START] = system_event_sta_start_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_STOP] = system_event_sta_stop_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_CONNECTED] = system_event_sta_connected_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_DISCONNECTED] = system_event_sta_disconnected_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_GOT_IP] = system_event_sta_got_ip_default; - default_event_handlers[SYSTEM_EVENT_STA_LOST_IP] = system_event_sta_lost_ip_default; - default_event_handlers[SYSTEM_EVENT_AP_START] = system_event_ap_start_handle_default; - default_event_handlers[SYSTEM_EVENT_AP_STOP] = system_event_ap_stop_handle_default; - - //esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop); -} \ No newline at end of file diff --git a/components/esp8266/source/event_loop.c b/components/esp8266/source/event_loop.c deleted file mode 100644 index de5d3daf3..000000000 --- a/components/esp8266/source/event_loop.c +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "esp_err.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_event_loop.h" -#include "esp_wifi_osi.h" - -#include "esp_log.h" -#include "sdkconfig.h" - -static const char* TAG = "event"; -static bool s_event_init_flag = false; -static void *s_event_queue = NULL; -static system_event_cb_t s_event_handler_cb = NULL; -static void *s_event_ctx = NULL; - -static esp_err_t esp_event_post_to_user(system_event_t *event) -{ - if (s_event_handler_cb) { - return (*s_event_handler_cb)(s_event_ctx, event); - } - return ESP_OK; -} - -static void esp_event_loop_task(void *pvParameters) -{ - while (1) { - system_event_t evt; - if (wifi_queue_recv(s_event_queue, &evt, OSI_FUNCS_TIME_BLOCKING) == pdPASS) { - esp_err_t ret = esp_event_process_default(&evt); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "default event handler failed!"); - } - ret = esp_event_post_to_user(&evt); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "post event to user fail!"); - } - } - } -} - -system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) -{ - system_event_cb_t old_cb = s_event_handler_cb; - s_event_handler_cb = cb; - s_event_ctx = ctx; - return old_cb; -} - -esp_err_t esp_event_send(system_event_t *event) -{ - if (s_event_queue == NULL) { - ESP_LOGE(TAG, "Event loop not initialized via esp_event_loop_init, but esp_event_send called"); - return ESP_ERR_INVALID_STATE; - } - - int ret = wifi_queue_send(s_event_queue, event, 0, OSI_QUEUE_SEND_BACK); - if (ret != true) { - if (event) { - ESP_LOGE(TAG, "e=%d f", event->event_id); - } else { - ESP_LOGE(TAG, "e null"); - } - return ESP_FAIL; - } - return ESP_OK; -} - -QueueHandle_t esp_event_loop_get_queue(void) -{ - return s_event_queue; -} - -esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx) -{ - if (s_event_init_flag) { - return ESP_FAIL; - } - s_event_handler_cb = cb; - s_event_ctx = ctx; - s_event_queue = wifi_queue_create(32, sizeof(system_event_t)); - if(s_event_queue == NULL) - return ESP_ERR_NO_MEM; - if(wifi_task_create(esp_event_loop_task, "esp_event_loop_task", EVENT_LOOP_STACKSIZE, NULL, wifi_task_get_max_priority() - 5) == NULL) { - return ESP_ERR_NO_MEM; - } - s_event_handler_cb = cb; - s_event_ctx = ctx; - s_event_init_flag = true; - return ESP_OK; -} \ No newline at end of file diff --git a/components/esp8266/source/hw_random.c b/components/esp8266/source/hw_random.c new file mode 100644 index 000000000..be875f26c --- /dev/null +++ b/components/esp8266/source/hw_random.c @@ -0,0 +1,40 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include +#include "esp_system.h" +#include "esp8266/eagle_soc.h" + +extern unsigned int adc_rand_noise; +uint32_t esp_random(void) +{ + return (adc_rand_noise ^ REG_READ(WDEV_RAND)); +} + +void esp_fill_random(void *buf, size_t len) +{ + assert(buf != NULL); + uint8_t *buf_bytes = (uint8_t *)buf; + while (len > 0) { + uint32_t word = esp_random(); + uint32_t to_copy = MIN(sizeof(word), len); + memcpy(buf_bytes, &word, to_copy); + buf_bytes += to_copy; + len -= to_copy; + } +} diff --git a/components/esp8266/source/phy.h b/components/esp8266/source/phy.h index 32c5376d4..cb549b384 100644 --- a/components/esp8266/source/phy.h +++ b/components/esp8266/source/phy.h @@ -26,9 +26,13 @@ uint8_t phy_check_data_table(uint32_t *table, uint8_t, uint8_t); void phy_afterwake_set_rfoption(uint8_t); +void phy_set_powerup_option(uint8_t); + void write_data_to_rtc(uint8_t *); void get_data_from_rtc(uint8_t *); +int register_chipv6_phy(uint8_t* ); +void phy_disable_agc(); uint8_t chip_init(uint8_t* init_data, uint8_t *mac, uint32_t uart_baudrate); diff --git a/components/esp8266/source/phy_init.c b/components/esp8266/source/phy_init.c index 099fb45d5..21563f8bb 100644 --- a/components/esp8266/source/phy_init.c +++ b/components/esp8266/source/phy_init.c @@ -17,6 +17,7 @@ #include #include "rom/ets_sys.h" +#include "rom/uart.h" #include "esp_err.h" #include "esp_phy_init.h" @@ -27,27 +28,29 @@ #include "nvs_flash.h" #include "sdkconfig.h" -#include "phy_init_data.h" +#include "esp_private/phy_init_data.h" #include "phy.h" -static const char *TAG = "phy_init"; +#include "driver/rtc.h" -static uint8_t phy_check_calibration_data(uint8_t *rf_cal_data) +static const char* TAG = "phy_init"; + +static uint8_t phy_check_calibration_data(uint8_t* rf_cal_data) { #define CHECK_NUM 26 #define CHIP_ID_L 24 #define CHIP_ID_H 25 uint8_t i; - uint32_t *cal_data_word = (uint32_t *)rf_cal_data; + uint32_t* cal_data_word = (uint32_t*)rf_cal_data; uint32_t check_sum = 0; /* L: flag_1[79:76], version[59:56], mac_map[55:48], mac_l[47:24] */ uint32_t chip_id_l = ((REG_READ(0x3FF00058) & 0xF000) << 16) | - (REG_READ(0x3ff00054) & 0xFFFFFFF); + (REG_READ(0x3ff00054) & 0xFFFFFFF); /* H: mac_l[31:24], mac_h[119:96] */ uint32_t chip_id_h = (REG_READ(0x3FF00050) & 0xFF000000) | - (REG_READ(0x3ff0005C) & 0xFFFFFF); + (REG_READ(0x3ff0005C) & 0xFFFFFF); cal_data_word[CHIP_ID_L] = chip_id_l; cal_data_word[CHIP_ID_H] = chip_id_h; @@ -63,28 +66,47 @@ static uint8_t phy_check_calibration_data(uint8_t *rf_cal_data) /* ToDo: use rx_gain_dc_table in nvs, need to modify internal libraries */ uint32_t rx_gain_dc_table[125]; -esp_err_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, esp_phy_calibration_mode_t mode, - esp_phy_calibration_data_t *calibration_data, phy_rf_module_t module) +esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode, + esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module) { esp_err_t status = ESP_OK; uint8_t sta_mac[6]; uint8_t *local_init_data = calloc(1, 256); memcpy(local_init_data, init_data->params, 128); + memcpy(local_init_data + 128, calibration_data->rf_cal_data, 128); - extern uint32_t *phy_rx_gain_dc_table; + extern uint32_t* phy_rx_gain_dc_table; phy_rx_gain_dc_table = calibration_data->rx_gain_dc_table; uint8_t cal_data_check = phy_check_calibration_data(calibration_data->rf_cal_data) || - phy_check_data_table(phy_rx_gain_dc_table, 125, 1); + phy_check_data_table(phy_rx_gain_dc_table, 125, 1); phy_afterwake_set_rfoption(1); if (!cal_data_check) { + phy_set_powerup_option(1); write_data_to_rtc(calibration_data->rf_cal_data); + } else { + phy_set_powerup_option(3); } esp_efuse_mac_get_default(sta_mac); - chip_init(local_init_data, sta_mac, CONFIG_CONSOLE_UART_BAUDRATE); + + /** + * The API "register_chipv6_phy" will modify the APB frequency to 80MHz, + * so UARTs must be flush here, then reconfigurate the UART frequency dividor + */ + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); + + int ret = register_chipv6_phy(local_init_data); + if (ret) { + ESP_LOGI(TAG, "phy register error, ret:%d", ret); + } + + phy_disable_agc(); + + ESP_LOGI(TAG, "phy ver: %d_%d", (READ_PERI_REG(0x6000107C)>>16)&0xFFF, READ_PERI_REG(0x6000107C)>>28); get_data_from_rtc((uint8_t *)calibration_data); memcpy(rx_gain_dc_table, calibration_data->rx_gain_dc_table, 4 * 125); @@ -95,9 +117,11 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t *init_data, esp_phy_calibrat if (cal_data_check == ESP_CAL_DATA_CHECK_FAIL) { #ifdef CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE ESP_LOGW(TAG, "saving new calibration data because of checksum failure, mode(%d)", mode); + if (mode != PHY_RF_CAL_FULL) { esp_phy_store_cal_data_to_nvs(calibration_data); } + #endif } @@ -115,9 +139,9 @@ esp_err_t esp_phy_rf_deinit(phy_rf_module_t module) #if CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION #include "esp_partition.h" -const esp_phy_init_data_t *esp_phy_get_init_data() +const esp_phy_init_data_t* esp_phy_get_init_data() { - const esp_partition_t *partition = esp_partition_find_first( + const esp_partition_t* partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL); if (partition == NULL) { @@ -128,7 +152,7 @@ const esp_phy_init_data_t *esp_phy_get_init_data() ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address); size_t init_data_store_length = sizeof(phy_init_magic_pre) + sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post); - uint8_t *init_data_store = (uint8_t *) malloc(init_data_store_length); + uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length); if (init_data_store == NULL) { ESP_LOGE(TAG, "failed to allocate memory for PHY init data"); @@ -150,25 +174,25 @@ const esp_phy_init_data_t *esp_phy_get_init_data() } ESP_LOGD(TAG, "PHY data partition validated"); - return (const esp_phy_init_data_t *)(init_data_store + sizeof(phy_init_magic_pre)); + return (const esp_phy_init_data_t*)(init_data_store + sizeof(phy_init_magic_pre)); } -void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) +void esp_phy_release_init_data(const esp_phy_init_data_t* init_data) { - free((uint8_t *) init_data - sizeof(phy_init_magic_pre)); + free((uint8_t*) init_data - sizeof(phy_init_magic_pre)); } #else // CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION // phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data -const esp_phy_init_data_t *esp_phy_get_init_data() +const esp_phy_init_data_t* esp_phy_get_init_data() { ESP_LOGD(TAG, "loading PHY init data from application binary"); return &phy_init_data; } -void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) +void esp_phy_release_init_data(const esp_phy_init_data_t* init_data) { // no-op } @@ -176,19 +200,19 @@ void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) // PHY calibration data handling functions -static const char *PHY_NAMESPACE = "phy"; -static const char *PHY_CAL_DATA_KEY = "cal_data"; -static const char *PHY_RX_GAIN_DC_TABLE_KEY = "dc_table"; +static const char* PHY_NAMESPACE = "phy"; +static const char* PHY_CAL_DATA_KEY = "cal_data"; +static const char* PHY_RX_GAIN_DC_TABLE_KEY = "dc_table"; -static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, - esp_phy_calibration_data_t *out_cal_data); +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle, + esp_phy_calibration_data_t* out_cal_data); -static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, - const esp_phy_calibration_data_t *cal_data); +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle, + const esp_phy_calibration_data_t* cal_data); -esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t *out_cal_data) +esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data) { - nvs_handle handle; + nvs_handle_t handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); if (err == ESP_ERR_NVS_NOT_INITIALIZED) { @@ -204,9 +228,9 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t *out_cal_dat return err; } -esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t *cal_data) +esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data) { - nvs_handle handle; + nvs_handle_t handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle); if (err != ESP_OK) { @@ -219,8 +243,8 @@ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t *cal_da } } -static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, - esp_phy_calibration_data_t *out_cal_data) +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle, + esp_phy_calibration_data_t* out_cal_data) { esp_err_t err; @@ -254,8 +278,8 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, return ESP_OK; } -static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, - const esp_phy_calibration_data_t *cal_data) +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle, + const esp_phy_calibration_data_t* cal_data) { esp_err_t err; @@ -284,15 +308,15 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, void esp_phy_load_cal_and_init(phy_rf_module_t module) { - esp_phy_calibration_data_t *cal_data = - (esp_phy_calibration_data_t *) calloc(sizeof(esp_phy_calibration_data_t), 1); + esp_phy_calibration_data_t* cal_data = + (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); if (cal_data == NULL) { ESP_LOGE(TAG, "failed to allocate memory for RF calibration data"); abort(); } - const esp_phy_init_data_t *init_data = esp_phy_get_init_data(); + const esp_phy_init_data_t* init_data = esp_phy_get_init_data(); if (init_data == NULL) { ESP_LOGE(TAG, "failed to obtain PHY init data"); @@ -329,3 +353,64 @@ void esp_phy_load_cal_and_init(phy_rf_module_t module) free(cal_data); // PHY maintains a copy of calibration data, so we can free this } + +uint16_t esp_wifi_get_vdd33(void) +{ + if (phy_init_data.params[107] != 0xFF) { + ESP_LOGE(TAG, "Please set VDD33 const to 0xff"); + return 0xFFFF; + } + + extern uint16_t phy_get_vdd33(); + uint16_t ret = phy_get_vdd33(); + + if (ret != 0xFFFF) { + ret = ret * 12 / 11; + } + + return ret; +} + +void esp_wifi_set_max_tx_power_via_vdd33(uint16_t vdd33) +{ + extern void phy_vdd33_set_tpw(uint16_t vdd33); + phy_vdd33_set_tpw(vdd33); +} + +/** + * @brief Just for compiling + */ +int phy_printf(const char *fmt, ...) +{ + return 0; +} + +void esp_phy_init_clk(void) +{ + uint8_t buf[128]; + const esp_phy_init_data_t *init_data; +#ifdef CONFIG_CONSOLE_UART_BAUDRATE + const uint32_t uart_baudrate = CONFIG_CONSOLE_UART_BAUDRATE; +#else + const uint32_t uart_baudrate = 74880; // ROM default baudrate +#endif + extern int rtc_init(void); + + init_data = esp_phy_get_init_data(); + if (init_data == NULL) { + ESP_LOGE(TAG, "failed to obtain PHY init data"); + abort(); + } + memcpy(buf, init_data->params, 128); + + uart_tx_wait_idle(0); + uart_div_modify(0, UART_CLK_FREQ / uart_baudrate); + + uart_tx_wait_idle(1); + uart_div_modify(1, UART_CLK_FREQ / uart_baudrate); + + rtc_init(); + rtc_init_clk(buf); + + esp_phy_release_init_data(init_data); +} diff --git a/components/esp8266/source/reset_reason.c b/components/esp8266/source/reset_reason.c new file mode 100644 index 000000000..1bac407af --- /dev/null +++ b/components/esp8266/source/reset_reason.c @@ -0,0 +1,161 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "sdkconfig.h" +#include +#include "esp_system.h" +#include "esp_private/esp_system_internal.h" +#include "esp8266/rtc_register.h" +#include "esp8266/rom_functions.h" +#include "esp_log.h" +#include "esp_libc.h" + +#define RTC_RESET_SW_CAUSE_REG RTC_STORE0 +#define RTC_RESET_HW_CAUSE_REG RTC_STATE1 +#define RTC_WAKEUP_HW_CAUSE_REG RTC_STATE2 + +#define RTC_RESET_HW_CAUSE_LSB 0 +#define RTC_RESET_HW_CAUSE_MSB 3 + +#define RTC_WAKEUP_HW_CAUSE_LSB 8 +#define RTC_WAKEUP_HW_CAUSE_MSB 13 + +static const char *TAG = "reset_reason"; +static uint32_t s_reset_reason; + +static inline void esp_reset_reason_clear_hint() +{ + rtc_sys_info.hint = 0; +} + +static inline uint32_t esp_reset_reason_get_hint(uint32_t hw_reset) +{ + if (hw_reset == POWERON_RESET && ((rtc_sys_info.hint != ESP_RST_SW) && (rtc_sys_info.hint != ESP_RST_FAST_SW))) + rtc_sys_info.hint = 0; + + return rtc_sys_info.hint; +} + +static inline uint32_t esp_rtc_get_reset_reason(void) +{ + return GET_PERI_REG_BITS(RTC_RESET_HW_CAUSE_REG, RTC_RESET_HW_CAUSE_MSB, RTC_RESET_HW_CAUSE_LSB); +} + +#if CONFIG_RESET_REASON_CHECK_WAKEUP +static inline uint32_t esp_rtc_get_wakeup_reason(void) +{ + return GET_PERI_REG_BITS(RTC_WAKEUP_HW_CAUSE_REG, RTC_WAKEUP_HW_CAUSE_MSB, RTC_WAKEUP_HW_CAUSE_LSB); +} +#endif + +static inline uint32_t get_reset_reason(uint32_t rtc_reset_reason, uint32_t reset_reason_hint) +{ + switch (rtc_reset_reason) { + case POWERON_RESET: + if (reset_reason_hint == ESP_RST_SW || + reset_reason_hint == ESP_RST_FAST_SW) + return reset_reason_hint; + return ESP_RST_POWERON; + case EXT_RESET: + if (reset_reason_hint == ESP_RST_DEEPSLEEP) { + return reset_reason_hint; + } + return ESP_RST_EXT; + case SW_RESET: + if (reset_reason_hint == ESP_RST_PANIC || + reset_reason_hint == ESP_RST_BROWNOUT || + reset_reason_hint == ESP_RST_TASK_WDT) { + return reset_reason_hint; + } + return ESP_RST_SW; + case DEEPSLEEP_RESET: + return ESP_RST_DEEPSLEEP; + case OWDT_RESET: + return ESP_RST_WDT; + case SDIO_RESET: + return ESP_RST_SDIO; + default: + return ESP_RST_UNKNOWN; + } +} + +/** + * Internal function to initialize SoC reset reason at system initialization + */ +static void __esp_reset_reason_init(int init) +{ + const uint32_t hw_reset = esp_rtc_get_reset_reason(); +#if CONFIG_RESET_REASON_CHECK_WAKEUP + const uint32_t hw_wakeup = esp_rtc_get_wakeup_reason(); +#else + const uint32_t hw_wakeup = 0; +#endif + const uint32_t hint = esp_reset_reason_get_hint(hw_reset); + + s_reset_reason = get_reset_reason(hw_reset, hint); + if (init && hint != ESP_RST_UNKNOWN) { + esp_reset_reason_clear_hint(); + } + + if (init) + ESP_LOGD(TAG, "RTC reset %u wakeup %u store %u, reason is %u", hw_reset, hw_wakeup, hint, s_reset_reason); +} + +/** + * @brief Internal function to get SoC reset reason at system initialization + */ +void esp_reset_reason_init(void) +{ + __esp_reset_reason_init(1); +} + +#if CONFIG_RESET_REASON + +/** + * @brief Internal function to set reset reason hint + */ +void esp_reset_reason_set_hint(esp_reset_reason_t hint) +{ + rtc_sys_info.hint = hint; +} + +/** + * @brief Get reason of last reset + */ +esp_reset_reason_t esp_reset_reason(void) +{ + return (esp_reset_reason_t)s_reset_reason; +} + +#else /* CONFIG_RESET_REASON */ + +/** + * null function for pass compiling + */ +void esp_reset_reason_set_hint(esp_reset_reason_t hint) +{ + +} + +#endif /* CONFIG_RESET_REASON */ + +/** + * Get reason of last reset but not clear it for next reset + */ +esp_reset_reason_t esp_reset_reason_early(void) +{ + __esp_reset_reason_init(0); + + return (esp_reset_reason_t)s_reset_reason; +} diff --git a/components/esp8266/source/rom.c b/components/esp8266/source/rom.c new file mode 100644 index 000000000..d8aa83db8 --- /dev/null +++ b/components/esp8266/source/rom.c @@ -0,0 +1,38 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rom/uart.h" + +void uart_tx_wait_idle(uint8_t uart_no) +{ + uint32_t tx_bytes; + uint32_t baudrate, byte_delay_us; + uart_dev_t *const UART[2] = {&uart0, &uart1}; + uart_dev_t *const uart = UART[uart_no]; + + baudrate = (UART_CLK_FREQ / (uart->clk_div.val & 0xFFFFF)); + byte_delay_us = (uint32_t)(10000000 / baudrate); + + do { + tx_bytes = uart->status.txfifo_cnt; + /* either tx count or state is non-zero */ + } while (tx_bytes); + + ets_delay_us(byte_delay_us); +} + +void uart_disable_swap_io(void) +{ + CLEAR_PERI_REG_MASK(UART_SWAP_REG, 0x4); +} diff --git a/components/esp8266/source/smartconfig.c b/components/esp8266/source/smartconfig.c new file mode 100644 index 000000000..57486c559 --- /dev/null +++ b/components/esp8266/source/smartconfig.c @@ -0,0 +1,83 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_log.h" +#include "esp_event_base.h" +#include "esp_private/wifi.h" +#include "esp_smartconfig.h" +#include "smartconfig_ack.h" + +/* Smartconfig events definitions */ +ESP_EVENT_DEFINE_BASE(SC_EVENT); + +static const char* TAG = "smartconfig"; + +static void handler_got_ssid_passwd(void* arg, esp_event_base_t base, int32_t event_id, void* data) +{ + smartconfig_event_got_ssid_pswd_t* evt = (smartconfig_event_got_ssid_pswd_t*)data; + uint8_t ssid[33] = { 0 }; + uint8_t password[65] = { 0 }; + uint8_t cellphone_ip[4]; + esp_err_t err = ESP_OK; + + memcpy(ssid, evt->ssid, sizeof(evt->ssid)); + memcpy(password, evt->password, sizeof(evt->password)); + memcpy(cellphone_ip, evt->cellphone_ip, sizeof(evt->cellphone_ip)); + + ESP_LOGD(TAG, "SSID:%s", ssid); + ESP_LOGD(TAG, "PASSWORD:%s", password); + ESP_LOGD(TAG, "Phone ip: %d.%d.%d.%d\n", cellphone_ip[0], cellphone_ip[1], cellphone_ip[2], cellphone_ip[3]); + + err = sc_send_ack_start(evt->type, evt->token, evt->cellphone_ip); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Send smartconfig ACK error: %d", err); + } +} + +esp_err_t esp_smartconfig_start(const smartconfig_start_config_t* config) +{ + esp_err_t err = ESP_OK; + + err = esp_event_handler_register(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd, NULL); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Register smartconfig default event handler fail!"); + return err; + } + + err = esp_smartconfig_internal_start(config); + + if (err != ESP_OK) { + esp_event_handler_unregister(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd); + } + + return err; +} + +esp_err_t esp_smartconfig_stop(void) +{ + esp_err_t err = ESP_OK; + + err = esp_smartconfig_internal_stop(); + + if (err == ESP_OK) { + sc_send_ack_stop(); + esp_event_handler_unregister(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd); + } + + return err; +} \ No newline at end of file diff --git a/components/esp8266/source/smartconfig_ack.c b/components/esp8266/source/smartconfig_ack.c new file mode 100644 index 000000000..34bd8eb30 --- /dev/null +++ b/components/esp8266/source/smartconfig_ack.c @@ -0,0 +1,243 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * After station connects to AP and gets IP address by smartconfig, + * it will use UDP to send 'ACK' to cellphone. + */ + +#include +#include +#include + +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "tcpip_adapter.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_smartconfig.h" +#include "smartconfig_ack.h" +#include "lwip/inet.h" + +#define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */ +#define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */ + +#define SC_ACK_TOUCH_DEVICE_PORT 7001 /*!< ESPTOUCH UDP port of server on device */ +#define SC_ACK_TOUCH_SERVER_PORT 18266 /*!< ESP touch UDP port of server on cellphone */ +#define SC_ACK_TOUCH_V2_SERVER_PORT(i) (18266+i*10000) /*!< ESP touch_v2 UDP port of server on cellphone */ +#define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */ +#define SC_ACK_AIRKISS_DEVICE_PORT 10001 /*!< Airkiss UDP port of server on device */ +#define SC_ACK_TIMEOUT 1500 /*!< Airkiss and ESP touch_v2 read data timout millisecond */ + +#define SC_ACK_TOUCH_LEN 11 /*!< Length of ESP touch ACK context */ +#define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */ + +#define SC_ACK_MAX_COUNT 60 /*!< Maximum count of sending smartconfig ACK */ + +/** + * @brief Smartconfig parameters passed to sc_ack_send call. + */ +typedef struct sc_ack { + smartconfig_type_t type; /*!< Smartconfig type(ESPTouch or AirKiss) */ + struct { + uint8_t token; /*!< Smartconfig token from the cellphone */ + uint8_t mac[6]; /*!< MAC address of station */ + uint8_t ip[4]; /*!< IP address of cellphone */ + } ctx; +} sc_ack_t; + +static const char* TAG = "smartconfig"; + +/* Flag to indicate sending smartconfig ACK or not. */ +static bool s_sc_ack_send = false; + +static int sc_ack_send_get_errno(int fd) +{ + int sock_errno = 0; + u32_t optlen = sizeof(sock_errno); + + getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + + return sock_errno; +} + +static void sc_ack_send_task(void* pvParameters) +{ + sc_ack_t* ack = (sc_ack_t*)pvParameters; + tcpip_adapter_ip_info_t local_ip; + uint8_t remote_ip[4]; + memcpy(remote_ip, ack->ctx.ip, sizeof(remote_ip)); + struct sockaddr_in server_addr; + socklen_t sin_size = sizeof(server_addr); + int send_sock = -1; + int optval = 1; + int sendlen; + int ack_len = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN; + uint8_t packet_count = 1; + int err; + int ret; + int remote_port = 0; + + if (ack->type == SC_TYPE_ESPTOUCH) { + remote_port = SC_ACK_TOUCH_SERVER_PORT; + } else if (ack->type == SC_TYPE_ESPTOUCH_V2) { + uint8_t port_bit = ack->ctx.token; + if(port_bit > 3) { + port_bit = 0; + } + remote_port = SC_ACK_TOUCH_V2_SERVER_PORT(port_bit); + memset(remote_ip, 0xFF, sizeof(remote_ip)); + } else { + remote_port = SC_ACK_AIRKISS_SERVER_PORT; + } + + bzero(&server_addr, sizeof(struct sockaddr_in)); + server_addr.sin_family = AF_INET; + memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(remote_ip)); + server_addr.sin_port = htons(remote_port); + + esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac); + + vTaskDelay(200 / portTICK_RATE_MS); + + while (s_sc_ack_send) { + /* Get local IP address of station */ + ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip); + + if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) { + /* If ESP touch, smartconfig ACK contains local IP address. */ + if (ack->type == SC_TYPE_ESPTOUCH) { + memcpy(ack->ctx.ip, &local_ip.ip.addr, 4); + } + + /* Create UDP socket. */ + send_sock = socket(AF_INET, SOCK_DGRAM, 0); + + if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) { + ESP_LOGE(TAG, "Creat udp socket failed"); + goto _end; + } + + setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int)); + + if (ack->type == SC_TYPE_AIRKISS || ack->type == SC_TYPE_ESPTOUCH_V2) { + char data = 0; + struct sockaddr_in local_addr, from; + socklen_t sockadd_len = sizeof(struct sockaddr); + struct timeval timeout = { + SC_ACK_TIMEOUT / 1000, + SC_ACK_TIMEOUT % 1000 * 1000 + }; + + bzero(&local_addr, sizeof(struct sockaddr_in)); + bzero(&from, sizeof(struct sockaddr_in)); + local_addr.sin_family = AF_INET; + local_addr.sin_addr.s_addr = INADDR_ANY; + if (ack->type == SC_TYPE_AIRKISS) { + local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT); + } else { + local_addr.sin_port = htons(SC_ACK_TOUCH_DEVICE_PORT); + } + bind(send_sock, (struct sockaddr*)&local_addr, sockadd_len); + setsockopt(send_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + recvfrom(send_sock, &data, 1, 0, (struct sockaddr*)&from, &sockadd_len); + + if (from.sin_addr.s_addr != INADDR_ANY) { + memcpy(remote_ip, &from.sin_addr, 4); + server_addr.sin_addr.s_addr = from.sin_addr.s_addr; + ESP_LOGI(TAG, "cellphone_ip: %s", inet_ntoa(server_addr.sin_addr)); + } else { + server_addr.sin_addr.s_addr = INADDR_BROADCAST; + } + } + + uint32_t ip_addr = server_addr.sin_addr.s_addr; + while (s_sc_ack_send) { + /* Send smartconfig ACK every 100ms. */ + vTaskDelay(100 / portTICK_RATE_MS); + if (ip_addr != INADDR_BROADCAST) { + sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + server_addr.sin_addr.s_addr = INADDR_BROADCAST; + sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + server_addr.sin_addr.s_addr = ip_addr; + } else { + sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + } + + if (sendlen <= 0) { + err = sc_ack_send_get_errno(send_sock); + ESP_LOGE(TAG, "send failed, errno %d", err); + vTaskDelay(200 / portTICK_RATE_MS); + } + + /* Send 60 smartconfig ACKs, exit regardless of failure or success. */ + if (packet_count++ >= SC_ACK_MAX_COUNT) { + esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY); + goto _end; + } + } + } else { + vTaskDelay((portTickType)(200 / portTICK_RATE_MS)); + } + } + +_end: + + if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) { + close(send_sock); + } + + free(ack); + vTaskDelete(NULL); +} + +esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t* cellphone_ip) +{ + sc_ack_t* ack = NULL; + + if (cellphone_ip == NULL) { + ESP_LOGE(TAG, "Cellphone IP address is NULL"); + return ESP_ERR_INVALID_ARG; + } + + ack = malloc(sizeof(sc_ack_t)); + + if (ack == NULL) { + ESP_LOGE(TAG, "ACK parameter malloc fail"); + return ESP_ERR_NO_MEM; + } + + ack->type = type; + ack->ctx.token = token; + memcpy(ack->ctx.ip, cellphone_ip, 4); + + s_sc_ack_send = true; + + if (xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL) != pdPASS) { + ESP_LOGE(TAG, "Create sending smartconfig ACK task fail"); + free(ack); + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + +void sc_send_ack_stop(void) +{ + s_sc_ack_send = false; +} diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index a9be92354..42fc18825 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -25,22 +25,34 @@ #include "esp_log.h" #include "esp_image_format.h" #include "esp_phy_init.h" -#include "esp_wifi_osi.h" #include "esp_heap_caps_init.h" #include "esp_task_wdt.h" -#include "internal/esp_wifi_internal.h" +#include "esp_private/wifi.h" +#include "esp_private/esp_system_internal.h" +#include "esp8266/eagle_soc.h" -#define FLASH_MAP_ADDR 0x40200000 -#define FLASH_MAP_SIZE 0x00100000 +#include "FreeRTOS.h" +#include "task.h" +#include "esp_task.h" + +#include "esp_newlib.h" -extern void chip_boot(size_t start_addr); -extern int rtc_init(void); -extern int mac_init(void); -extern int base_gpio_init(void); -extern int watchdog_init(void); -extern int wifi_timer_init(void); -extern int wifi_nvs_init(void); extern esp_err_t esp_pthread_init(void); +extern void chip_boot(void); +extern int base_gpio_init(void); + +static inline int should_load(uint32_t load_addr) +{ + if (IS_USR_RTC(load_addr)) { + if (esp_reset_reason_early() == ESP_RST_DEEPSLEEP) + return 0; + } + + if (IS_FLASH(load_addr)) + return 0; + + return 1; +} static void user_init_entry(void *param) { @@ -50,47 +62,70 @@ static void user_init_entry(void *param) extern void (*__init_array_end)(void); extern void app_main(void); + extern uint32_t esp_get_time(void); /* initialize C++ construture function */ for (func = &__init_array_start; func < &__init_array_end; func++) func[0](); - assert(nvs_flash_init() == 0); - assert(wifi_nvs_init() == 0); - assert(rtc_init() == 0); - assert(mac_init() == 0); + esp_phy_init_clk(); assert(base_gpio_init() == 0); - esp_phy_load_cal_and_init(0); - assert(wifi_timer_init() == 0); - esp_wifi_set_rx_pbuf_mem_type(WIFI_RX_PBUF_DRAM); + if (esp_reset_reason_early() != ESP_RST_FAST_SW) { + assert(esp_mac_init() == ESP_OK); + } + +#if CONFIG_RESET_REASON + esp_reset_reason_init(); +#endif -#ifdef CONFIG_TASK_WDT +#ifdef CONFIG_ESP_TASK_WDT esp_task_wdt_init(); #endif -#ifdef CONFIG_ENABLE_PTHREAD assert(esp_pthread_init() == 0); + +#ifdef CONFIG_BOOTLOADER_FAST_BOOT + REG_CLR_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); +#endif + +#ifdef CONFIG_ESP8266_DEFAULT_CPU_FREQ_160 + esp_set_cpu_freq(ESP_CPU_FREQ_160M); +#endif + +#ifdef CONFIG_ENABLE_TH25Q16HB_PATCH_0 + assert(th25q16hb_apply_patch_0() == 0); #endif app_main(); - wifi_task_delete(NULL); + vTaskDelete(NULL); } -void call_user_start(size_t start_addr) +void call_start_cpu(size_t start_addr) { int i; int *p; extern int _bss_start, _bss_end; + extern int _iram_bss_start, _iram_bss_end; - esp_image_header_t *head = (esp_image_header_t *)(FLASH_MAP_ADDR + (start_addr & (FLASH_MAP_SIZE - 1))); +#ifdef CONFIG_BOOTLOADER_FAST_BOOT + REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); +#endif + + esp_image_header_t *head = (esp_image_header_t *)(FLASH_BASE + (start_addr & (FLASH_SIZE - 1))); esp_image_segment_header_t *segment = (esp_image_segment_header_t *)((uintptr_t)head + sizeof(esp_image_header_t)); - for (i = 0; i < 3; i++) { + /* The data in flash cannot be accessed by byte in this stage, so just access by word and get the segment count. */ + uint8_t segment_count = ((*(volatile uint32_t *)head) & 0xFF00) >> 8; + + for (i = 0; i < segment_count - 1; i++) { segment = (esp_image_segment_header_t *)((uintptr_t)segment + sizeof(esp_image_segment_header_t) + segment->data_len); + if (!should_load(segment->load_addr)) + continue; + uint32_t *dest = (uint32_t *)segment->load_addr; uint32_t *src = (uint32_t *)((uintptr_t)segment + sizeof(esp_image_segment_header_t)); uint32_t size = segment->data_len / sizeof(uint32_t); @@ -108,12 +143,18 @@ void call_user_start(size_t start_addr) "wsr a0, vecbase\n" : : :"memory"); - chip_boot(start_addr); +#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH + chip_boot(); +#endif /* clear bss data */ for (p = &_bss_start; p < &_bss_end; p++) *p = 0; + /* clear iram_bss data */ + for (p = &_iram_bss_start; p < &_iram_bss_end; p++) + *p = 0; + __asm__ __volatile__( "rsil a2, 2\n" "movi a1, _chip_interrupt_tmp\n" @@ -121,9 +162,14 @@ void call_user_start(size_t start_addr) heap_caps_init(); - wifi_os_init(); +#ifdef CONFIG_INIT_OS_BEFORE_START + extern int __esp_os_init(void); + assert(__esp_os_init() == 0); +#endif + + assert(esp_newlib_init() == 0); - assert(wifi_task_create(user_init_entry, "uiT", CONFIG_MAIN_TASK_STACK_SIZE, NULL, wifi_task_get_max_priority()) != NULL); + assert(xTaskCreate(user_init_entry, "uiT", ESP_TASK_MAIN_STACK, NULL, ESP_TASK_MAIN_PRIO, NULL) == pdPASS); - wifi_os_start(); + vTaskStartScheduler(); } diff --git a/components/esp8266/source/system_api.c b/components/esp8266/source/system_api.c index a308d8721..1a0c1aad3 100644 --- a/components/esp8266/source/system_api.c +++ b/components/esp8266/source/system_api.c @@ -17,8 +17,9 @@ #include "esp_log.h" #include "esp_system.h" +#include "esp_private/esp_system_internal.h" -#include "crc.h" +#include "rom/crc.h" #include "esp8266/eagle_soc.h" #include "esp8266/efuse_register.h" @@ -31,12 +32,18 @@ static const char* TAG = "system_api"; static uint8_t base_mac_addr[6] = { 0 }; +uint32_t g_esp_ticks_per_us = 80; + +// Bootloader can get this information +const __attribute__((section(".SystemInfoVector.text"))) esp_sys_info_t g_esp_sys_info = { + .version = ESP_IDF_VERSION +}; esp_err_t esp_base_mac_addr_set(uint8_t *mac) { if (mac == NULL) { ESP_LOGE(TAG, "Base MAC address is NULL"); - abort(); + return ESP_ERR_INVALID_ARG; } memcpy(base_mac_addr, mac, 6); @@ -49,7 +56,7 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac) uint8_t null_mac[6] = {0}; if (memcmp(base_mac_addr, null_mac, 6) == 0) { - ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from BLK0 of EFUSE"); + ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from EFUSE"); return ESP_ERR_INVALID_MAC; } @@ -65,6 +72,7 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) uint8_t efuse_crc = 0; uint8_t calc_crc = 0; uint8_t version; + uint8_t use_default = 1; efuse[0] = REG_READ(EFUSE_DATA0_REG); efuse[1] = REG_READ(EFUSE_DATA1_REG); @@ -82,6 +90,8 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) mac[1] = efuse[3] >> 8; mac[2] = efuse[3]; + use_default = 0; + tmp_mac[0] = mac[2]; tmp_mac[1] = mac[1]; tmp_mac[2] = mac[0]; @@ -89,28 +99,28 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) efuse_crc = efuse[2] >> 24; calc_crc = esp_crc8(tmp_mac, 3); - if (efuse_crc != calc_crc) { - ESP_LOGE(TAG, "High MAC CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc); - return ESP_ERR_INVALID_MAC; - } + if (efuse_crc != calc_crc) + use_default = 1; - version = (efuse[1] >> EFUSE_VERSION_S) & EFUSE_VERSION_V; + if (!use_default) { + version = (efuse[1] >> EFUSE_VERSION_S) & EFUSE_VERSION_V; - if (version == EFUSE_VERSION_1 || version == EFUSE_VERSION_2) { - tmp_mac[0] = mac[5]; - tmp_mac[1] = mac[4]; - tmp_mac[2] = mac[3]; - tmp_mac[3] = efuse[1] >> 16; + if (version == EFUSE_VERSION_1 || version == EFUSE_VERSION_2) { + tmp_mac[0] = mac[5]; + tmp_mac[1] = mac[4]; + tmp_mac[2] = mac[3]; + tmp_mac[3] = efuse[1] >> 16; - efuse_crc = efuse[0] >> 16; - calc_crc = esp_crc8(tmp_mac, 4); + efuse_crc = efuse[0] >> 16; + calc_crc = esp_crc8(tmp_mac, 4); - if (efuse_crc != calc_crc) { - ESP_LOGE(TAG, "CRC8 error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc); - return ESP_ERR_INVALID_MAC; + if (efuse_crc != calc_crc) + use_default = 1; } } - } else { + } + + if (use_default) { mac[0] = 0x18; mac[1] = 0xFE; mac[2] = 0x34; @@ -126,7 +136,7 @@ static const char *BACKUP_MAC_DATA_KEY = "backup_mac_data"; static esp_err_t load_backup_mac_data(uint8_t *mac) { esp_err_t err; - nvs_handle handle; + nvs_handle_t handle; uint32_t efuse[4]; uint8_t efuse_crc = 0; uint8_t calc_crc = 0; @@ -211,7 +221,7 @@ static esp_err_t load_backup_mac_data(uint8_t *mac) static esp_err_t store_backup_mac_data() { esp_err_t err; - nvs_handle handle; + nvs_handle_t handle; uint32_t efuse[4]; efuse[0] = REG_READ(EFUSE_DATA0_REG); efuse[1] = REG_READ(EFUSE_DATA1_REG); @@ -303,6 +313,34 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type) return ESP_OK; } +esp_err_t esp_mac_init(void) +{ + esp_err_t ret; + uint8_t efuse_mac[6]; + + if ((ret = nvs_flash_init()) != ESP_OK) { + ESP_LOGE(TAG, "Init NVS error=%d", ret); + return ESP_ERR_INVALID_MAC; + } + + if (load_backup_mac_data(efuse_mac) == ESP_OK) { + ESP_LOGD(TAG, "Load MAC from NVS error=%d", ret); + return ESP_OK; + } + + if ((ret = esp_efuse_mac_get_default(efuse_mac)) != ESP_OK) { + ESP_LOGE(TAG, "Get mac address error=%d", ret); + return ESP_ERR_INVALID_MAC; + } + + if ((ret = store_backup_mac_data()) != ESP_OK) { + ESP_LOGE(TAG, "Store mac address error=%d", ret); + return ESP_ERR_INVALID_MAC; + } + + return ESP_OK; +} + /** * Get IDF version */ @@ -349,3 +387,26 @@ uint32_t esp_get_minimum_free_heap_size(void) { return heap_caps_get_minimum_free_size(MALLOC_CAP_32BIT); } + +/** + * @brief Get old SDK configuration parameters base address + */ +uint32_t esp_get_old_sysconf_addr(void) +{ + return rtc_sys_info.old_sysconf_addr; +} + +void os_update_cpu_frequency(uint32_t ticks_per_us) +{ + extern uint32_t _xt_tick_divisor; + + if (REG_READ(DPORT_CTL_REG) & DPORT_CTL_DOUBLE_CLK) { + g_esp_ticks_per_us = CPU_CLK_FREQ * 2 / 1000000; + _xt_tick_divisor = (CPU_CLK_FREQ * 2 / CONFIG_FREERTOS_HZ); + } else { + g_esp_ticks_per_us = CPU_CLK_FREQ / 1000000;; + _xt_tick_divisor = (CPU_CLK_FREQ / CONFIG_FREERTOS_HZ); + } +} + +void ets_update_cpu_frequency(uint32_t ticks_per_us) __attribute__((alias("os_update_cpu_frequency"))); diff --git a/components/esp8266/source/task_wdt.c b/components/esp8266/source/task_wdt.c index 1700bf501..bb2073424 100644 --- a/components/esp8266/source/task_wdt.c +++ b/components/esp8266/source/task_wdt.c @@ -16,27 +16,92 @@ #include "esp_log.h" #include "esp_libc.h" -#include "esp_wifi_osi.h" #include "esp_task_wdt.h" +#include "esp_attr.h" #include "portmacro.h" +#include "esp8266/rom_functions.h" #include "esp8266/eagle_soc.h" - -#define WDT_REG_READ(_reg) REG_READ(PERIPHS_WDT_BASEADDR + _reg) -#define WDT_REG_WRITE(_reg, _val) REG_WRITE(PERIPHS_WDT_BASEADDR + _reg, _val) -#define CLEAR_WDT_REG_MASK(_reg, _mask) WDT_REG_WRITE(_reg, WDT_REG_READ(_reg) & (~_mask)) -#define WDT_FEED() WDT_REG_WRITE(WDT_RST_ADDRESS, WDT_FEED_VALUE) +#include "driver/soc.h" static const char *TAG = "wdt"; -#ifdef CONFIG_TASK_WDT_PANIC +#ifdef CONFIG_ESP_TASK_WDT_PANIC /** * @brief Task watch dog interrupt function and it should do panic */ static void esp_task_wdt_isr(void *param) { extern void panicHandler(void *frame, int wdt); + extern void *__wifi_task_top_sp(void); - panicHandler(osi_task_top_sp(), 1); + panicHandler(__wifi_task_top_sp(), 1); +} +#endif + +#ifdef CONFIG_ESP8266_NMI_WDT + +#if CONFIG_ESP_TASK_WDT_TIMEOUT_S == 13 +#define NMI_WD_TOTAL_PERIOD (6553600) +#elif CONFIG_ESP_TASK_WDT_TIMEOUT_S == 14 +#define NMI_WD_TOTAL_PERIOD (13107200) +#elif CONFIG_ESP_TASK_WDT_TIMEOUT_S == 15 +#define NMI_WD_TOTAL_PERIOD (26214400) +#endif + +#define NMI_WD_CHECK_PERIOD (1 * 1000 * 1000) + +static int s_nmi_wd_state; + +static void nmi_panic_wd(void) +{ + extern uint32_t _chip_nmi_cnt; + extern uint8_t _chip_nmi_stk[]; + extern void panicHandler(void *frame, int wdt); + uint32_t *p; + + if (_chip_nmi_cnt == 1) { + p = (uint32_t *)&_chip_nmi_stk[512]; + } else { + p = (uint32_t *)&_chip_nmi_stk[512 + 124 + 256]; + } + + panicHandler(p - 1, 1); +} + +static void IRAM_ATTR nmi_set_wd_time(uint32_t us) +{ + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); + + REG_WRITE(WDEVTSFSW0_LO, 0); + REG_WRITE(WDEVTSFSW0_HI, 0); + REG_WRITE(WDEVTSFSW0_LO, 0); + + REG_WRITE(WDEVTSF0_TIMER_LO, 0); + REG_WRITE(WDEVTSF0_TIMER_HI, 0); + + REG_WRITE(WDEVTSF0_TIMER_LO, us); + + REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); +} + +static void IRAM_ATTR nmi_check_wd(void) +{ + switch (s_nmi_wd_state) { + case 0: + s_nmi_wd_state = 1; + nmi_set_wd_time(NMI_WD_CHECK_PERIOD); + break; + case 1: + s_nmi_wd_state = 2; + nmi_set_wd_time(NMI_WD_TOTAL_PERIOD - NMI_WD_CHECK_PERIOD); + break; + case 2: + Cache_Read_Enable_New(); + nmi_panic_wd(); + break; + default: + break; + } } #endif @@ -47,9 +112,12 @@ esp_err_t esp_task_wdt_init(void) { CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, BIT0); -#ifdef CONFIG_TASK_WDT_PANIC +#ifdef CONFIG_ESP_TASK_WDT_PANIC const uint32_t panic_time_param = 11; + // Just for soft restart + soc_clear_int_mask(1 << ETS_WDT_INUM); + _xt_isr_attach(ETS_WDT_INUM, esp_task_wdt_isr, NULL); _xt_isr_unmask(1 << ETS_WDT_INUM); @@ -60,9 +128,9 @@ esp_err_t esp_task_wdt_init(void) const uint32_t panic_time_param = 1; #endif - ESP_LOGD(TAG, "task watch dog trigger time parameter is %u", CONFIG_TASK_WDT_TIMEOUT_S); + ESP_LOGD(TAG, "task watch dog trigger time parameter is %u", CONFIG_ESP_TASK_WDT_TIMEOUT_S); - WDT_REG_WRITE(WDT_OP_ADDRESS, CONFIG_TASK_WDT_TIMEOUT_S); // 2^n * 0.8ms, mask 0xf, n = 13 -> (2^13 = 8192) * 0.8 * 0.001 = 6.5536 + WDT_REG_WRITE(WDT_OP_ADDRESS, CONFIG_ESP_TASK_WDT_TIMEOUT_S); // 2^n * 0.8ms, mask 0xf, n = 13 -> (2^13 = 8192) * 0.8 * 0.001 = 6.5536 WDT_REG_WRITE(WDT_OP_ND_ADDRESS, panic_time_param); // 2^n * 0.8ms, mask 0xf, n = 11 -> (2^11 = 2048) * 0.8 * 0.001 = 1.6384 SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_RSTLEN_MASK, 7 << WDT_CTL_RSTLEN_LSB, 0); @@ -73,6 +141,15 @@ esp_err_t esp_task_wdt_init(void) WDT_FEED(); +#ifdef CONFIG_ESP8266_NMI_WDT + { + extern void wDev_MacTimSetFunc(void *func); + + wDev_MacTimSetFunc(nmi_check_wd);; + nmi_set_wd_time(NMI_WD_CHECK_PERIOD); + } +#endif + return 0; } @@ -83,6 +160,10 @@ esp_err_t esp_task_wdt_init(void) void esp_task_wdt_reset(void) { WDT_FEED(); + +#ifdef CONFIG_ESP8266_NMI_WDT + s_nmi_wd_state = 0; +#endif } /** diff --git a/components/esp8266/test/test_interrupt_overhead.c b/components/esp8266/test/test_interrupt_overhead.c new file mode 100644 index 000000000..6f2357674 --- /dev/null +++ b/components/esp8266/test/test_interrupt_overhead.c @@ -0,0 +1,89 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include + +#include "FreeRTOS.h" +#include +#include "esp8266/timer_register.h" + +#define TIMER1_ENABLE_TIMER 0x0080 +#define TIMER1_INTERRUPT_TYPE_LEVEL 1 +#define hw_timer_intr_register(a, b) \ + _xt_isr_attach(ETS_FRC_TIMER1_INUM, (a), (b)) + +struct timer_regs { + uint32_t frc1_load; /* 0x60000600 */ + uint32_t frc1_count; /* 0x60000604 */ + uint32_t frc1_ctrl; /* 0x60000608 */ + uint32_t frc1_int; /* 0x6000060C */ +}; +static struct timer_regs *timer = (struct timer_regs *)(PERIPHS_TIMER_BASEDDR); + +static void test_timer_cb(void *cpu_clk_cnt) { + *(uint32_t *)cpu_clk_cnt = soc_get_ccount(); +} + +TEST_CASE("Test interrupt overhead time", "[log]") { + volatile uint32_t cpu_clk_cnt_interrupt_enter; + uint32_t cpu_clk_cnt_start; + uint32_t cpu_clk_cnt_stop; + + // Execute the test twice and only take the second result to make sure + // that IRAM has cached all instructions. + for (int i = 0; i < 2; i++) { + cpu_clk_cnt_interrupt_enter = 0; + hw_timer_init(test_timer_cb, (void *)&cpu_clk_cnt_interrupt_enter); + hw_timer_intr_register(test_timer_cb, (void *)&cpu_clk_cnt_interrupt_enter); + + // Setup the timer, so that it'll trigger exactly once. + timer->frc1_int = 0; // reset the interrupt status + timer->frc1_load = 0; // trigger the timer interrupt immediately + timer->frc1_ctrl = TIMER1_ENABLE_TIMER | TIMER1_INTERRUPT_TYPE_LEVEL; + cpu_clk_cnt_start = soc_get_ccount(); + + // busy wait until the interrupt triggered and updated the variable + while (!cpu_clk_cnt_interrupt_enter) + ; + + cpu_clk_cnt_stop = soc_get_ccount(); + hw_timer_deinit(); + } + + uint32_t overhead_enter = cpu_clk_cnt_interrupt_enter - cpu_clk_cnt_start; + uint32_t overhead_total = cpu_clk_cnt_stop - cpu_clk_cnt_start; + +#if CONFIG_OPTIMIZATION_LEVEL_DEBUG +# define INTERRUPT_OVERHEAD_ENTER_TIME 334 +# define INTERRUPT_OVERHEAD_TOTAL_TIME 459 +#else // CONFIG_OPTIMIZATION_LEVEL_RELEASE +# define INTERRUPT_OVERHEAD_ENTER_TIME 258 +# define INTERRUPT_OVERHEAD_TOTAL_TIME 385 +#endif + + if (overhead_enter != INTERRUPT_OVERHEAD_ENTER_TIME || + overhead_total != INTERRUPT_OVERHEAD_TOTAL_TIME) { + char buf[128]; + snprintf(buf, sizeof(buf), + "interrupt overhead times changed. expected (enter=%d, total=%d), " + "but got (enter=%d, total=%d)", + INTERRUPT_OVERHEAD_ENTER_TIME, INTERRUPT_OVERHEAD_TOTAL_TIME, + overhead_enter, overhead_total); + TEST_FAIL_MESSAGE(buf); + } +} diff --git a/components/esp8266/test/test_wifi.c b/components/esp8266/test/test_wifi.c new file mode 100644 index 000000000..00805309b --- /dev/null +++ b/components/esp8266/test/test_wifi.c @@ -0,0 +1,223 @@ +/* + Tests for the Wi-Fi +*/ +#include "string.h" +#include "unity.h" +#include "esp_system.h" +#include "esp_event_loop.h" +#include "esp_wifi.h" +#include "esp_wifi_types.h" +#include "esp_log.h" +#include "test_utils.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +static const char* TAG = "test_wifi"; + +#define GOT_IP_EVENT 0x00000001 +#define DISCONNECT_EVENT 0x00000002 + +#define EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT 0x00000001 +#define FULL_CAHNNEL_SCAN_DURATION_THRESHOLD 1500 + +static uint32_t wifi_event_handler_flag; + +xSemaphoreHandle cb_scan_num_mutex; +xSemaphoreHandle task_scan_num_mutex; +xSemaphoreHandle cb_scan_fail_mutex; +xSemaphoreHandle task_scan_fail_mutex; + +static EventGroupHandle_t scan_task_exit; +static EventGroupHandle_t wifi_events; + +struct timeval cb_scan_time_list[10]; +struct timeval task_scan_time_list[10]; + +static uint32_t cb_scan_ap_num = 0; +static uint32_t task_scan_ap_num = 0; +static uint32_t cb_scan_fail_times = 0; +static uint32_t task_scan_fail_times = 0; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + printf("ev_handle_called.\n"); + uint16_t num = 0; + struct timeval cb_tv = {0}; + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); + ESP_LOGI(TAG, "got ip:%s\n", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + if (wifi_events) { + xEventGroupSetBits(wifi_events, GOT_IP_EVENT); + } + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); + if (! (EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT & wifi_event_handler_flag) ) { + TEST_ESP_OK(esp_wifi_connect()); + } + if (wifi_events) { + xEventGroupSetBits(wifi_events, DISCONNECT_EVENT); + } + break; + case SYSTEM_EVENT_SCAN_DONE: + if (event->event_info.scan_done.status == 0) { + esp_wifi_scan_get_ap_num(&num); + xSemaphoreTake(cb_scan_num_mutex, portMAX_DELAY); + cb_scan_ap_num += num; + xSemaphoreGive(cb_scan_num_mutex); + printf("+SCANDONE\n"); + } + else { + gettimeofday(&cb_tv, NULL); + xSemaphoreTake(cb_scan_fail_mutex, portMAX_DELAY); + cb_scan_time_list[cb_scan_fail_times++] = cb_tv; + xSemaphoreGive(cb_scan_fail_mutex); + printf("+SCANFAIL\n"); + } + break; + default: + break; + } + return ESP_OK; +} + +static void start_wifi_as_sta(void) +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + cfg.nvs_enable = false; + // do not auto connect + wifi_event_handler_flag |= EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT; + TEST_ESP_OK(esp_event_loop_init(event_handler, NULL)); + // can't deinit event loop, need to reset leak check + unity_reset_leak_checks(); + if (wifi_events == NULL) { + wifi_events = xEventGroupCreate(); + } else { + xEventGroupClearBits(wifi_events, 0x00ffffff); + } + TEST_ESP_OK(esp_wifi_init(&cfg)); + TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA)); + TEST_ESP_OK(esp_wifi_start()); +} + +static void stop_wifi(void) +{ + printf("stop wifi\n"); + TEST_ESP_OK(esp_wifi_stop()); + TEST_ESP_OK(esp_wifi_deinit()); + if (wifi_events) { + vEventGroupDelete(wifi_events); + wifi_events = NULL; + } + vTaskDelay(1000/portTICK_PERIOD_MS); +} + +static void scan_task(void *param) +{ + int32_t ret; + uint16_t ap_num; + float scan_duration = 0.0; + struct timeval scan_tv_start = {0}, scan_tv_stop = {0}, task_tv = {0}; + uint8_t task_id = *((uint8_t *) param); + uint8_t *test_result = (uint8_t *) param; + wifi_scan_config_t scan_config = {0}; + for (int i = 0; i < 2; i++) { + ap_num = 0; + ESP_LOGI(TAG, "[%u] scan start", task_id); + gettimeofday(&scan_tv_start, NULL); + ret = esp_wifi_scan_start(&scan_config, true); + if (ret == ESP_OK) { + gettimeofday(&scan_tv_stop, NULL); + scan_duration = (scan_tv_stop.tv_sec - scan_tv_start.tv_sec) + (scan_tv_stop.tv_usec - scan_tv_start.tv_usec) * 1e-6f; + esp_wifi_scan_get_ap_num(&ap_num); + ESP_LOGI(TAG, "[%u] scan succeed. duration: %.2f; ap_num: %d; ret: %d", task_id, scan_duration, ap_num, ret); + if (scan_duration < FULL_CAHNNEL_SCAN_DURATION_THRESHOLD) { + *test_result = 0; + } + } else { + gettimeofday(&task_tv, NULL); + xSemaphoreTake(task_scan_fail_mutex, portMAX_DELAY); + task_scan_time_list[task_scan_fail_times++] = task_tv; + xSemaphoreGive(task_scan_fail_mutex); + ESP_LOGI(TAG, "[%u] scan fail, ret: %d", task_id, ret); + vTaskDelay(300 / portTICK_PERIOD_MS); + } + xSemaphoreTake(task_scan_num_mutex, portMAX_DELAY); + task_scan_ap_num += ap_num; + xSemaphoreGive(task_scan_num_mutex); + } + ESP_LOGI(TAG, "[%u] scan task exit", task_id); + xEventGroupSetBits(scan_task_exit, task_id); + vTaskDelete(NULL); +} + +TEST_CASE("wifi do block scan before scan finished","[wifi][ignore]") +{ + uint8_t i, ret[2]; + float time_interval = 0.0; + if (scan_task_exit == NULL) { + scan_task_exit = xEventGroupCreate(); + } + if (cb_scan_num_mutex == NULL) { + cb_scan_num_mutex = xSemaphoreCreateMutex(); + } + if (task_scan_num_mutex == NULL) { + task_scan_num_mutex = xSemaphoreCreateMutex(); + } + if (cb_scan_fail_mutex == NULL) { + cb_scan_fail_mutex = xSemaphoreCreateMutex(); + } + if (task_scan_fail_mutex == NULL) { + task_scan_fail_mutex = xSemaphoreCreateMutex(); + } + test_case_uses_tcpip(); + start_wifi_as_sta(); + xEventGroupClearBits(scan_task_exit, BIT0 | BIT1); + for (i = 1; i <= 2; i++) { + ret[i-1] = i; + if (xTaskCreate(scan_task, "scan task", 2048, &ret[i-1], 1, NULL) != pdTRUE) { + printf("create scan task fail"); + } + vTaskDelay(500 / portTICK_PERIOD_MS); + } + xEventGroupWaitBits(scan_task_exit, BIT0 | BIT1, true, true, portMAX_DELAY); + vTaskDelay(5000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "compare the ap nums got in cb and after esp_wifi_scan_start() finish"); + if (cb_scan_ap_num != task_scan_ap_num) { + TEST_IGNORE_MESSAGE("the ap nums are different"); + } + ESP_LOGI(TAG, "compare the times of printing SCANFAIL in cb and esp_wifi_scan_start() return error code"); + if (cb_scan_fail_times != task_scan_fail_times) { + TEST_IGNORE_MESSAGE("the times are different"); + } + ESP_LOGI(TAG, "check the time interval between printing SCANFAIL in cb and esp_wifi_scan_start() return error code"); + for (i = 0; i < task_scan_fail_times; i++) { + time_interval = (cb_scan_time_list[i].tv_sec - task_scan_time_list[i].tv_sec) + (cb_scan_time_list[i].tv_usec - task_scan_time_list[i].tv_usec) * 1e-6f; + if (abs(time_interval) > 1) { + TEST_IGNORE_MESSAGE("the time interval more than 1s"); + } + } + ESP_LOGI(TAG, "check scan time"); + for (i = 1; i <= 2; i++) { + if (ret[i-1] != i) { + TEST_IGNORE_MESSAGE("the scan time less than 1500ms"); + } + } + stop_wifi(); + vEventGroupDelete(scan_task_exit); + vSemaphoreDelete(cb_scan_num_mutex); + vSemaphoreDelete(task_scan_num_mutex); + vSemaphoreDelete(cb_scan_fail_mutex); + vSemaphoreDelete(task_scan_fail_mutex); + scan_task_exit = NULL; + cb_scan_num_mutex = NULL; + task_scan_num_mutex = NULL; + cb_scan_fail_mutex = NULL; + task_scan_fail_mutex = NULL; + TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of tcpip_adapter and event_loop."); +} diff --git a/components/esp_common/CMakeLists.txt b/components/esp_common/CMakeLists.txt new file mode 100644 index 000000000..b4d319cf2 --- /dev/null +++ b/components/esp_common/CMakeLists.txt @@ -0,0 +1,17 @@ +if(BOOTLOADER_BUILD) + # For bootloader, all we need from esp_common is headers + idf_component_register(INCLUDE_DIRS include) + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-Wl,--gc-sections") +else() + # Regular app build + idf_component_register(SRCS "src/stack_check.c" "src/esp_err_to_name.c" + INCLUDE_DIRS include + PRIV_REQUIRES "tcpip_adapter") + + set_source_files_properties( + "src/stack_check.c" + PROPERTIES COMPILE_FLAGS + -fno-stack-protector) + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_LIBRARIES "-Wl,--gc-sections") + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-Wl,--gc-sections") +endif() diff --git a/components/esp_common/Kconfig b/components/esp_common/Kconfig new file mode 100644 index 000000000..fd88fad90 --- /dev/null +++ b/components/esp_common/Kconfig @@ -0,0 +1,138 @@ +menu "Common ESP-related" + + config ESP_ERR_TO_NAME_LOOKUP + bool "Enable lookup of error code strings" + default "y" + help + Functions esp_err_to_name() and esp_err_to_name_r() return string representations of error codes from a + pre-generated lookup table. This option can be used to turn off the use of the look-up table in order to + save memory but this comes at the price of sacrificing distinguishable (meaningful) output string + representations. + + config ESP_SYSTEM_EVENT_QUEUE_SIZE + int "System event queue size" + default 32 + help + Config system event queue size in different application. + + config ESP_SYSTEM_EVENT_TASK_STACK_SIZE + int "Event loop task stack size" + default 2048 + help + Config system event task stack size in different application. + + config ESP_MAIN_TASK_STACK_SIZE + int "Main task stack size" + default 3584 + help + Configure the "main task" stack size. This is the stack of the task + which calls app_main(). If app_main() returns then this task is deleted + and its stack memory is freed. + + config ESP_TIMER_TASK_STACK_SIZE + int "High-resolution timer task stack size" + default 3584 + range 2048 65536 + help + Configure the stack size of esp_timer/ets_timer task. This task is used + to dispatch callbacks of timers created using ets_timer and esp_timer + APIs. If you are seing stack overflow errors in timer task, increase + this value. + + Note that this is not the same as FreeRTOS timer task. To configure + FreeRTOS timer task size, see "FreeRTOS timer task stack size" option + in "FreeRTOS" menu. + + choice ESP_CONSOLE_UART + prompt "UART for console output" + default ESP_CONSOLE_UART_DEFAULT + help + Select whether to use UART for console output (through stdout and stderr). + + - Default is to use UART0 on pins GPIO1(TX) and GPIO3(RX). + - If "Custom" is selected, UART0 or UART1 can be chosen, + and any pins can be selected. + - If "None" is selected, there will be no console output on any UART, except + for initial output from ROM bootloader. This output can be further suppressed by + bootstrapping GPIO13 pin to low logic level. + + config ESP_CONSOLE_UART_DEFAULT + bool "Default: UART0, TX=GPIO1, RX=GPIO3" + config ESP_CONSOLE_UART_CUSTOM + bool "Custom" + config ESP_CONSOLE_UART_NONE + bool "None" + endchoice + + choice ESP_CONSOLE_UART_NUM + prompt "UART peripheral to use for console output (0-1)" + depends on ESP_CONSOLE_UART_CUSTOM + default ESP_CONSOLE_UART_CUSTOM_NUM_0 + help + Due of a ROM bug, UART2 is not supported for console output + via ets_printf. + + config ESP_CONSOLE_UART_CUSTOM_NUM_0 + bool "UART0" + config ESP_CONSOLE_UART_CUSTOM_NUM_1 + bool "UART1" + endchoice + + config ESP_CONSOLE_UART_NUM + int + default 0 if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_NONE + default 0 if ESP_CONSOLE_UART_CUSTOM_NUM_0 + default 1 if ESP_CONSOLE_UART_CUSTOM_NUM_1 + + config ESP_CONSOLE_UART_BAUDRATE + int "UART console baud rate" + depends on !ESP_CONSOLE_UART_NONE + default 74880 + range 1200 4000000 + + config ESP_UART0_SWAP_IO + bool "Swap UART0 I/O pins" + default n + help + Enable this option, UART0's I/O pins are swaped: TXD <-> RTS, RTX <-> CTS. + + config ESP_TASK_WDT + bool "Initialize Task Watchdog Timer on startup" + default y + help + The Task Watchdog Timer can be used to make sure individual tasks are still + running. Enabling this option will cause the Task Watchdog Timer to be + initialized automatically at startup. The Task Watchdog timer can be + initialized after startup as well (see Task Watchdog Timer API Reference) + + config ESP_TASK_WDT_PANIC + bool "Invoke panic handler on Task Watchdog timeout" + depends on ESP_TASK_WDT + default y + help + If this option is enabled, the Task Watchdog Timer will be configured to + trigger the panic handler when it times out. This can also be configured + at run time (see Task Watchdog Timer API Reference) + + choice ESP_TASK_WDT_TIMEOUT_S + prompt "Task Watchdog timeout period (seconds)" + default ESP_TASK_WDT_TIMEOUT_15N + help + Timeout period configuration for the Task Watchdog Timer in seconds. + This is also configurable at run time. + + config ESP_TASK_WDT_TIMEOUT_13N + bool "6.5536s" + config ESP_TASK_WDT_TIMEOUT_14N + bool "13.1072s" + config ESP_TASK_WDT_TIMEOUT_15N + bool "26.2144s" + endchoice + + config ESP_TASK_WDT_TIMEOUT_S + int + default 13 if ESP_TASK_WDT_TIMEOUT_13N + default 14 if ESP_TASK_WDT_TIMEOUT_14N + default 15 if ESP_TASK_WDT_TIMEOUT_15N + +endmenu # Common ESP-related diff --git a/components/esp_common/component.mk b/components/esp_common/component.mk new file mode 100644 index 000000000..962d98676 --- /dev/null +++ b/components/esp_common/component.mk @@ -0,0 +1,12 @@ +# +# Component Makefile +# + +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_SRCDIRS := src + +# just to remove make compiling warning +src/stack_check.o: <:= + +# disable stack protection in files which are involved in initialization of that feature +src/stack_check.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS)) diff --git a/components/esp_common/include/esp_bit_defs.h b/components/esp_common/include/esp_bit_defs.h new file mode 100644 index 000000000..a15d17fdf --- /dev/null +++ b/components/esp_common/include/esp_bit_defs.h @@ -0,0 +1,57 @@ +// Copyright 2010-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +//Register Bits{{ +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 +//}} + +#ifndef __ASSEMBLER__ +#define BIT(nr) (1UL << (nr)) +#define BIT64(nr) (1ULL << (nr)) +#else +#define BIT(nr) (1 << (nr)) +#endif \ No newline at end of file diff --git a/components/esp_common/include/esp_compiler.h b/components/esp_common/include/esp_compiler.h new file mode 100644 index 000000000..6922c50ad --- /dev/null +++ b/components/esp_common/include/esp_compiler.h @@ -0,0 +1,51 @@ +// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __ESP_COMPILER_H +#define __ESP_COMPILER_H + +/* + * The likely and unlikely macro pairs: + * These macros are useful to place when application + * knows the majority ocurrence of a decision paths, + * placing one of these macros can hint the compiler + * to reorder instructions producing more optimized + * code. + */ +#if (CONFIG_COMPILER_OPTIMIZATION_PERF) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +/* + * Utility macros used for designated initializers, which work differently + * in C99 and C++ standards mainly for aggregate types. + * The member separator, comma, is already part of the macro, please omit the trailing comma. + * Usage example: + * struct config_t { char* pchr; char arr[SIZE]; } config = { + * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr) + * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value") + * }; + */ +#ifdef __cplusplus +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value }, +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { }, +#else +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value, +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) +#endif + +#endif \ No newline at end of file diff --git a/components/esp_common/include/esp_err.h b/components/esp_common/include/esp_err.h new file mode 100644 index 000000000..f14143579 --- /dev/null +++ b/components/esp_common/include/esp_err.h @@ -0,0 +1,148 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int32_t esp_err_t; + +/* Definitions for error constants. */ +#define ESP_OK 0 /*!< esp_err_t value indicating success (no error) */ +#define ESP_FAIL -1 /*!< Generic esp_err_t code indicating failure */ + +#define ESP_ERR_NO_MEM 0x101 /*!< Out of memory */ +#define ESP_ERR_INVALID_ARG 0x102 /*!< Invalid argument */ +#define ESP_ERR_INVALID_STATE 0x103 /*!< Invalid state */ +#define ESP_ERR_INVALID_SIZE 0x104 /*!< Invalid size */ +#define ESP_ERR_NOT_FOUND 0x105 /*!< Requested resource not found */ +#define ESP_ERR_NOT_SUPPORTED 0x106 /*!< Operation or feature not supported */ +#define ESP_ERR_TIMEOUT 0x107 /*!< Operation timed out */ +#define ESP_ERR_INVALID_RESPONSE 0x108 /*!< Received response was invalid */ +#define ESP_ERR_INVALID_CRC 0x109 /*!< CRC or checksum was invalid */ +#define ESP_ERR_INVALID_VERSION 0x10A /*!< Version was invalid */ +#define ESP_ERR_INVALID_MAC 0x10B /*!< MAC address was invalid */ + +#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */ +#define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */ + +/** + * @brief Returns string for esp_err_t error codes + * + * This function finds the error code in a pre-generated lookup-table and + * returns its string representation. + * + * The function is generated by the Python script + * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t + * error is modified, created or removed from the IDF project. + * + * @param code esp_err_t error code + * @return string error message + */ +const char *esp_err_to_name(esp_err_t code); + +/** + * @brief Returns string for esp_err_t and system error codes + * + * This function finds the error code in a pre-generated lookup-table of + * esp_err_t errors and returns its string representation. If the error code + * is not found then it is attempted to be found among system errors. + * + * The function is generated by the Python script + * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t + * error is modified, created or removed from the IDF project. + * + * @param code esp_err_t error code + * @param[out] buf buffer where the error message should be written + * @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte). + * @return buf containing the string error message + */ +const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen); + +/** @cond */ +void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn)); + +/** @cond */ +void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression); + +#ifndef __ASSERT_FUNC +/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which + uses /usr/include/assert.h or equivalent. +*/ +#ifdef __ASSERT_FUNCTION +#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */ +#else +#define __ASSERT_FUNC "??" +#endif +#endif +/** @endcond */ + +/** + * Macro which can be used to check the error code, + * and terminate the program in case the code is not ESP_OK. + * Prints the error code, error location, and the failed statement to serial output. + * + * Disabled if assertions are disabled. + */ +#ifdef NDEBUG +#define ESP_ERROR_CHECK(x) do { \ + esp_err_t __err_rc = (x); \ + (void) sizeof(__err_rc); \ + } while(0); +#elif defined(CONFIG_OPTIMIZATION_ASSERTIONS_SILENT) +#define ESP_ERROR_CHECK(x) do { \ + esp_err_t __err_rc = (x); \ + if (__err_rc != ESP_OK) { \ + abort(); \ + } \ + } while(0); +#else +#define ESP_ERROR_CHECK(x) do { \ + esp_err_t __err_rc = (x); \ + if (__err_rc != ESP_OK) { \ + _esp_error_check_failed(__err_rc, __ESP_FILE__, __LINE__, \ + __ASSERT_FUNC, #x); \ + } \ + } while(0); +#endif + +/** + * Macro which can be used to check the error code. Prints the error code, error location, and the failed statement to + * serial output. + * In comparison with ESP_ERROR_CHECK(), this prints the same error message but isn't terminating the program. + */ +#ifdef NDEBUG +#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \ + esp_err_t __err_rc = (x); \ + __err_rc; \ + }) +#else +#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \ + esp_err_t __err_rc = (x); \ + if (__err_rc != ESP_OK) { \ + _esp_error_check_failed_without_abort(__err_rc, __ESP_FILE__, __LINE__, \ + __ASSERT_FUNC, #x); \ + } \ + __err_rc; \ + }) +#endif //NDEBUG + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_common/include/esp_task.h b/components/esp_common/include/esp_task.h new file mode 100644 index 000000000..1b7937912 --- /dev/null +++ b/components/esp_common/include/esp_task.h @@ -0,0 +1,47 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* Notes: + * 1. Put all task priority and stack size definition in this file + * 2. If the task priority is less than 10, use ESP_TASK_PRIO_MIN + X style, + * otherwise use ESP_TASK_PRIO_MAX - X style + * 3. If this is a daemon task, the macro prefix is ESP_TASKD_, otherwise + * it's ESP_TASK_ + * 4. If the configMAX_PRIORITIES is modified, please make all priority are + * greater than 0 + * 5. Make sure esp_task.h is consistent between wifi lib and idf + */ + +#ifndef _ESP_TASK_H_ +#define _ESP_TASK_H_ + +#include "sdkconfig.h" +#include "freertos/FreeRTOSConfig.h" + +#define ESP_TASK_PRIO_MAX (configMAX_PRIORITIES) +#define ESP_TASK_PRIO_MIN (0) + +#define TASK_EXTRA_STACK_SIZE (0) + +/* idf task */ +#define ESP_TASK_TIMER_PRIO (ESP_TASK_PRIO_MAX - 3) +#define ESP_TASK_TIMER_STACK (CONFIG_ESP_TIMER_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) +#define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) +#define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) +#define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7) +#define ESP_TASK_TCPIP_STACK (CONFIG_LWIP_TCPIP_TASK_STACK_SIZE) +#define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1) +#define ESP_TASK_MAIN_STACK (CONFIG_ESP_MAIN_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) + +#endif diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c new file mode 100644 index 000000000..c21a95729 --- /dev/null +++ b/components/esp_common/src/esp_err_to_name.c @@ -0,0 +1,426 @@ +//Do not edit this file because it is autogenerated by gen_esp_err_to_name.py + +#include +#if __has_include("esp_err.h") +#include "esp_err.h" +#endif +#if __has_include("esp_http_client.h") +#include "esp_http_client.h" +#endif +#if __has_include("esp_http_server.h") +#include "esp_http_server.h" +#endif +#if __has_include("esp_image_format.h") +#include "esp_image_format.h" +#endif +#if __has_include("esp_now.h") +#include "esp_now.h" +#endif +#if __has_include("esp_ota_ops.h") +#include "esp_ota_ops.h" +#endif +#if __has_include("esp_ping.h") +#include "esp_ping.h" +#endif +#if __has_include("esp_wifi.h") +#include "esp_wifi.h" +#endif +#if __has_include("esp_wps.h") +#include "esp_supplicant/esp_wps.h" +#endif +#if __has_include("nvs.h") +#include "nvs.h" +#endif +#if __has_include("spi_flash.h") +#include "spi_flash.h" +#endif +#if __has_include("tcpip_adapter.h") +#include "tcpip_adapter.h" +#endif + +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP +#define ERR_TBL_IT(err) {err, #err} + +typedef struct { + esp_err_t code; + const char *msg; +} esp_err_msg_t; + +static const esp_err_msg_t esp_err_msg_table[] = { + // components/esp8266/include/esp_err.h +# ifdef ESP_FAIL + ERR_TBL_IT(ESP_FAIL), /* -1 Generic esp_err_t code indicating failure */ +# endif +# ifdef ESP_OK + ERR_TBL_IT(ESP_OK), /* 0 esp_err_t value indicating success (no error) */ +# endif +# ifdef ESP_ERR_NO_MEM + ERR_TBL_IT(ESP_ERR_NO_MEM), /* 257 0x101 Out of memory */ +# endif +# ifdef ESP_ERR_INVALID_ARG + ERR_TBL_IT(ESP_ERR_INVALID_ARG), /* 258 0x102 Invalid argument */ +# endif +# ifdef ESP_ERR_INVALID_STATE + ERR_TBL_IT(ESP_ERR_INVALID_STATE), /* 259 0x103 Invalid state */ +# endif +# ifdef ESP_ERR_INVALID_SIZE + ERR_TBL_IT(ESP_ERR_INVALID_SIZE), /* 260 0x104 Invalid size */ +# endif +# ifdef ESP_ERR_NOT_FOUND + ERR_TBL_IT(ESP_ERR_NOT_FOUND), /* 261 0x105 Requested resource not found */ +# endif +# ifdef ESP_ERR_NOT_SUPPORTED + ERR_TBL_IT(ESP_ERR_NOT_SUPPORTED), /* 262 0x106 Operation or feature not supported */ +# endif +# ifdef ESP_ERR_TIMEOUT + ERR_TBL_IT(ESP_ERR_TIMEOUT), /* 263 0x107 Operation timed out */ +# endif +# ifdef ESP_ERR_INVALID_RESPONSE + ERR_TBL_IT(ESP_ERR_INVALID_RESPONSE), /* 264 0x108 Received response was invalid */ +# endif +# ifdef ESP_ERR_INVALID_CRC + ERR_TBL_IT(ESP_ERR_INVALID_CRC), /* 265 0x109 CRC or checksum was invalid */ +# endif +# ifdef ESP_ERR_INVALID_VERSION + ERR_TBL_IT(ESP_ERR_INVALID_VERSION), /* 266 0x10a Version was invalid */ +# endif +# ifdef ESP_ERR_INVALID_MAC + ERR_TBL_IT(ESP_ERR_INVALID_MAC), /* 267 0x10b MAC address was invalid */ +# endif + // components/nvs_flash/include/nvs.h +# ifdef ESP_ERR_NVS_BASE + ERR_TBL_IT(ESP_ERR_NVS_BASE), /* 4352 0x1100 Starting number of error codes */ +# endif +# ifdef ESP_ERR_NVS_NOT_INITIALIZED + ERR_TBL_IT(ESP_ERR_NVS_NOT_INITIALIZED), /* 4353 0x1101 The storage driver is not initialized */ +# endif +# ifdef ESP_ERR_NVS_NOT_FOUND + ERR_TBL_IT(ESP_ERR_NVS_NOT_FOUND), /* 4354 0x1102 Id namespace doesn’t exist yet and mode is + NVS_READONLY */ +# endif +# ifdef ESP_ERR_NVS_TYPE_MISMATCH + ERR_TBL_IT(ESP_ERR_NVS_TYPE_MISMATCH), /* 4355 0x1103 The type of set or get operation doesn't + match the type of value stored in NVS */ +# endif +# ifdef ESP_ERR_NVS_READ_ONLY + ERR_TBL_IT(ESP_ERR_NVS_READ_ONLY), /* 4356 0x1104 Storage handle was opened as read only */ +# endif +# ifdef ESP_ERR_NVS_NOT_ENOUGH_SPACE + ERR_TBL_IT(ESP_ERR_NVS_NOT_ENOUGH_SPACE), /* 4357 0x1105 There is not enough space in the underlying + storage to save the value */ +# endif +# ifdef ESP_ERR_NVS_INVALID_NAME + ERR_TBL_IT(ESP_ERR_NVS_INVALID_NAME), /* 4358 0x1106 Namespace name doesn’t satisfy constraints */ +# endif +# ifdef ESP_ERR_NVS_INVALID_HANDLE + ERR_TBL_IT(ESP_ERR_NVS_INVALID_HANDLE), /* 4359 0x1107 Handle has been closed or is NULL */ +# endif +# ifdef ESP_ERR_NVS_REMOVE_FAILED + ERR_TBL_IT(ESP_ERR_NVS_REMOVE_FAILED), /* 4360 0x1108 The value wasn’t updated because flash write + operation has failed. The value was written + however, and update will be finished after + re-initialization of nvs, provided that + flash operation doesn’t fail again. */ +# endif +# ifdef ESP_ERR_NVS_KEY_TOO_LONG + ERR_TBL_IT(ESP_ERR_NVS_KEY_TOO_LONG), /* 4361 0x1109 Key name is too long */ +# endif +# ifdef ESP_ERR_NVS_PAGE_FULL + ERR_TBL_IT(ESP_ERR_NVS_PAGE_FULL), /* 4362 0x110a Internal error; never returned by nvs_ API + functions */ +# endif +# ifdef ESP_ERR_NVS_INVALID_STATE + ERR_TBL_IT(ESP_ERR_NVS_INVALID_STATE), /* 4363 0x110b NVS is in an inconsistent state due to a + previous error. Call nvs_flash_init and + nvs_open again, then retry. */ +# endif +# ifdef ESP_ERR_NVS_INVALID_LENGTH + ERR_TBL_IT(ESP_ERR_NVS_INVALID_LENGTH), /* 4364 0x110c String or blob length is not sufficient to + store data */ +# endif +# ifdef ESP_ERR_NVS_NO_FREE_PAGES + ERR_TBL_IT(ESP_ERR_NVS_NO_FREE_PAGES), /* 4365 0x110d NVS partition doesn't contain any empty + pages. This may happen if NVS partition was + truncated. Erase the whole partition and + call nvs_flash_init again. */ +# endif +# ifdef ESP_ERR_NVS_VALUE_TOO_LONG + ERR_TBL_IT(ESP_ERR_NVS_VALUE_TOO_LONG), /* 4366 0x110e String or blob length is longer than + supported by the implementation */ +# endif +# ifdef ESP_ERR_NVS_PART_NOT_FOUND + ERR_TBL_IT(ESP_ERR_NVS_PART_NOT_FOUND), /* 4367 0x110f Partition with specified name is not found + in the partition table */ +# endif + // components/app_update/include/esp_ota_ops.h +# ifdef ESP_ERR_OTA_BASE + ERR_TBL_IT(ESP_ERR_OTA_BASE), /* 5376 0x1500 Base error code for ota_ops api */ +# endif +# ifdef ESP_ERR_OTA_PARTITION_CONFLICT + ERR_TBL_IT(ESP_ERR_OTA_PARTITION_CONFLICT), /* 5377 0x1501 Error if request was to write or erase the + current running partition */ +# endif +# ifdef ESP_ERR_OTA_SELECT_INFO_INVALID + ERR_TBL_IT(ESP_ERR_OTA_SELECT_INFO_INVALID), /* 5378 0x1502 Error if OTA data partition contains invalid + content */ +# endif +# ifdef ESP_ERR_OTA_VALIDATE_FAILED + ERR_TBL_IT(ESP_ERR_OTA_VALIDATE_FAILED), /* 5379 0x1503 Error if OTA app image is invalid */ +# endif + // components/bootloader_support/include/esp_image_format.h +# ifdef ESP_ERR_IMAGE_BASE + ERR_TBL_IT(ESP_ERR_IMAGE_BASE), /* 8192 0x2000 */ +# endif +# ifdef ESP_ERR_IMAGE_FLASH_FAIL + ERR_TBL_IT(ESP_ERR_IMAGE_FLASH_FAIL), /* 8193 0x2001 */ +# endif +# ifdef ESP_ERR_IMAGE_INVALID + ERR_TBL_IT(ESP_ERR_IMAGE_INVALID), /* 8194 0x2002 */ +# endif + // components/esp8266/include/esp_err.h +# ifdef ESP_ERR_WIFI_BASE + ERR_TBL_IT(ESP_ERR_WIFI_BASE), /* 12288 0x3000 Starting number of WiFi error codes */ +# endif + // components/esp8266/include/esp_wifi.h +# ifdef ESP_ERR_WIFI_NOT_INIT + ERR_TBL_IT(ESP_ERR_WIFI_NOT_INIT), /* 12289 0x3001 WiFi driver was not installed by esp_wifi_init */ +# endif +# ifdef ESP_ERR_WIFI_NOT_STARTED + ERR_TBL_IT(ESP_ERR_WIFI_NOT_STARTED), /* 12290 0x3002 WiFi driver was not started by esp_wifi_start */ +# endif +# ifdef ESP_ERR_WIFI_NOT_STOPPED + ERR_TBL_IT(ESP_ERR_WIFI_NOT_STOPPED), /* 12291 0x3003 WiFi driver was not stopped by esp_wifi_stop */ +# endif +# ifdef ESP_ERR_WIFI_IF + ERR_TBL_IT(ESP_ERR_WIFI_IF), /* 12292 0x3004 WiFi interface error */ +# endif +# ifdef ESP_ERR_WIFI_MODE + ERR_TBL_IT(ESP_ERR_WIFI_MODE), /* 12293 0x3005 WiFi mode error */ +# endif +# ifdef ESP_ERR_WIFI_STATE + ERR_TBL_IT(ESP_ERR_WIFI_STATE), /* 12294 0x3006 WiFi internal state error */ +# endif +# ifdef ESP_ERR_WIFI_CONN + ERR_TBL_IT(ESP_ERR_WIFI_CONN), /* 12295 0x3007 WiFi internal control block of station or + soft-AP error */ +# endif +# ifdef ESP_ERR_WIFI_NVS + ERR_TBL_IT(ESP_ERR_WIFI_NVS), /* 12296 0x3008 WiFi internal NVS module error */ +# endif +# ifdef ESP_ERR_WIFI_MAC + ERR_TBL_IT(ESP_ERR_WIFI_MAC), /* 12297 0x3009 MAC address is invalid */ +# endif +# ifdef ESP_ERR_WIFI_SSID + ERR_TBL_IT(ESP_ERR_WIFI_SSID), /* 12298 0x300a SSID is invalid */ +# endif +# ifdef ESP_ERR_WIFI_PASSWORD + ERR_TBL_IT(ESP_ERR_WIFI_PASSWORD), /* 12299 0x300b Password is invalid */ +# endif +# ifdef ESP_ERR_WIFI_TIMEOUT + ERR_TBL_IT(ESP_ERR_WIFI_TIMEOUT), /* 12300 0x300c Timeout error */ +# endif +# ifdef ESP_ERR_WIFI_WAKE_FAIL + ERR_TBL_IT(ESP_ERR_WIFI_WAKE_FAIL), /* 12301 0x300d WiFi is in sleep state(RF closed) and wakeup fail */ +# endif +# ifdef ESP_ERR_WIFI_WOULD_BLOCK + ERR_TBL_IT(ESP_ERR_WIFI_WOULD_BLOCK), /* 12302 0x300e The caller would block */ +# endif +# ifdef ESP_ERR_WIFI_NOT_CONNECT + ERR_TBL_IT(ESP_ERR_WIFI_NOT_CONNECT), /* 12303 0x300f Station still in disconnect status */ +# endif +# ifdef ESP_ERR_WIFI_PM_MODE_OPEN + ERR_TBL_IT(ESP_ERR_WIFI_PM_MODE_OPEN), /* 12306 0x3012 Wifi is in min/max modem sleep mode */ +# endif +# ifdef ESP_ERR_WIFI_FPM_MODE + ERR_TBL_IT(ESP_ERR_WIFI_FPM_MODE), /* 12307 0x3013 Have not enable fpm mode */ +# endif + // components/wpa_supplicant/include/esp_supplicant/esp_wps.h +# ifdef ESP_ERR_WIFI_REGISTRAR + ERR_TBL_IT(ESP_ERR_WIFI_REGISTRAR), /* 12339 0x3033 WPS registrar is not supported */ +# endif +# ifdef ESP_ERR_WIFI_WPS_TYPE + ERR_TBL_IT(ESP_ERR_WIFI_WPS_TYPE), /* 12340 0x3034 WPS type error */ +# endif +# ifdef ESP_ERR_WIFI_WPS_SM + ERR_TBL_IT(ESP_ERR_WIFI_WPS_SM), /* 12341 0x3035 WPS state machine is not initialized */ +# endif + // components/esp8266/include/esp_now.h +# ifdef ESP_ERR_ESPNOW_BASE + ERR_TBL_IT(ESP_ERR_ESPNOW_BASE), /* 12388 0x3064 ESPNOW error number base. */ +# endif +# ifdef ESP_ERR_ESPNOW_NOT_INIT + ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_INIT), /* 12389 0x3065 ESPNOW is not initialized. */ +# endif +# ifdef ESP_ERR_ESPNOW_ARG + ERR_TBL_IT(ESP_ERR_ESPNOW_ARG), /* 12390 0x3066 Invalid argument */ +# endif +# ifdef ESP_ERR_ESPNOW_NO_MEM + ERR_TBL_IT(ESP_ERR_ESPNOW_NO_MEM), /* 12391 0x3067 Out of memory */ +# endif +# ifdef ESP_ERR_ESPNOW_FULL + ERR_TBL_IT(ESP_ERR_ESPNOW_FULL), /* 12392 0x3068 ESPNOW peer list is full */ +# endif +# ifdef ESP_ERR_ESPNOW_NOT_FOUND + ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_FOUND), /* 12393 0x3069 ESPNOW peer is not found */ +# endif +# ifdef ESP_ERR_ESPNOW_INTERNAL + ERR_TBL_IT(ESP_ERR_ESPNOW_INTERNAL), /* 12394 0x306a Internal error */ +# endif +# ifdef ESP_ERR_ESPNOW_EXIST + ERR_TBL_IT(ESP_ERR_ESPNOW_EXIST), /* 12395 0x306b ESPNOW peer has existed */ +# endif +# ifdef ESP_ERR_ESPNOW_IF + ERR_TBL_IT(ESP_ERR_ESPNOW_IF), /* 12396 0x306c Interface error */ +# endif + // components/esp8266/include/esp_err.h +# ifdef ESP_ERR_MESH_BASE + ERR_TBL_IT(ESP_ERR_MESH_BASE), /* 16384 0x4000 Starting number of MESH error codes */ +# endif + // components/tcpip_adapter/include/tcpip_adapter.h +# ifdef ESP_ERR_TCPIP_ADAPTER_BASE + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_BASE), /* 20480 0x5000 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS), /* 20481 0x5001 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY), /* 20482 0x5002 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED), /* 20483 0x5003 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED), /* 20484 0x5004 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED), /* 20485 0x5005 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_NO_MEM + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_NO_MEM), /* 20486 0x5006 */ +# endif +# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED + ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED), /* 20487 0x5007 */ +# endif + // components/lwip/include/lwip/apps/esp_ping.h +# ifdef ESP_ERR_PING_BASE + ERR_TBL_IT(ESP_ERR_PING_BASE), /* 24576 0x6000 */ +# endif +# ifdef ESP_ERR_PING_INVALID_PARAMS + ERR_TBL_IT(ESP_ERR_PING_INVALID_PARAMS), /* 24577 0x6001 */ +# endif +# ifdef ESP_ERR_PING_NO_MEM + ERR_TBL_IT(ESP_ERR_PING_NO_MEM), /* 24578 0x6002 */ +# endif + // components/esp_http_client/include/esp_http_client.h +# ifdef ESP_ERR_HTTP_BASE + ERR_TBL_IT(ESP_ERR_HTTP_BASE), /* 28672 0x7000 Starting number of HTTP error codes */ +# endif +# ifdef ESP_ERR_HTTP_MAX_REDIRECT + ERR_TBL_IT(ESP_ERR_HTTP_MAX_REDIRECT), /* 28673 0x7001 The error exceeds the number of HTTP redirects */ +# endif +# ifdef ESP_ERR_HTTP_CONNECT + ERR_TBL_IT(ESP_ERR_HTTP_CONNECT), /* 28674 0x7002 Error open the HTTP connection */ +# endif +# ifdef ESP_ERR_HTTP_WRITE_DATA + ERR_TBL_IT(ESP_ERR_HTTP_WRITE_DATA), /* 28675 0x7003 Error write HTTP data */ +# endif +# ifdef ESP_ERR_HTTP_FETCH_HEADER + ERR_TBL_IT(ESP_ERR_HTTP_FETCH_HEADER), /* 28676 0x7004 Error read HTTP header from server */ +# endif +# ifdef ESP_ERR_HTTP_INVALID_TRANSPORT + ERR_TBL_IT(ESP_ERR_HTTP_INVALID_TRANSPORT), /* 28677 0x7005 There are no transport support for the input + scheme */ +# endif +# ifdef ESP_ERR_HTTP_CONNECTING + ERR_TBL_IT(ESP_ERR_HTTP_CONNECTING), /* 28678 0x7006 HTTP connection hasn't been established yet */ +# endif +# ifdef ESP_ERR_HTTP_EAGAIN + ERR_TBL_IT(ESP_ERR_HTTP_EAGAIN), /* 28679 0x7007 Mapping of errno EAGAIN to esp_err_t */ +# endif + // components/esp_http_server/include/esp_http_server.h +# ifdef ESP_ERR_HTTPD_BASE + ERR_TBL_IT(ESP_ERR_HTTPD_BASE), /* 32768 0x8000 Starting number of HTTPD error codes */ +# endif +# ifdef ESP_ERR_HTTPD_HANDLERS_FULL + ERR_TBL_IT(ESP_ERR_HTTPD_HANDLERS_FULL), /* 32769 0x8001 All slots for registering URI handlers have + been consumed */ +# endif +# ifdef ESP_ERR_HTTPD_HANDLER_EXISTS + ERR_TBL_IT(ESP_ERR_HTTPD_HANDLER_EXISTS), /* 32770 0x8002 URI handler with same method and target URI + already registered */ +# endif +# ifdef ESP_ERR_HTTPD_INVALID_REQ + ERR_TBL_IT(ESP_ERR_HTTPD_INVALID_REQ), /* 32771 0x8003 Invalid request pointer */ +# endif +# ifdef ESP_ERR_HTTPD_RESULT_TRUNC + ERR_TBL_IT(ESP_ERR_HTTPD_RESULT_TRUNC), /* 32772 0x8004 Result string truncated */ +# endif +# ifdef ESP_ERR_HTTPD_RESP_HDR + ERR_TBL_IT(ESP_ERR_HTTPD_RESP_HDR), /* 32773 0x8005 Response header field larger than supported */ +# endif +# ifdef ESP_ERR_HTTPD_RESP_SEND + ERR_TBL_IT(ESP_ERR_HTTPD_RESP_SEND), /* 32774 0x8006 Error occured while sending response packet */ +# endif +# ifdef ESP_ERR_HTTPD_ALLOC_MEM + ERR_TBL_IT(ESP_ERR_HTTPD_ALLOC_MEM), /* 32775 0x8007 Failed to dynamically allocate memory for + resource */ +# endif +# ifdef ESP_ERR_HTTPD_TASK + ERR_TBL_IT(ESP_ERR_HTTPD_TASK), /* 32776 0x8008 Failed to launch server task/thread */ +# endif + // components/spi_flash/include/spi_flash.h +# ifdef ESP_ERR_FLASH_BASE + ERR_TBL_IT(ESP_ERR_FLASH_BASE), /* 65552 0x10010 */ +# endif +# ifdef ESP_ERR_FLASH_OP_FAIL + ERR_TBL_IT(ESP_ERR_FLASH_OP_FAIL), /* 65553 0x10011 */ +# endif +# ifdef ESP_ERR_FLASH_OP_TIMEOUT + ERR_TBL_IT(ESP_ERR_FLASH_OP_TIMEOUT), /* 65554 0x10012 */ +# endif +}; +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + +static const char esp_unknown_msg[] = +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + "ERROR"; +#else + "UNKNOWN ERROR"; +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + +const char *esp_err_to_name(esp_err_t code) +{ +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + int i; + + for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) { + if (esp_err_msg_table[i].code == code) { + return esp_err_msg_table[i].msg; + } + } +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + + return esp_unknown_msg; +} + +const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen) +{ +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + int i; + + for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) { + if (esp_err_msg_table[i].code == code) { + strlcpy(buf, esp_err_msg_table[i].msg, buflen); + return buf; + } + } +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + + if (strerror_r(code, buf, buflen) == 0) { + return buf; + } + + snprintf(buf, buflen, "%s 0x%x(%d)", esp_unknown_msg, code, code); + + return buf; +} diff --git a/components/esp_common/src/stack_check.c b/components/esp_common/src/stack_check.c new file mode 100644 index 000000000..a820004b1 --- /dev/null +++ b/components/esp_common/src/stack_check.c @@ -0,0 +1,40 @@ +// Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "sdkconfig.h" +#include "esp_system.h" + +#if CONFIG_COMPILER_STACK_CHECK + +#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include "esp_log.h" +const static char *TAG = "stack_chk"; + +void *__stack_chk_guard = NULL; + +static void __attribute__ ((constructor)) +__esp_stack_guard_setup (void) +{ + ESP_LOGD(TAG, "Intialize random stack guard"); + __stack_chk_guard = (void *)esp_random(); +} + +void __stack_chk_fail (void) +{ + ets_printf("\r\nStack smashing protect failure!\r\n\r\n"); + abort(); +} + +#endif diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt new file mode 100644 index 000000000..5f6511742 --- /dev/null +++ b/components/esp_event/CMakeLists.txt @@ -0,0 +1,13 @@ +idf_component_register(SRCS "default_event_loop.c" + "esp_event.c" + "esp_event_private.c" + "event_loop_legacy.c" + "event_send.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES log tcpip_adapter) + +if(GCC_NOT_5_2_0 AND CONFIG_ESP_EVENT_LOOP_PROFILING) + # uses C11 atomic feature + set_source_files_properties(esp_event.c PROPERTIES COMPILE_FLAGS -std=gnu11) +endif() diff --git a/components/esp_event/Kconfig b/components/esp_event/Kconfig new file mode 100644 index 000000000..ce3c50fd3 --- /dev/null +++ b/components/esp_event/Kconfig @@ -0,0 +1,17 @@ +menu "Event Loop Library" + + config ESP_EVENT_LOOP_PROFILING + bool "Enable event loop profiling" + default n + help + Enables collections of statistics in the event loop library such as the number of events posted + to/recieved by an event loop, number of callbacks involved, number of events dropped to to a full event + loop queue, run time of event handlers, and number of times/run time of each event handler. + + config ESP_EVENT_POST_FROM_ISR + bool "Support posting events from ISRs" + default y + help + Enable posting events from interrupt handlers. + +endmenu diff --git a/components/esp_event/component.mk b/components/esp_event/component.mk new file mode 100644 index 000000000..c59eccc41 --- /dev/null +++ b/components/esp_event/component.mk @@ -0,0 +1,17 @@ +# +# Component Makefile +# +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include +COMPONENT_SRCDIRS := . + +ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + PROFILING_ENABLED := 1 +else + PROFILING_ENABLED := 0 +endif + +ifeq ($(and $(GCC_NOT_5_2_0),$(PROFILING_ENABLED)), 1) +# uses C11 atomic feature +esp_event.o: CFLAGS += -std=gnu11 +endif diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c new file mode 100644 index 000000000..01418c72a --- /dev/null +++ b/components/esp_event/default_event_loop.c @@ -0,0 +1,120 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event.h" +#include "esp_event_internal.h" +#include "esp_task.h" + +/* ------------------------- Static Variables ------------------------------- */ + +static esp_event_loop_handle_t s_default_loop = NULL; + +/* ---------------------------- Public API ---------------------------------- */ + +esp_err_t esp_event_handler_register(esp_event_base_t event_base, int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_register_with(s_default_loop, event_base, event_id, + event_handler, event_handler_arg); +} + +esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, + esp_event_handler_t event_handler) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_unregister_with(s_default_loop, event_base, event_id, + event_handler); +} + +esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, TickType_t ticks_to_wait) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_post_to(s_default_loop, event_base, event_id, + event_data, event_data_size, ticks_to_wait); +} + + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +esp_err_t esp_event_isr_post(esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_isr_post_to(s_default_loop, event_base, event_id, + event_data, event_data_size, task_unblocked); +} +#endif + + +esp_err_t esp_event_loop_create_default() +{ + if (s_default_loop) { + return ESP_ERR_INVALID_STATE; + } + + esp_event_loop_args_t loop_args = { + .queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE, + .task_name = "sys_evt", + .task_stack_size = ESP_TASKD_EVENT_STACK, + .task_priority = ESP_TASKD_EVENT_PRIO, + .task_core_id = 0 + }; + + esp_err_t err; + + err = esp_event_loop_create(&loop_args, &s_default_loop); + if (err != ESP_OK) { + return err; + } + + return ESP_OK; +} + +esp_err_t esp_event_loop_delete_default() +{ + if (!s_default_loop) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err; + + err = esp_event_loop_delete(s_default_loop); + + if (err != ESP_OK) { + return err; + } + + s_default_loop = NULL; + + return ESP_OK; +} + + +/* Include the code to forward legacy system_event_t events to the this default + * event loop. + */ +#include "event_send_compat.inc" diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c new file mode 100644 index 000000000..99a3cf70b --- /dev/null +++ b/components/esp_event/esp_event.c @@ -0,0 +1,944 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_log.h" + +#include "esp_event.h" +#include "esp_event_internal.h" +#include "esp_event_private.h" + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +#include "esp_timer.h" +#endif + +/* ---------------------------- Definitions --------------------------------- */ + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +// LOOP @ rx: dr: +#define LOOP_DUMP_FORMAT "LOOP @%p,%s rx:%u dr:%u\n" + // handler @
ev: inv: time: +#define HANDLER_DUMP_FORMAT " HANDLER @%p ev:%s,%s inv:%u time:%lld us\n" + +#define PRINT_DUMP_INFO(dst, sz, ...) do { \ + int cb = snprintf(dst, sz, __VA_ARGS__); \ + dst += cb; \ + sz -= cb; \ + } while(0); +#endif + +/* ------------------------- Static Variables ------------------------------- */ + +static const char* TAG = "event"; +static const char* esp_event_any_base = "any"; + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +static SLIST_HEAD(esp_event_loop_instance_list_t, esp_event_loop_instance) s_event_loops = + SLIST_HEAD_INITIALIZER(s_event_loops); + +static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED; +#endif + + +/* ------------------------- Static Functions ------------------------------- */ + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + + +static int esp_event_dump_prepare() +{ + esp_event_loop_instance_t* loop_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; + esp_event_handler_instance_t* handler_it; + + // Count the number of items to be printed. This is needed to compute how much memory to reserve. + int loops = 0, handlers = 0; + + portENTER_CRITICAL(&s_event_loops_spinlock); + + SLIST_FOREACH(loop_it, &s_event_loops, next) { + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { + handlers++; + } + + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { + handlers++; + } + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + handlers++; + } + } + } + } + loops++; + } + + portEXIT_CRITICAL(&s_event_loops_spinlock); + + // Reserve slightly more memory than computed + int allowance = 3; + int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 2 * 11)) + + ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 2 * 20 + 11 + 20))); + + return size; +} +#endif + +static void esp_event_loop_run_task(void* args) +{ + esp_err_t err; + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + ESP_LOGD(TAG, "running task for loop %p", event_loop); + + while(1) { + err = esp_event_loop_run(event_loop, portMAX_DELAY); + if (err != ESP_OK) { + break; + } + } + + ESP_LOGE(TAG, "suspended task for loop %p", event_loop); + vTaskSuspend(NULL); +} + +static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_instance_t *handler, esp_event_post_instance_t post) +{ + ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, handler->handler, loop); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + int64_t start, diff; + start = esp_timer_get_time(); +#endif + // Execute the handler +#if CONFIG_ESP_EVENT_POST_FROM_ISR + void* data_ptr = NULL; + + if (post.data_set) { + if (post.data_allocated) { + data_ptr = post.data.ptr; + } else { + data_ptr = &post.data.val; + } + } + + (*(handler->handler))(handler->arg, post.base, post.id, data_ptr); +#else + (*(handler->handler))(handler->arg, post.base, post.id, post.data); +#endif + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + diff = esp_timer_get_time() - start; + + xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); + + handler->invoked++; + handler->time += diff; + + xSemaphoreGive(loop->profiling_mutex); +#endif +} + +static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_t handler, void* handler_arg) +{ + esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance)); + + if (!handler_instance) { + return ESP_ERR_NO_MEM; + } + + handler_instance->handler = handler; + handler_instance->arg = handler_arg; + + if (SLIST_EMPTY(handlers)) { + SLIST_INSERT_HEAD(handlers, handler_instance, next); + } + else { + esp_event_handler_instance_t *it = NULL, *last = NULL; + + SLIST_FOREACH(it, handlers, next) { + if (handler == it->handler) { + it->arg = handler_arg; + ESP_LOGW(TAG, "handler already registered, overwriting"); + free(handler_instance); + return ESP_OK; + } + last = it; + } + + SLIST_INSERT_AFTER(last, handler_instance, next); + } + + return ESP_OK; +} + +static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler, void* handler_arg) +{ + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(base_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_id_node_t *it = NULL, *id_node = NULL, *last_id_node = NULL; + + SLIST_FOREACH(it, &(base_node->id_nodes), next) { + if (it->id == id) { + id_node = it; + } + last_id_node = it; + } + + if (!last_id_node || !id_node) { + id_node = (esp_event_id_node_t*) calloc(1, sizeof(*id_node)); + + if (!id_node) { + ESP_LOGE(TAG, "alloc for new id node failed"); + return ESP_ERR_NO_MEM; + } + + id_node->id = id; + + SLIST_INIT(&(id_node->handlers)); + + err = handler_instances_add(&(id_node->handlers), handler, handler_arg); + + if (err == ESP_OK) { + if (!last_id_node) { + SLIST_INSERT_HEAD(&(base_node->id_nodes), id_node, next); + } + else { + SLIST_INSERT_AFTER(last_id_node, id_node, next); + } + } else { + free(id_node); + } + + return err; + } + else { + return handler_instances_add(&(id_node->handlers), handler, handler_arg); + } + } +} + +static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler, void* handler_arg) +{ + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(loop_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_base_node_t *it = NULL, *base_node = NULL, *last_base_node = NULL; + + SLIST_FOREACH(it, &(loop_node->base_nodes), next) { + if (it->base == base) { + base_node = it; + } + last_base_node = it; + } + + if (!last_base_node || + !base_node || + (base_node && !SLIST_EMPTY(&(base_node->id_nodes)) && id == ESP_EVENT_ANY_ID) || + (last_base_node && last_base_node->base != base && !SLIST_EMPTY(&(last_base_node->id_nodes)) && id == ESP_EVENT_ANY_ID)) { + base_node = (esp_event_base_node_t*) calloc(1, sizeof(*base_node)); + + if (!base_node) { + ESP_LOGE(TAG, "alloc mem for new base node failed"); + return ESP_ERR_NO_MEM; + } + + base_node->base = base; + + SLIST_INIT(&(base_node->handlers)); + SLIST_INIT(&(base_node->id_nodes)); + + err = base_node_add_handler(base_node, id, handler, handler_arg); + + if (err == ESP_OK) { + if (!last_base_node) { + SLIST_INSERT_HEAD(&(loop_node->base_nodes), base_node, next); + } + else { + SLIST_INSERT_AFTER(last_base_node, base_node, next); + } + } else { + free(base_node); + } + + return err; + } else { + return base_node_add_handler(base_node, id, handler, handler_arg); + } + } +} + +static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_t handler) +{ + esp_event_handler_instance_t *it, *temp; + + SLIST_FOREACH_SAFE(it, handlers, next, temp) { + if (it->handler == handler) { + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); + return ESP_OK; + } + } + + return ESP_ERR_NOT_FOUND; +} + + +static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler) +{ + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(base_node->handlers), handler); + } + else { + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + if (it->id == id) { + esp_err_t res = handler_instances_remove(&(it->handlers), handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; +} + +static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler) +{ + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(loop_node->handlers), handler); + } + else { + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + if (it->base == base) { + esp_err_t res = base_node_remove_handler(it, id, handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers)) && SLIST_EMPTY(&(it->id_nodes))) { + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; +} + +static void handler_instances_remove_all(esp_event_handler_instances_t* handlers) +{ + esp_event_handler_instance_t *it, *temp; + SLIST_FOREACH_SAFE(it, handlers, next, temp) { + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); + } +} + +static void base_node_remove_all_handler(esp_event_base_node_t* base_node) +{ + handler_instances_remove_all(&(base_node->handlers)); + + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + handler_instances_remove_all(&(it->handlers)); + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); + } +} + +static void loop_node_remove_all_handler(esp_event_loop_node_t* loop_node) +{ + handler_instances_remove_all(&(loop_node->handlers)); + + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + base_node_remove_all_handler(it); + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); + } +} + +static void inline __attribute__((always_inline)) post_instance_delete(esp_event_post_instance_t* post) +{ +#if CONFIG_ESP_EVENT_POST_FROM_ISR + if (post->data_allocated && post->data.ptr) { + free(post->data.ptr); + } +#else + if (post->data) { + free(post->data); + } +#endif + memset(post, 0, sizeof(*post)); +} + +/* ---------------------------- Public API --------------------------------- */ + +esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop) +{ + assert(event_loop_args); + + esp_event_loop_instance_t* loop; + esp_err_t err = ESP_ERR_NO_MEM; // most likely error + + loop = calloc(1, sizeof(*loop)); + if (loop == NULL) { + ESP_LOGE(TAG, "alloc for event loop failed"); + return err; + } + + loop->queue = xQueueCreate(event_loop_args->queue_size , sizeof(esp_event_post_instance_t)); + if (loop->queue == NULL) { + ESP_LOGE(TAG, "create event loop queue failed"); + goto on_err; + } + + loop->mutex = xSemaphoreCreateRecursiveMutex(); + if (loop->mutex == NULL) { + ESP_LOGE(TAG, "create event loop mutex failed"); + goto on_err; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + loop->profiling_mutex = xSemaphoreCreateMutex(); + if (loop->profiling_mutex == NULL) { + ESP_LOGE(TAG, "create event loop profiling mutex failed"); + goto on_err; + } +#endif + + SLIST_INIT(&(loop->loop_nodes)); + + // Create the loop task if requested + if (event_loop_args->task_name != NULL) { + BaseType_t task_created = xTaskCreatePinnedToCore(esp_event_loop_run_task, event_loop_args->task_name, + event_loop_args->task_stack_size, (void*) loop, + event_loop_args->task_priority, &(loop->task), event_loop_args->task_core_id); + + if (task_created != pdPASS) { + ESP_LOGE(TAG, "create task for loop failed"); + err = ESP_FAIL; + goto on_err; + } + + loop->name = event_loop_args->task_name; + + ESP_LOGD(TAG, "created task for loop %p", loop); + } else { + loop->name = ""; + loop->task = NULL; + } + + loop->running_task = NULL; + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + portENTER_CRITICAL(&s_event_loops_spinlock); + SLIST_INSERT_HEAD(&s_event_loops, loop, next); + portEXIT_CRITICAL(&s_event_loops_spinlock); +#endif + + *event_loop = (esp_event_loop_handle_t) loop; + + ESP_LOGD(TAG, "created event loop %p", loop); + + return ESP_OK; + +on_err: + if (loop->queue != NULL) { + vQueueDelete(loop->queue); + } + + if (loop->mutex != NULL) { + vSemaphoreDelete(loop->mutex); + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + if (loop->profiling_mutex != NULL) { + vSemaphoreDelete(loop->profiling_mutex); + } +#endif + + free(loop); + + return err; +} + +// On event lookup performance: The library implements the event list as a linked list, which results to O(n) +// lookup time. The test comparing this implementation to the O(lg n) performance of rbtrees +// (https://github.com/freebsd/freebsd/blob/master/sys/sys/tree.h) +// indicate that the difference is not that substantial, especially considering the additional +// pointers per node of rbtrees. Code for the rbtree implementation of the event loop library is archived +// in feature/esp_event_loop_library_rbtrees if needed. +esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run) +{ + assert(event_loop); + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + esp_event_post_instance_t post; + TickType_t marker = xTaskGetTickCount(); + TickType_t end = 0; + +#if (configUSE_16_BIT_TICKS == 1) + int32_t remaining_ticks = ticks_to_run; +#else + int64_t remaining_ticks = ticks_to_run; +#endif + + while(xQueueReceive(loop->queue, &post, ticks_to_run) == pdTRUE) { + // The event has already been unqueued, so ensure it gets executed. + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + loop->running_task = xTaskGetCurrentTaskHandle(); + + bool exec = false; + + esp_event_handler_instance_t *handler; + esp_event_loop_node_t *loop_node; + esp_event_base_node_t *base_node; + esp_event_id_node_t *id_node; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + // Execute loop level handlers + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == post.base) { + // Execute base level handlers + SLIST_FOREACH(handler, &(base_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if (id_node->id == post.id) { + // Execute id level handlers + SLIST_FOREACH(handler, &(id_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + // Skip to next base node + break; + } + } + } + } + } + + esp_event_base_t base = post.base; + int32_t id = post.id; + + post_instance_delete(&post); + + if (ticks_to_run != portMAX_DELAY) { + end = xTaskGetTickCount(); + remaining_ticks -= end - marker; + // If the ticks to run expired, return to the caller + if (remaining_ticks <= 0) { + xSemaphoreGiveRecursive(loop->mutex); + break; + } else { + marker = end; + } + } + + loop->running_task = NULL; + + xSemaphoreGiveRecursive(loop->mutex); + + if (!exec) { + // No handlers were registered, not even loop/base level handlers + ESP_LOGD(TAG, "no handlers have been registered for event %s:%d posted to loop %p", base, id, event_loop); + } + } + + return ESP_OK; +} + +esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) +{ + assert(event_loop); + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + SemaphoreHandle_t loop_mutex = loop->mutex; +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + SemaphoreHandle_t loop_profiling_mutex = loop->profiling_mutex; +#endif + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + xSemaphoreTakeRecursive(loop->profiling_mutex, portMAX_DELAY); + portENTER_CRITICAL(&s_event_loops_spinlock); + SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, next); + portEXIT_CRITICAL(&s_event_loops_spinlock); +#endif + + // Delete the task if it was created + if (loop->task != NULL) { + vTaskDelete(loop->task); + } + + // Remove all registered events and handlers in the loop + esp_event_loop_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + loop_node_remove_all_handler(it); + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + } + + // Drop existing posts on the queue + esp_event_post_instance_t post; + while(xQueueReceive(loop->queue, &post, 0) == pdTRUE) { + post_instance_delete(&post); + } + + // Cleanup loop + vQueueDelete(loop->queue); + free(loop); + // Free loop mutex before deleting + xSemaphoreGiveRecursive(loop_mutex); +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + xSemaphoreGiveRecursive(loop_profiling_mutex); + vSemaphoreDelete(loop_profiling_mutex); +#endif + vSemaphoreDelete(loop_mutex); + + ESP_LOGD(TAG, "deleted loop %p", (void*) event_loop); + + return ESP_OK; +} + +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg) +{ + assert(event_loop); + assert(event_handler); + + if (event_base == ESP_EVENT_ANY_BASE && event_id != ESP_EVENT_ANY_ID) { + ESP_LOGE(TAG, "registering to any event base with specific id unsupported"); + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + if (event_base == ESP_EVENT_ANY_BASE) { + event_base = esp_event_any_base; + } + + esp_err_t err = ESP_OK; + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + esp_event_loop_node_t *loop_node = NULL, *last_loop_node = NULL; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + last_loop_node = loop_node; + } + + bool is_loop_level_handler = (event_base == esp_event_any_base) && (event_id == ESP_EVENT_ANY_ID); + + if (!last_loop_node || + (last_loop_node && !SLIST_EMPTY(&(last_loop_node->base_nodes)) && is_loop_level_handler)) { + loop_node = (esp_event_loop_node_t*) calloc(1, sizeof(*loop_node)); + + SLIST_INIT(&(loop_node->handlers)); + SLIST_INIT(&(loop_node->base_nodes)); + + if (!loop_node) { + ESP_LOGE(TAG, "alloc for new loop node failed"); + err = ESP_ERR_NO_MEM; + goto on_err; + } + + err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg); + + if (err == ESP_OK) { + if (!last_loop_node) { + SLIST_INSERT_HEAD(&(loop->loop_nodes), loop_node, next); + } + else { + SLIST_INSERT_AFTER(last_loop_node, loop_node, next); + } + } else { + free(loop_node); + } + } + else { + err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg); + } + +on_err: + xSemaphoreGiveRecursive(loop->mutex); + return err; +} + +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler) +{ + assert(event_loop); + assert(event_handler); + + if (event_base == ESP_EVENT_ANY_BASE && event_id != ESP_EVENT_ANY_ID) { + ESP_LOGE(TAG, "unregistering to any event base with specific id unsupported"); + return ESP_FAIL; + } + + if (event_base == ESP_EVENT_ANY_BASE) { + event_base = esp_event_any_base; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + esp_event_loop_node_t *it, *temp; + + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + esp_err_t res = loop_node_remove_handler(it, event_base, event_id, event_handler); + + if (res == ESP_OK && SLIST_EMPTY(&(it->base_nodes)) && SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + break; + } + } + + xSemaphoreGiveRecursive(loop->mutex); + + return ESP_OK; +} + +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, TickType_t ticks_to_wait) +{ + assert(event_loop); + + if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + esp_event_post_instance_t post; + memset((void*)(&post), 0, sizeof(post)); + + if (event_data != NULL && event_data_size != 0) { + // Make persistent copy of event data on heap. + void* event_data_copy = calloc(1, event_data_size); + + if (event_data_copy == NULL) { + return ESP_ERR_NO_MEM; + } + + memcpy(event_data_copy, event_data, event_data_size); +#if CONFIG_ESP_EVENT_POST_FROM_ISR + post.data.ptr = event_data_copy; + post.data_allocated = true; + post.data_set = true; +#else + post.data = event_data_copy; +#endif + } + post.base = event_base; + post.id = event_id; + + BaseType_t result = pdFALSE; + + // Find the task that currently executes the loop. It is safe to query loop->task since it is + // not mutated since loop creation. ENSURE THIS REMAINS TRUE. + if (loop->task == NULL) { + // The loop has no dedicated task. Find out what task is currently running it. + result = xSemaphoreTakeRecursive(loop->mutex, ticks_to_wait); + + if (result == pdTRUE) { + if (loop->running_task != xTaskGetCurrentTaskHandle()) { + xSemaphoreGiveRecursive(loop->mutex); + result = xQueueSendToBack(loop->queue, &post, ticks_to_wait); + } else { + xSemaphoreGiveRecursive(loop->mutex); + result = xQueueSendToBack(loop->queue, &post, 0); + } + } + } else { + // The loop has a dedicated task. + if (loop->task != xTaskGetCurrentTaskHandle()) { + result = xQueueSendToBack(loop->queue, &post, ticks_to_wait); + } else { + result = xQueueSendToBack(loop->queue, &post, 0); + } + } + + if (result != pdTRUE) { + post_instance_delete(&post); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_dropped, 1); +#endif + return ESP_ERR_TIMEOUT; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_recieved, 1); +#endif + + return ESP_OK; +} + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + assert(event_loop); + + if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + esp_event_post_instance_t post; + memset((void*)(&post), 0, sizeof(post)); + + if (event_data_size > sizeof(post.data.val)) { + return ESP_ERR_INVALID_ARG; + } + + if (event_data != NULL && event_data_size != 0) { + memcpy((void*)(&(post.data.val)), event_data, event_data_size); + post.data_allocated = false; + post.data_set = true; + } + post.base = event_base; + post.id = event_id; + + BaseType_t result = pdFALSE; + + // Post the event from an ISR, + result = xQueueSendToBackFromISR(loop->queue, &post, task_unblocked); + + if (result != pdTRUE) { + post_instance_delete(&post); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_dropped, 1); +#endif + return ESP_FAIL; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_recieved, 1); +#endif + + return ESP_OK; +} +#endif + +esp_err_t esp_event_dump(FILE* file) +{ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + assert(file); + + esp_event_loop_instance_t* loop_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; + esp_event_handler_instance_t* handler_it; + + // Allocate memory for printing + int sz = esp_event_dump_prepare(); + char* buf = calloc(sz, sizeof(char)); + char* dst = buf; + + char id_str_buf[20]; + + // Print info to buffer + portENTER_CRITICAL(&s_event_loops_spinlock); + + SLIST_FOREACH(loop_it, &s_event_loops, next) { + uint32_t events_recieved, events_dropped; + + events_recieved = atomic_load(&loop_it->events_recieved); + events_dropped = atomic_load(&loop_it->events_dropped); + + PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->task != NULL ? loop_it->name : "none" , + events_recieved, events_dropped); + + int sz_bak = sz; + + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, "ESP_EVENT_ANY_BASE", + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); + } + + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); + } + + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + memset(id_str_buf, 0, sizeof(id_str_buf)); + snprintf(id_str_buf, sizeof(id_str_buf), "%d", id_node_it->id); + + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + id_str_buf, handler_it->invoked, handler_it->time); + } + } + } + } + + // No handlers registered for this loop + if (sz == sz_bak) { + PRINT_DUMP_INFO(dst, sz, " NO HANDLERS REGISTERED\n"); + } + } + + portEXIT_CRITICAL(&s_event_loops_spinlock); + + // Print the contents of the buffer to the file + fprintf(file, buf); + + // Free the allocated buffer + free(buf); +#endif + return ESP_OK; +} diff --git a/components/esp_event/esp_event_private.c b/components/esp_event/esp_event_private.c new file mode 100644 index 000000000..828e458c6 --- /dev/null +++ b/components/esp_event/esp_event_private.c @@ -0,0 +1,68 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event_private.h" +#include "esp_event_internal.h" + +#include "esp_log.h" + +bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler) +{ + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + bool result = false; + + esp_event_loop_node_t* loop_node; + esp_event_base_node_t* base_node; + esp_event_id_node_t* id_node; + esp_event_handler_instance_t* handler; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == event_base) { + SLIST_FOREACH(handler, &(base_node->handlers), next) { + if(event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if(id_node->id == event_id) { + SLIST_FOREACH(handler, &(id_node->handlers), next) { + if(handler->handler == event_handler) + { + result = true; + goto out; + } + } + } + } + } + } + } + +out: + xSemaphoreGive(loop->mutex); + return result; +} \ No newline at end of file diff --git a/components/esp_event/event_loop_legacy.c b/components/esp_event/event_loop_legacy.c new file mode 100644 index 000000000..2b4615aa8 --- /dev/null +++ b/components/esp_event/event_loop_legacy.c @@ -0,0 +1,101 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_event_legacy.h" +#include "esp_event.h" + +#include "sdkconfig.h" + +static const char* TAG = "event"; + +static system_event_cb_t s_event_handler_cb; +static void *s_event_ctx; +static bool s_initialized; + +ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); + +static void esp_event_post_to_user(void* arg, esp_event_base_t base, int32_t id, void* data) +{ + if (s_event_handler_cb) { + system_event_t* event = (system_event_t*) data; + (*s_event_handler_cb)(s_event_ctx, event); + } +} + +system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) +{ + system_event_cb_t old_cb = s_event_handler_cb; + s_event_handler_cb = cb; + s_event_ctx = ctx; + return old_cb; +} + +esp_err_t esp_event_send_legacy(system_event_t *event) +{ + if (!s_initialized) { + ESP_LOGE(TAG, "system event loop not initialized via esp_event_loop_init"); + return ESP_ERR_INVALID_STATE; + } + + return esp_event_post(SYSTEM_EVENT, event->event_id, event, sizeof(*event), portMAX_DELAY); +} + +esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx) +{ + if (s_initialized) { + ESP_LOGE(TAG, "system event loop already initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = esp_event_loop_create_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + + err = esp_event_handler_register(SYSTEM_EVENT, ESP_EVENT_ANY_ID, esp_event_post_to_user, NULL); + if (err != ESP_OK) { + return err; + } + + s_initialized = true; + s_event_handler_cb = cb; + s_event_ctx = ctx; + return ESP_OK; +} + +esp_err_t esp_event_loop_deinit() +{ + if (!s_initialized) { + ESP_LOGE(TAG, "system event loop not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = esp_event_handler_unregister(SYSTEM_EVENT, ESP_EVENT_ANY_ID, esp_event_post_to_user); + if (err != ESP_OK) { + return err; + } + + err = esp_event_loop_delete_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + + s_initialized = false; + s_event_handler_cb = NULL; + s_event_ctx = NULL; + return ESP_OK; +} + diff --git a/components/esp_event/event_send.c b/components/esp_event/event_send.c new file mode 100644 index 000000000..2c31ee0f6 --- /dev/null +++ b/components/esp_event/event_send.c @@ -0,0 +1,45 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "esp_event.h" +#include "esp_event_legacy.h" + +esp_err_t esp_event_send_noop(system_event_t *event); + +extern esp_err_t esp_event_send_legacy(system_event_t *event) __attribute__((weak, alias("esp_event_send_noop"))); +extern esp_err_t esp_event_send_to_default_loop(system_event_t *event) __attribute((weak, alias("esp_event_send_noop"))); + + +esp_err_t esp_event_send_noop(system_event_t *event) +{ + return ESP_OK; +} + +esp_err_t esp_event_send(system_event_t *event) +{ + // send the event to the new style event loop + esp_err_t err = esp_event_send_to_default_loop(event); + if (err != ESP_OK) { + return err; + } + + // send the event to the legacy event loop + err = esp_event_send_legacy(event); + if (err != ESP_OK) { + return err; + } + + return ESP_OK; +} diff --git a/components/esp_event/event_send_compat.inc b/components/esp_event/event_send_compat.inc new file mode 100644 index 000000000..a920eee2f --- /dev/null +++ b/components/esp_event/event_send_compat.inc @@ -0,0 +1,281 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event.h" +#include "esp_log.h" +#include "esp_event_legacy.h" +#include "esp_wifi_types.h" +#include "tcpip_adapter.h" + +/** + * The purpose of this file is to provide an "esp_event_send_to_default_loop" + * function, which is used to forward legacy events (system_event_t) sent using + * esp_event_send, to the new default event loop (esp_event_post). + * + * For each of the events in system_event_id_t, we extract the event data from + * the corresponding system_event_info_t member, and forward that to + * esp_event_post function. + * + * Some macros are used to reduce the amount of boilerplate. + * + * Note that this function only needs to be included into the output file if + * the new default event loop is used. This function is in a separate file for + * readability reasons. In order to be linked if the contents of + * default_event_loop.c is linked, this file is #include-ed into default_event_loop.c. + */ + +//#if LOG_LOCAL_LEVEL >= 4 /* ESP_LOG_DEBUG */ +#if 1 +#define WITH_EVENT_DEBUG +#endif + +#ifdef WITH_EVENT_DEBUG +static void esp_system_event_debug(const system_event_t* event); +#endif + +#define HANDLE_SYS_EVENT(base_, name_) \ + case SYSTEM_EVENT_ ## name_: \ + return esp_event_post(base_ ## _EVENT, base_ ## _EVENT_ ## name_, \ + NULL, 0, send_timeout) + +#define HANDLE_SYS_EVENT_ARG(base_, name_, member_) \ + case SYSTEM_EVENT_ ## name_: \ + return esp_event_post(base_ ## _EVENT, base_ ## _EVENT_ ## name_, \ + &event->event_info.member_, sizeof(event->event_info.member_), \ + send_timeout) + +esp_err_t esp_event_send_to_default_loop(system_event_t *event) +{ +#ifdef WITH_EVENT_DEBUG + esp_system_event_debug(event); +#endif // WITH_EVENT_DEBUG + + const TickType_t send_timeout = 0; + switch (event->event_id) { + /* Wi-Fi common events */ + HANDLE_SYS_EVENT(WIFI, WIFI_READY); + HANDLE_SYS_EVENT_ARG(WIFI, SCAN_DONE, scan_done); + HANDLE_SYS_EVENT(WIFI, STA_START); + HANDLE_SYS_EVENT(WIFI, STA_STOP); + + /* STA events */ + HANDLE_SYS_EVENT_ARG(WIFI, STA_CONNECTED, connected); + HANDLE_SYS_EVENT_ARG(WIFI, STA_DISCONNECTED, disconnected); + HANDLE_SYS_EVENT_ARG(WIFI, STA_AUTHMODE_CHANGE, auth_change); + + /* WPS events */ + HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_SUCCESS); + HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_TIMEOUT); + HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_FAILED, sta_er_fail_reason); + HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_PIN, sta_er_pin); + HANDLE_SYS_EVENT_ARG(WIFI, STA_BSS_RSSI_LOW, bss_rssi_low); + + /* AP events */ + HANDLE_SYS_EVENT(WIFI, AP_START); + HANDLE_SYS_EVENT(WIFI, AP_STOP); + HANDLE_SYS_EVENT_ARG(WIFI, AP_STACONNECTED, sta_connected); + HANDLE_SYS_EVENT_ARG(WIFI, AP_STADISCONNECTED, sta_disconnected); + HANDLE_SYS_EVENT_ARG(WIFI, AP_PROBEREQRECVED, ap_probereqrecved); + + /* IP events */ + HANDLE_SYS_EVENT_ARG(IP, STA_GOT_IP, got_ip); + HANDLE_SYS_EVENT(IP, STA_LOST_IP); + HANDLE_SYS_EVENT_ARG(IP, GOT_IP6, got_ip6); + HANDLE_SYS_EVENT(IP, AP_STAIPASSIGNED); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +#ifdef WITH_EVENT_DEBUG + +static const char* TAG = "system_event"; + +typedef struct { + int err; + const char *reason; +} wifi_reason_t; + +static const wifi_reason_t wifi_reason[] = +{ + {0, "other reason"}, + {WIFI_REASON_UNSPECIFIED, "unspecified"}, + {WIFI_REASON_AUTH_EXPIRE, "auth expire"}, + {WIFI_REASON_AUTH_LEAVE, "auth leave"}, + {WIFI_REASON_ASSOC_EXPIRE, "assoc expire"}, + {WIFI_REASON_ASSOC_TOOMANY, "assoc too many"}, + {WIFI_REASON_NOT_AUTHED, "not authed"}, + {WIFI_REASON_NOT_ASSOCED, "not assoced"}, + {WIFI_REASON_ASSOC_LEAVE, "assoc leave"}, + {WIFI_REASON_ASSOC_NOT_AUTHED, "assoc not authed"}, + {WIFI_REASON_BEACON_TIMEOUT, "beacon timeout"}, + {WIFI_REASON_NO_AP_FOUND, "no ap found"}, + {WIFI_REASON_AUTH_FAIL, "auth fail"}, + {WIFI_REASON_ASSOC_FAIL, "assoc fail"}, + {WIFI_REASON_HANDSHAKE_TIMEOUT, "hanshake timeout"}, + {WIFI_REASON_DISASSOC_PWRCAP_BAD, "bad Power Capability, disassoc"}, + {WIFI_REASON_DISASSOC_SUPCHAN_BAD, "bad Supported Channels, disassoc"}, + {WIFI_REASON_IE_INVALID, "invalid IE"}, + {WIFI_REASON_MIC_FAILURE, "MIC failure"}, + {WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT, "4-way keying handshake timeout"}, + {WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT, "Group key handshake"}, + {WIFI_REASON_IE_IN_4WAY_DIFFERS, "IE in 4-way differs"}, + {WIFI_REASON_GROUP_CIPHER_INVALID, "invalid group cipher"}, + {WIFI_REASON_PAIRWISE_CIPHER_INVALID, "invalid pairwise cipher"}, + {WIFI_REASON_AKMP_INVALID, "invalid AKMP"}, + {WIFI_REASON_UNSUPP_RSN_IE_VERSION, "unsupported RSN IE version"}, + {WIFI_REASON_INVALID_RSN_IE_CAP, "invalid RSN IE capability"}, + {WIFI_REASON_802_1X_AUTH_FAILED, "802.1x auth failed"}, + {WIFI_REASON_CIPHER_SUITE_REJECTED, "cipher suite rejected"} +}; + +static const char* wifi_disconnect_reason_to_str(int err) +{ + for (int i=0; i< sizeof(wifi_reason)/sizeof(wifi_reason[0]); i++){ + if (err == wifi_reason[i].err){ + return wifi_reason[i].reason; + } + } + return wifi_reason[0].reason; +} + +static void esp_system_event_debug(const system_event_t* event) +{ + if (event == NULL) { + return; + } + + switch (event->event_id) { + case SYSTEM_EVENT_WIFI_READY: { + ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY"); + break; + } + case SYSTEM_EVENT_SCAN_DONE: { + const system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done; + ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d", scan_done->status, scan_done->number); + break; + } + case SYSTEM_EVENT_STA_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START"); + break; + } + case SYSTEM_EVENT_STA_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP"); + break; + } + case SYSTEM_EVENT_STA_CONNECTED: { + const system_event_sta_connected_t *connected = &event->event_info.connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \ + connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode); + break; + } + case SYSTEM_EVENT_STA_DISCONNECTED: { + const system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d (%s)", \ + disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason, + wifi_disconnect_reason_to_str(disconnected->reason)); + break; + } + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { + const system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode); + break; + } + case SYSTEM_EVENT_STA_GOT_IP: { + const system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR, + IP2STR(&got_ip->ip_info.ip), + IP2STR(&got_ip->ip_info.netmask), + IP2STR(&got_ip->ip_info.gw)); + break; + } + case SYSTEM_EVENT_STA_LOST_IP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_FAILED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_PIN: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); + break; + } + case SYSTEM_EVENT_AP_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START"); + break; + } + case SYSTEM_EVENT_AP_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP"); + break; + } + case SYSTEM_EVENT_AP_STACONNECTED: { + const system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(staconnected->mac), staconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STADISCONNECTED: { + const system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(stadisconnected->mac), stadisconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STAIPASSIGNED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED"); + break; + } + case SYSTEM_EVENT_AP_PROBEREQRECVED: { + const system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ + ap_probereqrecved->rssi, \ + MAC2STR(ap_probereqrecved->mac)); + break; + } + case SYSTEM_EVENT_STA_BSS_RSSI_LOW: { + const system_event_bss_rssi_low_t *bss_rssi_low = &event->event_info.bss_rssi_low; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_BSS_RSSI_LOW, rssi:%d", bss_rssi_low->rssi); + break; + } +#if LWIP_IPV6 + case SYSTEM_EVENT_GOT_IP6: { + const ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + IP6_ADDR_BLOCK1(addr), + IP6_ADDR_BLOCK2(addr), + IP6_ADDR_BLOCK3(addr), + IP6_ADDR_BLOCK4(addr), + IP6_ADDR_BLOCK5(addr), + IP6_ADDR_BLOCK6(addr), + IP6_ADDR_BLOCK7(addr), + IP6_ADDR_BLOCK8(addr)); + break; + } +#endif + default: { + ESP_LOGW(TAG, "unexpected system event %d!", event->event_id); + break; + } + } +} + +#endif // WITH_EVENT_DEBUG diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h new file mode 100644 index 000000000..c78636415 --- /dev/null +++ b/components/esp_event/include/esp_event.h @@ -0,0 +1,382 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_H_ +#define ESP_EVENT_H_ + +#include "esp_err.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +#include "esp_event_base.h" +#include "esp_event_legacy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// Configuration for creating event loops +typedef struct { + int32_t queue_size; /**< size of the event loop queue */ + const char* task_name; /**< name of the event loop task; if NULL, + a dedicated task is not created for event loop*/ + UBaseType_t task_priority; /**< priority of the event loop task, ignored if task name is NULL */ + uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ + BaseType_t task_core_id; /**< core to which the event loop task is pinned to, + ignored if task name is NULL */ +} esp_event_loop_args_t; + +/** + * @brief Create a new event loop. + * + * @param[in] event_loop_args configuration structure for the event loop to create + * @param[out] event_loop handle to the created event loop + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - ESP_FAIL: Failed to create task loop + * - Others: Fail + */ +esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop); + +/** + * @brief Delete an existing event loop. + * + * @param[in] event_loop event loop to delete + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop); + +/** + * @brief Create default event loop + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - ESP_FAIL: Failed to create task loop + * - Others: Fail + */ +esp_err_t esp_event_loop_create_default(); + +/** + * @brief Delete the default event loop + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_delete_default(); + +/** + * @brief Dispatch events posted to an event loop. + * + * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL + * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time + * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee + * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have + * been dispatched during the call, as the function might have spent all of the alloted time waiting on the event queue. + * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being + * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued + * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code + * execution. The guaranteed time of exit is therefore the alloted time + amount of time required to dispatch + * the last unqueued event. + * + * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is + * normal behavior. + * + * @param[in] event_loop event loop to dispatch posted events from + * @param[in] ticks_to_run number of ticks to run the loop + * + * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error. + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run); + +/** + * @brief Register an event handler to the system event loop. + * + * This function can be used to register a handler for either: (1) specific events, + * (2) all events of a certain event base, or (3) all events known by the system event loop. + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * Registering multiple handlers to events is possible. Registering a single handler to multiple events is + * also possible. However, registering the same handler to the same event multiple times would cause the + * previous registrations to be overwritten. + * + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void* event_handler_arg); + +/** + * @brief Register an event handler to a specific loop. + * + * This function behaves in the same manner as esp_event_handler_register, except the additional + * specification of the event loop to register the handler to. + * + * @param[in] event_loop the event loop to register this handler function to + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void* event_handler_arg); + +/** + * @brief Unregister a handler with the system event loop. + * + * This function can be used to unregister a handler so that it no longer gets called during dispatch. + * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, + * or (3) all events known by the system event loop + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * This function ignores unregistration of handlers that has not been previously registered. + * + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] event_handler the handler to unregister + * + * @return ESP_OK success + * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id + * @return others fail + */ +esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); + +/** + * @brief Unregister a handler with the system event loop. + * + * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of + * the event loop to unregister the handler with. + * + * @param[in] event_loop the event loop with which to unregister this handler function + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] event_handler the handler to unregister + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler); + +/** + * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * handler recieves is always valid. + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[in] ticks_to_wait number of ticks to block on a full event queue + * + * @return + * - ESP_OK: Success + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + TickType_t ticks_to_wait); + +/** + * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * handler recieves is always valid. + * + * This function behaves in the same manner as esp_event_post_to, except the additional specification of the event loop + * to post the event to. + * + * @param[in] event_loop the event loop to post to + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[in] ticks_to_wait number of ticks to block on a full event queue + * + * @return + * - ESP_OK: Success + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + TickType_t ticks_to_wait); + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +/** + * @brief Special variant of esp_event_post for posting events from interrupt handlers. + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data; max is 4 bytes + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the default event loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); + +/** + * @brief Special variant of esp_event_post_to for posting events from interrupt handlers + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); +#endif + +/** + * @brief Dumps statistics of all event loops. + * + * Dumps event loop info in the format: + * + @verbatim + event loop + handler + handler + ... + event loop + handler + handler + ... + + where: + + event loop + format: address,name rx:total_recieved dr:total_dropped + where: + address - memory address of the event loop + name - name of the event loop, 'none' if no dedicated task + total_recieved - number of successfully posted events + total_dropped - number of events unsucessfully posted due to queue being full + + handler + format: address ev:base,id inv:total_invoked run:total_runtime + where: + address - address of the handler function + base,id - the event specified by event base and id this handler executes + total_invoked - number of times this handler has been invoked + total_runtime - total amount of time used for invoking this handler + + @endverbatim + * + * @param[in] file the file stream to output to + * + * @note this function is a noop when CONFIG_ESP_EVENT_LOOP_PROFILING is disabled + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - Others: Fail + */ +esp_err_t esp_event_dump(FILE* file); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_H_ diff --git a/components/esp_event/include/esp_event_base.h b/components/esp_event/include/esp_event_base.h new file mode 100644 index 000000000..73bc73be8 --- /dev/null +++ b/components/esp_event/include/esp_event_base.h @@ -0,0 +1,43 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_BASE_H_ +#define ESP_EVENT_BASE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Defines for declaring and defining event base +#define ESP_EVENT_DECLARE_BASE(id) extern esp_event_base_t id +#define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id + +// Event loop library types +typedef const char* esp_event_base_t; /**< unique pointer to a subsystem that exposes events */ +typedef void* esp_event_loop_handle_t; /**< a number that identifies an event with respect to a base */ +typedef void (*esp_event_handler_t)(void* event_handler_arg, + esp_event_base_t event_base, + int32_t event_id, + void* event_data); /**< function called when an event is posted to the queue */ + + +// Defines for registering/unregistering event handlers +#define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */ +#define ESP_EVENT_ANY_ID -1 /**< register handler for any event id */ + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef ESP_EVENT_BASE_H_ diff --git a/components/esp_event/include/esp_event_legacy.h b/components/esp_event/include/esp_event_legacy.h new file mode 100644 index 000000000..a54ad0e55 --- /dev/null +++ b/components/esp_event/include/esp_event_legacy.h @@ -0,0 +1,226 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "esp_err.h" +#include "esp_wifi_types.h" +#include "tcpip_adapter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** System event types enumeration */ +typedef enum { + SYSTEM_EVENT_WIFI_READY = 0, /*!< WiFi ready */ + SYSTEM_EVENT_SCAN_DONE, /*!< finish scanning AP */ + SYSTEM_EVENT_STA_START, /*!< station start */ + SYSTEM_EVENT_STA_STOP, /*!< station stop */ + SYSTEM_EVENT_STA_CONNECTED, /*!< station connected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /*!< station disconnected from AP */ + SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /*!< the auth mode of AP connected by station changed */ + SYSTEM_EVENT_STA_BSS_RSSI_LOW, /*!< Connected BSS rssi goes below threshold */ + SYSTEM_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */ + SYSTEM_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */ + SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /*!< station wps succeeds in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_FAILED, /*!< station wps fails in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /*!< station wps timeout in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_PIN, /*!< station wps pin code in enrollee mode */ + SYSTEM_EVENT_AP_START, /*!< soft-AP start */ + SYSTEM_EVENT_AP_STOP, /*!< soft-AP stop */ + SYSTEM_EVENT_AP_STACONNECTED, /*!< a station connected to soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /*!< a station disconnected from soft-AP */ + SYSTEM_EVENT_AP_STAIPASSIGNED, /*!< soft-AP assign an IP to a connected station */ + SYSTEM_EVENT_AP_PROBEREQRECVED, /*!< Receive probe request packet in soft-AP interface */ + SYSTEM_EVENT_ETH_START, /*!< ethernet start */ + SYSTEM_EVENT_ETH_STOP, /*!< ethernet stop */ + SYSTEM_EVENT_ETH_CONNECTED, /*!< ethernet phy link up */ + SYSTEM_EVENT_ETH_DISCONNECTED, /*!< ethernet phy link down */ + SYSTEM_EVENT_ETH_GOT_IP, /*!< ethernet got IP from connected AP */ + SYSTEM_EVENT_GOT_IP6, /*!< station or ap or ethernet interface v6IP addr is preferred */ + SYSTEM_EVENT_MAX /*!< Number of members in this enum */ +} system_event_id_t; + +/* add this macro define for compatible with old IDF version */ +#ifndef SYSTEM_EVENT_AP_STA_GOT_IP6 +#define SYSTEM_EVENT_AP_STA_GOT_IP6 SYSTEM_EVENT_GOT_IP6 +#endif + + +/** Argument structure of SYSTEM_EVENT_STA_WPS_ER_FAILED event */ +typedef wifi_event_sta_wps_fail_reason_t system_event_sta_wps_fail_reason_t; + +/** Argument structure of SYSTEM_EVENT_SCAN_DONE event */ +typedef wifi_event_sta_scan_done_t system_event_sta_scan_done_t; + +/** Argument structure of SYSTEM_EVENT_STA_CONNECTED event */ +typedef wifi_event_sta_connected_t system_event_sta_connected_t; + +/** Argument structure of SYSTEM_EVENT_STA_DISCONNECTED event */ +typedef wifi_event_sta_disconnected_t system_event_sta_disconnected_t; + +/** Argument structure of SYSTEM_EVENT_STA_AUTHMODE_CHANGE event */ +typedef wifi_event_sta_authmode_change_t system_event_sta_authmode_change_t; + +/** Argument structure of SYSTEM_EVENT_STA_WPS_ER_PIN event */ +typedef wifi_event_sta_wps_er_pin_t system_event_sta_wps_er_pin_t; + +/** Argument structure of event */ +typedef wifi_event_ap_staconnected_t system_event_ap_staconnected_t; + +/** Argument structure of event */ +typedef wifi_event_ap_stadisconnected_t system_event_ap_stadisconnected_t; + +/** Argument structure of event */ +typedef wifi_event_ap_probe_req_rx_t system_event_ap_probe_req_rx_t; + +/** Argument structure of event */ +typedef wifi_event_bss_rssi_low_t system_event_bss_rssi_low_t; + +/** Argument structure of event */ +typedef ip_event_ap_staipassigned_t system_event_ap_staipassigned_t; + +/** Argument structure of event */ +typedef ip_event_got_ip_t system_event_sta_got_ip_t; + +/** Argument structure of event */ +typedef ip_event_got_ip6_t system_event_got_ip6_t; + +/** Union of all possible system_event argument structures */ +typedef union { + system_event_sta_connected_t connected; /*!< station connected to AP */ + system_event_sta_disconnected_t disconnected; /*!< station disconnected to AP */ + system_event_sta_scan_done_t scan_done; /*!< station scan (APs) done */ + system_event_sta_authmode_change_t auth_change; /*!< the auth mode of AP station connected to changed */ + system_event_sta_got_ip_t got_ip; /*!< station got IP, first time got IP or when IP is changed */ + system_event_sta_wps_er_pin_t sta_er_pin; /*!< station WPS enrollee mode PIN code received */ + system_event_sta_wps_fail_reason_t sta_er_fail_reason; /*!< station WPS enrollee mode failed reason code received */ + system_event_ap_staconnected_t sta_connected; /*!< a station connected to soft-AP */ + system_event_ap_stadisconnected_t sta_disconnected; /*!< a station disconnected to soft-AP */ + system_event_ap_probe_req_rx_t ap_probereqrecved; /*!< soft-AP receive probe request packet */ + system_event_bss_rssi_low_t bss_rssi_low; /*!< Connected BSS rssi goes below threshold */ + system_event_ap_staipassigned_t ap_staipassigned; /**< soft-AP assign an IP to the station*/ + system_event_got_ip6_t got_ip6; /*!< station or ap or ethernet ipv6 addr state change to preferred */ +} system_event_info_t; + +/** Event, as a tagged enum */ +typedef struct { + system_event_id_t event_id; /*!< event ID */ + system_event_info_t event_info; /*!< event information */ +} system_event_t; + +/** Event handler function type */ +typedef esp_err_t (*system_event_handler_t)(system_event_t *event); + +/** + * @brief Send a event to event task + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * Other task/modules, such as the tcpip_adapter, can call this API to send an event to event task + * + * @param event Event to send + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_event_send(system_event_t *event); + +/** + * @brief Default event handler for system events + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * This function performs default handling of system events. + * When using esp_event_loop APIs, it is called automatically before invoking the user-provided + * callback function. + * + * Applications which implement a custom event loop must call this function + * as part of event processing. + * + * @param event pointer to event to be handled + * @return ESP_OK if an event was handled successfully + */ +esp_err_t esp_event_process_default(system_event_t *event); + +/** + * @brief Install default event handlers for Ethernet interface + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + */ +void esp_event_set_default_eth_handlers(); + +/** + * @brief Install default event handlers for Wi-Fi interfaces (station and AP) + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + */ +void esp_event_set_default_wifi_handlers(); + +/** + * @brief Application specified event callback function + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * + * @param ctx reserved for user + * @param event event type defined in this file + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); + +/** + * @brief Initialize event loop + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * Create the event handler and task + * + * @param cb application specified event callback, it can be modified by call esp_event_set_cb + * @param ctx reserved for user + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx); + +/** + * @brief Set application specified event callback function + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * @attention 1. If cb is NULL, means application don't need to handle + * If cb is not NULL, it will be call when an event is received, after the default event callback is completed + * + * @param cb application callback function + * @param ctx argument to be passed to callback + * + * + * @return old callback + */ +system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/components/esp_event/include/esp_event_loop.h b/components/esp_event/include/esp_event_loop.h new file mode 100644 index 000000000..6267ee37d --- /dev/null +++ b/components/esp_event/include/esp_event_loop.h @@ -0,0 +1 @@ +#include "esp_event_legacy.h" diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h new file mode 100644 index 000000000..fb970a806 --- /dev/null +++ b/components/esp_event/private_include/esp_event_internal.h @@ -0,0 +1,112 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_INTERNAL_H_ +#define ESP_EVENT_INTERNAL_H_ + +#include "esp_event.h" +#include "stdatomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef SLIST_HEAD(base_nodes, base_node) base_nodes_t; + +/// Event handler +typedef struct esp_event_handler_instance { + esp_event_handler_t handler; /**< event handler function*/ + void* arg; /**< event handler argument */ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + uint32_t invoked; /**< number of times this handler has been invoked */ + int64_t time; /**< total runtime of this handler across all calls */ +#endif + SLIST_ENTRY(esp_event_handler_instance) next; /**< next event handler in the list */ +} esp_event_handler_instance_t; + +typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_instance) esp_event_handler_instances_t; + +/// Event +typedef struct esp_event_id_node { + int32_t id; /**< id number of the event */ + esp_event_handler_instances_t handlers; /**< list of handlers to be executed when + this event is raised */ + SLIST_ENTRY(esp_event_id_node) next; /**< pointer to the next event node on the linked list */ +} esp_event_id_node_t; + +typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t; + +typedef struct esp_event_base_node { + esp_event_base_t base; /**< base identifier of the event */ + esp_event_handler_instances_t handlers; /**< event base level handlers, handlers for + all events with this base */ + esp_event_id_nodes_t id_nodes; /**< list of event ids with this base */ + SLIST_ENTRY(esp_event_base_node) next; /**< pointer to the next base node on the linked list */ +} esp_event_base_node_t; + +typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t; + +typedef struct esp_event_loop_node { + esp_event_handler_instances_t handlers; /** event loop level handlers */ + esp_event_base_nodes_t base_nodes; /** list of event bases registered to the loop */ + SLIST_ENTRY(esp_event_loop_node) next; /** pointer to the next loop node containing + event loop level handlers and the rest of + event bases registered to the loop */ +} esp_event_loop_node_t; + +typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t; + +/// Event loop +typedef struct esp_event_loop_instance { + const char* name; /**< name of this event loop */ + QueueHandle_t queue; /**< event queue */ + TaskHandle_t task; /**< task that consumes the event queue */ + TaskHandle_t running_task; /**< for loops with no dedicated task, the + task that consumes the queue */ + SemaphoreHandle_t mutex; /**< mutex for updating the events linked list */ + esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the + registered handlers for the loop */ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_uint_least32_t events_recieved; /**< number of events successfully posted to the loop */ + atomic_uint_least32_t events_dropped; /**< number of events dropped due to queue being full */ + SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */ + SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */ +#endif +} esp_event_loop_instance_t; + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +typedef union esp_event_post_data { + uint32_t val; + void *ptr; +} esp_event_post_data_t; +#else +typedef void* esp_event_post_data_t; +#endif + +/// Event posted to the event queue +typedef struct esp_event_post_instance { +#if CONFIG_ESP_EVENT_POST_FROM_ISR + bool data_allocated; /**< indicates whether data is allocated from heap */ + bool data_set; /**< indicates if data is null */ +#endif + esp_event_base_t base; /**< the event base */ + int32_t id; /**< the event id */ + esp_event_post_data_t data; /**< data associated with the event */ +} esp_event_post_instance_t; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_INTERNAL_H_ diff --git a/components/esp_event/private_include/esp_event_private.h b/components/esp_event/private_include/esp_event_private.h new file mode 100644 index 000000000..990d51872 --- /dev/null +++ b/components/esp_event/private_include/esp_event_private.h @@ -0,0 +1,54 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_PRIVATE_H_ +#define ESP_EVENT_PRIVATE_H_ + +#include "esp_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Searches handlers registered with an event loop to see if it has been registered. + * + * @param[in] event_loop the loop to search + * @param[in] event_base the event base to search + * @param[in] event_id the event id to search + * @param[in] event_handler the event handler to look for + * + * @return true handler registered + * @return false handler not registered + * + * @return + * - true: Handler registered + * - false: Handler not registered + */ +bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); + +/** + * @brief Deinitializes the event loop library + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_deinit(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_PRIVATE_H_ \ No newline at end of file diff --git a/components/esp_event/test/CMakeLists.txt b/components/esp_event/test/CMakeLists.txt new file mode 100644 index 000000000..8264f10dd --- /dev/null +++ b/components/esp_event/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "../private_include" "." + REQUIRES unity test_utils esp_event driver) diff --git a/components/esp_event/test/component.mk b/components/esp_event/test/component.mk new file mode 100644 index 000000000..22e49eddd --- /dev/null +++ b/components/esp_event/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# +COMPONENT_PRIV_INCLUDEDIRS := ../private_include . +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \ No newline at end of file diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c new file mode 100644 index 000000000..0efc2d492 --- /dev/null +++ b/components/esp_event/test/test_event.c @@ -0,0 +1,1280 @@ +#include +#include + +#include "esp_event.h" +#include "sdkconfig.h" + +#include "freertos/FreeRTOS.h" +#include "esp_event_loop.h" +#include "freertos/task.h" +#include "freertos/portmacro.h" +#include "esp_log.h" +#include "driver/periph_ctrl.h" +#include "driver/timer.h" + +#include "esp_event.h" +#include "esp_event_private.h" +#include "esp_event_internal.h" + +#include "esp_heap_caps.h" + +#include "sdkconfig.h" +#include "unity.h" + +#include "test_utils.h" + +static const char* TAG = "test_event"; + +#define TEST_CONFIG_ITEMS_TO_REGISTER 5 +#define TEST_CONFIG_TASKS_TO_SPAWN 2 + +#define TEST_CONFIG_WAIT_MULTIPLIER 5 + +// The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed +// during teardown. +#define TEST_SETUP() \ + ESP_LOGI(TAG, "initializing test"); \ + size_t free_mem_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); \ + test_setup(); \ + s_test_core_id = xPortGetCoreID(); \ + s_test_priority = uxTaskPriorityGet(NULL); + +#define TEST_TEARDOWN() \ + test_teardown(); \ + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); \ + TEST_ASSERT_EQUAL(free_mem_before, heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); + +typedef struct { + void* data; + SemaphoreHandle_t start; + SemaphoreHandle_t done; +} task_arg_t; + +typedef struct { + esp_event_base_t base; + int32_t id; + esp_event_handler_t* handles; + int32_t num; + esp_event_loop_handle_t loop; + bool is_registration; +} handler_registration_data_t; + +typedef struct { + esp_event_base_t base; + int32_t id; + esp_event_loop_handle_t loop; + int32_t num; +} post_event_data_t; + +typedef struct { + int performed; + int expected; + SemaphoreHandle_t done; +} performance_data_t; + +typedef struct { + void* data; + SemaphoreHandle_t mutex; +} simple_arg_t; + +typedef struct { + int *arr; + int index; +} ordered_data_t; + +static BaseType_t s_test_core_id; +static UBaseType_t s_test_priority; + +ESP_EVENT_DECLARE_BASE(s_test_base1); +ESP_EVENT_DECLARE_BASE(s_test_base2); + +ESP_EVENT_DEFINE_BASE(s_test_base1); +ESP_EVENT_DEFINE_BASE(s_test_base2); + +enum { + TEST_EVENT_BASE1_EV1, + TEST_EVENT_BASE1_EV2, + TEST_EVENT_BASE1_MAX +}; + +enum { + TEST_EVENT_BASE2_EV1, + TEST_EVENT_BASE2_EV2, + TEST_EVENT_BASE2_MAX +}; + +static BaseType_t test_event_get_core() +{ + static int calls = 0; + + if (portNUM_PROCESSORS > 1) { + return (s_test_core_id + calls++) % portNUM_PROCESSORS; + } else { + return s_test_core_id; + } +} + +static esp_event_loop_args_t test_event_get_default_loop_args() +{ + esp_event_loop_args_t loop_config = { + .queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE, + .task_name = "loop", + .task_priority = s_test_priority, + .task_stack_size = 2048, + .task_core_id = test_event_get_core() + }; + + return loop_config; +} + +static void test_event_simple_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + if (!event_handler_arg) { + return; + } + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + xSemaphoreTake(arg->mutex, portMAX_DELAY); + + int* count = (int*) arg->data; + + if (event_data == NULL) { + (*count)++; + } else { + (*count) += *((int*) event_data); + } + + xSemaphoreGive(arg->mutex); +} + +static void test_event_ordered_dispatch(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + int *arg = (int*) event_handler_arg; + ordered_data_t *data = *((ordered_data_t**) (event_data)); + + data->arr[data->index++] = *arg; +} + +static void test_event_performance_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + performance_data_t* data = (performance_data_t*) event_handler_arg; + + data->performed++; + + if (data->performed >= data->expected) { + xSemaphoreGive(data->done); + } +} + +static void test_event_post_task(void* args) +{ + task_arg_t* arg = (task_arg_t*) args; + post_event_data_t* data = arg->data; + + xSemaphoreTake(arg->start, portMAX_DELAY); + + for (int i = 0; i < data->num; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY)); + vTaskDelay(1); + } + + xSemaphoreGive(arg->done); + + vTaskDelete(NULL); +} + +static void test_event_simple_handler_registration_task(void* args) +{ + task_arg_t* arg = (task_arg_t*) args; + handler_registration_data_t* data = (handler_registration_data_t*) arg->data; + + xSemaphoreTake(arg->start, portMAX_DELAY); + + for(int i = 0; i < data->num; i++) { + if (data->is_registration) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL)); + } else { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i])); + } + vTaskDelay(1); + } + + xSemaphoreGive(arg->done); + + vTaskDelete(NULL); +} + +static void test_handler_post_w_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data; + int* count = (int*) arg->data; + + (*count)++; + + if (*count <= 2) { + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } else{ + xSemaphoreGive((SemaphoreHandle_t) arg->mutex); + } + } else { + // Test that once the queue is full and the handler attempts to post to the same loop, + // posting does not block indefinitely. + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + } +} + +static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data; + int* count = (int*) arg->data; + + (*count)++; + + if (*count <= 2) { + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } else{ + xSemaphoreGive((SemaphoreHandle_t) arg->mutex); + } + } else { + // Test that once the queue is full and the handler attempts to post to the same loop, + // posting does not block indefinitely. + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + } +} + +static void test_post_from_handler_loop_task(void* args) +{ + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + while(1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(event_loop, portMAX_DELAY)); + } +} + +static void test_setup() +{ + TEST_ASSERT_TRUE(TEST_CONFIG_TASKS_TO_SPAWN >= 2); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); +} + +static void test_teardown() +{ + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); +} + +#define TIMER_DIVIDER 16 // Hardware timer clock divider +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds +#define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + SemaphoreHandle_t *sem = (SemaphoreHandle_t*) event_handler_arg; + // Event data is just the address value (maybe have been truncated due to casting). + int *data = (int*) event_data; + TEST_ASSERT_EQUAL(*data, (int) (*sem)); + xSemaphoreGive(*sem); +} +#endif + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +void IRAM_ATTR test_event_on_timer_alarm(void* para) +{ + /* Retrieve the interrupt status and the counter value + from the timer that reported the interrupt */ + TIMERG0.hw_timer[TIMER_0].update = 1; + uint64_t timer_counter_value = + ((uint64_t) TIMERG0.hw_timer[TIMER_0].cnt_high) << 32 + | TIMERG0.hw_timer[TIMER_0].cnt_low; + + TIMERG0.int_clr_timers.t0 = 1; + timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); + TIMERG0.hw_timer[TIMER_0].alarm_high = (uint32_t) (timer_counter_value >> 32); + TIMERG0.hw_timer[TIMER_0].alarm_low = (uint32_t) timer_counter_value; + + int data = (int) para; + // Posting events with data more than 4 bytes should fail. + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL)); + // This should succeedd, as data is int-sized. The handler for the event checks that the passed event data + // is correct. + BaseType_t task_unblocked; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked)); + if (task_unblocked == pdTRUE) { + portYIELD_FROM_ISR(); + } +} +#endif //CONFIG_ESP_EVENT_POST_FROM_ISR + +TEST_CASE("can create and delete event loops", "[event]") +{ + /* this test aims to verify that: + * - creating loops with and without a task succeeds + * - event queue can accomodate the set queue size, and drops the post when exceeded + * - deleting loops with unconsumed posts and unregistered handlers (when unregistration is enabled) does not leak memory */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop1; // with dedicated task + esp_event_loop_handle_t loop2; // without dedicated task + esp_event_loop_handle_t loop3; // with leftover post and handlers + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop1)); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop3)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, (void*) 0x00000001, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, (void*) 0x00000002, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, (void*) 0x00000003, NULL)); + + for (int i = 0; i < loop_args.queue_size; i++) { + int mod = i % 4; + + switch(mod) { + case 0: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + break; + case 1: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + break; + case 2: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + break; + case 3: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + break; + default: + break; + } + } + + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop3)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can register/unregister handlers for all events/all events for a specific base", "[event]") +{ + /* this test aims to verify that handlers can be registered to be called on all events + * or for all events with specific bases */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + /* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning) + * This aims to verify: 1) Handler's argument to be updated + * 2) Registration not to leak memory + */ + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3) + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3) + + // Post unknown events. Respective loop level and base level handlers should still execute. + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY)); // exec loop and base level (+2) + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY)); // exec loop level (+1) + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(9, count); // 3 + 3 + 2 + 1 + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can unregister handler", "[event]") +{ + /* this test aims to verify that unregistered handlers no longer execute when events are raised */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(2, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can exit running loop at approximately the set amount of time", "[event]") +{ + /* this test aims to verify that running loop does not block indefinitely in cases where + * events are posted frequently */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + performance_data_t handler_data = { + .performed = 0, + .expected = INT32_MAX, + .done = xSemaphoreCreateBinary() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_performance_handler, &handler_data)); + + post_event_data_t post_event_data = { + .base = s_test_base1, + .id = TEST_EVENT_BASE1_EV1, + .loop = loop, + .num = INT32_MAX + }; + + task_arg_t post_event_arg = { + .data = &post_event_data, + .done = xSemaphoreCreateBinary(), + .start = xSemaphoreCreateBinary() + }; + + TaskHandle_t post_task; + + xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg, s_test_priority, &post_task, test_event_get_core()); + + int runtime_ms = 10; + int runtime_us = runtime_ms * 1000; + + int64_t start, diff; + start = esp_timer_get_time(); + + xSemaphoreGive(post_event_arg.start); + + // Run the loop for the runtime_ms set amount of time, regardless of whether events + // are still being posted to the loop. + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms))); + + diff = (esp_timer_get_time() - start); + + // Threshold is 25 percent. + TEST_ASSERT(diff < runtime_us * 1.25f); + + // Verify that the post task still continues + TEST_ASSERT_NOT_EQUAL(pdTRUE, xSemaphoreTake(post_event_arg.done, pdMS_TO_TICKS(10))); + + vSemaphoreDelete(post_event_arg.done); + vSemaphoreDelete(post_event_arg.start); + vSemaphoreDelete(handler_data.done); + vTaskDelete(post_task); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can register/unregister handlers simultaneously", "[event]") +{ + /* this test aims to verify that the event handlers list remains consistent despite + * simultaneous access by differenct tasks */ + + TEST_SETUP(); + + const char* base = "base"; + int32_t id = 0; + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + ESP_LOGI(TAG, "registering handlers"); + + handler_registration_data_t* registration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_data)); + task_arg_t* registration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + registration_data[i].base = base; + registration_data[i].id = id; + registration_data[i].loop = loop; + registration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t)); + registration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + registration_data[i].is_registration = true; + + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + registration_data[i].handles[j] = (void*) (i * TEST_CONFIG_ITEMS_TO_REGISTER) + (j + TEST_CONFIG_ITEMS_TO_REGISTER); + } + + registration_arg[i].start = xSemaphoreCreateBinary(); + registration_arg[i].done = xSemaphoreCreateBinary(); + registration_arg[i].data = ®istration_data[i]; + + xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "register", 2048, ®istration_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + // Give the semaphores to the spawned registration task + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(registration_arg[i].start); + } + + // Take the same semaphores in order to proceed + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(registration_arg[i].done, portMAX_DELAY); + } + + ESP_LOGI(TAG, "checking consistency of handlers list"); + + // Check consistency of events list + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + TEST_ASSERT_TRUE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j])); + } + } + + ESP_LOGI(TAG, "unregistering handlers"); + + /* Test if tasks can unregister simultaneously */ + + // Unregister registered events + handler_registration_data_t* unregistration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_data)); + task_arg_t* unregistration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + unregistration_data[i].base = base; + unregistration_data[i].id = id; + unregistration_data[i].loop = loop; + unregistration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t)); + unregistration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + unregistration_data[i].is_registration = false; + + memcpy(unregistration_data[i].handles, registration_data[i].handles, TEST_CONFIG_ITEMS_TO_REGISTER * sizeof(esp_event_handler_t)); + + unregistration_arg[i].data = &unregistration_data[i]; + unregistration_arg[i].start = xSemaphoreCreateBinary(); + unregistration_arg[i].done = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "unregister", 2048, &unregistration_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + // Give the semaphores to the spawned unregistration task + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(unregistration_arg[i].start); + } + + // Take the same semaphores in order to proceed + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(unregistration_arg[i].done, portMAX_DELAY); + } + + ESP_LOGI(TAG, "checking consistency of handlers list"); + + // Check consistency of events list + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + TEST_ASSERT_FALSE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j])); + } + } + + // Do cleanup + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + free(registration_data[i].handles); + vSemaphoreDelete(registration_arg[i].start); + vSemaphoreDelete(registration_arg[i].done); + + free(unregistration_data[i].handles); + vSemaphoreDelete(unregistration_arg[i].start); + vSemaphoreDelete(unregistration_arg[i].done); + } + + free(registration_data); + free(unregistration_data); + free(registration_arg); + free(unregistration_arg); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post and run events", "[event]") +{ + /* this test aims to verify that: + * - multiple tasks can post to the queue simultaneously + * - handlers recieve the appropriate handler arg and associated event data */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data)); + task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) + { + post_event_data[i].base = s_test_base1; + post_event_data[i].id = TEST_EVENT_BASE1_EV1; + post_event_data[i].loop = loop; + post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + + post_event_arg[i].data = &post_event_data[i]; + post_event_arg[i].start = xSemaphoreCreateBinary(); + post_event_arg[i].done = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(post_event_arg[i].start); + } + + // Execute some events as they are posted + for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + } + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY); + } + + // Execute the rest + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count); + + // Cleanup + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + vSemaphoreDelete(post_event_arg[i].start); + vSemaphoreDelete(post_event_arg[i].done); + } + + free(post_event_data); + free(post_event_arg); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +static void loop_run_task(void* args) +{ + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + while(1) { + esp_event_loop_run(event_loop, portMAX_DELAY); + } +} + +static void performance_test(bool dedicated_task) +{ + // rand() seems to do a one-time allocation. Call it here so that the memory it allocates + // is not counted as a leak. + unsigned int _rand __attribute__((unused)) = rand(); + + TEST_SETUP(); + + const char test_base[] = "qwertyuiopasdfghjklzxvbnmmnbvcxzqwertyuiopasdfghjklzxvbnmmnbvcxz"; + + #define TEST_CONFIG_BASES (sizeof(test_base) - 1) + #define TEST_CONFIG_IDS (TEST_CONFIG_BASES / 2) + + // Create loop + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + esp_event_loop_handle_t loop; + + if (!dedicated_task) { + loop_args.task_name = NULL; + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + performance_data_t data; + + // Register the handlers + for (int base = 0; base < TEST_CONFIG_BASES; base++) { + for (int id = 0; id < TEST_CONFIG_IDS; id++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data)); + } + } + + TaskHandle_t mtask = NULL; + + if (!dedicated_task) { + xTaskCreate(loop_run_task, "loop_run", loop_args.task_stack_size, (void*) loop, loop_args.task_priority, &mtask); + } + + // Perform performance test + float running_sum = 0; + float running_count = 0; + + for (int bases = 1; bases <= TEST_CONFIG_BASES; bases *= 2) { + for (int ids = 1; ids <= TEST_CONFIG_IDS; ids *= 2) { + + data.performed = 0; + data.expected = bases * ids; + data.done = xSemaphoreCreateBinary(); + + // Generate randomized list of posts + int post_bases[TEST_CONFIG_BASES]; + int post_ids[TEST_CONFIG_IDS]; + + for (int i = 0; i < bases; i++) { + post_bases[i] = i; + } + + for (int i = 0; i < ids; i++) { + post_ids[i] = i; + } + + for (int i = 0; i < bases; i++) { + int rand_a = rand() % bases; + int rand_b = rand() % bases; + + int temp = post_bases[rand_a]; + post_bases[rand_a]= post_bases[rand_b]; + post_bases[rand_b] = temp; + } + + for (int i = 0; i < ids; i++) { + int rand_a = rand() % ids; + int rand_b = rand() % ids; + + int temp = post_ids[rand_a]; + post_ids[rand_a]= post_ids[rand_b]; + post_ids[rand_b] = temp; + } + + // Post the events + int64_t start = esp_timer_get_time(); + for (int base = 0; base < bases; base++) { + for (int id = 0; id < ids; id++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY)); + } + } + + xSemaphoreTake(data.done, portMAX_DELAY); + int64_t elapsed = esp_timer_get_time() - start; + + // Record data + TEST_ASSERT_EQUAL(data.expected, data.performed); + + running_count++; + running_sum += data.performed / (elapsed / (1000000.0)); + + vSemaphoreDelete(data.done); + } + } + + int average = (int) (running_sum / (running_count)); + + if (!dedicated_task) { + ((esp_event_loop_instance_t*) loop)->task = mtask; + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + ESP_LOGI(TAG, "events dispatched/second with profiling enabled: %d", average); + // Enabling profiling will slow down event dispatch, so the set threshold + // is not valid when it is enabled. +#else +#ifndef CONFIG_ESP32_SPIRAM_SUPPORT + TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH, "%d", average); +#else + TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH_PSRAM, "%d", average); +#endif // CONFIG_ESP32_SPIRAM_SUPPORT +#endif // CONFIG_ESP_EVENT_LOOP_PROFILING +} + +TEST_CASE("performance test - dedicated task", "[event]") +{ + performance_test(true); +} + +TEST_CASE("performance test - no dedicated task", "[event]") +{ + performance_test(false); +} + +TEST_CASE("can post to loop from handler - dedicated task", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop_w_task; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + int count; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateBinary() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_w_task)); + + count = 0; + + // Test that a handler can post to a different loop while there is still slots on the queue + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_w_task, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY)); + + xSemaphoreTake(arg.mutex, portMAX_DELAY); + + TEST_ASSERT_EQUAL(2, count); + + // Test that other tasks can still post while there is still slots in the queue, while handler is executing + count = 100; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY)); + + for (int i = 0; i < loop_args.queue_size; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, + pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER))); + + xSemaphoreGive(arg.mutex); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_w_task)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post to loop from handler - no dedicated task", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop_wo_task; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + int count; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateBinary() + }; + + count = 0; + + loop_args.queue_size = 1; + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_wo_task)); + + TaskHandle_t mtask; + + xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask); + + // Test that a handler can post to a different loop while there is still slots on the queue + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_wo_task, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY)); + + xSemaphoreTake(arg.mutex, portMAX_DELAY); + + TEST_ASSERT_EQUAL(2, count); + + count = 100; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY)); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + // For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, + pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER))); + + xSemaphoreGive(arg.mutex); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + vTaskDelete(mtask); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_wo_task)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +static void test_event_simple_handler_template(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + int* count = (int*) handler_arg; + (*count)++; +} + +static void test_event_simple_handler_1(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_event_simple_handler_3(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_event_simple_handler_2(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_registration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1, handler_arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2, handler_arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3, handler_arg)); +} + +static void test_unregistration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3)); +} + +TEST_CASE("can register from handler", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_registration_from_handler_hdlr, &count)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_unregistration_from_handler_hdlr, &count)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(&loop), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(&loop), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +static void test_create_loop_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data) +{ + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + if (id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args)); + } else { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args))); + } +} + +TEST_CASE("can create and delete loop from handler", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_handle_t test_loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_create_loop_handler, &test_loop)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_create_loop_handler, &test_loop)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("events are dispatched in the order they are registered", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int id_arr[7]; + + for (int i = 0; i < 7; i++) { + id_arr[i] = i; + } + + int data_arr[12] = {0}; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_event_ordered_dispatch, id_arr + 0)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_event_ordered_dispatch, id_arr + 3)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_ordered_dispatch, id_arr + 4)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 5)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_ordered_dispatch, id_arr + 6)); + + esp_event_dump(stdout); + + ordered_data_t data = { + .arr = data_arr, + .index = 0 + }; + + ordered_data_t* dptr = &data; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + // Expected data executing the posts above + int ref_arr[12] = {1, 3, 5, 1, 2, 4, 1, 2, 6, 0, 1, 5}; + + for (int i = 0; i < 12; i++) { + TEST_ASSERT_EQUAL(ref_arr[i], data_arr[i]); + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +TEST_CASE("can properly prepare event data posted to loop", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + esp_event_post_instance_t post; + esp_event_loop_instance_t* loop_def = (esp_event_loop_instance_t*) loop; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY)); + TEST_ASSERT_EQUAL(false, post.data_set); + TEST_ASSERT_EQUAL(false, post.data_allocated); + TEST_ASSERT_EQUAL(NULL, post.data.ptr); + + int sample = 0; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_isr_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &sample, sizeof(sample), NULL)); + TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY)); + TEST_ASSERT_EQUAL(true, post.data_set); + TEST_ASSERT_EQUAL(false, post.data_allocated); + TEST_ASSERT_EQUAL(false, post.data.val); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post events from interrupt handler", "[event]") +{ + SemaphoreHandle_t sem = xSemaphoreCreateBinary(); + + /* Select and initialize basic parameters of the timer */ + timer_config_t config; + config.divider = TIMER_DIVIDER; + config.counter_dir = TIMER_COUNT_UP; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.intr_type = TIMER_INTR_LEVEL; + config.auto_reload = false; + timer_init(TIMER_GROUP_0, TIMER_0, &config); + + /* Timer's counter will initially start from value below. + Also, if auto_reload is set, this value will be automatically reload on alarm */ + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL); + + /* Configure the alarm value and the interrupt on alarm. */ + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm, + (void *) sem, ESP_INTR_FLAG_IRAM, NULL); + + timer_start(TIMER_GROUP_0, TIMER_0); + + TEST_SETUP(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, + test_handler_post_from_isr, &sem)); + + xSemaphoreTake(sem, portMAX_DELAY); + + TEST_TEARDOWN(); +} +#endif + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +TEST_CASE("can dump event loop profile", "[event]") +{ + /* this test aims to verify that dumping event loop statistics succeed */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + loop_args.queue_size = 5; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + // 5 invocations of loop-levlel handlers + 3 invocation of base-level handlers (s_test_base1) + + // 5 invocations of respective event-level handlers + TEST_ASSERT_EQUAL(13, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_dump(stdout)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} +#endif diff --git a/components/esp_gdbstub/CMakeLists.txt b/components/esp_gdbstub/CMakeLists.txt new file mode 100644 index 000000000..8dcdc7a85 --- /dev/null +++ b/components/esp_gdbstub/CMakeLists.txt @@ -0,0 +1,12 @@ +idf_build_get_property(target IDF_TARGET) + +set(esp_gdbstub_srcs "src/gdbstub.c" + "src/packet.c" + "${target}/gdbstub_${target}.c" + "xtensa/gdbstub_xtensa.c") + +idf_component_register(SRCS "${esp_gdbstub_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" "${target}" "xtensa" + REQUIRES "freertos" + PRIV_REQUIRES "esp8266") diff --git a/components/esp_gdbstub/Kconfig b/components/esp_gdbstub/Kconfig new file mode 100644 index 000000000..14e7d859c --- /dev/null +++ b/components/esp_gdbstub/Kconfig @@ -0,0 +1,25 @@ +menu "GDB Stub" + + # Hidden option which is selected from the "Panic handler behavior" + # menu in the target component. + config ESP_GDBSTUB_ENABLED + bool + + config ESP_GDBSTUB_SUPPORT_TASKS + bool "Enable listing FreeRTOS tasks through GDB Stub" + depends on ESP_GDBSTUB_ENABLED + default y + help + If enabled, GDBStub can supply the list of FreeRTOS tasks to GDB. + Thread list can be queried from GDB using 'info threads' command. + Note that if GDB task lists were corrupted, this feature may not work. + If GDBStub fails, try disabling this feature. + + config ESP_GDBSTUB_MAX_TASKS + int "Maximum number of tasks supported by GDB Stub" + default 32 + depends on ESP_GDBSTUB_SUPPORT_TASKS + help + Set the number of tasks which GDB Stub will support. + +endmenu diff --git a/components/esp_gdbstub/component.mk b/components/esp_gdbstub/component.mk new file mode 100644 index 000000000..9f9a74799 --- /dev/null +++ b/components/esp_gdbstub/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include esp8266 xtensa +COMPONENT_SRCDIRS := src esp8266 xtensa diff --git a/components/esp_gdbstub/esp8266/gdbstub_esp8266.c b/components/esp_gdbstub/esp8266/gdbstub_esp8266.c new file mode 100644 index 000000000..e5e77c26d --- /dev/null +++ b/components/esp_gdbstub/esp8266/gdbstub_esp8266.c @@ -0,0 +1,52 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp8266/uart_register.h" +#include "esp8266/eagle_soc.h" +#include "sdkconfig.h" +#include "esp_task_wdt.h" + +#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM + +void esp_gdbstub_target_init(void) +{ +} + +int esp_gdbstub_getchar(void) +{ + while (((READ_PERI_REG(UART_STATUS(UART_NUM)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT) == 0) { + esp_task_wdt_reset(); + } + return READ_PERI_REG(UART_FIFO(UART_NUM)); +} + +void esp_gdbstub_putchar(int c) +{ + while (((READ_PERI_REG(UART_STATUS(UART_NUM)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) >= 126) { + ; + } + + WRITE_PERI_REG(UART_FIFO(UART_NUM) , c); +} + +int esp_gdbstub_readmem(intptr_t addr) +{ + if (addr < 0x3ff00000 || addr >= 0x60010000) { + /* see cpu_configure_region_protection */ + return -1; + } + uint32_t val_aligned = *(uint32_t *)(addr & (~3)); + uint32_t shift = (addr & 3) * 8; + return (val_aligned >> shift) & 0xff; +} diff --git a/components/esp_gdbstub/esp8266/gdbstub_target_config.h b/components/esp_gdbstub/esp8266/gdbstub_target_config.h new file mode 100644 index 000000000..ae31ae9da --- /dev/null +++ b/components/esp_gdbstub/esp8266/gdbstub_target_config.h @@ -0,0 +1,18 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/* Number of extra TIE defined registers, not listed in the XCHAL */ +#define GDBSTUB_EXTRA_TIE_SIZE 0 diff --git a/components/esp_gdbstub/include/esp_gdbstub.h b/components/esp_gdbstub/include/esp_gdbstub.h new file mode 100644 index 000000000..02fda63e5 --- /dev/null +++ b/components/esp_gdbstub/include/esp_gdbstub.h @@ -0,0 +1,27 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_gdbstub_arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void esp_gdbstub_panic_handler(esp_gdbstub_frame_t *frame) __attribute__((noreturn)); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_gdbstub/private_include/esp_gdbstub_common.h b/components/esp_gdbstub/private_include/esp_gdbstub_common.h new file mode 100644 index 000000000..43c35dcab --- /dev/null +++ b/components/esp_gdbstub/private_include/esp_gdbstub_common.h @@ -0,0 +1,151 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "esp_gdbstub.h" +#include "sdkconfig.h" + +#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + +/* Internal error codes used by the routines that parse the incoming gdb packet */ +#define GDBSTUB_ST_ENDPACKET -1 +#define GDBSTUB_ST_ERR -2 +#define GDBSTUB_ST_OK -3 + +/* Special task index values */ +#define GDBSTUB_CUR_TASK_INDEX_UNKNOWN -1 + +/* Cab be set to a lower value in gdbstub_target_config.h */ +#ifndef GDBSTUB_CMD_BUFLEN +#define GDBSTUB_CMD_BUFLEN 512 +#endif + +#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +typedef enum { + GDBSTUB_NOT_STARTED, + GDBSTUB_STARTED, + GDBSTUB_TASK_SUPPORT_DISABLED +} esp_gdbstub_state_t; + +#define GDBSTUB_TASKS_NUM CONFIG_ESP_GDBSTUB_MAX_TASKS + +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + +/* gdbstub temporary run-time data, stored in .bss to reduce stack usage */ +typedef struct { + esp_gdbstub_gdb_regfile_t regfile; + int signal; +#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + esp_gdbstub_state_t state; + int task_count; + int paniced_task_index; + int current_task_index; + int thread_info_index; //!< index of the last task passed to qsThreadInfo + esp_gdbstub_frame_t paniced_frame; + TaskSnapshot_t tasks[GDBSTUB_TASKS_NUM]; // TODO: add an API to get snapshots one by one +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +} esp_gdbstub_scratch_t; + + +/**** Functions provided by the architecture specific part ****/ + +/** + * @param frame exception frame pointer + * @return the appropriate "signal" number for the given exception cause + */ +int esp_gdbstub_get_signal(const esp_gdbstub_frame_t *frame); + +/** + * Write registers from the exception frame to the GDB register file + * @param frame exception frame to parse + * @param dst pointer to the GDB register file + */ +void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_gdb_regfile_t *dst); + +#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +/** + * Write registers from the saved frame of a given task to the GDB register file + * @param tcb pointer to the TCB of the task + * @param dst pointer to the GDB register file + */ +void esp_gdbstub_tcb_to_regfile(TaskHandle_t tcb, esp_gdbstub_gdb_regfile_t *dst); +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + + + +/**** Functions provided by the target specific part ****/ + +/** + * Do target-specific initialization before gdbstub can start communicating. + * This may involve, for example, configuring the UART. + */ +void esp_gdbstub_target_init(void); + +/** + * Receive a byte from the GDB client. Blocks until a byte is available. + * @return received byte + */ +int esp_gdbstub_getchar(void); + +/** + * Send a byte to the GDB client + * @param c byte to send + */ +void esp_gdbstub_putchar(int c); + +/** + * Read a byte from target memory + * @param ptr address + * @return byte value, or GDBSTUB_ST_ERR if the address is not readable + */ +int esp_gdbstub_readmem(intptr_t addr); + + +/**** GDB packet related functions ****/ + +/** Begin a packet */ +void esp_gdbstub_send_start(void); + +/** Send a character as part of the packet */ +void esp_gdbstub_send_char(char c); + +/** Send a string as part of the packet */ +void esp_gdbstub_send_str(const char *s); + +/** Send a hex value as part of the packet */ +void esp_gdbstub_send_hex(int val, int bits); + +/** Finish sending the packet */ +void esp_gdbstub_send_end(void); + +/** Send a packet with a string as content */ +void esp_gdbstub_send_str_packet(const char* str); + +/** Get a hex value from the gdb packet */ +uint32_t esp_gdbstub_gethex(const unsigned char **ptr, int bits); + +/** Read, unescape, and validate the incoming GDB command */ +int esp_gdbstub_read_command(unsigned char **out_cmd, size_t *out_size); + +/** Handle a command received from gdb */ +int esp_gdbstub_handle_command(unsigned char *cmd, int len); + diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c new file mode 100644 index 000000000..f15be617f --- /dev/null +++ b/components/esp_gdbstub/src/gdbstub.c @@ -0,0 +1,345 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp_gdbstub.h" +#include "esp_gdbstub_common.h" +#include "sdkconfig.h" + + +#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +static void init_task_info(void); +static void find_paniced_task_index(void); +static int handle_task_commands(unsigned char *cmd, int len); +#endif + +static void send_reason(void); + + +static esp_gdbstub_scratch_t s_scratch; + + +void esp_gdbstub_panic_handler(esp_gdbstub_frame_t *frame) +{ +#ifndef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + esp_gdbstub_frame_to_regfile(frame, &s_scratch.regfile); +#else + if (s_scratch.state == GDBSTUB_STARTED) { + /* We have re-entered GDB Stub. Try disabling task support. */ + s_scratch.state = GDBSTUB_TASK_SUPPORT_DISABLED; + /* Flush any pending GDB packet (this creates a garbage value) */ + esp_gdbstub_send_end(); + } else if (s_scratch.state == GDBSTUB_NOT_STARTED) { + s_scratch.state = GDBSTUB_STARTED; + /* Save the paniced frame and get the list of tasks */ + memcpy(&s_scratch.paniced_frame, frame, sizeof(*frame)); + esp_gdbstub_frame_to_regfile(frame, &s_scratch.regfile); + init_task_info(); + find_paniced_task_index(); + /* Current task is the paniced task */ + if (s_scratch.paniced_task_index == GDBSTUB_CUR_TASK_INDEX_UNKNOWN) { + s_scratch.current_task_index = 0; + } + } +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + + esp_gdbstub_target_init(); + s_scratch.signal = esp_gdbstub_get_signal(frame); + send_reason(); + while (true) { + unsigned char *cmd; + size_t size; + int res = esp_gdbstub_read_command(&cmd, &size); + if (res > 0) { + /* character received instead of a command */ + continue; + } + if (res == GDBSTUB_ST_ERR) { + esp_gdbstub_send_str_packet("E01"); + continue; + } + res = esp_gdbstub_handle_command(cmd, size); + if (res == GDBSTUB_ST_ERR) { + esp_gdbstub_send_str_packet(NULL); + } + } +} + + +static void send_reason(void) +{ + esp_gdbstub_send_start(); + esp_gdbstub_send_char('T'); + esp_gdbstub_send_hex(s_scratch.signal, 8); + esp_gdbstub_send_end(); +} + +static uint32_t gdbstub_hton(uint32_t i) +{ + return __builtin_bswap32(i); +} + +/** Send all registers to gdb */ +static void handle_g_command(const unsigned char* cmd, int len) +{ + uint32_t *p = (uint32_t *) &s_scratch.regfile; + esp_gdbstub_send_start(); + for (int i = 0; i < sizeof(s_scratch.regfile) / sizeof(*p); ++i) { + esp_gdbstub_send_hex(gdbstub_hton(*p++), 32); + } + esp_gdbstub_send_end(); +} + +/** Receive register values from gdb */ +static void handle_G_command(const unsigned char* cmd, int len) +{ + uint32_t *p = (uint32_t *) &s_scratch.regfile; + for (int i = 0; i < sizeof(s_scratch.regfile) / sizeof(*p); ++i) { + *p++ = gdbstub_hton(esp_gdbstub_gethex(&cmd, 32)); + } + esp_gdbstub_send_str_packet("OK"); +} + +/** Read memory to gdb */ +static void handle_m_command(const unsigned char* cmd, int len) +{ + intptr_t addr = (intptr_t) esp_gdbstub_gethex(&cmd, -1); + cmd++; + uint32_t size = esp_gdbstub_gethex(&cmd, -1); + + if (esp_gdbstub_readmem(addr) < 0 || esp_gdbstub_readmem(addr + size - 1) < 0) { + esp_gdbstub_send_str_packet("E01"); + return; + } + + esp_gdbstub_send_start(); + for (int i = 0; i < size; ++i) { + int b = esp_gdbstub_readmem(addr++); + esp_gdbstub_send_hex(b, 8); + } + esp_gdbstub_send_end(); +} + +/** Handle a command received from gdb */ +int esp_gdbstub_handle_command(unsigned char *cmd, int len) +{ + unsigned char *data = cmd + 1; + if (cmd[0] == 'g') + { + handle_g_command(data, len - 1); + } else if (cmd[0] == 'G') { + /* receive content for all registers from gdb */ + handle_G_command(data, len - 1); + } else if (cmd[0] == 'm') { + /* read memory to gdb */ + handle_m_command(data, len - 1); + } else if (cmd[0] == '?') { + /* Reply with stop reason */ + send_reason(); +#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + } else if (s_scratch.state != GDBSTUB_TASK_SUPPORT_DISABLED) { + return handle_task_commands(cmd, len); +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + } else { + /* Unrecognized command */ + return GDBSTUB_ST_ERR; + } + return GDBSTUB_ST_OK; +} + +/* Everything below is related to the support for listing FreeRTOS tasks as threads in GDB */ + +#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + +static void init_task_info(void) +{ + unsigned tcb_size; + s_scratch.task_count = uxTaskGetSnapshotAll(s_scratch.tasks, GDBSTUB_TASKS_NUM, &tcb_size); +} + +static bool get_task_handle(size_t index, TaskHandle_t *handle) +{ + if (index >= s_scratch.task_count) { + return false; + } + *handle = (TaskHandle_t) s_scratch.tasks[index].pxTCB; + return true; +} + +/** Get the index of the task running on the current CPU, and save the result */ +static void find_paniced_task_index(void) +{ + TaskHandle_t cur_handle = xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID()); + TaskHandle_t handle; + for (int i = 0; i < s_scratch.task_count; i++) { + if (get_task_handle(i, &handle) && cur_handle == handle) { + s_scratch.paniced_task_index = i; + return; + } + } + s_scratch.paniced_task_index = GDBSTUB_CUR_TASK_INDEX_UNKNOWN; +} + +/** H command sets the "current task" for the purpose of further commands */ +static void handle_H_command(const unsigned char* cmd, int len) +{ + if (cmd[1] == 'g' || cmd[1] == 'c') { + const char *ret = "OK"; + cmd += 2; + int requested_task_index = esp_gdbstub_gethex(&cmd, -1); + if (requested_task_index == s_scratch.paniced_task_index || + (requested_task_index == 0 && s_scratch.current_task_index == GDBSTUB_CUR_TASK_INDEX_UNKNOWN)) { + /* Get the registers of the paniced task */ + esp_gdbstub_frame_to_regfile(&s_scratch.paniced_frame, &s_scratch.regfile); + } else if (requested_task_index > s_scratch.task_count) { + ret = "E00"; + } else { + TaskHandle_t handle = NULL; + get_task_handle(requested_task_index, &handle); + /* FIXME: for the task currently running on the other CPU, extracting the registers from TCB + * isn't valid. Need to use some IPC mechanism to obtain the registers of the other CPU + */ + if (handle != NULL) { + esp_gdbstub_tcb_to_regfile(handle, &s_scratch.regfile); + } + } + esp_gdbstub_send_str_packet(ret); + } else { + esp_gdbstub_send_str_packet(NULL); + } +} + +/** qC returns the current thread ID */ +static void handle_qC_command(const unsigned char* cmd, int len) +{ + esp_gdbstub_send_start(); + esp_gdbstub_send_str("QC"); + esp_gdbstub_send_hex(s_scratch.current_task_index, 32); + esp_gdbstub_send_end(); +} + +/** T command checks if the task is alive. + * Since GDB isn't going to ask about the tasks which haven't been listed by q*ThreadInfo, + * and the state of tasks can not change (no stepping allowed), simply return "OK" here. + */ +static void handle_T_command(const unsigned char* cmd, int len) +{ + esp_gdbstub_send_str_packet("OK"); +} + +/** qfThreadInfo requests the start of the thread list, qsThreadInfo (below) is repeated to + * get the subsequent threads. + */ +static void handle_qfThreadInfo_command(const unsigned char* cmd, int len) +{ + /* The first task in qfThreadInfo reply is going to be the one which GDB will request to stop. + * Therefore it has to be the paniced task. + * Reply with the paniced task index, and later skip over this index while handling qsThreadInfo + */ + esp_gdbstub_send_start(); + esp_gdbstub_send_str("m"); + esp_gdbstub_send_hex(s_scratch.paniced_task_index, 32); + esp_gdbstub_send_end(); + + s_scratch.thread_info_index = 0; +} + +static void handle_qsThreadInfo_command(const unsigned char* cmd, int len) +{ + int next_task_index = ++s_scratch.thread_info_index; + + if (next_task_index == s_scratch.task_count) { + /* No more tasks */ + esp_gdbstub_send_str_packet("l"); + return; + } + + if (next_task_index == s_scratch.paniced_task_index) { + /* Have already sent this one in the reply to qfThreadInfo, skip over it */ + handle_qsThreadInfo_command(cmd, len); + return; + } + + esp_gdbstub_send_start(); + esp_gdbstub_send_str("m"); + esp_gdbstub_send_hex(next_task_index, 32); + esp_gdbstub_send_end(); +} + +/** qThreadExtraInfo requests the thread name */ +static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) +{ + cmd += sizeof("qThreadExtraInfo,") - 1; + int task_index = esp_gdbstub_gethex(&cmd, -1); + TaskHandle_t handle; + if (!get_task_handle(task_index, &handle)) { + esp_gdbstub_send_str_packet("E01"); + return; + } + esp_gdbstub_send_start(); + const char* task_name = pcTaskGetTaskName(handle); + while (*task_name) { + esp_gdbstub_send_hex(*task_name, 8); + task_name++; + } + /** TODO: add "Running" or "Suspended" and "CPU0" or "CPU1" */ + esp_gdbstub_send_end(); +} + +bool command_name_matches(const char* pattern, const unsigned char* ucmd, int len) +{ + const char* cmd = (const char*) ucmd; + const char* end = cmd + len; + for (; *pattern && cmd < end; ++cmd, ++pattern) { + if (*pattern == '?') { + continue; + } + if (*pattern != *cmd) { + return false; + } + } + return *pattern == 0 && (cmd == end || *cmd == ','); +} + +/** Handle all the thread-related commands */ +static int handle_task_commands(unsigned char *cmd, int len) +{ + if (cmd[0] == 'H') { + /* Continue with task */ + handle_H_command(cmd, len); + } else if (cmd[0] == 'T') { + /* Task alive check */ + handle_T_command(cmd, len); + } else if (cmd[0] == 'q') { + if (command_name_matches("qfThreadInfo", cmd, len)) { + handle_qfThreadInfo_command(cmd, len); + } else if (command_name_matches("qsThreadInfo", cmd, len)) { + handle_qsThreadInfo_command(cmd, len); + } else if (command_name_matches("qC", cmd, len)) { + handle_qC_command(cmd, len); + } else if (command_name_matches("qThreadExtraInfo", cmd, len)) { + handle_qThreadExtraInfo_command(cmd, len); + } else { + /* Unrecognized command */ + return GDBSTUB_ST_ERR; + } + } else { + /* Unrecognized command */ + return GDBSTUB_ST_ERR; + } + return GDBSTUB_ST_OK; +} + +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + diff --git a/components/esp_gdbstub/src/packet.c b/components/esp_gdbstub/src/packet.c new file mode 100644 index 000000000..39e0c6883 --- /dev/null +++ b/components/esp_gdbstub/src/packet.c @@ -0,0 +1,177 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_gdbstub_common.h" + +// GDB command input buffer +static unsigned char s_cmd[GDBSTUB_CMD_BUFLEN]; + +// Running checksum of the output packet +static char s_chsum; + +// Send the start of a packet; reset checksum calculation. +void esp_gdbstub_send_start(void) +{ + s_chsum = 0; + esp_gdbstub_putchar('$'); +} + +// Send a char as part of a packet +void esp_gdbstub_send_char(char c) +{ + if (c == '#' || c == '$' || c == '}' || c == '*') { + esp_gdbstub_putchar('}'); + esp_gdbstub_putchar(c ^ 0x20); + s_chsum += (c ^ 0x20) + '}'; + } else { + esp_gdbstub_putchar(c); + s_chsum += c; + } +} + +// Send a string as part of a packet +void esp_gdbstub_send_str(const char *c) +{ + while (*c != 0) { + esp_gdbstub_send_char(*c); + c++; + } +} + +// Send a hex val as part of a packet. +// 'bits'/4 dictates the number of hex chars sent. +void esp_gdbstub_send_hex(int val, int bits) +{ + const char* hex_chars = "0123456789abcdef"; + for (int i = bits; i > 0; i -= 4) { + esp_gdbstub_send_char(hex_chars[(val >> (i - 4)) & 0xf]); + } +} + +// Finish sending a packet. +void esp_gdbstub_send_end(void) +{ + esp_gdbstub_putchar('#'); + esp_gdbstub_send_hex(s_chsum, 8); +} + +// Send a packet with a string as content +void esp_gdbstub_send_str_packet(const char* str) +{ + esp_gdbstub_send_start(); + if (str != NULL) { + esp_gdbstub_send_str(str); + } + esp_gdbstub_send_end(); +} + +// Grab a hex value from the gdb packet. Ptr will get positioned on the end +// of the hex string, as far as the routine has read into it. Bits/4 indicates +// the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much +// hex chars as possible. +uint32_t esp_gdbstub_gethex(const unsigned char **ptr, int bits) +{ + int i; + int no; + uint32_t v = 0; + char c; + no = bits / 4; + if (bits == -1) { + no = 64; + } + for (i = 0; i < no; i++) { + c = **ptr; + (*ptr)++; + if (c >= '0' && c <= '9') { + v <<= 4; + v |= (c - '0'); + } else if (c >= 'A' && c <= 'F') { + v <<= 4; + v |= (c - 'A') + 10; + } else if (c >= 'a' && c <= 'f') { + v <<= 4; + v |= (c - 'a') + 10; + } else if (c == '#') { + if (bits == -1) { + (*ptr)--; + return v; + } + return GDBSTUB_ST_ENDPACKET; + } else { + if (bits == -1) { + (*ptr)--; + return v; + } + return GDBSTUB_ST_ERR; + } + } + return v; +} + + +// Lower layer: grab a command packet and check the checksum +// Calls gdbHandleCommand on the packet if the checksum is OK +// Returns GDBSTUB_ST_OK on success, GDBSTUB_ST_ERR when checksum fails, a +// character if it is received instead of the GDB packet +// start char. +int esp_gdbstub_read_command(unsigned char **out_cmd, size_t *out_size) +{ + unsigned char c; + unsigned char chsum = 0; + unsigned char sentchs[2]; + int p = 0; + c = esp_gdbstub_getchar(); + if (c != '$') { + return c; + } + while (1) { + c = esp_gdbstub_getchar(); + if (c == '#') { + // end of packet, checksum follows + s_cmd[p] = 0; + break; + } + chsum += c; + if (c == '$') { + // restart packet? + chsum = 0; + p = 0; + continue; + } + if (c == '}') { + //escape the next char + c = esp_gdbstub_getchar(); + chsum += c; + c ^= 0x20; + } + s_cmd[p++] = c; + if (p >= GDBSTUB_CMD_BUFLEN) { + return GDBSTUB_ST_ERR; + } + } + // A # has been received. Get and check the received chsum. + sentchs[0] = esp_gdbstub_getchar(); + sentchs[1] = esp_gdbstub_getchar(); + const unsigned char* c_ptr = &sentchs[0]; + unsigned char rchsum = esp_gdbstub_gethex(&c_ptr, 8); + if (rchsum != chsum) { + esp_gdbstub_putchar('-'); + return GDBSTUB_ST_ERR; + } else { + esp_gdbstub_putchar('+'); + *out_cmd = s_cmd; + *out_size = p; + return GDBSTUB_ST_OK; + } +} diff --git a/components/esp_gdbstub/xtensa/esp_gdbstub_arch.h b/components/esp_gdbstub/xtensa/esp_gdbstub_arch.h new file mode 100644 index 000000000..ad79d6082 --- /dev/null +++ b/components/esp_gdbstub/xtensa/esp_gdbstub_arch.h @@ -0,0 +1,93 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include "freertos/xtensa_context.h" +#include "gdbstub_target_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef XtExcFrame esp_gdbstub_frame_t; + +/* GDB regfile structure, configuration dependent */ +typedef struct { + uint32_t a[XCHAL_NUM_AREGS]; + uint32_t pc; + +#if XCHAL_HAVE_LOOPS + uint32_t lbeg; + uint32_t lend; + uint32_t lcount; +#endif + + uint32_t sar; + + uint32_t litbase; + +#if XCHAL_HAVE_WINDOWED + uint32_t windowbase; + uint32_t windowstart; +#endif + + uint32_t configid0; + uint32_t configid1; + uint32_t ps; + +#if XCHAL_HAVE_THREADPTR + uint32_t threadptr; +#endif + +#if XCHAL_HAVE_BOOLEANS + uint32_t br; +#endif + +#if XCHAL_HAVE_S32C1I + uint32_t scompare1; +#endif + +#if XCHAL_HAVE_MAC16 + uint32_t acclo; + uint32_t acchi; + uint32_t m0; + uint32_t m1; + uint32_t m2; + uint32_t m3; +#endif + +#if XCHAL_HAVE_DFP_ACCEL + uint32_t expstate; + uint32_t f64r_lo; + uint32_t f64r_hi; + uint32_t f64s; +#endif + +#if XCHAL_HAVE_FP + uint32_t f[16]; + uint32_t fcr; + uint32_t fsr; +#endif + +#if GDBSTUB_EXTRA_TIE_SIZE > 0 + uint32_t tie[GDBSTUB_EXTRA_TIE_SIZE]; +#endif + +} esp_gdbstub_gdb_regfile_t; + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_gdbstub/xtensa/gdbstub_xtensa.c b/components/esp_gdbstub/xtensa/gdbstub_xtensa.c new file mode 100644 index 000000000..023cec728 --- /dev/null +++ b/components/esp_gdbstub/xtensa/gdbstub_xtensa.c @@ -0,0 +1,125 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp_gdbstub.h" +#include "esp_gdbstub_common.h" +#include "esp8266/eagle_soc.h" +#include "sdkconfig.h" + +inline static bool esp_stack_ptr_is_sane(uint32_t sp) +{ + //Check if stack ptr is in between SOC_DRAM_LOW and SOC_DRAM_HIGH, and 16 byte aligned. + return !(!IS_DRAM(sp) || ((sp & 0xF) != 0)); +} + +static void init_regfile(esp_gdbstub_gdb_regfile_t *dst) +{ + memset(dst, 0, sizeof(*dst)); +} + +static void update_regfile_common(esp_gdbstub_gdb_regfile_t *dst) +{ + if (dst->a[0] & 0x8000000U) { + dst->a[0] = (dst->a[0] & 0x3fffffffU) | 0x40000000U; + } + if (!esp_stack_ptr_is_sane(dst->a[1])) { + dst->a[1] = 0xDEADBEEF; + } +#if XCHAL_HAVE_WINDOWED + dst->windowbase = 0; + dst->windowstart = 0x1; + RSR(CONFIGID0, dst->configid0); + RSR(CONFIGID1, dst->configid1); +#endif +} + +void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_gdb_regfile_t *dst) +{ + init_regfile(dst); + const uint32_t *a_regs = (const uint32_t *) &frame->a0; + dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U; + + for (int i = 0; i < 16; i++) { + dst->a[i] = a_regs[i]; + } +#if XCHAL_HAVE_WINDOWED + for (int i = 16; i < 64; i++) { + dst->a[i] = 0xDEADBEEF; + } +#endif + +#if XCHAL_HAVE_LOOPS + dst->lbeg = frame->lbeg; + dst->lend = frame->lend; + dst->lcount = frame->lcount; +#endif + + dst->ps = (frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps; + dst->sar = frame->sar; + update_regfile_common(dst); +} + +#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + +static void solicited_frame_to_regfile(const XtSolFrame *frame, esp_gdbstub_gdb_regfile_t *dst) +{ + init_regfile(dst); + const uint32_t *a_regs = (const uint32_t *) &frame->a0; + dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U; + + /* only 4 registers saved in the solicited frame */ + for (int i = 0; i < 4; i++) { + dst->a[i] = a_regs[i]; + } +#if XCHAL_HAVE_WINDOWED + for (int i = 4; i < 64; i++) { + dst->a[i] = 0xDEADBEEF; + } +#endif + + dst->ps = (frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps; + update_regfile_common(dst); +} + +/* Represents FreeRTOS TCB structure */ +typedef struct { + uint8_t *top_of_stack; + /* Other members aren't needed */ +} dummy_tcb_t; + + +void esp_gdbstub_tcb_to_regfile(TaskHandle_t tcb, esp_gdbstub_gdb_regfile_t *dst) +{ + const dummy_tcb_t *dummy_tcb = (const dummy_tcb_t *) tcb; + + const XtExcFrame *frame = (XtExcFrame *) dummy_tcb->top_of_stack; + if (frame->exit != 0) { + esp_gdbstub_frame_to_regfile(frame, dst); + } else { + const XtSolFrame *taskFrame = (const XtSolFrame *) dummy_tcb->top_of_stack; + solicited_frame_to_regfile(taskFrame, dst); + } +} + +#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS + +int esp_gdbstub_get_signal(const esp_gdbstub_frame_t *frame) +{ + const char exccause_to_signal[] = {4, 31, 11, 11, 2, 6, 8, 0, 6, 7, 0, 0, 7, 7, 7, 7}; + if (frame->exccause > sizeof(exccause_to_signal)) { + return 11; + } + return (int) exccause_to_signal[frame->exccause]; +} diff --git a/components/esp_http_client/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt new file mode 100644 index 000000000..b2f9ec1e1 --- /dev/null +++ b/components/esp_http_client/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register(SRCS "esp_http_client.c" + "lib/http_auth.c" + "lib/http_header.c" + "lib/http_utils.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "lib/include" + REQUIRES http_parser + PRIV_REQUIRES mbedtls lwip esp-tls tcp_transport tcpip_adapter) diff --git a/components/esp_http_client/Kconfig b/components/esp_http_client/Kconfig new file mode 100644 index 000000000..a2e56c5d4 --- /dev/null +++ b/components/esp_http_client/Kconfig @@ -0,0 +1,23 @@ +menu "ESP HTTP client" + + + config ESP_HTTP_CLIENT_ENABLE_HTTPS + bool "Enable https" + default y + help + This option will enable https protocol by linking mbedtls library and initializing SSL transport + + config ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH + bool "Enable HTTP Basic Authentication" + default n + help + This option will enable HTTP Basic Authentication. It is disabled by default as Basic + auth uses unencrypted encoding, so it introduces a vulnerability when not using TLS + + config HTTP_BUF_SIZE + int "Default HTTP Buffer Size (both send and receive)" + default 512 + range 512 1460 + help + Set HTTP Buffer Size. The larger buffer size will make send and receive more size packet once. +endmenu diff --git a/components/esp_http_client/component.mk b/components/esp_http_client/component.mk new file mode 100644 index 000000000..96b5b6c4c --- /dev/null +++ b/components/esp_http_client/component.mk @@ -0,0 +1,6 @@ +# +# Component Makefile +# + +COMPONENT_SRCDIRS := . lib +COMPONENT_PRIV_INCLUDEDIRS := lib/include diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c new file mode 100644 index 000000000..b059a58db --- /dev/null +++ b/components/esp_http_client/esp_http_client.c @@ -0,0 +1,1359 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include + +#include "esp_system.h" +#include "esp_log.h" + +#include "http_header.h" +#include "esp_transport.h" +#include "esp_transport_tcp.h" +#include "http_utils.h" +#include "http_auth.h" +#include "sdkconfig.h" +#include "esp_http_client.h" +#include "errno.h" + +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS +#include "esp_transport_ssl.h" +#endif + +static const char *TAG = "HTTP_CLIENT"; + +/** + * HTTP Buffer + */ +typedef struct { + char *data; /*!< The HTTP data received from the server */ + int len; /*!< The HTTP data len received from the server */ + char *raw_data; /*!< The HTTP data after decoding */ + int raw_len; /*!< The HTTP data len after decoding */ + char *output_ptr; /*!< The destination address of the data to be copied to after decoding */ +} esp_http_buffer_t; + +/** + * private HTTP Data structure + */ +typedef struct { + http_header_handle_t headers; /*!< http header */ + esp_http_buffer_t *buffer; /*!< data buffer as linked list */ + int status_code; /*!< status code (integer) */ + int content_length; /*!< data length */ + int data_offset; /*!< offset to http data (Skip header) */ + int data_process; /*!< data processed */ + int method; /*!< http method */ + bool is_chunked; +} esp_http_data_t; + +typedef struct { + char *url; + char *scheme; + char *host; + int port; + char *username; + char *password; + char *path; + char *query; + char *cert_pem; + esp_http_client_method_t method; + esp_http_client_auth_type_t auth_type; + esp_http_client_transport_t transport_type; + int max_store_header_size; +} connection_info_t; + +typedef enum { + HTTP_STATE_UNINIT = 0, + HTTP_STATE_INIT, + HTTP_STATE_CONNECTED, + HTTP_STATE_REQ_COMPLETE_HEADER, + HTTP_STATE_REQ_COMPLETE_DATA, + HTTP_STATE_RES_COMPLETE_HEADER, + HTTP_STATE_RES_COMPLETE_DATA, + HTTP_STATE_CLOSE +} esp_http_state_t; +/** + * HTTP client class + */ +struct esp_http_client { + int redirect_counter; + int max_redirection_count; + int process_again; + struct http_parser *parser; + struct http_parser_settings *parser_settings; + esp_transport_list_handle_t transport_list; + esp_transport_handle_t transport; + esp_http_data_t *request; + esp_http_data_t *response; + void *user_data; + esp_http_auth_data_t *auth_data; + char *post_data; + char *location; + char *auth_header; + char *current_header_key; + char *current_header_value; + int post_len; + connection_info_t connection_info; + bool is_chunk_complete; + esp_http_state_t state; + http_event_handle_cb event_handler; + int timeout_ms; + int buffer_size_rx; + int buffer_size_tx; + bool disable_auto_redirect; + esp_http_client_event_t event; + int data_written_index; + int data_write_left; + bool first_line_prepared; + int header_index; + bool is_async; +}; + +typedef struct esp_http_client esp_http_client_t; + +static esp_err_t _clear_connection_info(esp_http_client_handle_t client); +/** + * Default settings + */ +#define DEFAULT_HTTP_PORT (80) +#define DEFAULT_HTTPS_PORT (443) + +#define ASYNC_TRANS_CONNECT_FAIL -1 +#define ASYNC_TRANS_CONNECTING 0 +#define ASYNC_TRANS_CONNECT_PASS 1 + +static const char *DEFAULT_HTTP_USER_AGENT = "ESP32 HTTP Client/1.0"; +static const char *DEFAULT_HTTP_PROTOCOL = "HTTP/1.1"; +static const char *DEFAULT_HTTP_PATH = "/"; +static int DEFAULT_MAX_REDIRECT = 10; +static int DEFAULT_TIMEOUT_MS = 5000; + +static const char *HTTP_METHOD_MAPPING[] = { + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "HEAD", + "NOTIFY", + "SUBSCRIBE", + "UNSUBSCRIBE", + "OPTIONS" +}; + +static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len); +static esp_err_t esp_http_client_connect(esp_http_client_handle_t client); +static esp_err_t esp_http_client_send_post_data(esp_http_client_handle_t client); + +static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_event_id_t event_id, void *data, int len) +{ + esp_http_client_event_t *event = &client->event; + + if (client->event_handler) { + event->event_id = event_id; + event->user_data = client->user_data; + event->data = data; + event->data_len = len; + return client->event_handler(event); + } + return ESP_OK; +} + +static int http_on_message_begin(http_parser *parser) +{ + esp_http_client_t *client = parser->data; + ESP_LOGD(TAG, "on_message_begin"); + + client->response->is_chunked = false; + client->is_chunk_complete = false; + return 0; +} + +static int http_on_url(http_parser *parser, const char *at, size_t length) +{ + ESP_LOGD(TAG, "http_on_url"); + return 0; +} + +static int http_on_status(http_parser *parser, const char *at, size_t length) +{ + return 0; +} + +static int http_on_header_field(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_t *client = parser->data; + http_utils_assign_string(&client->current_header_key, at, length); + + return 0; +} + +static int http_on_header_value(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_handle_t client = parser->data; + if (client->current_header_key == NULL) { + return 0; + } + if (strcasecmp(client->current_header_key, "Location") == 0) { + http_utils_assign_string(&client->location, at, length); + } else if (strcasecmp(client->current_header_key, "Transfer-Encoding") == 0 + && memcmp(at, "chunked", length) == 0) { + client->response->is_chunked = true; + } else if (strcasecmp(client->current_header_key, "WWW-Authenticate") == 0) { + http_utils_assign_string(&client->auth_header, at, length); + } + http_utils_assign_string(&client->current_header_value, at, length); + + ESP_LOGD(TAG, "HEADER=%s:%s", client->current_header_key, client->current_header_value); + client->event.header_key = client->current_header_key; + client->event.header_value = client->current_header_value; + http_dispatch_event(client, HTTP_EVENT_ON_HEADER, NULL, 0); + free(client->current_header_key); + free(client->current_header_value); + client->current_header_key = NULL; + client->current_header_value = NULL; + return 0; +} + +static int http_on_headers_complete(http_parser *parser) +{ + esp_http_client_handle_t client = parser->data; + client->response->status_code = parser->status_code; + client->response->data_offset = parser->nread; + client->response->content_length = parser->content_length; + client->response->data_process = 0; + ESP_LOGD(TAG, "http_on_headers_complete, status=%d, offset=%d, nread=%d", parser->status_code, client->response->data_offset, parser->nread); + client->state = HTTP_STATE_RES_COMPLETE_HEADER; + return 0; +} + +static int http_on_body(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_t *client = parser->data; + ESP_LOGD(TAG, "http_on_body %d", length); + client->response->buffer->raw_data = (char *)at; + if (client->response->buffer->output_ptr) { + memcpy(client->response->buffer->output_ptr, (char *)at, length); + client->response->buffer->output_ptr += length; + } + + client->response->data_process += length; + client->response->buffer->raw_len += length; + http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length); + return 0; +} + +static int http_on_message_complete(http_parser *parser) +{ + ESP_LOGD(TAG, "http_on_message_complete, parser=%x", (int)parser); + esp_http_client_handle_t client = parser->data; + client->is_chunk_complete = true; + return 0; +} + +static int http_on_chunk_complete(http_parser *parser) +{ + ESP_LOGD(TAG, "http_on_chunk_complete"); + return 0; +} + +esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char *key, const char *value) +{ + return http_header_set(client->request->headers, key, value); +} + +esp_err_t esp_http_client_get_header(esp_http_client_handle_t client, const char *key, char **value) +{ + return http_header_get(client->request->headers, key, value); +} + +esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const char *key) +{ + return http_header_delete(client->request->headers, key); +} + +esp_err_t esp_http_client_get_username(esp_http_client_handle_t client, char **value) +{ + if (client == NULL || value == NULL) { + ESP_LOGE(TAG, "client or value must not be NULL"); + return ESP_ERR_INVALID_ARG; + } + *value = client->connection_info.username; + return ESP_OK; +} + +esp_err_t esp_http_client_set_username(esp_http_client_handle_t client, const char *username) +{ + if (client == NULL) { + ESP_LOGE(TAG, "client must not be NULL"); + return ESP_ERR_INVALID_ARG; + } + if (client->connection_info.username != NULL) { + free(client->connection_info.username); + } + client->connection_info.username = username ? strdup(username) : NULL; + return ESP_OK; +} + +esp_err_t esp_http_client_get_password(esp_http_client_handle_t client, char **value) +{ + if (client == NULL || value == NULL) { + ESP_LOGE(TAG, "client or value must not be NULL"); + return ESP_ERR_INVALID_ARG; + } + *value = client->connection_info.password; + return ESP_OK; +} + +esp_err_t esp_http_client_set_password(esp_http_client_handle_t client, char *password) +{ + if (client == NULL) { + ESP_LOGE(TAG, "client must not be NULL"); + return ESP_ERR_INVALID_ARG; + } + if (client->connection_info.password != NULL) { + memset(client->connection_info.password, 0, strlen(client->connection_info.password)); + free(client->connection_info.password); + } + client->connection_info.password = password ? strdup(password) : NULL; + return ESP_OK; +} + +esp_err_t esp_http_client_set_authtype(esp_http_client_handle_t client, esp_http_client_auth_type_t auth_type) +{ + if (client == NULL) { + ESP_LOGE(TAG, "client must not be NULL"); + return ESP_ERR_INVALID_ARG; + } + client->connection_info.auth_type = auth_type; + return ESP_OK; +} + +static esp_err_t _set_config(esp_http_client_handle_t client, const esp_http_client_config_t *config) +{ + client->connection_info.method = config->method; + client->connection_info.port = config->port; + client->connection_info.auth_type = config->auth_type; + client->event_handler = config->event_handler; + client->timeout_ms = config->timeout_ms; + client->max_redirection_count = config->max_redirection_count; + client->user_data = config->user_data; + client->buffer_size_rx = config->buffer_size; + client->buffer_size_tx = config->buffer_size_tx; + client->disable_auto_redirect = config->disable_auto_redirect; + + if (config->buffer_size == 0) { + client->buffer_size_rx = DEFAULT_HTTP_BUF_SIZE; + } + + if (config->buffer_size_tx == 0) { + client->buffer_size_tx = DEFAULT_HTTP_BUF_SIZE; + } + + if (client->max_redirection_count == 0) { + client->max_redirection_count = DEFAULT_MAX_REDIRECT; + } + + if (config->path) { + client->connection_info.path = strdup(config->path); + } else { + client->connection_info.path = strdup(DEFAULT_HTTP_PATH); + } + HTTP_MEM_CHECK(TAG, client->connection_info.path, { + return ESP_ERR_NO_MEM; + }); + + if (config->host) { + client->connection_info.host = strdup(config->host); + + HTTP_MEM_CHECK(TAG, client->connection_info.host, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->query) { + client->connection_info.query = strdup(config->query); + HTTP_MEM_CHECK(TAG, client->connection_info.query, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->username) { + client->connection_info.username = strdup(config->username); + HTTP_MEM_CHECK(TAG, client->connection_info.username, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->password) { + client->connection_info.password = strdup(config->password); + HTTP_MEM_CHECK(TAG, client->connection_info.password, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->transport_type == HTTP_TRANSPORT_OVER_SSL) { + http_utils_assign_string(&client->connection_info.scheme, "https", 0); + if (client->connection_info.port == 0) { + client->connection_info.port = DEFAULT_HTTPS_PORT; + } + } else { + http_utils_assign_string(&client->connection_info.scheme, "http", 0); + if (client->connection_info.port == 0) { + client->connection_info.port = DEFAULT_HTTP_PORT; + } + } + if (client->timeout_ms == 0) { + client->timeout_ms = DEFAULT_TIMEOUT_MS; + } + if (config->is_async) { + client->is_async = true; + } + + return ESP_OK; +} + +static esp_err_t _clear_connection_info(esp_http_client_handle_t client) +{ + free(client->connection_info.path); + free(client->connection_info.host); + free(client->connection_info.query); + free(client->connection_info.username); + if (client->connection_info.password) { + memset(client->connection_info.password, 0, strlen(client->connection_info.password)); + free(client->connection_info.password); + } + free(client->connection_info.scheme); + free(client->connection_info.url); + memset(&client->connection_info, 0, sizeof(connection_info_t)); + return ESP_OK; +} + +static esp_err_t _clear_auth_data(esp_http_client_handle_t client) +{ + if (client->auth_data == NULL) { + return ESP_FAIL; + } + + free(client->auth_data->method); + free(client->auth_data->realm); + free(client->auth_data->algorithm); + free(client->auth_data->qop); + free(client->auth_data->nonce); + free(client->auth_data->opaque); + memset(client->auth_data, 0, sizeof(esp_http_auth_data_t)); + return ESP_OK; +} + +static esp_err_t esp_http_client_prepare(esp_http_client_handle_t client) +{ + client->process_again = 0; + client->response->data_process = 0; + client->first_line_prepared = false; + http_parser_init(client->parser, HTTP_RESPONSE); + if (client->connection_info.username) { + char *auth_response = NULL; + + if (client->connection_info.auth_type == HTTP_AUTH_TYPE_BASIC) { + auth_response = http_auth_basic(client->connection_info.username, client->connection_info.password); + } else if (client->connection_info.auth_type == HTTP_AUTH_TYPE_DIGEST && client->auth_data) { + client->auth_data->uri = client->connection_info.path; + client->auth_data->cnonce = ((uint64_t)esp_random() << 32) + esp_random(); + auth_response = http_auth_digest(client->connection_info.username, client->connection_info.password, client->auth_data); + client->auth_data->nc ++; + } + + if (auth_response) { + ESP_LOGD(TAG, "auth_response=%s", auth_response); + esp_http_client_set_header(client, "Authorization", auth_response); + free(auth_response); + } + } + return ESP_OK; +} + +esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config) +{ + + esp_http_client_handle_t client; + esp_transport_handle_t tcp; + bool _success; + + _success = ( + (client = calloc(1, sizeof(esp_http_client_t))) && + (client->parser = calloc(1, sizeof(struct http_parser))) && + (client->parser_settings = calloc(1, sizeof(struct http_parser_settings))) && + (client->auth_data = calloc(1, sizeof(esp_http_auth_data_t))) && + (client->request = calloc(1, sizeof(esp_http_data_t))) && + (client->request->headers = http_header_init()) && + (client->request->buffer = calloc(1, sizeof(esp_http_buffer_t))) && + (client->response = calloc(1, sizeof(esp_http_data_t))) && + (client->response->headers = http_header_init()) && + (client->response->buffer = calloc(1, sizeof(esp_http_buffer_t))) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error allocate memory"); + goto error; + } + + _success = ( + (client->transport_list = esp_transport_list_init()) && + (tcp = esp_transport_tcp_init()) && + (esp_transport_set_default_port(tcp, DEFAULT_HTTP_PORT) == ESP_OK) && + (esp_transport_list_add(client->transport_list, tcp, "http") == ESP_OK) + ); + if (!_success) { + ESP_LOGE(TAG, "Error initialize transport"); + goto error; + } +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS + esp_transport_handle_t ssl; + _success = ( + (ssl = esp_transport_ssl_init()) && + (esp_transport_set_default_port(ssl, DEFAULT_HTTPS_PORT) == ESP_OK) && + (esp_transport_list_add(client->transport_list, ssl, "https") == ESP_OK) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error initialize SSL Transport"); + goto error; + } + + if (config->use_global_ca_store == true) { + esp_transport_ssl_enable_global_ca_store(ssl); + } else if (config->cert_pem) { + esp_transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem)); + } + + if (config->client_cert_pem) { + esp_transport_ssl_set_client_cert_data(ssl, config->client_cert_pem, strlen(config->client_cert_pem)); + } + + if (config->client_key_pem) { + esp_transport_ssl_set_client_key_data(ssl, config->client_key_pem, strlen(config->client_key_pem)); + } + + if (config->skip_cert_common_name_check) { + esp_transport_ssl_skip_common_name_check(ssl); + } +#endif + + if (_set_config(client, config) != ESP_OK) { + ESP_LOGE(TAG, "Error set configurations"); + goto error; + } + _success = ( + (client->request->buffer->data = malloc(client->buffer_size_tx)) && + (client->response->buffer->data = malloc(client->buffer_size_rx)) + ); + + if (!_success) { + ESP_LOGE(TAG, "Allocation failed"); + goto error; + } + + if (config->host != NULL && config->path != NULL) { + _success = ( + (esp_http_client_set_header(client, "User-Agent", DEFAULT_HTTP_USER_AGENT) == ESP_OK) && + (esp_http_client_set_header(client, "Host", client->connection_info.host) == ESP_OK) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error while setting default configurations"); + goto error; + } + } else if (config->url != NULL) { + _success = ( + (esp_http_client_set_url(client, config->url) == ESP_OK) && + (esp_http_client_set_header(client, "User-Agent", DEFAULT_HTTP_USER_AGENT) == ESP_OK) && + (esp_http_client_set_header(client, "Host", client->connection_info.host) == ESP_OK) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error while setting default configurations"); + goto error; + } + } else { + ESP_LOGE(TAG, "config should have either URL or host & path"); + goto error; + } + + client->parser_settings->on_message_begin = http_on_message_begin; + client->parser_settings->on_url = http_on_url; + client->parser_settings->on_status = http_on_status; + client->parser_settings->on_header_field = http_on_header_field; + client->parser_settings->on_header_value = http_on_header_value; + client->parser_settings->on_headers_complete = http_on_headers_complete; + client->parser_settings->on_body = http_on_body; + client->parser_settings->on_message_complete = http_on_message_complete; + client->parser_settings->on_chunk_complete = http_on_chunk_complete; + client->parser->data = client; + client->event.client = client; + + client->state = HTTP_STATE_INIT; + return client; +error: + esp_http_client_cleanup(client); + return NULL; +} + +esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client) +{ + if (client == NULL) { + return ESP_FAIL; + } + esp_http_client_close(client); + esp_transport_list_destroy(client->transport_list); + if (client->request) { + http_header_destroy(client->request->headers); + if (client->request->buffer) { + free(client->request->buffer->data); + } + free(client->request->buffer); + free(client->request); + } + if (client->response) { + http_header_destroy(client->response->headers); + if (client->response->buffer) { + free(client->response->buffer->data); + } + free(client->response->buffer); + free(client->response); + } + + free(client->parser); + free(client->parser_settings); + _clear_connection_info(client); + _clear_auth_data(client); + free(client->auth_data); + free(client->current_header_key); + free(client->location); + free(client->auth_header); + free(client); + return ESP_OK; +} + +esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client) +{ + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (client->location == NULL) { + return ESP_ERR_INVALID_ARG; + } + ESP_LOGD(TAG, "Redirect to %s", client->location); + return esp_http_client_set_url(client, client->location); +} + +static esp_err_t esp_http_check_response(esp_http_client_handle_t client) +{ + if (client->redirect_counter >= client->max_redirection_count || client->disable_auto_redirect) { + ESP_LOGE(TAG, "Error, reach max_redirection_count count=%d", client->redirect_counter); + return ESP_ERR_HTTP_MAX_REDIRECT; + } + switch (client->response->status_code) { + case HttpStatus_MovedPermanently: + case HttpStatus_Found: + case HttpStatus_TemporaryRedirect: + esp_http_client_set_redirection(client); + client->redirect_counter ++; + client->process_again = 1; + break; + case HttpStatus_Unauthorized: + esp_http_client_add_auth(client); + } + return ESP_OK; +} + +esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *url) +{ + char *old_host = NULL; + struct http_parser_url purl; + int old_port; + + if (client == NULL || url == NULL) { + ESP_LOGE(TAG, "client or url must not NULL"); + return ESP_ERR_INVALID_ARG; + } + + http_parser_url_init(&purl); + + int parser_status = http_parser_parse_url(url, strlen(url), 0, &purl); + + if (parser_status != 0) { + ESP_LOGE(TAG, "Error parse url %s", url); + return ESP_ERR_INVALID_ARG; + } + if (client->connection_info.host) { + old_host = strdup(client->connection_info.host); + } + old_port = client->connection_info.port; + + if (purl.field_data[UF_HOST].len) { + http_utils_assign_string(&client->connection_info.host, url + purl.field_data[UF_HOST].off, purl.field_data[UF_HOST].len); + HTTP_MEM_CHECK(TAG, client->connection_info.host, { + free(old_host); + return ESP_ERR_NO_MEM; + }); + } + // Close the connection if host was changed + if (old_host && client->connection_info.host + && strcasecmp(old_host, (const void *)client->connection_info.host) != 0) { + ESP_LOGD(TAG, "New host assign = %s", client->connection_info.host); + if (esp_http_client_set_header(client, "Host", client->connection_info.host) != ESP_OK) { + free(old_host); + return ESP_ERR_NO_MEM; + } + esp_http_client_close(client); + } + + if (old_host) { + free(old_host); + old_host = NULL; + } + + if (purl.field_data[UF_SCHEMA].len) { + http_utils_assign_string(&client->connection_info.scheme, url + purl.field_data[UF_SCHEMA].off, purl.field_data[UF_SCHEMA].len); + HTTP_MEM_CHECK(TAG, client->connection_info.scheme, return ESP_ERR_NO_MEM); + + if (strcasecmp(client->connection_info.scheme, "http") == 0) { + client->connection_info.port = DEFAULT_HTTP_PORT; + } else if (strcasecmp(client->connection_info.scheme, "https") == 0) { + client->connection_info.port = DEFAULT_HTTPS_PORT; + } + } + + if (purl.field_data[UF_PORT].len) { + client->connection_info.port = strtol((const char*)(url + purl.field_data[UF_PORT].off), NULL, 10); + } + + if (old_port != client->connection_info.port) { + esp_http_client_close(client); + } + + if (purl.field_data[UF_USERINFO].len) { + char *user_info = NULL; + http_utils_assign_string(&user_info, url + purl.field_data[UF_USERINFO].off, purl.field_data[UF_USERINFO].len); + if (user_info) { + char *username = user_info; + char *password = strchr(user_info, ':'); + if (password) { + *password = 0; + password ++; + http_utils_assign_string(&client->connection_info.password, password, 0); + HTTP_MEM_CHECK(TAG, client->connection_info.password, return ESP_ERR_NO_MEM); + } + http_utils_assign_string(&client->connection_info.username, username, 0); + HTTP_MEM_CHECK(TAG, client->connection_info.username, return ESP_ERR_NO_MEM); + free(user_info); + } else { + return ESP_ERR_NO_MEM; + } + } + + //Reset path and query if there are no information + if (purl.field_data[UF_PATH].len) { + http_utils_assign_string(&client->connection_info.path, url + purl.field_data[UF_PATH].off, purl.field_data[UF_PATH].len); + } else { + http_utils_assign_string(&client->connection_info.path, "/", 0); + } + HTTP_MEM_CHECK(TAG, client->connection_info.path, return ESP_ERR_NO_MEM); + + if (purl.field_data[UF_QUERY].len) { + http_utils_assign_string(&client->connection_info.query, url + purl.field_data[UF_QUERY].off, purl.field_data[UF_QUERY].len); + HTTP_MEM_CHECK(TAG, client->connection_info.query, return ESP_ERR_NO_MEM); + } else if (client->connection_info.query) { + free(client->connection_info.query); + client->connection_info.query = NULL; + } + + return ESP_OK; +} + +esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method) +{ + client->connection_info.method = method; + return ESP_OK; +} + +static int esp_http_client_get_data(esp_http_client_handle_t client) +{ + if (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { + return ESP_FAIL; + } + + if (client->connection_info.method == HTTP_METHOD_HEAD) { + return 0; + } + + esp_http_buffer_t *res_buffer = client->response->buffer; + + ESP_LOGD(TAG, "data_process=%d, content_length=%d", client->response->data_process, client->response->content_length); + + int rlen = esp_transport_read(client->transport, res_buffer->data, client->buffer_size_rx, client->timeout_ms); + if (rlen >= 0) { + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); + } + return rlen; +} + +bool esp_http_client_is_complete_data_received(esp_http_client_handle_t client) +{ + if (client->response->is_chunked) { + if (!client->is_chunk_complete) { + ESP_LOGD(TAG, "Chunks were not completely read"); + return false; + } + } else { + if (client->response->data_process != client->response->content_length) { + ESP_LOGD(TAG, "Data processed %d != Data specified in content length %d", client->response->data_process, client->response->content_length); + return false; + } + } + return true; +} + +int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) +{ + esp_http_buffer_t *res_buffer = client->response->buffer; + + int rlen = ESP_FAIL, ridx = 0; + if (res_buffer->raw_len) { + int remain_len = client->response->buffer->raw_len; + if (remain_len > len) { + remain_len = len; + } + memcpy(buffer, res_buffer->raw_data, remain_len); + res_buffer->raw_len -= remain_len; + res_buffer->raw_data += remain_len; + ridx = remain_len; + } + int need_read = len - ridx; + bool is_data_remain = true; + while (need_read > 0 && is_data_remain) { + if (client->response->is_chunked) { + is_data_remain = !client->is_chunk_complete; + } else { + is_data_remain = client->response->data_process < client->response->content_length; + } + ESP_LOGD(TAG, "is_data_remain=%d, is_chunked=%d, content_length=%d", is_data_remain, client->response->is_chunked, client->response->content_length); + if (!is_data_remain) { + break; + } + int byte_to_read = need_read; + if (byte_to_read > client->buffer_size_rx) { + byte_to_read = client->buffer_size_rx; + } + errno = 0; + rlen = esp_transport_read(client->transport, res_buffer->data, byte_to_read, client->timeout_ms); + ESP_LOGD(TAG, "need_read=%d, byte_to_read=%d, rlen=%d, ridx=%d", need_read, byte_to_read, rlen, ridx); + + if (rlen <= 0) { + if (errno != 0) { + esp_log_level_t sev = ESP_LOG_WARN; + /* On connection close from server, recv should ideally return 0 but we have error conversion + * in `tcp_transport` SSL layer which translates it `-1` and hence below additional checks */ + if (rlen == -1 && errno == ENOTCONN && client->response->is_chunked) { + /* Explicit call to parser for invoking `message_complete` callback */ + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, 0); + /* ...and lowering the message severity, as closed connection from server side is expected in chunked transport */ + sev = ESP_LOG_DEBUG; + } + ESP_LOG_LEVEL(sev, TAG, "esp_transport_read returned:%d and errno:%d ", rlen, errno); + } + if (rlen < 0 && ridx == 0) { + return ESP_FAIL; + } else { + return ridx; + } + } + res_buffer->output_ptr = buffer + ridx; + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); + ridx += res_buffer->raw_len; + need_read -= res_buffer->raw_len; + + res_buffer->raw_len = 0; //clear + res_buffer->output_ptr = NULL; + } + + return ridx; +} + +esp_err_t esp_http_client_perform(esp_http_client_handle_t client) +{ + esp_err_t err; + do { + if (client->process_again) { + esp_http_client_prepare(client); + } + switch (client->state) { + /* In case of blocking esp_http_client_perform(), the following states will fall through one after the after; + in case of non-blocking esp_http_client_perform(), if there is an error condition, like EINPROGRESS or EAGAIN, + then the esp_http_client_perform() API will return ESP_ERR_HTTP_EAGAIN error. The user may call + esp_http_client_perform API again, and for this reason, we maintain the states */ + case HTTP_STATE_INIT: + if ((err = esp_http_client_connect(client)) != ESP_OK) { + if (client->is_async && err == ESP_ERR_HTTP_CONNECTING) { + return ESP_ERR_HTTP_EAGAIN; + } + return err; + } + /* falls through */ + case HTTP_STATE_CONNECTED: + if ((err = esp_http_client_request_send(client, client->post_len)) != ESP_OK) { + if (client->is_async && errno == EAGAIN) { + return ESP_ERR_HTTP_EAGAIN; + } + return err; + } + /* falls through */ + case HTTP_STATE_REQ_COMPLETE_HEADER: + if ((err = esp_http_client_send_post_data(client)) != ESP_OK) { + if (client->is_async && errno == EAGAIN) { + return ESP_ERR_HTTP_EAGAIN; + } + return err; + } + /* falls through */ + case HTTP_STATE_REQ_COMPLETE_DATA: + if (esp_http_client_fetch_headers(client) < 0) { + if (client->is_async && errno == EAGAIN) { + return ESP_ERR_HTTP_EAGAIN; + } + return ESP_ERR_HTTP_FETCH_HEADER; + } + /* falls through */ + case HTTP_STATE_RES_COMPLETE_HEADER: + if ((err = esp_http_check_response(client)) != ESP_OK) { + ESP_LOGE(TAG, "Error response"); + return err; + } + while (client->response->is_chunked && !client->is_chunk_complete) { + if (esp_http_client_get_data(client) <= 0) { + if (client->is_async && errno == EAGAIN) { + return ESP_ERR_HTTP_EAGAIN; + } + ESP_LOGD(TAG, "Read finish or server requests close"); + break; + } + } + while (client->response->data_process < client->response->content_length) { + if (esp_http_client_get_data(client) <= 0) { + if (client->is_async && errno == EAGAIN) { + return ESP_ERR_HTTP_EAGAIN; + } + ESP_LOGD(TAG, "Read finish or server requests close"); + break; + } + } + http_dispatch_event(client, HTTP_EVENT_ON_FINISH, NULL, 0); + + if (!http_should_keep_alive(client->parser)) { + ESP_LOGD(TAG, "Close connection"); + esp_http_client_close(client); + } else { + if (client->state > HTTP_STATE_CONNECTED) { + client->state = HTTP_STATE_CONNECTED; + client->first_line_prepared = false; + } + } + break; + default: + break; + } + } while (client->process_again); + return ESP_OK; +} + +int esp_http_client_fetch_headers(esp_http_client_handle_t client) +{ + if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { + return ESP_FAIL; + } + + client->state = HTTP_STATE_REQ_COMPLETE_DATA; + esp_http_buffer_t *buffer = client->response->buffer; + client->response->status_code = -1; + + while (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { + buffer->len = esp_transport_read(client->transport, buffer->data, client->buffer_size_rx, client->timeout_ms); + if (buffer->len <= 0) { + return ESP_FAIL; + } + http_parser_execute(client->parser, client->parser_settings, buffer->data, buffer->len); + } + ESP_LOGD(TAG, "content_length = %d", client->response->content_length); + if (client->response->content_length <= 0) { + client->response->is_chunked = true; + return 0; + } + return client->response->content_length; +} + +static esp_err_t esp_http_client_connect(esp_http_client_handle_t client) +{ + esp_err_t err; + + if (client->state == HTTP_STATE_UNINIT) { + ESP_LOGE(TAG, "Client has not been initialized"); + return ESP_ERR_INVALID_STATE; + } + + if ((err = esp_http_client_prepare(client)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize request data"); + esp_http_client_close(client); + return err; + } + + if (client->state < HTTP_STATE_CONNECTED) { + ESP_LOGD(TAG, "Begin connect to: %s://%s:%d", client->connection_info.scheme, client->connection_info.host, client->connection_info.port); + client->transport = esp_transport_list_get_transport(client->transport_list, client->connection_info.scheme); + if (client->transport == NULL) { + ESP_LOGE(TAG, "No transport found"); +#ifndef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS + if (strcasecmp(client->connection_info.scheme, "https") == 0) { + ESP_LOGE(TAG, "Please enable HTTPS at menuconfig to allow requesting via https"); + } +#endif + return ESP_ERR_HTTP_INVALID_TRANSPORT; + } + if (!client->is_async) { + if (esp_transport_connect(client->transport, client->connection_info.host, client->connection_info.port, client->timeout_ms) < 0) { + ESP_LOGE(TAG, "Connection failed, sock < 0"); + return ESP_ERR_HTTP_CONNECT; + } + } else { + int ret = esp_transport_connect_async(client->transport, client->connection_info.host, client->connection_info.port, client->timeout_ms); + if (ret == ASYNC_TRANS_CONNECT_FAIL) { + ESP_LOGE(TAG, "Connection failed"); + if (strcasecmp(client->connection_info.scheme, "http") == 0) { + ESP_LOGE(TAG, "Asynchronous mode doesn't work for HTTP based connection"); + return ESP_ERR_INVALID_ARG; + } + return ESP_ERR_HTTP_CONNECT; + } else if (ret == ASYNC_TRANS_CONNECTING) { + ESP_LOGD(TAG, "Connection not yet established"); + return ESP_ERR_HTTP_CONNECTING; + } + } + client->state = HTTP_STATE_CONNECTED; + http_dispatch_event(client, HTTP_EVENT_ON_CONNECTED, NULL, 0); + } + return ESP_OK; +} + +static int http_client_prepare_first_line(esp_http_client_handle_t client, int write_len) +{ + if (write_len >= 0) { + http_header_set_format(client->request->headers, "Content-Length", "%d", write_len); + } else { + esp_http_client_set_header(client, "Transfer-Encoding", "chunked"); + esp_http_client_set_method(client, HTTP_METHOD_POST); + } + + const char *method = HTTP_METHOD_MAPPING[client->connection_info.method]; + + int first_line_len = snprintf(client->request->buffer->data, + client->buffer_size_tx, "%s %s", + method, + client->connection_info.path); + if (first_line_len >= client->buffer_size_tx) { + ESP_LOGE(TAG, "Out of buffer"); + return -1; + } + + if (client->connection_info.query) { + first_line_len += snprintf(client->request->buffer->data + first_line_len, + client->buffer_size_tx - first_line_len, "?%s", client->connection_info.query); + if (first_line_len >= client->buffer_size_tx) { + ESP_LOGE(TAG, "Out of buffer"); + return -1; + + } + } + first_line_len += snprintf(client->request->buffer->data + first_line_len, + client->buffer_size_tx - first_line_len, " %s\r\n", DEFAULT_HTTP_PROTOCOL); + if (first_line_len >= client->buffer_size_tx) { + ESP_LOGE(TAG, "Out of buffer"); + return -1; + } + return first_line_len; +} + +static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len) +{ + int first_line_len = 0; + if (!client->first_line_prepared) { + if ((first_line_len = http_client_prepare_first_line(client, write_len)) < 0) { + return first_line_len; + } + client->first_line_prepared = true; + client->header_index = 0; + client->data_written_index = 0; + client->data_write_left = 0; + } + + if (client->data_write_left > 0) { + /* sending leftover data from previous call to esp_http_client_request_send() API */ + int wret = 0; + if (((wret = esp_http_client_write(client, client->request->buffer->data + client->data_written_index, client->data_write_left)) < 0)) { + ESP_LOGE(TAG, "Error write request"); + return ESP_ERR_HTTP_WRITE_DATA; + } + client->data_write_left -= wret; + client->data_written_index += wret; + if (client->is_async && client->data_write_left > 0) { + return ESP_ERR_HTTP_WRITE_DATA; /* In case of EAGAIN error, we return ESP_ERR_HTTP_WRITE_DATA, + and the handling of EAGAIN should be done in the higher level APIs. */ + } + } + + int wlen = client->buffer_size_tx - first_line_len; + while ((client->header_index = http_header_generate_string(client->request->headers, client->header_index, client->request->buffer->data + first_line_len, &wlen))) { + if (wlen <= 0) { + break; + } + if (first_line_len) { + wlen += first_line_len; + first_line_len = 0; + } + client->request->buffer->data[wlen] = 0; + ESP_LOGD(TAG, "Write header[%d]: %s", client->header_index, client->request->buffer->data); + + client->data_write_left = wlen; + client->data_written_index = 0; + while (client->data_write_left > 0) { + int wret = esp_transport_write(client->transport, client->request->buffer->data + client->data_written_index, client->data_write_left, client->timeout_ms); + if (wret <= 0) { + ESP_LOGE(TAG, "Error write request"); + esp_http_client_close(client); + return ESP_ERR_HTTP_WRITE_DATA; + } + client->data_write_left -= wret; + client->data_written_index += wret; + } + wlen = client->buffer_size_tx; + } + + client->data_written_index = 0; + client->data_write_left = client->post_len; + http_dispatch_event(client, HTTP_EVENT_HEADERS_SENT, NULL, 0); + client->state = HTTP_STATE_REQ_COMPLETE_HEADER; + return ESP_OK; +} + +static esp_err_t esp_http_client_send_post_data(esp_http_client_handle_t client) +{ + if (client->state != HTTP_STATE_REQ_COMPLETE_HEADER) { + ESP_LOGE(TAG, "Invalid state"); + return ESP_ERR_INVALID_STATE; + } + if (!(client->post_data && client->post_len)) { + goto success; + } + + int wret = esp_http_client_write(client, client->post_data + client->data_written_index, client->data_write_left); + if (wret < 0) { + return wret; + } + client->data_write_left -= wret; + client->data_written_index += wret; + + if (client->data_write_left <= 0) { + goto success; + } else { + return ESP_ERR_HTTP_WRITE_DATA; + } + +success: + client->state = HTTP_STATE_REQ_COMPLETE_DATA; + return ESP_OK; +} + +esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len) +{ + client->post_len = write_len; + esp_err_t err; + if ((err = esp_http_client_connect(client)) != ESP_OK) { + return err; + } + if ((err = esp_http_client_request_send(client, write_len)) != ESP_OK) { + return err; + } + return ESP_OK; +} + +int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len) +{ + if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { + return ESP_FAIL; + } + + int wlen = 0, widx = 0; + while (len > 0) { + wlen = esp_transport_write(client->transport, buffer + widx, len, client->timeout_ms); + /* client->async_block is initialised in case of non-blocking IO, and in this case we return how + much ever data was written by the esp_transport_write() API. */ + if (client->is_async || wlen <= 0) { + return wlen; + } + widx += wlen; + len -= wlen; + } + return widx; +} + +esp_err_t esp_http_client_close(esp_http_client_handle_t client) +{ + if (client->state >= HTTP_STATE_INIT) { + http_dispatch_event(client, HTTP_EVENT_DISCONNECTED, esp_transport_get_error_handle(client->transport), 0); + client->state = HTTP_STATE_INIT; + return esp_transport_close(client->transport); + } + return ESP_OK; +} + +esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len) +{ + esp_err_t err = ESP_OK; + client->post_data = (char *)data; + client->post_len = len; + ESP_LOGD(TAG, "set post file length = %d", len); + if (client->post_data) { + char *value = NULL; + if ((err = esp_http_client_get_header(client, "Content-Type", &value)) != ESP_OK) { + return err; + } + if (value == NULL) { + err = esp_http_client_set_header(client, "Content-Type", "application/x-www-form-urlencoded"); + } + } else { + client->post_len = 0; + err = esp_http_client_set_header(client, "Content-Type", NULL); + } + return err; +} + +int esp_http_client_get_post_field(esp_http_client_handle_t client, char **data) +{ + if (client->post_data) { + *data = client->post_data; + return client->post_len; + } + return 0; +} + +int esp_http_client_get_status_code(esp_http_client_handle_t client) +{ + return client->response->status_code; +} + +int esp_http_client_get_content_length(esp_http_client_handle_t client) +{ + return client->response->content_length; +} + +bool esp_http_client_is_chunked_response(esp_http_client_handle_t client) +{ + return client->response->is_chunked; +} + +esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_handle_t client) +{ + if (!strcasecmp(client->connection_info.scheme, "https") ) { + return HTTP_TRANSPORT_OVER_SSL; + } else if (!strcasecmp(client->connection_info.scheme, "http")) { + return HTTP_TRANSPORT_OVER_TCP; + } else { + return HTTP_TRANSPORT_UNKNOWN; + } +} + +void esp_http_client_add_auth(esp_http_client_handle_t client) +{ + if (client == NULL) { + return; + } + if (client->state != HTTP_STATE_RES_COMPLETE_HEADER) { + return; + } + + char *auth_header = client->auth_header; + if (auth_header) { + http_utils_trim_whitespace(&auth_header); + ESP_LOGD(TAG, "UNAUTHORIZED: %s", auth_header); + client->redirect_counter++; + if (http_utils_str_starts_with(auth_header, "Digest") == 0) { + ESP_LOGD(TAG, "type = Digest"); + client->connection_info.auth_type = HTTP_AUTH_TYPE_DIGEST; +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH + } else if (http_utils_str_starts_with(auth_header, "Basic") == 0) { + ESP_LOGD(TAG, "type = Basic"); + client->connection_info.auth_type = HTTP_AUTH_TYPE_BASIC; +#endif + } else { + client->connection_info.auth_type = HTTP_AUTH_TYPE_NONE; + ESP_LOGE(TAG, "This authentication method is not supported: %s", auth_header); + return; + } + + _clear_auth_data(client); + + client->auth_data->method = strdup(HTTP_METHOD_MAPPING[client->connection_info.method]); + + client->auth_data->nc = 1; + client->auth_data->realm = http_utils_get_string_between(auth_header, "realm=\"", "\""); + client->auth_data->algorithm = http_utils_get_string_between(auth_header, "algorithm=", ","); + client->auth_data->qop = http_utils_get_string_between(auth_header, "qop=\"", "\""); + client->auth_data->nonce = http_utils_get_string_between(auth_header, "nonce=\"", "\""); + client->auth_data->opaque = http_utils_get_string_between(auth_header, "opaque=\"", "\""); + client->process_again = 1; + } else { + client->connection_info.auth_type = HTTP_AUTH_TYPE_NONE; + ESP_LOGW(TAG, "This request requires authentication, but does not provide header information for that"); + } +} + +int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer, int len) +{ + int read_len = 0; + while (read_len < len) { + int data_read = esp_http_client_read(client, buffer + read_len, len - read_len); + if (data_read <= 0) { + return read_len; + } + read_len += data_read; + } + return read_len; +} + +esp_err_t esp_http_client_get_url(esp_http_client_handle_t client, char *url, const int len) +{ + if (client == NULL || url == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (client->connection_info.host && client->connection_info.scheme && client->connection_info.path) { + snprintf(url, len, "%s://%s%s", client->connection_info.scheme, client->connection_info.host, client->connection_info.path); + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to get URL"); + } + return ESP_FAIL; +} diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h new file mode 100644 index 000000000..b22783ae0 --- /dev/null +++ b/components/esp_http_client/include/esp_http_client.h @@ -0,0 +1,533 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_HTTP_CLIENT_H +#define _ESP_HTTP_CLIENT_H + +#include "freertos/FreeRTOS.h" +#include "http_parser.h" +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFAULT_HTTP_BUF_SIZE CONFIG_HTTP_BUF_SIZE + +typedef struct esp_http_client *esp_http_client_handle_t; +typedef struct esp_http_client_event *esp_http_client_event_handle_t; + +/** + * @brief HTTP Client events id + */ +typedef enum { + HTTP_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */ + HTTP_EVENT_ON_CONNECTED, /*!< Once the HTTP has been connected to the server, no data exchange has been performed */ + HTTP_EVENT_HEADERS_SENT, /*!< After sending all the headers to the server */ + HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatability + and will be deprecated in future versions esp-idf */ + HTTP_EVENT_ON_HEADER, /*!< Occurs when receiving each header sent from the server */ + HTTP_EVENT_ON_DATA, /*!< Occurs when receiving data from the server, possibly multiple portions of the packet */ + HTTP_EVENT_ON_FINISH, /*!< Occurs when finish a HTTP session */ + HTTP_EVENT_DISCONNECTED, /*!< The connection has been disconnected */ +} esp_http_client_event_id_t; + +/** + * @brief HTTP Client events data + */ +typedef struct esp_http_client_event { + esp_http_client_event_id_t event_id; /*!< event_id, to know the cause of the event */ + esp_http_client_handle_t client; /*!< esp_http_client_handle_t context */ + void *data; /*!< data of the event */ + int data_len; /*!< data length of data */ + void *user_data; /*!< user_data context, from esp_http_client_config_t user_data */ + char *header_key; /*!< For HTTP_EVENT_ON_HEADER event_id, it's store current http header key */ + char *header_value; /*!< For HTTP_EVENT_ON_HEADER event_id, it's store current http header value */ +} esp_http_client_event_t; + + +/** + * @brief HTTP Client transport + */ +typedef enum { + HTTP_TRANSPORT_UNKNOWN = 0x0, /*!< Unknown */ + HTTP_TRANSPORT_OVER_TCP, /*!< Transport over tcp */ + HTTP_TRANSPORT_OVER_SSL, /*!< Transport over ssl */ +} esp_http_client_transport_t; + +typedef esp_err_t (*http_event_handle_cb)(esp_http_client_event_t *evt); + +/** + * @brief HTTP method + */ +typedef enum { + HTTP_METHOD_GET = 0, /*!< HTTP GET Method */ + HTTP_METHOD_POST, /*!< HTTP POST Method */ + HTTP_METHOD_PUT, /*!< HTTP PUT Method */ + HTTP_METHOD_PATCH, /*!< HTTP PATCH Method */ + HTTP_METHOD_DELETE, /*!< HTTP DELETE Method */ + HTTP_METHOD_HEAD, /*!< HTTP HEAD Method */ + HTTP_METHOD_NOTIFY, /*!< HTTP NOTIFY Method */ + HTTP_METHOD_SUBSCRIBE, /*!< HTTP SUBSCRIBE Method */ + HTTP_METHOD_UNSUBSCRIBE,/*!< HTTP UNSUBSCRIBE Method */ + HTTP_METHOD_OPTIONS, /*!< HTTP OPTIONS Method */ + HTTP_METHOD_MAX, +} esp_http_client_method_t; + +/** + * @brief HTTP Authentication type + */ +typedef enum { + HTTP_AUTH_TYPE_NONE = 0, /*!< No authention */ + HTTP_AUTH_TYPE_BASIC, /*!< HTTP Basic authentication */ + HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Disgest authentication */ +} esp_http_client_auth_type_t; + +/** + * @brief HTTP configuration + */ +typedef struct { + const char *url; /*!< HTTP URL, the information on the URL is most important, it overrides the other fields below, if any */ + const char *host; /*!< Domain or IP as string */ + int port; /*!< Port to connect, default depend on esp_http_client_transport_t (80 or 443) */ + const char *username; /*!< Using for Http authentication */ + const char *password; /*!< Using for Http authentication */ + esp_http_client_auth_type_t auth_type; /*!< Http authentication type, see `esp_http_client_auth_type_t` */ + const char *path; /*!< HTTP Path, if not set, default is `/` */ + const char *query; /*!< HTTP query */ + const char *cert_pem; /*!< SSL server certification, PEM format as string, if the client requires to verify server */ + const char *client_cert_pem; /*!< SSL client certification, PEM format as string, if the server requires to verify client */ + const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */ + esp_http_client_method_t method; /*!< HTTP Method */ + int timeout_ms; /*!< Network timeout in milliseconds */ + bool disable_auto_redirect; /*!< Disable HTTP automatic redirects */ + int max_redirection_count; /*!< Max redirection number, using default value if zero*/ + http_event_handle_cb event_handler; /*!< HTTP Event Handle */ + esp_http_client_transport_t transport_type; /*!< HTTP transport type, see `esp_http_client_transport_t` */ + int buffer_size; /*!< HTTP receive buffer size */ + int buffer_size_tx; /*!< HTTP transmit buffer size */ + void *user_data; /*!< HTTP user_data context */ + bool is_async; /*!< Set asynchronous mode, only supported with HTTPS for now */ + bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */ + bool skip_cert_common_name_check; /*!< Skip any validation of server certificate CN field */ +} esp_http_client_config_t; + +/** + * Enum for the HTTP status codes. + */ +typedef enum { + /* 3xx - Redirection */ + HttpStatus_MovedPermanently = 301, + HttpStatus_Found = 302, + HttpStatus_TemporaryRedirect = 307, + + /* 4xx - Client Error */ + HttpStatus_Unauthorized = 401 +} HttpStatus_Code; + +#define ESP_ERR_HTTP_BASE (0x7000) /*!< Starting number of HTTP error codes */ +#define ESP_ERR_HTTP_MAX_REDIRECT (ESP_ERR_HTTP_BASE + 1) /*!< The error exceeds the number of HTTP redirects */ +#define ESP_ERR_HTTP_CONNECT (ESP_ERR_HTTP_BASE + 2) /*!< Error open the HTTP connection */ +#define ESP_ERR_HTTP_WRITE_DATA (ESP_ERR_HTTP_BASE + 3) /*!< Error write HTTP data */ +#define ESP_ERR_HTTP_FETCH_HEADER (ESP_ERR_HTTP_BASE + 4) /*!< Error read HTTP header from server */ +#define ESP_ERR_HTTP_INVALID_TRANSPORT (ESP_ERR_HTTP_BASE + 5) /*!< There are no transport support for the input scheme */ +#define ESP_ERR_HTTP_CONNECTING (ESP_ERR_HTTP_BASE + 6) /*!< HTTP connection hasn't been established yet */ +#define ESP_ERR_HTTP_EAGAIN (ESP_ERR_HTTP_BASE + 7) /*!< Mapping of errno EAGAIN to esp_err_t */ + +/** + * @brief Start a HTTP session + * This function must be the first function to call, + * and it returns a esp_http_client_handle_t that you must use as input to other functions in the interface. + * This call MUST have a corresponding call to esp_http_client_cleanup when the operation is complete. + * + * @param[in] config The configurations, see `http_client_config_t` + * + * @return + * - `esp_http_client_handle_t` + * - NULL if any errors + */ +esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config); + +/** + * @brief Invoke this function after `esp_http_client_init` and all the options calls are made, and will perform the + * transfer as described in the options. It must be called with the same esp_http_client_handle_t as input as the esp_http_client_init call returned. + * esp_http_client_perform performs the entire request in either blocking or non-blocking manner. By default, the API performs request in a blocking manner and returns when done, + * or if it failed, and in non-blocking manner, it returns if EAGAIN/EWOULDBLOCK or EINPROGRESS is encountered, or if it failed. And in case of non-blocking request, + * the user may call this API multiple times unless request & response is complete or there is a failure. To enable non-blocking esp_http_client_perform(), `is_async` member of esp_http_client_config_t + * must be set while making a call to esp_http_client_init() API. + * You can do any amount of calls to esp_http_client_perform while using the same esp_http_client_handle_t. The underlying connection may be kept open if the server allows it. + * If you intend to transfer more than one file, you are even encouraged to do so. + * esp_http_client will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. + * Just note that you will have to use `esp_http_client_set_**` between the invokes to set options for the following esp_http_client_perform. + * + * @note You must never call this function simultaneously from two places using the same client handle. + * Let the function return first before invoking it another time. + * If you want parallel transfers, you must use several esp_http_client_handle_t. + * This function include `esp_http_client_open` -> `esp_http_client_write` -> `esp_http_client_fetch_headers` -> `esp_http_client_read` (and option) `esp_http_client_close`. + * + * @param client The esp_http_client handle + * + * @return + * - ESP_OK on successful + * - ESP_FAIL on error + */ +esp_err_t esp_http_client_perform(esp_http_client_handle_t client); + +/** + * @brief Set URL for client, when performing this behavior, the options in the URL will replace the old ones + * + * @param[in] client The esp_http_client handle + * @param[in] url The url + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *url); + +/** + * @brief Set post data, this function must be called before `esp_http_client_perform`. + * Note: The data parameter passed to this function is a pointer and this function will not copy the data + * + * @param[in] client The esp_http_client handle + * @param[in] data post data pointer + * @param[in] len post length + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len); + +/** + * @brief Get current post field information + * + * @param[in] client The client + * @param[out] data Point to post data pointer + * + * @return Size of post data + */ +int esp_http_client_get_post_field(esp_http_client_handle_t client, char **data); + +/** + * @brief Set http request header, this function must be called after esp_http_client_init and before any + * perform function + * + * @param[in] client The esp_http_client handle + * @param[in] key The header key + * @param[in] value The header value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char *key, const char *value); + +/** + * @brief Get http request header. + * The value parameter will be set to NULL if there is no header which is same as + * the key specified, otherwise the address of header value will be assigned to value parameter. + * This function must be called after `esp_http_client_init`. + * + * @param[in] client The esp_http_client handle + * @param[in] key The header key + * @param[out] value The header value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_get_header(esp_http_client_handle_t client, const char *key, char **value); + +/** + * @brief Get http request username. + * The address of username buffer will be assigned to value parameter. + * This function must be called after `esp_http_client_init`. + * + * @param[in] client The esp_http_client handle + * @param[out] value The username value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_get_username(esp_http_client_handle_t client, char **value); + +/** + * @brief Set http request username. + * The value of username parameter will be assigned to username buffer. + * If the username parameter is NULL then username buffer will be freed. + * + * @param[in] client The esp_http_client handle + * @param[in] username The username value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_set_username(esp_http_client_handle_t client, const char *username); + +/** + * @brief Get http request password. + * The address of password buffer will be assigned to value parameter. + * This function must be called after `esp_http_client_init`. + * + * @param[in] client The esp_http_client handle + * @param[out] value The password value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_get_password(esp_http_client_handle_t client, char **value); + +/** + * @brief Set http request password. + * The value of password parameter will be assigned to password buffer. + * If the password parameter is NULL then password buffer will be freed. + * + * @param[in] client The esp_http_client handle + * @param[in] password The password value + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_set_password(esp_http_client_handle_t client, char *password); + +/** + * @brief Set http request auth_type. + * + * @param[in] client The esp_http_client handle + * @param[in] auth_type The esp_http_client auth type + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_set_authtype(esp_http_client_handle_t client, esp_http_client_auth_type_t auth_type); + +/** + * @brief Set http request method + * + * @param[in] client The esp_http_client handle + * @param[in] method The method + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method); + +/** + * @brief Delete http request header + * + * @param[in] client The esp_http_client handle + * @param[in] key The key + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const char *key); + +/** + * @brief This function will be open the connection, write all header strings and return + * + * @param[in] client The esp_http_client handle + * @param[in] write_len HTTP Content length need to write to the server + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len); + +/** + * @brief This function will write data to the HTTP connection previously opened by esp_http_client_open() + * + * @param[in] client The esp_http_client handle + * @param buffer The buffer + * @param[in] len This value must not be larger than the write_len parameter provided to esp_http_client_open() + * + * @return + * - (-1) if any errors + * - Length of data written + */ +int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len); + +/** + * @brief This function need to call after esp_http_client_open, it will read from http stream, process all receive headers + * + * @param[in] client The esp_http_client handle + * + * @return + * - (0) if stream doesn't contain content-length header, or chunked encoding (checked by `esp_http_client_is_chunked` response) + * - (-1: ESP_FAIL) if any errors + * - Download data length defined by content-length header + */ +int esp_http_client_fetch_headers(esp_http_client_handle_t client); + + +/** + * @brief Check response data is chunked + * + * @param[in] client The esp_http_client handle + * + * @return true or false + */ +bool esp_http_client_is_chunked_response(esp_http_client_handle_t client); + +/** + * @brief Read data from http stream + * + * @param[in] client The esp_http_client handle + * @param buffer The buffer + * @param[in] len The length + * + * @return + * - (-1) if any errors + * - Length of data was read + */ +int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len); + + +/** + * @brief Get http response status code, the valid value if this function invoke after `esp_http_client_perform` + * + * @param[in] client The esp_http_client handle + * + * @return Status code + */ +int esp_http_client_get_status_code(esp_http_client_handle_t client); + +/** + * @brief Get http response content length (from header Content-Length) + * the valid value if this function invoke after `esp_http_client_perform` + * + * @param[in] client The esp_http_client handle + * + * @return + * - (-1) Chunked transfer + * - Content-Length value as bytes + */ +int esp_http_client_get_content_length(esp_http_client_handle_t client); + +/** + * @brief Close http connection, still kept all http request resources + * + * @param[in] client The esp_http_client handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_close(esp_http_client_handle_t client); + +/** + * @brief This function must be the last function to call for an session. + * It is the opposite of the esp_http_client_init function and must be called with the same handle as input that a esp_http_client_init call returned. + * This might close all connections this handle has used and possibly has kept open until now. + * Don't call this function if you intend to transfer more files, re-using handles is a key to good performance with esp_http_client. + * + * @param[in] client The esp_http_client handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client); + +/** + * @brief Get transport type + * + * @param[in] client The esp_http_client handle + * + * @return + * - HTTP_TRANSPORT_UNKNOWN + * - HTTP_TRANSPORT_OVER_TCP + * - HTTP_TRANSPORT_OVER_SSL + */ +esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_handle_t client); + +/** + * @brief Set redirection URL. + * When received the 30x code from the server, the client stores the redirect URL provided by the server. + * This function will set the current URL to redirect to enable client to execute the redirection request. + * + * @param[in] client The esp_http_client handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client); + +/** + * @brief On receiving HTTP Status code 401, this API can be invoked to add authorization + * information. + * + * @note There is a possibility of receiving body message with redirection status codes, thus make sure + * to flush off body data after calling this API. + * + * @param[in] client The esp_http_client handle + */ +void esp_http_client_add_auth(esp_http_client_handle_t client); + +/** + * @brief Checks if entire data in the response has been read without any error. + * + * @param[in] client The esp_http_client handle + * + * @return + * - true + * - false + */ +bool esp_http_client_is_complete_data_received(esp_http_client_handle_t client); + +/** + * @brief Helper API to read larger data chunks + * This is a helper API which internally calls `esp_http_client_read` multiple times till the end of data is reached or till the buffer gets full. + * + * @param[in] client The esp_http_client handle + * @param buffer The buffer + * @param[in] len The buffer length + * + * @return + * - Length of data was read + */ + +int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer, int len); + +/** + * @brief Get URL from client + * + * @param[in] client The esp_http_client handle + * @param[inout] url The buffer to store URL + * @param[in] len The buffer length + * + * @return + * - ESP_OK + * - ESP_FAIL + */ + +esp_err_t esp_http_client_get_url(esp_http_client_handle_t client, char *url, const int len); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/components/esp_http_client/lib/http_auth.c b/components/esp_http_client/lib/http_auth.c new file mode 100644 index 000000000..8827870d9 --- /dev/null +++ b/components/esp_http_client/lib/http_auth.c @@ -0,0 +1,155 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_netif.h" +#include "lwip/sockets.h" +#include "rom/md5_hash.h" +#include "mbedtls/base64.h" + +#include "esp_system.h" +#include "esp_log.h" + +#include "http_utils.h" +#include "http_auth.h" + +#define MD5_MAX_LEN (33) +#define HTTP_AUTH_BUF_LEN (1024) + +static const char *TAG = "HTTP_AUTH"; + +/** + * @brief This function hash a formatted string with MD5 and format the result as ascii characters + * + * @param md The buffer will hold the ascii result + * @param[in] fmt The format + * + * @return Length of the result + */ +static int md5_printf(char *md, const char *fmt, ...) +{ + unsigned char *buf; + unsigned char digest[MD5_MAX_LEN]; + int len, i; + struct MD5Context md5_ctx; + va_list ap; + va_start(ap, fmt); + len = vasprintf((char **)&buf, fmt, ap); + if (buf == NULL) { + return ESP_FAIL; + } + + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, buf, len); + MD5Final(digest, &md5_ctx); + + for (i = 0; i < 16; ++i) { + sprintf(&md[i * 2], "%02x", (unsigned int)digest[i]); + } + va_end(ap); + + free(buf); + return MD5_MAX_LEN; +} + +char *http_auth_digest(const char *username, const char *password, esp_http_auth_data_t *auth_data) +{ + char *ha1, *ha2 = NULL; + char *digest = NULL; + char *auth_str = NULL; + + if (username == NULL || + password == NULL || + auth_data->nonce == NULL || + auth_data->uri == NULL || + auth_data->realm == NULL) { + return NULL; + } + + if (auth_data->algorithm == NULL) { + auth_data->algorithm = "md5"; + } + + ha1 = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, ha1, goto _digest_exit); + + ha2 = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, ha2, goto _digest_exit); + + digest = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, digest, goto _digest_exit); + + if (md5_printf(ha1, "%s:%s:%s", username, auth_data->realm, password) <= 0) { + goto _digest_exit; + } + + ESP_LOGD(TAG, "%s %s %s %s\r\n", "Digest", username, auth_data->realm, password); + if (strcasecmp(auth_data->algorithm, "md5-sess") == 0) { + if (md5_printf(ha1, "%s:%s:%016llx", ha1, auth_data->nonce, auth_data->cnonce) <= 0) { + goto _digest_exit; + } + } + if (md5_printf(ha2, "%s:%s", auth_data->method, auth_data->uri) <= 0) { + goto _digest_exit; + } + + //support qop = auth + if (auth_data->qop && strcasecmp(auth_data->qop, "auth-int") == 0) { + if (md5_printf(ha2, "%s:%s", ha2, "entity") <= 0) { + goto _digest_exit; + } + } + + if (auth_data->qop) { + // response=MD5(HA1:nonce:nonceCount:cnonce:qop:HA2) + if (md5_printf(digest, "%s:%s:%08x:%016llx:%s:%s", ha1, auth_data->nonce, auth_data->nc, auth_data->cnonce, auth_data->qop, ha2) <= 0) { + goto _digest_exit; + } + } else { + // response=MD5(HA1:nonce:HA2) + if (md5_printf(digest, "%s:%s:%s", ha1, auth_data->nonce, ha2) <= 0) { + goto _digest_exit; + } + } + asprintf(&auth_str, "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", algorithm=\"MD5\", " + "response=\"%s\", opaque=\"%s\", qop=%s, nc=%08x, cnonce=\"%016llx\"", + username, auth_data->realm, auth_data->nonce, auth_data->uri, digest, auth_data->opaque, auth_data->qop, auth_data->nc, auth_data->cnonce); +_digest_exit: + free(ha1); + free(ha2); + free(digest); + return auth_str; +} + +char *http_auth_basic(const char *username, const char *password) +{ + int out; + char *user_info = NULL; + char *digest = NULL; + size_t n = 0; + asprintf(&user_info, "%s:%s", username, password); + HTTP_MEM_CHECK(TAG, user_info, return NULL); + mbedtls_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info)); + digest = calloc(1, 6 + n + 1); + HTTP_MEM_CHECK(TAG, digest, goto _basic_exit); + strcpy(digest, "Basic "); + mbedtls_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info)); +_basic_exit: + free(user_info); + return digest; +} diff --git a/components/esp_http_client/lib/http_header.c b/components/esp_http_client/lib/http_header.c new file mode 100644 index 000000000..b3dda8eea --- /dev/null +++ b/components/esp_http_client/lib/http_header.c @@ -0,0 +1,247 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "http_header.h" +#include "http_utils.h" + +static const char *TAG = "HTTP_HEADER"; +#define HEADER_BUFFER (1024) + +/** + * dictionary item struct, with key-value pair + */ +typedef struct http_header_item { + char *key; /*!< key */ + char *value; /*!< value */ + STAILQ_ENTRY(http_header_item) next; /*!< Point to next entry */ +} http_header_item_t; + +STAILQ_HEAD(http_header, http_header_item); + + +http_header_handle_t http_header_init(void) +{ + http_header_handle_t header = calloc(1, sizeof(struct http_header)); + HTTP_MEM_CHECK(TAG, header, return NULL); + STAILQ_INIT(header); + return header; +} + +esp_err_t http_header_destroy(http_header_handle_t header) +{ + esp_err_t err = http_header_clean(header); + free(header); + return err; +} + +http_header_item_handle_t http_header_get_item(http_header_handle_t header, const char *key) +{ + http_header_item_handle_t item; + if (header == NULL || key == NULL) { + return NULL; + } + STAILQ_FOREACH(item, header, next) { + if (strcasecmp(item->key, key) == 0) { + return item; + } + } + return NULL; +} + +esp_err_t http_header_get(http_header_handle_t header, const char *key, char **value) +{ + http_header_item_handle_t item; + + item = http_header_get_item(header, key); + if (item) { + *value = item->value; + } else { + *value = NULL; + } + + return ESP_OK; +} + +static esp_err_t http_header_new_item(http_header_handle_t header, const char *key, const char *value) +{ + http_header_item_handle_t item; + + item = calloc(1, sizeof(http_header_item_t)); + HTTP_MEM_CHECK(TAG, item, return ESP_ERR_NO_MEM); + http_utils_assign_string(&item->key, key, 0); + HTTP_MEM_CHECK(TAG, item->key, goto _header_new_item_exit); + http_utils_trim_whitespace(&item->key); + http_utils_assign_string(&item->value, value, 0); + HTTP_MEM_CHECK(TAG, item->value, goto _header_new_item_exit); + http_utils_trim_whitespace(&item->value); + STAILQ_INSERT_TAIL(header, item, next); + return ESP_OK; +_header_new_item_exit: + free(item->key); + free(item->value); + return ESP_ERR_NO_MEM; +} + +esp_err_t http_header_set(http_header_handle_t header, const char *key, const char *value) +{ + http_header_item_handle_t item; + + if (value == NULL) { + return http_header_delete(header, key); + } + + item = http_header_get_item(header, key); + + if (item) { + free(item->value); + item->value = strdup(value); + http_utils_trim_whitespace(&item->value); + return ESP_OK; + } + return http_header_new_item(header, key, value); +} + +esp_err_t http_header_set_from_string(http_header_handle_t header, const char *key_value_data) +{ + char *eq_ch; + char *p_str; + + p_str = strdup(key_value_data); + HTTP_MEM_CHECK(TAG, p_str, return ESP_ERR_NO_MEM); + eq_ch = strchr(p_str, ':'); + if (eq_ch == NULL) { + free(p_str); + return ESP_ERR_INVALID_ARG; + } + *eq_ch = 0; + + http_header_set(header, p_str, eq_ch + 1); + free(p_str); + return ESP_OK; +} + + +esp_err_t http_header_delete(http_header_handle_t header, const char *key) +{ + http_header_item_handle_t item = http_header_get_item(header, key); + if (item) { + STAILQ_REMOVE(header, item, http_header_item, next); + free(item->key); + free(item->value); + free(item); + } else { + return ESP_ERR_NOT_FOUND; + } + return ESP_OK; +} + + +int http_header_set_format(http_header_handle_t header, const char *key, const char *format, ...) +{ + va_list argptr; + int len = 0; + char *buf = NULL; + va_start(argptr, format); + len = vasprintf(&buf, format, argptr); + HTTP_MEM_CHECK(TAG, buf, return 0); + va_end(argptr); + if (buf == NULL) { + return 0; + } + http_header_set(header, key, buf); + free(buf); + return len; +} + +int http_header_generate_string(http_header_handle_t header, int index, char *buffer, int *buffer_len) +{ + http_header_item_handle_t item; + int siz = 0; + int idx = 0; + int ret_idx = -1; + bool is_end = false; + + // iterate over the header entries to calculate buffer size and determine last item + STAILQ_FOREACH(item, header, next) { + if (item->value && idx >= index) { + siz += strlen(item->key); + siz += strlen(item->value); + siz += 4; //': ' and '\r\n' + } + idx ++; + + if (siz + 1 > *buffer_len - 2) { + // if this item would not fit to the buffer, return the index of the last fitting one + ret_idx = idx - 1; + ESP_LOGE(TAG, "Buffer length is small to fit all the headers"); + break; + } + } + + if (siz == 0) { + return 0; + } + if (ret_idx < 0) { + // all items would fit, mark this as the end of http header string + ret_idx = idx; + is_end = true; + } + + // iterate again over the header entries to write only the fitting indeces + int str_len = 0; + idx = 0; + STAILQ_FOREACH(item, header, next) { + if (item->value && idx >= index && idx < ret_idx) { + str_len += snprintf(buffer + str_len, *buffer_len - str_len, "%s: %s\r\n", item->key, item->value); + } + idx ++; + } + if (is_end) { + // write the http header terminator if all header entries have been written in this function call + str_len += snprintf(buffer + str_len, *buffer_len - str_len, "\r\n"); + } + *buffer_len = str_len; + return ret_idx; +} + +esp_err_t http_header_clean(http_header_handle_t header) +{ + http_header_item_handle_t item = STAILQ_FIRST(header), tmp; + while (item != NULL) { + tmp = STAILQ_NEXT(item, next); + free(item->key); + free(item->value); + free(item); + item = tmp; + } + STAILQ_INIT(header); + return ESP_OK; +} + +int http_header_count(http_header_handle_t header) +{ + http_header_item_handle_t item; + int count = 0; + STAILQ_FOREACH(item, header, next) { + count ++; + } + return count; +} diff --git a/components/esp_http_client/lib/http_utils.c b/components/esp_http_client/lib/http_utils.c new file mode 100644 index 000000000..267e39e6d --- /dev/null +++ b/components/esp_http_client/lib/http_utils.c @@ -0,0 +1,125 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "http_utils.h" + +#ifndef mem_check +#define mem_check(x) assert(x) +#endif + +char *http_utils_join_string(const char *first_str, int len_first, const char *second_str, int len_second) +{ + int first_str_len = len_first > 0 ? len_first : strlen(first_str); + int second_str_len = len_second > 0 ? len_second : strlen(second_str); + char *ret = NULL; + if (first_str_len + second_str_len > 0) { + ret = calloc(1, first_str_len + second_str_len + 1); + mem_check(ret); + memcpy(ret, first_str, first_str_len); + memcpy(ret + first_str_len, second_str, second_str_len); + } + return ret; +} + +char *http_utils_assign_string(char **str, const char *new_str, int len) +{ + int l = len; + if (new_str == NULL) { + return NULL; + } + char *old_str = *str; + if (l <= 0) { + l = strlen(new_str); + } + if (old_str) { + old_str = realloc(old_str, l + 1); + mem_check(old_str); + old_str[l] = 0; + } else { + old_str = calloc(1, l + 1); + mem_check(old_str); + } + memcpy(old_str, new_str, l); + *str = old_str; + return old_str; +} + +void http_utils_trim_whitespace(char **str) +{ + char *end, *start; + if (str == NULL) { + return; + } + start = *str; + if (start == NULL) { + return; + } + // Trim leading space + while (isspace((unsigned char)*start)) start ++; + + if (*start == 0) { // All spaces? + **str = 0; + return; + } + + // Trim trailing space + end = (char *)(start + strlen(start) - 1); + while (end > start && isspace((unsigned char)*end)) { + end--; + } + + // Write new null terminator + *(end + 1) = 0; + memmove(*str, start, strlen(start) + 1); +} + +char *http_utils_get_string_between(const char *str, const char *begin, const char *end) +{ + char *found = strstr(str, begin); + char *ret = NULL; + if (found) { + found += strlen(begin); + char *found_end = strstr(found, end); + if (found_end) { + ret = calloc(1, found_end - found + 1); + mem_check(ret); + memcpy(ret, found, found_end - found); + return ret; + } + } + return NULL; +} + +int http_utils_str_starts_with(const char *str, const char *start) +{ + int i; + int match_str_len = strlen(str); + int start_len = strlen(start); + + if (start_len > match_str_len) { + return -1; + } + for (i = 0; i < start_len; i++) { + if (str[i] != start[i]) { + return 1; + } + } + return 0; +} diff --git a/components/esp_http_client/lib/include/http_auth.h b/components/esp_http_client/lib/include/http_auth.h new file mode 100644 index 000000000..8835666c2 --- /dev/null +++ b/components/esp_http_client/lib/include/http_auth.h @@ -0,0 +1,60 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _HTTP_BASIC_AUTH_H_ +#define _HTTP_BASIC_AUTH_H_ + +/** + * HTTP Digest authentication data + */ +typedef struct { + char *method; /*!< Request method, example: GET */ + char *algorithm; /*!< Authentication algorithm */ + char *uri; /*!< URI of request example: /path/to/file.html */ + char *realm; /*!< Authentication realm */ + char *nonce; /*!< Authentication nonce */ + char *qop; /*!< Authentication qop */ + char *opaque; /*!< Authentication opaque */ + uint64_t cnonce; /*!< Authentication cnonce */ + int nc; /*!< Authentication nc */ +} esp_http_auth_data_t; + +/** + * @brief This use for Http digest authentication method, create http header for digest authentication. + * The returned string need to free after use + * + * @param[in] username The username + * @param[in] password The password + * @param auth_data The auth data + * + * @return + * - HTTP Header value of Authorization, valid for digest authentication, must be freed after usage + * - NULL + */ +char *http_auth_digest(const char *username, const char *password, esp_http_auth_data_t *auth_data); + +/** + * @brief This use for Http basic authentication method, create header value for basic http authentication + * The returned string need to free after use + * + * @param[in] username The username + * @param[in] password The password + * + * @return + * - HTTP Header value of Authorization, valid for basic authentication, must be free after use + * - NULL + */ +char *http_auth_basic(const char *username, const char *password); +#endif diff --git a/components/esp_http_client/lib/include/http_header.h b/components/esp_http_client/lib/include/http_header.h new file mode 100644 index 000000000..c514c6163 --- /dev/null +++ b/components/esp_http_client/lib/include/http_header.h @@ -0,0 +1,128 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _HTTP_HEADER_H_ +#define _HTTP_HEADER_H_ + +#include "rom/queue.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct http_header *http_header_handle_t; +typedef struct http_header_item *http_header_item_handle_t; + +/** + * @brief initialize and allocate the memory for the header object + * + * @return + * - http_header_handle_t + * - NULL if any errors + */ +http_header_handle_t http_header_init(void); + +/** + * @brief Cleanup and free all http header pairs + * + * @param[in] header The header + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_clean(http_header_handle_t header); + +/** + * @brief Cleanup with http_header_clean and destroy http header handle object + * + * @param[in] header The header + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_destroy(http_header_handle_t header); + +/** + * @brief Add a key-value pair of http header to the list, + * note that with value = NULL, this function will remove the header with `key` already exists in the list. + * + * @param[in] header The header + * @param[in] key The key + * @param[in] value The value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_set(http_header_handle_t header, const char *key, const char *value); + +/** + * @brief Sample as `http_header_set` but the value can be formated + * + * @param[in] header The header + * @param[in] key The key + * @param[in] format The format + * @param[in] ... format parameters + * + * @return Total length of value + */ +int http_header_set_format(http_header_handle_t header, const char *key, const char *format, ...); + +/** + * @brief Get a value of header in header list + * The address of the value will be assign set to `value` parameter or NULL if no header with the key exists in the list + * + * @param[in] header The header + * @param[in] key The key + * @param[out] value The value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_get(http_header_handle_t header, const char *key, char **value); + +/** + * @brief Create HTTP header string from the header with index, output string to buffer with buffer_len + * Also return the last index of header was generated + * + * @param[in] header The header + * @param[in] index The index + * @param buffer The buffer + * @param buffer_len The buffer length + * + * @return The last index of header was generated + */ +int http_header_generate_string(http_header_handle_t header, int index, char *buffer, int *buffer_len); + +/** + * @brief Remove the header with key from the headers list + * + * @param[in] header The header + * @param[in] key The key + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_delete(http_header_handle_t header, const char *key); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp_http_client/lib/include/http_utils.h b/components/esp_http_client/lib/include/http_utils.h new file mode 100644 index 000000000..14c3b10c4 --- /dev/null +++ b/components/esp_http_client/lib/include/http_utils.h @@ -0,0 +1,88 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _HTTP_UTILS_H_ +#define _HTTP_UTILS_H_ +#include + +/** + * @brief Assign new_str to *str pointer, and realloc *str if it not NULL + * + * @param str pointer to string pointer + * @param new_str assign this tring to str + * @param len length of string, 0 if new_str is zero terminated + * + * @return + * - new_str pointer + * - NULL + */ +char *http_utils_assign_string(char **str, const char *new_str, int len); + +/** + * @brief Remove white space at begin and end of string + * + * @param[in] str The string + * + * @return New strings have been trimmed + */ +void http_utils_trim_whitespace(char **str); + +/** + * @brief Gets the string between 2 string. + * It will allocate a new memory space for this string, so you need to free it when no longer use + * + * @param[in] str The source string + * @param[in] begin The begin string + * @param[in] end The end string + * + * @return The string between begin and end + */ +char *http_utils_get_string_between(const char *str, const char *begin, const char *end); + +/** + * @brief Join 2 strings to one + * It will allocate a new memory space for this string, so you need to free it when no longer use + * + * @param[in] first_str The first string + * @param[in] len_first The length first + * @param[in] second_str The second string + * @param[in] len_second The length second + * + * @return + * - New string pointer + * - NULL: Invalid input + */ +char *http_utils_join_string(const char *first_str, int len_first, const char *second_str, int len_second); + +/** + * @brief Check if ``str`` is start with ``start`` + * + * @param[in] str The string + * @param[in] start The start + * + * @return + * - (-1) if length of ``start`` larger than length of ``str`` + * - (1) if ``start`` NOT starts with ``start`` + * - (0) if ``str`` starts with ``start`` + */ +int http_utils_str_starts_with(const char *str, const char *start); + + +#define HTTP_MEM_CHECK(TAG, a, action) if (!(a)) { \ + ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } + +#endif diff --git a/components/esp_http_client/test/CMakeLists.txt b/components/esp_http_client/test/CMakeLists.txt new file mode 100644 index 000000000..202d2fed1 --- /dev/null +++ b/components/esp_http_client/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES unity test_utils esp_http_client) \ No newline at end of file diff --git a/components/esp_http_client/test/component.mk b/components/esp_http_client/test/component.mk new file mode 100644 index 000000000..ce464a212 --- /dev/null +++ b/components/esp_http_client/test/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/esp_http_client/test/test_http_client.c b/components/esp_http_client/test/test_http_client.c new file mode 100644 index 000000000..4a2f725d8 --- /dev/null +++ b/components/esp_http_client/test/test_http_client.c @@ -0,0 +1,139 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "unity.h" +#include "test_utils.h" + +#define HOST "httpbin.org" +#define USERNAME "user" +#define PASSWORD "challenge" + +TEST_CASE("Test in common case: Only URL and hostname are specified.", "[ESP HTTP CLIENT]") +{ + esp_http_client_config_t config_incorrect = {0}; + + test_case_uses_tcpip(); + + esp_http_client_handle_t client = esp_http_client_init(&config_incorrect); + TEST_ASSERT(client == NULL); + + esp_http_client_config_t config_with_url = { + .url = "http://httpbin.org/get", + }; + client = esp_http_client_init(&config_with_url); + TEST_ASSERT(client != NULL); + TEST_ASSERT(esp_http_client_cleanup(client) == ESP_OK); + + + esp_http_client_config_t config_with_hostname_path = { + .host = HOST, + .path = "/get", + }; + client = esp_http_client_init(&config_with_hostname_path); + TEST_ASSERT(client != NULL); + TEST_ASSERT(esp_http_client_cleanup(client) == ESP_OK); +} + +TEST_CASE("Get username and password after initialization.", "[ESP HTTP CLIENT]") +{ + esp_http_client_config_t config_with_auth = { + .host = HOST, + .path = "/", + .username = USERNAME, + .password = PASSWORD + }; + char *value = NULL; + esp_http_client_handle_t client = esp_http_client_init(&config_with_auth); + TEST_ASSERT_NOT_NULL(client); + // Test with username + esp_err_t r = esp_http_client_get_username(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + TEST_ASSERT_NOT_NULL(value); + TEST_ASSERT_EQUAL_STRING(USERNAME, value); + // Test with password + value = NULL; + r = esp_http_client_get_password(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + TEST_ASSERT_NOT_NULL(value); + TEST_ASSERT_EQUAL_STRING(PASSWORD, value); + esp_http_client_cleanup(client); +} + +/** + * Test case to test that, the esp_http_client_set_url won't drop username and password + * when pass a path "/abc" for url. + **/ +TEST_CASE("Username is unmodified when we change to new path", "[ESP HTTP CLIENT]") +{ + esp_http_client_config_t config_with_auth = { + .host = HOST, + .path = "/", + .username = USERNAME, + .password = PASSWORD + }; + char *value = NULL; + esp_http_client_handle_t client = esp_http_client_init(&config_with_auth); + TEST_ASSERT_NOT_NULL(client); + esp_err_t r = esp_http_client_get_username(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + TEST_ASSERT_NOT_NULL(value); + TEST_ASSERT_EQUAL_STRING(USERNAME, value); + esp_http_client_set_url(client, "/something-else/"); + r = esp_http_client_get_username(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + TEST_ASSERT_NOT_NULL(value); + TEST_ASSERT_EQUAL_STRING(USERNAME, value); + esp_http_client_cleanup(client); +} + +/** + * Test case to test that, the esp_http_client_set_url do not reset the auth credentials + * Explicit APIs esp_http_client_set_username and esp_http_client_set_password are used to change + * the auth credentials + **/ +TEST_CASE("Username and password will not reset if new absolute URL doesnot specify auth credentials.", "[ESP HTTP CLIENT]") +{ + esp_http_client_config_t config_with_auth = { + .host = HOST, + .path = "/", + .username = USERNAME, + .password = PASSWORD + }; + char *value = NULL; + esp_http_client_handle_t client = esp_http_client_init(&config_with_auth); + TEST_ASSERT_NOT_NULL(client); + esp_err_t r = esp_http_client_get_username(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + TEST_ASSERT_NOT_NULL(value); + TEST_ASSERT_EQUAL_STRING(USERNAME, value); + esp_http_client_set_url(client, "http://" HOST "/get"); + esp_http_client_set_username(client, value); + esp_http_client_set_password(client, value); + //checks if username is set or not + r = esp_http_client_get_username(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + //If username is set then value should not be NULL + TEST_ASSERT_NOT_NULL(value); + //checks if password is set or not + r = esp_http_client_get_password(client, &value); + TEST_ASSERT_EQUAL(ESP_OK, r); + //If password is set then value should not be NULL + TEST_ASSERT_NOT_NULL(value); + esp_http_client_cleanup(client); +} diff --git a/components/esp_http_server/CMakeLists.txt b/components/esp_http_server/CMakeLists.txt new file mode 100644 index 000000000..878034677 --- /dev/null +++ b/components/esp_http_server/CMakeLists.txt @@ -0,0 +1,13 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_PRIV_INCLUDEDIRS src/port/esp8266 src/util) +set(COMPONENT_SRCS "src/httpd_main.c" + "src/httpd_parse.c" + "src/httpd_sess.c" + "src/httpd_txrx.c" + "src/httpd_uri.c" + "src/util/ctrl_sock.c") + +set(COMPONENT_PRIV_REQUIRES lwip) +set(COMPONENT_REQUIRES http_parser) + +register_component() diff --git a/components/esp_http_server/Kconfig b/components/esp_http_server/Kconfig new file mode 100644 index 000000000..323961ad5 --- /dev/null +++ b/components/esp_http_server/Kconfig @@ -0,0 +1,15 @@ +menu "HTTP Server" + +config HTTPD_MAX_REQ_HDR_LEN + int "Max HTTP Request Header Length" + default 512 + help + This sets the maximum supported size of headers section in HTTP request packet to be processed by the server + +config HTTPD_MAX_URI_LEN + int "Max HTTP URI Length" + default 512 + help + This sets the maximum supported size of HTTP request URI to be processed by the server + +endmenu diff --git a/components/esp_http_server/component.mk b/components/esp_http_server/component.mk new file mode 100644 index 000000000..d2a9f6feb --- /dev/null +++ b/components/esp_http_server/component.mk @@ -0,0 +1,5 @@ + +COMPONENT_SRCDIRS := src src/util +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := src/port/esp8266 src/util + diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h new file mode 100644 index 000000000..93dae4dc7 --- /dev/null +++ b/components/esp_http_server/include/esp_http_server.h @@ -0,0 +1,1188 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_HTTP_SERVER_H_ +#define _ESP_HTTP_SERVER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +note: esp_https_server.h includes a customized copy of this +initializer that should be kept in sync +*/ +#define HTTPD_DEFAULT_CONFIG() { \ + .task_priority = tskIDLE_PRIORITY+5, \ + .stack_size = 4096, \ + .server_port = 80, \ + .ctrl_port = 32768, \ + .max_open_sockets = 7, \ + .max_uri_handlers = 8, \ + .max_resp_headers = 8, \ + .backlog_conn = 5, \ + .lru_purge_enable = false, \ + .recv_wait_timeout = 5, \ + .send_wait_timeout = 5, \ + .global_user_ctx = NULL, \ + .global_user_ctx_free_fn = NULL, \ + .global_transport_ctx = NULL, \ + .global_transport_ctx_free_fn = NULL, \ + .open_fn = NULL, \ + .close_fn = NULL, \ +} + +#define ESP_ERR_HTTPD_BASE (0x8000) /*!< Starting number of HTTPD error codes */ +#define ESP_ERR_HTTPD_HANDLERS_FULL (ESP_ERR_HTTPD_BASE + 1) /*!< All slots for registering URI handlers have been consumed */ +#define ESP_ERR_HTTPD_HANDLER_EXISTS (ESP_ERR_HTTPD_BASE + 2) /*!< URI handler with same method and target URI already registered */ +#define ESP_ERR_HTTPD_INVALID_REQ (ESP_ERR_HTTPD_BASE + 3) /*!< Invalid request pointer */ +#define ESP_ERR_HTTPD_RESULT_TRUNC (ESP_ERR_HTTPD_BASE + 4) /*!< Result string truncated */ +#define ESP_ERR_HTTPD_RESP_HDR (ESP_ERR_HTTPD_BASE + 5) /*!< Response header field larger than supported */ +#define ESP_ERR_HTTPD_RESP_SEND (ESP_ERR_HTTPD_BASE + 6) /*!< Error occured while sending response packet */ +#define ESP_ERR_HTTPD_ALLOC_MEM (ESP_ERR_HTTPD_BASE + 7) /*!< Failed to dynamically allocate memory for resource */ +#define ESP_ERR_HTTPD_TASK (ESP_ERR_HTTPD_BASE + 8) /*!< Failed to launch server task/thread */ + +/* ************** Group: Initialization ************** */ +/** @name Initialization + * APIs related to the Initialization of the web server + * @{ + */ + +/** + * @brief HTTP Server Instance Handle + * + * Every instance of the server will have a unique handle. + */ +typedef void* httpd_handle_t; + +/** + * @brief HTTP Method Type wrapper over "enum http_method" + * available in "http_parser" library + */ +typedef enum http_method httpd_method_t; + +/** + * @brief Prototype for freeing context data (if any) + * @param[in] ctx : object to free + */ +typedef void (*httpd_free_ctx_fn_t)(void *ctx); + +/** + * @brief Function prototype for opening a session. + * + * Called immediately after the socket was opened to set up the send/recv functions and + * other parameters of the socket. + * + * @param[in] hd : server instance + * @param[in] sockfd : session socket file descriptor + * @return status + */ +typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd); + +/** + * @brief Function prototype for closing a session. + * + * @note It's possible that the socket descriptor is invalid at this point, the function + * is called for all terminated sessions. Ensure proper handling of return codes. + * + * @param[in] hd : server instance + * @param[in] sockfd : session socket file descriptor + */ +typedef void (*httpd_close_func_t)(httpd_handle_t hd, int sockfd); + +/** + * @brief HTTP Server Configuration Structure + * + * @note Use HTTPD_DEFAULT_CONFIG() to initialize the configuration + * to a default value and then modify only those fields that are + * specifically determined by the use case. + */ +typedef struct httpd_config { + unsigned task_priority; /*!< Priority of FreeRTOS task which runs the server */ + size_t stack_size; /*!< The maximum stack size allowed for the server task */ + + /** + * TCP Port number for receiving and transmitting HTTP traffic + */ + uint16_t server_port; + + /** + * UDP Port number for asynchronously exchanging control signals + * between various components of the server + */ + uint16_t ctrl_port; + + uint16_t max_open_sockets; /*!< Max number of sockets/clients connected at any time*/ + uint16_t max_uri_handlers; /*!< Maximum allowed uri handlers */ + uint16_t max_resp_headers; /*!< Maximum allowed additional headers in HTTP response */ + uint16_t backlog_conn; /*!< Number of backlog connections */ + bool lru_purge_enable; /*!< Purge "Least Recently Used" connection */ + uint16_t recv_wait_timeout; /*!< Timeout for recv function (in seconds)*/ + uint16_t send_wait_timeout; /*!< Timeout for send function (in seconds)*/ + + /** + * Global user context. + * + * This field can be used to store arbitrary user data within the server context. + * The value can be retrieved using the server handle, available e.g. in the httpd_req_t struct. + * + * When shutting down, the server frees up the user context by + * calling free() on the global_user_ctx field. If you wish to use a custom + * function for freeing the global user context, please specify that here. + */ + void * global_user_ctx; + + /** + * Free function for global user context + */ + httpd_free_ctx_fn_t global_user_ctx_free_fn; + + /** + * Global transport context. + * + * Similar to global_user_ctx, but used for session encoding or encryption (e.g. to hold the SSL context). + * It will be freed using free(), unless global_transport_ctx_free_fn is specified. + */ + void * global_transport_ctx; + + /** + * Free function for global transport context + */ + httpd_free_ctx_fn_t global_transport_ctx_free_fn; + + /** + * Custom session opening callback. + * + * Called on a new session socket just after accept(), but before reading any data. + * + * This is an opportunity to set up e.g. SSL encryption using global_transport_ctx + * and the send/recv/pending session overrides. + * + * If a context needs to be maintained between these functions, store it in the session using + * httpd_sess_set_transport_ctx() and retrieve it later with httpd_sess_get_transport_ctx() + */ + httpd_open_func_t open_fn; + + /** + * Custom session closing callback. + * + * Called when a session is deleted, before freeing user and transport contexts and before + * closing the socket. This is a place for custom de-init code common to all sockets. + * + * Set the user or transport context to NULL if it was freed here, so the server does not + * try to free it again. + * + * This function is run for all terminated sessions, including sessions where the socket + * was closed by the network stack - that is, the file descriptor may not be valid anymore. + */ + httpd_close_func_t close_fn; +} httpd_config_t; + +/** + * @brief Starts the web server + * + * Create an instance of HTTP server and allocate memory/resources for it + * depending upon the specified configuration. + * + * Example usage: + * @code{c} + * + * //Function for starting the webserver + * httpd_handle_t start_webserver(void) + * { + * // Generate default configuration + * httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + * + * // Empty handle to http_server + * httpd_handle_t server = NULL; + * + * // Start the httpd server + * if (httpd_start(&server, &config) == ESP_OK) { + * // Register URI handlers + * httpd_register_uri_handler(server, &uri_get); + * httpd_register_uri_handler(server, &uri_post); + * } + * // If server failed to start, handle will be NULL + * return server; + * } + * + * @endcode + * + * @param[in] config : Configuration for new instance of the server + * @param[out] handle : Handle to newly created instance of the server. NULL on error + * @return + * - ESP_OK : Instance created successfully + * - ESP_ERR_INVALID_ARG : Null argument(s) + * - ESP_ERR_HTTPD_ALLOC_MEM : Failed to allocate memory for instance + * - ESP_ERR_HTTPD_TASK : Failed to launch server task + */ +esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config); + +/** + * @brief Stops the web server + * + * Deallocates memory/resources used by an HTTP server instance and + * deletes it. Once deleted the handle can no longer be used for accessing + * the instance. + * + * Example usage: + * @code{c} + * + * // Function for stopping the webserver + * void stop_webserver(httpd_handle_t server) + * { + * // Ensure handle is non NULL + * if (server != NULL) { + * // Stop the httpd server + * httpd_stop(server); + * } + * } + * + * @endcode + * + * @param[in] handle Handle to server returned by httpd_start + * @return + * - ESP_OK : Server stopped successfully + * - ESP_ERR_INVALID_ARG : Handle argument is Null + */ +esp_err_t httpd_stop(httpd_handle_t handle); + +/** End of Group Initialization + * @} + */ + +/* ************** Group: URI Handlers ************** */ +/** @name URI Handlers + * APIs related to the URI handlers + * @{ + */ + +/* Max supported HTTP request header length */ +#define HTTPD_MAX_REQ_HDR_LEN CONFIG_HTTPD_MAX_REQ_HDR_LEN + +/* Max supported HTTP request URI length */ +#define HTTPD_MAX_URI_LEN CONFIG_HTTPD_MAX_URI_LEN + +/** + * @brief HTTP Request Data Structure + */ +typedef struct httpd_req { + httpd_handle_t handle; /*!< Handle to server instance */ + int method; /*!< The type of HTTP request, -1 if unsupported method */ + const char uri[HTTPD_MAX_URI_LEN + 1]; /*!< The URI of this request (1 byte extra for null termination) */ + size_t content_len; /*!< Length of the request body */ + void *aux; /*!< Internally used members */ + + /** + * User context pointer passed during URI registration. + */ + void *user_ctx; + + /** + * Session Context Pointer + * + * A session context. Contexts are maintained across 'sessions' for a + * given open TCP connection. One session could have multiple request + * responses. The web server will ensure that the context persists + * across all these request and responses. + * + * By default, this is NULL. URI Handlers can set this to any meaningful + * value. + * + * If the underlying socket gets closed, and this pointer is non-NULL, + * the web server will free up the context by calling free(), unless + * free_ctx function is set. + */ + void *sess_ctx; + + /** + * Pointer to free context hook + * + * Function to free session context + * + * If the web server's socket closes, it frees up the session context by + * calling free() on the sess_ctx member. If you wish to use a custom + * function for freeing the session context, please specify that here. + */ + httpd_free_ctx_fn_t free_ctx; +} httpd_req_t; + +/** + * @brief Structure for URI handler + */ +typedef struct httpd_uri { + const char *uri; /*!< The URI to handle */ + httpd_method_t method; /*!< Method supported by the URI */ + + /** + * Handler to call for supported request method. This must + * return ESP_OK, or else the underlying socket will be closed. + */ + esp_err_t (*handler)(httpd_req_t *r); + + /** + * Pointer to user context data which will be available to handler + */ + void *user_ctx; +} httpd_uri_t; + +/** + * @brief Registers a URI handler + * + * @note URI handlers can be registered in real time as long as the + * server handle is valid. + * + * Example usage: + * @code{c} + * + * esp_err_t my_uri_handler(httpd_req_t* req) + * { + * // Recv , Process and Send + * .... + * .... + * .... + * + * // Fail condition + * if (....) { + * // Return fail to close session // + * return ESP_FAIL; + * } + * + * // On success + * return ESP_OK; + * } + * + * // URI handler structure + * httpd_uri_t my_uri { + * .uri = "/my_uri/path/xyz", + * .method = HTTPD_GET, + * .handler = my_uri_handler, + * .user_ctx = NULL + * }; + * + * // Register handler + * if (httpd_register_uri_handler(server_handle, &my_uri) != ESP_OK) { + * // If failed to register handler + * .... + * } + * + * @endcode + * + * @param[in] handle handle to HTTPD server instance + * @param[in] uri_handler pointer to handler that needs to be registered + * + * @return + * - ESP_OK : On successfully registering the handler + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_HANDLERS_FULL : If no slots left for new handler + * - ESP_ERR_HTTPD_HANDLER_EXISTS : If handler with same URI and + * method is already registered + */ +esp_err_t httpd_register_uri_handler(httpd_handle_t handle, + const httpd_uri_t *uri_handler); + +/** + * @brief Unregister a URI handler + * + * @param[in] handle handle to HTTPD server instance + * @param[in] uri URI string + * @param[in] method HTTP method + * + * @return + * - ESP_OK : On successfully deregistering the handler + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_NOT_FOUND : Handler with specified URI and method not found + */ +esp_err_t httpd_unregister_uri_handler(httpd_handle_t handle, + const char *uri, httpd_method_t method); + +/** + * @brief Unregister all URI handlers with the specified uri string + * + * @param[in] handle handle to HTTPD server instance + * @param[in] uri uri string specifying all handlers that need + * to be deregisterd + * + * @return + * - ESP_OK : On successfully deregistering all such handlers + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_NOT_FOUND : No handler registered with specified uri string + */ +esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char* uri); + +/** End of URI Handlers + * @} + */ + +/* ************** Group: TX/RX ************** */ +/** @name TX / RX + * Prototype for HTTPDs low-level send/recv functions + * @{ + */ + +#define HTTPD_SOCK_ERR_FAIL -1 +#define HTTPD_SOCK_ERR_INVALID -2 +#define HTTPD_SOCK_ERR_TIMEOUT -3 + +/** + * @brief Prototype for HTTPDs low-level send function + * + * @note User specified send function must handle errors internally, + * depending upon the set value of errno, and return specific + * HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as + * return value of httpd_send() function + * + * @param[in] hd : server instance + * @param[in] sockfd : session socket file descriptor + * @param[in] buf : buffer with bytes to send + * @param[in] buf_len : data size + * @param[in] flags : flags for the send() function + * @return + * - Bytes : The number of bytes sent successfully + * - HTTPD_SOCK_ERR_INVALID : Invalid arguments + * - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket send() + * - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket send() + */ +typedef int (*httpd_send_func_t)(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags); + +/** + * @brief Prototype for HTTPDs low-level recv function + * + * @note User specified recv function must handle errors internally, + * depending upon the set value of errno, and return specific + * HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as + * return value of httpd_req_recv() function + * + * @param[in] hd : server instance + * @param[in] sockfd : session socket file descriptor + * @param[in] buf : buffer with bytes to send + * @param[in] buf_len : data size + * @param[in] flags : flags for the send() function + * @return + * - Bytes : The number of bytes received successfully + * - 0 : Buffer length parameter is zero / connection closed by peer + * - HTTPD_SOCK_ERR_INVALID : Invalid arguments + * - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket recv() + * - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket recv() + */ +typedef int (*httpd_recv_func_t)(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags); + +/** + * @brief Prototype for HTTPDs low-level "get pending bytes" function + * + * @note User specified pending function must handle errors internally, + * depending upon the set value of errno, and return specific + * HTTPD_SOCK_ERR_ codes, which will be handled accordingly in + * the server task. + * + * @param[in] hd : server instance + * @param[in] sockfd : session socket file descriptor + * @return + * - Bytes : The number of bytes waiting to be received + * - HTTPD_SOCK_ERR_INVALID : Invalid arguments + * - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket pending() + * - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket pending() + */ +typedef int (*httpd_pending_func_t)(httpd_handle_t hd, int sockfd); + +/** End of TX / RX + * @} + */ + +/* ************** Group: Request/Response ************** */ +/** @name Request / Response + * APIs related to the data send/receive by URI handlers. + * These APIs are supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * @{ + */ + +/** + * @brief Override web server's receive function (by session FD) + * + * This function overrides the web server's receive function. This same function is + * used to read HTTP request packets. + * + * @note This API is supposed to be called either from the context of + * - an http session APIs where sockfd is a valid parameter + * - a URI handler where sockfd is obtained using httpd_req_to_sockfd() + * + * @param[in] hd HTTPD instance handle + * @param[in] sockfd Session socket FD + * @param[in] recv_func The receive function to be set for this session + * + * @return + * - ESP_OK : On successfully registering override + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_sess_set_recv_override(httpd_handle_t hd, int sockfd, httpd_recv_func_t recv_func); + +/** + * @brief Override web server's send function (by session FD) + * + * This function overrides the web server's send function. This same function is + * used to send out any response to any HTTP request. + * + * @note This API is supposed to be called either from the context of + * - an http session APIs where sockfd is a valid parameter + * - a URI handler where sockfd is obtained using httpd_req_to_sockfd() + * + * @param[in] hd HTTPD instance handle + * @param[in] sockfd Session socket FD + * @param[in] send_func The send function to be set for this session + * + * @return + * - ESP_OK : On successfully registering override + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_sess_set_send_override(httpd_handle_t hd, int sockfd, httpd_send_func_t send_func); + +/** + * @brief Override web server's pending function (by session FD) + * + * This function overrides the web server's pending function. This function is + * used to test for pending bytes in a socket. + * + * @note This API is supposed to be called either from the context of + * - an http session APIs where sockfd is a valid parameter + * - a URI handler where sockfd is obtained using httpd_req_to_sockfd() + * + * @param[in] hd HTTPD instance handle + * @param[in] sockfd Session socket FD + * @param[in] pending_func The receive function to be set for this session + * + * @return + * - ESP_OK : On successfully registering override + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_sess_set_pending_override(httpd_handle_t hd, int sockfd, httpd_pending_func_t pending_func); + +/** + * @brief Get the Socket Descriptor from the HTTP request + * + * This API will return the socket descriptor of the session for + * which URI handler was executed on reception of HTTP request. + * This is useful when user wants to call functions that require + * session socket fd, from within a URI handler, ie. : + * httpd_sess_get_ctx(), + * httpd_sess_trigger_close(), + * httpd_sess_update_lru_counter(). + * + * @note This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * + * @param[in] r The request whose socket descriptor should be found + * + * @return + * - Socket descriptor : The socket descriptor for this request + * - -1 : Invalid/NULL request pointer + */ +int httpd_req_to_sockfd(httpd_req_t *r); + +/** + * @brief API to read content data from the HTTP request + * + * This API will read HTTP content data from the HTTP request into + * provided buffer. Use content_len provided in httpd_req_t structure + * to know the length of data to be fetched. If content_len is too + * large for the buffer then user may have to make multiple calls to + * this function, each time fetching 'buf_len' number of bytes, + * while the pointer to content data is incremented internally by + * the same number. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - If an error is returned, the URI handler must further return an error. + * This will ensure that the erroneous socket is closed and cleaned up by + * the web server. + * - Presently Chunked Encoding is not supported + * + * @param[in] r The request being responded to + * @param[in] buf Pointer to a buffer that the data will be read into + * @param[in] buf_len Length of the buffer + * + * @return + * - Bytes : Number of bytes read into the buffer successfully + * - 0 : Buffer length parameter is zero / connection closed by peer + * - HTTPD_SOCK_ERR_INVALID : Invalid arguments + * - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket recv() + * - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket recv() + */ +int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len); + +/** + * @brief Search for a field in request headers and + * return the string length of it's value + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once httpd_resp_send() API is called all request headers + * are purged, so request headers need be copied into separate + * buffers if they are required later. + * + * @param[in] r The request being responded to + * @param[in] field The header field to be searched in the request + * + * @return + * - Length : If field is found in the request URL + * - Zero : Field not found / Invalid request / Null arguments + */ +size_t httpd_req_get_hdr_value_len(httpd_req_t *r, const char *field); + +/** + * @brief Get the value string of a field from the request headers + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once httpd_resp_send() API is called all request headers + * are purged, so request headers need be copied into separate + * buffers if they are required later. + * - If output size is greater than input, then the value is truncated, + * accompanied by truncation error as return value. + * - Use httpd_req_get_hdr_value_len() to know the right buffer length + * + * @param[in] r The request being responded to + * @param[in] field The field to be searched in the header + * @param[out] val Pointer to the buffer into which the value will be copied if the field is found + * @param[in] val_size Size of the user buffer "val" + * + * @return + * - ESP_OK : Field found in the request header and value string copied + * - ESP_ERR_NOT_FOUND : Key not found + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid HTTP request pointer + * - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated + */ +esp_err_t httpd_req_get_hdr_value_str(httpd_req_t *r, const char *field, char *val, size_t val_size); + +/** + * @brief Get Query string length from the request URL + * + * @note This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid + * + * @param[in] r The request being responded to + * + * @return + * - Length : Query is found in the request URL + * - Zero : Query not found / Null arguments / Invalid request + */ +size_t httpd_req_get_url_query_len(httpd_req_t *r); + +/** + * @brief Get Query string from the request URL + * + * @note + * - Presently, the user can fetch the full URL query string, but decoding + * will have to be performed by the user. Request headers can be read using + * httpd_req_get_hdr_value_str() to know the 'Content-Type' (eg. Content-Type: + * application/x-www-form-urlencoded) and then the appropriate decoding + * algorithm needs to be applied. + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid + * - If output size is greater than input, then the value is truncated, + * accompanied by truncation error as return value + * - Use httpd_req_get_url_query_len() to know the right buffer length + * + * @param[in] r The request being responded to + * @param[out] buf Pointer to the buffer into which the query string will be copied (if found) + * @param[in] buf_len Length of output buffer + * + * @return + * - ESP_OK : Query is found in the request URL and copied to buffer + * - ESP_ERR_NOT_FOUND : Query not found + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid HTTP request pointer + * - ESP_ERR_HTTPD_RESULT_TRUNC : Query string truncated + */ +esp_err_t httpd_req_get_url_query_str(httpd_req_t *r, char *buf, size_t buf_len); + +/** + * @brief Helper function to get a URL query tag from a query + * string of the type param1=val1¶m2=val2 + * + * @note + * - The components of URL query string (keys and values) are not URLdecoded. + * The user must check for 'Content-Type' field in the request headers and + * then depending upon the specified encoding (URLencoded or otherwise) apply + * the appropriate decoding algorithm. + * - If actual value size is greater than val_size, then the value is truncated, + * accompanied by truncation error as return value. + * + * @param[in] qry Pointer to query string + * @param[in] key The key to be searched in the query string + * @param[out] val Pointer to the buffer into which the value will be copied if the key is found + * @param[in] val_size Size of the user buffer "val" + * + * @return + * - ESP_OK : Key is found in the URL query string and copied to buffer + * - ESP_ERR_NOT_FOUND : Key not found + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated + */ +esp_err_t httpd_query_key_value(const char *qry, const char *key, char *val, size_t val_size); + +/** + * @brief API to send a complete HTTP response. + * + * This API will send the data as an HTTP response to the request. + * This assumes that you have the entire response ready in a single + * buffer. If you wish to send response in incremental chunks use + * httpd_resp_send_chunk() instead. + * + * If no status code and content-type were set, by default this + * will send 200 OK status code and content type as text/html. + * You may call the following functions before this API to configure + * the response headers : + * httpd_resp_set_status() - for setting the HTTP status string, + * httpd_resp_set_type() - for setting the Content Type, + * httpd_resp_set_hdr() - for appending any additional field + * value entries in the response header + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once this API is called, the request has been responded to. + * - No additional data can then be sent for the request. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if + * they are required later. + * + * @param[in] r The request being responded to + * @param[in] buf Buffer from where the content is to be fetched + * @param[in] buf_len Length of the buffer, -1 to use strlen() + * + * @return + * - ESP_OK : On successfully sending the response packet + * - ESP_ERR_INVALID_ARG : Null request pointer + * - ESP_ERR_HTTPD_RESP_HDR : Essential headers are too large for internal buffer + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request + */ +esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len); + +/** + * @brief API to send one HTTP chunk + * + * This API will send the data as an HTTP response to the + * request. This API will use chunked-encoding and send the response + * in the form of chunks. If you have the entire response contained in + * a single buffer, please use httpd_resp_send() instead. + * + * If no status code and content-type were set, by default this will + * send 200 OK status code and content type as text/html. You may + * call the following functions before this API to configure the + * response headers + * httpd_resp_set_status() - for setting the HTTP status string, + * httpd_resp_set_type() - for setting the Content Type, + * httpd_resp_set_hdr() - for appending any additional field + * value entries in the response header + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - When you are finished sending all your chunks, you must call + * this function with buf_len as 0. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if they + * are required later. + * + * @param[in] r The request being responded to + * @param[in] buf Pointer to a buffer that stores the data + * @param[in] buf_len Length of the data from the buffer that should be sent out, -1 to use strlen() + * + * @return + * - ESP_OK : On successfully sending the response packet chunk + * - ESP_ERR_INVALID_ARG : Null request pointer + * - ESP_ERR_HTTPD_RESP_HDR : Essential headers are too large for internal buffer + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len); + +/* Some commonly used status codes */ +#define HTTPD_200 "200 OK" /*!< HTTP Response 200 */ +#define HTTPD_204 "204 No Content" /*!< HTTP Response 204 */ +#define HTTPD_207 "207 Multi-Status" /*!< HTTP Response 207 */ +#define HTTPD_400 "400 Bad Request" /*!< HTTP Response 400 */ +#define HTTPD_404 "404 Not Found" /*!< HTTP Response 404 */ +#define HTTPD_408 "408 Request Timeout" /*!< HTTP Response 408 */ +#define HTTPD_500 "500 Internal Server Error" /*!< HTTP Response 500 */ + +/** + * @brief API to set the HTTP status code + * + * This API sets the status of the HTTP response to the value specified. + * By default, the '200 OK' response is sent as the response. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - This API only sets the status to this value. The status isn't + * sent out until any of the send APIs is executed. + * - Make sure that the lifetime of the status string is valid till + * send function is called. + * + * @param[in] r The request being responded to + * @param[in] status The HTTP status code of this response + * + * @return + * - ESP_OK : On success + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status); + +/* Some commonly used content types */ +#define HTTPD_TYPE_JSON "application/json" /*!< HTTP Content type JSON */ +#define HTTPD_TYPE_TEXT "text/html" /*!< HTTP Content type text/HTML */ +#define HTTPD_TYPE_OCTET "application/octet-stream" /*!< HTTP Content type octext-stream */ + +/** + * @brief API to set the HTTP content type + * + * This API sets the 'Content Type' field of the response. + * The default content type is 'text/html'. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - This API only sets the content type to this value. The type + * isn't sent out until any of the send APIs is executed. + * - Make sure that the lifetime of the type string is valid till + * send function is called. + * + * @param[in] r The request being responded to + * @param[in] type The Content Type of the response + * + * @return + * - ESP_OK : On success + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type); + +/** + * @brief API to append any additional headers + * + * This API sets any additional header fields that need to be sent in the response. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - The header isn't sent out until any of the send APIs is executed. + * - The maximum allowed number of additional headers is limited to + * value of max_resp_headers in config structure. + * - Make sure that the lifetime of the field value strings are valid till + * send function is called. + * + * @param[in] r The request being responded to + * @param[in] field The field name of the HTTP header + * @param[in] value The value of this HTTP header + * + * @return + * - ESP_OK : On successfully appending new header + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESP_HDR : Total additional headers exceed max allowed + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value); + +/** + * @brief Helper function for HTTP 404 + * + * Send HTTP 404 message. If you wish to send additional data in the body of the + * response, please use the lower-level functions directly. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if + * they are required later. + * + * @param[in] r The request being responded to + * + * @return + * - ESP_OK : On successfully sending the response packet + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_send_404(httpd_req_t *r); + +/** + * @brief Helper function for HTTP 408 + * + * Send HTTP 408 message. If you wish to send additional data in the body of the + * response, please use the lower-level functions directly. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if + * they are required later. + * + * @param[in] r The request being responded to + * + * @return + * - ESP_OK : On successfully sending the response packet + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_send_408(httpd_req_t *r); + +/** + * @brief Helper function for HTTP 500 + * + * Send HTTP 500 message. If you wish to send additional data in the body of the + * response, please use the lower-level functions directly. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Once this API is called, all request headers are purged, so + * request headers need be copied into separate buffers if + * they are required later. + * + * @param[in] r The request being responded to + * + * @return + * - ESP_OK : On successfully sending the response packet + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESP_SEND : Error in raw send + * - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer + */ +esp_err_t httpd_resp_send_500(httpd_req_t *r); + +/** + * @brief Raw HTTP send + * + * Call this API if you wish to construct your custom response packet. + * When using this, all essential header, eg. HTTP version, Status Code, + * Content Type and Length, Encoding, etc. will have to be constructed + * manually, and HTTP delimeters (CRLF) will need to be placed correctly + * for separating sub-sections of the HTTP response packet. + * + * If the send override function is set, this API will end up + * calling that function eventually to send data out. + * + * @note + * - This API is supposed to be called only from the context of + * a URI handler where httpd_req_t* request pointer is valid. + * - Unless the response has the correct HTTP structure (which the + * user must now ensure) it is not guaranteed that it will be + * recognized by the client. For most cases, you wouldn't have + * to call this API, but you would rather use either of : + * httpd_resp_send(), + * httpd_resp_send_chunk() + * + * @param[in] r The request being responded to + * @param[in] buf Buffer from where the fully constructed packet is to be read + * @param[in] buf_len Length of the buffer + * + * @return + * - Bytes : Number of bytes that were sent successfully + * - HTTPD_SOCK_ERR_INVALID : Invalid arguments + * - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket send() + * - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket send() + */ +int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len); + +/** End of Request / Response + * @} + */ + +/* ************** Group: Session ************** */ +/** @name Session + * Functions for controlling sessions and accessing context data + * @{ + */ + +/** + * @brief Get session context from socket descriptor + * + * Typically if a session context is created, it is available to URI handlers + * through the httpd_req_t structure. But, there are cases where the web + * server's send/receive functions may require the context (for example, for + * accessing keying information etc). Since the send/receive function only have + * the socket descriptor at their disposal, this API provides them with a way to + * retrieve the session context. + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor for which the context should be extracted. + * + * @return + * - void* : Pointer to the context associated with this session + * - NULL : Empty context / Invalid handle / Invalid socket fd + */ +void *httpd_sess_get_ctx(httpd_handle_t handle, int sockfd); + +/** + * @brief Set session context by socket descriptor + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor for which the context should be extracted. + * @param[in] ctx Context object to assign to the session + * @param[in] free_fn Function that should be called to free the context + */ +void httpd_sess_set_ctx(httpd_handle_t handle, int sockfd, void *ctx, httpd_free_ctx_fn_t free_fn); + +/** + * @brief Get session 'transport' context by socket descriptor + * @see httpd_sess_get_ctx() + * + * This context is used by the send/receive functions, for example to manage SSL context. + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor for which the context should be extracted. + * @return + * - void* : Pointer to the transport context associated with this session + * - NULL : Empty context / Invalid handle / Invalid socket fd + */ +void *httpd_sess_get_transport_ctx(httpd_handle_t handle, int sockfd); + +/** + * @brief Set session 'transport' context by socket descriptor + * @see httpd_sess_set_ctx() + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor for which the context should be extracted. + * @param[in] ctx Transport context object to assign to the session + * @param[in] free_fn Function that should be called to free the transport context + */ +void httpd_sess_set_transport_ctx(httpd_handle_t handle, int sockfd, void *ctx, httpd_free_ctx_fn_t free_fn); + +/** + * @brief Get HTTPD global user context (it was set in the server config struct) + * + * @param[in] handle Handle to server returned by httpd_start + * @return global user context + */ +void *httpd_get_global_user_ctx(httpd_handle_t handle); + +/** + * @brief Get HTTPD global transport context (it was set in the server config struct) + * + * @param[in] handle Handle to server returned by httpd_start + * @return global transport context + */ +void *httpd_get_global_transport_ctx(httpd_handle_t handle); + +/** + * @brief Trigger an httpd session close externally + * + * @note Calling this API is only required in special circumstances wherein + * some application requires to close an httpd client session asynchronously. + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor of the session to be closed + * + * @return + * - ESP_OK : On successfully initiating closure + * - ESP_FAIL : Failure to queue work + * - ESP_ERR_NOT_FOUND : Socket fd not found + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_sess_trigger_close(httpd_handle_t handle, int sockfd); + +/** + * @brief Update LRU counter for a given socket + * + * LRU Counters are internally associated with each session to monitor + * how recently a session exchanged traffic. When LRU purge is enabled, + * if a client is requesting for connection but maximum number of + * sockets/sessions is reached, then the session having the earliest + * LRU counter is closed automatically. + * + * Updating the LRU counter manually prevents the socket from being purged + * due to the Least Recently Used (LRU) logic, even though it might not + * have received traffic for some time. This is useful when all open + * sockets/session are frequently exchanging traffic but the user specifically + * wants one of the sessions to be kept open, irrespective of when it last + * exchanged a packet. + * + * @note Calling this API is only necessary if the LRU Purge Enable option + * is enabled. + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] sockfd The socket descriptor of the session for which LRU counter + * is to be updated + * + * @return + * - ESP_OK : Socket found and LRU counter updated + * - ESP_ERR_NOT_FOUND : Socket not found + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_sess_update_lru_counter(httpd_handle_t handle, int sockfd); + +/** End of Session + * @} + */ + +/* ************** Group: Work Queue ************** */ +/** @name Work Queue + * APIs related to the HTTPD Work Queue + * @{ + */ + +/** + * @brief Prototype of the HTTPD work function + * Please refer to httpd_queue_work() for more details. + * @param[in] arg The arguments for this work function + */ +typedef void (*httpd_work_fn_t)(void *arg); + +/** + * @brief Queue execution of a function in HTTPD's context + * + * This API queues a work function for asynchronous execution + * + * @note Some protocols require that the web server generate some asynchronous data + * and send it to the persistently opened connection. This facility is for use + * by such protocols. + * + * @param[in] handle Handle to server returned by httpd_start + * @param[in] work Pointer to the function to be executed in the HTTPD's context + * @param[in] arg Pointer to the arguments that should be passed to this function + * + * @return + * - ESP_OK : On successfully queueing the work + * - ESP_FAIL : Failure in ctrl socket + * - ESP_ERR_INVALID_ARG : Null arguments + */ +esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *arg); + +/** End of Group Work Queue + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! _ESP_HTTP_SERVER_H_ */ diff --git a/components/esp_http_server/include/http_server.h b/components/esp_http_server/include/http_server.h new file mode 100644 index 000000000..56f73c5b7 --- /dev/null +++ b/components/esp_http_server/include/http_server.h @@ -0,0 +1,2 @@ +#warning http_server.h has been renamed to esp_http_server.h, please update include directives +#include "esp_http_server.h" diff --git a/components/esp_http_server/src/esp_httpd_priv.h b/components/esp_http_server/src/esp_httpd_priv.h new file mode 100644 index 000000000..8cbd0e94c --- /dev/null +++ b/components/esp_http_server/src/esp_httpd_priv.h @@ -0,0 +1,531 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _HTTPD_PRIV_H_ +#define _HTTPD_PRIV_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include "osal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Size of request data block/chunk (not to be confused with chunked encoded data) + * that is received and parsed in one turn of the parsing process. This should not + * exceed the scratch buffer size and should atleast be 8 bytes */ +#define PARSER_BLOCK_SIZE 128 + +/* Calculate the maximum size needed for the scratch buffer */ +#define HTTPD_SCRATCH_BUF MAX(HTTPD_MAX_REQ_HDR_LEN, HTTPD_MAX_URI_LEN) + +/* Formats a log string to prepend context function name */ +#define LOG_FMT(x) "%s: " x, __func__ + +/** + * @brief Thread related data for internal use + */ +struct thread_data { + othread_t handle; /*!< Handle to thread/task */ + enum { + THREAD_IDLE = 0, + THREAD_RUNNING, + THREAD_STOPPING, + THREAD_STOPPED, + } status; /*!< State of the thread */ +}; + +/** + * @brief Error codes sent by server in case of errors + * encountered during processing of an HTTP request + */ +typedef enum { + /* For any unexpected errors during parsing, like unexpected + * state transitions, or unhandled errors. + */ + HTTPD_500_SERVER_ERROR = 0, + + /* For methods not supported by http_parser. Presently + * http_parser halts parsing when such methods are + * encountered and so the server responds with 400 Bad + * Request error instead. + */ + HTTPD_501_METHOD_NOT_IMPLEMENTED, + + /* When HTTP version is not 1.1 */ + HTTPD_505_VERSION_NOT_SUPPORTED, + + /* Returned when http_parser halts parsing due to incorrect + * syntax of request, unsupported method in request URI or + * due to chunked encoding option present in headers + */ + HTTPD_400_BAD_REQUEST, + + /* When requested URI is not found */ + HTTPD_404_NOT_FOUND, + + /* When URI found, but method has no handler registered */ + HTTPD_405_METHOD_NOT_ALLOWED, + + /* Intended for recv timeout. Presently it's being sent + * for other recv errors as well. Client should expect the + * server to immediatly close the connection after + * responding with this. + */ + HTTPD_408_REQ_TIMEOUT, + + /* Intended for responding to chunked encoding, which is + * not supported currently. Though unhandled http_parser + * callback for chunked request returns "400 Bad Request" + */ + HTTPD_411_LENGTH_REQUIRED, + + /* URI length greater than HTTPD_MAX_URI_LEN */ + HTTPD_414_URI_TOO_LONG, + + /* Headers section larger thn HTTPD_MAX_REQ_HDR_LEN */ + HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE, + + /* There is no particular HTTP error code for not supporting + * upgrade. For this respond with 200 OK. Client expects status + * code 101 if upgrade were supported, so 200 should be fine. + */ + HTTPD_XXX_UPGRADE_NOT_SUPPORTED +} httpd_err_resp_t; + +/** + * @brief A database of all the open sockets in the system. + */ +struct sock_db { + int fd; /*!< The file descriptor for this socket */ + void *ctx; /*!< A custom context for this socket */ + void *transport_ctx; /*!< A custom 'transport' context for this socket, to be used by send/recv/pending */ + httpd_handle_t handle; /*!< Server handle */ + httpd_free_ctx_fn_t free_ctx; /*!< Function for freeing the context */ + httpd_free_ctx_fn_t free_transport_ctx; /*!< Function for freeing the 'transport' context */ + httpd_send_func_t send_fn; /*!< Send function for this socket */ + httpd_recv_func_t recv_fn; /*!< Receive function for this socket */ + httpd_pending_func_t pending_fn; /*!< Pending function for this socket */ + uint64_t lru_counter; /*!< LRU Counter indicating when the socket was last used */ + char pending_data[PARSER_BLOCK_SIZE]; /*!< Buffer for pending data to be received */ + size_t pending_len; /*!< Length of pending data to be received */ +}; + +/** + * @brief Auxilary data structure for use during reception and processing + * of requests and temporarily keeping responses + */ +struct httpd_req_aux { + struct sock_db *sd; /*!< Pointer to socket database */ + char scratch[HTTPD_SCRATCH_BUF + 1]; /*!< Temporary buffer for our operations (1 byte extra for null termination) */ + size_t remaining_len; /*!< Amount of data remaining to be fetched */ + char *status; /*!< HTTP response's status code */ + char *content_type; /*!< HTTP response's content type */ + bool first_chunk_sent; /*!< Used to indicate if first chunk sent */ + unsigned req_hdrs_count; /*!< Count of total headers in request packet */ + unsigned resp_hdrs_count; /*!< Count of additional headers in response packet */ + struct resp_hdr { + const char *field; + const char *value; + } *resp_hdrs; /*!< Additional headers in response packet */ + struct http_parser_url url_parse_res; /*!< URL parsing result, used for retrieving URL elements */ +}; + +/** + * @brief Server data for each instance. This is exposed publicaly as + * httpd_handle_t but internal structure/members are kept private. + */ +struct httpd_data { + httpd_config_t config; /*!< HTTPD server configuration */ + int listen_fd; /*!< Server listener FD */ + int ctrl_fd; /*!< Ctrl message receiver FD */ + int msg_fd; /*!< Ctrl message sender FD */ + struct thread_data hd_td; /*!< Information for the HTTPd thread */ + struct sock_db *hd_sd; /*!< The socket database */ + httpd_uri_t **hd_calls; /*!< Registered URI handlers */ + struct httpd_req hd_req; /*!< The current HTTPD request */ + struct httpd_req_aux hd_req_aux; /*!< Additional data about the HTTPD request kept unexposed */ +}; + +/******************* Group : Session Management ********************/ +/** @name Session Management + * Functions related to HTTP session management + * @{ + */ + +/** + * @brief Retrieve a session by its descriptor + * + * @param[in] hd Server instance data + * @param[in] sockfd Socket FD + * @return pointer into the socket DB, or NULL if not found + */ +struct sock_db *httpd_sess_get(struct httpd_data *hd, int sockfd); + +/** + * @brief Delete sessions whose FDs have became invalid. + * This is a recovery strategy e.g. after select() fails. + * + * @param[in] hd Server instance data + */ +void httpd_sess_delete_invalid(struct httpd_data *hd); + +/** + * @brief Initializes an http session by resetting the sockets database. + * + * @param[in] hd Server instance data + */ +void httpd_sess_init(struct httpd_data *hd); + +/** + * @brief Starts a new session for client requesting connection and adds + * it's descriptor to the socket database. + * + * @param[in] hd Server instance data + * @param[in] newfd Descriptor of the new client to be added to the session. + * + * @return + * - ESP_OK : on successfully queueing the work + * - ESP_FAIL : in case of control socket error while sending + */ +esp_err_t httpd_sess_new(struct httpd_data *hd, int newfd); + +/** + * @brief Processes incoming HTTP requests + * + * @param[in] hd Server instance data + * @param[in] clifd Descriptor of the client from which data is to be received + * + * @return + * - ESP_OK : on successfully receiving, parsing and responding to a request + * - ESP_FAIL : in case of failure in any of the stages of processing + */ +esp_err_t httpd_sess_process(struct httpd_data *hd, int clifd); + +/** + * @brief Remove client descriptor from the session / socket database + * and close the connection for this client. + * + * @note The returned descriptor should be used by httpd_sess_iterate() + * to continue the iteration correctly. This ensurs that the + * iteration is not restarted abruptly which may cause reading from + * a socket which has been already processed and thus blocking + * the server loop until data appears on that socket. + * + * @param[in] hd Server instance data + * @param[in] clifd Descriptor of the client to be removed from the session. + * + * @return + * - +VE : Client descriptor preceding the one being deleted + * - -1 : No descriptor preceding the one being deleted + */ +int httpd_sess_delete(struct httpd_data *hd, int clifd); + +/** + * @brief Free session context + * + * @param[in] ctx Pointer to session context + * @param[in] free_fn Free function to call on session context + */ +void httpd_sess_free_ctx(void *ctx, httpd_free_ctx_fn_t free_fn); + +/** + * @brief Add descriptors present in the socket database to an fd_set and + * update the value of maxfd which are needed by the select function + * for looking through all available sockets for incoming data. + * + * @param[in] hd Server instance data + * @param[out] fdset File descriptor set to be updated. + * @param[out] maxfd Maximum value among all file descriptors. + */ +void httpd_sess_set_descriptors(struct httpd_data *hd, fd_set *fdset, int *maxfd); + +/** + * @brief Iterates through the list of client fds in the session /socket database. + * Passing the value of a client fd returns the fd for the next client + * in the database. In order to iterate from the beginning pass -1 as fd. + * + * @param[in] hd Server instance data + * @param[in] fd Last accessed client descriptor. + * -1 to reset iterator to start of database. + * + * @return + * - +VE : Client descriptor next in the database + * - -1 : End of iteration + */ +int httpd_sess_iterate(struct httpd_data *hd, int fd); + +/** + * @brief Checks if session can accept another connection from new client. + * If sockets database is full then this returns false. + * + * @param[in] hd Server instance data + * + * @return True if session can accept new clients + */ +bool httpd_is_sess_available(struct httpd_data *hd); + +/** + * @brief Checks if session has any pending data/packets + * for processing + * + * This is needed as httpd_unrecv may unreceive next + * packet in the stream. If only partial packet was + * received then select() would mark the fd for processing + * as remaining part of the packet would still be in socket + * recv queue. But if a complete packet got unreceived + * then it would not be processed until furtur data is + * received on the socket. This is when this function + * comes in use, as it checks the socket's pending data + * buffer. + * + * @param[in] hd Server instance data + * @param[in] fd Client descriptor + * + * @return True if there is any pending data + */ +bool httpd_sess_pending(struct httpd_data *hd, int fd); + +/** + * @brief Removes the least recently used client from the session + * + * This may be useful if new clients are requesting for connection but + * max number of connections is reached, in which case the client which + * is inactive for the longest will be removed from the session. + * + * @param[in] hd Server instance data + * + * @return + * - ESP_OK : if session closure initiated successfully + * - ESP_FAIL : if failed + */ +esp_err_t httpd_sess_close_lru(struct httpd_data *hd); + +/** End of Group : Session Management + * @} + */ + +/****************** Group : URI Handling ********************/ +/** @name URI Handling + * Methods for accessing URI handlers + * @{ + */ + +/** + * @brief For an HTTP request, searches through all the registered URI handlers + * and invokes the appropriate one if found + * + * @param[in] hd Server instance data for which handler needs to be invoked + * + * @return + * - ESP_OK : if handler found and executed successfully + * - ESP_FAIL : otherwise + */ +esp_err_t httpd_uri(struct httpd_data *hd); + +/** + * @brief Deregister all URI handlers + * + * @param[in] hd Server instance data + */ +void httpd_unregister_all_uri_handlers(struct httpd_data *hd); + +/** + * @brief Validates the request to prevent users from calling APIs, that are to + * be called only inside a URI handler, outside the handler context + * + * @param[in] req Pointer to HTTP request that neds to be validated + * + * @return + * - true : if valid request + * - false : otherwise + */ +bool httpd_validate_req_ptr(httpd_req_t *r); + +/* httpd_validate_req_ptr() adds some overhead to frequently used APIs, + * and is useful mostly for debugging, so it's preferable to disable + * the check by defaut and enable it only if necessary */ +#ifdef CONFIG_HTTPD_VALIDATE_REQ +#define httpd_valid_req(r) httpd_validate_req_ptr(r) +#else +#define httpd_valid_req(r) true +#endif + +/** End of Group : URI Handling + * @} + */ + +/****************** Group : Processing ********************/ +/** @name Processing + * Methods for processing HTTP requests + * @{ + */ + +/** + * @brief Initiates the processing of HTTP request + * + * Receives incoming TCP packet on a socket, then parses the packet as + * HTTP request and fills httpd_req_t data structure with the extracted + * URI, headers are ready to be fetched from scratch buffer and calling + * http_recv() after this reads the body of the request. + * + * @param[in] hd Server instance data + * @param[in] sd Pointer to socket which is needed for receiving TCP packets. + * + * @return + * - ESP_OK : if request packet is valid + * - ESP_FAIL : otherwise + */ +esp_err_t httpd_req_new(struct httpd_data *hd, struct sock_db *sd); + +/** + * @brief For an HTTP request, resets the resources allocated for it and + * purges any data left to be received + * + * @param[in] hd Server instance data + * + * @return + * - ESP_OK : if request packet deleted and resources cleaned. + * - ESP_FAIL : otherwise. + */ +esp_err_t httpd_req_delete(struct httpd_data *hd); + +/** End of Group : Parsing + * @} + */ + +/****************** Group : Send/Receive ********************/ +/** @name Send and Receive + * Methods for transmitting and receiving HTTP requests and responses + * @{ + */ + +/** + * @brief For sending out error code in response to HTTP request. + * + * @param[in] req Pointer to the HTTP request for which the resonse needs to be sent + * @param[in] error Error type to send + * + * @return + * - ESP_OK : if successful + * - ESP_FAIL : if failed + */ +esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error); + +/** + * @brief For sending out data in response to an HTTP request. + * + * @param[in] req Pointer to the HTTP request for which the resonse needs to be sent + * @param[in] buf Pointer to the buffer from where the body of the response is taken + * @param[in] buf_len Length of the buffer + * + * @return + * - Length of data : if successful + * - ESP_FAIL : if failed + */ +int httpd_send(httpd_req_t *req, const char *buf, size_t buf_len); + +/** + * @brief For receiving HTTP request data + * + * @note The exposed API httpd_recv() is simply this function with last parameter + * set as false. This function is used internally during reception and + * processing of a new request. The option to halt after receiving pending + * data prevents the server from requesting more data than is needed for + * completing a packet in case when all the remaining part of the packet is + * in the pending buffer. + * + * @param[in] req Pointer to new HTTP request which only has the socket descriptor + * @param[out] buf Pointer to the buffer which will be filled with the received data + * @param[in] buf_len Length of the buffer + * @param[in] halt_after_pending When set true, halts immediatly after receiving from + * pending buffer + * + * @return + * - Length of data : if successful + * - ESP_FAIL : if failed + */ +int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending); + +/** + * @brief For un-receiving HTTP request data + * + * This function copies data into internal buffer pending_data so that + * when httpd_recv is called, it first fetches this pending data and + * then only starts receiving from the socket + * + * @note If data is too large for the internal buffer then only + * part of the data is unreceived, reflected in the returned + * length. Make sure that such truncation is checked for and + * handled properly. + * + * @param[in] req Pointer to new HTTP request which only has the socket descriptor + * @param[in] buf Pointer to the buffer from where data needs to be un-received + * @param[in] buf_len Length of the buffer + * + * @return Length of data copied into pending buffer + */ +size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len); + +/** + * @brief This is the low level default send function of the HTTPD. This should + * NEVER be called directly. The semantics of this is exactly similar to + * send() of the BSD socket API. + * + * @param[in] hd Server instance data + * @param[in] sockfd Socket descriptor for sending data + * @param[in] buf Pointer to the buffer from where the body of the response is taken + * @param[in] buf_len Length of the buffer + * @param[in] flags Flags for mode selection + * + * @return + * - Length of data : if successful + * - -1 : if failed (appropriate errno is set) + */ +int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags); + +/** + * @brief This is the low level default recv function of the HTTPD. This should + * NEVER be called directly. The semantics of this is exactly similar to + * recv() of the BSD socket API. + * + * @param[in] hd Server instance data + * @param[in] sockfd Socket descriptor for sending data + * @param[out] buf Pointer to the buffer which will be filled with the received data + * @param[in] buf_len Length of the buffer + * @param[in] flags Flags for mode selection + * + * @return + * - Length of data : if successful + * - -1 : if failed (appropriate errno is set) + */ +int httpd_default_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags); + +/** End of Group : Send and Receive + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! _HTTPD_PRIV_H_ */ diff --git a/components/esp_http_server/src/httpd_main.c b/components/esp_http_server/src/httpd_main.c new file mode 100644 index 000000000..5724383aa --- /dev/null +++ b/components/esp_http_server/src/httpd_main.c @@ -0,0 +1,426 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "esp_httpd_priv.h" +#include "ctrl_sock.h" + +static const char *TAG = "httpd"; + +static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd) +{ + /* If no space is available for new session, close the least recently used one */ + if (hd->config.lru_purge_enable == true) { + if (!httpd_is_sess_available(hd)) { + /* Queue asynchronous closure of the least recently used session */ + return httpd_sess_close_lru(hd); + /* Returning from this allowes the main server thread to process + * the queued asynchronous control message for closing LRU session. + * Since connection request hasn't been addressed yet using accept() + * therefore httpd_accept_conn() will be called again, but this time + * with space available for one session + */ + } + } + + struct sockaddr_in addr_from; + socklen_t addr_from_len = sizeof(addr_from); + int new_fd = accept(listen_fd, (struct sockaddr *)&addr_from, &addr_from_len); + if (new_fd < 0) { + ESP_LOGW(TAG, LOG_FMT("error in accept (%d)"), errno); + return ESP_FAIL; + } + ESP_LOGD(TAG, LOG_FMT("newfd = %d"), new_fd); + + struct timeval tv; + /* Set recv timeout of this fd as per config */ + tv.tv_sec = hd->config.recv_wait_timeout; + tv.tv_usec = 0; + setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)); + + /* Set send timeout of this fd as per config */ + tv.tv_sec = hd->config.send_wait_timeout; + tv.tv_usec = 0; + setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv)); + + if (ESP_OK != httpd_sess_new(hd, new_fd)) { + ESP_LOGW(TAG, LOG_FMT("session creation failed")); + close(new_fd); + return ESP_FAIL; + } + ESP_LOGD(TAG, LOG_FMT("complete")); + return ESP_OK; +} + +struct httpd_ctrl_data { + enum httpd_ctrl_msg { + HTTPD_CTRL_SHUTDOWN, + HTTPD_CTRL_WORK, + } hc_msg; + httpd_work_fn_t hc_work; + void *hc_work_arg; +}; + +esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *arg) +{ + if (handle == NULL || work == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_data *hd = (struct httpd_data *) handle; + struct httpd_ctrl_data msg = { + .hc_msg = HTTPD_CTRL_WORK, + .hc_work = work, + .hc_work_arg = arg, + }; + + int ret = cs_send_to_ctrl_sock(hd->msg_fd, hd->config.ctrl_port, &msg, sizeof(msg)); + if (ret < 0) { + ESP_LOGW(TAG, LOG_FMT("failed to queue work")); + return ESP_FAIL; + } + + return ESP_OK; +} + +void *httpd_get_global_user_ctx(httpd_handle_t handle) +{ + return ((struct httpd_data *)handle)->config.global_user_ctx; +} + +void *httpd_get_global_transport_ctx(httpd_handle_t handle) +{ + return ((struct httpd_data *)handle)->config.global_transport_ctx; +} + +static void httpd_close_all_sessions(struct httpd_data *hd) +{ + int fd = -1; + while ((fd = httpd_sess_iterate(hd, fd)) != -1) { + ESP_LOGD(TAG, LOG_FMT("cleaning up socket %d"), fd); + httpd_sess_delete(hd, fd); + close(fd); + } +} + +static void httpd_process_ctrl_msg(struct httpd_data *hd) +{ + struct httpd_ctrl_data msg; + int ret = recv(hd->ctrl_fd, &msg, sizeof(msg), 0); + if (ret <= 0) { + ESP_LOGW(TAG, LOG_FMT("error in recv (%d)"), errno); + return; + } + if (ret != sizeof(msg)) { + ESP_LOGW(TAG, LOG_FMT("incomplete msg")); + return; + } + + switch (msg.hc_msg) { + case HTTPD_CTRL_WORK: + if (msg.hc_work) { + ESP_LOGD(TAG, LOG_FMT("work")); + (*msg.hc_work)(msg.hc_work_arg); + } + break; + case HTTPD_CTRL_SHUTDOWN: + ESP_LOGD(TAG, LOG_FMT("shutdown")); + hd->hd_td.status = THREAD_STOPPING; + break; + default: + break; + } +} + +/* Manage in-coming connection or data requests */ +static esp_err_t httpd_server(struct httpd_data *hd) +{ + fd_set read_set; + FD_ZERO(&read_set); + FD_SET(hd->listen_fd, &read_set); + FD_SET(hd->ctrl_fd, &read_set); + + int tmp_max_fd; + httpd_sess_set_descriptors(hd, &read_set, &tmp_max_fd); + int maxfd = MAX(hd->listen_fd, tmp_max_fd); + tmp_max_fd = maxfd; + maxfd = MAX(hd->ctrl_fd, tmp_max_fd); + + ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1); + int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL); + if (active_cnt < 0) { + ESP_LOGE(TAG, LOG_FMT("error in select (%d)"), errno); + httpd_sess_delete_invalid(hd); + return ESP_OK; + } + + /* Case0: Do we have a control message? */ + if (FD_ISSET(hd->ctrl_fd, &read_set)) { + ESP_LOGD(TAG, LOG_FMT("processing ctrl message")); + httpd_process_ctrl_msg(hd); + if (hd->hd_td.status == THREAD_STOPPING) { + ESP_LOGD(TAG, LOG_FMT("stopping thread")); + return ESP_FAIL; + } + } + + /* Case1: Do we have any activity on the current data + * sessions? */ + int fd = -1; + while ((fd = httpd_sess_iterate(hd, fd)) != -1) { + if (FD_ISSET(fd, &read_set) || (httpd_sess_pending(hd, fd))) { + ESP_LOGD(TAG, LOG_FMT("processing socket %d"), fd); + if (httpd_sess_process(hd, fd) != ESP_OK) { + ESP_LOGD(TAG, LOG_FMT("closing socket %d"), fd); + close(fd); + /* Delete session and update fd to that + * preceding the one being deleted */ + fd = httpd_sess_delete(hd, fd); + } + } + } + + /* Case2: Do we have any incoming connection requests to + * process? */ + if (FD_ISSET(hd->listen_fd, &read_set)) { + ESP_LOGD(TAG, LOG_FMT("processing listen socket %d"), hd->listen_fd); + if (httpd_accept_conn(hd, hd->listen_fd) != ESP_OK) { + ESP_LOGW(TAG, LOG_FMT("error accepting new connection")); + } + } + return ESP_OK; +} + +/* The main HTTPD thread */ +static void httpd_thread(void *arg) +{ + int ret; + struct httpd_data *hd = (struct httpd_data *) arg; + hd->hd_td.status = THREAD_RUNNING; + + ESP_LOGD(TAG, LOG_FMT("web server started")); + while (1) { + ret = httpd_server(hd); + if (ret != ESP_OK) { + break; + } + } + + ESP_LOGD(TAG, LOG_FMT("web server exiting")); + close(hd->msg_fd); + cs_free_ctrl_sock(hd->ctrl_fd); + httpd_close_all_sessions(hd); + close(hd->listen_fd); + hd->hd_td.status = THREAD_STOPPED; + httpd_os_thread_delete(); +} + +static esp_err_t httpd_server_init(struct httpd_data *hd) +{ +#ifdef CONFIG_LWIP_IPV6 + int fd = socket(PF_INET6, SOCK_STREAM, 0); +#else + int fd = socket(PF_INET, SOCK_STREAM, 0); +#endif /* CONFIG_LWIP_IPV6 */ + if (fd < 0) { + ESP_LOGE(TAG, LOG_FMT("error in socket (%d)"), errno); + return ESP_FAIL; + } + +#ifdef CONFIG_LWIP_IPV6 + struct in6_addr inaddr_any = IN6ADDR_ANY_INIT; + struct sockaddr_in6 serv_addr = { + .sin6_family = PF_INET6, + .sin6_addr = inaddr_any, + .sin6_port = htons(hd->config.server_port) + }; +#else + struct sockaddr_in serv_addr = { + .sin_family = PF_INET, + .sin_addr = { + .s_addr = htonl(INADDR_ANY) + }, + .sin_port = htons(hd->config.server_port) + }; +#endif /* CONFIG_LWIP_IPV6 */ + + /* Enable SO_REUSEADDR to allow binding to the same + * address and port when restarting the server */ + int enable = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { + /* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But + * it does not affect the normal working of the HTTP Server */ + ESP_LOGW(TAG, LOG_FMT("error in setsockopt SO_REUSEADDR (%d)"), errno); + } + + int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); + if (ret < 0) { + ESP_LOGE(TAG, LOG_FMT("error in bind (%d)"), errno); + close(fd); + return ESP_FAIL; + } + + ret = listen(fd, hd->config.backlog_conn); + if (ret < 0) { + ESP_LOGE(TAG, LOG_FMT("error in listen (%d)"), errno); + close(fd); + return ESP_FAIL; + } + + int ctrl_fd = cs_create_ctrl_sock(hd->config.ctrl_port); + if (ctrl_fd < 0) { + ESP_LOGE(TAG, LOG_FMT("error in creating ctrl socket (%d)"), errno); + close(fd); + return ESP_FAIL; + } + + int msg_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (msg_fd < 0) { + ESP_LOGE(TAG, LOG_FMT("error in creating msg socket (%d)"), errno); + close(fd); + close(ctrl_fd); + return ESP_FAIL; + } + + hd->listen_fd = fd; + hd->ctrl_fd = ctrl_fd; + hd->msg_fd = msg_fd; + return ESP_OK; +} + +static struct httpd_data *httpd_create(const httpd_config_t *config) +{ + /* Allocate memory for httpd instance data */ + struct httpd_data *hd = calloc(1, sizeof(struct httpd_data)); + if (hd != NULL) { + hd->hd_calls = calloc(config->max_uri_handlers, sizeof(httpd_uri_t *)); + if (hd->hd_calls == NULL) { + free(hd); + return NULL; + } + hd->hd_sd = calloc(config->max_open_sockets, sizeof(struct sock_db)); + if (hd->hd_sd == NULL) { + free(hd->hd_calls); + free(hd); + return NULL; + } + struct httpd_req_aux *ra = &hd->hd_req_aux; + ra->resp_hdrs = calloc(config->max_resp_headers, sizeof(struct resp_hdr)); + if (ra->resp_hdrs == NULL) { + free(hd->hd_sd); + free(hd->hd_calls); + free(hd); + return NULL; + } + /* Save the configuration for this instance */ + hd->config = *config; + } else { + ESP_LOGE(TAG, "mem alloc failed"); + } + return hd; +} + +static void httpd_delete(struct httpd_data *hd) +{ + struct httpd_req_aux *ra = &hd->hd_req_aux; + /* Free memory of httpd instance data */ + free(ra->resp_hdrs); + free(hd->hd_sd); + + /* Free registered URI handlers */ + httpd_unregister_all_uri_handlers(hd); + free(hd->hd_calls); + free(hd); +} + +esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config) +{ + if (handle == NULL || config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_data *hd = httpd_create(config); + if (hd == NULL) { + /* Failed to allocate memory */ + return ESP_ERR_HTTPD_ALLOC_MEM; + } + + if (httpd_server_init(hd) != ESP_OK) { + httpd_delete(hd); + return ESP_FAIL; + } + + httpd_sess_init(hd); + if (httpd_os_thread_create(&hd->hd_td.handle, "httpd", + hd->config.stack_size, + hd->config.task_priority, + httpd_thread, hd) != ESP_OK) { + /* Failed to launch task */ + httpd_delete(hd); + return ESP_ERR_HTTPD_TASK; + } + + *handle = (httpd_handle_t *)hd; + return ESP_OK; +} + +esp_err_t httpd_stop(httpd_handle_t handle) +{ + struct httpd_data *hd = (struct httpd_data *) handle; + if (hd == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_ctrl_data msg; + memset(&msg, 0, sizeof(msg)); + msg.hc_msg = HTTPD_CTRL_SHUTDOWN; + cs_send_to_ctrl_sock(hd->msg_fd, hd->config.ctrl_port, &msg, sizeof(msg)); + + ESP_LOGD(TAG, LOG_FMT("sent control msg to stop server")); + while (hd->hd_td.status != THREAD_STOPPED) { + httpd_os_thread_sleep(100); + } + + /* Release global user context, if not NULL */ + if (hd->config.global_user_ctx) { + if (hd->config.global_user_ctx_free_fn) { + hd->config.global_user_ctx_free_fn(hd->config.global_user_ctx); + } else { + free(hd->config.global_user_ctx); + } + hd->config.global_user_ctx = NULL; + } + + /* Release global transport context, if not NULL */ + if (hd->config.global_transport_ctx) { + if (hd->config.global_transport_ctx_free_fn) { + hd->config.global_transport_ctx_free_fn(hd->config.global_transport_ctx); + } else { + free(hd->config.global_transport_ctx); + } + hd->config.global_transport_ctx = NULL; + } + + ESP_LOGD(TAG, LOG_FMT("server stopped")); + httpd_delete(hd); + return ESP_OK; +} diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c new file mode 100644 index 000000000..51843182d --- /dev/null +++ b/components/esp_http_server/src/httpd_parse.c @@ -0,0 +1,856 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include +#include + +#include +#include "esp_httpd_priv.h" +#include "osal.h" + +static const char *TAG = "httpd_parse"; + +typedef struct { + /* Parser settings for http_parser_execute() */ + http_parser_settings settings; + + /* Request being parsed */ + struct httpd_req *req; + + /* Status of the parser describes the part of the + * HTTP request packet being processed at any moment. + */ + enum { + PARSING_IDLE = 0, + PARSING_URL, + PARSING_HDR_FIELD, + PARSING_HDR_VALUE, + PARSING_BODY, + PARSING_COMPLETE, + PARSING_FAILED + } status; + + /* Response error code in case of PARSING_FAILED */ + httpd_err_resp_t error; + + /* For storing last callback parameters */ + struct { + const char *at; + size_t length; + } last; + + /* State variables */ + bool paused; /*!< Parser is paused */ + size_t pre_parsed; /*!< Length of data to be skipped while parsing */ + size_t raw_datalen; /*!< Full length of the raw data in scratch buffer */ +} parser_data_t; + +static esp_err_t verify_url (http_parser *parser) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + struct httpd_req *r = parser_data->req; + struct httpd_req_aux *ra = r->aux; + struct http_parser_url *res = &ra->url_parse_res; + + /* Get previous values of the parser callback arguments */ + const char *at = parser_data->last.at; + size_t length = parser_data->last.length; + + if ((r->method = parser->method) < 0) { + ESP_LOGW(TAG, LOG_FMT("HTTP Operation not supported")); + parser_data->error = HTTPD_501_METHOD_NOT_IMPLEMENTED; + return ESP_FAIL; + } + + if (sizeof(r->uri) < (length + 1)) { + ESP_LOGW(TAG, LOG_FMT("URI length (%d) greater than supported (%d)"), + length, sizeof(r->uri)); + parser_data->error = HTTPD_414_URI_TOO_LONG; + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + /* Keep URI with terminating null character. Note URI string pointed + * by 'at' is not NULL terminated, therefore use length provided by + * parser while copying the URI to buffer */ + strlcpy((char *)r->uri, at, (length + 1)); + ESP_LOGD(TAG, LOG_FMT("received URI = %s"), r->uri); + + /* Make sure version is HTTP/1.1 */ + if ((parser->http_major != 1) && (parser->http_minor != 1)) { + ESP_LOGW(TAG, LOG_FMT("unsupported HTTP version = %d.%d"), + parser->http_major, parser->http_minor); + parser_data->error = HTTPD_505_VERSION_NOT_SUPPORTED; + return ESP_FAIL; + } + + /* Parse URL and keep result for later */ + http_parser_url_init(res); + if (http_parser_parse_url(r->uri, strlen(r->uri), + r->method == HTTP_CONNECT, res)) { + ESP_LOGW(TAG, LOG_FMT("http_parser_parse_url failed with errno = %d"), + parser->http_errno); + parser_data->error = HTTPD_400_BAD_REQUEST; + return ESP_FAIL; + } + return ESP_OK; +} + +/* http_parser callback on finding url in HTTP request + * Will be invoked ATLEAST once every packet + */ +static esp_err_t cb_url(http_parser *parser, + const char *at, size_t length) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + + if (parser_data->status == PARSING_IDLE) { + ESP_LOGD(TAG, LOG_FMT("message begin")); + + /* Store current values of the parser callback arguments */ + parser_data->last.at = at; + parser_data->last.length = 0; + parser_data->status = PARSING_URL; + } else if (parser_data->status != PARSING_URL) { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("processing url = %.*s"), length, at); + + /* Update length of URL string */ + if ((parser_data->last.length += length) > HTTPD_MAX_URI_LEN) { + ESP_LOGW(TAG, LOG_FMT("URI length (%d) greater than supported (%d)"), + parser_data->last.length, HTTPD_MAX_URI_LEN); + parser_data->error = HTTPD_414_URI_TOO_LONG; + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t pause_parsing(http_parser *parser, const char* at) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + struct httpd_req *r = parser_data->req; + struct httpd_req_aux *ra = r->aux; + + parser_data->pre_parsed = parser_data->raw_datalen + - (at - ra->scratch); + + if (parser_data->pre_parsed != httpd_unrecv(r, at, parser_data->pre_parsed)) { + ESP_LOGE(TAG, LOG_FMT("data too large for un-recv = %d"), + parser_data->pre_parsed); + return ESP_FAIL; + } + + http_parser_pause(parser, 1); + parser_data->paused = true; + ESP_LOGD(TAG, LOG_FMT("paused")); + return ESP_OK; +} + +static size_t continue_parsing(http_parser *parser, size_t length) +{ + parser_data_t *data = (parser_data_t *) parser->data; + + /* Part of the blk may have been parsed before + * so we must skip that */ + length = MIN(length, data->pre_parsed); + data->pre_parsed -= length; + ESP_LOGD(TAG, LOG_FMT("skip pre-parsed data of size = %d"), length); + + http_parser_pause(parser, 0); + data->paused = false; + ESP_LOGD(TAG, LOG_FMT("un-paused")); + return length; +} + +/* http_parser callback on header field in HTTP request + * May be invoked ATLEAST once every header field + */ +static esp_err_t cb_header_field(http_parser *parser, const char *at, size_t length) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + struct httpd_req *r = parser_data->req; + struct httpd_req_aux *ra = r->aux; + + /* Check previous status */ + if (parser_data->status == PARSING_URL) { + if (verify_url(parser) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("headers begin")); + /* Last at is set to start of scratch where headers + * will be received next */ + parser_data->last.at = ra->scratch; + parser_data->last.length = 0; + parser_data->status = PARSING_HDR_FIELD; + + /* Stop parsing for now and give control to process */ + if (pause_parsing(parser, at) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + } else if (parser_data->status == PARSING_HDR_VALUE) { + /* NULL terminate last header (key: value) pair */ + size_t offset = parser_data->last.at - ra->scratch; + ra->scratch[offset + parser_data->last.length] = '\0'; + + /* Store current values of the parser callback arguments */ + parser_data->last.at = at; + parser_data->last.length = 0; + parser_data->status = PARSING_HDR_FIELD; + } else if (parser_data->status != PARSING_HDR_FIELD) { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("processing field = %.*s"), length, at); + + /* Update length of header string */ + parser_data->last.length += length; + return ESP_OK; +} + +/* http_parser callback on header value in HTTP request. + * May be invoked ATLEAST once every header value + */ +static esp_err_t cb_header_value(http_parser *parser, const char *at, size_t length) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + struct httpd_req *r = parser_data->req; + struct httpd_req_aux *ra = r->aux; + + /* Check previous status */ + if (parser_data->status == PARSING_HDR_FIELD) { + /* Store current values of the parser callback arguments */ + parser_data->last.at = at; + parser_data->last.length = 0; + parser_data->status = PARSING_HDR_VALUE; + /* Increment header count */ + ra->req_hdrs_count++; + } else if (parser_data->status != PARSING_HDR_VALUE) { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("processing value = %.*s"), length, at); + + /* Update length of header string */ + parser_data->last.length += length; + return ESP_OK; +} + +/* http_parser callback on completing headers in HTTP request. + * Will be invoked ONLY once every packet + */ +static esp_err_t cb_headers_complete(http_parser *parser) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + struct httpd_req *r = parser_data->req; + struct httpd_req_aux *ra = r->aux; + + /* Check previous status */ + if (parser_data->status == PARSING_URL) { + ESP_LOGD(TAG, LOG_FMT("no headers")); + if (verify_url(parser) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + } else if (parser_data->status == PARSING_HDR_VALUE) { + /* NULL terminate last header (key: value) pair */ + size_t offset = parser_data->last.at - ra->scratch; + ra->scratch[offset + parser_data->last.length] = '\0'; + + /* Reach end of last header */ + parser_data->last.at += parser_data->last.length; + } else { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + /* In absence of body/chunked encoding, http_parser sets content_len to -1 */ + r->content_len = ((int)parser->content_length != -1 ? + parser->content_length : 0); + + ESP_LOGD(TAG, LOG_FMT("bytes read = %d"), parser->nread); + ESP_LOGD(TAG, LOG_FMT("content length = %zu"), r->content_len); + + if (parser->upgrade) { + ESP_LOGW(TAG, LOG_FMT("upgrade from HTTP not supported")); + parser_data->error = HTTPD_XXX_UPGRADE_NOT_SUPPORTED; + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + parser_data->status = PARSING_BODY; + ra->remaining_len = r->content_len; + return ESP_OK; +} + +/* Last http_parser callback if body present in HTTP request. + * Will be invoked ONLY once every packet + */ +static esp_err_t cb_on_body(http_parser *parser, const char *at, size_t length) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + + /* Check previous status */ + if (parser_data->status != PARSING_BODY) { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + /* Pause parsing so that if part of another packet + * is in queue then it doesn't get parsed, which + * may reset the parser state and cause current + * request packet to be lost */ + if (pause_parsing(parser, at) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + parser_data->last.at = 0; + parser_data->last.length = 0; + parser_data->status = PARSING_COMPLETE; + ESP_LOGD(TAG, LOG_FMT("body begins")); + return ESP_OK; +} + +/* Last http_parser callback if body absent in HTTP request. + * Will be invoked ONLY once every packet + */ +static esp_err_t cb_no_body(http_parser *parser) +{ + parser_data_t *parser_data = (parser_data_t *) parser->data; + const char* at = parser_data->last.at; + + /* Check previous status */ + if (parser_data->status == PARSING_URL) { + ESP_LOGD(TAG, LOG_FMT("no headers")); + if (verify_url(parser) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + } else if (parser_data->status != PARSING_BODY) { + ESP_LOGE(TAG, LOG_FMT("unexpected state transition")); + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + /* Get end of packet */ + at += strlen("\r\n\r\n"); + + /* Pause parsing so that if part of another packet + * is in queue then it doesn't get parsed, which + * may reset the parser state and cause current + * request packet to be lost */ + if (pause_parsing(parser, at) != ESP_OK) { + parser_data->status = PARSING_FAILED; + return ESP_FAIL; + } + + parser_data->last.at = 0; + parser_data->last.length = 0; + parser_data->status = PARSING_COMPLETE; + ESP_LOGD(TAG, LOG_FMT("message complete")); + return ESP_OK; +} + +static int read_block(httpd_req_t *req, size_t offset, size_t length) +{ + struct httpd_req_aux *raux = req->aux; + + /* Limits the read to scratch buffer size */ + size_t buf_len = MIN(length, (sizeof(raux->scratch) - offset)); + if (buf_len == 0) { + return 0; + } + + /* Receive data into buffer. If data is pending (from unrecv) then return + * immediately after receiving pending data, as pending data may just complete + * this request packet. */ + int nbytes = httpd_recv_with_opt(req, raux->scratch + offset, buf_len, true); + if (nbytes < 0) { + ESP_LOGD(TAG, LOG_FMT("error in httpd_recv")); + if (nbytes == HTTPD_SOCK_ERR_TIMEOUT) { + httpd_resp_send_err(req, HTTPD_408_REQ_TIMEOUT); + } + return -1; + } else if (nbytes == 0) { + ESP_LOGD(TAG, LOG_FMT("connection closed")); + return -1; + } + + ESP_LOGD(TAG, LOG_FMT("received HTTP request block size = %d"), nbytes); + return nbytes; +} + +static int parse_block(http_parser *parser, size_t offset, size_t length) +{ + parser_data_t *data = (parser_data_t *)(parser->data); + httpd_req_t *req = data->req; + struct httpd_req_aux *raux = req->aux; + size_t nparsed = 0; + + if (!length) { + ESP_LOGW(TAG, LOG_FMT("response uri/header too big")); + switch (data->status) { + case PARSING_URL: + data->error = HTTPD_414_URI_TOO_LONG; + break; + case PARSING_HDR_FIELD: + case PARSING_HDR_VALUE: + data->error = HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE; + default: + break; + } + data->status = PARSING_FAILED; + return -1; + } + + /* Unpause the parsing if paused */ + if (data->paused) { + nparsed = continue_parsing(parser, length); + length -= nparsed; + offset += nparsed; + if (!length) { + return nparsed; + } + } + + /* Execute http_parser */ + nparsed = http_parser_execute(parser, &data->settings, + raux->scratch + offset, length); + + /* Check state */ + if (data->status == PARSING_FAILED) { + ESP_LOGW(TAG, LOG_FMT("parsing failed")); + return -1; + } else if (data->paused) { + /* Keep track of parsed data to be skipped + * during next parsing cycle */ + data->pre_parsed -= (length - nparsed); + return 0; + } else if (nparsed != length) { + /* http_parser error */ + data->status = PARSING_FAILED; + data->error = HTTPD_400_BAD_REQUEST; + ESP_LOGW(TAG, LOG_FMT("incomplete (%d/%d) with parser error = %d"), + nparsed, length, parser->http_errno); + return -1; + } + + /* Continue parsing this section of HTTP request packet */ + ESP_LOGD(TAG, LOG_FMT("parsed block size = %d"), offset + nparsed); + return offset + nparsed; +} + +static void parse_init(httpd_req_t *r, http_parser *parser, parser_data_t *data) +{ + /* Initialize parser data */ + memset(data, 0, sizeof(parser_data_t)); + data->req = r; + + /* Initialize parser */ + http_parser_init(parser, HTTP_REQUEST); + parser->data = (void *)data; + + /* Initialize parser settings */ + http_parser_settings_init(&data->settings); + + /* Set parser callbacks */ + data->settings.on_url = cb_url; + data->settings.on_header_field = cb_header_field; + data->settings.on_header_value = cb_header_value; + data->settings.on_headers_complete = cb_headers_complete; + data->settings.on_body = cb_on_body; + data->settings.on_message_complete = cb_no_body; +} + +/* Function that receives TCP data and runs parser on it + */ +static esp_err_t httpd_parse_req(struct httpd_data *hd) +{ + httpd_req_t *r = &hd->hd_req; + int blk_len, offset; + http_parser parser; + parser_data_t parser_data; + + /* Initialize parser */ + parse_init(r, &parser, &parser_data); + + /* Set offset to start of scratch buffer */ + offset = 0; + do { + /* Read block into scratch buffer */ + if ((blk_len = read_block(r, offset, PARSER_BLOCK_SIZE)) < 0) { + /* Return error to close socket */ + return ESP_FAIL; + } + + /* This is used by the callbacks to track + * data usage of the buffer */ + parser_data.raw_datalen = blk_len + offset; + + /* Parse data block from buffer */ + if ((offset = parse_block(&parser, offset, blk_len)) < 0) { + /* Server/Client error. Send error code as response status */ + return httpd_resp_send_err(r, parser_data.error); + } + } while (parser_data.status != PARSING_COMPLETE); + + ESP_LOGD(TAG, LOG_FMT("parsing complete")); + return httpd_uri(hd); +} + +static void init_req(httpd_req_t *r, httpd_config_t *config) +{ + r->handle = 0; + r->method = 0; + memset((char*)r->uri, 0, sizeof(r->uri)); + r->content_len = 0; + r->aux = 0; + r->user_ctx = 0; + r->sess_ctx = 0; + r->free_ctx = 0; +} + +static void init_req_aux(struct httpd_req_aux *ra, httpd_config_t *config) +{ + ra->sd = 0; + memset(ra->scratch, 0, sizeof(ra->scratch)); + ra->remaining_len = 0; + ra->status = 0; + ra->content_type = 0; + ra->first_chunk_sent = 0; + ra->req_hdrs_count = 0; + ra->resp_hdrs_count = 0; + memset(ra->resp_hdrs, 0, config->max_resp_headers * sizeof(struct resp_hdr)); +} + +static void httpd_req_cleanup(httpd_req_t *r) +{ + struct httpd_req_aux *ra = r->aux; + + /* Retrieve session info from the request into the socket database */ + if (ra->sd->ctx != r->sess_ctx) { + /* Free previous context */ + httpd_sess_free_ctx(ra->sd->ctx, ra->sd->free_ctx); + ra->sd->ctx = r->sess_ctx; + } + ra->sd->free_ctx = r->free_ctx; + + /* Clear out the request and request_aux structures */ + ra->sd = NULL; + r->handle = NULL; + r->aux = NULL; +} + +/* Function that processes incoming TCP data and + * updates the http request data httpd_req_t + */ +esp_err_t httpd_req_new(struct httpd_data *hd, struct sock_db *sd) +{ + httpd_req_t *r = &hd->hd_req; + init_req(r, &hd->config); + init_req_aux(&hd->hd_req_aux, &hd->config); + r->handle = hd; + r->aux = &hd->hd_req_aux; + /* Associate the request to the socket */ + struct httpd_req_aux *ra = r->aux; + ra->sd = sd; + /* Set defaults */ + ra->status = (char *)HTTPD_200; + ra->content_type = (char *)HTTPD_TYPE_TEXT; + ra->first_chunk_sent = false; + /* Copy session info to the request */ + r->sess_ctx = sd->ctx; + r->free_ctx = sd->free_ctx; + /* Parse request */ + esp_err_t err = httpd_parse_req(hd); + if (err != ESP_OK) { + httpd_req_cleanup(r); + } + return err; +} + +/* Function that resets the http request data + */ +esp_err_t httpd_req_delete(struct httpd_data *hd) +{ + httpd_req_t *r = &hd->hd_req; + struct httpd_req_aux *ra = r->aux; + + /* Finish off reading any pending/leftover data */ + while (ra->remaining_len) { + /* Any length small enough not to overload the stack, but large + * enough to finish off the buffers fast + */ + char dummy[32]; + int recv_len = MIN(sizeof(dummy) - 1, ra->remaining_len); + int ret = httpd_req_recv(r, dummy, recv_len); + if (ret < 0) { + httpd_req_cleanup(r); + return ESP_FAIL; + } + + dummy[ret] = '\0'; + ESP_LOGD(TAG, LOG_FMT("purging data : %s"), dummy); + } + + httpd_req_cleanup(r); + return ESP_OK; +} + +/* Validates the request to prevent users from calling APIs, that are to + * be called only inside URI handler, outside the handler context + */ +bool httpd_validate_req_ptr(httpd_req_t *r) +{ + if (r) { + struct httpd_data *hd = (struct httpd_data *) r->handle; + if (hd) { + /* Check if this function is running in the context of + * the correct httpd server thread */ + if (httpd_os_thread_handle() == hd->hd_td.handle) { + return true; + } + } + } + return false; +} + +/* Helper function to get a URL query tag from a query string of the type param1=val1¶m2=val2 */ +esp_err_t httpd_query_key_value(const char *qry_str, const char *key, char *val, size_t val_size) +{ + if (qry_str == NULL || key == NULL || val == NULL) { + return ESP_ERR_INVALID_ARG; + } + + const char *qry_ptr = qry_str; + const size_t buf_len = val_size; + + while (strlen(qry_ptr)) { + /* Search for the '=' character. Else, it would mean + * that the parameter is invalid */ + const char *val_ptr = strchr(qry_ptr, '='); + if (!val_ptr) { + break; + } + size_t offset = val_ptr - qry_ptr; + + /* If the key, does not match, continue searching. + * Compare lengths first as key from url is not + * null terminated (has '=' in the end) */ + if ((offset != strlen(key)) || + (strncasecmp(qry_ptr, key, offset))) { + /* Get the name=val string. Multiple name=value pairs + * are separated by '&' */ + qry_ptr = strchr(val_ptr, '&'); + if (!qry_ptr) { + break; + } + qry_ptr++; + continue; + } + + /* Locate start of next query */ + qry_ptr = strchr(++val_ptr, '&'); + /* Or this could be the last query, in which + * case get to the end of query string */ + if (!qry_ptr) { + qry_ptr = val_ptr + strlen(val_ptr); + } + + /* Update value length, including one byte for null */ + val_size = qry_ptr - val_ptr + 1; + + /* Copy value to the caller's buffer. */ + strlcpy(val, val_ptr, MIN(val_size, buf_len)); + + /* If buffer length is smaller than needed, return truncation error */ + if (buf_len < val_size) { + return ESP_ERR_HTTPD_RESULT_TRUNC; + } + return ESP_OK; + } + ESP_LOGD(TAG, LOG_FMT("key %s not found"), key); + return ESP_ERR_NOT_FOUND; +} + +size_t httpd_req_get_url_query_len(httpd_req_t *r) +{ + if (r == NULL) { + return 0; + } + + if (!httpd_valid_req(r)) { + return 0; + } + + struct httpd_req_aux *ra = r->aux; + struct http_parser_url *res = &ra->url_parse_res; + + /* Check if query field is present in the URL */ + if (res->field_set & (1 << UF_QUERY)) { + return res->field_data[UF_QUERY].len; + } + return 0; +} + +esp_err_t httpd_req_get_url_query_str(httpd_req_t *r, char *buf, size_t buf_len) +{ + if (r == NULL || buf == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + struct http_parser_url *res = &ra->url_parse_res; + + /* Check if query field is present in the URL */ + if (res->field_set & (1 << UF_QUERY)) { + const char *qry = r->uri + res->field_data[UF_QUERY].off; + + /* Minimum required buffer len for keeping + * null terminated query string */ + size_t min_buf_len = res->field_data[UF_QUERY].len + 1; + + strlcpy(buf, qry, MIN(buf_len, min_buf_len)); + if (buf_len < min_buf_len) { + return ESP_ERR_HTTPD_RESULT_TRUNC; + } + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; +} + +/* Get the length of the value string of a header request field */ +size_t httpd_req_get_hdr_value_len(httpd_req_t *r, const char *field) +{ + if (r == NULL || field == NULL) { + return 0; + } + + if (!httpd_valid_req(r)) { + return 0; + } + + struct httpd_req_aux *ra = r->aux; + const char *hdr_ptr = ra->scratch; /*!< Request headers are kept in scratch buffer */ + unsigned count = ra->req_hdrs_count; /*!< Count set during parsing */ + + while (count--) { + /* Search for the ':' character. Else, it would mean + * that the field is invalid + */ + const char *val_ptr = strchr(hdr_ptr, ':'); + if (!val_ptr) { + break; + } + + /* If the field, does not match, continue searching. + * Compare lengths first as field from header is not + * null terminated (has ':' in the end). + */ + if ((val_ptr - hdr_ptr != strlen(field)) || + (strncasecmp(hdr_ptr, field, strlen(field)))) { + hdr_ptr += strlen(hdr_ptr) + strlen("\r\n"); + continue; + } + /* Skip ':' */ + val_ptr++; + + /* Skip preceding space */ + while ((*val_ptr != '\0') && (*val_ptr == ' ')) { + val_ptr++; + } + return strlen(val_ptr); + } + return 0; +} + +/* Get the value of a field from the request headers */ +esp_err_t httpd_req_get_hdr_value_str(httpd_req_t *r, const char *field, char *val, size_t val_size) +{ + if (r == NULL || field == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + const char *hdr_ptr = ra->scratch; /*!< Request headers are kept in scratch buffer */ + unsigned count = ra->req_hdrs_count; /*!< Count set during parsing */ + const size_t buf_len = val_size; + + while (count--) { + /* Search for the ':' character. Else, it would mean + * that the field is invalid + */ + const char *val_ptr = strchr(hdr_ptr, ':'); + if (!val_ptr) { + break; + } + + /* If the field, does not match, continue searching. + * Compare lengths first as field from header is not + * null terminated (has ':' in the end). + */ + if ((val_ptr - hdr_ptr != strlen(field)) || + (strncasecmp(hdr_ptr, field, strlen(field)))) { + hdr_ptr += strlen(hdr_ptr) + strlen("\r\n"); + continue; + } + + /* Skip ':' */ + val_ptr++; + + /* Skip preceding space */ + while ((*val_ptr != '\0') && (*val_ptr == ' ')) { + val_ptr++; + } + + /* Get the NULL terminated value and copy it to the caller's buffer. */ + strlcpy(val, val_ptr, buf_len); + + /* Update value length, including one byte for null */ + val_size = strlen(val_ptr) + 1; + + /* If buffer length is smaller than needed, return truncation error */ + if (buf_len < val_size) { + return ESP_ERR_HTTPD_RESULT_TRUNC; + } + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; +} diff --git a/components/esp_http_server/src/httpd_sess.c b/components/esp_http_server/src/httpd_sess.c new file mode 100644 index 000000000..0f722211a --- /dev/null +++ b/components/esp_http_server/src/httpd_sess.c @@ -0,0 +1,393 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include + +#include +#include "esp_httpd_priv.h" +#include + +static const char *TAG = "httpd_sess"; + +bool httpd_is_sess_available(struct httpd_data *hd) +{ + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == -1) { + return true; + } + } + return false; +} + +struct sock_db *httpd_sess_get(struct httpd_data *hd, int sockfd) +{ + if (hd == NULL) { + return NULL; + } + + /* Check if called inside a request handler, and the + * session sockfd in use is same as the parameter */ + if ((hd->hd_req_aux.sd) && (hd->hd_req_aux.sd->fd == sockfd)) { + /* Just return the pointer to the sock_db + * corresponding to the request */ + return hd->hd_req_aux.sd; + } + + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == sockfd) { + return &hd->hd_sd[i]; + } + } + return NULL; +} + +esp_err_t httpd_sess_new(struct httpd_data *hd, int newfd) +{ + ESP_LOGD(TAG, LOG_FMT("fd = %d"), newfd); + + if (httpd_sess_get(hd, newfd)) { + ESP_LOGE(TAG, LOG_FMT("session already exists with fd = %d"), newfd); + return ESP_FAIL; + } + + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == -1) { + memset(&hd->hd_sd[i], 0, sizeof(hd->hd_sd[i])); + hd->hd_sd[i].fd = newfd; + hd->hd_sd[i].handle = (httpd_handle_t) hd; + hd->hd_sd[i].send_fn = httpd_default_send; + hd->hd_sd[i].recv_fn = httpd_default_recv; + + /* Call user-defined session opening function */ + if (hd->config.open_fn) { + esp_err_t ret = hd->config.open_fn(hd, hd->hd_sd[i].fd); + if (ret != ESP_OK) return ret; + } + return ESP_OK; + } + } + ESP_LOGD(TAG, LOG_FMT("unable to launch session for fd = %d"), newfd); + return ESP_FAIL; +} + +void httpd_sess_free_ctx(void *ctx, httpd_free_ctx_fn_t free_fn) +{ + if (ctx) { + if (free_fn) { + free_fn(ctx); + } else { + free(ctx); + } + } +} + +void *httpd_sess_get_ctx(httpd_handle_t handle, int sockfd) +{ + struct sock_db *sd = httpd_sess_get(handle, sockfd); + if (sd == NULL) { + return NULL; + } + + /* Check if the function has been called from inside a + * request handler, in which case fetch the context from + * the httpd_req_t structure */ + struct httpd_data *hd = (struct httpd_data *) handle; + if (hd->hd_req_aux.sd == sd) { + return hd->hd_req.sess_ctx; + } + + return sd->ctx; +} + +void httpd_sess_set_ctx(httpd_handle_t handle, int sockfd, void *ctx, httpd_free_ctx_fn_t free_fn) +{ + struct sock_db *sd = httpd_sess_get(handle, sockfd); + if (sd == NULL) { + return; + } + + /* Check if the function has been called from inside a + * request handler, in which case set the context inside + * the httpd_req_t structure */ + struct httpd_data *hd = (struct httpd_data *) handle; + if (hd->hd_req_aux.sd == sd) { + if (hd->hd_req.sess_ctx != ctx) { + /* Don't free previous context if it is in sockdb + * as it will be freed inside httpd_req_cleanup() */ + if (sd->ctx != hd->hd_req.sess_ctx) { + /* Free previous context */ + httpd_sess_free_ctx(hd->hd_req.sess_ctx, hd->hd_req.free_ctx); + } + hd->hd_req.sess_ctx = ctx; + } + hd->hd_req.free_ctx = free_fn; + return; + } + + /* Else set the context inside the sock_db structure */ + if (sd->ctx != ctx) { + /* Free previous context */ + httpd_sess_free_ctx(sd->ctx, sd->free_ctx); + sd->ctx = ctx; + } + sd->free_ctx = free_fn; +} + +void *httpd_sess_get_transport_ctx(httpd_handle_t handle, int sockfd) +{ + struct sock_db *sd = httpd_sess_get(handle, sockfd); + if (sd == NULL) { + return NULL; + } + + return sd->transport_ctx; +} + +void httpd_sess_set_transport_ctx(httpd_handle_t handle, int sockfd, void *ctx, httpd_free_ctx_fn_t free_fn) +{ + struct sock_db *sd = httpd_sess_get(handle, sockfd); + if (sd == NULL) { + return; + } + + if (sd->transport_ctx != ctx) { + /* Free previous transport context */ + httpd_sess_free_ctx(sd->transport_ctx, sd->free_transport_ctx); + sd->transport_ctx = ctx; + } + sd->free_transport_ctx = free_fn; +} + +void httpd_sess_set_descriptors(struct httpd_data *hd, + fd_set *fdset, int *maxfd) +{ + int i; + *maxfd = -1; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd != -1) { + FD_SET(hd->hd_sd[i].fd, fdset); + if (hd->hd_sd[i].fd > *maxfd) { + *maxfd = hd->hd_sd[i].fd; + } + } + } +} + +/** Check if a FD is valid */ +static int fd_is_valid(int fd) +{ + return fcntl(fd, F_GETFD, 0) != -1 || errno != EBADF; +} + +static inline uint64_t httpd_sess_get_lru_counter() +{ + static uint64_t lru_counter = 0; + return lru_counter++; +} + +void httpd_sess_delete_invalid(struct httpd_data *hd) +{ + for (int i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd != -1 && !fd_is_valid(hd->hd_sd[i].fd)) { + ESP_LOGW(TAG, LOG_FMT("Closing invalid socket %d"), hd->hd_sd[i].fd); + httpd_sess_delete(hd, hd->hd_sd[i].fd); + } + } +} + +int httpd_sess_delete(struct httpd_data *hd, int fd) +{ + ESP_LOGD(TAG, LOG_FMT("fd = %d"), fd); + int i; + int pre_sess_fd = -1; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == fd) { + /* global close handler */ + if (hd->config.close_fn) { + hd->config.close_fn(hd, fd); + } + + /* release 'user' context */ + if (hd->hd_sd[i].ctx) { + if (hd->hd_sd[i].free_ctx) { + hd->hd_sd[i].free_ctx(hd->hd_sd[i].ctx); + } else { + free(hd->hd_sd[i].ctx); + } + hd->hd_sd[i].ctx = NULL; + hd->hd_sd[i].free_ctx = NULL; + } + + /* release 'transport' context */ + if (hd->hd_sd[i].transport_ctx) { + if (hd->hd_sd[i].free_transport_ctx) { + hd->hd_sd[i].free_transport_ctx(hd->hd_sd[i].transport_ctx); + } else { + free(hd->hd_sd[i].transport_ctx); + } + hd->hd_sd[i].transport_ctx = NULL; + hd->hd_sd[i].free_transport_ctx = NULL; + } + + /* mark session slot as available */ + hd->hd_sd[i].fd = -1; + break; + } else if (hd->hd_sd[i].fd != -1) { + /* Return the fd just preceding the one being + * deleted so that iterator can continue from + * the correct fd */ + pre_sess_fd = hd->hd_sd[i].fd; + } + } + return pre_sess_fd; +} + +void httpd_sess_init(struct httpd_data *hd) +{ + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + hd->hd_sd[i].fd = -1; + hd->hd_sd[i].ctx = NULL; + } +} + +bool httpd_sess_pending(struct httpd_data *hd, int fd) +{ + struct sock_db *sd = httpd_sess_get(hd, fd); + if (! sd) { + return ESP_FAIL; + } + + if (sd->pending_fn) { + // test if there's any data to be read (besides read() function, which is handled by select() in the main httpd loop) + // this should check e.g. for the SSL data buffer + if (sd->pending_fn(hd, fd) > 0) return true; + } + + return (sd->pending_len != 0); +} + +/* This MUST return ESP_OK on successful execution. If any other + * value is returned, everything related to this socket will be + * cleaned up and the socket will be closed. + */ +esp_err_t httpd_sess_process(struct httpd_data *hd, int newfd) +{ + struct sock_db *sd = httpd_sess_get(hd, newfd); + if (! sd) { + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("httpd_req_new")); + if (httpd_req_new(hd, sd) != ESP_OK) { + return ESP_FAIL; + } + ESP_LOGD(TAG, LOG_FMT("httpd_req_delete")); + if (httpd_req_delete(hd) != ESP_OK) { + return ESP_FAIL; + } + ESP_LOGD(TAG, LOG_FMT("success")); + sd->lru_counter = httpd_sess_get_lru_counter(); + return ESP_OK; +} + +esp_err_t httpd_sess_update_lru_counter(httpd_handle_t handle, int sockfd) +{ + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Search for the socket database entry */ + struct httpd_data *hd = (struct httpd_data *) handle; + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == sockfd) { + hd->hd_sd[i].lru_counter = httpd_sess_get_lru_counter(); + return ESP_OK; + } + } + return ESP_ERR_NOT_FOUND; +} + +esp_err_t httpd_sess_close_lru(struct httpd_data *hd) +{ + uint64_t lru_counter = UINT64_MAX; + int lru_fd = -1; + int i; + for (i = 0; i < hd->config.max_open_sockets; i++) { + /* If a descriptor is -1, there is no need to close any session. + * So, we can return from here, without finding the Least Recently Used + * session + */ + if (hd->hd_sd[i].fd == -1) { + return ESP_OK; + } + if (hd->hd_sd[i].lru_counter < lru_counter) { + lru_counter = hd->hd_sd[i].lru_counter; + lru_fd = hd->hd_sd[i].fd; + } + } + ESP_LOGD(TAG, LOG_FMT("fd = %d"), lru_fd); + return httpd_sess_trigger_close(hd, lru_fd); +} + +int httpd_sess_iterate(struct httpd_data *hd, int start_fd) +{ + int start_index = 0; + int i; + + if (start_fd != -1) { + /* Take our index to where this fd is stored */ + for (i = 0; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd == start_fd) { + start_index = i + 1; + break; + } + } + } + + for (i = start_index; i < hd->config.max_open_sockets; i++) { + if (hd->hd_sd[i].fd != -1) { + return hd->hd_sd[i].fd; + } + } + return -1; +} + +static void httpd_sess_close(void *arg) +{ + struct sock_db *sock_db = (struct sock_db *)arg; + if (sock_db) { + int fd = sock_db->fd; + struct httpd_data *hd = (struct httpd_data *) sock_db->handle; + httpd_sess_delete(hd, fd); + close(fd); + } +} + +esp_err_t httpd_sess_trigger_close(httpd_handle_t handle, int sockfd) +{ + struct sock_db *sock_db = httpd_sess_get(handle, sockfd); + if (sock_db) { + return httpd_queue_work(handle, httpd_sess_close, sock_db); + } + + return ESP_ERR_NOT_FOUND; +} diff --git a/components/esp_http_server/src/httpd_txrx.c b/components/esp_http_server/src/httpd_txrx.c new file mode 100644 index 000000000..69a5ba004 --- /dev/null +++ b/components/esp_http_server/src/httpd_txrx.c @@ -0,0 +1,553 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include + +#include +#include "esp_httpd_priv.h" + +static const char *TAG = "httpd_txrx"; + +esp_err_t httpd_sess_set_send_override(httpd_handle_t hd, int sockfd, httpd_send_func_t send_func) +{ + struct sock_db *sess = httpd_sess_get(hd, sockfd); + if (!sess) { + return ESP_ERR_INVALID_ARG; + } + sess->send_fn = send_func; + return ESP_OK; +} + +esp_err_t httpd_sess_set_recv_override(httpd_handle_t hd, int sockfd, httpd_recv_func_t recv_func) +{ + struct sock_db *sess = httpd_sess_get(hd, sockfd); + if (!sess) { + return ESP_ERR_INVALID_ARG; + } + sess->recv_fn = recv_func; + return ESP_OK; +} + +esp_err_t httpd_sess_set_pending_override(httpd_handle_t hd, int sockfd, httpd_pending_func_t pending_func) +{ + struct sock_db *sess = httpd_sess_get(hd, sockfd); + if (!sess) { + return ESP_ERR_INVALID_ARG; + } + sess->pending_fn = pending_func; + return ESP_OK; +} + +int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len) +{ + if (r == NULL || buf == NULL) { + return HTTPD_SOCK_ERR_INVALID; + } + + if (!httpd_valid_req(r)) { + return HTTPD_SOCK_ERR_INVALID; + } + + struct httpd_req_aux *ra = r->aux; + int ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0); + if (ret < 0) { + ESP_LOGD(TAG, LOG_FMT("error in send_fn")); + return ret; + } + return ret; +} + +static esp_err_t httpd_send_all(httpd_req_t *r, const char *buf, size_t buf_len) +{ + struct httpd_req_aux *ra = r->aux; + int ret; + + while (buf_len > 0) { + ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0); + if (ret < 0) { + ESP_LOGD(TAG, LOG_FMT("error in send_fn")); + return ESP_FAIL; + } + ESP_LOGD(TAG, LOG_FMT("sent = %d"), ret); + buf += ret; + buf_len -= ret; + } + return ESP_OK; +} + +static size_t httpd_recv_pending(httpd_req_t *r, char *buf, size_t buf_len) +{ + struct httpd_req_aux *ra = r->aux; + size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len; + + /* buf_len must not be greater than remaining_len */ + buf_len = MIN(ra->sd->pending_len, buf_len); + memcpy(buf, ra->sd->pending_data + offset, buf_len); + + ra->sd->pending_len -= buf_len; + return buf_len; +} + +int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending) +{ + ESP_LOGD(TAG, LOG_FMT("requested length = %d"), buf_len); + + size_t pending_len = 0; + struct httpd_req_aux *ra = r->aux; + + /* First fetch pending data from local buffer */ + if (ra->sd->pending_len > 0) { + ESP_LOGD(TAG, LOG_FMT("pending length = %d"), ra->sd->pending_len); + pending_len = httpd_recv_pending(r, buf, buf_len); + buf += pending_len; + buf_len -= pending_len; + + /* If buffer filled then no need to recv. + * If asked to halt after receiving pending data then + * return with received length */ + if (!buf_len || halt_after_pending) { + return pending_len; + } + } + + /* Receive data of remaining length */ + int ret = ra->sd->recv_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0); + if (ret < 0) { + ESP_LOGD(TAG, LOG_FMT("error in recv_fn")); + if ((ret == HTTPD_SOCK_ERR_TIMEOUT) && (pending_len != 0)) { + /* If recv() timeout occurred, but pending data is + * present, return length of pending data. + * This behavior is similar to that of socket recv() + * function, which, in case has only partially read the + * requested length, due to timeout, returns with read + * length, rather than error */ + return pending_len; + } + return ret; + } + + ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len); + return ret + pending_len; +} + +int httpd_recv(httpd_req_t *r, char *buf, size_t buf_len) +{ + return httpd_recv_with_opt(r, buf, buf_len, false); +} + +size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len) +{ + struct httpd_req_aux *ra = r->aux; + /* Truncate if external buf_len is greater than pending_data buffer size */ + ra->sd->pending_len = MIN(sizeof(ra->sd->pending_data), buf_len); + + /* Copy data into internal pending_data buffer */ + size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len; + memcpy(ra->sd->pending_data + offset, buf, buf_len); + ESP_LOGD(TAG, LOG_FMT("length = %d"), ra->sd->pending_len); + return ra->sd->pending_len; +} + +/** + * This API appends an additional header field-value pair in the HTTP response. + * But the header isn't sent out until any of the send APIs is executed. + */ +esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value) +{ + if (r == NULL || field == NULL || value == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + struct httpd_data *hd = (struct httpd_data *) r->handle; + + /* Number of additional headers is limited */ + if (ra->resp_hdrs_count >= hd->config.max_resp_headers) { + return ESP_ERR_HTTPD_RESP_HDR; + } + + /* Assign header field-value pair */ + ra->resp_hdrs[ra->resp_hdrs_count].field = field; + ra->resp_hdrs[ra->resp_hdrs_count].value = value; + ra->resp_hdrs_count++; + + ESP_LOGD(TAG, LOG_FMT("new header = %s: %s"), field, value); + return ESP_OK; +} + +/** + * This API sets the status of the HTTP response to the value specified. + * But the status isn't sent out until any of the send APIs is executed. + */ +esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status) +{ + if (r == NULL || status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + ra->status = (char *)status; + return ESP_OK; +} + +/** + * This API sets the method/type of the HTTP response to the value specified. + * But the method isn't sent out until any of the send APIs is executed. + */ +esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type) +{ + if (r == NULL || type == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + ra->content_type = (char *)type; + return ESP_OK; +} + +esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len) +{ + if (r == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + struct httpd_req_aux *ra = r->aux; + const char *httpd_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n"; + const char *colon_separator = ": "; + const char *cr_lf_seperator = "\r\n"; + + if (buf_len == -1) buf_len = strlen(buf); + + /* Request headers are no longer available */ + ra->req_hdrs_count = 0; + + /* Size of essential headers is limited by scratch buffer size */ + if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_hdr_str, + ra->status, ra->content_type, buf_len) >= sizeof(ra->scratch)) { + return ESP_ERR_HTTPD_RESP_HDR; + } + + /* Sending essential headers */ + if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + + /* Sending additional headers based on set_header */ + for (unsigned i = 0; i < ra->resp_hdrs_count; i++) { + /* Send header field */ + if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send ': ' */ + if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send header value */ + if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send CR + LF */ + if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + } + + /* End header section */ + if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + + /* Sending content */ + if (buf && buf_len) { + if (httpd_send_all(r, buf, buf_len) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + } + return ESP_OK; +} + +esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len) +{ + if (r == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!httpd_valid_req(r)) { + return ESP_ERR_HTTPD_INVALID_REQ; + } + + if (buf_len == -1) buf_len = strlen(buf); + + struct httpd_req_aux *ra = r->aux; + const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunked\r\n"; + const char *colon_separator = ": "; + const char *cr_lf_seperator = "\r\n"; + + /* Request headers are no longer available */ + ra->req_hdrs_count = 0; + + if (!ra->first_chunk_sent) { + /* Size of essential headers is limited by scratch buffer size */ + if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_chunked_hdr_str, + ra->status, ra->content_type) >= sizeof(ra->scratch)) { + return ESP_ERR_HTTPD_RESP_HDR; + } + + /* Sending essential headers */ + if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + + /* Sending additional headers based on set_header */ + for (unsigned i = 0; i < ra->resp_hdrs_count; i++) { + /* Send header field */ + if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send ': ' */ + if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send header value */ + if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + /* Send CR + LF */ + if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + } + + /* End header section */ + if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + ra->first_chunk_sent = true; + } + + /* Sending chunked content */ + char len_str[10]; + snprintf(len_str, sizeof(len_str), "%x\r\n", buf_len); + if (httpd_send_all(r, len_str, strlen(len_str)) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + + if (buf) { + if (httpd_send_all(r, buf, (size_t) buf_len) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + } + + /* Indicate end of chunk */ + if (httpd_send_all(r, "\r\n", strlen("\r\n")) != ESP_OK) { + return ESP_ERR_HTTPD_RESP_SEND; + } + return ESP_OK; +} + +esp_err_t httpd_resp_send_404(httpd_req_t *r) +{ + return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND); +} + +esp_err_t httpd_resp_send_408(httpd_req_t *r) +{ + return httpd_resp_send_err(r, HTTPD_408_REQ_TIMEOUT); +} + +esp_err_t httpd_resp_send_500(httpd_req_t *r) +{ + return httpd_resp_send_err(r, HTTPD_500_SERVER_ERROR); +} + +esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error) +{ + const char *msg; + const char *status; + switch (error) { + case HTTPD_501_METHOD_NOT_IMPLEMENTED: + status = "501 Method Not Implemented"; + msg = "Request method is not supported by server"; + break; + case HTTPD_505_VERSION_NOT_SUPPORTED: + status = "505 Version Not Supported"; + msg = "HTTP version not supported by server"; + break; + case HTTPD_400_BAD_REQUEST: + status = "400 Bad Request"; + msg = "Server unable to understand request due to invalid syntax"; + break; + case HTTPD_404_NOT_FOUND: + status = "404 Not Found"; + msg = "This URI doesn't exist"; + break; + case HTTPD_405_METHOD_NOT_ALLOWED: + status = "405 Method Not Allowed"; + msg = "Request method for this URI is not handled by server"; + break; + case HTTPD_408_REQ_TIMEOUT: + status = "408 Request Timeout"; + msg = "Server closed this connection"; + break; + case HTTPD_414_URI_TOO_LONG: + status = "414 URI Too Long"; + msg = "URI is too long for server to interpret"; + break; + case HTTPD_411_LENGTH_REQUIRED: + status = "411 Length Required"; + msg = "Chunked encoding not supported by server"; + break; + case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE: + status = "431 Request Header Fields Too Large"; + msg = "Header fields are too long for server to interpret"; + break; + case HTTPD_XXX_UPGRADE_NOT_SUPPORTED: + /* If the server does not support upgrade, or is unable to upgrade + * it responds with a standard HTTP/1.1 response */ + status = "200 OK"; + msg = "Upgrade not supported by server"; + break; + case HTTPD_500_SERVER_ERROR: + default: + status = "500 Server Error"; + msg = "Server has encountered an unexpected error"; + } + ESP_LOGW(TAG, LOG_FMT("%s - %s"), status, msg); + + httpd_resp_set_status (req, status); + httpd_resp_set_type (req, HTTPD_TYPE_TEXT); + return httpd_resp_send (req, msg, strlen(msg)); +} + +int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len) +{ + if (r == NULL || buf == NULL) { + return HTTPD_SOCK_ERR_INVALID; + } + + if (!httpd_valid_req(r)) { + ESP_LOGW(TAG, LOG_FMT("invalid request")); + return HTTPD_SOCK_ERR_INVALID; + } + + struct httpd_req_aux *ra = r->aux; + ESP_LOGD(TAG, LOG_FMT("remaining length = %d"), ra->remaining_len); + + if (buf_len > ra->remaining_len) { + buf_len = ra->remaining_len; + } + if (buf_len == 0) { + return buf_len; + } + + int ret = httpd_recv(r, buf, buf_len); + if (ret < 0) { + ESP_LOGD(TAG, LOG_FMT("error in httpd_recv")); + return ret; + } + ra->remaining_len -= ret; + ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret); + return ret; +} + +int httpd_req_to_sockfd(httpd_req_t *r) +{ + if (r == NULL) { + return -1; + } + + if (!httpd_valid_req(r)) { + ESP_LOGW(TAG, LOG_FMT("invalid request")); + return -1; + } + + struct httpd_req_aux *ra = r->aux; + return ra->sd->fd; +} + +static int httpd_sock_err(const char *ctx, int sockfd) +{ + int errval; + int sock_err; + size_t sock_err_len = sizeof(sock_err); + + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sock_err, &sock_err_len) < 0) { + ESP_LOGE(TAG, LOG_FMT("error calling getsockopt : %d"), errno); + return HTTPD_SOCK_ERR_FAIL; + } + ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, sock_err); + + switch(sock_err) { + case EAGAIN: + case EINTR: + errval = HTTPD_SOCK_ERR_TIMEOUT; + break; + case EINVAL: + case EBADF: + case EFAULT: + case ENOTSOCK: + errval = HTTPD_SOCK_ERR_INVALID; + break; + default: + errval = HTTPD_SOCK_ERR_FAIL; + } + return errval; +} + +int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags) +{ + (void)hd; + if (buf == NULL) { + return HTTPD_SOCK_ERR_INVALID; + } + + int ret = send(sockfd, buf, buf_len, flags); + if (ret < 0) { + return httpd_sock_err("send", sockfd); + } + return ret; +} + +int httpd_default_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags) +{ + (void)hd; + if (buf == NULL) { + return HTTPD_SOCK_ERR_INVALID; + } + + int ret = recv(sockfd, buf, buf_len, flags); + if (ret < 0) { + return httpd_sock_err("recv", sockfd); + } + return ret; +} diff --git a/components/esp_http_server/src/httpd_uri.c b/components/esp_http_server/src/httpd_uri.c new file mode 100644 index 000000000..e31a6108f --- /dev/null +++ b/components/esp_http_server/src/httpd_uri.c @@ -0,0 +1,224 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include + +#include +#include "esp_httpd_priv.h" + +static const char *TAG = "httpd_uri"; + +static int httpd_find_uri_handler(struct httpd_data *hd, + const char* uri, + httpd_method_t method) +{ + for (int i = 0; i < hd->config.max_uri_handlers; i++) { + if (hd->hd_calls[i]) { + ESP_LOGD(TAG, LOG_FMT("[%d] = %s"), i, hd->hd_calls[i]->uri); + if ((hd->hd_calls[i]->method == method) && // First match methods + (strcmp(hd->hd_calls[i]->uri, uri) == 0)) { // Then match uri strings + return i; + } + } + } + return -1; +} + +esp_err_t httpd_register_uri_handler(httpd_handle_t handle, + const httpd_uri_t *uri_handler) +{ + if (handle == NULL || uri_handler == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_data *hd = (struct httpd_data *) handle; + + /* Make sure another handler with same URI and method + * is not already registered + */ + if (httpd_find_uri_handler(handle, uri_handler->uri, + uri_handler->method) != -1) { + ESP_LOGW(TAG, LOG_FMT("handler %s with method %d already registered"), + uri_handler->uri, uri_handler->method); + return ESP_ERR_HTTPD_HANDLER_EXISTS; + } + + for (int i = 0; i < hd->config.max_uri_handlers; i++) { + if (hd->hd_calls[i] == NULL) { + hd->hd_calls[i] = malloc(sizeof(httpd_uri_t)); + if (hd->hd_calls[i] == NULL) { + /* Failed to allocate memory */ + return ESP_ERR_HTTPD_ALLOC_MEM; + } + + /* Copy URI string */ + hd->hd_calls[i]->uri = strdup(uri_handler->uri); + if (hd->hd_calls[i]->uri == NULL) { + /* Failed to allocate memory */ + free(hd->hd_calls[i]); + return ESP_ERR_HTTPD_ALLOC_MEM; + } + + /* Copy remaining members */ + hd->hd_calls[i]->method = uri_handler->method; + hd->hd_calls[i]->handler = uri_handler->handler; + hd->hd_calls[i]->user_ctx = uri_handler->user_ctx; + ESP_LOGD(TAG, LOG_FMT("[%d] installed %s"), i, uri_handler->uri); + return ESP_OK; + } + ESP_LOGD(TAG, LOG_FMT("[%d] exists %s"), i, hd->hd_calls[i]->uri); + } + ESP_LOGW(TAG, LOG_FMT("no slots left for registering handler")); + return ESP_ERR_HTTPD_HANDLERS_FULL; +} + +esp_err_t httpd_unregister_uri_handler(httpd_handle_t handle, + const char *uri, httpd_method_t method) +{ + if (handle == NULL || uri == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_data *hd = (struct httpd_data *) handle; + int i = httpd_find_uri_handler(hd, uri, method); + + if (i != -1) { + ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, hd->hd_calls[i]->uri); + + free((char*)hd->hd_calls[i]->uri); + free(hd->hd_calls[i]); + hd->hd_calls[i] = NULL; + return ESP_OK; + } + ESP_LOGW(TAG, LOG_FMT("handler %s with method %d not found"), uri, method); + return ESP_ERR_NOT_FOUND; +} + +esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char *uri) +{ + if (handle == NULL || uri == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct httpd_data *hd = (struct httpd_data *) handle; + bool found = false; + + for (int i = 0; i < hd->config.max_uri_handlers; i++) { + if ((hd->hd_calls[i] != NULL) && + (strcmp(hd->hd_calls[i]->uri, uri) == 0)) { + ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, uri); + + free((char*)hd->hd_calls[i]->uri); + free(hd->hd_calls[i]); + hd->hd_calls[i] = NULL; + found = true; + } + } + if (!found) { + ESP_LOGW(TAG, LOG_FMT("no handler found for URI %s"), uri); + } + return (found ? ESP_OK : ESP_ERR_NOT_FOUND); +} + +void httpd_unregister_all_uri_handlers(struct httpd_data *hd) +{ + for (unsigned i = 0; i < hd->config.max_uri_handlers; i++) { + if (hd->hd_calls[i]) { + ESP_LOGD(TAG, LOG_FMT("[%d] removing %s"), i, hd->hd_calls[i]->uri); + + free((char*)hd->hd_calls[i]->uri); + free(hd->hd_calls[i]); + } + } +} + +/* Alternate implmentation of httpd_find_uri_handler() + * which takes a uri_len field. This is useful when the URI + * string contains extra parameters that are not to be included + * while matching with the registered URI_handler strings + */ +static httpd_uri_t* httpd_find_uri_handler2(httpd_err_resp_t *err, + struct httpd_data *hd, + const char *uri, size_t uri_len, + httpd_method_t method) +{ + *err = 0; + for (int i = 0; i < hd->config.max_uri_handlers; i++) { + if (hd->hd_calls[i]) { + ESP_LOGD(TAG, LOG_FMT("[%d] = %s"), i, hd->hd_calls[i]->uri); + if ((strlen(hd->hd_calls[i]->uri) == uri_len) && // First match uri length + (strncmp(hd->hd_calls[i]->uri, uri, uri_len) == 0)) { // Then match uri strings + if (hd->hd_calls[i]->method == method) { // Finally match methods + return hd->hd_calls[i]; + } + /* URI found but method not allowed. + * If URI IS found later then this + * error is to be neglected */ + *err = HTTPD_405_METHOD_NOT_ALLOWED; + } + } + } + if (*err == 0) { + *err = HTTPD_404_NOT_FOUND; + } + return NULL; +} + +esp_err_t httpd_uri(struct httpd_data *hd) +{ + httpd_uri_t *uri = NULL; + httpd_req_t *req = &hd->hd_req; + struct http_parser_url *res = &hd->hd_req_aux.url_parse_res; + + /* For conveying URI not found/method not allowed */ + httpd_err_resp_t err = 0; + + ESP_LOGD(TAG, LOG_FMT("request for %s with type %d"), req->uri, req->method); + /* URL parser result contains offset and length of path string */ + if (res->field_set & (1 << UF_PATH)) { + uri = httpd_find_uri_handler2(&err, hd, + req->uri + res->field_data[UF_PATH].off, + res->field_data[UF_PATH].len, + req->method); + } + + /* If URI with method not found, respond with error code */ + if (uri == NULL) { + switch (err) { + case HTTPD_404_NOT_FOUND: + ESP_LOGW(TAG, LOG_FMT("URI '%s' not found"), req->uri); + return httpd_resp_send_err(req, HTTPD_404_NOT_FOUND); + case HTTPD_405_METHOD_NOT_ALLOWED: + ESP_LOGW(TAG, LOG_FMT("Method '%d' not allowed for URI '%s'"), req->method, req->uri); + return httpd_resp_send_err(req, HTTPD_405_METHOD_NOT_ALLOWED); + default: + return ESP_FAIL; + } + } + + /* Attach user context data (passed during URI registration) into request */ + req->user_ctx = uri->user_ctx; + + /* Invoke handler */ + if (uri->handler(req) != ESP_OK) { + /* Handler returns error, this socket should be closed */ + ESP_LOGW(TAG, LOG_FMT("uri handler execution failed")); + return ESP_FAIL; + } + return ESP_OK; +} diff --git a/components/esp_http_server/src/port/esp8266/osal.h b/components/esp_http_server/src/port/esp8266/osal.h new file mode 100644 index 000000000..55ebe309a --- /dev/null +++ b/components/esp_http_server/src/port/esp8266/osal.h @@ -0,0 +1,64 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _OSAL_H_ +#define _OSAL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_SUCCESS ESP_OK +#define OS_FAIL ESP_FAIL + +typedef TaskHandle_t othread_t; + +static inline int httpd_os_thread_create(othread_t *thread, + const char *name, uint16_t stacksize, int prio, + void (*thread_routine)(void *arg), void *arg) +{ + int ret = xTaskCreate(thread_routine, name, stacksize, arg, prio, thread); + if (ret == pdPASS) { + return OS_SUCCESS; + } + return OS_FAIL; +} + +/* Only self delete is supported */ +static inline void httpd_os_thread_delete() +{ + vTaskDelete(xTaskGetCurrentTaskHandle()); +} + +static inline void httpd_os_thread_sleep(int msecs) +{ + vTaskDelay(msecs / portTICK_RATE_MS); +} + +static inline othread_t httpd_os_thread_handle() +{ + return xTaskGetCurrentTaskHandle(); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ! _OSAL_H_ */ diff --git a/components/esp_http_server/src/util/ctrl_sock.c b/components/esp_http_server/src/util/ctrl_sock.c new file mode 100644 index 000000000..5c84f80ef --- /dev/null +++ b/components/esp_http_server/src/util/ctrl_sock.c @@ -0,0 +1,77 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include +#include +#include + +#include "ctrl_sock.h" + +/* Control socket, because in some network stacks select can't be woken up any + * other way + */ +int cs_create_ctrl_sock(int port) +{ + int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + return -1; + } + + int ret; + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + inet_aton("127.0.0.1", &addr.sin_addr); + ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + close(fd); + return -1; + } + return fd; +} + +void cs_free_ctrl_sock(int fd) +{ + close(fd); +} + +int cs_send_to_ctrl_sock(int send_fd, int port, void *data, unsigned int data_len) +{ + int ret; + struct sockaddr_in to_addr; + to_addr.sin_family = AF_INET; + to_addr.sin_port = htons(port); + inet_aton("127.0.0.1", &to_addr.sin_addr); + ret = sendto(send_fd, data, data_len, 0, (struct sockaddr *)&to_addr, sizeof(to_addr)); + + if (ret < 0) { + return -1; + } + return ret; +} + +int cs_recv_from_ctrl_sock(int fd, void *data, unsigned int data_len) +{ + int ret; + ret = recvfrom(fd, data, data_len, 0, NULL, NULL); + + if (ret < 0) { + return -1; + } + return ret; +} diff --git a/components/esp_http_server/src/util/ctrl_sock.h b/components/esp_http_server/src/util/ctrl_sock.h new file mode 100644 index 000000000..d392d3539 --- /dev/null +++ b/components/esp_http_server/src/util/ctrl_sock.h @@ -0,0 +1,99 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * \file ctrl_sock.h + * \brief Control Socket for select() wakeup + * + * LWIP doesn't allow an easy mechanism to on-demand wakeup a thread + * sleeping on select. This is a common requirement for sending + * control commands to a network server. This control socket API + * facilitates the same. + */ +#ifndef _CTRL_SOCK_H_ +#define _CTRL_SOCK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create a control socket + * + * LWIP doesn't allow an easy mechanism to on-demand wakeup a thread + * sleeping on select. This is a common requirement for sending + * control commands to a network server. This control socket API + * facilitates the same. + * + * This API will create a UDP control socket on the specified port. It + * will return a socket descriptor that can then be added to your + * fd_set in select() + * + * @param[in] port the local port on which the control socket will listen + * + * @return - the socket descriptor that can be added to the fd_set in select. + * - an error code if less than zero + */ +int cs_create_ctrl_sock(int port); + +/** + * @brief Free the control socket + * + * This frees up the control socket that was earlier created using + * cs_create_ctrl_sock() + * + * @param[in] fd the socket descriptor associated with this control socket + */ +void cs_free_ctrl_sock(int fd); + +/** + * @brief Send data to control socket + * + * This API sends data to the control socket. If a server is blocked + * on select() with the control socket, this call will wake up that + * server. + * + * @param[in] send_fd the socket for sending ctrl messages + * @param[in] port the port on which the control socket was created + * @param[in] data pointer to a buffer that contains data to send on the socket + * @param[in] data_len the length of the data contained in the buffer pointed to be data + * + * @return - the number of bytes sent to the control socket + * - an error code if less than zero + */ +int cs_send_to_ctrl_sock(int send_fd, int port, void *data, unsigned int data_len); + +/** + * @brief Receive data from control socket + * + * This API receives any data that was sent to the control + * socket. This will be typically called from the server thread to + * process any commands on this socket. + * + * @param[in] fd the socket descriptor of the control socket + * @param[in] data pointer to a buffer that will be used to store + * received from the control socket + * @param[in] data_len the maximum length of the data that can be + * stored in the buffer pointed by data + * + * @return - the number of bytes received from the control socket + * - an error code if less than zero + */ +int cs_recv_from_ctrl_sock(int fd, void *data, unsigned int data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* ! _CTRL_SOCK_H_ */ diff --git a/components/esp_https_ota/CMakeLists.txt b/components/esp_https_ota/CMakeLists.txt new file mode 100644 index 000000000..6ef0a5c9e --- /dev/null +++ b/components/esp_https_ota/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_SRCS "src/esp_https_ota.c") + +set(COMPONENT_REQUIRES esp_http_client) +set(COMPONENT_PRIV_REQUIRES log app_update) + +register_component() diff --git a/components/esp_https_ota/Kconfig b/components/esp_https_ota/Kconfig new file mode 100644 index 000000000..946fc9e49 --- /dev/null +++ b/components/esp_https_ota/Kconfig @@ -0,0 +1,21 @@ +menu "ESP HTTPS OTA" + +config OTA_BUF_SIZE + int "Default OTA Buffer Size" + default 256 + range 256 1460 + help + Set OTA Buffer Size. The larger buffer size will read more size packet once and can reduce upgrade cost time. + This buffer size depends on CONFIG_HTTP_BUF_SIZE. If you want to enlarge ota buffer size, please also enlarge CONFIG_HTTP_BUF_SIZE. + OTA_BUF_SIZE equals to 1460 can save 40% upgrade time in contrast to OTA_BUF_SIZE which equals to 256. + +config OTA_ALLOW_HTTP + bool "Allow HTTP for OTA (WARNING: ONLY FOR TESTING PURPOSE, READ HELP)" + default n + help + It is highly recommended to keep HTTPS (along with server certificate validation) enabled. + Enabling this option comes with potential risk of: + - Non-encrypted communication channel with server + - Accepting firmware upgrade image from server with fake identity + +endmenu diff --git a/components/esp_https_ota/component.mk b/components/esp_https_ota/component.mk new file mode 100644 index 000000000..84730f8a1 --- /dev/null +++ b/components/esp_https_ota/component.mk @@ -0,0 +1,4 @@ + +COMPONENT_SRCDIRS := src + +COMPONENT_ADD_INCLUDEDIRS := include diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h new file mode 100644 index 000000000..157195601 --- /dev/null +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -0,0 +1,45 @@ +// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief HTTPS OTA Firmware upgrade. + * + * This function performs HTTPS OTA Firmware upgrade + * + * @param[in] config pointer to esp_http_client_config_t structure. + * + * @note For secure HTTPS updates, the `cert_pem` member of `config` + * structure must be set to the server certificate. + * + * @return + * - ESP_OK: OTA data updated, next reboot will use specified partition. + * - ESP_FAIL: For generic failure. + * - ESP_ERR_OTA_VALIDATE_FAILED: Invalid app image + * - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation. + * - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed. + * - For other return codes, refer OTA documentation in esp-idf's app_update component. + */ +esp_err_t esp_https_ota(const esp_http_client_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_https_ota/src/esp_https_ota.c b/components/esp_https_ota/src/esp_https_ota.c new file mode 100644 index 000000000..d326c2bea --- /dev/null +++ b/components/esp_https_ota/src/esp_https_ota.c @@ -0,0 +1,135 @@ +// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include "sdkconfig.h" + +#define OTA_BUF_SIZE CONFIG_OTA_BUF_SIZE +static const char *TAG = "esp_https_ota"; + +static void http_cleanup(esp_http_client_handle_t client) +{ + esp_http_client_close(client); + esp_http_client_cleanup(client); +} + +esp_err_t esp_https_ota(const esp_http_client_config_t *config) +{ + if (!config) { + ESP_LOGE(TAG, "esp_http_client config not found"); + return ESP_ERR_INVALID_ARG; + } + +#if !CONFIG_OTA_ALLOW_HTTP + if (!config->cert_pem) { + ESP_LOGE(TAG, "Server certificate not found in esp_http_client config"); + return ESP_FAIL; + } +#endif + + esp_http_client_handle_t client = esp_http_client_init(config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); + return ESP_FAIL; + } + +#if !CONFIG_OTA_ALLOW_HTTP + if (esp_http_client_get_transport_type(client) != HTTP_TRANSPORT_OVER_SSL) { + ESP_LOGE(TAG, "Transport is not over HTTPS"); + return ESP_FAIL; + } +#endif + + esp_err_t err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + esp_http_client_cleanup(client); + ESP_LOGE(TAG, "Failed to open HTTP connection: %d", err); + return err; + } + esp_http_client_fetch_headers(client); + + esp_ota_handle_t update_handle = 0; + const esp_partition_t *update_partition = NULL; + ESP_LOGI(TAG, "Starting OTA..."); + update_partition = esp_ota_get_next_update_partition(NULL); + if (update_partition == NULL) { + ESP_LOGE(TAG, "Passive OTA partition not found"); + http_cleanup(client); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", + update_partition->subtype, update_partition->address); + + err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err); + http_cleanup(client); + return err; + } + ESP_LOGI(TAG, "esp_ota_begin succeeded"); + ESP_LOGI(TAG, "Please Wait. This may take time"); + + esp_err_t ota_write_err = ESP_OK; + char *upgrade_data_buf = (char *)malloc(OTA_BUF_SIZE); + if (!upgrade_data_buf) { + ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer"); + return ESP_ERR_NO_MEM; + } + int binary_file_len = 0; + while (1) { + int data_read = esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE); + if (data_read == 0) { + ESP_LOGI(TAG, "Connection closed,all data received"); + break; + } + if (data_read < 0) { + ESP_LOGE(TAG, "Error: SSL data read error"); + break; + } + if (data_read > 0) { + ota_write_err = esp_ota_write( update_handle, (const void *)upgrade_data_buf, data_read); + if (ota_write_err != ESP_OK) { + break; + } + binary_file_len += data_read; + ESP_LOGD(TAG, "Written image length %d", binary_file_len); + } + } + free(upgrade_data_buf); + http_cleanup(client); + ESP_LOGD(TAG, "Total binary data length writen: %d", binary_file_len); + + esp_err_t ota_end_err = esp_ota_end(update_handle); + if (ota_write_err != ESP_OK) { + ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%d", err); + return ota_write_err; + } else if (ota_end_err != ESP_OK) { + ESP_LOGE(TAG, "Error: esp_ota_end failed! err=0x%d. Image is invalid", ota_end_err); + return ota_end_err; + } + + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%d", err); + return err; + } + ESP_LOGI(TAG, "esp_ota_set_boot_partition succeeded"); + + return ESP_OK; +} diff --git a/components/esp_ringbuf/CMakeLists.txt b/components/esp_ringbuf/CMakeLists.txt new file mode 100644 index 000000000..90fe6482c --- /dev/null +++ b/components/esp_ringbuf/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_ADD_INCLUDEDIRS "include" "include/freertos") +set(COMPONENT_SRCS "ringbuf.c") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/esp_ringbuf/component.mk b/components/esp_ringbuf/component.mk new file mode 100644 index 000000000..a3a014241 --- /dev/null +++ b/components/esp_ringbuf/component.mk @@ -0,0 +1,3 @@ + +COMPONENT_ADD_INCLUDEDIRS += include/freertos + diff --git a/components/freertos/include/freertos/ringbuf.h b/components/esp_ringbuf/include/freertos/ringbuf.h similarity index 100% rename from components/freertos/include/freertos/ringbuf.h rename to components/esp_ringbuf/include/freertos/ringbuf.h diff --git a/components/freertos/freertos/ringbuf.c b/components/esp_ringbuf/ringbuf.c similarity index 100% rename from components/freertos/freertos/ringbuf.c rename to components/esp_ringbuf/ringbuf.c diff --git a/components/espos/component.mk b/components/espos/component.mk deleted file mode 100644 index 510745da9..000000000 --- a/components/espos/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -# Component Makefile -# -COMPONENT_SRCDIRS := platform/freertos diff --git a/components/espos/include/arch/espos_arch.h b/components/espos/include/arch/espos_arch.h deleted file mode 100644 index dadd32307..000000000 --- a/components/espos/include/arch/espos_arch.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_ARCH_H_ -#define _ESPOS_ARCH_H_ - -#include "espos_esp8266.h" - -#endif /* _ESPOS_ARCH_H_ */ diff --git a/components/espos/include/arch/espos_esp8266.h b/components/espos/include/arch/espos_esp8266.h deleted file mode 100644 index 5e5699a99..000000000 --- a/components/espos/include/arch/espos_esp8266.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_ESP8266_H_ -#define _ESPOS_ESP8266_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define ESPOS_PROCESSORS_NUM 1u - -#define ESPOS_SPINLOCK_ARCH_UNLOCK_INITIALIZER \ - { \ - 0, \ - } - -typedef int32_t esp_err_t; - -typedef struct espos_spinlock_arch { - uintptr_t lock; -} espos_spinlock_arch_t; - -static inline uintptr_t espos_suspend_interrupt(void) -{ - uintptr_t state; - - __asm__ volatile ("RSIL %0, 5" : "=a" (state) :: "memory"); - - return state; -} - -static inline void espos_resume_interrupt(uintptr_t state) -{ - __asm__ volatile ("WSR %0, ps" :: "a" (state) : "memory"); -} - -#define espos_get_core_id() 0 - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_ESP8266_H_ */ diff --git a/components/espos/include/espos_errno.h b/components/espos/include/espos_errno.h deleted file mode 100644 index a82c124a2..000000000 --- a/components/espos/include/espos_errno.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_ERRNO_H_ -#define _ESPOS_ERRNO_H_ - -#include - -#endif /* _ESPOS_ERRNO_H_ */ diff --git a/components/espos/include/espos_mutex.h b/components/espos/include/espos_mutex.h deleted file mode 100644 index 05e6abad2..000000000 --- a/components/espos/include/espos_mutex.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_MUTEX_H_ -#define _ESPOS_MUTEX_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* use default option to create mutex */ -typedef enum espos_mutex_type_opt { - - /* AT this mode, deadlock detection shall not be provided. Attempting to relock the mutex causes deadlock. - * - * If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, - * undefined behavior results. - */ - ESPOS_MUTEX_NORMAL = 0, - - ESPOS_MUTEX_RECURSIVE, - - ESPOS_MUTEX_TYPE_MAX -} espos_mutex_type_opt_t; - -#define ESPOS_MUTEX_TYPE(type) (type & 0xFF) - -/** - * @brief create a mutex - * - * @param mutex mutex handle point - * @param opt mutex option, if you don't know how to do, just use "ESPOS_MUTEX_NORMAL" here - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINTR : you do this at interrupt state, and it is not supported - * -EINVAL : input parameter error - */ -esp_err_t espos_mutex_create(espos_mutex_t *mutex, espos_mutex_type_opt_t opt); - -/** - * @brief set a mutex name - * - * @param mutex mutex handle - * @param name mutex's name - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_mutex_set_name(espos_mutex_t mutex, const char *name); - -/** - * @brief lock a mutex - * - * @param mutex mutex handle - * @param wait_ticks sleep for system ticks if the locked mutex is not unlocked. Otherwise if someone - * else unlock the locked mutex, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY" - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - * -ETIMEDOUT : timeout and you have not locked it - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -esp_err_t espos_mutex_lock(espos_mutex_t mutex, espos_tick_t wait_ticks); - -/** - * @bref try to lock a mutex and it will return immediately without being blocked - * - * @param m mutex handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - */ -#define espos_mutex_trylock(m) espos_mutex_lock(m, ESPOS_NO_DELAY) - -/** - * @brief unlock a mutex - * - * @param mutex mutex handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - * -EPERM : current task don't lock the mutex - */ -esp_err_t espos_mutex_unlock(espos_mutex_t mutex); - -/** - * @brief get task handle which lock the mutex - * - * @param mutex mutex handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -espos_task_t espos_mutex_get_holder(espos_mutex_t mutex); - -/** - * @brief delete the mutex - * - * @param mutex mutex handle - * - * @return the result - * 0 : successful - * -EINTR : you do this at interrupt state, and it is not supported - * -EINVAL : input parameter error - * - * @note if low-level module is YunOS, this function will awake all task blocked at the mutex - */ -esp_err_t espos_mutex_del(espos_mutex_t mutex); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_MUTEX_H_ */ diff --git a/components/espos/include/espos_queue.h b/components/espos/include/espos_queue.h deleted file mode 100644 index 163a5d130..000000000 --- a/components/espos/include/espos_queue.h +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_QUEUE_H_ -#define _ESPOS_QUEUE_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum espos_queue_pos { - /* send message to the front of the queue */ - ESPOS_QUEUE_SEND_FRONT = 0, - - /* send message to the back of the queue */ - ESPOS_QUEUE_SEND_BACK, - - ESPOS_QUEUE_POS_MAX -} espos_queue_pos_t; - -typedef enum espos_queue_send_opt { - /* send message with normal option */ - ESPOS_QUEUE_SEND_OPT_NORMAL = 0, - - ESPOS_QUEUE_SEND_OPT_MAX -} espos_queue_send_opt_t; - -typedef enum espos_queue_recv_opt { - /* receive message with normal option */ - ESPOS_QUEUE_RECV_OPT_NORMAL = 0, - - ESPOS_QUEUE_RECV_OPT_MAX -} espos_queue_recv_opt_t; - -/** - * @brief create a queue - * - * @param queue queue handle point - * @param msg_len queue internal message length (bytes) - * @param queue_len queue internal message maximum number - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINTR : you do this at interrupt state, and it is not supported - * -EINVAL : input parameter error - * - * @note all input and out message length is fixedly "msg_len" - */ -esp_err_t espos_queue_create(espos_queue_t *queue, espos_size_t msg_len, espos_size_t queue_len); - -/** - * @brief set a queue name - * - * @param queue queue handle - * @param name queue's name - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_queue_set_name(espos_queue_t queue, const char *name); - -/** - * @brief send a message to the queue, it is suggested that you had better not use "espos_queue_send" directly, - * please use "espos_queue_send_front" or "espos_queue_send_back" - * - * @param queue queue handle - * @param msg message point - * @param wait_ticks sleep for system ticks if the queue is full. Otherwise if queue is not full, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY" - * @param pos position where sending the message - * ESPOS_QUEUE_SEND_FRONT : send message to the front of the queue - * ESPOS_QUEUE_SEND_BACK : send message to the back of the queue - * @param opt sending option - * ESPOS_QUEUE_SEND_OPT_NORMAL : wake up blocked task - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and the queue is full - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -esp_err_t espos_queue_send_generic(espos_queue_t queue, void *msg, espos_tick_t wait_ticks, espos_pos_t pos, espos_opt_t opt); - -/** - * @brief send a message to the front of the queue - * - * @param q queue handle - * @param m message point - * @param t sleep for system ticks if the queue is full. Otherwise if queue is not full, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY" - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and the queue is full - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -#define espos_queue_send_front(q, m, t) espos_queue_send_generic(q, m, t, ESPOS_QUEUE_SEND_FRONT, ESPOS_QUEUE_SEND_OPT_NORMAL) - -/** - * @brief send a message to the back of the queue - * - * @param q queue handle - * @param m message point - * @param t sleep for system ticks if the queue is full. Otherwise if queue is not full, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY" - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and the queue is full - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -#define espos_queue_send(q, m, t) espos_queue_send_generic(q, m, t, ESPOS_QUEUE_SEND_BACK, ESPOS_QUEUE_SEND_OPT_NORMAL) - -/** - * @brief receive a message of the queue - * - * @param queue queue handle - * @param msg message point - * @param wait_ticks sleep for system ticks if the queue is empty. Otherwise if queue is not empty, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY", at CPU ISR mode, it is forced to be 0 - * @param opt queue sending option - * ESPOS_QUEUE_RECV_OPT_NORMAL : use wait_ticks to check if it is need be blocked - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and the queue is empty - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -esp_err_t espos_queue_recv_generic(espos_queue_t queue, void *msg, espos_tick_t wait_ticks, espos_opt_t opt); - -/** - * @brief receive a message of the queue with normal option - * - * @param queue queue handle - * @param msg message point - * @param wait_ticks sleep for system ticks if the queue is empty. Otherwise if queue is not empty, you will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY", at CPU ISR mode, it is forced to be 0 - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and the queue is empty - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -#define espos_queue_recv(q, m, t) espos_queue_recv_generic(q, m, t, ESPOS_QUEUE_RECV_OPT_NORMAL) - -/** - * @brief get current message number of the queue - * - * @param queue queue handle - * - * @return current message number of the queue - */ -espos_size_t espos_queue_msg_waiting(espos_queue_t queue); - -/** - * @brief reset the queue - * - * @param queue queue handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * - * @note if low-level module is YunOS, the function will not awake the tasks which is blocked at the queue - */ -esp_err_t espos_queue_flush(espos_queue_t queue); - -/** - * @brief delete the queue - * - * @param queue queue handle - * - * @return the result - * 0 : successful - * -EINTR : you do this at interrupt state, and it is not supported - * -EINVAL : input parameter error - * - * @note if low-level module is YunOS, this function will awake all task blocked at the mutex - */ -esp_err_t espos_queue_del(espos_queue_t queue); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_QUEUE_H_ */ diff --git a/components/espos/include/espos_scheduler.h b/components/espos/include/espos_scheduler.h deleted file mode 100644 index b7747c9bf..000000000 --- a/components/espos/include/espos_scheduler.h +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_SCHEDULER_H_ -#define _ESPOS_SCHEDULER_H_ - -#include - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_spinlock.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * ESPOS state - */ -typedef enum espos_stat { - ESPOS_IS_NOT_STARTED = 0, - ESPOS_IS_RUNNING, - ESPOS_IS_SUSPENDED -} espos_stat_t; - -/************************************ internal function ************************************/ -/** - * @brief enter ESPOS system critical state - * - * @param spinlock spinlock handle point - * - * @return critical state temple variable(used by "espos_exit_critical") - */ -espos_critical_t _espos_enter_critical(espos_spinlock_t *spinlock); - -/** - * @brief exit ESPOS system critical state - * - * @param spinlock spinlock handle point - * @param tmp critical state temple variable(created by "espos_enter_critical") - * - * @return none - */ -void _espos_exit_critical(espos_spinlock_t *spinlock, espos_critical_t tmp); - -/*******************************************************************************************/ - -/** - * @brief initialize ESPOS system - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - */ -esp_err_t espos_init(void); - -/** - * @brief start ESPOS system - * - * @return the result - * 0 : successful - * -EPERM : failed (it will never happen in a general way) - */ -esp_err_t espos_start(void); - -/** - * @brief get espos system state - * - * @return the state - * ESPOS_IS_NOT_STARTED : ESPOS is not started - * ESPOS_IS_RUNNING : ESPOS is running - * ESPOS_IS_SUSPENDED : ESPOS is suspended - */ -espos_stat_t espos_sched_state_get(void); - -#if ESPOS_PROCESSORS_NUM > 1u - -/** - * @brief start ESPOS system CPU port - * - * @param port CPU port ID - * - * @return the result - * 0 : successful - * -EPERM : failed (it will never happen in a general way) - */ -esp_err_t espos_start_port(int port); - -/** - * @brief declare espos critical temp data - */ -#define espos_declare_critical(t) espos_critical_t t - -/** - * @brief enter ESPOS system critical state - * - * @param sl spinlock handle - * @param t critical state - * - * @return critical state temple variable(used by "espos_exit_critical") - */ -#define espos_enter_critical(t, sl) (t) = _espos_enter_critical(&(sl)) - -/** - * @brief exit ESPOS system critical state - * - * @param t critical state temple variable(created by "espos_enter_critical") - * @param sl spinlock handle point - * - * @return none - */ -#define espos_exit_critical(t, sl) _espos_exit_critical(&(sl), t) - -/** - * @brief OS internal function enter ESPOS system critical state - * - * @param sl spinlock handle - * @param t critical state - * - * @return critical state temple variable(used by "espos_exit_critical") - * - * @note: ESPOS is application level OS API, so it means all APIs call internal - * real OS's function, so if OS's or its core hardware's functions want - * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's - * at OS internal state now. - */ -#define espos_os_enter_critical(t, sl) \ - espos_os_enter(); \ - (t) = _espos_enter_critical(&(sl)) - -/** - * @brief OS internal function exit ESPOS system critical state - * - * @param t critical state temple variable(created by "espos_enter_critical") - * @param sl spinlock handle point - * - * @return none - * - * @note: ESPOS is application level OS API, so it means all APIs call internal - * real OS's function, so if OS's or its core hardware's functions want - * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's - * at OS internal state now. - */ -#define espos_os_exit_critical(t, sl) \ - _espos_exit_critical(&(sl), t); \ - espos_os_exit() - -#else - -/** - * @brief start ESPOS system CPU port - * - * @param port CPU port ID - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_start_port(int port) -{ - return -ENODEV; -} - -/** - * @brief declare espos critical temp data - */ -#define espos_declare_critical(t) espos_critical_t t - -/** - * @brief enter ESPOS system critical state - * - * @param sl no mean - * @param t critical state - * - * @return critical state temple variable(used by "espos_exit_critical") - */ -#define espos_enter_critical(t, sl) (t) = _espos_enter_critical(NULL) - -/** - * @brief exit ESPOS system critical state - * - * @param t critical state temple variable(created by "espos_enter_critical") - * @param sl no mean - * - * @return none - */ -#define espos_exit_critical(t, sl) _espos_exit_critical(NULL, t) - -/** - * @brief OS internal function enter ESPOS system critical state - * - * @param sl no mean - * @param t critical state - * - * @return critical state temple variable(used by "espos_exit_critical") - * - * @note: ESPOS is application level OS API, so it means all APIs call internal - * real OS's function, so if OS's or its core hardware's functions want - * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's - * at OS internal state now. - */ -#define espos_os_enter_critical(t, sl) \ - espos_os_enter(); \ - (t) = _espos_enter_critical(NULL) - -/** - * @brief OS internal function exit ESPOS system critical state - * - * @param t critical state temple variable(created by "espos_enter_critical") - * @param sl no mean - * - * @return none - * - * @note: ESPOS is application level OS API, so it means all APIs call internal - * real OS's function, so if OS's or its core hardware's functions want - * to call ESPOS, loop nesting will occur, so we should tell ESPOS it's - * at OS internal state now. - */ -#define espos_os_exit_critical(t, sl) \ - _espos_exit_critical(NULL, t); \ - espos_os_exit() - -#endif - -/** - * @brief suspend the local CPU core preempt and the current task - * owned by local CPU core will not be preempted - * - * @return the result - * 0 : successful - * -EAGAIN : preempt suspending maximum number is reached, and fail to do it - * -EINTR : you do this at interrupt state, and it is not supported - * - * @note the function can be used nested - */ -esp_err_t espos_preempt_suspend_local(void); - -/** - * @brief resume the local CPU core preempt - * - * @return the result - * 0 : successful - * -EAGAIN : preempt resuming maximum number is reached, and fail to do it - * -EINTR : you do this at interrupt state, and it is not supported - * - * @note the function can be used nested - */ -esp_err_t espos_preempt_resume_local(void); - -/** - * @brief enter system interrupt server, the function must be used after entering hardware interrupt - * - * @return the result - * 0 : successful - * -EAGAIN : nested count is reached - * - * @note the function can be used nested - */ -esp_err_t espos_isr_enter (void); - -/** - * @brief exit system interrupt server, the function must be used before exiting hardware interrupt - * - * @return none - * - * @note the function can be used nested - */ -void espos_isr_exit(void); - -/** - * @brief check if the CPU is at ISR state - * - * @param none - * - * @return true if the CPU is at ISR state or false - */ -bool espos_in_isr(void); - -/** - * @brief mark it enters real OS interal function - * - * @return the result - * 0 : successful - * -EAGAIN : nested count is reached - * - * @note the function can be used nested - */ -esp_err_t espos_os_enter(void); - -/** - * @brief remove mark it enters real OS interal function - * - * @param none - * - * @return none - */ -void espos_os_exit(void); - -/** - * @brief check if the function is at real OS internal fucntion - * - * @param none - * - * @return true if the CPU is at real OS internal fucntion or false - */ -bool espos_os_isr(void); - -size_t espos_get_free_heap_size(void); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/components/espos/include/espos_semaphore.h b/components/espos/include/espos_semaphore.h deleted file mode 100644 index 96f9badc8..000000000 --- a/components/espos/include/espos_semaphore.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_SEMAPHORE_H_ -#define _ESPOS_SEMAPHORE_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief create a semaphore - * - * @param sem semaphore handle point - * @param max_count semaphore maximum count - * @param init_count semaphore initialized count - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINVAL : input parameter error - * - * @note if low-level module is YunOS, "max_count" does not work, and the reachable count is "0xFFFFFFFF" - */ -esp_err_t espos_sem_create(espos_sem_t *sem, espos_sem_count_t max_count, espos_sem_count_t init_count); - -/** - * @brief set a semaphore name - * - * @param semaphore semaphore handle - * @param name semaphore's name - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_sem_set_name(espos_sem_t sem, const char *name); - -/** - * @brief take semaphore - * - * @param sem semaphore handle - * @param wait_ticks sleep for system ticks if the semaphore is empty. Otherwise if semaphore is given, - * oldest blocked task will wake up. - * maximum time is "ESPOS_MAX_DELAY", no time is "ESPOS_NO_DELAY" - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : timeout and not take semaphore - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -esp_err_t espos_sem_take(espos_sem_t sem, espos_tick_t wait_ticks); - -/** - * @brief try to take semaphore - * - * @param s semaphore handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ETIMEDOUT : not take semaphore - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -#define espos_sem_trytake(s) espos_sem_take(s, ESPOS_NO_DELAY) - -/** - * @brief give up semaphore - * - * @param sem semaphore handle - * @param wait_ticks no meaning - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -EAGAIN : the maximum count is reached - * - * @note you can transform the millisecond to ticks by "espos_ms_to_ticks" - */ -esp_err_t espos_sem_give(espos_sem_t sem); - -/** - * @brief delete the semaphore - * - * @param sem semaphore handle - * - * @return the result - * 0 : successful - * -EINTR : you do this at interrupt state, and it is not supported - * -EINVAL : input parameter error - * - * @note if low-level module is YunOS, this function will awake all task blocked here - */ -esp_err_t espos_sem_del(espos_sem_t sem); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_SEMAPHORE_H_ */ diff --git a/components/espos/include/espos_spinlock.h b/components/espos/include/espos_spinlock.h deleted file mode 100644 index 7413e9ce2..000000000 --- a/components/espos/include/espos_spinlock.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_SPINLOCK_H_ -#define _ESPOS_SPINLOCK_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_task.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if ESPOS_PROCESSORS_NUM > 1u - -typedef struct espos_spinlock { - espos_spinlock_arch_t lock; - espos_task_t holder; -} espos_spinlock_t; - -#define ESPOS_SPINLOCK_UNLOCK_INITIALIZER \ - { \ - ESPOS_SPINLOCK_ARCH_UNLOCK_INITIALIZER, \ - ESPOS_OBJ_NONE, \ - } - -#define ESPOS_DEFINE_SPINLOCK(l) \ - espos_spinlock_t l = ESPOS_SPINLOCK_UNLOCK_INITIALIZER - -#define ESPOS_DEFINE_STATIC_SPINLOCK(l) \ - static espos_spinlock_t l = ESPOS_SPINLOCK_UNLOCK_INITIALIZER - -/** - * @brief create a spinlock - * - * @param spinlock spinlock handle point - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_create (espos_spinlock_t *spinlock); - -/** - * @brief set a spinlock name - * - * @param spinlock spinlock handle - * @param name spinlock's name - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_set_name(espos_spinlock_t *spinlock, const char *name); - -/** - * @brief spin to lock a spinlock until successfully - * - * @param spinlock spinlock handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_lock(espos_spinlock_t *spinlock); - -/** - * @brief try to lock a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * 0 : successful - * -EAGAIN : no spinlock is valid - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_trylock(espos_spinlock_t *spinlock); - -/** - * @brief get spinlock holder task handle - * - * @param spinlock spinlock handle - * - * @return holder task handle - */ -espos_task_t espos_spinlock_get_holder(espos_spinlock_t *spinlock); - -/** - * @brief unlock a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * 0 : successful - * -EAGAIN : no spinlock is locked - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_unlock(espos_spinlock_t *spinlock); - -/** - * @brief delete a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * 0 : successful - * -EACCES : failed to do it with some special reason - * -EINVAL : input parameter error - */ -esp_err_t espos_spinlock_del(espos_spinlock_t *spinlock); - -#else - -typedef struct espos_spinlock { - espos_spinlock_arch_t lock; -} espos_spinlock_t; - -#define ESPOS_SPINLOCK_UNLOCK_INITIALIZER \ - { \ - ESPOS_SPINLOCK_ARCH_UNLOCK_INITIALIZER, \ - } - -#define ESPOS_DEFINE_SPINLOCK(l) - -#define ESPOS_DEFINE_STATIC_SPINLOCK(l) - -/** - * @brief create a spinlock - * - * @param spinlock spinlock handle point - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_create (espos_spinlock_t *spinlock) -{ - return -ENODEV; -} - -/** - * @brief set a spinlock name - * - * @param spinlock spinlock handle - * @param name spinlock's name - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_set_name(espos_spinlock_t *spinlock, const char *name) -{ - return -ENODEV; -} - -/** - * @brief spin to lock a spinlock until successfully - * - * @param spinlock spinlock handle - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_lock(espos_spinlock_t *spinlock) -{ - return -ENODEV; -} - -/** - * @brief try to lock a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_trylock(espos_spinlock_t *spinlock) -{ - return -ENODEV; -} - -/** - * @brief get spinlock holder task handle - * - * @param spinlock spinlock handle - * - * @return none espos object - */ -static inline espos_task_t espos_spinlock_get_holder(espos_spinlock_t *spinlock) -{ - return ESPOS_OBJ_NONE; -} - -/** - * @brief unlock a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_unlock(espos_spinlock_t *spinlock) -{ - return -ENODEV; -} - -/** - * @brief delete a spinlock - * - * @param spinlock spinlock handle - * - * @return the result - * -ENODEV : no device - */ -static inline esp_err_t espos_spinlock_del(espos_spinlock_t *spinlock) -{ - return -ENODEV; -} - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_SPINLOCK_H_ */ diff --git a/components/espos/include/espos_task.h b/components/espos/include/espos_task.h deleted file mode 100644 index fcb449a8e..000000000 --- a/components/espos/include/espos_task.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_TASK_H_ -#define _ESPOS_TASK_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* task will run at any CPU */ -#define ESPOS_TASK_NO_AFFINITY -1 - -typedef enum espos_task_opt { - /* create task and start it automatically */ - ESPOS_TASK_CREATE_NORMAL = 0, - /* just create task and don't start it */ - ESPOS_TASK_CREATE_SILENCE, - - ESPOS_TASK_OPT_MAX -} espos_task_opt_t; - -/* task delete itself */ -#define ESPOS_TASK_DELETE_SELF 0 - -/* - * we should use a platform API instead of 'marco' - */ -#define ESPOS_TASK_PRIO_NUM espos_task_prio_num() - -/* task maximum priority number */ -#define ESPOS_TASK_PRIO_MAX (ESPOS_TASK_PRIO_NUM - 1) - -/** - * @brief create a task - * - * @param task task handle point - * @param name task name, if name is NULL, we will use "default_task" default - * @param arg task entry function inputting parameter - * @param prio task priority - * @param ticks task time slice - * @param stack_size task stack size, its unit is "byte" - * @param entry task entry function - * @param opt task option - * ESPOS_TASK_CREATE_NORMAL : the created task will be started automatically - * ESPOS_TASK_CREATE_SILENCE : the created task will not be started automatically - * @param cpu_id task CPU id - * natural number : the task only runs at the CPU of the number - * ESPOS_TASK_NO_AFFINITY : the task runs at any CPU - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - */ -esp_err_t espos_task_create_on_cpu(espos_task_t *task, const char *name, void *arg, espos_prio_t prio, espos_tick_t ticks, - espos_size_t stack_size, espos_task_entry_t entry, espos_task_opt_t opt, espos_cpu_t cpu_id); - - -/** - * @brief create a task and set its CPU id to be "ESPOS_TASK_NO_AFFINITY" - * - * @param task task handle point - * @param name task name, if name is NULL, we will use "default_task" default - * @param arg task entry function inputting parameter - * @param prio task priority - * @param ticks task time slice - * @param stack_size task stack size, its unit is "byte" - * @param entry task entry function - * @param opt task option - * ESPOS_TASK_CREATE_NORMAL : the created task will be started automatically - * ESPOS_TASK_CREATE_SILENCE : the created task will not be started automatically - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - */ -#define espos_task_create(task, name, arg, prio, ticks, stack_size, entry, opt) \ - espos_task_create_on_cpu(task, name, arg, prio, ticks, stack_size, entry, opt, ESPOS_TASK_NO_AFFINITY) - -/** - * @brief delete a task - * - * @param task task handle - * ESPOS_TASK_DELETE_SELF : task will delete itself - * - * @return the result - * 0 : successful - * -EACCES : failed to do it with some special reason - */ -esp_err_t espos_task_del(espos_task_t task); - -/** - * @brief let current task sleep for some ticks - * - * @param delay_ticks system ticks - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_task_delay(const espos_tick_t delay_ticks); - -/** - * @brief suspend target task - * - * @param task task handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_task_suspend(espos_task_t task); - -/** - * @brief resume target task - * - * @param task task handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_task_resume(espos_task_t task); - -/** - * @brief yield the cpu once - * - * @return the result - * 0 : successful - * -EACCES : failed to do it with some special reason - */ -esp_err_t espos_task_yield(void); - -/** - * @brief get current task handle - * - * @return current task handle - */ -espos_task_t espos_task_get_current(void); - -/** - * @brief get current task name point - * - * @param task task handle - * @param pname pointing at name's point - * - * @return current task handle - */ -esp_err_t espos_task_get_name (espos_task_t task, char **pname); - -/** - * @brief set task private data - * - * @param task task handle - * @param idx task data index - * @param info task private data - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_task_set_private_data(espos_task_t task, int idx, void *info); - -/** - * @brief get task private data - * - * @param task task handle - * @param idx task data index - * @param info task private data point - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_task_get_private_data(espos_task_t task, int idx, void **info); - -/** - * @brief get CPU affinity of task - * - * @return CPU affinity of task - */ -espos_cpu_t espos_task_get_affinity(espos_task_t task); - -/** - * @brief get ESPOS task priority number - * - * @return ESPOS task priority number - */ -espos_size_t espos_task_prio_num(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_TASK_H_ */ diff --git a/components/espos/include/espos_time.h b/components/espos/include/espos_time.h deleted file mode 100644 index 6d8c4d915..000000000 --- a/components/espos/include/espos_time.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_TIME_H_ -#define _ESPOS_TIME_H_ - -#include "espos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * delay or wait for ticks, it is used by mutex, queue, - * semaphore, timer and so on - */ -/* no delay for ticks, function will return immediately */ -#define ESPOS_NO_DELAY 0u -/* delay forever, function will never return until event triggers */ -#define ESPOS_MAX_DELAY 0xffffffffu - -/** - * @brief get tick milliseconds per system tick - * - * @return current ticks - */ -espos_time_t espos_get_tick_per_ms(void); - -/** - * @brief get current system ticks - * - * @return current ticks - */ -espos_tick_t espos_get_tick_count(void); - -/** - * @brief transform milliseconds to system ticks - * - * @param ms milliseconds - * - * @return system ticks - * - * @note the function discards the shortage of digits, for example: - * 20ms -> 2 ticks ; 21ms -> 2 ticks; 29 -> 2 ticks - */ -espos_tick_t espos_ms_to_ticks(espos_time_t ms); - -/** - * @brief transform system ticks to milliseconds - * - * @param ticks system ticks - * - * @return milliseconds - */ -espos_time_t espos_ticks_to_ms(espos_tick_t ticks); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_TIME_H_ */ diff --git a/components/espos/include/espos_timer.h b/components/espos/include/espos_timer.h deleted file mode 100644 index 7c24e9a1b..000000000 --- a/components/espos/include/espos_timer.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_TIMER_H_ -#define _ESPOS_TIMER_H_ - -#include "espos_types.h" -#include "espos_errno.h" -#include "espos_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* timer just run once after starting it */ -#define ESPOS_TIMER_NO_AUTO_RUN 0 -/* timer run cycle after starting it */ -#define ESPOS_TIMER_AUTO_RUN (1 << 0) - -/* timer configuration command */ -typedef enum espos_timer_cmd { - /* configure time's period */ - ESPOS_TIMER_CHANGE_PERIOD = 0, - /* configure time to be "once" */ - ESPOS_TIMER_CHANGE_ONCE, - /* configure time to be "auto" */ - ESPOS_TIMER_CHANGE_AUTO, - - ESPOS_TIMER_CMD_MAX -} espos_timer_cmd_t; - -/** - * @brief create a timer - * - * @param timer timer handle point - * @param name timer name, if name is NULL, we will use "default_timer" default - * @param cb timer callback function - * @param arg timer entry function inputting parameter - * @param period_ticks timer period ticks - * @param opt timer option - * ESPOS_TIMER_NO_AUTO_RUN : created timer will run once, even if it is started, - * ESPOS_TIMER_AUTO_RUN : created timer will run automatically - * - * @return the result - * 0 : successful - * -ENOMEM : no enough memory - * -EINVAL : input parameter error - * -EINTR : you do this at interrupt state, and it is not supported - * - * @note after starting the created timer by "espos_timer_start", it will only run. - */ -esp_err_t espos_timer_create(espos_timer_t *timer, const char *name, espos_timer_cb_t cb, void *arg, - espos_tick_t period_ticks, espos_opt_t opt); - -/** - * @brief start a timer - * - * @param timer timer handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - * - * @note after starting the created timer by "espos_timer_start", it will only run - */ -esp_err_t espos_timer_start(espos_timer_t timer); - -/** - * @brief stop a timer - * - * @param timer timer handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - * - * @note the timer should be started again, if it is stopped - */ -esp_err_t espos_timer_stop(espos_timer_t timer); - -/** - * @brief configure a timer - * - * @param timer timer handle - * @param opt timer option command - * @param arg timer parameter - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - */ -esp_err_t espos_timer_change(espos_timer_t timer, espos_opt_t opt, void *arg); - -/** - * @brief configure period of timer - * - * @param t timer handle - * @param a timer period - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - */ -#define espos_timer_set_period(t, a) espos_timer_change(t, ESPOS_TIMER_CHANGE_PERIOD, (void *)a) - -/** - * @brief configure timer to be "once" - * - * @param t timer handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - */ -#define espos_timer_set_once(t) espos_timer_change(t, ESPOS_TIMER_CHANGE_ONCE, NULL) - -/** - * @brief configure timer to be "auto" - * - * @param t timer handle - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - * -ECANCELED : failed for some reason depend on low-level OS - */ -#define espos_timer_set_auto(t) espos_timer_change(t, ESPOS_TIMER_CHANGE_AUTO, NULL) - -/** - * @brief delete a timer - * - * @param t timer handle - * - * @return the result - * 0 : successful - * -EACCES : failed to do it with some special reason - * -EINTR : you do this at interrupt state, and it is not supported - */ -esp_err_t espos_timer_del(espos_timer_t timer); - -/** - * @brief get current timer name point - * - * @param timer timer handle - * @param pname pointing at name's point - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_get_timer_name (espos_timer_t timer, char **pname); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESPOS_TIMER_H_ */ diff --git a/components/espos/include/espos_types.h b/components/espos/include/espos_types.h deleted file mode 100644 index 5f78a910b..000000000 --- a/components/espos/include/espos_types.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESPOS_TYPES_H_ -#define _ESPOS_TYPES_H_ - -#include -#include -#include - -#include "arch/espos_arch.h" - -#define ESPOS_OBJ_NONE 0 - -typedef uintptr_t espos_obj_t; - -typedef espos_obj_t espos_task_t; -typedef espos_obj_t espos_queue_t; -typedef espos_obj_t espos_mutex_t; -typedef espos_obj_t espos_sem_t; -typedef espos_obj_t espos_timer_t; -typedef espos_obj_t espos_critical_t; - -typedef size_t espos_size_t; -typedef size_t espos_pos_t; -typedef uint8_t espos_prio_t; -typedef uint32_t espos_opt_t; -typedef int32_t espos_cpu_t; - -typedef espos_size_t espos_tick_t; -typedef espos_size_t espos_time_t; -typedef espos_size_t espos_sem_count_t; - -typedef void (*espos_task_entry_t)(void *p); -typedef void (*espos_timer_cb_t)(espos_timer_t timer, void *arg); - -#endif /* _ESPOS_TYPES_H_ */ diff --git a/components/espos/platform/freertos/espos_mutex.c b/components/espos/platform/freertos/espos_mutex.c deleted file mode 100644 index 882bef88b..000000000 --- a/components/espos/platform/freertos/espos_mutex.c +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/task.h" - -#include "espos_mutex.h" -#include "espos_scheduler.h" - -/* real ESPOS mutex structure */ -typedef struct espos_mutex_os { - espos_opt_t opt; - SemaphoreHandle_t mutex; -} espos_mutex_os_t; - -/** - * @brief create a mutex - */ -esp_err_t espos_mutex_create ( - espos_mutex_t *mutex, - espos_mutex_type_opt_t opt -) -{ - esp_err_t ret; - espos_mutex_os_t *os_mutex; - - if (!mutex || (ESPOS_MUTEX_TYPE(opt) >= ESPOS_MUTEX_TYPE_MAX)) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - os_mutex = malloc(sizeof(espos_mutex_os_t)); - if (!os_mutex) { - return -ENOMEM; - } - - switch (ESPOS_MUTEX_TYPE(opt)) { - case ESPOS_MUTEX_NORMAL: - os_mutex->mutex = xSemaphoreCreateMutex(); - break; - case ESPOS_MUTEX_RECURSIVE: - os_mutex->mutex = xSemaphoreCreateRecursiveMutex(); - break; - default : - os_mutex->mutex = NULL; - break; - } - - if (os_mutex->mutex) { - ret = 0; - os_mutex->opt = opt; - *mutex = (espos_mutex_t)os_mutex; - } else { - free(os_mutex); - ret = -ENOMEM; - } - - return ret; -} - -/** - * @brief set a mutex name - */ -esp_err_t espos_mutex_set_name(espos_mutex_t mutex, const char *name) -{ - return 0; -} - -/** - * @brief lock a mutex - */ -esp_err_t espos_mutex_lock ( - espos_mutex_t mutex, - espos_tick_t wait_ticks -) -{ - esp_err_t ret; - espos_mutex_os_t *os_mutex = (espos_mutex_os_t *)mutex; - - if (!os_mutex) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - switch (ESPOS_MUTEX_TYPE(os_mutex->opt)) { - case ESPOS_MUTEX_NORMAL: - ret = xSemaphoreTake(os_mutex->mutex, wait_ticks); - break; - case ESPOS_MUTEX_RECURSIVE: - ret = xSemaphoreTakeRecursive(os_mutex->mutex, wait_ticks); - break; - default: - ret = -EINVAL; - break; - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - - return ret; -} - -/** - * @brief unlock a mutex - */ -esp_err_t espos_mutex_unlock ( - espos_mutex_t mutex -) -{ - esp_err_t ret; - espos_mutex_os_t *os_mutex = (espos_mutex_os_t *)mutex; - - if (!os_mutex) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - if (xSemaphoreGetMutexHolder(os_mutex->mutex) != xTaskGetCurrentTaskHandle()) { - return -EPERM; - } - - switch (ESPOS_MUTEX_TYPE(os_mutex->opt)) { - case ESPOS_MUTEX_NORMAL: - ret = xSemaphoreGive(os_mutex->mutex); - break; - case ESPOS_MUTEX_RECURSIVE: - ret = xSemaphoreGiveRecursive(os_mutex->mutex); - break; - default: - ret = -EINVAL; - break; - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -EPERM; - } - - return ret; -} - -/** - * @brief get task handle whick lock the mutex - */ -espos_task_t espos_mutex_get_holder ( - espos_mutex_t mutex -) -{ - espos_task_t tmp; - espos_mutex_os_t *os_mutex = (espos_mutex_os_t *)mutex; - - if (!os_mutex) { - return -EINVAL; - } - - tmp = (espos_task_t)xSemaphoreGetMutexHolder(os_mutex->mutex); - - return tmp; -} - -/** - * @brief delete the mutex - */ -esp_err_t espos_mutex_del ( - espos_mutex_t mutex -) -{ - espos_mutex_os_t *os_mutex = (espos_mutex_os_t *)mutex; - - if (!os_mutex) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - vSemaphoreDelete(os_mutex->mutex); - free(os_mutex); - - return 0; -} - diff --git a/components/espos/platform/freertos/espos_queue.c b/components/espos/platform/freertos/espos_queue.c deleted file mode 100644 index a6753c67d..000000000 --- a/components/espos/platform/freertos/espos_queue.c +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#include "espos_queue.h" -#include "espos_scheduler.h" - -#define portYIELD_FROM_ISR() taskYIELD() - -/** - * @brief create a queue - */ -esp_err_t espos_queue_create ( - espos_queue_t *queue, - espos_size_t msg_len, - espos_size_t queue_len -) -{ - esp_err_t ret; - QueueHandle_t os_queue; - - if (!queue || !msg_len || !queue_len) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - os_queue = xQueueCreate(queue_len, msg_len); - if (os_queue) { - ret = 0; - *queue = (espos_queue_t)os_queue; - } else { - ret = -ENOMEM; - } - - return ret; -} - -/** - * @brief set a queue name - * - * @param queue queue handle - * @param name queue's name - * - * @return the result - * 0 : successful - * -EINVAL : input parameter error - */ -esp_err_t espos_queue_set_name(espos_queue_t queue, const char *name) -{ - return 0; -} - -/** - * @brief send a message to the queue - */ -esp_err_t espos_queue_send_generic ( - espos_queue_t queue, - void *msg, - espos_tick_t wait_ticks, - espos_pos_t pos, - espos_opt_t opt -) -{ - esp_err_t ret; - QueueHandle_t os_queue = (QueueHandle_t)queue; - - if (!queue || !msg || pos >= ESPOS_QUEUE_POS_MAX - || opt >= ESPOS_QUEUE_SEND_OPT_MAX) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - if (pos == ESPOS_QUEUE_SEND_FRONT) { - ret = xQueueSendToFrontFromISR(os_queue, msg, &xHigherPrioritTaskWoken); - } else if (pos == ESPOS_QUEUE_SEND_BACK) { - ret = xQueueSendToBackFromISR(os_queue, msg, &xHigherPrioritTaskWoken); - } else { - ret = pdFAIL; - } - - if (pdPASS == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdPASS) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } else { - if (pos == ESPOS_QUEUE_SEND_FRONT) { - ret = xQueueSendToFront(os_queue, msg, wait_ticks); - } else if (pos == ESPOS_QUEUE_SEND_BACK) { - ret = xQueueSendToBack(os_queue, msg, wait_ticks); - } else { - ret = pdFAIL; - } - - if (ret == pdPASS) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } - - return ret; -} - -/** - * @brief receive a message of the queue - */ -esp_err_t espos_queue_recv_generic ( - espos_queue_t queue, - void *msg, - espos_tick_t wait_ticks, - espos_opt_t opt -) -{ - esp_err_t ret; - QueueHandle_t os_queue = (QueueHandle_t)queue; - - if (!os_queue || !msg || opt >= ESPOS_QUEUE_RECV_OPT_MAX) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xQueueReceiveFromISR(os_queue, msg, &xHigherPrioritTaskWoken); - if (pdTRUE == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } else { - ret = xQueueReceive(os_queue, msg, wait_ticks); - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } - - return ret; - -} - -/** - * @brief get current message number of the queue - */ -espos_size_t espos_queue_msg_waiting(espos_queue_t queue) -{ - UBaseType_t num; - QueueHandle_t os_queue = (QueueHandle_t)queue; - - if (!os_queue) { - return 0; - } - - num = uxQueueMessagesWaiting(os_queue); - - return num; -} - -/** - * @brief reset the queue - */ -esp_err_t espos_queue_flush ( - espos_queue_t queue -) -{ - BaseType_t ret; - QueueHandle_t os_queue = (QueueHandle_t)queue; - - if (!os_queue) { - return -EINVAL; - } - - ret = xQueueReset(os_queue); - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -EINVAL; - } - - return 0; -} - -/** - * @brief delete the queue - */ -esp_err_t espos_queue_del ( - espos_queue_t queue -) -{ - QueueHandle_t os_queue = (QueueHandle_t)queue; - - if (!os_queue) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - vQueueDelete(os_queue); - - return 0; -} - diff --git a/components/espos/platform/freertos/espos_scheduler.c b/components/espos/platform/freertos/espos_scheduler.c deleted file mode 100644 index ff2f4edb8..000000000 --- a/components/espos/platform/freertos/espos_scheduler.c +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#include "espos_scheduler.h" - -#define portYIELD_FROM_ISR() taskYIELD() - -static espos_size_t s_isr_nested_count[ESPOS_PROCESSORS_NUM]; -static espos_size_t s_os_nested_count[ESPOS_PROCESSORS_NUM]; -static espos_size_t s_critial_count[ESPOS_PROCESSORS_NUM]; -static espos_critical_t s_critical_state[ESPOS_PROCESSORS_NUM]; - -/** - * @brief initialize ESPOS system - */ -esp_err_t espos_init(void) -{ - return 0; -} - -/** - * @brief start ESPOS system - */ -esp_err_t espos_start(void) -{ - vTaskStartScheduler(); - - return 0; -} - -/** - * @brief get ESPOS system state - */ -espos_stat_t espos_sched_state_get(void) -{ - espos_stat_t state; - BaseType_t os_state = xTaskGetSchedulerState(); - - if (os_state == taskSCHEDULER_NOT_STARTED) { - state = ESPOS_IS_NOT_STARTED; - } else if (os_state == taskSCHEDULER_RUNNING) { - state = ESPOS_IS_RUNNING; - } else { - state = ESPOS_IS_SUSPENDED; - } - - return state; -} - -/** - * @brief check if the CPU is at ISR state - */ -bool espos_in_isr(void) -{ - extern char _xt_isr_status; - //return (s_isr_nested_count[espos_get_core_id()] > 0) ? true : false; - return _xt_isr_status == 0 ? false : true; -} - -/** - * @brief check if the function is at real OS internal fucntion - */ -bool espos_os_isr(void) -{ - return (s_os_nested_count[espos_get_core_id()] > 0) ? true : false; -} - -/** - * @brief enter ESPOS system critical state - */ -espos_critical_t _espos_enter_critical(espos_spinlock_t *spinlock) -{ - espos_critical_t tmp; - - tmp = espos_suspend_interrupt(); - - if (!s_critial_count[espos_get_core_id()]) - s_critical_state[espos_get_core_id()] = tmp; - s_critial_count[espos_get_core_id()]++; - -#ifdef CONFIG_ESPOS_SMP - if (espos_spinlock_get_holder(spinlock) != espos_task_get_current()) - espos_spinlock_lock(spinlock); -#else - //espos_preempt_suspend_local(); -#endif - - return tmp; -} - -/** - * @brief exit ESPOS system critical state - */ -void _espos_exit_critical(espos_spinlock_t *spinlock, espos_critical_t tmp) -{ -#ifdef CONFIG_ESPOS_SMP - espos_spinlock_unlock(spinlock); -#else - //espos_preempt_resume_local(); -#endif - - s_critial_count[espos_get_core_id()]--; - if (!s_critial_count[espos_get_core_id()]) { - espos_resume_interrupt( s_critical_state[espos_get_core_id()]); - } -} - - -/** -* @brief suspend the preempt and the current task will not be preempted -*/ -esp_err_t espos_preempt_suspend_local(void) -{ - vTaskSuspendAll(); - - return 0; -} - -/** - * @brief resume the preempt - */ -esp_err_t espos_preempt_resume_local(void) -{ - if (xTaskResumeAll() == 0) { - taskYIELD(); - } - - return 0; -} - -/** - * @brief enter system interrupt server, the function must be used after entering hardware interrupt - */ -esp_err_t espos_isr_enter (void) -{ - s_isr_nested_count[espos_get_core_id()]++; - - return 0; -} - -/** - * @brief exit system interrupt server, the function must be used before exiting hardware interrupt - */ -void espos_isr_exit(void) -{ - if (!s_isr_nested_count[espos_get_core_id()]) { - return ; - } - - s_isr_nested_count[espos_get_core_id()]--; - - return ; -} - -/** - * @brief mark it enters real OS interal function - */ -esp_err_t espos_os_enter (void) -{ - s_os_nested_count[espos_get_core_id()]++; - - return 0; -} - -/** - * @brief remove mark it enters real OS interal function - */ -void espos_os_exit(void) -{ - if (!s_os_nested_count[espos_get_core_id()]) { - return ; - } - - s_os_nested_count[espos_get_core_id()]--; - - return ; -} diff --git a/components/espos/platform/freertos/espos_semaphore.c b/components/espos/platform/freertos/espos_semaphore.c deleted file mode 100644 index 3e4419a52..000000000 --- a/components/espos/platform/freertos/espos_semaphore.c +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/task.h" - -#include "espos_semaphore.h" -#include "espos_scheduler.h" - -#define portYIELD_FROM_ISR() taskYIELD() - -/** - * @brief create a semaphore - */ -esp_err_t espos_sem_create ( - espos_sem_t *sem, - espos_sem_count_t max_count, - espos_sem_count_t init_count -) -{ - esp_err_t ret; - SemaphoreHandle_t os_mutex; - - if (!sem || !max_count) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - os_mutex = xSemaphoreCreateCounting(max_count, init_count); - if (os_mutex) { - ret = 0; - *sem = (espos_sem_t)os_mutex; - } else { - ret = -ENOMEM; - } - - return ret; -} - -/** - * @brief set a semaphore name - */ -esp_err_t espos_sem_set_name(espos_sem_t sem, const char *name) -{ - return 0; -} - -/** - * @brief take semaphore - */ -esp_err_t espos_sem_take ( - espos_sem_t sem, - espos_tick_t wait_ticks -) -{ - esp_err_t ret; - SemaphoreHandle_t os_sem = (SemaphoreHandle_t)sem; - - if (!os_sem) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xSemaphoreTakeFromISR(os_sem, &xHigherPrioritTaskWoken); - if (pdPASS == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdPASS) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } else { - ret = xSemaphoreTake(os_sem, wait_ticks); - if (ret == pdPASS) { - ret = 0; - } else { - ret = -ETIMEDOUT; - } - } - - return ret; -} - -/** - * @brief give up semaphore - */ -esp_err_t espos_sem_give ( - espos_sem_t sem -) -{ - BaseType_t ret; - SemaphoreHandle_t os_sem = (SemaphoreHandle_t)sem; - - if (!os_sem) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xSemaphoreGiveFromISR(os_sem, &xHigherPrioritTaskWoken); - if (pdPASS == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdPASS) { - ret = 0; - } else { - ret = -EAGAIN; - } - } else { - ret = xSemaphoreGive(os_sem); - if (ret == pdPASS) { - ret = 0; - } else { - ret = -EAGAIN; - } - } - - return ret; -} - -/** - * @brief delete the semaphore - */ -esp_err_t espos_sem_del ( - espos_sem_t sem -) -{ - SemaphoreHandle_t os_sem = (SemaphoreHandle_t)sem; - - if (!os_sem) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - vSemaphoreDelete(os_sem); - - return 0; -} - diff --git a/components/espos/platform/freertos/espos_task.c b/components/espos/platform/freertos/espos_task.c deleted file mode 100644 index 9d98054fe..000000000 --- a/components/espos/platform/freertos/espos_task.c +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "espos_task.h" -#include "espos_scheduler.h" - -#define portYIELD_FROM_ISR() taskYIELD() - -/** - * @brief create a task - */ -esp_err_t espos_task_create_on_cpu ( - espos_task_t *task, - const char *name, - void *arg, - espos_prio_t prio, - espos_tick_t ticks, - espos_size_t stack_size, - espos_task_entry_t entry, - espos_task_opt_t opt, - espos_cpu_t cpu_id -) -{ - BaseType_t ret; - TaskHandle_t os_task; - - if (!task || !name || !stack_size || !entry) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - ret = xTaskCreate(entry, name, stack_size, arg, prio, &os_task); - if (ret == pdPASS) { - ret = 0; - - *task = (espos_task_t)os_task; - } else { - ret = -ENOMEM; - } - - return ret; -} - -/** - * @brief delete a task - */ -esp_err_t espos_task_del ( - espos_task_t task -) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (espos_in_isr() == true) { - return -EINTR; - } - - vTaskDelete(os_task); - - return 0; -} - -/** - * @brief let current task sleep for some ticks - */ -esp_err_t espos_task_delay ( - const espos_tick_t delay_ticks -) -{ - vTaskDelay(delay_ticks); - - return 0; -} - -/** - * @brief suspend target task - */ -esp_err_t espos_task_suspend ( - espos_task_t task -) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task) { - return -EINVAL; - } - - vTaskSuspend(os_task); - - return 0; -} - -/** - * @brief resume target task - */ -esp_err_t espos_task_resume ( - espos_task_t task -) -{ - esp_err_t ret; - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - ret = xTaskResumeFromISR(os_task); - if (ret == pdTRUE) { - ret = 0; - portYIELD_FROM_ISR(); - } else { - ret = -ECANCELED; - } - - } else { - vTaskResume(os_task); - ret = 0; - } - - return 0; -} - -/** - * @brief yield the cpu once - */ -esp_err_t espos_task_yield(void) -{ - taskYIELD(); - - return 0; -} - -/** - * @brief get current task handle - */ -espos_task_t espos_task_get_current(void) -{ - return (espos_task_t)xTaskGetCurrentTaskHandle(); -} - -/** - * @brief get current task name point - */ -esp_err_t espos_task_get_name ( - espos_task_t task, - char **pname -) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task) { - return -EINVAL; - } - - *pname = (char *)pcTaskGetTaskName(os_task); - - return 0; -} - -#if 0 - -/** - * @brief set task private data - */ -esp_err_t espos_task_set_private_data ( - espos_task_t task, - int idx, - void *info -) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task) { - return -EINVAL; - } - - vTaskSetThreadLocalStoragePointer(os_task, idx, info); - - return 0; -} - -/** - * @brief get task private data - */ -esp_err_t espos_task_get_private_data ( - espos_task_t task, - int idx, - void **info -) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task || !info) { - return -EINVAL; - } - - *info = pvTaskGetThreadLocalStoragePointer(os_task, idx); - - return 0; -} - -/** - * @brief get cpu affinity of task - */ -espos_cpu_t espos_task_get_affinity(espos_task_t task) -{ - TaskHandle_t os_task = (TaskHandle_t)task; - - if (!os_task) { - return -EINVAL; - } - - return xTaskGetAffinity(os_task); -} - -#endif - -/** - * @brief get ESPOS task priority number - */ -espos_size_t espos_task_prio_num(void) -{ - return configMAX_PRIORITIES + 1; -} diff --git a/components/espos/platform/freertos/espos_time.c b/components/espos/platform/freertos/espos_time.c deleted file mode 100644 index 445f83740..000000000 --- a/components/espos/platform/freertos/espos_time.c +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "espos_time.h" - -espos_time_t espos_get_tick_per_ms(void) -{ - return portTICK_PERIOD_MS; -} - -/** - * @brief get current system ticks - */ -espos_tick_t espos_get_tick_count(void) -{ - return (espos_tick_t)xTaskGetTickCount(); -} - -/** - * @brief transform milliseconds to system ticks - */ -espos_tick_t espos_ms_to_ticks(espos_time_t ms) -{ - return (ms / (portTICK_PERIOD_MS)); -} - -/** - * @brief transform system ticks to milliseconds - */ -espos_time_t espos_ticks_to_ms(espos_tick_t ticks) -{ - return (ticks * (portTICK_PERIOD_MS)); -} - -void espos_add_tick_count(size_t t) -{ - vTaskStepTick((portTickType)t); -} diff --git a/components/espos/platform/freertos/espos_timer.c b/components/espos/platform/freertos/espos_timer.c deleted file mode 100644 index 9dc1352e7..000000000 --- a/components/espos/platform/freertos/espos_timer.c +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/timers.h" - -#include "espos_timer.h" -#include "espos_scheduler.h" - -#define portYIELD_FROM_ISR() taskYIELD() - -typedef struct espos_timer_os { - /* FreeRTOS handle */ - TimerHandle_t timer; - - /* ESPOS timer callback function */ - espos_timer_cb_t cb; - - /* ESPOS timer private parameter*/ - void *priv; -} espos_timer_os_t; - -/** - * @brief FreeRTOS callback function - */ -static void os_timer_callback(TimerHandle_t xTimer) -{ - espos_timer_os_t *os_timer = - (espos_timer_os_t *)pvTimerGetTimerID(xTimer); - espos_timer_t timer = (espos_timer_t)os_timer; - - os_timer->cb(timer, os_timer->priv); -} - -/** - * @brief create a timer - */ -esp_err_t espos_timer_create ( - espos_timer_t *timer, - const char *name, - espos_timer_cb_t cb, - void *arg, - espos_tick_t period_ticks, - espos_opt_t opt -) -{ - espos_timer_os_t *os_timer; - UBaseType_t auto_load; - esp_err_t ret; - - if (!timer || !name || !cb || !period_ticks) { - return -EINVAL; - } - - if (opt == ESPOS_TIMER_AUTO_RUN) { - auto_load = pdTRUE; - } else if (opt == ESPOS_TIMER_NO_AUTO_RUN) { - auto_load = pdFALSE; - } else { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - os_timer = malloc(sizeof(espos_timer_os_t)); - if (!os_timer) { - return -ENOMEM; - } - - os_timer->timer = xTimerCreate(name, period_ticks, auto_load, os_timer, os_timer_callback); - if (os_timer->timer) { - ret = 0; - - os_timer->cb = cb; - os_timer->priv = arg; - - *timer = (espos_timer_t)os_timer; - } else { - ret = -ENOMEM; - - free(os_timer); - } - - return ret; -} - -/** - * @brief start a timer - */ -esp_err_t espos_timer_start ( - espos_timer_t timer -) -{ - esp_err_t ret; - espos_timer_os_t *os_timer = (espos_timer_os_t *)timer; - - if (!os_timer) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xTimerStartFromISR(os_timer->timer, &xHigherPrioritTaskWoken); - if (pdTRUE == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } else { - ret = xTimerStart(os_timer->timer, ESPOS_MAX_DELAY); - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } - - return ret; -} - -/** - * @brief stop a timer - */ -esp_err_t espos_timer_stop ( - espos_timer_t timer -) -{ - esp_err_t ret; - espos_timer_os_t *os_timer = (espos_timer_os_t *)timer; - - if (!os_timer) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xTimerStopFromISR(os_timer->timer, &xHigherPrioritTaskWoken); - if (pdTRUE == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } else { - ret = xTimerStop(os_timer->timer, ESPOS_MAX_DELAY); - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } - - return ret; -} - -/** - * @brief configure a timer - */ -esp_err_t espos_timer_change ( - espos_timer_t timer, - espos_opt_t opt, - void *arg -) -{ - esp_err_t ret; - espos_timer_os_t *os_timer = (espos_timer_os_t *)timer; - - if (!os_timer) { - return -EINVAL; - } - - if (ESPOS_TIMER_CHANGE_PERIOD == opt) { - TickType_t period = (TickType_t)arg; - - if (espos_in_isr() == true) { - BaseType_t xHigherPrioritTaskWoken = pdFALSE; - - ret = xTimerChangePeriodFromISR(os_timer->timer, period, &xHigherPrioritTaskWoken); - if (pdTRUE == ret && pdTRUE == xHigherPrioritTaskWoken) { - portYIELD_FROM_ISR(); - } - - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } else { - ret = xTimerChangePeriod(os_timer->timer, period, ESPOS_MAX_DELAY); - if (ret == pdTRUE) { - ret = 0; - } else { - ret = -ECANCELED; - } - } - } else if (ESPOS_TIMER_CHANGE_ONCE == opt) { - return -EINVAL; - } else if (ESPOS_TIMER_CHANGE_AUTO == opt) { - return -EINVAL; - } else { - return -EINVAL; - } - - return -ret; -} - -/** - * @brief delete a timer - */ -esp_err_t espos_timer_del ( - espos_timer_t timer -) -{ - esp_err_t ret; - espos_timer_os_t *os_timer = (espos_timer_os_t *)timer; - - if (!os_timer) { - return -EINVAL; - } - - if (espos_in_isr() == true) { - return -EINTR; - } - - ret = xTimerDelete(os_timer->timer, ESPOS_MAX_DELAY); - if (ret == pdTRUE) { - ret = 0; - free(os_timer); - } else { - ret = -ECANCELED; - } - - return ret; -} - -/** - * @brief get current timer name point - */ -esp_err_t espos_get_timer_name ( - espos_timer_t timer, - char **tname -) -{ - espos_timer_os_t *os_timer = (espos_timer_os_t *)timer; - - if (!os_timer) { - return -EINVAL; - } - - *tname = NULL; - - return -ENODEV; -} - diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index bdd55ceea..d30210531 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -1 +1,81 @@ -register_config_only_component() +idf_component_register(REQUIRES bootloader) + +if(NOT BOOTLOADER_BUILD) + string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}") + set(ESPTOOLPY_FLASH_PROJECT_OPTIONS + "${ESPTOOLPY_FLASH_PROJECT_OPTIONS}" + ) + + if(CONFIG_SECURE_BOOT_ENABLED) + set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "") + endif() + + # FLASH_PROJECT_ARGS, FLASH_PROJECT_ARGS_JSON, FLASH_PROJECT_ARGS_ENTRY_JSON + # are used in the flasher args input files (flash_project_args.in, flasher_args.json.in) + idf_component_get_property(FLASH_PROJECT_ARGS ${COMPONENT_NAME} + FLASH_PROJECT_ARGS GENERATOR_EXPRESSION) + idf_component_get_property(FLASH_PROJECT_ARGS_JSON ${COMPONENT_NAME} + FLASH_PROJECT_ARGS_JSON GENERATOR_EXPRESSION) + idf_component_get_property(FLASH_PROJECT_ARGS_ENTRY_JSON ${COMPONENT_NAME} + FLASH_PROJECT_ARGS_ENTRY_JSON GENERATOR_EXPRESSION) + + # Generate the flash project args and the flasher args json file using the accumulated values + # from esptool_py_flash_project_args calls. The file is first configured using configure_file() for all variable values, + # and then generated using file(GENERATE... for generator expressions. + configure_file(${COMPONENT_DIR}/flash_project_args.in + ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in) + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2 + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2) + + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in + ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in) + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2 + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_encrypted_project_args + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2) + endif() + + configure_file(${COMPONENT_DIR}/flasher_args.json.in + ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in) + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2 + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flasher_args.json + INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2) + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in" + "${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2" + "${CMAKE_BINARY_DIR}/flash_project_args" + "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in" + "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2" + "${CMAKE_BINARY_DIR}/flasher_args.json") + + idf_build_get_property(build_dir BUILD_DIR) + partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") + esptool_py_flash_project_args(app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} FLASH_IN_PROJECT) + + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in "--encrypt ${app_partition_offset} ${PROJECT_BIN}") + esptool_py_flash_project_args(encrypted_app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} + FLASH_FILE_TEMPLATE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in) + endif() + + add_dependencies(flash partition_table) + + # If anti-rollback option is set then factory partition should not be in Partition Table. + # In this case, should be used the partition table with two ota app without the factory. + partition_table_get_partition_info(factory_offset "--partition-type app --partition-subtype factory" "offset") + if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND factory_offset) + fail_at_build_time(check_table_contents + "ERROR: Anti-rollback option is enabled. Partition table should consist of two ota app without factory partition.") + add_dependencies(app check_table_contents) + endif() +endif() + diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 7b29f4e33..46230a81a 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -48,18 +48,20 @@ config ESPTOOLPY_COMPRESSED choice FLASHMODE prompt "Flash SPI mode" - default FLASHMODE_QIO + default ESPTOOLPY_FLASHMODE_QIO help Mode the flash chip is flashed in, as well as the default mode for the binary to run in. -config FLASHMODE_QIO + The esptool.py flashes firmware at DIO mode when user select "QIO", "QOUT" or "DIO" mode. + +config ESPTOOLPY_FLASHMODE_QIO bool "QIO" -config FLASHMODE_QOUT +config ESPTOOLPY_FLASHMODE_QOUT bool "QOUT" -config FLASHMODE_DIO +config ESPTOOLPY_FLASHMODE_DIO bool "DIO" -config FLASHMODE_DOUT +config ESPTOOLPY_FLASHMODE_DOUT bool "DOUT" endchoice @@ -68,10 +70,17 @@ endchoice # itself to quad mode during initialisation config ESPTOOLPY_FLASHMODE string - default "qio" if FLASHMODE_QIO - default "qout" if FLASHMODE_QOUT - default "dio" if FLASHMODE_DIO - default "dout" if FLASHMODE_DOUT + default "dio" if ESPTOOLPY_FLASHMODE_QIO + default "dio" if ESPTOOLPY_FLASHMODE_QOUT + default "dio" if ESPTOOLPY_FLASHMODE_DIO + default "dout" if ESPTOOLPY_FLASHMODE_DOUT + +config SPI_FLASH_MODE + hex + default 0x0 if ESPTOOLPY_FLASHMODE_QIO + default 0x1 if ESPTOOLPY_FLASHMODE_QOUT + default 0x2 if ESPTOOLPY_FLASHMODE_DIO + default 0x3 if ESPTOOLPY_FLASHMODE_DOUT choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" @@ -96,12 +105,20 @@ config ESPTOOLPY_FLASHFREQ default "26m" if ESPTOOLPY_FLASHFREQ_26M default "20m" if ESPTOOLPY_FLASHFREQ_20M +config SPI_FLASH_FREQ + hex + default 0xf if ESPTOOLPY_FLASHFREQ_80M + default 0x0 if ESPTOOLPY_FLASHFREQ_40M + default 0x1 if ESPTOOLPY_FLASHFREQ_26M + default 0x2 if ESPTOOLPY_FLASHFREQ_20M choice ESPTOOLPY_FLASHSIZE prompt "Flash size" default ESPTOOLPY_FLASHSIZE_2MB help - SPI flash size, in megabytes + SPI flash size, in megabytes. Users must not configure a larger value than their real flash size. + Otherwise an unexpected result may cause if users read/write a wrong address of flash. + config ESPTOOLPY_FLASHSIZE_1MB bool "1 MB" config ESPTOOLPY_FLASHSIZE_2MB @@ -122,6 +139,14 @@ config ESPTOOLPY_FLASHSIZE default "8MB" if ESPTOOLPY_FLASHSIZE_8MB default "16MB" if ESPTOOLPY_FLASHSIZE_16MB +config SPI_FLASH_SIZE + hex + default 0x100000 if ESPTOOLPY_FLASHSIZE_1MB + default 0x200000 if ESPTOOLPY_FLASHSIZE_2MB + default 0x400000 if ESPTOOLPY_FLASHSIZE_4MB + default 0x800000 if ESPTOOLPY_FLASHSIZE_8MB + default 0x1000000 if ESPTOOLPY_FLASHSIZE_16MB + choice ESPTOOLPY_BEFORE prompt "Before flashing" default ESPTOOLPY_BEFORE_RESET @@ -145,72 +170,69 @@ config ESPTOOLPY_BEFORE choice ESPTOOLPY_AFTER prompt "After flashing" - default ESPTOOLPY_AFTER_RESET + default ESPTOOLPY_AFTER_HARD_RESET help - Configure whether esptool.py should reset the ESP32 after flashing. + Configure whether esptool.py should reset the ESP8266 after flashing. Automatic resetting depends on the RTS & DTR signals being wired from the serial port to the ESP32. Most USB development boards do this internally. -config ESPTOOLPY_AFTER_RESET - bool "Reset after flashing" +config ESPTOOLPY_AFTER_HARD_RESET + bool "Hard reset after flashing" +config ESPTOOLPY_AFTER_SOFT_RESET + bool "Soft reset after flashing" config ESPTOOLPY_AFTER_NORESET bool "Stay in bootloader" endchoice config ESPTOOLPY_AFTER string - default "hard_reset" if ESPTOOLPY_AFTER_RESET + default "hard_reset" if ESPTOOLPY_AFTER_HARD_RESET + default "soft_reset" if ESPTOOLPY_AFTER_SOFT_RESET default "no_reset" if ESPTOOLPY_AFTER_NORESET -choice MONITOR_BAUD +choice ESPTOOLPY_MONITOR_BAUD prompt "'make monitor' baud rate" - default MONITOR_BAUD_74880B + default ESPTOOLPY_MONITOR_BAUD_74880B help Baud rate to use when running 'make monitor' to view serial output from a running chip. Can override by setting the MONITORBAUD environment variable. -config MONITOR_BAUD_9600B +config ESPTOOLPY_MONITOR_BAUD_9600B bool "9600 bps" -config MONITOR_BAUD_57600B +config ESPTOOLPY_MONITOR_BAUD_57600B bool "57600 bps" -config MONITOR_BAUD_74880B +config ESPTOOLPY_MONITOR_BAUD_74880B bool "74880 bps" -config MONITOR_BAUD_115200B +config ESPTOOLPY_MONITOR_BAUD_115200B bool "115200 bps" -config MONITOR_BAUD_230400B +config ESPTOOLPY_MONITOR_BAUD_230400B bool "230400 bps" -config MONITOR_BAUD_921600B +config ESPTOOLPY_MONITOR_BAUD_921600B bool "921600 bps" -config MONITOR_BAUD_2MB +config ESPTOOLPY_MONITOR_BAUD_2MB bool "2 Mbps" -config MONITOR_BAUD_OTHER +config ESPTOOLPY_MONITOR_BAUD_OTHER bool "Custom baud rate" endchoice -config MONITOR_BAUD_OTHER_VAL +config ESPTOOLPY_MONITOR_BAUD_OTHER_VAL int "Custom baud rate value" if MONITOR_BAUD_OTHER default 74880 -config MONITOR_BAUD +config ESPTOOLPY_MONITOR_BAUD int - default 9600 if MONITOR_BAUD_9600B - default 57600 if MONITOR_BAUD_57600B - default 74880 if MONITOR_BAUD_74880B - default 115200 if MONITOR_BAUD_115200B - default 230400 if MONITOR_BAUD_230400B - default 921600 if MONITOR_BAUD_921600B - default 2000000 if MONITOR_BAUD_2MB - default MONITOR_BAUD_OTHER_VAL if MONITOR_BAUD_OTHER - -config ESPTOOLPY_ENABLE_TIME - bool "Enable monitor time information" - default n - help - Enable this option, time string will be added at the head of serial input data line. + default 9600 if ESPTOOLPY_MONITOR_BAUD_9600B + default 57600 if ESPTOOLPY_MONITOR_BAUD_57600B + default 74880 if ESPTOOLPY_MONITOR_BAUD_74880B + default 115200 if ESPTOOLPY_MONITOR_BAUD_115200B + default 230400 if ESPTOOLPY_MONITOR_BAUD_230400B + default 921600 if ESPTOOLPY_MONITOR_BAUD_921600B + default 2000000 if ESPTOOLPY_MONITOR_BAUD_2MB + default ESPTOOLPY_MONITOR_BAUD_OTHER_VAL if ESPTOOLPY_MONITOR_BAUD_OTHER endmenu diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index c071dc51b..c45762fb7 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -13,6 +13,12 @@ else ENABLE_TIME := n endif +ifdef CONFIG_ESPTOOLPY_ENABLE_SAVELOG +ENABLE_SAVELOG := y +else +ENABLE_SAVELOG := n +endif + CONFIG_ESPTOOLPY_COMPRESSED ?= PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) @@ -42,9 +48,13 @@ else ESPTOOL_ELF2IMAGE_OPTIONS := endif +ifdef CONFIG_DISABLE_ROM_UART_PRINT +ESPTOOL_ELF2IMAGE_OPTIONS += --rom_print 0 +endif + ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z,-u) $(ESPTOOL_WRITE_FLASH_OPTIONS) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(APP_OFFSET) $(APP_BIN) ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES ifndef IS_BOOTLOADER_BUILD @@ -60,30 +70,23 @@ APP_BIN_UNSIGNED ?= $(APP_BIN) $(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) $(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $< -ifdef IS_BOOTLOADER_BUILD - @mv $@0x00000.bin $@ -endif flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) - @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..." + @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(APP_OFFSET))..." ifdef CONFIG_SECURE_BOOT_ENABLED @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" endif $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) app-flash: $(APP_BIN) $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) - @echo "Flashing app to serial port $(ESPPORT), offset $(CONFIG_APP_OFFSET)..." - $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) - -# Submodules normally added in component.mk, but can be added -# at the project level as long as qualified path -COMPONENT_SUBMODULES += $(COMPONENT_PATH)/esptool + @echo "Flashing app to serial port $(ESPPORT), offset $(APP_OFFSET)..." + $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN) erase_flash: @echo "Erasing entire flash..." $(ESPTOOLPY_SERIAL) erase_flash -MONITORBAUD ?= $(CONFIG_MONITOR_BAUD) +MONITORBAUD ?= $(CONFIG_ESPTOOLPY_MONITOR_BAUD) MONITOR_PYTHON := $(PYTHON) @@ -99,7 +102,7 @@ endif simple_monitor: $(call prereq_if_explicit,%flash) $(MONITOR_PYTHON) -m serial.tools.miniterm --rts 0 --dtr 0 --raw $(ESPPORT) $(MONITORBAUD) -MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_TOOLPREFIX) --make "$(MAKE)" --enable-time $(ENABLE_TIME) +MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_SDK_TOOLPREFIX) --make "$(MAKE)" monitor: $(call prereq_if_explicit,%flash) $(summary) MONITOR diff --git a/components/esptool_py/esptool/esptool.py b/components/esptool_py/esptool/esptool.py index 45a386f57..521eefaa1 100755 --- a/components/esptool_py/esptool/esptool.py +++ b/components/esptool_py/esptool/esptool.py @@ -1358,6 +1358,11 @@ def default_output_name(self, input_file): """ Derive a default output name from the ELF name. """ return input_file + '-' + def close_rom_print(self): + """ Configurate UART0 baudrate to be max value to \"close\" ROM UART print. """ + segment = ImageSegment(0x60000014, '\x00' * 8) + self.segments.insert(0, segment) + def save(self, basename): """ Save a set of V1 images for flashing. Parameter is a base filename. """ # IROM data goes in its own plain binary file @@ -1368,7 +1373,7 @@ def save(self, basename): # everything but IROM goes at 0x00000 in an image file normal_segments = self.get_non_irom_segments() - with open("%s0x00000.bin" % basename, 'wb') as f: + with open("%s" % basename, 'wb') as f: self.write_common_header(f, normal_segments) checksum = ESPLoader.ESP_CHECKSUM_MAGIC for segment in normal_segments: @@ -1538,8 +1543,8 @@ def save(self, filename): checksum = ESPLoader.ESP_CHECKSUM_MAGIC # split segments into flash-mapped vs ram-loaded, and take copies so we can mutate them - flash_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if self.is_flash_addr(s.addr)] - ram_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if not self.is_flash_addr(s.addr)] + flash_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if self.is_flash_addr(s.addr) and len(s.data)] + ram_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if not self.is_flash_addr(s.addr) and len(s.data)] IROM_ALIGN = 65536 @@ -1554,11 +1559,11 @@ def save(self, filename): #print('%x' % last_addr) for segment in flash_segments[1:]: if segment.addr // IROM_ALIGN == last_addr // IROM_ALIGN: + print(segment) raise FatalError(("Segment loaded at 0x%08x lands in same 64KB flash mapping as segment loaded at 0x%08x. " + "Can't generate binary. Suggest changing linker script or ELF to merge sections.") % (segment.addr, last_addr)) last_addr = segment.addr - print('%x' % last_addr) def get_alignment_data_needed(segment): # Actual alignment (in data bytes) required for a segment header: positioned so that @@ -1594,6 +1599,9 @@ def get_alignment_data_needed(segment): checksum = self.save_segment(f, pad_segment, checksum) total_segments += 1 else: + # remove 8 bytes empty data for insert segment header + if segment.name == '.flash.rodata': + segment.data = segment.data[8:] # write the flash segment #assert (f.tell() + 8) % IROM_ALIGN == segment.addr % IROM_ALIGN checksum = self.save_segment(f, segment, checksum) @@ -2353,6 +2361,9 @@ def elf2image(args): image.flash_size_freq = image.ROM_LOADER.FLASH_SIZES[args.flash_size] image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] + if args.version == '1' and args.rom_print == 0: + image.close_rom_print() + if args.output is None: args.output = image.default_output_name(args.input) image.save(args.output) @@ -2612,6 +2623,7 @@ def add_spi_flash_subparsers(parent, is_elf2image): parser_elf2image.add_argument('input', help='Input ELF file') parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1','2','3'], default='1') + parser_elf2image.add_argument('--rom_print', type=arg_auto_int, help='Configurate UART0 baudrate to be max value to \"close\" ROM UART print', choices=[0, 1], default=1) add_spi_flash_subparsers(parser_elf2image, is_elf2image=True) diff --git a/components/esptool_py/flash_project_args.in b/components/esptool_py/flash_project_args.in new file mode 100644 index 000000000..b6e3f8f9e --- /dev/null +++ b/components/esptool_py/flash_project_args.in @@ -0,0 +1,3 @@ +${ESPTOOLPY_FLASH_PROJECT_OPTIONS} +$ \ No newline at end of file diff --git a/components/esptool_py/flasher_args.json.in b/components/esptool_py/flasher_args.json.in new file mode 100644 index 000000000..ca8693cc7 --- /dev/null +++ b/components/esptool_py/flasher_args.json.in @@ -0,0 +1,20 @@ +{ + "write_flash_args" : [ "--flash_mode", "${ESPFLASHMODE}", + "--flash_size", "${ESPFLASHSIZE}", + "--flash_freq", "${ESPFLASHFREQ}" ], + "flash_settings" : { + "flash_mode": "${ESPFLASHMODE}", + "flash_size": "${ESPFLASHSIZE}", + "flash_freq": "${ESPFLASHFREQ}" + }, + "flash_files" : { + $ + }, + $, + "extra_esptool_args" : { + "after" : "${ESPTOOLPY_AFTER}", + "before" : "${ESPTOOLPY_BEFORE}" + } +} diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake new file mode 100644 index 000000000..172628f04 --- /dev/null +++ b/components/esptool_py/project_include.cmake @@ -0,0 +1,212 @@ +# Set some global esptool.py variables +# +# Many of these are read when generating flash_app_args & flash_project_args +idf_build_get_property(python PYTHON) +set(ESPTOOLPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip esp8266) +set(ESPSECUREPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py") +set(ESPEFUSEPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py") + +set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) +set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) +set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) + +set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}") +set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}") + +if(CONFIG_SECURE_BOOT_ENABLED OR CONFIG_SECURE_FLASH_ENC_ENABLED) + # If security enabled then override post flash option + set(ESPTOOLPY_AFTER "no_reset") +endif() + +set(ESPTOOLPY_SERIAL "${ESPTOOLPY}" + --port "${ESPPORT}" + --baud ${ESPBAUD} + --before "${ESPTOOLPY_BEFORE}" + --after "${ESPTOOLPY_AFTER}" + ) + +if(CONFIG_ESPTOOLPY_COMPRESSED) + set(ESPTOOLPY_COMPRESSED_OPT -z) +else() + set(ESPTOOLPY_COMPRESSED_OPT -u) +endif() + +set(ESPTOOLPY_FLASH_OPTIONS + --flash_mode ${ESPFLASHMODE} + --flash_freq ${ESPFLASHFREQ} + --flash_size ${ESPFLASHSIZE} + ) + +# String for printing flash command +string(REPLACE ";" " " ESPTOOLPY_WRITE_FLASH_STR + "${ESPTOOLPY} --port (PORT) --baud (BAUD) --before ${ESPTOOLPY_BEFORE} --after ${ESPTOOLPY_AFTER} " + "write_flash ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}") + +if(CONFIG_SECURE_BOOT_ENABLED AND + NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION + AND NOT BOOTLOADER_BUILD) + set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} --secure-pad) +endif() + +if(BOOTLOADER_BUILD) + set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS}) +else() + set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} "--version=3") +endif() + + +if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT) + # Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated, + # as elf2image can't have 'detect' as an option... + set(ESPFLASHSIZE detect) +endif() + +idf_build_get_property(build_dir BUILD_DIR) + +idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) +idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) + +if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT BOOTLOADER_BUILD) + set(unsigned_project_binary "${elf_name}-unsigned.bin") +else() + set(unsigned_project_binary "${elf_name}.bin") +endif() + +set(PROJECT_BIN "${elf_name}.bin") + +# +# Add 'app.bin' target - generates with elf2image +# +add_custom_command(OUTPUT "${build_dir}/.bin_timestamp" + COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS} + -o "${build_dir}/${unsigned_project_binary}" "${elf}" + COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}" + COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${unsigned_project_binary}" > "${build_dir}/.bin_timestamp" + DEPENDS ${elf} + VERBATIM + WORKING_DIRECTORY ${build_dir} + COMMENT "Generating binary image from built executable" + ) +add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp") + +set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${build_dir}/${unsigned_project_binary}" + ) + +add_custom_target(app ALL DEPENDS gen_project_binary) + +if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS) + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + # for locally signed secure boot image, add a signing step to get from unsigned app to signed app + add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp" + COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key} + -o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}" + COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" + "from ${build_dir}/${unsigned_project_binary}" + COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${PROJECT_BIN}" > "${build_dir}/.signed_bin_timestamp" + DEPENDS "${build_dir}/.bin_timestamp" + VERBATIM + COMMENT "Generating signed binary image" + ) + add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp") + add_dependencies(gen_project_binary gen_signed_project_binary) + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${build_dir}/${PROJECT_BIN}" + ) + else() + string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") + add_custom_command(TARGET app POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo + "App built but not signed. Sign app before flashing" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/${PROJECT_BIN}" + VERBATIM) + endif() +endif() + +# +# Add 'flash' target - not all build systems can run this directly +# +function(esptool_py_custom_target target_name flasher_filename dependencies) + idf_build_get_property(idf_path IDF_PATH) + add_custom_target(${target_name} DEPENDS ${dependencies} + COMMAND ${CMAKE_COMMAND} + -D IDF_PATH="${idf_path}" + -D ESPTOOLPY="${ESPTOOLPY}" + -D ESPTOOL_ARGS="write_flash;@flash_${flasher_filename}_args" + -D ESPTOOL_WORKING_DIR="${build_dir}" + -P run_esptool.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + USES_TERMINAL + ) +endfunction() + +esptool_py_custom_target(flash project "app;partition_table;bootloader") +esptool_py_custom_target(app-flash app "app") + +if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + esptool_py_custom_target(encrypted-flash encrypted_project "app;partition_table;bootloader") + esptool_py_custom_target(encrypted-app-flash encrypted_app "app") +endif() + +# esptool_py_flash_project_args +# +# Add file to the flasher args list, to be flashed at a particular offset. +# +# When a template FLASH_FILE_TEMPLATE is given, the variables OFFSET and IMAGE +# hold the value of arguments offset and image, respectively. +function(esptool_py_flash_project_args entry offset image) + set(options FLASH_IN_PROJECT) # flash the image when flashing the project + set(single_value FLASH_FILE_TEMPLATE) # template file to use to be able to + # flash the image individually using esptool + cmake_parse_arguments(_ "${options}" "${single_value}" "" "${ARGN}") + + if(${entry} IN_LIST flash_project_entries) + message(FATAL_ERROR "entry '${entry}' has already been added to flash project entries") + endif() + + idf_component_set_property(esptool_py FLASH_PROJECT_ENTRIES "${entry}" APPEND) + + idf_build_get_property(build_dir BUILD_DIR) + file(RELATIVE_PATH image ${build_dir} ${image}) + + # Generate the standalone flash file to flash the image individually using esptool + set(entry_flash_args ${build_dir}/flash_${entry}_args) + if(NOT __FLASH_FILE_TEMPLATE) + file(GENERATE OUTPUT ${entry_flash_args} CONTENT "${offset} ${image}") + else() + set(OFFSET ${offset}) + set(IMAGE ${image}) + + get_filename_component(template_in "${__FLASH_FILE_TEMPLATE}" ABSOLUTE) + get_filename_component(template_name "${template_in}" NAME) + set(template_partial "${CMAKE_CURRENT_BINARY_DIR}/${template_name}.in2") + + configure_file("${template_in}" "${template_partial}") + file(GENERATE OUTPUT ${entry_flash_args} INPUT "${template_partial}") + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES "${template_partial}") + unset(OFFSET) + unset(IMAGE) + endif() + + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${entry_flash_args}) + + # Generate standalone entries in the flasher args json file + idf_component_set_property(esptool_py FLASH_PROJECT_ARGS_ENTRY_JSON + "\"${entry}\" : { \"offset\" : \"${offset}\", \"file\" : \"${image}\" }" APPEND) + + # Generate entries in the flasher args json file + if(__FLASH_IN_PROJECT) + idf_component_set_property(esptool_py FLASH_PROJECT_ARGS + "${offset} ${image}" APPEND) + + idf_component_set_property(esptool_py FLASH_PROJECT_ARGS_JSON + "\"${offset}\" : \"${image}\"" APPEND) + endif() +endfunction() diff --git a/components/esptool_py/run_esptool.cmake b/components/esptool_py/run_esptool.cmake new file mode 100644 index 000000000..a63eb55f0 --- /dev/null +++ b/components/esptool_py/run_esptool.cmake @@ -0,0 +1,46 @@ +# A CMake script to run esptool commands from within ninja or make +# or another cmake-based build runner +# +# (Needed to expand environment variables, for backwards compatibility.) +# +# It is recommended to NOT USE this CMake script if you have the option of +# running esptool.py directly. This script exists only for use inside CMake builds. +# +cmake_minimum_required(VERSION 3.5) + +if(NOT IDF_PATH OR NOT ESPTOOLPY OR NOT ESPTOOL_ARGS OR NOT ESPTOOL_WORKING_DIR) + message(FATAL_ERROR "IDF_PATH, ESPTOOLPY, ESPTOOL_ARGS, and ESPTOOL_WORKING_DIR must " + "be specified on the CMake command line. For direct esptool execution, it is " + "strongly recommended to run esptool.py directly.") +endif() + +# Note: we can't expand these environment variables in the main IDF CMake build, +# because we want to expand them at flashing time not at CMake runtime (so they can change +# without needing a CMake re-run) +set(ESPPORT $ENV{ESPPORT}) +if(NOT ESPPORT) + message("Note: esptool.py will search for a serial port. To specify a port, set the ESPPORT environment variable.") +else() + set(port_arg "-p ${ESPPORT}") +endif() + +set(ESPBAUD $ENV{ESPBAUD}) +if(NOT ESPBAUD) + message("Note: Using default baud rate 460800. To modify, set ESPBAUD environment variable.") + set(ESPBAUD 460800) +endif() + +include("${IDF_PATH}/tools/cmake/utilities.cmake") + +set(cmd "${ESPTOOLPY} ${port_arg} -b ${ESPBAUD} ${ESPTOOL_ARGS}") +spaces2list(cmd) + +execute_process(COMMAND ${cmd} + WORKING_DIRECTORY "${ESPTOOL_WORKING_DIR}" + RESULT_VARIABLE result + ) + +if(${result}) + # No way to have CMake silently fail, unfortunately + message(FATAL_ERROR "esptool.py failed") +endif() diff --git a/components/esptool_py/sdkconfig.rename b/components/esptool_py/sdkconfig.rename new file mode 100644 index 000000000..da13849a3 --- /dev/null +++ b/components/esptool_py/sdkconfig.rename @@ -0,0 +1,18 @@ +# sdkconfig replacement configurations for deprecated options formatted as +# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION + +CONFIG_FLASHMODE_QIO CONFIG_ESPTOOLPY_FLASHMODE_QIO +CONFIG_FLASHMODE_QOUT CONFIG_ESPTOOLPY_FLASHMODE_QOUT +CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +CONFIG_FLASHMODE_DOUT CONFIG_ESPTOOLPY_FLASHMODE_DOUT + +CONFIG_MONITOR_BAUD CONFIG_ESPTOOLPY_MONITOR_BAUD +CONFIG_MONITOR_BAUD_9600B CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B +CONFIG_MONITOR_BAUD_74880B CONFIG_ESPTOOLPY_MONITOR_BAUD_74880B +CONFIG_MONITOR_BAUD_57600B CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B +CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +CONFIG_MONITOR_BAUD_230400B CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B +CONFIG_MONITOR_BAUD_921600B CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B +CONFIG_MONITOR_BAUD_2MB CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB +CONFIG_MONITOR_BAUD_OTHER CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER +CONFIG_MONITOR_BAUD_OTHER_VAL CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL diff --git a/components/fatfs/CMakeLists.txt b/components/fatfs/CMakeLists.txt new file mode 100644 index 000000000..882f1fa4f --- /dev/null +++ b/components/fatfs/CMakeLists.txt @@ -0,0 +1,17 @@ +set(srcs "diskio/diskio.c" + "diskio/diskio_rawflash.c" + "diskio/diskio_wl.c" + "src/ff.c" + "port/freertos/ffsystem.c" + "src/ffunicode.c" + "vfs/vfs_fat.c" + "vfs/vfs_fat_spiflash.c") + +if(IDF_TARGET STREQUAL "esp32") + list(APPEND srcs "vfs/vfs_fat_sdmmc.c") +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS diskio vfs src + REQUIRES wear_levelling + ) diff --git a/components/fatfs/Kconfig b/components/fatfs/Kconfig new file mode 100644 index 000000000..31dd4f278 --- /dev/null +++ b/components/fatfs/Kconfig @@ -0,0 +1,183 @@ +menu "FAT Filesystem support" + + choice FATFS_CHOOSE_CODEPAGE + prompt "OEM Code Page" + default FATFS_CODEPAGE_437 + help + OEM code page used for file name encodings. + + If "Dynamic" is selected, code page can be chosen at runtime using + f_setcp function. Note that choosing this option will increase + application size by ~480kB. + + config FATFS_CODEPAGE_DYNAMIC + bool "Dynamic (all code pages supported)" + config FATFS_CODEPAGE_437 + bool "US (CP437)" + config FATFS_CODEPAGE_720 + bool "Arabic (CP720)" + config FATFS_CODEPAGE_737 + bool "Greek (CP737)" + config FATFS_CODEPAGE_771 + bool "KBL (CP771)" + config FATFS_CODEPAGE_775 + bool "Baltic (CP775)" + config FATFS_CODEPAGE_850 + bool "Latin 1 (CP850)" + config FATFS_CODEPAGE_852 + bool "Latin 2 (CP852)" + config FATFS_CODEPAGE_855 + bool "Cyrillic (CP855)" + config FATFS_CODEPAGE_857 + bool "Turkish (CP857)" + config FATFS_CODEPAGE_860 + bool "Portugese (CP860)" + config FATFS_CODEPAGE_861 + bool "Icelandic (CP861)" + config FATFS_CODEPAGE_862 + bool "Hebrew (CP862)" + config FATFS_CODEPAGE_863 + bool "Canadian French (CP863)" + config FATFS_CODEPAGE_864 + bool "Arabic (CP864)" + config FATFS_CODEPAGE_865 + bool "Nordic (CP865)" + config FATFS_CODEPAGE_866 + bool "Russian (CP866)" + config FATFS_CODEPAGE_869 + bool "Greek 2 (CP869)" + config FATFS_CODEPAGE_932 + bool "Japanese (DBCS) (CP932)" + config FATFS_CODEPAGE_936 + bool "Simplified Chinese (DBCS) (CP936)" + config FATFS_CODEPAGE_949 + bool "Korean (DBCS) (CP949)" + config FATFS_CODEPAGE_950 + bool "Traditional Chinese (DBCS) (CP950)" + + endchoice + + config FATFS_CODEPAGE + int + default 0 if FATFS_CODEPAGE_DYNAMIC + default 437 if FATFS_CODEPAGE_437 + default 720 if FATFS_CODEPAGE_720 + default 737 if FATFS_CODEPAGE_737 + default 771 if FATFS_CODEPAGE_771 + default 775 if FATFS_CODEPAGE_775 + default 850 if FATFS_CODEPAGE_850 + default 852 if FATFS_CODEPAGE_852 + default 855 if FATFS_CODEPAGE_855 + default 857 if FATFS_CODEPAGE_857 + default 860 if FATFS_CODEPAGE_860 + default 861 if FATFS_CODEPAGE_861 + default 862 if FATFS_CODEPAGE_862 + default 863 if FATFS_CODEPAGE_863 + default 864 if FATFS_CODEPAGE_864 + default 865 if FATFS_CODEPAGE_865 + default 866 if FATFS_CODEPAGE_866 + default 869 if FATFS_CODEPAGE_869 + default 932 if FATFS_CODEPAGE_932 + default 936 if FATFS_CODEPAGE_936 + default 949 if FATFS_CODEPAGE_949 + default 950 if FATFS_CODEPAGE_950 + default 437 + + choice FATFS_LONG_FILENAMES + prompt "Long filename support" + default FATFS_LFN_NONE + help + Support long filenames in FAT. Long filename data increases + memory usage. FATFS can be configured to store the buffer for + long filename data in stack or heap. + + config FATFS_LFN_NONE + bool "No long filenames" + config FATFS_LFN_HEAP + bool "Long filename buffer in heap" + config FATFS_LFN_STACK + bool "Long filename buffer on stack" + endchoice + + config FATFS_MAX_LFN + int "Max long filename length" + depends on !FATFS_LFN_NONE + default 255 + range 12 255 + help + Maximum long filename length. Can be reduced to save RAM. + + choice FATFS_API_ENCODING + prompt "API character encoding" + depends on !FATFS_LFN_NONE + default FATFS_API_ENCODING_ANSI_OEM + help + Choose encoding for character and string arguments/returns when using + FATFS APIs. The encoding of arguments will usually depend on text + editor settings. + + config FATFS_API_ENCODING_ANSI_OEM + bool "API uses ANSI/OEM encoding" + config FATFS_API_ENCODING_UTF_16 + bool "API uses UTF-16 encoding" + config FATFS_API_ENCODING_UTF_8 + bool "API uses UTF-8 encoding" + endchoice + + config FATFS_FS_LOCK + int "Number of simultaneously open files protected by lock function" + default 0 + range 0 65535 + help + This option sets the FATFS configuration value _FS_LOCK. + The option _FS_LOCK switches file lock function to control duplicated file open + and illegal operation to open objects. + + * 0: Disable file lock function. To avoid volume corruption, application + should avoid illegal open, remove and rename to the open objects. + + * >0: Enable file lock function. The value defines how many files/sub-directories + can be opened simultaneously under file lock control. + + Note that the file lock control is independent of re-entrancy. + + config FATFS_TIMEOUT_MS + int "Timeout for acquiring a file lock, ms" + default 10000 + help + This option sets FATFS configuration value _FS_TIMEOUT, scaled to milliseconds. + Sets the number of milliseconds FATFS will wait to acquire a mutex when + operating on an open file. For example, if one task is performing a lenghty + operation, another task will wait for the first task to release the lock, + and time out after amount of time set by this option. + + + config FATFS_PER_FILE_CACHE + bool "Use separate cache for each file" + default y + help + This option affects FATFS configuration value _FS_TINY. + + If this option is set, _FS_TINY is 0, and each open file has its own cache, + size of the cache is equal to the _MAX_SS variable (512 or 4096 bytes). + This option uses more RAM if more than 1 file is open, but needs less reads + and writes to the storage for some operations. + + If this option is not set, _FS_TINY is 1, and single cache is used for + all open files, size is also equal to _MAX_SS variable. This reduces the + amount of heap used when multiple files are open, but increases the number + of read and write operations which FATFS needs to make. + + + config FATFS_ALLOC_PREFER_EXTRAM + bool "Perfer external RAM when allocating FATFS buffers" + default y + depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC + help + When the option is enabled, internal buffers used by FATFS will be allocated + from external RAM. If the allocation from external RAM fails, the buffer will + be allocated from the internal RAM. + Disable this option if optimizing for performance. Enable this option if + optimizing for internal memory size. + +endmenu diff --git a/components/fatfs/component.mk b/components/fatfs/component.mk new file mode 100644 index 000000000..996a65225 --- /dev/null +++ b/components/fatfs/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := diskio vfs src +COMPONENT_SRCDIRS := diskio vfs port/freertos src +COMPONENT_OBJEXCLUDE := src/diskio.o src/ffsystem.o diskio/diskio_sdmmc.o vfs/vfs_fat_sdmmc.o diff --git a/components/fatfs/diskio/diskio.c b/components/fatfs/diskio/diskio.c new file mode 100644 index 000000000..c8075166d --- /dev/null +++ b/components/fatfs/diskio/diskio.c @@ -0,0 +1,93 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ +/* ESP-IDF port Copyright 2016 Espressif Systems (Shanghai) PTE LTD */ +/*-----------------------------------------------------------------------*/ +/* If a working storage control module is available, it should be */ +/* attached to the FatFs via a glue function rather than modifying it. */ +/* This is an example of glue functions to attach various exsisting */ +/* storage control modules to the FatFs module with a defined API. */ +/*-----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "diskio_impl.h" +#include "ffconf.h" +#include "ff.h" + +static ff_diskio_impl_t * s_impls[FF_VOLUMES] = { NULL }; + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +PARTITION VolToPart[] = { + {0, 0}, /* Logical drive 0 ==> Physical drive 0, auto detection */ + {1, 0} /* Logical drive 1 ==> Physical drive 1, auto detection */ +}; +#endif + +esp_err_t ff_diskio_get_drive(BYTE* out_pdrv) +{ + BYTE i; + for(i=0; iinit(pdrv); +} +DSTATUS ff_disk_status (BYTE pdrv) +{ + return s_impls[pdrv]->status(pdrv); +} +DRESULT ff_disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) +{ + return s_impls[pdrv]->read(pdrv, buff, sector, count); +} +DRESULT ff_disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) +{ + return s_impls[pdrv]->write(pdrv, buff, sector, count); +} +DRESULT ff_disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) +{ + return s_impls[pdrv]->ioctl(pdrv, cmd, buff); +} + +DWORD get_fattime(void) +{ + time_t t = time(NULL); + struct tm tmr; + localtime_r(&t, &tmr); + int year = tmr.tm_year < 80 ? 0 : tmr.tm_year - 80; + return ((DWORD)(year) << 25) + | ((DWORD)(tmr.tm_mon + 1) << 21) + | ((DWORD)tmr.tm_mday << 16) + | (WORD)(tmr.tm_hour << 11) + | (WORD)(tmr.tm_min << 5) + | (WORD)(tmr.tm_sec >> 1); +} diff --git a/components/fatfs/diskio/diskio_impl.h b/components/fatfs/diskio/diskio_impl.h new file mode 100644 index 000000000..76c246dd8 --- /dev/null +++ b/components/fatfs/diskio/diskio_impl.h @@ -0,0 +1,71 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +typedef unsigned int UINT; +typedef unsigned char BYTE; +typedef uint32_t DWORD; + +#include "diskio.h" +#include "esp_err.h" + +/** + * Structure of pointers to disk IO driver functions. + * + * See FatFs documentation for details about these functions + */ +typedef struct { + DSTATUS (*init) (unsigned char pdrv); /*!< disk initialization function */ + DSTATUS (*status) (unsigned char pdrv); /*!< disk status check function */ + DRESULT (*read) (unsigned char pdrv, unsigned char* buff, uint32_t sector, unsigned count); /*!< sector read function */ + DRESULT (*write) (unsigned char pdrv, const unsigned char* buff, uint32_t sector, unsigned count); /*!< sector write function */ + DRESULT (*ioctl) (unsigned char pdrv, unsigned char cmd, void* buff); /*!< function to get info about disk and do some misc operations */ +} ff_diskio_impl_t; + +/** + * Register or unregister diskio driver for given drive number. + * + * When FATFS library calls one of disk_xxx functions for driver number pdrv, + * corresponding function in discio_impl for given pdrv will be called. + * + * @param pdrv drive number + * @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions + * or NULL to unregister and free previously registered drive + */ +void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl); + +#define ff_diskio_unregister(pdrv_) ff_diskio_register(pdrv_, NULL) + + +/** + * Get next available drive number + * + * @param out_pdrv pointer to the byte to set if successful + * + * @return ESP_OK on success + * ESP_ERR_NOT_FOUND if all drives are attached + */ +esp_err_t ff_diskio_get_drive(BYTE* out_pdrv); + + +#ifdef __cplusplus +} +#endif + diff --git a/components/fatfs/diskio/diskio_rawflash.c b/components/fatfs/diskio/diskio_rawflash.c new file mode 100644 index 000000000..382e53239 --- /dev/null +++ b/components/fatfs/diskio/diskio_rawflash.c @@ -0,0 +1,105 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "diskio_impl.h" +#include "ffconf.h" +#include "ff.h" +#include "esp_log.h" +#include "diskio_rawflash.h" +#include "esp_compiler.h" + +static const char* TAG = "diskio_rawflash"; + +const esp_partition_t* ff_raw_handles[FF_VOLUMES]; + + +DSTATUS ff_raw_initialize (BYTE pdrv) +{ + return 0; +} + +DSTATUS ff_raw_status (BYTE pdrv) +{ + return 0; +} + +DRESULT ff_raw_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_raw_read - pdrv=%i, sector=%i, count=%in", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + const esp_partition_t* part = ff_raw_handles[pdrv]; + assert(part); + esp_err_t err = esp_partition_read(part, sector * SPI_FLASH_SEC_SIZE, buff, count * SPI_FLASH_SEC_SIZE); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "esp_partition_read failed (0x%x)", err); + return RES_ERROR; + } + return RES_OK; +} + + +DRESULT ff_raw_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + return RES_ERROR; +} + +DRESULT ff_raw_ioctl (BYTE pdrv, BYTE cmd, void *buff) +{ + const esp_partition_t* part = ff_raw_handles[pdrv]; + ESP_LOGV(TAG, "ff_raw_ioctl: cmd=%in", cmd); + assert(part); + switch (cmd) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((DWORD *) buff) = part->size / SPI_FLASH_SEC_SIZE; + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD *) buff) = SPI_FLASH_SEC_SIZE; + return RES_OK; + case GET_BLOCK_SIZE: + return RES_ERROR; + } + return RES_ERROR; +} + + +esp_err_t ff_diskio_register_raw_partition(BYTE pdrv, const esp_partition_t* part_handle) +{ + if (pdrv >= FF_VOLUMES) { + return ESP_ERR_INVALID_ARG; + } + static const ff_diskio_impl_t raw_impl = { + .init = &ff_raw_initialize, + .status = &ff_raw_status, + .read = &ff_raw_read, + .write = &ff_raw_write, + .ioctl = &ff_raw_ioctl + }; + ff_diskio_register(pdrv, &raw_impl); + ff_raw_handles[pdrv] = part_handle; + return ESP_OK; + +} + + +BYTE ff_diskio_get_pdrv_raw(const esp_partition_t* part_handle) +{ + for (int i = 0; i < FF_VOLUMES; i++) { + if (part_handle == ff_raw_handles[i]) { + return i; + } + } + return 0xff; +} diff --git a/components/fatfs/diskio/diskio_rawflash.h b/components/fatfs/diskio/diskio_rawflash.h new file mode 100644 index 000000000..73ff15f88 --- /dev/null +++ b/components/fatfs/diskio/diskio_rawflash.h @@ -0,0 +1,37 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DISKIO_RAWFLASH_DEFINED +#define _DISKIO_RAWFLASH_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_partition.h" + +/** + * Register spi flash partition + * + * @param pdrv drive number + * @param part_handle pointer to raw flash partition. + */ +esp_err_t ff_diskio_register_raw_partition(unsigned char pdrv, const esp_partition_t* part_handle); +unsigned char ff_diskio_get_pdrv_raw(const esp_partition_t* part_handle); + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_RAWFLASH_DEFINED diff --git a/components/fatfs/diskio/diskio_sdmmc.c b/components/fatfs/diskio/diskio_sdmmc.c new file mode 100644 index 000000000..15e4a8677 --- /dev/null +++ b/components/fatfs/diskio/diskio_sdmmc.c @@ -0,0 +1,91 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "diskio_impl.h" +#include "ffconf.h" +#include "ff.h" +#include "sdmmc_cmd.h" +#include "esp_log.h" +#include "esp_compiler.h" + +static sdmmc_card_t* s_cards[FF_VOLUMES] = { NULL }; + +static const char* TAG = "diskio_sdmmc"; + +DSTATUS ff_sdmmc_initialize (BYTE pdrv) +{ + return 0; +} + +DSTATUS ff_sdmmc_status (BYTE pdrv) +{ + return 0; +} + +DRESULT ff_sdmmc_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) +{ + sdmmc_card_t* card = s_cards[pdrv]; + assert(card); + esp_err_t err = sdmmc_read_sectors(card, buff, sector, count); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "sdmmc_read_blocks failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_sdmmc_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) +{ + sdmmc_card_t* card = s_cards[pdrv]; + assert(card); + esp_err_t err = sdmmc_write_sectors(card, buff, sector, count); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "sdmmc_write_blocks failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_sdmmc_ioctl (BYTE pdrv, BYTE cmd, void* buff) +{ + sdmmc_card_t* card = s_cards[pdrv]; + assert(card); + switch(cmd) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((DWORD*) buff) = card->csd.capacity; + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD*) buff) = card->csd.sector_size; + return RES_OK; + case GET_BLOCK_SIZE: + return RES_ERROR; + } + return RES_ERROR; +} + +void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card) +{ + static const ff_diskio_impl_t sdmmc_impl = { + .init = &ff_sdmmc_initialize, + .status = &ff_sdmmc_status, + .read = &ff_sdmmc_read, + .write = &ff_sdmmc_write, + .ioctl = &ff_sdmmc_ioctl + }; + s_cards[pdrv] = card; + ff_diskio_register(pdrv, &sdmmc_impl); +} + diff --git a/components/fatfs/diskio/diskio_sdmmc.h b/components/fatfs/diskio/diskio_sdmmc.h new file mode 100644 index 000000000..d7a50221b --- /dev/null +++ b/components/fatfs/diskio/diskio_sdmmc.h @@ -0,0 +1,35 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "sdmmc_cmd.h" +#include "driver/sdmmc_host.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Register SD/MMC diskio driver + * + * @param pdrv drive number + * @param card pointer to sdmmc_card_t structure describing a card; card should be initialized before calling f_mount. + */ +void ff_diskio_register_sdmmc(unsigned char pdrv, sdmmc_card_t* card); + +#ifdef __cplusplus +} +#endif + diff --git a/components/fatfs/diskio/diskio_wl.c b/components/fatfs/diskio/diskio_wl.c new file mode 100644 index 000000000..617236e8f --- /dev/null +++ b/components/fatfs/diskio/diskio_wl.c @@ -0,0 +1,127 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "diskio_impl.h" +#include "ffconf.h" +#include "ff.h" +#include "esp_log.h" +#include "diskio_wl.h" +#include "wear_levelling.h" +#include "esp_compiler.h" + +static const char* TAG = "ff_diskio_spiflash"; + +wl_handle_t ff_wl_handles[FF_VOLUMES] = { + WL_INVALID_HANDLE, + WL_INVALID_HANDLE, +}; + +DSTATUS ff_wl_initialize (BYTE pdrv) +{ + return 0; +} + +DSTATUS ff_wl_status (BYTE pdrv) +{ + return 0; +} + +DRESULT ff_wl_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_wl_read - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + assert(wl_handle + 1); + esp_err_t err = wl_read(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "wl_read failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_wl_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_wl_write - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + assert(wl_handle + 1); + esp_err_t err = wl_erase_range(wl_handle, sector * wl_sector_size(wl_handle), count * wl_sector_size(wl_handle)); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "wl_erase_range failed (%d)", err); + return RES_ERROR; + } + err = wl_write(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); + if (unlikely(err != ESP_OK)) { + ESP_LOGE(TAG, "wl_write failed (%d)", err); + return RES_ERROR; + } + return RES_OK; +} + +DRESULT ff_wl_ioctl (BYTE pdrv, BYTE cmd, void *buff) +{ + wl_handle_t wl_handle = ff_wl_handles[pdrv]; + ESP_LOGV(TAG, "ff_wl_ioctl: cmd=%i\n", cmd); + assert(wl_handle + 1); + switch (cmd) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((DWORD *) buff) = wl_size(wl_handle) / wl_sector_size(wl_handle); + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD *) buff) = wl_sector_size(wl_handle); + return RES_OK; + case GET_BLOCK_SIZE: + return RES_ERROR; + } + return RES_ERROR; +} + + +esp_err_t ff_diskio_register_wl_partition(BYTE pdrv, wl_handle_t flash_handle) +{ + if (pdrv >= FF_VOLUMES) { + return ESP_ERR_INVALID_ARG; + } + static const ff_diskio_impl_t wl_impl = { + .init = &ff_wl_initialize, + .status = &ff_wl_status, + .read = &ff_wl_read, + .write = &ff_wl_write, + .ioctl = &ff_wl_ioctl + }; + ff_wl_handles[pdrv] = flash_handle; + ff_diskio_register(pdrv, &wl_impl); + return ESP_OK; +} + +BYTE ff_diskio_get_pdrv_wl(wl_handle_t flash_handle) +{ + for (int i = 0; i < FF_VOLUMES; i++) { + if (flash_handle == ff_wl_handles[i]) { + return i; + } + } + return 0xff; +} + +void ff_diskio_clear_pdrv_wl(wl_handle_t flash_handle) +{ + for (int i = 0; i < FF_VOLUMES; i++) { + if (flash_handle == ff_wl_handles[i]) { + ff_wl_handles[i] = WL_INVALID_HANDLE; + } + } +} diff --git a/components/fatfs/diskio/diskio_wl.h b/components/fatfs/diskio/diskio_wl.h new file mode 100644 index 000000000..af3f14797 --- /dev/null +++ b/components/fatfs/diskio/diskio_wl.h @@ -0,0 +1,39 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DISKIO_WL_DEFINED +#define _DISKIO_WL_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wear_levelling.h" + + +/** + * Register spi flash partition + * + * @param pdrv drive number + * @param flash_handle handle of the wear levelling partition. + */ +esp_err_t ff_diskio_register_wl_partition(unsigned char pdrv, wl_handle_t flash_handle); +unsigned char ff_diskio_get_pdrv_wl(wl_handle_t flash_handle); +void ff_diskio_clear_pdrv_wl(wl_handle_t flash_handle); + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_WL_DEFINED diff --git a/components/fatfs/port/freertos/ffsystem.c b/components/fatfs/port/freertos/ffsystem.c new file mode 100644 index 000000000..45a894de5 --- /dev/null +++ b/components/fatfs/port/freertos/ffsystem.c @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------*/ +/* Sample Code of OS Dependent Functions for FatFs */ +/* (C)ChaN, 2017 */ +/*------------------------------------------------------------------------*/ + + +#include +#include +#include "ff.h" +#include "sdkconfig.h" +#ifdef CONFIG_FATFS_ALLOC_EXTRAM_FIRST +#include "esp_heap_caps.h" +#endif + +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */ + unsigned msize /* Number of bytes to allocate */ +) +{ +#ifdef CONFIG_FATFS_ALLOC_EXTRAM_FIRST + return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, + MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL); +#else + return malloc(msize); +#endif +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free (nothing to do for null) */ +) +{ + free(mblock); /* Free the memory block with POSIX API */ +} + + + + +#if FF_FS_REENTRANT /* Mutal exclusion */ + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to create a new +/ synchronization object for the volume, such as semaphore and mutex. +/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. +*/ + + +int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ + BYTE vol, /* Corresponding volume (logical drive number) */ + FF_SYNC_t *sobj /* Pointer to return the created sync object */ +) +{ + *sobj = xSemaphoreCreateMutex(); + return (*sobj != NULL) ? 1 : 0; +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to delete a synchronization +/ object that created with ff_cre_syncobj() function. When a 0 is returned, +/ the f_mount() function fails with FR_INT_ERR. +*/ + +int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ + FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ +) +{ + vSemaphoreDelete(sobj); + return 1; +} + + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on entering file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ + FF_SYNC_t sobj /* Sync object to wait */ +) +{ + return (xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE) ? 1 : 0; +} + + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leaving file functions to unlock the volume. +*/ + +void ff_rel_grant ( + FF_SYNC_t sobj /* Sync object to be signaled */ +) +{ + xSemaphoreGive(sobj); +} + +#endif // FF_FS_REENTRANT diff --git a/components/fatfs/port/linux/ffsystem.c b/components/fatfs/port/linux/ffsystem.c new file mode 100644 index 000000000..5013c8b12 --- /dev/null +++ b/components/fatfs/port/linux/ffsystem.c @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------*/ +/* OS Dependent Functions for FatFs */ +/* (C)ChaN, 2018 */ +/*------------------------------------------------------------------------*/ + + +#include "ff.h" +#include + +/* This is the implementation for host-side testing on Linux. + * Host-side tests are single threaded, so lock functionality isn't needed. + */ + +void* ff_memalloc(UINT msize) +{ + return malloc(msize); +} + +void ff_memfree(void* mblock) +{ + free(mblock); +} + +/* 1:Function succeeded, 0:Could not create the sync object */ +int ff_cre_syncobj(BYTE vol, FF_SYNC_t* sobj) +{ + *sobj = NULL; + return 1; +} + +/* 1:Function succeeded, 0:Could not delete due to an error */ +int ff_del_syncobj(FF_SYNC_t sobj) +{ + return 1; +} + +/* 1:Function succeeded, 0:Could not acquire lock */ +int ff_req_grant (FF_SYNC_t sobj) +{ + return 1; +} + +void ff_rel_grant (FF_SYNC_t sobj) +{ +} + diff --git a/components/fatfs/src/00history.txt b/components/fatfs/src/00history.txt new file mode 100644 index 000000000..db12a9e1b --- /dev/null +++ b/components/fatfs/src/00history.txt @@ -0,0 +1,330 @@ +---------------------------------------------------------------------------- + Revision history of FatFs module +---------------------------------------------------------------------------- + +R0.00 (February 26, 2006) + + Prototype. + + + +R0.01 (April 29, 2006) + + The first release. + + + +R0.02 (June 01, 2006) + + Added FAT12 support. + Removed unbuffered mode. + Fixed a problem on small (<32M) partition. + + + +R0.02a (June 10, 2006) + + Added a configuration option (_FS_MINIMUM). + + + +R0.03 (September 22, 2006) + + Added f_rename(). + Changed option _FS_MINIMUM to _FS_MINIMIZE. + + + +R0.03a (December 11, 2006) + + Improved cluster scan algorithm to write files fast. + Fixed f_mkdir() creates incorrect directory on FAT32. + + + +R0.04 (February 04, 2007) + + Added f_mkfs(). + Supported multiple drive system. + Changed some interfaces for multiple drive system. + Changed f_mountdrv() to f_mount(). + + + +R0.04a (April 01, 2007) + + Supported multiple partitions on a physical drive. + Added a capability of extending file size to f_lseek(). + Added minimization level 3. + Fixed an endian sensitive code in f_mkfs(). + + + +R0.04b (May 05, 2007) + + Added a configuration option _USE_NTFLAG. + Added FSINFO support. + Fixed DBCS name can result FR_INVALID_NAME. + Fixed short seek (<= csize) collapses the file object. + + + +R0.05 (August 25, 2007) + + Changed arguments of f_read(), f_write() and f_mkfs(). + Fixed f_mkfs() on FAT32 creates incorrect FSINFO. + Fixed f_mkdir() on FAT32 creates incorrect directory. + + + +R0.05a (February 03, 2008) + + Added f_truncate() and f_utime(). + Fixed off by one error at FAT sub-type determination. + Fixed btr in f_read() can be mistruncated. + Fixed cached sector is not flushed when create and close without write. + + + +R0.06 (April 01, 2008) + + Added fputc(), fputs(), fprintf() and fgets(). + Improved performance of f_lseek() on moving to the same or following cluster. + + + +R0.07 (April 01, 2009) + + Merged Tiny-FatFs as a configuration option. (_FS_TINY) + Added long file name feature. (_USE_LFN) + Added multiple code page feature. (_CODE_PAGE) + Added re-entrancy for multitask operation. (_FS_REENTRANT) + Added auto cluster size selection to f_mkfs(). + Added rewind option to f_readdir(). + Changed result code of critical errors. + Renamed string functions to avoid name collision. + + + +R0.07a (April 14, 2009) + + Septemberarated out OS dependent code on reentrant cfg. + Added multiple sector size feature. + + + +R0.07c (June 21, 2009) + + Fixed f_unlink() can return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir() and f_chdrive(). + Added proper case conversion to extended character. + + + +R0.07e (November 03, 2009) + + Septemberarated out configuration options from ff.h to ffconf.h. + Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. + Fixed name matching error on the 13 character boundary. + Added a configuration option, _LFN_UNICODE. + Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + + + +R0.08 (May 15, 2010) + + Added a memory configuration option. (_USE_LFN = 3) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed .fname in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + + + +R0.08a (August 16, 2010) + + Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase feature. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed f_mkfs() creates wrong FAT32 volume. + + + +R0.08b (January 15, 2011) + + Fast seek feature is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf(). + Ignores duplicated directory separators in given path name. + + + +R0.09 (September 06, 2011) + + f_mkfs() supports multiple partition to complete the multiple partition feature. + Added f_fdisk(). + + + +R0.09a (August 27, 2012) + + Changed f_open() and f_opendir() reject null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. + Fixed assertion failure due to OS/2 EA on FAT12/16 volume. + + + +R0.09b (January 24, 2013) + + Added f_setlabel() and f_getlabel(). + + + +R0.10 (October 02, 2013) + + Added selection of character encoding on the file. (_STRF_ENCODE) + Added f_closedir(). + Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) + Added forced mount feature with changes of f_mount(). + Improved behavior of volume auto detection. + Improved write throughput of f_puts() and f_printf(). + Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). + Fixed f_write() can be truncated when the file size is close to 4GB. + Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error. + + + +R0.10a (January 15, 2014) + + Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) + Added a configuration option of minimum sector size. (_MIN_SS) + 2nd argument of f_rename() can have a drive number and it will be ignored. + Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) + Fixed f_close() invalidates the file object without volume lock. + Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) + Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) + + + +R0.10b (May 19, 2014) + + Fixed a hard error in the disk I/O layer can collapse the directory entry. + Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07) + + + +R0.10c (November 09, 2014) + + Added a configuration option for the platforms without RTC. (_FS_NORTC) + Changed option name _USE_ERASE to _USE_TRIM. + Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) + Fixed a potential problem of FAT access that can appear on disk error. + Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) + + + +R0.11 (February 09, 2015) + + Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) + Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) + Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) + + + +R0.11a (September 05, 2015) + + Fixed wrong media change can lead a deadlock at thread-safe configuration. + Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) + Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) + Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). + Fixed errors in the case conversion teble of Unicode (cc*.c). + + + +R0.12 (April 12, 2016) + + Added support for exFAT file system. (_FS_EXFAT) + Added f_expand(). (_USE_EXPAND) + Changed some members in FINFO structure and behavior of f_readdir(). + Added an option _USE_CHMOD. + Removed an option _WORD_ACCESS. + Fixed errors in the case conversion table of Unicode (cc*.c). + + + +R0.12a (July 10, 2016) + + Added support for creating exFAT volume with some changes of f_mkfs(). + Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. + f_forward() is available regardless of _FS_TINY. + Fixed f_mkfs() creates wrong volume. (appeared at R0.12) + Fixed wrong memory read in create_name(). (appeared at R0.12) + Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. + + + +R0.12b (September 04, 2016) + + Made f_rename() be able to rename objects with the same name but case. + Fixed an error in the case conversion teble of code page 866. (ff.c) + Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) + Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) + Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) + Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) + Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) + Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) + + + +R0.12c (March 04, 2017) + + Improved write throughput at the fragmented file on the exFAT volume. + Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN. + Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12) + Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c) + + + +R0.13 (May 21, 2017) + + Changed heading character of configuration keywords "_" to "FF_". + Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead. + Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0) + Improved cluster allocation time on stretch a deep buried cluster chain. + Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3. + Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous. + Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12) + Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c) + Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c) + + + +R0.13a (October 14, 2017) + + Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2) + Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF). + Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk(). + Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09) + Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c) + Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12) + + + +R0.13b (April 07, 2018) + + Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3) + Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2) + Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c) + Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b) + + + +R0.13c (October 14, 2018) + Supported stdint.h for C99 and later. (integer.h was included in ff.h) + Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12) + Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12) + Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b) + diff --git a/components/fatfs/src/00readme.txt b/components/fatfs/src/00readme.txt new file mode 100644 index 000000000..dcccbdbeb --- /dev/null +++ b/components/fatfs/src/00readme.txt @@ -0,0 +1,21 @@ +FatFs Module Source Files R0.13c + + +FILES + + 00readme.txt This file. + 00history.txt Revision history. + ff.c FatFs module. + ffconf.h Configuration file of FatFs module. + ff.h Common include file for FatFs and application module. + diskio.h Common include file for FatFs and disk I/O module. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + ffunicode.c Optional Unicode utility functions. + ffsystem.c An example of optional O/S related functions. + + + Low level disk I/O module is not included in this archive because the FatFs + module is only a generic file system layer and it does not depend on any specific + storage device. You need to provide a low level disk I/O module written to + control the storage device that attached to the target system. + diff --git a/components/fatfs/src/diskio.c b/components/fatfs/src/diskio.c new file mode 100644 index 000000000..08ffcc860 --- /dev/null +++ b/components/fatfs/src/diskio.c @@ -0,0 +1,229 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ +/*-----------------------------------------------------------------------*/ +/* If a working storage control module is available, it should be */ +/* attached to the FatFs via a glue function rather than modifying it. */ +/* This is an example of glue functions to attach various exsisting */ +/* storage control modules to the FatFs module with a defined API. */ +/*-----------------------------------------------------------------------*/ + +#include "ff.h" /* Obtains integer types */ +#include "diskio.h" /* Declarations of disk functions */ + +/* Definitions of physical drive number for each drive */ +#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */ +#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */ +#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */ + + +/*-----------------------------------------------------------------------*/ +/* Get Drive Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + DSTATUS stat; + int result; + + switch (pdrv) { + case DEV_RAM : + result = RAM_disk_status(); + + // translate the reslut code here + + return stat; + + case DEV_MMC : + result = MMC_disk_status(); + + // translate the reslut code here + + return stat; + + case DEV_USB : + result = USB_disk_status(); + + // translate the reslut code here + + return stat; + } + return STA_NOINIT; +} + + + +/*-----------------------------------------------------------------------*/ +/* Inidialize a Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + DSTATUS stat; + int result; + + switch (pdrv) { + case DEV_RAM : + result = RAM_disk_initialize(); + + // translate the reslut code here + + return stat; + + case DEV_MMC : + result = MMC_disk_initialize(); + + // translate the reslut code here + + return stat; + + case DEV_USB : + result = USB_disk_initialize(); + + // translate the reslut code here + + return stat; + } + return STA_NOINIT; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to read */ +) +{ + DRESULT res; + int result; + + switch (pdrv) { + case DEV_RAM : + // translate the arguments here + + result = RAM_disk_read(buff, sector, count); + + // translate the reslut code here + + return res; + + case DEV_MMC : + // translate the arguments here + + result = MMC_disk_read(buff, sector, count); + + // translate the reslut code here + + return res; + + case DEV_USB : + // translate the arguments here + + result = USB_disk_read(buff, sector, count); + + // translate the reslut code here + + return res; + } + + return RES_PARERR; +} + + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +#if FF_FS_READONLY == 0 + +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to write */ +) +{ + DRESULT res; + int result; + + switch (pdrv) { + case DEV_RAM : + // translate the arguments here + + result = RAM_disk_write(buff, sector, count); + + // translate the reslut code here + + return res; + + case DEV_MMC : + // translate the arguments here + + result = MMC_disk_write(buff, sector, count); + + // translate the reslut code here + + return res; + + case DEV_USB : + // translate the arguments here + + result = USB_disk_write(buff, sector, count); + + // translate the reslut code here + + return res; + } + + return RES_PARERR; +} + +#endif + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + DRESULT res; + int result; + + switch (pdrv) { + case DEV_RAM : + + // Process of the command for the RAM drive + + return res; + + case DEV_MMC : + + // Process of the command for the MMC/SD card + + return res; + + case DEV_USB : + + // Process of the command the USB drive + + return res; + } + + return RES_PARERR; +} + diff --git a/components/fatfs/src/diskio.h b/components/fatfs/src/diskio.h new file mode 100644 index 000000000..31776b8b6 --- /dev/null +++ b/components/fatfs/src/diskio.h @@ -0,0 +1,77 @@ +/*-----------------------------------------------------------------------/ +/ Low level disk interface modlue include file (C)ChaN, 2014 / +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/fatfs/src/ff.c b/components/fatfs/src/ff.c new file mode 100644 index 000000000..d9833c72e --- /dev/null +++ b/components/fatfs/src/ff.c @@ -0,0 +1,6566 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module R0.13c / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of device I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if FF_DEFINED != 86604 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Limits and boundaries */ +#define MAX_DIR 0x200000 /* Max size of FAT directory */ +#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ +#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ +#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ + + +/* Character code support macros */ +#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') +#define IsLower(c) ((c) >= 'a' && (c) <= 'z') +#define IsDigit(c) ((c) >= '0' && (c) <= '9') +#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF) +#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF) +#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF) + + +/* Additional file access control and file status flags for internal use */ +#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ +#define FA_MODIFIED 0x40 /* File has been modified */ +#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ + + +/* Additional file attribute bits for internal use */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Name status flags in fn[11] */ +#define NSFLAG 11 /* Index of the name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ +#define NS_NOLFN 0x40 /* Do not find LFN */ +#define NS_NONAME 0x80 /* Not followed */ + + +/* exFAT directory entry types */ +#define ET_BITMAP 0x81 /* Allocation bitmap */ +#define ET_UPCASE 0x82 /* Up-case table */ +#define ET_VLABEL 0x83 /* Volume label */ +#define ET_FILEDIR 0x85 /* File and directory */ +#define ET_STREAM 0xC0 /* Stream extension */ +#define ET_FILENAME 0xC1 /* Name extension */ + + +/* FatFs refers the FAT structure as simple byte array instead of structure member +/ because the C structure is not binary compatible between different platforms */ + +#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ +#define BS_OEMName 3 /* OEM name (8-byte) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +#define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ +#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ +#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +#define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ +#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ +#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ +#define BS_NTres 37 /* WindowsNT error flag (BYTE) */ +#define BS_BootSig 38 /* Extended boot signature (BYTE) */ +#define BS_VolID 39 /* Volume serial number (DWORD) */ +#define BS_VolLab 43 /* Volume label string (8-byte) */ +#define BS_FilSysType 54 /* Filesystem type string (8-byte) */ +#define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ + +#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ +#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ +#define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ +#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ +#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ +#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ +#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ +#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ +#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ +#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ +#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ +#define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ +#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ + +#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ +#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ +#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ +#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ +#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ +#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ +#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ +#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ +#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ +#define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ +#define BPB_VolFlagEx 106 /* exFAT: Volume flags (WORD) */ +#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ +#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ +#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ +#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ +#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ +#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ +#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ + +#define DIR_Name 0 /* Short file name (11-byte) */ +#define DIR_Attr 11 /* Attribute (BYTE) */ +#define DIR_NTres 12 /* Lower case flag (BYTE) */ +#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ +#define DIR_CrtTime 14 /* Created time (DWORD) */ +#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ +#define DIR_ModTime 22 /* Modified time (DWORD) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ +#define DIR_FileSize 28 /* File size (DWORD) */ +#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ +#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ +#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ +#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ +#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ +#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ +#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ +#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ +#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ +#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ +#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ +#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ +#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ +#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ +#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ +#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ +#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ +#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ +#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ +#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ +#define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ +#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ +#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ +#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ +#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ +#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ + +#define SZDIRE 32 /* Size of a directory entry */ +#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ +#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ +#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ + +#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ + +#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define PTE_Boot 0 /* MBR PTE: Boot indicator */ +#define PTE_StHead 1 /* MBR PTE: Start head */ +#define PTE_StSec 2 /* MBR PTE: Start sector */ +#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ +#define PTE_System 4 /* MBR PTE: System ID */ +#define PTE_EdHead 5 /* MBR PTE: End head */ +#define PTE_EdSec 6 /* MBR PTE: End sector */ +#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ +#define PTE_StLba 8 /* MBR PTE: Start in LBA */ +#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ + + +/* Post process on fatal error in the file operations */ +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* Re-entrancy related */ +#if FF_FS_REENTRANT +#if FF_USE_LFN == 1 +#error Static LFN work area cannot be used at thread-safe configuration +#endif +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define LEAVE_FF(fs, res) return res +#endif + + +/* Definitions of volume - physical location conversion */ +#if FF_MULTI_PARTITION +#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ +#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */ +#else +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ +#endif + + +/* Definitions of sector size */ +#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) +#error Wrong sector size configuration +#endif +#if FF_MAX_SS == FF_MIN_SS +#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + +/* Timestamp */ +#if FF_FS_NORTC == 1 +#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 +#error Invalid FF_FS_NORTC settings +#endif +#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) +#else +#define GET_FATTIME() get_fattime() +#endif + + +/* File lock controls */ +#if FF_FS_LOCK != 0 +#if FF_FS_READONLY +#error FF_FS_LOCK must be 0 at read-only configuration +#endif +typedef struct { + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, containing directory (0:root) */ + DWORD ofs; /* Object ID 3, offset in the directory */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* SBCS up-case tables (\x80-\xFF) */ +#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ + 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ + 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ + 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ + 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ + 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ + 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ + 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ + 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ + 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ + 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} + + +/* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ +#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} +#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} +#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} +#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} + + +/* Macros for table definitions */ +#define MERGE_2STR(a, b) a ## b +#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) + + + + +/*-------------------------------------------------------------------------- + + Module Private Work Area + +---------------------------------------------------------------------------*/ +/* Remark: Variables defined here without initial value shall be guaranteed +/ zero/null at start-up. If not, the linker option or start-up routine is +/ not compliance with C standard. */ + +/*--------------------------------*/ +/* File/Volume controls */ +/*--------------------------------*/ + +#if FF_VOLUMES < 1 || FF_VOLUMES > 10 +#error Wrong FF_VOLUMES setting +#endif +static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* Filesystem mount ID */ + +#if FF_FS_RPATH != 0 +static BYTE CurrVol; /* Current drive */ +#endif + +#if FF_FS_LOCK != 0 +static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ +#endif + +#if FF_STR_VOLUME_ID +#ifdef FF_VOLUME_STRS +static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +#endif +#endif + + +/*--------------------------------*/ +/* LFN/Directory working buffer */ +/*--------------------------------*/ + +#if FF_USE_LFN == 0 /* Non-LFN configuration */ +#if FF_FS_EXFAT +#error LFN must be enabled when enable exFAT +#endif +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#else /* LFN configurations */ +#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 +#error Wrong setting of FF_MAX_LFN +#endif +#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 +#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF +#endif +#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 +#error Wrong setting of FF_LFN_UNICODE +#endif +static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ +#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the name length */ + +#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ +#if FF_FS_EXFAT +static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ +#endif +static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } +#define FREE_NAMBUF() +#else +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } +#define FREE_NAMBUF() +#endif +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } +#define FREE_NAMBUF() ff_memfree(lfn) +#else +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +#define FREE_NAMBUF() ff_memfree(lfn) +#endif +#define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ + +#else +#error Wrong setting of FF_USE_LFN + +#endif /* FF_USE_LFN == 1 */ +#endif /* FF_USE_LFN == 0 */ + + + +/*--------------------------------*/ +/* Code conversion tables */ +/*--------------------------------*/ + +#if FF_CODE_PAGE == 0 /* Run-time code page configuration */ +#define CODEPAGE CodePage +static WORD CodePage; /* Current code page */ +static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ + +static const BYTE Ct437[] = TBL_CT437; +static const BYTE Ct720[] = TBL_CT720; +static const BYTE Ct737[] = TBL_CT737; +static const BYTE Ct771[] = TBL_CT771; +static const BYTE Ct775[] = TBL_CT775; +static const BYTE Ct850[] = TBL_CT850; +static const BYTE Ct852[] = TBL_CT852; +static const BYTE Ct855[] = TBL_CT855; +static const BYTE Ct857[] = TBL_CT857; +static const BYTE Ct860[] = TBL_CT860; +static const BYTE Ct861[] = TBL_CT861; +static const BYTE Ct862[] = TBL_CT862; +static const BYTE Ct863[] = TBL_CT863; +static const BYTE Ct864[] = TBL_CT864; +static const BYTE Ct865[] = TBL_CT865; +static const BYTE Ct866[] = TBL_CT866; +static const BYTE Ct869[] = TBL_CT869; +static const BYTE Dc932[] = TBL_DC932; +static const BYTE Dc936[] = TBL_DC936; +static const BYTE Dc949[] = TBL_DC949; +static const BYTE Dc950[] = TBL_DC950; + +#elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); + +#else /* Static code page configuration (DBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); + +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Load/Store multi-byte word in the FAT structure */ +/*-----------------------------------------------------------------------*/ + +static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +{ + WORD rv; + + rv = ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +{ + DWORD rv; + + rv = ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +#if FF_FS_EXFAT +static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +{ + QWORD rv; + + rv = ptr[7]; + rv = rv << 8 | ptr[6]; + rv = rv << 8 | ptr[5]; + rv = rv << 8 | ptr[4]; + rv = rv << 8 | ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} +#endif + +#if !FF_FS_READONLY +static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +#if FF_FS_EXFAT +static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} +#endif +#endif /* !FF_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static void mem_cpy (void* dst, const void* src, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + + if (cnt != 0) { + do { + *d++ = *s++; + } while (--cnt); + } +} + + +/* Fill memory block */ +static void mem_set (void* dst, int val, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + + do { + *d++ = (BYTE)val; + } while (--cnt); +} + + +/* Compare memory block */ +static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ +{ + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + do { + r = *d++ - *s++; + } while (--cnt && r == 0); + + return r; +} + + +/* Check if chr is contained in the string */ +static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ +{ + while (*str && *str != chr) str++; + return *str; +} + + +/* Test if the character is DBC 1st byte */ +static int dbc_1st (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +/* Test if the character is DBC 2nd byte */ +static int dbc_2nd (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +#if FF_USE_LFN + +/* Get a character from TCHAR string in defined API encodeing */ +static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ + const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ +) +{ + DWORD uc; + const TCHAR *p = *str; + +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + WCHAR wc; + + uc = *p++; /* Get a unit */ + if (IsSurrogate(uc)) { /* Surrogate? */ + wc = *p++; /* Get low surrogate */ + if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ + uc = uc << 16 | wc; + } + +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + BYTE b; + int nf; + + uc = (BYTE)*p++; /* Get a unit */ + if (uc & 0x80) { /* Multiple byte code? */ + if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ + uc &= 0x1F; nf = 1; + } else { + if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */ + uc &= 0x0F; nf = 2; + } else { + if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */ + uc &= 0x07; nf = 3; + } else { /* Wrong sequence */ + return 0xFFFFFFFF; + } + } + } + do { /* Get trailing bytes */ + b = (BYTE)*p++; + if ((b & 0xC0) != 0x80) return 0xFFFFFFFF; /* Wrong sequence? */ + uc = uc << 6 | (b & 0x3F); + } while (--nf != 0); + if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + } + +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + uc = (TCHAR)*p++; /* Get a unit */ + if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + +#else /* ANSI/OEM input */ + BYTE b; + WCHAR wc; + + wc = (BYTE)*p++; /* Get a byte */ + if (dbc_1st((BYTE)wc)) { /* Is it a DBC 1st byte? */ + b = (BYTE)*p++; /* Get 2nd byte */ + if (!dbc_2nd(b)) return 0xFFFFFFFF; /* Invalid code? */ + wc = (wc << 8) + b; /* Make a DBC */ + } + if (wc != 0) { + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM ==> Unicode */ + if (wc == 0) return 0xFFFFFFFF; /* Invalid code? */ + } + uc = wc; + +#endif + *str = p; /* Next read pointer */ + return uc; +} + + +/* Output a TCHAR string in defined API encoding */ +static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ + DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ + TCHAR* buf, /* Output buffer */ + UINT szb /* Size of the buffer */ +) +{ +#if FF_LFN_UNICODE == 1 /* UTF-16 output */ + WCHAR hs, wc; + + hs = (WCHAR)(chr >> 16); + wc = (WCHAR)chr; + if (hs == 0) { /* Single encoding unit? */ + if (szb < 1 || IsSurrogate(wc)) return 0; /* Buffer overflow or wrong code? */ + *buf = wc; + return 1; + } + if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0; /* Buffer overflow or wrong surrogate? */ + *buf++ = hs; + *buf++ = wc; + return 2; + +#elif FF_LFN_UNICODE == 2 /* UTF-8 output */ + DWORD hc; + + if (chr < 0x80) { /* Single byte code? */ + if (szb < 1) return 0; /* Buffer overflow? */ + *buf = (TCHAR)chr; + return 1; + } + if (chr < 0x800) { /* 2-byte sequence? */ + if (szb < 2) return 0; /* Buffer overflow? */ + *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 2; + } + if (chr < 0x10000) { /* 3-byte sequence? */ + if (szb < 3 || IsSurrogate(chr)) return 0; /* Buffer overflow or wrong code? */ + *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 3; + } + /* 4-byte sequence */ + if (szb < 4) return 0; /* Buffer overflow? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07)); + *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 4; + +#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ + DWORD hc; + + if (szb < 1) return 0; /* Buffer overflow? */ + if (chr >= 0x10000) { /* Out of BMP? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + } + *buf++ = (TCHAR)chr; + return 1; + +#else /* ANSI/OEM output */ + WCHAR wc; + + wc = ff_uni2oem(chr, CODEPAGE); + if (wc >= 0x100) { /* Is this a DBC? */ + if (szb < 2) return 0; + *buf++ = (char)(wc >> 8); /* Store DBC 1st byte */ + *buf++ = (TCHAR)wc; /* Store DBC 2nd byte */ + return 2; + } + if (wc == 0 || szb < 1) return 0; /* Invalid char or buffer overflow? */ + *buf++ = (TCHAR)wc; /* Store the character */ + return 1; +#endif +} +#endif /* FF_USE_LFN */ + + +#if FF_FS_REENTRANT +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +static int lock_fs ( /* 1:Ok, 0:timeout */ + FATFS* fs /* Filesystem object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static void unlock_fs ( + FATFS* fs, /* Filesystem object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} + +#endif + + + +#if FF_FS_LOCK != 0 +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ + +static FRESULT chk_lock ( /* Check if the file can be accessed */ + FF_DIR* dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ +) +{ + UINT i, be; + + /* Search open object table for the object */ + be = 0; + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } else { /* Blank entry */ + be = 1; + } + } + if (i == FF_FS_LOCK) { /* The object has not been opened */ + return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ + } + + /* The object was opened. Reject any open against writing file and all write mode open */ + return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + return (i == FF_FS_LOCK) ? 0 : 1; +} + + +static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + FF_DIR* dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ + if (Files[i].fs == dp->obj.fs && + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } + + if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->obj.fs; + Files[i].clu = dp->obj.sclust; + Files[i].ofs = dp->dptr; + Files[i].ctr = 0; + } + + if (acc >= 1 && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; /* Index number origin from 1 */ +} + + +static FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n > 0) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } else { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} + +#endif /* FF_FS_LOCK != 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the filesystem object */ +/*-----------------------------------------------------------------------*/ +#if !FF_FS_READONLY +static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res = FR_OK; + + + if (fs->wflag) { /* Is the disk access window dirty */ + if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write back the window */ + fs->wflag = 0; /* Clear window dirty flag */ + if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ + if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ + } + } else { + res = FR_DISK_ERR; + } + } + return res; +} +#endif + + +static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs, /* Filesystem object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + FRESULT res = FR_OK; + + + if (sector != fs->winsect) { /* Window offset changed? */ +#if !FF_FS_READONLY + res = sync_window(fs); /* Write-back changes */ +#endif + if (res == FR_OK) { /* Fill sector window with new data */ + if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) { + sector = 0xFFFFFFFF; /* Invalidate window if read data is not valid */ + res = FR_DISK_ERR; + } + fs->winsect = sector; + } + } + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Synchronize filesystem and data on the storage */ +/*-----------------------------------------------------------------------*/ + +static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ + /* Create FSInfo structure */ + mem_set(fs->win, 0, sizeof fs->win); + st_word(fs->win + BS_55AA, 0xAA55); + st_dword(fs->win + FSI_LeadSig, 0x41615252); + st_dword(fs->win + FSI_StrucSig, 0x61417272); + st_dword(fs->win + FSI_Free_Count, fs->free_clst); + st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); + /* Write it into the FSInfo sector */ + fs->winsect = fs->volbase + 1; + disk_write(fs->pdrv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the lower layer */ + if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + } + + return res; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Get physical sector number from cluster number */ +/*-----------------------------------------------------------------------*/ + +static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ + FATFS* fs, /* Filesystem object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; /* Cluster number is origin from 2 */ + if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ + return fs->database + fs->csize * clst; /* Start sector number of the cluster */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster number to get the value */ +) +{ + UINT wc, bc; + DWORD val; + FATFS *fs = obj->fs; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ + val = 1; /* Internal error */ + + } else { + val = 0xFFFFFFFF; /* Default value falls on disk error */ + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ + val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ + break; + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; + val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ + break; + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ + break; +#if FF_FS_EXFAT + case FS_EXFAT : + if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ + DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ + DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ + + if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ + val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ + break; + } + if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ + val = clst + 1; /* Generate the value */ + break; + } + if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ + if (obj->n_frag != 0) { /* Is it on the growing edge? */ + val = 0x7FFFFFFF; /* Generate EOC */ + } else { + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + } + break; + } + } + /* go to default */ +#endif + default: + val = 1; /* Internal error */ + } + } + + return val; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ + FATFS* fs, /* Corresponding filesystem object */ + DWORD clst, /* FAT index number (cluster number) to be changed */ + DWORD val /* New value to be set to the entry */ +) +{ + UINT bc; + BYTE *p; + FRESULT res = FR_INT_ERR; + + + if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc++ % SS(fs); + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Put 1st byte */ + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc % SS(fs); + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Put 2nd byte */ + fs->wflag = 1; + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ + fs->wflag = 1; + break; + + case FS_FAT32 : +#if FF_FS_EXFAT + case FS_EXFAT : +#endif + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + } + st_dword(fs->win + clst * 4 % SS(fs), val); + fs->wflag = 1; + break; + } + } + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_FS_EXFAT && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* exFAT: Accessing FAT and Allocation Bitmap */ +/*-----------------------------------------------------------------------*/ + +/*--------------------------------------*/ +/* Find a contiguous free cluster block */ +/*--------------------------------------*/ + +static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to scan from */ + DWORD ncl /* Number of contiguous clusters to find (1..) */ +) +{ + BYTE bm, bv; + UINT i; + DWORD val, scl, ctr; + + + clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ + if (clst >= fs->n_fatent - 2) clst = 0; + scl = val = clst; ctr = 0; + for (;;) { + if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; + i = val / 8 % SS(fs); bm = 1 << (val % 8); + do { + do { + bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ + if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ + val = 0; bm = 0; i = SS(fs); + } + if (bv == 0) { /* Is it a free cluster? */ + if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ + } else { + scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ + } + if (val == clst) return 0; /* All cluster scanned? */ + } while (bm != 0); + bm = 1; + } while (++i < SS(fs)); + } +} + + +/*----------------------------------------*/ +/* Set/Clear a block of allocation bitmap */ +/*----------------------------------------*/ + +static FRESULT change_bitmap ( + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to change from */ + DWORD ncl, /* Number of clusters to be changed */ + int bv /* bit value to be set (0 or 1) */ +) +{ + BYTE bm; + UINT i; + DWORD sect; + + + clst -= 2; /* The first bit corresponds to cluster #2 */ + sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */ + i = clst / 8 % SS(fs); /* Byte offset in the sector */ + bm = 1 << (clst % 8); /* Bit mask in the byte */ + for (;;) { + if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; + do { + do { + if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ + fs->win[i] ^= bm; /* Flip the bit */ + fs->wflag = 1; + if (--ncl == 0) return FR_OK; /* All bits processed? */ + } while (bm <<= 1); /* Next bit */ + bm = 1; + } while (++i < SS(fs)); /* Next byte */ + i = 0; + } +} + + +/*---------------------------------------------*/ +/* Fill the first fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_first_frag ( + FFOBJID* obj /* Pointer to the corresponding object */ +) +{ + FRESULT res; + DWORD cl, n; + + + if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ + for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ + res = put_fat(obj->fs, cl, cl + 1); + if (res != FR_OK) return res; + } + obj->stat = 0; /* Change status 'FAT chain is valid' */ + } + return FR_OK; +} + + +/*---------------------------------------------*/ +/* Fill the last fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_last_frag ( + FFOBJID* obj, /* Pointer to the corresponding object */ + DWORD lcl, /* Last cluster of the fragment */ + DWORD term /* Value to set the last FAT entry */ +) +{ + FRESULT res; + + + while (obj->n_frag > 0) { /* Create the chain of last fragment */ + res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); + if (res != FR_OK) return res; + obj->n_frag--; + } + return FR_OK; +} + +#endif /* FF_FS_EXFAT && !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ + +static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst, /* Cluster to remove a chain from */ + DWORD pclst /* Previous cluster of clst (0 if entire chain) */ +) +{ + FRESULT res = FR_OK; + DWORD nxt; + FATFS *fs = obj->fs; +#if FF_FS_EXFAT || FF_USE_TRIM + DWORD scl = clst, ecl = clst; +#endif +#if FF_USE_TRIM + DWORD rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ + + /* Mark the previous cluster 'EOC' on the FAT if it exists */ + if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { + res = put_fat(fs, pclst, 0xFFFFFFFF); + if (res != FR_OK) return res; + } + + /* Remove the chain */ + do { + nxt = get_fat(obj, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) return FR_INT_ERR; /* Internal error? */ + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ + if (res != FR_OK) return res; + } + if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst++; + fs->fsi_flag |= 1; + } +#if FF_FS_EXFAT || FF_USE_TRIM + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous cluster block */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ + if (res != FR_OK) return res; + } +#endif +#if FF_USE_TRIM + rt[0] = clst2sect(fs, scl); /* Start of data area freed */ + rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area freed */ + disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform device the data in the block is no longer needed */ +#endif + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } while (clst < fs->n_fatent); /* Repeat while not the last link */ + +#if FF_FS_EXFAT + /* Some post processes for chain status */ + if (fs->fs_type == FS_EXFAT) { + if (pclst == 0) { /* Has the entire chain been removed? */ + obj->stat = 0; /* Change the chain status 'initial' */ + } else { + if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ + clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ + while (clst != pclst) { + nxt = get_fat(obj, clst); + if (nxt < 2) return FR_INT_ERR; + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; + if (nxt != clst + 1) break; /* Not contiguous? */ + clst++; + } + if (clst == pclst) { /* Has the chain got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } else { + if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } + } + } +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch a chain or Create a new chain */ +/*-----------------------------------------------------------------------*/ + +static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster# to stretch, 0:Create a new chain */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + FATFS *fs = obj->fs; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clst; /* Suggested cluster to start to find */ + if (scl == 0 || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch a chain */ + cs = get_fat(obj, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* Test for insanity */ + if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; /* Cluster to start to find */ + } + if (fs->free_clst == 0) return 0; /* No free cluster */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ + if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ + res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ + if (res == FR_INT_ERR) return 1; + if (res == FR_DISK_ERR) return 0xFFFFFFFF; + if (clst == 0) { /* Is it a new chain? */ + obj->stat = 2; /* Set status 'contiguous' */ + } else { /* It is a stretched chain */ + if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ + obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ + obj->stat = 3; /* Change status 'just fragmented' */ + } + } + if (obj->stat != 2) { /* Is the file non-contiguous? */ + if (ncl == clst + 1) { /* Is the cluster next to previous one? */ + obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ + } else { /* New fragment */ + if (obj->n_frag == 0) obj->n_frag = 1; + res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ + if (res == FR_OK) obj->n_frag = 1; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + ncl = 0; + if (scl == clst) { /* Stretching an existing chain? */ + ncl = scl + 1; /* Test if next cluster is free */ + if (ncl >= fs->n_fatent) ncl = 2; + cs = get_fat(obj, ncl); /* Get next cluster status */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (cs != 0) { /* Not free? */ + cs = fs->last_clst; /* Start at suggested cluster if it is valid */ + if (cs >= 2 && cs < fs->n_fatent) scl = cs; + ncl = 0; + } + } + if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Check wrap-around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster found? */ + } + cs = get_fat(obj, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster? */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (ncl == scl) return 0; /* No free cluster found? */ + } + } + res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ + } + } + + if (res == FR_OK) { /* Update FSINFO if function succeeded. */ + fs->last_clst = ncl; + if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; + fs->fsi_flag |= 1; + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ + } + + return ncl; /* Return new cluster number or error status */ +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + FATFS *fs = fp->obj.fs; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (ncl == 0) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} + +#endif /* FF_USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Fill a cluster with zeros */ +/*-----------------------------------------------------------------------*/ + +#if !FF_FS_READONLY +static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS *fs, /* Filesystem object */ + DWORD clst /* Directory table to clear */ +) +{ + DWORD sect; + UINT n, szb; + BYTE *ibuf; + + + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ + sect = clst2sect(fs, clst); /* Top of the cluster */ + fs->winsect = sect; /* Set window to top of the cluster */ + mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */ +#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ + /* Allocate a temporary buffer */ + for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; + if (szb > SS(fs)) { /* Buffer allocated? */ + mem_set(ibuf, 0, szb); + szb /= SS(fs); /* Bytes -> Sectors */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + ff_memfree(ibuf); + } else +#endif + { + ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + } + return (n == fs->csize) ? FR_OK : FR_DISK_ERR; +} +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ + FF_DIR* dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + DWORD csz, clst; + FATFS *fs = dp->obj.fs; + + + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ + return FR_INT_ERR; + } + dp->dptr = ofs; /* Set current offset */ + clst = dp->obj.sclust; /* Table start cluster (0:root) */ + if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ + clst = fs->dirbase; + if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ + } + + if (clst == 0) { /* Static table (root-directory on the FAT volume) */ + if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ + dp->sect = fs->dirbase; + + } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ + csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ + while (ofs >= csz) { /* Follow cluster chain */ + clst = get_fat(&dp->obj, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ + ofs -= csz; + } + dp->sect = clst2sect(fs, clst); + } + dp->clust = clst; /* Current cluster# */ + if (dp->sect == 0) return FR_INT_ERR; + dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ + dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + FF_DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD ofs, clst; + FATFS *fs = dp->obj.fs; + + + ofs = dp->dptr + SZDIRE; /* Next entry */ + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */ + if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */ + + if (ofs % SS(fs) == 0) { /* Sector changed? */ + dp->sect++; /* Next sector */ + + if (dp->clust == 0) { /* Static table */ + if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ + dp->sect = 0; return FR_NO_FILE; + } + } + else { /* Dynamic table */ + if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ +#if !FF_FS_READONLY + if (!stretch) { /* If no stretch, report EOT */ + dp->sect = 0; return FR_NO_FILE; + } + clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ + if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ +#else + if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ + dp->sect = 0; return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clst2sect(fs, clst); + } + } + } + dp->dptr = ofs; /* Current entry */ + dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve a block of directory entries */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + FF_DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ +) +{ + FRESULT res; + UINT n; + FATFS *fs = dp->obj.fs; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; +#if FF_FS_EXFAT + if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { +#else + if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { +#endif + if (++n == nent) break; /* A block of contiguous free entries is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dp, 1); + } while (res == FR_OK); /* Next entry with table stretch enabled */ + } + + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT: Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ +) +{ + DWORD cl; + + cl = ld_word(dir + DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) { + cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + } + + return cl; +} + + +#if !FF_FS_READONLY +static void st_clust ( + FATFS* fs, /* Pointer to the fs object */ + BYTE* dir, /* Pointer to the key entry */ + DWORD cl /* Value to be set */ +) +{ + st_word(dir + DIR_FstClusLO, (WORD)cl); + if (fs->fs_type == FS_FAT32) { + st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + } +} +#endif + + + +#if FF_USE_LFN +/*--------------------------------------------------------*/ +/* FAT-LFN: Compare a part of file name with an LFN entry */ +/*--------------------------------------------------------*/ + +static int cmp_lfn ( /* 1:matched, 0:not matched */ + const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ + BYTE* dir /* Pointer to the directory entry containing the part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ + return 0; /* Not matched */ + } + wc = uc; + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ + + return 1; /* The part of LFN matched */ +} + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------*/ +/* FAT-LFN: Pick a part of file name from an LFN entry */ +/*-----------------------------------------------------*/ + +static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ + BYTE* dir /* Pointer to the LFN entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ + + i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */ + if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; /* The part of LFN is valid */ +} +#endif + + +#if !FF_FS_READONLY +/*-----------------------------------------*/ +/* FAT-LFN: Create an entry of LFN entries */ +/*-----------------------------------------*/ + +static void put_lfn ( + const WCHAR* lfn, /* Pointer to the LFN */ + BYTE* dir, /* Pointer to the LFN entry to be created */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* Checksum of the corresponding SFN */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set checksum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + st_word(dir + LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ + st_word(dir + LfnOfs[s], wc); /* Put it */ + if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ + } while (++s < 13); + if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LFN */ + + + +#if FF_USE_LFN && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Create a Numbered SFN */ +/*-----------------------------------------------------------------------*/ + +static void gen_numname ( + BYTE* dst, /* Pointer to the buffer to store numbered SFN */ + const BYTE* src, /* Pointer to SFN */ + const WCHAR* lfn, /* Pointer to LFN */ + UINT seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + WCHAR wc; + DWORD sr; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ + sr = seq; + while (*lfn) { /* Create a CRC as hash value */ + wc = *lfn++; + for (i = 0; i < 16; i++) { + sr = (sr << 1) + (wc & 1); + wc >>= 1; + if (sr & 0x10000) sr ^= 0x11021; + } + } + seq = (UINT)sr; + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (BYTE)((seq % 16) + '0'); + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number to the SFN body */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (dbc_1st(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif /* FF_USE_LFN && !FF_FS_READONLY */ + + + +#if FF_USE_LFN +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Calculate checksum of an SFN entry */ +/*-----------------------------------------------------------------------*/ + +static BYTE sum_sfn ( + const BYTE* dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do { + sum = (sum >> 1) + (sum << 7) + *dir++; + } while (--n); + return sum; +} + +#endif /* FF_USE_LFN */ + + + +#if FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* exFAT: Checksum */ +/*-----------------------------------------------------------------------*/ + +static WORD xdir_sum ( /* Get checksum of the directoly entry block */ + const BYTE* dir /* Directory entry block to be calculated */ +) +{ + UINT i, szblk; + WORD sum; + + + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ + for (i = sum = 0; i < szblk; i++) { + if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ + i++; + } else { + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; + } + } + return sum; +} + + + +static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ + const WCHAR* name /* File name to be calculated */ +) +{ + WCHAR chr; + WORD sum = 0; + + + while ((chr = *name++) != 0) { + chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); + } + return sum; +} + + +#if !FF_FS_READONLY && FF_USE_MKFS +static DWORD xsum32 ( /* Returns 32-bit checksum */ + BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ + DWORD sum /* Previous sum value */ +) +{ + sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; + return sum; +} +#endif + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*------------------------------------------------------*/ +/* exFAT: Get object information from a directory block */ +/*------------------------------------------------------*/ + +static void get_xfileinfo ( + BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ + FILINFO* fno /* Buffer to store the extracted file information */ +) +{ + WCHAR wc, hs; + UINT di, si, nc; + + /* Get file name from the entry block */ + si = SZDIRE * 2; /* 1st C1 entry */ + nc = 0; hs = 0; di = 0; + while (nc < dirb[XDIR_NumName]) { + if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + wc = ld_word(dirb + si); si += 2; nc++; /* Get a character */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ + if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + fno->fname[di] = 0; /* Terminate the name */ + fno->altname[0] = 0; /* exFAT does not support SFN */ + + fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ + fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + +/*-----------------------------------*/ +/* exFAT: Get a directry entry block */ +/*-----------------------------------*/ + +static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + FF_DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +) +{ + FRESULT res; + UINT i, sz_ent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ + + + /* Load file-directory entry */ + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); + sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; + if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; + + /* Load stream-extension entry */ + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); + if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; + + /* Load file-name entries */ + i = 2 * SZDIRE; /* Name offset to load */ + do { + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */ + if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE); + } while ((i += SZDIRE) < sz_ent); + + /* Sanity check (do it for only accessible object) */ + if (i <= MAXDIRB(FF_MAX_LFN)) { + if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + } + return FR_OK; +} + + +/*------------------------------------------------------------------*/ +/* exFAT: Initialize object allocation info with loaded entry block */ +/*------------------------------------------------------------------*/ + +static void init_alloc_info ( + FATFS* fs, /* Filesystem object */ + FFOBJID* obj /* Object allocation information to be initialized */ +) +{ + obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ + obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ + obj->n_frag = 0; /* No last fragment info */ +} + + + +#if !FF_FS_READONLY || FF_FS_RPATH != 0 +/*------------------------------------------------*/ +/* exFAT: Load the object's directory entry block */ +/*------------------------------------------------*/ + +static FRESULT load_obj_xdir ( + FF_DIR* dp, /* Blank directory object to be used to access containing direcotry */ + const FFOBJID* obj /* Object with its containing directory information */ +) +{ + FRESULT res; + + /* Open object containing directory */ + dp->obj.fs = obj->fs; + dp->obj.sclust = obj->c_scl; + dp->obj.stat = (BYTE)obj->c_size; + dp->obj.objsize = obj->c_size & 0xFFFFFF00; + dp->obj.n_frag = 0; + dp->blk_ofs = obj->c_ofs; + + res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ + if (res == FR_OK) { + res = load_xdir(dp); /* Load the object's entry block */ + } + return res; +} +#endif + + +#if !FF_FS_READONLY +/*----------------------------------------*/ +/* exFAT: Store the directory entry block */ +/*----------------------------------------*/ + +static FRESULT store_xdir ( + FF_DIR* dp /* Pointer to the direcotry object */ +) +{ + FRESULT res; + UINT nent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ + + /* Create set sum */ + st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); + nent = dirb[XDIR_NumSec] + 1; + + /* Store the direcotry entry block to the directory */ + res = dir_sdi(dp, dp->blk_ofs); + while (res == FR_OK) { + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) break; + mem_cpy(dp->dir, dirb, SZDIRE); + dp->obj.fs->wflag = 1; + if (--nent == 0) break; + dirb += SZDIRE; + res = dir_next(dp, 0); + } + return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; +} + + + +/*-------------------------------------------*/ +/* exFAT: Create a new directory enrty block */ +/*-------------------------------------------*/ + +static void create_xdir ( + BYTE* dirb, /* Pointer to the direcotry entry block buffer */ + const WCHAR* lfn /* Pointer to the object name */ +) +{ + UINT i; + BYTE nc1, nlen; + WCHAR wc; + + + /* Create file-directory and stream-extension entry */ + mem_set(dirb, 0, 2 * SZDIRE); + dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR; + dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM; + + /* Create file-name entries */ + i = SZDIRE * 2; /* Top of file_name entries */ + nlen = nc1 = 0; wc = 1; + do { + dirb[i++] = ET_FILENAME; dirb[i++] = 0; + do { /* Fill name field */ + if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ + st_word(dirb + i, wc); /* Store it */ + i += 2; + } while (i % SZDIRE != 0); + nc1++; + } while (lfn[nlen]); /* Fill next entry if any char follows */ + + dirb[XDIR_NumName] = nlen; /* Set name length */ + dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count (C0 + C1s) */ + st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_EXFAT */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ + +#define DIR_READ_FILE(dp) dir_read(dp, 0) +#define DIR_READ_LABEL(dp) dir_read(dp, 1) + +static FRESULT dir_read ( + FF_DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res = FR_NO_FILE; + FATFS *fs = dp->obj.fs; + BYTE attr, b; +#if FF_USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + while (dp->sect) { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + b = dp->dir[DIR_Name]; /* Test for the entry type */ + if (b == 0) { + res = FR_NO_FILE; break; /* Reached to end of the directory */ + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + if (FF_USE_LABEL && vol) { + if (b == ET_VLABEL) break; /* Volume label entry? */ + } else { + if (b == ET_FILEDIR) { /* Start of the file entry block? */ + dp->blk_ofs = dp->dptr; /* Get location of the block */ + res = load_xdir(dp); /* Load the entry block */ + if (res == FR_OK) { + dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ + } + break; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ +#if FF_USE_LFN /* LFN configuration */ + if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (attr == AM_LFN) { /* An LFN entry is found */ + if (b & LLEF) { /* Is it start of an LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + b &= (BYTE)~LLEF; ord = b; + dp->blk_ofs = dp->dptr; + } + /* Check LFN validity and capture it */ + ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ + dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ + } + break; + } + } +#else /* Non LFN configuration */ + if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ + break; + } +#endif + } + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ + return res; +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + FF_DIR* dp /* Pointer to the directory object with the file name */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; + BYTE c; +#if FF_USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + BYTE nc; + UINT di, ni; + WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ + + while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */ +#if FF_MAX_LFN < 255 + if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ +#endif + if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ + if ((di % SZDIRE) == 0) di += 2; + if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + } + if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ + } + return res; + } +#endif + /* On the FAT/FAT32 volume */ +#if FF_USE_LFN + ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ +#endif + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if FF_USE_LFN /* LFN configuration */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; + if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (!(dp->fn[NSFLAG] & NS_NOLFN)) { + if (c & LLEF) { /* Is it start of LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; /* LFN start order */ + dp->blk_ofs = dp->dptr; /* Start offset of LFN */ + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ + if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + } +#else /* Non LFN configuration */ + dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; + if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ +#endif + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + FF_DIR* dp /* Target directory with object name to be created */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + UINT n, nlen, nent; + BYTE sn[12], sum; + + + if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ + for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ + res = dir_alloc(dp, nent); /* Allocate directory entries */ + if (res != FR_OK) return res; + dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ + + if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */ + dp->obj.stat &= ~4; + res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ + if (res != FR_OK) return res; + if (dp->obj.sclust != 0) { /* Is it a sub-directory? */ + FF_DIR dj; + + res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ + if (res != FR_OK) return res; + dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ + st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ + st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; + res = store_xdir(&dj); /* Store the object status */ + if (res != FR_OK) return res; + } + } + + create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ + return FR_OK; + } +#endif + /* On the FAT/FAT32 volume */ + mem_cpy(sn, dp->fn, 12); + if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + dp->fn[NSFLAG] = sn[NSFLAG]; + } + + /* Create an SFN with/without LFNs. */ + nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res == FR_OK && --nent) { /* Set LFN entry if needed */ + res = dir_sdi(dp, dp->dptr - nent * SZDIRE); + if (res == FR_OK) { + sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); + fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK && --nent); + } + } + +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ + +#endif + + /* Set SFN entry */ + if (res == FR_OK) { + res = move_window(fs, dp->sect); + if (res == FR_OK) { + mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */ + mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ +#if FF_USE_LFN + dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + fs->wflag = 1; + } + } + + return res; +} + +#endif /* !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + FF_DIR* dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + DWORD last = dp->dptr; + + res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ + if (res == FR_OK) { + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */ + } else { /* On the FAT/FAT32 volume */ + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */ + } + fs->wflag = 1; + if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } +#else /* Non LFN configuration */ + + res = move_window(fs, dp->sect); + if (res == FR_OK) { + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'.*/ + fs->wflag = 1; + } +#endif + + return res; +} + +#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ + +static void get_fileinfo ( + FF_DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + UINT si, di; +#if FF_USE_LFN + BYTE lcf; + WCHAR wc, hs; + FATFS *fs = dp->obj.fs; +#else + TCHAR c; +#endif + + + fno->fname[0] = 0; /* Invaidate file info */ + if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ + +#if FF_USE_LFN /* LFN configuration */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + get_xfileinfo(fs->dirbuf, fno); + return; + } else +#endif + { /* On the FAT/FAT32 volume */ + if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ + si = di = hs = 0; + while (fs->lfnbuf[si] != 0) { + wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ + if (wc == 0) { di = 0; break; } /* Invalid char or buffer overflow? */ + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + fno->fname[di] = 0; /* Terminate the LFN (null string means LFN is invalid) */ + } + } + + si = di = 0; + while (si < 11) { /* Get SFN from SFN entry */ + wc = dp->dir[si++]; /* Get a char */ + if (wc == ' ') continue; /* Skip padding spaces */ + if (wc == RDDEM) wc = DDEM; /* Restore replaced DDEM character */ + if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.'; /* Insert a . if extension is exist */ +#if FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) { /* Make a DBC if needed */ + wc = wc << 8 | dp->dir[si++]; + } + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ + if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ + wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ + if (wc == 0) { di = 0; break; } /* Buffer overflow? */ + di += wc; +#else /* ANSI/OEM output */ + fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ +#endif + } + fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ + + if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ + if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ + fno->fname[di++] = '?'; + } else { + for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ + wc = (WCHAR)fno->altname[si]; + if (wc == '.') lcf = NS_EXT; + if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20; + fno->fname[di] = (TCHAR)wc; + } + } + fno->fname[di] = 0; /* Terminate the LFN */ + if (!dp->dir[DIR_NTres]) fno->altname[0] = 0; /* Altname is not needed if neither LFN nor case info is exist. */ + } + +#else /* Non-LFN configuration */ + si = di = 0; + while (si < 11) { /* Copy name body and extension */ + c = (TCHAR)dp->dir[si++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = DDEM; /* Restore replaced DDEM character */ + if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */ + fno->fname[di++] = c; + } + fno->fname[di] = 0; +#endif + + fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ + fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ + fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + + +#if FF_USE_FIND && FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Pattern matching */ +/*-----------------------------------------------------------------------*/ + +static DWORD get_achar ( /* Get a character and advances ptr */ + const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ +) +{ + DWORD chr; + + +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode input */ + chr = tchar2uni(ptr); + if (chr == 0xFFFFFFFF) chr = 0; /* Wrong UTF encoding is recognized as end of the string */ + chr = ff_wtoupper(chr); + +#else /* ANSI/OEM input */ + chr = (BYTE)*(*ptr)++; /* Get a byte */ + if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ +#if FF_CODE_PAGE == 0 + if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#elif FF_CODE_PAGE < 900 + if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#endif +#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 + if (dbc_1st((BYTE)chr)) { /* Get DBC 2nd byte if needed */ + chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0; + } +#endif + +#endif + return chr; +} + + +static int pattern_matching ( /* 0:not matched, 1:matched */ + const TCHAR* pat, /* Matching pattern */ + const TCHAR* nam, /* String to be tested */ + int skip, /* Number of pre-skip chars (number of ?s) */ + int inf /* Infinite search (* specified) */ +) +{ + const TCHAR *pp, *np; + DWORD pc, nc; + int nm, nx; + + + while (skip--) { /* Pre-skip name chars */ + if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ + } + if (*pat == 0 && inf) return 1; /* (short circuit) */ + + do { + pp = pat; np = nam; /* Top of pattern and name to match */ + for (;;) { + if (*pp == '?' || *pp == '*') { /* Wildcard? */ + nm = nx = 0; + do { /* Analyze the wildcard block */ + if (*pp++ == '?') nm++; else nx = 1; + } while (*pp == '?' || *pp == '*'); + if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ + nc = *np; break; /* Branch mismatched */ + } + pc = get_achar(&pp); /* Get a pattern char */ + nc = get_achar(&np); /* Get a name char */ + if (pc != nc) break; /* Branch mismatched? */ + if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ + } + get_achar(&nam); /* nam++ */ + } while (inf && nc); /* Retry until end of name if infinite search is specified */ + + return 0; +} + +#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ + + + +/*-----------------------------------------------------------------------*/ +/* Pick a top segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + FF_DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ +) +{ +#if FF_USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR wc, *lfn; + DWORD uc; + UINT i, ni, si, di; + const TCHAR *p; + + + /* Create LFN into LFN working buffer */ + p = *path; lfn = dp->obj.fs->lfnbuf; di = 0; + for (;;) { + uc = tchar2uni(&p); /* Get a character */ + if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */ + if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */ + wc = (WCHAR)uc; + if (wc < ' ' || wc == '/' || wc == '\\') break; /* Break if end of the path or a separator is found */ + if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ + if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ + lfn[di++] = wc; /* Store the Unicode character */ + } + while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */ + *path = p; /* Return pointer to the next segment */ + cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + +#if FF_FS_RPATH != 0 + if ((di == 1 && lfn[di - 1] == '.') || + (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ + lfn[di] = 0; + for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */ + dp->fn[i] = (i < di) ? '.' : ' '; + } + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Snip off trailing spaces and dots if exist */ + wc = lfn[di - 1]; + if (wc != ' ' && wc != '.') break; + di--; + } + lfn[di] = 0; /* LFN is created into the working buffer */ + if (di == 0) return FR_INVALID_NAME; /* Reject null name */ + + /* Create SFN in directory form */ + for (si = 0; lfn[si] == ' '; si++) ; /* Remove leading spaces */ + if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */ + while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */ + + mem_set(dp->fn, ' ', 11); + i = b = 0; ni = 8; + for (;;) { + wc = lfn[si++]; /* Get an LFN character */ + if (wc == 0) break; /* Break on end of the LFN */ + if (wc == ' ' || (wc == '.' && si != di)) { /* Remove embedded spaces and dots */ + cf |= NS_LOSS | NS_LFN; + continue; + } + + if (i >= ni || si == di) { /* End of field? */ + if (ni == 11) { /* Name extension overflow? */ + cf |= NS_LOSS | NS_LFN; + break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Name body overflow? */ + if (si > di) break; /* No name extension? */ + si = di; i = 8; ni = 11; b <<= 2; /* Enter name extension */ + continue; + } + + if (wc >= 0x80) { /* Is this a non-ASCII character? */ + cf |= NS_LFN; /* LFN entry needs to be created */ +#if FF_CODE_PAGE == 0 + if (ExCvt) { /* At SBCS */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ + } else { /* At DBCS */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ + } +#elif FF_CODE_PAGE < 900 /* SBCS cfg */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ +#else /* DBCS cfg */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ +#endif + } + + if (wc >= 0x100) { /* Is this a DBC? */ + if (i >= ni - 1) { /* Field overflow? */ + cf |= NS_LOSS | NS_LFN; + i = ni; continue; /* Next field */ + } + dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */ + } else { /* SBC */ + if (wc == 0 || chk_chr("+,;=[]", wc)) { /* Replace illegal characters for SFN if needed */ + wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(wc)) { /* ASCII upper case? */ + b |= 2; + } + if (IsLower(wc)) { /* ASCII lower case? */ + b |= 1; wc -= 0x20; + } + } + } + dp->fn[i++] = (BYTE)wc; + } + + if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + + if (ni == 8) b <<= 2; /* Shift capital flags if no extension */ + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* LFN entry needs to be created if composite capitals */ + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ + if (b & 0x01) cf |= NS_EXT; /* NT flag (Extension has small capital letters only) */ + if (b & 0x04) cf |= NS_BODY; /* NT flag (Body has small capital letters only) */ + } + + dp->fn[NSFLAG] = cf; /* SFN is created into dp->fn[] */ + + return FR_OK; + + +#else /* FF_USE_LFN : Non-LFN configuration */ + BYTE c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + p = *path; sfn = dp->fn; + mem_set(sfn, ' ', 11); + si = i = 0; ni = 8; +#if FF_FS_RPATH != 0 + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = p + si; /* Return pointer to the next segment */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; /* Get a byte */ + if (c <= ' ') break; /* Break if end of the path name */ + if (c == '/' || c == '\\') { /* Break if a separator is found */ + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (c == '.' || i >= ni) { /* End of body or field overflow? */ + if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */ + i = 8; ni = 11; /* Enter file extension field */ + continue; + } +#if FF_CODE_PAGE == 0 + if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#elif FF_CODE_PAGE < 900 + if (c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#endif + if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ + sfn[i++] = c; + sfn[i++] = d; + } else { /* SBC */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ + if (IsLower(c)) c -= 0x20; /* To upper */ + sfn[i++] = c; + } + } + *path = p + si; /* Return pointer to the next segment */ + if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ + + if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + + return FR_OK; +#endif /* FF_USE_LFN */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + FF_DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE ns; + FATFS *fs = dp->obj.fs; + + +#if FF_FS_RPATH != 0 + if (*path != '/' && *path != '\\') { /* Without heading separator */ + dp->obj.sclust = fs->cdir; /* Start from current directory */ + } else +#endif + { /* With heading separator */ + while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ + dp->obj.sclust = 0; /* Start from root directory */ + } +#if FF_FS_EXFAT + dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ +#if FF_FS_RPATH != 0 + if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ + FF_DIR dj; + + dp->obj.c_scl = fs->cdc_scl; + dp->obj.c_size = fs->cdc_size; + dp->obj.c_ofs = fs->cdc_ofs; + res = load_obj_xdir(&dj, &dp->obj); + if (res != FR_OK) return res; + dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } +#endif +#endif + + if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ + dp->fn[NSFLAG] = NS_NONAME; + res = dir_sdi(dp, 0); + + } else { /* Follow path */ + for (;;) { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the segment name */ + ns = dp->fn[NSFLAG]; + if (res != FR_OK) { /* Failed to find the object */ + if (res == FR_NO_FILE) { /* Object is not found */ + if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + dp->fn[NSFLAG] = NS_NONAME; + res = FR_OK; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + /* Get into the sub-directory */ + if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ + res = FR_NO_PATH; break; + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ + dp->obj.c_scl = dp->obj.sclust; + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Open next directory */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ + } + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ + const TCHAR** path /* Pointer to pointer to the path name */ +) +{ + const TCHAR *tp, *tt; + TCHAR tc; + int i, vol = -1; +#if FF_STR_VOLUME_ID /* Find string volume ID */ + const char *sp; + char c; +#endif + + tt = tp = *path; + if (!tp) return vol; /* Invalid path name? */ + do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */ + + if (tc == ':') { /* DOS/Windows style volume ID? */ + i = FF_VOLUMES; + if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ + i = (int)*tp - '0'; /* Get the LD number */ + } +#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ + else { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *tp++; + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + } +#endif + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ + if (*tp == '/') { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *(++tp); + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tp; /* Snip the drive prefix off */ + return vol; + } + } +#endif + /* No drive prefix is found */ +#if FF_FS_RPATH != 0 + vol = CurrVol; /* Default drive is current drive */ +#else + vol = 0; /* Default drive is 0 */ +#endif + return vol; /* Return the default drive */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT VBR */ +/*-----------------------------------------------------------------------*/ + +static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +) +{ + fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ + + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ + +#if FF_FS_EXFAT + if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ +#endif + if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) { /* Valid JumpBoot code? */ + if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */ + if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */ + } + return 2; /* Valid BS but not FAT */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Determine logical drive number and mount the volume if needed */ +/*-----------------------------------------------------------------------*/ + +static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt, *pt; + int vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; + WORD nrsv; + FATFS *fs; + UINT i; + + + /* Get logical drive number */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the filesystem object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the filesystem object */ + if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ +#if FF_FS_REENTRANT + if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ +#endif + *rfs = fs; /* Return pointer to the filesystem object */ + + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ + if (fs->fs_type != 0) { /* If the volume has been mounted */ + stat = disk_status(fs->pdrv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + } + return FR_OK; /* The filesystem object is valid */ + } + } + + /* The filesystem object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ + + fs->fs_type = 0; /* Clear the filesystem object */ + fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + } + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; + } +#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ + if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; +#endif + + /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */ + bsect = 0; + fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ + if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */ + for (i = 0; i < 4; i++) { /* Get partition offset */ + pt = fs->win + (MBR_Table + i * SZ_PTE); + br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; + } + i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + if (i != 0) i--; + do { /* Find an FAT volume */ + bsect = br[i]; + fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ + } while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); + } + if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found (bsect). Following code initializes the filesystem object */ + +#if FF_FS_EXFAT + if (fmt == 1) { + QWORD maxlba; + DWORD so, cv, bcl; + + for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ + if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; + + if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ + + if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + } + + maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ + if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ + + fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + + fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ + if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ + + fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ + if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ + + nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ + fs->n_fatent = nclst + 2; + + /* Boundaries and Limits */ + fs->volbase = bsect; + fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + + /* Get bitmap location and check if it is contiguous (implementation assumption) */ + so = i = 0; + for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */ + if (i == 0) { + if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */ + if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR; + so++; + } + if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ + i = (i + SZDIRE) % SS(fs); /* Next entry */ + } + bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */ + if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; + fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */ + for (;;) { /* Check if bitmap is contiguous */ + if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; + cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); + if (cv == 0xFFFFFFFF) break; /* Last link? */ + if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */ + } + +#if !FF_FS_READONLY + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ +#endif + fmt = FS_EXFAT; /* FAT sub-type */ + } else +#endif /* FF_FS_EXFAT */ + { + if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + + fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ + if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ + if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ + + tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + + nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + FF_DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = 0; + if (nclst <= MAX_FAT32) fmt = FS_FAT32; + if (nclst <= MAX_FAT16) fmt = FS_FAT16; + if (nclst <= MAX_FAT12) fmt = FS_FAT12; + if (fmt == 0) return FR_NO_FILESYSTEM; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ + } else { + if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ + +#if !FF_FS_READONLY + /* Get FSInfo if available */ + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ + fs->fsi_flag = 0x80; +#if (FF_FS_NOFSINFO & 3) != 3 + if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ + && ld_word(fs->win + BPB_FSInfo32) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ + && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 + && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) + { +#if (FF_FS_NOFSINFO & 1) == 0 + fs->free_clst = ld_dword(fs->win + FSI_Free_Count); +#endif +#if (FF_FS_NOFSINFO & 2) == 0 + fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); +#endif + } + } +#endif /* (FF_FS_NOFSINFO & 3) != 3 */ +#endif /* !FF_FS_READONLY */ + } + + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* Volume mount ID */ +#if FF_USE_LFN == 1 + fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ +#if FF_FS_EXFAT + fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ +#endif +#endif +#if FF_FS_RPATH != 0 + fs->cdir = 0; /* Initialize current directory */ +#endif +#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ + clear_lock(fs); +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/FF_DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +) +{ + FRESULT res = FR_INVALID_OBJECT; + + + if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ +#if FF_FS_REENTRANT + if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } else { + unlock_fs(obj->fs, FR_OK); + } + } else { + res = FR_TIMEOUT; + } +#else + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } +#endif + } + *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ + return res; +} + + + + +/*--------------------------------------------------------------------------- + + Public Functions (FatFs API) + +----------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + FATFS* fs, /* Pointer to the filesystem object (NULL:unmount)*/ + const TCHAR* path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + const TCHAR *rp = path; + + + /* Get logical drive number */ + vol = get_ldnumber(&rp); + if (vol < 0) return FR_INVALID_DRIVE; + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) { +#if FF_FS_LOCK != 0 + clear_lock(cfs); +#endif +#if FF_FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if FF_FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ + + res = find_volume(&path, &fs, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL* fp, /* Pointer to the blank file object */ + const TCHAR* path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; +#if !FF_FS_READONLY + DWORD dw, cl, bcs, clst, sc; + FSIZE_t ofs; +#endif + DEF_NAMBUF + + + if (!fp) return FR_INVALID_OBJECT; + + /* Get logical drive number */ + mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; + res = find_volume(&path, &fs, mode); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ +#if !FF_FS_READONLY /* Read/Write configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ + res = FR_INVALID_NAME; + } +#if FF_FS_LOCK != 0 + else { + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ + } +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ +#if FF_FS_LOCK != 0 + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + } + mode |= FA_CREATE_ALWAYS; /* File is created */ + } + else { /* Any object with the same name is already existing */ + if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or FF_DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + /* Get current allocation info */ + fp->obj.fs = fs; + init_alloc_info(fs, &fp->obj); + /* Set directory entry block initial state */ + mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ + mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ + fs->dirbuf[XDIR_Attr] = AM_ARC; + st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); + fs->dirbuf[XDIR_GenFlags] = 1; + res = store_xdir(&dj); + if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ + } + } else +#endif + { + /* Set directory entry initial state */ + cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ + st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ + dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ + st_clust(fs, dj.dir, 0); /* Reset file allocation info */ + st_dword(dj.dir + DIR_FileSize, 0); + fs->wflag = 1; + if (cl != 0) { /* Remove the cluster chain if exist */ + dw = fs->winsect; + res = remove_chain(&dj.obj, cl, 0); + if (res == FR_OK) { + res = move_window(fs, dw); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Is the object exsiting? */ + if (dj.obj.attr & AM_DIR) { /* File open against a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ + res = FR_DENIED; + } + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dj.dir; +#if FF_FS_LOCK != 0 + fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ + if (fp->obj.lockid == 0) res = FR_INT_ERR; +#endif + } +#else /* R/O configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ + res = FR_INVALID_NAME; + } else { + if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ + res = FR_NO_FILE; + } + } + } +#endif + + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ + fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fp->obj.c_ofs = dj.blk_ofs; + init_alloc_info(fs, &fp->obj); + } else +#endif + { + fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ + fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + } +#if FF_USE_FASTSEEK + fp->cltbl = 0; /* Disable fast seek mode */ +#endif + fp->obj.fs = fs; /* Validate the file object */ + fp->obj.id = fs->id; + fp->flag = mode; /* Set file access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ +#if !FF_FS_READONLY +#if !FF_FS_TINY + mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */ +#endif + if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ + fp->fptr = fp->obj.objsize; /* Offset to seek */ + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ + clst = fp->obj.sclust; /* Follow the cluster chain */ + for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { + clst = get_fat(&fp->obj, clst); + if (clst <= 1) res = FR_INT_ERR; + if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; + } + fp->clust = clst; + if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ + if ((sc = clst2sect(fs, clst)) == 0) { + res = FR_INT_ERR; + } else { + fp->sect = sc + (DWORD)(ofs / SS(fs)); +#if !FF_FS_TINY + if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; +#endif + } + } + } +#endif + } + + FREE_NAMBUF(); + } + + if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL* fp, /* Pointer to the file object */ + void* buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT* br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, cc, csect; + BYTE *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until btr bytes read */ + btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow cluster chain from the origin */ + } else { /* Middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ + } + } + if (clst < 2) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if FF_FS_TINY + if (fs->wflag && fs->winsect - sect < cc) { + mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); + } +#else + if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { + mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); + } +#endif +#endif + rcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !FF_FS_TINY + if (fp->sect != sect) { /* Load data sector if not in cache */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + } +#endif + fp->sect = sect; + } + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#else + mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#endif + } + + LEAVE_FF(fs, FR_OK); +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT* bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + UINT wcnt, cc, csect; + const BYTE *wbuff = (const BYTE*)buff; + + + *bw = 0; /* Clear write byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + for ( ; btw; /* Repeat until all data written */ + btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + if (clst == 0) { /* If no cluster is allocated, */ + clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ + } + } else { /* On the middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ + } +#if FF_FS_TINY + if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ +#else + if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if FF_FS_MINIMIZE <= 2 +#if FF_FS_TINY + if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); + fs->wflag = 0; + } +#else + if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif +#endif + wcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if FF_FS_TINY + if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ + if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); + fs->winsect = sect; + } +#else + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { + ABORT(fs, FR_DISK_ERR); + } +#endif + fp->sect = sect; + } + wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fs->wflag = 1; +#else + mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fp->flag |= FA_DIRTY; +#endif + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD tm; + BYTE *dir; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { + if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ +#if !FF_FS_TINY + if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + /* Update the directory entry */ + tm = GET_FATTIME(); /* Modified time */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ + if (res == FR_OK) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } + if (res == FR_OK) { + FF_DIR dj; + DEF_NAMBUF + + INIT_NAMBUF(fs); + res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ + if (res == FR_OK) { + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ + st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); + st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); + st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + st_dword(fs->dirbuf + XDIR_AccTime, 0); + res = store_xdir(&dj); /* Restore it to the directory */ + if (res == FR_OK) { + res = sync_fs(fs); + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + FREE_NAMBUF(); + } + } else +#endif + { + res = move_window(fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ + st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_dword(dir + DIR_ModTime, tm); /* Update modified time */ + st_word(dir + DIR_LstAccDate, 0); + fs->wflag = 1; + res = sync_fs(fs); /* Restore it to the directory */ + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL* fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + +#if !FF_FS_READONLY + res = f_sync(fp); /* Flush cached data */ + if (res == FR_OK) +#endif + { + res = validate(&fp->obj, &fs); /* Lock volume */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ + if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ +#else + fp->obj.fs = 0; /* Invalidate file object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + } + return res; +} + + + + +#if FF_FS_RPATH >= 1 +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chdrive ( + const TCHAR* path /* Drive number to set */ +) +{ + int vol; + + + /* Get logical drive number */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + CurrVol = (BYTE)vol; /* Set it as current volume */ + + return FR_OK; +} + + + +FRESULT f_chdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ +#if FF_STR_VOLUME_ID == 2 + UINT i; +#endif + FRESULT res; + FF_DIR dj; + FATFS *fs; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ + fs->cdir = dj.obj.sclust; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdc_scl = dj.obj.c_scl; + fs->cdc_size = dj.obj.c_size; + fs->cdc_ofs = dj.obj.c_ofs; + } +#endif + } else { + if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fs->cdc_ofs = dj.blk_ofs; + } else +#endif + { + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + } + } else { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; +#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ + if (res == FR_OK) { + for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ + CurrVol = (BYTE)i; + } +#endif + } + + LEAVE_FF(fs, res); +} + + +#if FF_FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR* buff, /* Pointer to the directory path */ + UINT len /* Size of buff in unit of TCHAR */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; + UINT i, n; + DWORD ccl; + TCHAR *tp = buff; +#if FF_VOLUMES >= 2 + UINT vl; +#if FF_STR_VOLUME_ID + const char *vp; +#endif +#endif + FILINFO fno; + DEF_NAMBUF + + + /* Get logical drive */ + buff[0] = 0; /* Set null string to get current volume */ + res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + + /* Follow parent directories and create the path */ + i = len; /* Bottom of buffer (directory stack base) */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ + dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ + res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ + if (res != FR_OK) break; + res = move_window(fs, dj.sect); + if (res != FR_OK) break; + dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child directory */ + res = DIR_READ_FILE(&dj); + if (res != FR_OK) break; + if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + for (n = 0; fno.fname[n]; n++) ; /* Name length */ + if (i < n + 1) { /* Insufficient space to store the path name? */ + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ + buff[--i] = '/'; + } + } + if (res == FR_OK) { + if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ +#if FF_VOLUMES >= 2 /* Put drive prefix */ + vl = 0; +#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ + for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; + if (i >= n + 2) { + if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; + for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; + if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; + vl++; + } +#else /* Numeric volume ID */ + if (i >= 3) { + *tp++ = (TCHAR)'0' + CurrVol; + *tp++ = (TCHAR)':'; + vl = 2; + } +#endif + if (vl == 0) res = FR_NOT_ENOUGH_CORE; +#endif + /* Add current directory path */ + if (res == FR_OK) { + do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ + } + } + FREE_NAMBUF(); + } + + *tp = 0; + LEAVE_FF(fs, res); +} + +#endif /* FF_FS_RPATH >= 2 */ +#endif /* FF_FS_RPATH >= 1 */ + + + +#if FF_FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, bcs, nsect; + FSIZE_t ifptr; +#if FF_USE_FASTSEEK + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) res = (FRESULT)fp->err; +#if FF_FS_EXFAT && !FF_FS_READONLY + if (res == FR_OK && fs->fs_type == FS_EXFAT) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } +#endif + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->obj.sclust; /* Origin of the chain */ + if (cl != 0) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(&fp->obj, cl); + if (cl <= 1) ABORT(fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) { + *tbl = 0; /* Terminate table */ + } else { + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + } + } else { /* Fast seek */ + if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ + fp->fptr = ofs; /* Set file pointer */ + if (ofs > 0) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clst2sect(fs, fp->clust); + if (dsc == 0) ABORT(fs, FR_INT_ERR); + dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); + if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ +#endif + fp->sect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ +#endif + if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ + ofs = fp->obj.objsize; + } + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs > 0) { + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->obj.sclust; /* start from the first cluster */ +#if !FF_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(&fp->obj, 0); + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->obj.sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ + ofs -= bcs; fp->fptr += bcs; +#if !FF_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) { /* Clip file size in case of disk full */ + ofs = 0; break; + } + } else +#endif + { + clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); + fp->clust = clst; + } + fp->fptr += ofs; + if (ofs % SS(fs)) { + nsect = clst2sect(fs, clst); /* Current sector */ + if (nsect == 0) ABORT(fs, FR_INT_ERR); + nsect += (DWORD)(ofs / SS(fs)); + } + } + } + if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ +#endif + fp->sect = nsect; + } + } + + LEAVE_FF(fs, res); +} + + + +#if FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + FF_DIR* dp, /* Pointer to directory object to create */ + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + dp->obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(dp, path); /* Follow the path to the directory */ + if (res == FR_OK) { /* Follow completed */ + if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ + if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Get object allocation info */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ + } + } else { /* This object is a file */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dp->obj.id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + if (dp->obj.sclust != 0) { + dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; + } else { + dp->obj.lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + FF_DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + + + res = validate(&dp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ + if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ +#else + dp->obj.fs = 0; /* Invalidate directory object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + FF_DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } else { + INIT_NAMBUF(fs); + res = DIR_READ_FILE(dp); /* Read an item */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ + } + FREE_NAMBUF(); + } + } + LEAVE_FF(fs, res); +} + + + +#if FF_USE_FIND +/*-----------------------------------------------------------------------*/ +/* Find Next File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findnext ( + FF_DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to the file information structure */ +) +{ + FRESULT res; + + + for (;;) { + res = f_readdir(dp, fno); /* Get a directory item */ + if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ + if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ +#if FF_USE_LFN && FF_USE_FIND == 2 + if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ +#endif + } + return res; +} + + + +/*-----------------------------------------------------------------------*/ +/* Find First File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findfirst ( + FF_DIR* dp, /* Pointer to the blank directory object */ + FILINFO* fno, /* Pointer to the file information structure */ + const TCHAR* path, /* Pointer to the directory to open */ + const TCHAR* pattern /* Pointer to the matching pattern */ +) +{ + FRESULT res; + + + dp->pat = pattern; /* Save pointer to pattern string */ + res = f_opendir(dp, path); /* Open the target directory */ + if (res == FR_OK) { + res = f_findnext(dp, fno); /* Find the first item */ + } + return res; +} + +#endif /* FF_USE_FIND */ + + + +#if FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR* path, /* Pointer to the file path */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FF_DIR dj; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) { + INIT_NAMBUF(dj.obj.fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ + res = FR_INVALID_NAME; + } else { /* Found an object */ + if (fno) get_fileinfo(&dj, fno); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(dj.obj.fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR* path, /* Logical drive number */ + DWORD* nclst, /* Pointer to a variable to return number of free clusters */ + FATFS** fatfs /* Pointer to return pointer to corresponding filesystem object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD nfree, clst, sect, stat; + UINT i; + FFOBJID obj; + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + *fatfs = fs; /* Return ptr to the fs object */ + /* If free_clst is valid, return it without full FAT scan */ + if (fs->free_clst <= fs->n_fatent - 2) { + *nclst = fs->free_clst; + } else { + /* Scan FAT to obtain number of free clusters */ + nfree = 0; + if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ + clst = 2; obj.fs = fs; + do { + stat = get_fat(&obj, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) nfree++; + } while (++clst < fs->n_fatent); + } else { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ + BYTE bm; + UINT b; + + clst = fs->n_fatent - 2; /* Number of clusters */ + sect = fs->bitbase; /* Bitmap sector */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of bits with zero in the bitmap */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { + if (!(bm & 1)) nfree++; + bm >>= 1; + } + i = (i + 1) % SS(fs); + } while (clst); + } else +#endif + { /* FAT16/32: Scan WORD/DWORD FAT entries */ + clst = fs->n_fatent; /* Number of entries */ + sect = fs->fatbase; /* Top of the FAT */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of entries with zero in the FAT */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + if (fs->fs_type == FS_FAT16) { + if (ld_word(fs->win + i) == 0) nfree++; + i += 2; + } else { + if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; + i += 4; + } + i %= SS(fs); + } while (--clst); + } + } + *nclst = nfree; /* Return the free clusters */ + fs->free_clst = nfree; /* Now free_clst is valid */ + fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ + } + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD ncl; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fp->obj.sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(&fp->obj, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fs->n_fatent) { + res = remove_chain(&fp->obj, ncl, fp->clust); + } + } + fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ + fp->flag |= FA_MODIFIED; +#if !FF_FS_TINY + if (res == FR_OK && (fp->flag & FA_DIRTY)) { + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { + res = FR_DISK_ERR; + } else { + fp->flag &= (BYTE)~FA_DIRTY; + } + } +#endif + if (res != FR_OK) ABORT(fs, res); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR* path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + FF_DIR dj, sdj; + DWORD dclst = 0; + FATFS *fs; +#if FF_FS_EXFAT + FFOBJID obj; +#endif + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } +#if FF_FS_LOCK != 0 + if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#endif + if (res == FR_OK) { /* The object is accessible */ + if (dj.fn[NSFLAG] & NS_NONAME) { + res = FR_INVALID_NAME; /* Cannot remove the origin directory */ + } else { + if (dj.obj.attr & AM_RDO) { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + obj.fs = fs; + if (fs->fs_type == FS_EXFAT) { + init_alloc_info(fs, &obj); + dclst = obj.sclust; + } else +#endif + { + dclst = ld_clust(fs, dj.dir); + } + if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ +#if FF_FS_RPATH != 0 + if (dclst == fs->cdir) { /* Is it the current directory? */ + res = FR_DENIED; + } else +#endif + { + sdj.obj.fs = fs; /* Open the sub-directory */ + sdj.obj.sclust = dclst; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + sdj.obj.objsize = obj.objsize; + sdj.obj.stat = obj.stat; + } +#endif + res = dir_sdi(&sdj, 0); + if (res == FR_OK) { + res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */ + if (res == FR_OK) res = FR_DENIED; /* Not empty? */ + if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */ +#if FF_FS_EXFAT + res = remove_chain(&obj, dclst, 0); +#else + res = remove_chain(&dj.obj, dclst, 0); +#endif + } + if (res == FR_OK) res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FF_DIR dj; + FFOBJID sobj; + FATFS *fs; + DWORD dcl, pcl, tm; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Name collision? */ + if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */ + res = FR_INVALID_NAME; + } + if (res == FR_NO_FILE) { /* It is clear to create a new directory */ + sobj.fs = fs; /* New object id to create a new chain */ + dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */ + if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */ + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */ + tm = GET_FATTIME(); + if (res == FR_OK) { + res = dir_clear(fs, dcl); /* Clean up the new table */ + if (res == FR_OK) { + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */ + mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */ + fs->win[DIR_Name] = '.'; + fs->win[DIR_Attr] = AM_DIR; + st_dword(fs->win + DIR_ModTime, tm); + st_clust(fs, fs->win, dcl); + mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */ + fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; + st_clust(fs, fs->win + SZDIRE, pcl); + fs->wflag = 1; + } + res = dir_register(&dj); /* Register the object to the parent directoy */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ + st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */ + st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, tm); /* Created time */ + st_clust(fs, dj.dir, dcl); /* Table start cluster */ + dj.dir[DIR_Attr] = AM_DIR; /* Attribute */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } else { + remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */ + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR* path_old, /* Pointer to the object name to be renamed */ + const TCHAR* path_new /* Pointer to the new name */ +) +{ + FRESULT res; + FF_DIR djo, djn; + FATFS *fs; + BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; + DWORD dw; + DEF_NAMBUF + + + get_ldnumber(&path_new); /* Snip the drive number of new name off */ + res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + if (res == FR_OK) { + djo.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&djo, path_old); /* Check old object */ + if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + res = chk_lock(&djo, 2); + } +#endif + if (res == FR_OK) { /* Object to be renamed is found */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ + BYTE nf, nn; + WORD nh; + + mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ + mem_cpy(&djn, &djo, sizeof djo); + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; + nh = ld_word(fs->dirbuf + XDIR_NameHash); + mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ + fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; + st_word(fs->dirbuf + XDIR_NameHash, nh); + if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ +/* Start of critical section where an interruption can cause a cross-link */ + res = store_xdir(&djn); + } + } + } else +#endif + { /* At FAT/FAT32 volume */ + mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ + mem_cpy(&djn, &djo, sizeof (FF_DIR)); /* Duplicate the directory object */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy directory entry of the object except name */ + mem_cpy(dir + 13, buf + 13, SZDIRE - 13); + dir[DIR_Attr] = buf[DIR_Attr]; + if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ + fs->wflag = 1; + if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ + dw = clst2sect(fs, ld_clust(fs, dir)); + if (dw == 0) { + res = FR_INT_ERR; + } else { +/* Start of critical section where an interruption can cause a cross-link */ + res = move_window(fs, dw); + dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ + if (res == FR_OK && dir[1] == '.') { + st_clust(fs, dir, djn.obj.sclust); + fs->wflag = 1; + } + } + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) { + res = sync_fs(fs); + } + } +/* End of the critical section */ + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_MINIMIZE == 0 */ +#endif /* FF_FS_MINIMIZE <= 1 */ +#endif /* FF_FS_MINIMIZE <= 2 */ + + + +#if FF_USE_CHMOD && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR* path, /* Pointer to the file path */ + BYTE attr, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + res = store_xdir(&dj); + } else +#endif + { + dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR* path, /* Pointer to the file/directory name */ + const FILINFO* fno /* Pointer to the timestamp to be set */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_CHMOD && !FF_FS_READONLY */ + + + +#if FF_USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Logical drive number */ + TCHAR* label, /* Buffer to store the volume label */ + DWORD* vsn /* Variable to store the volume serial number */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; + UINT si, di; + WCHAR wc; + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = DIR_READ_LABEL(&dj); /* Find a volume label entry */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + WCHAR hs; + + for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ + wc = ld_word(dj.dir + XDIR_Label + si * 2); + if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ + hs = wc; continue; + } + wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4); + if (wc == 0) { di = 0; break; } + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + label[di] = 0; + } else +#endif + { + si = di = 0; /* Extract volume label from AM_VOL entry */ + while (si < 11) { + wc = dj.dir[si++]; +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ + wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ + if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ + if (wc == 0) { di = 0; break; } + di += wc; +#else /* ANSI/OEM output */ + label[di++] = (TCHAR)wc; +#endif + } + do { /* Truncate trailing spaces */ + label[di] = 0; + if (di == 0) break; + } while (label[--di] == ' '); + } + } + } + if (res == FR_NO_FILE) { /* No label entry and return nul string */ + label[0] = 0; + res = FR_OK; + } + } + + /* Get volume serial number */ + if (res == FR_OK && vsn) { + res = move_window(fs, fs->volbase); + if (res == FR_OK) { + switch (fs->fs_type) { + case FS_EXFAT: + di = BPB_VolIDEx; break; + + case FS_FAT32: + di = BS_VolID32; break; + + default: + di = BS_VolID; + } + *vsn = ld_dword(fs->win + di); + } + } + + LEAVE_FF(fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Volume label to set with heading logical drive number */ +) +{ + FRESULT res; + FF_DIR dj; + FATFS *fs; + BYTE dirvn[22]; + UINT di; + WCHAR wc; + static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ +#if FF_USE_LFN + DWORD dc; +#endif + + /* Get logical drive */ + res = find_volume(&label, &fs, FA_WRITE); + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + mem_set(dirvn, 0, 22); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ + dc = tchar2uni(&label); /* Get a Unicode character */ + if (dc >= 0x10000) { + if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ + dc = 0; + } else { + st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; + } + } + if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) { /* Check validity of the volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + st_word(dirvn + di * 2, (WCHAR)dc); di++; + } + } else +#endif + { /* On the FAT/FAT32 volume */ + mem_set(dirvn, ' ', 11); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ +#if FF_USE_LFN + dc = tchar2uni(&label); + wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; +#else /* ANSI/OEM input */ + wc = (BYTE)*label++; + if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0; + if (IsLower(wc)) wc -= 0x20; /* To upper ASCII characters */ +#if FF_CODE_PAGE == 0 + if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#elif FF_CODE_PAGE < 900 + if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#endif +#endif + if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8); + dirvn[di++] = (BYTE)wc; + } + if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ + while (di && dirvn[di - 1] == ' ') di--; /* Snip trailing spaces */ + } + + /* Set volume label */ + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = DIR_READ_LABEL(&dj); /* Get volume label entry */ + if (res == FR_OK) { + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */ + mem_cpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + if (di != 0) { + mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */ + } else { + dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ + } + } + fs->wflag = 1; + res = sync_fs(fs); + } else { /* No volume label entry or an error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (di != 0) { /* Create a volume label entry */ + res = dir_alloc(&dj, 1); /* Allocate an entry */ + if (res == FR_OK) { + mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */ + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */ + dj.dir[XDIR_NumLabel] = (BYTE)di; + mem_cpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ + mem_cpy(dj.dir, dirvn, 11); + } + fs->wflag = 1; + res = sync_fs(fs); + } + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LABEL */ + + + +#if FF_USE_EXPAND && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Allocate a Contiguous Blocks to the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_expand ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t fsz, /* File size to be expanded to */ + BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, stcl, scl, ncl, tcl, lclst; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ +#endif + n = (DWORD)fs->csize * SS(fs); /* Cluster size */ + tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ + stcl = fs->last_clst; lclst = 0; + if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ + if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ + if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ + lclst = scl + tcl - 1; + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } else +#endif + { + scl = clst = stcl; ncl = 0; + for (;;) { /* Find a contiguous cluster block */ + n = get_fat(&fp->obj, clst); + if (++clst >= fs->n_fatent) clst = 2; + if (n == 1) { res = FR_INT_ERR; break; } + if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (n == 0) { /* Is it a free cluster? */ + if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ + } else { + scl = clst; ncl = 0; /* Not a free cluster */ + } + if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ + } + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ + res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); + if (res != FR_OK) break; + lclst = clst; + } + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } + + if (res == FR_OK) { + fs->last_clst = lclst; /* Set suggested start cluster to start next */ + if (opt) { /* Is it allocated now? */ + fp->obj.sclust = scl; /* Update object allocation information */ + fp->obj.objsize = fsz; + if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ + fp->flag |= FA_MODIFIED; + if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst -= tcl; + fs->fsi_flag |= 1; + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_EXPAND && !FF_FS_READONLY */ + + + +#if FF_USE_FORWARD +/*-----------------------------------------------------------------------*/ +/* Forward Data to the Stream Directly */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_forward ( + FIL* fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT* bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, csect; + BYTE *dbuf; + + + *bf = 0; /* Clear transfer byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + remain = fp->obj.objsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + if (csect == 0) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->obj.sclust : get_fat(&fp->obj, fp->clust); + if (clst <= 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clst2sect(fs, fp->clust); /* Get current data sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; +#if FF_FS_TINY + if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ + dbuf = fs->win; +#else + if (fp->sect != sect) { /* Fill sector cache with file data */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + dbuf = fp->buf; +#endif + fp->sect = sect; + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ + rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ + if (rcnt == 0) ABORT(fs, FR_INT_ERR); + } + + LEAVE_FF(fs, FR_OK); +} +#endif /* FF_USE_FORWARD */ + + + +#if FF_USE_MKFS && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create an FAT/exFAT volume */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkfs ( + const TCHAR* path, /* Logical drive number */ + BYTE opt, /* Format option */ + DWORD au, /* Size of allocation unit (cluster) [byte] */ + void* work, /* Pointer to working buffer (null: use heap memory) */ + UINT len /* Size of working buffer [byte] */ +) +{ + const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ + const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ + BYTE fmt, sys, *buf, *pte, pdrv, part; + WORD ss; /* Sector size */ + DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; + DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ + DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ + UINT i; + int vol; + DSTATUS stat; +#if FF_USE_TRIM || FF_FS_EXFAT + DWORD tbl[3]; +#endif + + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); /* Get target logical drive */ + if (vol < 0) return FR_INVALID_DRIVE; + if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */ + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ + + /* Check physical drive status */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ +#if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = FF_MAX_SS; +#endif + if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ + au /= ss; /* Cluster size in unit of sector */ + + /* Get working buffer */ +#if FF_USE_LFN == 3 + if (!work) { /* Use heap memory for working buffer */ + for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; + sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ + } else +#endif + { + buf = (BYTE*)work; /* Working buffer */ + sz_buf = len / ss; /* Size of working buffer (sector) */ + szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ + } + if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; + + /* Determine where the volume to be located (b_vol, sz_vol) */ + if (FF_MULTI_PARTITION && part != 0) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ + if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ + pte = buf + (MBR_Table + (part - 1) * SZ_PTE); + if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ + b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + } else { + /* Create a single-partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ + if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); + sz_vol -= b_vol; /* Volume size */ + } + if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ + + /* Pre-determine the FAT type */ + do { + if (FF_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ + if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ + fmt = FS_EXFAT; break; + } + } + if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER); /* Too large au for FAT/FAT32 */ + if (opt & FM_FAT32) { /* FAT32 possible? */ + if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ + fmt = FS_FAT32; break; + } + } + if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER); /* no-FAT? */ + fmt = FS_FAT16; + } while (0); + +#if FF_FS_EXFAT + if (fmt == FS_EXFAT) { /* Create an exFAT volume */ + DWORD szb_bit, szb_case, sum, nb, cl; + WCHAR ch, si; + UINT j, st; + BYTE b; + + if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Determine FAT location, data location and number of clusters */ + if (au == 0) { /* au auto-selection */ + au = 8; + if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ + } + b_fat = b_vol + 32; /* FAT start at offset 32 */ + sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ + b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ + if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ + if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */ + if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */ + + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ + + /* Create a compressed up-case table */ + sect = b_data + au * tbl[0]; /* Table start sector */ + sum = 0; /* Table checksum to be stored in the 82 entry */ + st = 0; si = 0; i = 0; j = 0; szb_case = 0; + do { + switch (st) { + case 0: + ch = (WCHAR)ff_wtoupper(si); /* Get an up-case char */ + if (ch != si) { + si++; break; /* Store the up-case char if exist */ + } + for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ + if (j >= 128) { + ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ + } + st = 1; /* Do not compress short run */ + /* go to next case */ + case 1: + ch = si++; /* Fill the short run */ + if (--j == 0) st = 0; + break; + + default: + ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ + st = 0; + } + sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ + sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); + i += 2; szb_case += 2; + if (si == 0 || i == szb_buf) { /* Write buffered data when buffer full or end of process */ + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; i = 0; + } + } while (si); + tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ + tbl[2] = 1; /* Number of root dir clusters */ + + /* Initialize the allocation bitmap */ + sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ + nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ + do { + mem_set(buf, 0, szb_buf); + for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; + for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the FAT */ + sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ + j = nb = cl = 0; + do { + mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ + if (cl == 0) { /* Set entry 0 and 1 */ + st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; + st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; + } + do { /* Create chains of bitmap, up-case and root dir */ + while (nb != 0 && i < szb_buf) { /* Create a chain */ + st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); + i += 4; cl++; nb--; + } + if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ + } while (nb != 0 && i < szb_buf); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the root directory */ + mem_set(buf, 0, szb_buf); + buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */ + buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ + st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ + buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ + st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ + st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ + sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ + do { /* Fill root directory sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + + /* Create two set of the exFAT VBR blocks */ + sect = b_vol; + for (n = 0; n < 2; n++) { + /* Main record (+0) */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ + st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ + st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ + st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ + st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ + for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ + for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ + buf[BPB_NumFATsEx] = 1; /* Number of FATs */ + buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ + st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + for (i = sum = 0; i < ss; i++) { /* VBR checksum */ + if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); + } + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + /* Extended bootstrap record (+1..+8) */ + mem_set(buf, 0, ss); + st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + for (j = 1; j < 9; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* OEM/Reserved record (+9..+10) */ + mem_set(buf, 0, ss); + for ( ; j < 11; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* Sum record (+11) */ + for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + + } else +#endif /* FF_FS_EXFAT */ + { /* Create an FAT/FAT32 volume */ + do { + pau = au; + /* Pre-determine number of clusters and FAT sub-type */ + if (fmt == FS_FAT32) { /* FAT32 volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ + for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; /* Number of clusters */ + sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 32; /* Number of reserved sectors */ + sz_dir = 0; /* No static directory */ + if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); + } else { /* FAT volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ + for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; + if (n_clst > MAX_FAT12) { + n = n_clst * 2 + 4; /* FAT size [byte] */ + } else { + fmt = FS_FAT12; + n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ + } + sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 1; /* Number of reserved sectors */ + sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ + } + b_fat = b_vol + sz_rsv; /* FAT base */ + b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ + + /* Align data base to erase block boundary (for flash memory media) */ + n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ + if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ + sz_rsv += n; b_fat += n; + } else { /* FAT: Expand FAT size */ + sz_fat += n / n_fats; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume */ + n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; + if (fmt == FS_FAT32) { + if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32 */ + if (au == 0 && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fmt == FS_FAT16) { + if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ + if (au == 0 && (pau * 2) <= 64) { + au = pau * 2; continue; /* Adjust cluster size and retry */ + } + if ((opt & FM_FAT32)) { + fmt = FS_FAT32; continue; /* Switch type to FAT32 and retry */ + } + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters for FAT12 */ + + /* Ok, it is the valid cluster configuration */ + break; + } while (1); + +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Create FAT VBR */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ + st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ + st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ + st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ + if (sz_vol < 0x10000) { + st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + } else { + st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ + } + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ + st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ + if (fmt == FS_FAT32) { + st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ + + /* Create FSINFO record if needed */ + if (fmt == FS_FAT32) { + disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + mem_set(buf, 0, ss); + st_dword(buf + FSI_LeadSig, 0x41615252); + st_dword(buf + FSI_StrucSig, 0x61417272); + st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_word(buf + BS_55AA, 0xAA55); + disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + } + + /* Initialize FAT area */ + mem_set(buf, 0, (UINT)szb_buf); + sect = b_fat; /* FAT start sector */ + for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ + if (fmt == FS_FAT32) { + st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ + st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ + st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ + } else { + st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ + } + nsect = sz_fat; /* Number of FAT sectors */ + do { /* Fill FAT sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + } + + /* Initialize root directory (fill with zero) */ + nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ + do { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + } + + /* Determine system ID in the partition table */ + if (FF_FS_EXFAT && fmt == FS_EXFAT) { + sys = 0x07; /* HPFS/NTFS/exFAT */ + } else { + if (fmt == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else { + if (sz_vol >= 0x10000) { + sys = 0x06; /* FAT12/16 (large) */ + } else { + sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ + } + } + } + + /* Update partition information */ + if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ + /* Update system ID in the partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ + buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ + } else { /* Created as a new single partition */ + if (!(opt & FM_SFD)) { /* Create partition table if in FDISK format */ + mem_set(buf, 0, ss); + st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ + pte[PTE_Boot] = 0; /* Boot indicator */ + pte[PTE_StHead] = 1; /* Start head */ + pte[PTE_StSec] = 1; /* Start sector */ + pte[PTE_StCyl] = 0; /* Start cylinder */ + pte[PTE_System] = sys; /* System type */ + n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ + pte[PTE_EdHead] = 254; /* End head */ + pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63); /* End sector */ + pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ + st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ + st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the MBR */ + } + } + + if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + + LEAVE_MKFS(FR_OK); +} + + + +#if FF_MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Create Partition Table on the Physical Drive */ +/*-----------------------------------------------------------------------*/ + +#define CLUSTER_SIZE 63 +#define SUPPORTED_FLASH_SIZE 0x1000 + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD* szt, /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer (null: use heap memory) */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + DWORD cluster_size = CLUSTER_SIZE; + FRESULT res; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + buf = (BYTE*)work; +#if FF_USE_LFN == 3 + if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ +#endif + if (!buf) return FR_NOT_ENOUGH_CORE; + + /* Determine the CHS without any consideration of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / cluster_size > 1024; n *= 2) { + ; + } + if (n == 256) n--; + if (sz_disk < SUPPORTED_FLASH_SIZE) { + cluster_size = 1; + n = sz_disk; + } + e_hd = n - 1; + sz_cyl = cluster_size * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, FF_MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ + if (p_cyl == 0) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += cluster_size; sz_part -= cluster_size; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ + if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER); + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x07; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | cluster_size); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + st_dword(p + 8, s_part); /* Start sector in LBA */ + st_dword(p + 12, sz_part); /* Number of sectors */ + + /* Next partition */ + b_cyl += p_cyl; + } + st_word(p, 0xAA55); /* MBR signature (always at offset 510) */ + + /* Write it to the MBR */ + res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; + LEAVE_MKFS(res); +} + +#endif /* FF_MULTI_PARTITION */ +#endif /* FF_USE_MKFS && !FF_FS_READONLY */ + + + + +#if FF_USE_STRFUNC +#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3) +#error Wrong FF_STRF_ENCODE setting +#endif +/*-----------------------------------------------------------------------*/ +/* Get a String from the File */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (items) */ + FIL* fp /* Pointer to the file object */ +) +{ + int nc = 0; + TCHAR *p = buff; + BYTE s[4]; + UINT rc; + DWORD dc; +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 + WCHAR wc; +#endif +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 + UINT ct; +#endif + +#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ + /* Make a room for the character and terminator */ + if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; + if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; + if (FF_LFN_UNICODE == 3) len -= 1; + while (nc < len) { +#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + wc = s[0]; + if (dbc_1st((BYTE)wc)) { + f_read(fp, s, 1, &rc); + if (rc != 1 || !dbc_2nd(s[0])) continue; + wc = wc << 8 | s[0]; + } + dc = ff_oem2uni(wc, CODEPAGE); + if (dc == 0) continue; +#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (IsSurrogateL(dc)) continue; + if (IsSurrogateH(dc)) { + f_read(fp, s, 2, &rc); + if (rc != 2) break; + wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (!IsSurrogateL(wc)) continue; + dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); + } +#else /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (dc >= 0x80) { /* Multi-byte character? */ + ct = 0; + if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte? */ + if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte? */ + if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte? */ + if (ct == 0) continue; + f_read(fp, s, ct, &rc); /* Get trailing bytes */ + if (rc != ct) break; + rc = 0; + do { /* Merge trailing bytes */ + if ((s[rc] & 0xC0) != 0x80) break; + dc = dc << 6 | (s[rc] & 0x3F); + } while (++rc < ct); + if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ + } +#endif + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ +#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ + if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ + *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ + dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ + } + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; /* End of line? */ +#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ + if (dc < 0x80) { /* 1-byte */ + *p++ = (TCHAR)dc; + nc++; + if (dc == '\n') break; /* End of line? */ + } else { + if (dc < 0x800) { /* 2-byte */ + *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 2; + } else { + if (dc < 0x10000) { /* 3-byte */ + *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 3; + } else { /* 4-byte */ + *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); + *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 4; + } + } + } +#endif + } + +#else /* Byte-by-byte without any conversion (ANSI/OEM API) */ + len -= 1; /* Make a room for the terminator */ + while (nc < len) { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; + } +#endif + + *p = 0; /* Terminate the string */ + return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ +} + + + + +#if !FF_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a Character to the File */ +/*-----------------------------------------------------------------------*/ + +typedef struct { /* Putchar output buffer and work area */ + FIL *fp; /* Ptr to the writing file */ + int idx, nchr; /* Write index of buf[] (-1:error), number of encoding units written */ +#if FF_USE_LFN && FF_LFN_UNICODE == 1 + WCHAR hs; +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 + BYTE bs[4]; + UINT wi, ct; +#endif + BYTE buf[64]; /* Write buffer */ +} putbuff; + + +static void putc_bfd ( /* Buffered write with code conversion */ + putbuff* pb, + TCHAR c +) +{ + UINT n; + int i, nc; +#if FF_USE_LFN && FF_LFN_UNICODE + WCHAR hs, wc; +#if FF_LFN_UNICODE == 2 + DWORD dc; + TCHAR *tp; +#endif +#endif + + if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ + putc_bfd(pb, '\r'); + } + + i = pb->idx; /* Write index of pb->buf[] */ + if (i < 0) return; + nc = pb->nchr; /* Write unit counter */ + +#if FF_USE_LFN && FF_LFN_UNICODE +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + if (IsSurrogateH(c)) { + pb->hs = c; return; + } + hs = pb->hs; pb->hs = 0; + if (hs != 0) { + if (!IsSurrogateL(c)) hs = 0; + } else { + if (IsSurrogateL(c)) return; + } + wc = c; +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + for (;;) { + if (pb->ct == 0) { /* Out of multi-byte sequence? */ + pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ + if ((BYTE)c < 0x80) break; /* 1-byte? */ + if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1; /* 2-byte? */ + if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte? */ + if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte? */ + return; + } else { /* In the multi-byte sequence */ + if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ + pb->ct = 0; continue; + } + pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ + if (--pb->ct == 0) break; /* End of multi-byte sequence? */ + return; + } + } + tp = (TCHAR*)pb->bs; + dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ + if (dc == 0xFFFFFFFF) return; + wc = (WCHAR)dc; + hs = (WCHAR)(dc >> 16); +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + if (IsSurrogate(c) || c >= 0x110000) return; + if (c >= 0x10000) { + hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ + wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ + } else { + hs = 0; + wc = (WCHAR)c; + } +#endif + +#if FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + if (hs != 0) { + st_word(&pb->buf[i], hs); + i += 2; + nc++; + } + st_word(&pb->buf[i], wc); + i += 2; +#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + if (hs != 0) { + pb->buf[i++] = (BYTE)(hs >> 8); + pb->buf[i++] = (BYTE)hs; + nc++; + } + pb->buf[i++] = (BYTE)(wc >> 8); + pb->buf[i++] = (BYTE)wc; +#elif FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ + if (hs != 0) { /* 4-byte */ + nc += 3; + hs = (hs & 0x3FF) + 0x40; + pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); + pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); + pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } else { + if (wc < 0x80) { /* 1-byte */ + pb->buf[i++] = (BYTE)wc; + } else { + if (wc < 0x800) { /* 2-byte */ + nc += 1; + pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); + } else { /* 3-byte */ + nc += 2; + pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); + pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } + } +#else /* Write it in ANSI/OEM */ + if (hs != 0) return; + wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ + if (wc == 0) return; + if (wc >= 0x100) { + pb->buf[i++] = (BYTE)(wc >> 8); nc++; + } + pb->buf[i++] = (BYTE)wc; +#endif + +#else /* ANSI/OEM input (without re-encode) */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ + f_write(pb->fp, pb->buf, (UINT)i, &n); + i = (n == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr = nc + 1; +} + + +static int putc_flush ( /* Flush left characters in the buffer */ + putbuff* pb +) +{ + UINT nw; + + if ( pb->idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK + && (UINT)pb->idx == nw) return pb->nchr; + return EOF; +} + + +static void putc_init ( /* Initialize write buffer */ + putbuff* pb, + FIL* fp +) +{ + mem_set(pb, 0, sizeof (putbuff)); + pb->fp = fp; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + putc_bfd(&pb, c); /* Put the character */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + while (*str) putc_bfd(&pb, *str++); /* Put the string */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a Formatted String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + putbuff pb; + BYTE f, r; + UINT i, j, w; + DWORD v; + TCHAR c, d, str[32], *p; + + + putc_init(&pb, fp); + + va_start(arp, fmt); + + for (;;) { + c = *fmt++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + putc_bfd(&pb, c); + continue; + } + w = f = 0; + c = *fmt++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + if (c == '*') { /* Minimum width by argument */ + w = va_arg(arp, int); + c = *fmt++; + } else { + while (IsDigit(c)) { /* Minimum width */ + w = w * 10 + c - '0'; + c = *fmt++; + } + } + if (c == 'l' || c == 'L') { /* Type prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (c == 0) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Atgument type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + if (!(f & 2)) { /* Right padded */ + while (j++ < w) putc_bfd(&pb, ' ') ; + } + while (*p) putc_bfd(&pb, *p++) ; /* String body */ + while (j++ < w) putc_bfd(&pb, ' ') ; /* Left padded */ + continue; + + case 'C' : /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; + + case 'B' : /* Unsigned binary */ + r = 2; break; + + case 'O' : /* Unsigned octal */ + r = 8; break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + + case 'X' : /* Unsigned hexdecimal */ + r = 16; break; + + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + str[i++] = d + '0'; + } while (v && i < sizeof str / sizeof *str); + if (f & 8) str[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + if (!(f & 2)) { + while (j++ < w) putc_bfd(&pb, d); /* Right pad */ + } + do { + putc_bfd(&pb, str[--i]); /* Number body */ + } while (i); + while (j++ < w) putc_bfd(&pb, d); /* Left pad */ + } + + va_end(arp); + + return putc_flush(&pb); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_STRFUNC */ + + + +#if FF_CODE_PAGE == 0 +/*-----------------------------------------------------------------------*/ +/* Set Active Codepage for the Path Name */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setcp ( + WORD cp /* Value to be set as active code page */ +) +{ + static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; + static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + UINT i; + + + for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ + if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ + + CodePage = cp; + if (cp >= 900) { /* DBCS */ + ExCvt = 0; + DbcTbl = tables[i]; + } else { /* SBCS */ + ExCvt = tables[i]; + DbcTbl = 0; + } + return FR_OK; +} +#endif /* FF_CODE_PAGE == 0 */ + diff --git a/components/fatfs/src/ff.h b/components/fatfs/src/ff.h new file mode 100644 index 000000000..d8ebeb833 --- /dev/null +++ b/components/fatfs/src/ff.h @@ -0,0 +1,405 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem module R0.13c / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#ifndef FF_DEFINED +#define FF_DEFINED 86604 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ffconf.h" /* FatFs configuration options */ + +#if FF_DEFINED != FFCONF_DEF +#error Wrong configuration file (ffconf.h). +#endif + + +/* Integer types used for FatFs API */ + +#if defined(_WIN32) /* Main development platform */ +#define FF_INTDEF 2 +#include +typedef unsigned __int64 QWORD; +#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */ +#define FF_INTDEF 2 +#include +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef uint16_t WORD; /* 16-bit unsigned integer */ +typedef uint16_t WCHAR; /* 16-bit unsigned integer */ +typedef uint32_t DWORD; /* 32-bit unsigned integer */ +typedef uint64_t QWORD; /* 64-bit unsigned integer */ +#else /* Earlier than C99 */ +#define FF_INTDEF 1 +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef unsigned short WORD; /* 16-bit unsigned integer */ +typedef unsigned short WCHAR; /* 16-bit unsigned integer */ +typedef unsigned long DWORD; /* 32-bit unsigned integer */ +#endif + + +/* Definitions of volume management */ + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#endif + +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + + + +/* Type of path name strings on FatFs API */ + +#ifndef _INC_TCHAR +#define _INC_TCHAR + +#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ +typedef char TCHAR; +#define _T(x) u8 ## x +#define _TEXT(x) u8 ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) +#error Wrong FF_LFN_UNICODE setting +#else /* ANSI/OEM code in SBCS/DBCS */ +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* Type of file size variables */ + +#if FF_FS_EXFAT +#if FF_INTDEF != 2 +#error exFAT feature wants C99 or later +#endif +typedef QWORD FSIZE_t; +#else +typedef DWORD FSIZE_t; +#endif + + + +/* Filesystem object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* Filesystem type (0:not mounted) */ + BYTE pdrv; /* Associated physical drive */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* Volume mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if FF_MAX_SS != FF_MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if FF_USE_LFN + WCHAR* lfnbuf; /* LFN working buffer */ +#endif +#if FF_FS_EXFAT + BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ +#endif +#if FF_FS_REENTRANT + FF_SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !FF_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if FF_FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#if FF_FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Size of an FAT [sectors] */ + DWORD volbase; /* Volume base sector */ + DWORD fatbase; /* FAT base sector */ + DWORD dirbase; /* Root directory base sector/cluster */ + DWORD database; /* Data base sector */ +#if FF_FS_EXFAT + DWORD bitbase; /* Allocation bitmap base sector */ +#endif + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +} FATFS; + + + +/* Object ID and allocation information (FFOBJID) */ + +typedef struct { + FATFS* fs; /* Pointer to the hosting volume of this object */ + WORD id; /* Hosting volume mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if FF_FS_EXFAT + DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ +#endif +#if FF_FS_LOCK + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif +} FFOBJID; + + + +/* File object structure (FIL) */ + +typedef struct { + FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !FF_FS_READONLY + DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ + BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ +#endif +#if FF_USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !FF_FS_TINY + BYTE buf[FF_MAX_SS]; /* File private data read/write window */ +#endif +} FIL; + + + +/* Directory object structure (FF_DIR) */ + +typedef struct { + FFOBJID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector (0:Read operation has terminated) */ + BYTE* dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if FF_USE_LFN + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if FF_USE_FIND + const TCHAR* pat; /* Pointer to the name matching pattern */ +#endif +} FF_DIR; + + + +/* File information structure (FILINFO) */ + +typedef struct { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if FF_USE_LFN + TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ + TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ +#else + TCHAR fname[12 + 1]; /* File name */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ +FRESULT f_truncate (FIL* fp); /* Truncate the file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ +FRESULT f_opendir (FF_DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (FF_DIR* dp); /* Close an open directory */ +FRESULT f_readdir (FF_DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_findfirst (FF_DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ +FRESULT f_findnext (FF_DIR* dp, FILINFO* fno); /* Find next file */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ +FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ +FRESULT f_setcp (WORD cp); /* Set current code page */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) +#define f_unmount(path) f_mount(0, path, 0) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !FF_FS_READONLY && !FF_FS_NORTC +DWORD get_fattime (void); +#endif + +/* LFN support functions */ +#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ +WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ +WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ +DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ +#endif +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif + +/* Sync functions */ +#if FF_FS_REENTRANT +int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + +/* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + +/* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + +/* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + +/* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#ifdef __cplusplus +} +#endif + +#endif /* FF_DEFINED */ diff --git a/components/fatfs/src/ffconf.h b/components/fatfs/src/ffconf.h new file mode 100644 index 000000000..79792beef --- /dev/null +++ b/components/fatfs/src/ffconf.h @@ -0,0 +1,325 @@ +#include "sdkconfig.h" + +/*---------------------------------------------------------------------------/ +/ FatFs Functional Configurations +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 86604 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 0 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 1 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 1 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE CONFIG_FATFS_CODEPAGE +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#if defined(CONFIG_FATFS_LFN_STACK) +#define FF_USE_LFN 2 +#elif defined(CONFIG_FATFS_LFN_HEAP) +#define FF_USE_LFN 3 +#else /* CONFIG_FATFS_LFN_NONE */ +#define FF_USE_LFN 0 +#endif + +#ifdef CONFIG_FATFS_MAX_LFN +#define FF_MAX_LFN CONFIG_FATFS_MAX_LFN +#endif + +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() in ffsystem.c, need to be added to the project. */ + + +#ifdef CONFIG_FATFS_API_ENCODING_UTF_8 +#define FF_LFN_UNICODE 2 +#elif defined(CONFIG_FATFS_API_ENCODING_UTF_16) +#define FF_LFN_UNICODE 1 +#else /* CONFIG_FATFS_API_ENCODING_ANSI_OEM */ +#define FF_LFN_UNICODE 0 +#endif +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be suffcient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 2 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#define FF_MULTI_PARTITION 1 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + +/* SD card sector size */ +#define FF_SS_SDCARD 512 +/* wear_levelling library sector size */ +#define FF_SS_WL CONFIG_WL_SECTOR_SIZE + +#define FF_MIN_SS MIN(FF_SS_SDCARD, FF_SS_WL) +#define FF_MAX_SS MAX(FF_SS_SDCARD, FF_SS_WL) +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY (!CONFIG_FATFS_PER_FILE_CACHE) +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 0 +#define FF_NORTC_MON 1 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK CONFIG_FATFS_FS_LOCK +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 1 +#define FF_FS_TIMEOUT (CONFIG_FATFS_TIMEOUT_MS / portTICK_PERIOD_MS) +#define FF_SYNC_t SemaphoreHandle_t +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +/* Some memory allocation functions are declared here in addition to ff.h, so that + they can be used also by external code when LFN feature is disabled. + */ +void* ff_memalloc (unsigned msize); +void ff_memfree(void*); + + +/*--- End of configuration options ---*/ + +/* Redefine names of disk IO functions to prevent name collisions */ +#define disk_initialize ff_disk_initialize +#define disk_status ff_disk_status +#define disk_read ff_disk_read +#define disk_write ff_disk_write +#define disk_ioctl ff_disk_ioctl diff --git a/components/fatfs/src/ffsystem.c b/components/fatfs/src/ffsystem.c new file mode 100644 index 000000000..b88ce1555 --- /dev/null +++ b/components/fatfs/src/ffsystem.c @@ -0,0 +1,170 @@ +/*------------------------------------------------------------------------*/ +/* Sample Code of OS Dependent Functions for FatFs */ +/* (C)ChaN, 2018 */ +/*------------------------------------------------------------------------*/ + + +#include "ff.h" + + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ + +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ + +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ + UINT msize /* Number of bytes to allocate */ +) +{ + return malloc(msize); /* Allocate a new memory block with POSIX API */ +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free (nothing to do if null) */ +) +{ + free(mblock); /* Free the memory block with POSIX API */ +} + +#endif + + + +#if FF_FS_REENTRANT /* Mutal exclusion */ + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to create a new +/ synchronization object for the volume, such as semaphore and mutex. +/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. +*/ + +//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */ + + +int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ + BYTE vol, /* Corresponding volume (logical drive number) */ + FF_SYNC_t* sobj /* Pointer to return the created sync object */ +) +{ + /* Win32 */ + *sobj = CreateMutex(NULL, FALSE, NULL); + return (int)(*sobj != INVALID_HANDLE_VALUE); + + /* uITRON */ +// T_CSEM csem = {TA_TPRI,1,1}; +// *sobj = acre_sem(&csem); +// return (int)(*sobj > 0); + + /* uC/OS-II */ +// OS_ERR err; +// *sobj = OSMutexCreate(0, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// *sobj = xSemaphoreCreateMutex(); +// return (int)(*sobj != NULL); + + /* CMSIS-RTOS */ +// *sobj = osMutexCreate(&Mutex[vol]); +// return (int)(*sobj != NULL); +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to delete a synchronization +/ object that created with ff_cre_syncobj() function. When a 0 is returned, +/ the f_mount() function fails with FR_INT_ERR. +*/ + +int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ + FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ +) +{ + /* Win32 */ + return (int)CloseHandle(sobj); + + /* uITRON */ +// return (int)(del_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// vSemaphoreDelete(sobj); +// return 1; + + /* CMSIS-RTOS */ +// return (int)(osMutexDelete(sobj) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on entering file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ + FF_SYNC_t sobj /* Sync object to wait */ +) +{ + /* Win32 */ + return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); + + /* uITRON */ +// return (int)(wai_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); + + /* CMSIS-RTOS */ +// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leaving file functions to unlock the volume. +*/ + +void ff_rel_grant ( + FF_SYNC_t sobj /* Sync object to be signaled */ +) +{ + /* Win32 */ + ReleaseMutex(sobj); + + /* uITRON */ +// sig_sem(sobj); + + /* uC/OS-II */ +// OSMutexPost(sobj); + + /* FreeRTOS */ +// xSemaphoreGive(sobj); + + /* CMSIS-RTOS */ +// osMutexRelease(sobj); +} + +#endif + diff --git a/components/fatfs/src/ffunicode.c b/components/fatfs/src/ffunicode.c new file mode 100644 index 000000000..349901b1f --- /dev/null +++ b/components/fatfs/src/ffunicode.c @@ -0,0 +1,15597 @@ +/*------------------------------------------------------------------------*/ +/* Unicode handling functions for FatFs R0.13c */ +/*------------------------------------------------------------------------*/ +/* This module will occupy a huge memory in the .const section when the / +/ FatFs is configured for LFN with DBCS. If the system has any Unicode / +/ utilitiy for the code conversion, this module should be modified to use / +/ that function to avoid silly memory consumption. / +/-------------------------------------------------------------------------*/ +/* +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +*/ + + +#include "ff.h" + +#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */ + +#if FF_DEFINED != 86604 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + +#define MERGE2(a, b) a ## b +#define CVTBL(tbl, cp) MERGE2(tbl, cp) + + +/*------------------------------------------------------------------------*/ +/* Code Conversion Tables */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */ +static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ + 0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180, + 0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6, + 0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE, + 0x03A1, 0x83AF, 0x03A3, 0x83B0, 0x03A4, 0x83B1, 0x03A5, 0x83B2, 0x03A6, 0x83B3, 0x03A7, 0x83B4, 0x03A8, 0x83B5, 0x03A9, 0x83B6, + 0x03B1, 0x83BF, 0x03B2, 0x83C0, 0x03B3, 0x83C1, 0x03B4, 0x83C2, 0x03B5, 0x83C3, 0x03B6, 0x83C4, 0x03B7, 0x83C5, 0x03B8, 0x83C6, + 0x03B9, 0x83C7, 0x03BA, 0x83C8, 0x03BB, 0x83C9, 0x03BC, 0x83CA, 0x03BD, 0x83CB, 0x03BE, 0x83CC, 0x03BF, 0x83CD, 0x03C0, 0x83CE, + 0x03C1, 0x83CF, 0x03C3, 0x83D0, 0x03C4, 0x83D1, 0x03C5, 0x83D2, 0x03C6, 0x83D3, 0x03C7, 0x83D4, 0x03C8, 0x83D5, 0x03C9, 0x83D6, + 0x0401, 0x8446, 0x0410, 0x8440, 0x0411, 0x8441, 0x0412, 0x8442, 0x0413, 0x8443, 0x0414, 0x8444, 0x0415, 0x8445, 0x0416, 0x8447, + 0x0417, 0x8448, 0x0418, 0x8449, 0x0419, 0x844A, 0x041A, 0x844B, 0x041B, 0x844C, 0x041C, 0x844D, 0x041D, 0x844E, 0x041E, 0x844F, + 0x041F, 0x8450, 0x0420, 0x8451, 0x0421, 0x8452, 0x0422, 0x8453, 0x0423, 0x8454, 0x0424, 0x8455, 0x0425, 0x8456, 0x0426, 0x8457, + 0x0427, 0x8458, 0x0428, 0x8459, 0x0429, 0x845A, 0x042A, 0x845B, 0x042B, 0x845C, 0x042C, 0x845D, 0x042D, 0x845E, 0x042E, 0x845F, + 0x042F, 0x8460, 0x0430, 0x8470, 0x0431, 0x8471, 0x0432, 0x8472, 0x0433, 0x8473, 0x0434, 0x8474, 0x0435, 0x8475, 0x0436, 0x8477, + 0x0437, 0x8478, 0x0438, 0x8479, 0x0439, 0x847A, 0x043A, 0x847B, 0x043B, 0x847C, 0x043C, 0x847D, 0x043D, 0x847E, 0x043E, 0x8480, + 0x043F, 0x8481, 0x0440, 0x8482, 0x0441, 0x8483, 0x0442, 0x8484, 0x0443, 0x8485, 0x0444, 0x8486, 0x0445, 0x8487, 0x0446, 0x8488, + 0x0447, 0x8489, 0x0448, 0x848A, 0x0449, 0x848B, 0x044A, 0x848C, 0x044B, 0x848D, 0x044C, 0x848E, 0x044D, 0x848F, 0x044E, 0x8490, + 0x044F, 0x8491, 0x0451, 0x8476, 0x2010, 0x815D, 0x2015, 0x815C, 0x2018, 0x8165, 0x2019, 0x8166, 0x201C, 0x8167, 0x201D, 0x8168, + 0x2020, 0x81F5, 0x2021, 0x81F6, 0x2025, 0x8164, 0x2026, 0x8163, 0x2030, 0x81F1, 0x2032, 0x818C, 0x2033, 0x818D, 0x203B, 0x81A6, + 0x2103, 0x818E, 0x2116, 0x8782, 0x2121, 0x8784, 0x212B, 0x81F0, 0x2160, 0x8754, 0x2161, 0x8755, 0x2162, 0x8756, 0x2163, 0x8757, + 0x2164, 0x8758, 0x2165, 0x8759, 0x2166, 0x875A, 0x2167, 0x875B, 0x2168, 0x875C, 0x2169, 0x875D, 0x2170, 0xFA40, 0x2171, 0xFA41, + 0x2172, 0xFA42, 0x2173, 0xFA43, 0x2174, 0xFA44, 0x2175, 0xFA45, 0x2176, 0xFA46, 0x2177, 0xFA47, 0x2178, 0xFA48, 0x2179, 0xFA49, + 0x2190, 0x81A9, 0x2191, 0x81AA, 0x2192, 0x81A8, 0x2193, 0x81AB, 0x21D2, 0x81CB, 0x21D4, 0x81CC, 0x2200, 0x81CD, 0x2202, 0x81DD, + 0x2203, 0x81CE, 0x2207, 0x81DE, 0x2208, 0x81B8, 0x220B, 0x81B9, 0x2211, 0x8794, 0x221A, 0x81E3, 0x221D, 0x81E5, 0x221E, 0x8187, + 0x221F, 0x8798, 0x2220, 0x81DA, 0x2225, 0x8161, 0x2227, 0x81C8, 0x2228, 0x81C9, 0x2229, 0x81BF, 0x222A, 0x81BE, 0x222B, 0x81E7, + 0x222C, 0x81E8, 0x222E, 0x8793, 0x2234, 0x8188, 0x2235, 0x81E6, 0x223D, 0x81E4, 0x2252, 0x81E0, 0x2260, 0x8182, 0x2261, 0x81DF, + 0x2266, 0x8185, 0x2267, 0x8186, 0x226A, 0x81E1, 0x226B, 0x81E2, 0x2282, 0x81BC, 0x2283, 0x81BD, 0x2286, 0x81BA, 0x2287, 0x81BB, + 0x22A5, 0x81DB, 0x22BF, 0x8799, 0x2312, 0x81DC, 0x2460, 0x8740, 0x2461, 0x8741, 0x2462, 0x8742, 0x2463, 0x8743, 0x2464, 0x8744, + 0x2465, 0x8745, 0x2466, 0x8746, 0x2467, 0x8747, 0x2468, 0x8748, 0x2469, 0x8749, 0x246A, 0x874A, 0x246B, 0x874B, 0x246C, 0x874C, + 0x246D, 0x874D, 0x246E, 0x874E, 0x246F, 0x874F, 0x2470, 0x8750, 0x2471, 0x8751, 0x2472, 0x8752, 0x2473, 0x8753, 0x2500, 0x849F, + 0x2501, 0x84AA, 0x2502, 0x84A0, 0x2503, 0x84AB, 0x250C, 0x84A1, 0x250F, 0x84AC, 0x2510, 0x84A2, 0x2513, 0x84AD, 0x2514, 0x84A4, + 0x2517, 0x84AF, 0x2518, 0x84A3, 0x251B, 0x84AE, 0x251C, 0x84A5, 0x251D, 0x84BA, 0x2520, 0x84B5, 0x2523, 0x84B0, 0x2524, 0x84A7, + 0x2525, 0x84BC, 0x2528, 0x84B7, 0x252B, 0x84B2, 0x252C, 0x84A6, 0x252F, 0x84B6, 0x2530, 0x84BB, 0x2533, 0x84B1, 0x2534, 0x84A8, + 0x2537, 0x84B8, 0x2538, 0x84BD, 0x253B, 0x84B3, 0x253C, 0x84A9, 0x253F, 0x84B9, 0x2542, 0x84BE, 0x254B, 0x84B4, 0x25A0, 0x81A1, + 0x25A1, 0x81A0, 0x25B2, 0x81A3, 0x25B3, 0x81A2, 0x25BC, 0x81A5, 0x25BD, 0x81A4, 0x25C6, 0x819F, 0x25C7, 0x819E, 0x25CB, 0x819B, + 0x25CE, 0x819D, 0x25CF, 0x819C, 0x25EF, 0x81FC, 0x2605, 0x819A, 0x2606, 0x8199, 0x2640, 0x818A, 0x2642, 0x8189, 0x266A, 0x81F4, + 0x266D, 0x81F3, 0x266F, 0x81F2, 0x3000, 0x8140, 0x3001, 0x8141, 0x3002, 0x8142, 0x3003, 0x8156, 0x3005, 0x8158, 0x3006, 0x8159, + 0x3007, 0x815A, 0x3008, 0x8171, 0x3009, 0x8172, 0x300A, 0x8173, 0x300B, 0x8174, 0x300C, 0x8175, 0x300D, 0x8176, 0x300E, 0x8177, + 0x300F, 0x8178, 0x3010, 0x8179, 0x3011, 0x817A, 0x3012, 0x81A7, 0x3013, 0x81AC, 0x3014, 0x816B, 0x3015, 0x816C, 0x301D, 0x8780, + 0x301F, 0x8781, 0x3041, 0x829F, 0x3042, 0x82A0, 0x3043, 0x82A1, 0x3044, 0x82A2, 0x3045, 0x82A3, 0x3046, 0x82A4, 0x3047, 0x82A5, + 0x3048, 0x82A6, 0x3049, 0x82A7, 0x304A, 0x82A8, 0x304B, 0x82A9, 0x304C, 0x82AA, 0x304D, 0x82AB, 0x304E, 0x82AC, 0x304F, 0x82AD, + 0x3050, 0x82AE, 0x3051, 0x82AF, 0x3052, 0x82B0, 0x3053, 0x82B1, 0x3054, 0x82B2, 0x3055, 0x82B3, 0x3056, 0x82B4, 0x3057, 0x82B5, + 0x3058, 0x82B6, 0x3059, 0x82B7, 0x305A, 0x82B8, 0x305B, 0x82B9, 0x305C, 0x82BA, 0x305D, 0x82BB, 0x305E, 0x82BC, 0x305F, 0x82BD, + 0x3060, 0x82BE, 0x3061, 0x82BF, 0x3062, 0x82C0, 0x3063, 0x82C1, 0x3064, 0x82C2, 0x3065, 0x82C3, 0x3066, 0x82C4, 0x3067, 0x82C5, + 0x3068, 0x82C6, 0x3069, 0x82C7, 0x306A, 0x82C8, 0x306B, 0x82C9, 0x306C, 0x82CA, 0x306D, 0x82CB, 0x306E, 0x82CC, 0x306F, 0x82CD, + 0x3070, 0x82CE, 0x3071, 0x82CF, 0x3072, 0x82D0, 0x3073, 0x82D1, 0x3074, 0x82D2, 0x3075, 0x82D3, 0x3076, 0x82D4, 0x3077, 0x82D5, + 0x3078, 0x82D6, 0x3079, 0x82D7, 0x307A, 0x82D8, 0x307B, 0x82D9, 0x307C, 0x82DA, 0x307D, 0x82DB, 0x307E, 0x82DC, 0x307F, 0x82DD, + 0x3080, 0x82DE, 0x3081, 0x82DF, 0x3082, 0x82E0, 0x3083, 0x82E1, 0x3084, 0x82E2, 0x3085, 0x82E3, 0x3086, 0x82E4, 0x3087, 0x82E5, + 0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9, 0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED, + 0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, 0x309E, 0x8155, + 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342, 0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346, 0x30A8, 0x8347, + 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A, 0x30AC, 0x834B, 0x30AD, 0x834C, 0x30AE, 0x834D, 0x30AF, 0x834E, 0x30B0, 0x834F, + 0x30B1, 0x8350, 0x30B2, 0x8351, 0x30B3, 0x8352, 0x30B4, 0x8353, 0x30B5, 0x8354, 0x30B6, 0x8355, 0x30B7, 0x8356, 0x30B8, 0x8357, + 0x30B9, 0x8358, 0x30BA, 0x8359, 0x30BB, 0x835A, 0x30BC, 0x835B, 0x30BD, 0x835C, 0x30BE, 0x835D, 0x30BF, 0x835E, 0x30C0, 0x835F, + 0x30C1, 0x8360, 0x30C2, 0x8361, 0x30C3, 0x8362, 0x30C4, 0x8363, 0x30C5, 0x8364, 0x30C6, 0x8365, 0x30C7, 0x8366, 0x30C8, 0x8367, + 0x30C9, 0x8368, 0x30CA, 0x8369, 0x30CB, 0x836A, 0x30CC, 0x836B, 0x30CD, 0x836C, 0x30CE, 0x836D, 0x30CF, 0x836E, 0x30D0, 0x836F, + 0x30D1, 0x8370, 0x30D2, 0x8371, 0x30D3, 0x8372, 0x30D4, 0x8373, 0x30D5, 0x8374, 0x30D6, 0x8375, 0x30D7, 0x8376, 0x30D8, 0x8377, + 0x30D9, 0x8378, 0x30DA, 0x8379, 0x30DB, 0x837A, 0x30DC, 0x837B, 0x30DD, 0x837C, 0x30DE, 0x837D, 0x30DF, 0x837E, 0x30E0, 0x8380, + 0x30E1, 0x8381, 0x30E2, 0x8382, 0x30E3, 0x8383, 0x30E4, 0x8384, 0x30E5, 0x8385, 0x30E6, 0x8386, 0x30E7, 0x8387, 0x30E8, 0x8388, + 0x30E9, 0x8389, 0x30EA, 0x838A, 0x30EB, 0x838B, 0x30EC, 0x838C, 0x30ED, 0x838D, 0x30EE, 0x838E, 0x30EF, 0x838F, 0x30F0, 0x8390, + 0x30F1, 0x8391, 0x30F2, 0x8392, 0x30F3, 0x8393, 0x30F4, 0x8394, 0x30F5, 0x8395, 0x30F6, 0x8396, 0x30FB, 0x8145, 0x30FC, 0x815B, + 0x30FD, 0x8152, 0x30FE, 0x8153, 0x3231, 0x878A, 0x3232, 0x878B, 0x3239, 0x878C, 0x32A4, 0x8785, 0x32A5, 0x8786, 0x32A6, 0x8787, + 0x32A7, 0x8788, 0x32A8, 0x8789, 0x3303, 0x8765, 0x330D, 0x8769, 0x3314, 0x8760, 0x3318, 0x8763, 0x3322, 0x8761, 0x3323, 0x876B, + 0x3326, 0x876A, 0x3327, 0x8764, 0x332B, 0x876C, 0x3336, 0x8766, 0x333B, 0x876E, 0x3349, 0x875F, 0x334A, 0x876D, 0x334D, 0x8762, + 0x3351, 0x8767, 0x3357, 0x8768, 0x337B, 0x877E, 0x337C, 0x878F, 0x337D, 0x878E, 0x337E, 0x878D, 0x338E, 0x8772, 0x338F, 0x8773, + 0x339C, 0x876F, 0x339D, 0x8770, 0x339E, 0x8771, 0x33A1, 0x8775, 0x33C4, 0x8774, 0x33CD, 0x8783, 0x4E00, 0x88EA, 0x4E01, 0x929A, + 0x4E03, 0x8EB5, 0x4E07, 0x969C, 0x4E08, 0x8FE4, 0x4E09, 0x8E4F, 0x4E0A, 0x8FE3, 0x4E0B, 0x89BA, 0x4E0D, 0x9573, 0x4E0E, 0x975E, + 0x4E10, 0x98A0, 0x4E11, 0x894E, 0x4E14, 0x8A8E, 0x4E15, 0x98A1, 0x4E16, 0x90A2, 0x4E17, 0x99C0, 0x4E18, 0x8B75, 0x4E19, 0x95B8, + 0x4E1E, 0x8FE5, 0x4E21, 0x97BC, 0x4E26, 0x95C0, 0x4E28, 0xFA68, 0x4E2A, 0x98A2, 0x4E2D, 0x9286, 0x4E31, 0x98A3, 0x4E32, 0x8BF8, + 0x4E36, 0x98A4, 0x4E38, 0x8ADB, 0x4E39, 0x924F, 0x4E3B, 0x8EE5, 0x4E3C, 0x98A5, 0x4E3F, 0x98A6, 0x4E42, 0x98A7, 0x4E43, 0x9454, + 0x4E45, 0x8B76, 0x4E4B, 0x9456, 0x4E4D, 0x93E1, 0x4E4E, 0x8CC1, 0x4E4F, 0x9652, 0x4E55, 0xE568, 0x4E56, 0x98A8, 0x4E57, 0x8FE6, + 0x4E58, 0x98A9, 0x4E59, 0x89B3, 0x4E5D, 0x8BE3, 0x4E5E, 0x8CEE, 0x4E5F, 0x96E7, 0x4E62, 0x9BA4, 0x4E71, 0x9790, 0x4E73, 0x93FB, + 0x4E7E, 0x8AA3, 0x4E80, 0x8B54, 0x4E82, 0x98AA, 0x4E85, 0x98AB, 0x4E86, 0x97B9, 0x4E88, 0x975C, 0x4E89, 0x9188, 0x4E8A, 0x98AD, + 0x4E8B, 0x8E96, 0x4E8C, 0x93F1, 0x4E8E, 0x98B0, 0x4E91, 0x895D, 0x4E92, 0x8CDD, 0x4E94, 0x8CDC, 0x4E95, 0x88E4, 0x4E98, 0x986A, + 0x4E99, 0x9869, 0x4E9B, 0x8DB1, 0x4E9C, 0x889F, 0x4E9E, 0x98B1, 0x4E9F, 0x98B2, 0x4EA0, 0x98B3, 0x4EA1, 0x9653, 0x4EA2, 0x98B4, + 0x4EA4, 0x8CF0, 0x4EA5, 0x88E5, 0x4EA6, 0x9692, 0x4EA8, 0x8B9C, 0x4EAB, 0x8B9D, 0x4EAC, 0x8B9E, 0x4EAD, 0x92E0, 0x4EAE, 0x97BA, + 0x4EB0, 0x98B5, 0x4EB3, 0x98B6, 0x4EB6, 0x98B7, 0x4EBA, 0x906C, 0x4EC0, 0x8F59, 0x4EC1, 0x906D, 0x4EC2, 0x98BC, 0x4EC4, 0x98BA, + 0x4EC6, 0x98BB, 0x4EC7, 0x8B77, 0x4ECA, 0x8DA1, 0x4ECB, 0x89EE, 0x4ECD, 0x98B9, 0x4ECE, 0x98B8, 0x4ECF, 0x95A7, 0x4ED4, 0x8E65, + 0x4ED5, 0x8E64, 0x4ED6, 0x91BC, 0x4ED7, 0x98BD, 0x4ED8, 0x9574, 0x4ED9, 0x90E5, 0x4EDD, 0x8157, 0x4EDE, 0x98BE, 0x4EDF, 0x98C0, + 0x4EE1, 0xFA69, 0x4EE3, 0x91E3, 0x4EE4, 0x97DF, 0x4EE5, 0x88C8, 0x4EED, 0x98BF, 0x4EEE, 0x89BC, 0x4EF0, 0x8BC2, 0x4EF2, 0x9287, + 0x4EF6, 0x8C8F, 0x4EF7, 0x98C1, 0x4EFB, 0x9443, 0x4EFC, 0xFA6A, 0x4F00, 0xFA6B, 0x4F01, 0x8AE9, 0x4F03, 0xFA6C, 0x4F09, 0x98C2, + 0x4F0A, 0x88C9, 0x4F0D, 0x8CDE, 0x4F0E, 0x8AEA, 0x4F0F, 0x959A, 0x4F10, 0x94B0, 0x4F11, 0x8B78, 0x4F1A, 0x89EF, 0x4F1C, 0x98E5, + 0x4F1D, 0x9360, 0x4F2F, 0x948C, 0x4F30, 0x98C4, 0x4F34, 0x94BA, 0x4F36, 0x97E0, 0x4F38, 0x904C, 0x4F39, 0xFA6D, 0x4F3A, 0x8E66, + 0x4F3C, 0x8E97, 0x4F3D, 0x89BE, 0x4F43, 0x92CF, 0x4F46, 0x9241, 0x4F47, 0x98C8, 0x4F4D, 0x88CA, 0x4F4E, 0x92E1, 0x4F4F, 0x8F5A, + 0x4F50, 0x8DB2, 0x4F51, 0x9743, 0x4F53, 0x91CC, 0x4F55, 0x89BD, 0x4F56, 0xFA6E, 0x4F57, 0x98C7, 0x4F59, 0x975D, 0x4F5A, 0x98C3, + 0x4F5B, 0x98C5, 0x4F5C, 0x8DEC, 0x4F5D, 0x98C6, 0x4F5E, 0x9B43, 0x4F69, 0x98CE, 0x4F6F, 0x98D1, 0x4F70, 0x98CF, 0x4F73, 0x89C0, + 0x4F75, 0x95B9, 0x4F76, 0x98C9, 0x4F7B, 0x98CD, 0x4F7C, 0x8CF1, 0x4F7F, 0x8E67, 0x4F83, 0x8AA4, 0x4F86, 0x98D2, 0x4F88, 0x98CA, + 0x4F8A, 0xFA70, 0x4F8B, 0x97E1, 0x4F8D, 0x8E98, 0x4F8F, 0x98CB, 0x4F91, 0x98D0, 0x4F92, 0xFA6F, 0x4F94, 0xFA72, 0x4F96, 0x98D3, + 0x4F98, 0x98CC, 0x4F9A, 0xFA71, 0x4F9B, 0x8B9F, 0x4F9D, 0x88CB, 0x4FA0, 0x8BA0, 0x4FA1, 0x89BF, 0x4FAB, 0x9B44, 0x4FAD, 0x9699, + 0x4FAE, 0x958E, 0x4FAF, 0x8CF2, 0x4FB5, 0x904E, 0x4FB6, 0x97B5, 0x4FBF, 0x95D6, 0x4FC2, 0x8C57, 0x4FC3, 0x91A3, 0x4FC4, 0x89E2, + 0x4FC9, 0xFA61, 0x4FCA, 0x8F72, 0x4FCD, 0xFA73, 0x4FCE, 0x98D7, 0x4FD0, 0x98DC, 0x4FD1, 0x98DA, 0x4FD4, 0x98D5, 0x4FD7, 0x91AD, + 0x4FD8, 0x98D8, 0x4FDA, 0x98DB, 0x4FDB, 0x98D9, 0x4FDD, 0x95DB, 0x4FDF, 0x98D6, 0x4FE1, 0x904D, 0x4FE3, 0x9693, 0x4FE4, 0x98DD, + 0x4FE5, 0x98DE, 0x4FEE, 0x8F43, 0x4FEF, 0x98EB, 0x4FF3, 0x946F, 0x4FF5, 0x9555, 0x4FF6, 0x98E6, 0x4FF8, 0x95EE, 0x4FFA, 0x89B4, + 0x4FFE, 0x98EA, 0x4FFF, 0xFA76, 0x5005, 0x98E4, 0x5006, 0x98ED, 0x5009, 0x9171, 0x500B, 0x8CC2, 0x500D, 0x947B, 0x500F, 0xE0C5, + 0x5011, 0x98EC, 0x5012, 0x937C, 0x5014, 0x98E1, 0x5016, 0x8CF4, 0x5019, 0x8CF3, 0x501A, 0x98DF, 0x501E, 0xFA77, 0x501F, 0x8ED8, + 0x5021, 0x98E7, 0x5022, 0xFA75, 0x5023, 0x95ED, 0x5024, 0x926C, 0x5025, 0x98E3, 0x5026, 0x8C91, 0x5028, 0x98E0, 0x5029, 0x98E8, + 0x502A, 0x98E2, 0x502B, 0x97CF, 0x502C, 0x98E9, 0x502D, 0x9860, 0x5036, 0x8BE4, 0x5039, 0x8C90, 0x5040, 0xFA74, 0x5042, 0xFA7A, + 0x5043, 0x98EE, 0x5046, 0xFA78, 0x5047, 0x98EF, 0x5048, 0x98F3, 0x5049, 0x88CC, 0x504F, 0x95CE, 0x5050, 0x98F2, 0x5055, 0x98F1, + 0x5056, 0x98F5, 0x505A, 0x98F4, 0x505C, 0x92E2, 0x5065, 0x8C92, 0x506C, 0x98F6, 0x5070, 0xFA79, 0x5072, 0x8EC3, 0x5074, 0x91A4, + 0x5075, 0x92E3, 0x5076, 0x8BF4, 0x5078, 0x98F7, 0x507D, 0x8B55, 0x5080, 0x98F8, 0x5085, 0x98FA, 0x508D, 0x9654, 0x5091, 0x8C86, + 0x5094, 0xFA7B, 0x5098, 0x8E50, 0x5099, 0x94F5, 0x509A, 0x98F9, 0x50AC, 0x8DC3, 0x50AD, 0x9762, 0x50B2, 0x98FC, 0x50B3, 0x9942, + 0x50B4, 0x98FB, 0x50B5, 0x8DC2, 0x50B7, 0x8F9D, 0x50BE, 0x8C58, 0x50C2, 0x9943, 0x50C5, 0x8BCD, 0x50C9, 0x9940, 0x50CA, 0x9941, + 0x50CD, 0x93AD, 0x50CF, 0x919C, 0x50D1, 0x8BA1, 0x50D5, 0x966C, 0x50D6, 0x9944, 0x50D8, 0xFA7D, 0x50DA, 0x97BB, 0x50DE, 0x9945, + 0x50E3, 0x9948, 0x50E5, 0x9946, 0x50E7, 0x916D, 0x50ED, 0x9947, 0x50EE, 0x9949, 0x50F4, 0xFA7C, 0x50F5, 0x994B, 0x50F9, 0x994A, + 0x50FB, 0x95C6, 0x5100, 0x8B56, 0x5101, 0x994D, 0x5102, 0x994E, 0x5104, 0x89AD, 0x5109, 0x994C, 0x5112, 0x8EF2, 0x5114, 0x9951, + 0x5115, 0x9950, 0x5116, 0x994F, 0x5118, 0x98D4, 0x511A, 0x9952, 0x511F, 0x8F9E, 0x5121, 0x9953, 0x512A, 0x9744, 0x5132, 0x96D7, + 0x5137, 0x9955, 0x513A, 0x9954, 0x513B, 0x9957, 0x513C, 0x9956, 0x513F, 0x9958, 0x5140, 0x9959, 0x5141, 0x88F2, 0x5143, 0x8CB3, + 0x5144, 0x8C5A, 0x5145, 0x8F5B, 0x5146, 0x929B, 0x5147, 0x8BA2, 0x5148, 0x90E6, 0x5149, 0x8CF5, 0x514A, 0xFA7E, 0x514B, 0x8D8E, + 0x514C, 0x995B, 0x514D, 0x96C6, 0x514E, 0x9365, 0x5150, 0x8E99, 0x5152, 0x995A, 0x5154, 0x995C, 0x515A, 0x937D, 0x515C, 0x8A95, + 0x5162, 0x995D, 0x5164, 0xFA80, 0x5165, 0x93FC, 0x5168, 0x9153, 0x5169, 0x995F, 0x516A, 0x9960, 0x516B, 0x94AA, 0x516C, 0x8CF6, + 0x516D, 0x985A, 0x516E, 0x9961, 0x5171, 0x8BA4, 0x5175, 0x95BA, 0x5176, 0x91B4, 0x5177, 0x8BEF, 0x5178, 0x9354, 0x517C, 0x8C93, + 0x5180, 0x9962, 0x5182, 0x9963, 0x5185, 0x93E0, 0x5186, 0x897E, 0x5189, 0x9966, 0x518A, 0x8DFB, 0x518C, 0x9965, 0x518D, 0x8DC4, + 0x518F, 0x9967, 0x5190, 0xE3EC, 0x5191, 0x9968, 0x5192, 0x9660, 0x5193, 0x9969, 0x5195, 0x996A, 0x5196, 0x996B, 0x5197, 0x8FE7, + 0x5199, 0x8ECA, 0x519D, 0xFA81, 0x51A0, 0x8AA5, 0x51A2, 0x996E, 0x51A4, 0x996C, 0x51A5, 0x96BB, 0x51A6, 0x996D, 0x51A8, 0x9579, + 0x51A9, 0x996F, 0x51AA, 0x9970, 0x51AB, 0x9971, 0x51AC, 0x937E, 0x51B0, 0x9975, 0x51B1, 0x9973, 0x51B2, 0x9974, 0x51B3, 0x9972, + 0x51B4, 0x8DE1, 0x51B5, 0x9976, 0x51B6, 0x96E8, 0x51B7, 0x97E2, 0x51BD, 0x9977, 0x51BE, 0xFA82, 0x51C4, 0x90A6, 0x51C5, 0x9978, + 0x51C6, 0x8F79, 0x51C9, 0x9979, 0x51CB, 0x929C, 0x51CC, 0x97BD, 0x51CD, 0x9380, 0x51D6, 0x99C3, 0x51DB, 0x997A, 0x51DC, 0xEAA3, + 0x51DD, 0x8BC3, 0x51E0, 0x997B, 0x51E1, 0x967D, 0x51E6, 0x8F88, 0x51E7, 0x91FA, 0x51E9, 0x997D, 0x51EA, 0x93E2, 0x51EC, 0xFA83, + 0x51ED, 0x997E, 0x51F0, 0x9980, 0x51F1, 0x8A4D, 0x51F5, 0x9981, 0x51F6, 0x8BA5, 0x51F8, 0x93CA, 0x51F9, 0x899A, 0x51FA, 0x8F6F, + 0x51FD, 0x949F, 0x51FE, 0x9982, 0x5200, 0x9381, 0x5203, 0x906E, 0x5204, 0x9983, 0x5206, 0x95AA, 0x5207, 0x90D8, 0x5208, 0x8AA0, + 0x520A, 0x8AA7, 0x520B, 0x9984, 0x520E, 0x9986, 0x5211, 0x8C59, 0x5214, 0x9985, 0x5215, 0xFA84, 0x5217, 0x97F1, 0x521D, 0x8F89, + 0x5224, 0x94BB, 0x5225, 0x95CA, 0x5227, 0x9987, 0x5229, 0x9798, 0x522A, 0x9988, 0x522E, 0x9989, 0x5230, 0x939E, 0x5233, 0x998A, + 0x5236, 0x90A7, 0x5237, 0x8DFC, 0x5238, 0x8C94, 0x5239, 0x998B, 0x523A, 0x8E68, 0x523B, 0x8D8F, 0x5243, 0x92E4, 0x5244, 0x998D, + 0x5247, 0x91A5, 0x524A, 0x8DED, 0x524B, 0x998E, 0x524C, 0x998F, 0x524D, 0x914F, 0x524F, 0x998C, 0x5254, 0x9991, 0x5256, 0x9655, + 0x525B, 0x8D84, 0x525E, 0x9990, 0x5263, 0x8C95, 0x5264, 0x8DDC, 0x5265, 0x948D, 0x5269, 0x9994, 0x526A, 0x9992, 0x526F, 0x959B, + 0x5270, 0x8FE8, 0x5271, 0x999B, 0x5272, 0x8A84, 0x5273, 0x9995, 0x5274, 0x9993, 0x5275, 0x916E, 0x527D, 0x9997, 0x527F, 0x9996, + 0x5283, 0x8A63, 0x5287, 0x8C80, 0x5288, 0x999C, 0x5289, 0x97AB, 0x528D, 0x9998, 0x5291, 0x999D, 0x5292, 0x999A, 0x5294, 0x9999, + 0x529B, 0x97CD, 0x529C, 0xFA85, 0x529F, 0x8CF7, 0x52A0, 0x89C1, 0x52A3, 0x97F2, 0x52A6, 0xFA86, 0x52A9, 0x8F95, 0x52AA, 0x9377, + 0x52AB, 0x8D85, 0x52AC, 0x99A0, 0x52AD, 0x99A1, 0x52AF, 0xFB77, 0x52B1, 0x97E3, 0x52B4, 0x984A, 0x52B5, 0x99A3, 0x52B9, 0x8CF8, + 0x52BC, 0x99A2, 0x52BE, 0x8A4E, 0x52C0, 0xFA87, 0x52C1, 0x99A4, 0x52C3, 0x9675, 0x52C5, 0x92BA, 0x52C7, 0x9745, 0x52C9, 0x95D7, + 0x52CD, 0x99A5, 0x52D2, 0xE8D3, 0x52D5, 0x93AE, 0x52D7, 0x99A6, 0x52D8, 0x8AA8, 0x52D9, 0x96B1, 0x52DB, 0xFA88, 0x52DD, 0x8F9F, + 0x52DE, 0x99A7, 0x52DF, 0x95E5, 0x52E0, 0x99AB, 0x52E2, 0x90A8, 0x52E3, 0x99A8, 0x52E4, 0x8BCE, 0x52E6, 0x99A9, 0x52E7, 0x8AA9, + 0x52F2, 0x8C4D, 0x52F3, 0x99AC, 0x52F5, 0x99AD, 0x52F8, 0x99AE, 0x52F9, 0x99AF, 0x52FA, 0x8ED9, 0x52FE, 0x8CF9, 0x52FF, 0x96DC, + 0x5300, 0xFA89, 0x5301, 0x96E6, 0x5302, 0x93F5, 0x5305, 0x95EF, 0x5306, 0x99B0, 0x5307, 0xFA8A, 0x5308, 0x99B1, 0x530D, 0x99B3, + 0x530F, 0x99B5, 0x5310, 0x99B4, 0x5315, 0x99B6, 0x5316, 0x89BB, 0x5317, 0x966B, 0x5319, 0x8DFA, 0x531A, 0x99B7, 0x531D, 0x9178, + 0x5320, 0x8FA0, 0x5321, 0x8BA7, 0x5323, 0x99B8, 0x5324, 0xFA8B, 0x532A, 0x94D9, 0x532F, 0x99B9, 0x5331, 0x99BA, 0x5333, 0x99BB, + 0x5338, 0x99BC, 0x5339, 0x9543, 0x533A, 0x8BE6, 0x533B, 0x88E3, 0x533F, 0x93BD, 0x5340, 0x99BD, 0x5341, 0x8F5C, 0x5343, 0x90E7, + 0x5345, 0x99BF, 0x5346, 0x99BE, 0x5347, 0x8FA1, 0x5348, 0x8CDF, 0x5349, 0x99C1, 0x534A, 0x94BC, 0x534D, 0x99C2, 0x5351, 0x94DA, + 0x5352, 0x91B2, 0x5353, 0x91EC, 0x5354, 0x8BA6, 0x5357, 0x93EC, 0x5358, 0x9250, 0x535A, 0x948E, 0x535C, 0x966D, 0x535E, 0x99C4, + 0x5360, 0x90E8, 0x5366, 0x8C54, 0x5369, 0x99C5, 0x536E, 0x99C6, 0x536F, 0x894B, 0x5370, 0x88F3, 0x5371, 0x8AEB, 0x5372, 0xFA8C, + 0x5373, 0x91A6, 0x5374, 0x8B70, 0x5375, 0x9791, 0x5377, 0x99C9, 0x5378, 0x89B5, 0x537B, 0x99C8, 0x537F, 0x8BA8, 0x5382, 0x99CA, + 0x5384, 0x96EF, 0x5393, 0xFA8D, 0x5396, 0x99CB, 0x5398, 0x97D0, 0x539A, 0x8CFA, 0x539F, 0x8CB4, 0x53A0, 0x99CC, 0x53A5, 0x99CE, + 0x53A6, 0x99CD, 0x53A8, 0x907E, 0x53A9, 0x8958, 0x53AD, 0x897D, 0x53AE, 0x99CF, 0x53B0, 0x99D0, 0x53B2, 0xFA8E, 0x53B3, 0x8CB5, + 0x53B6, 0x99D1, 0x53BB, 0x8B8E, 0x53C2, 0x8E51, 0x53C3, 0x99D2, 0x53C8, 0x9694, 0x53C9, 0x8DB3, 0x53CA, 0x8B79, 0x53CB, 0x9746, + 0x53CC, 0x916F, 0x53CD, 0x94BD, 0x53CE, 0x8EFB, 0x53D4, 0x8F66, 0x53D6, 0x8EE6, 0x53D7, 0x8EF3, 0x53D9, 0x8F96, 0x53DB, 0x94BE, + 0x53DD, 0xFA8F, 0x53DF, 0x99D5, 0x53E1, 0x8962, 0x53E2, 0x9170, 0x53E3, 0x8CFB, 0x53E4, 0x8CC3, 0x53E5, 0x8BE5, 0x53E8, 0x99D9, + 0x53E9, 0x9240, 0x53EA, 0x91FC, 0x53EB, 0x8BA9, 0x53EC, 0x8FA2, 0x53ED, 0x99DA, 0x53EE, 0x99D8, 0x53EF, 0x89C2, 0x53F0, 0x91E4, + 0x53F1, 0x8EB6, 0x53F2, 0x8E6A, 0x53F3, 0x8945, 0x53F6, 0x8A90, 0x53F7, 0x8D86, 0x53F8, 0x8E69, 0x53FA, 0x99DB, 0x5401, 0x99DC, + 0x5403, 0x8B68, 0x5404, 0x8A65, 0x5408, 0x8D87, 0x5409, 0x8B67, 0x540A, 0x92DD, 0x540B, 0x8944, 0x540C, 0x93AF, 0x540D, 0x96BC, + 0x540E, 0x8D40, 0x540F, 0x9799, 0x5410, 0x9366, 0x5411, 0x8CFC, 0x541B, 0x8C4E, 0x541D, 0x99E5, 0x541F, 0x8BE1, 0x5420, 0x9669, + 0x5426, 0x94DB, 0x5429, 0x99E4, 0x542B, 0x8ADC, 0x542C, 0x99DF, 0x542D, 0x99E0, 0x542E, 0x99E2, 0x5436, 0x99E3, 0x5438, 0x8B7A, + 0x5439, 0x9081, 0x543B, 0x95AB, 0x543C, 0x99E1, 0x543D, 0x99DD, 0x543E, 0x8CE1, 0x5440, 0x99DE, 0x5442, 0x9843, 0x5446, 0x95F0, + 0x5448, 0x92E6, 0x5449, 0x8CE0, 0x544A, 0x8D90, 0x544E, 0x99E6, 0x5451, 0x93DB, 0x545F, 0x99EA, 0x5468, 0x8EFC, 0x546A, 0x8EF4, + 0x5470, 0x99ED, 0x5471, 0x99EB, 0x5473, 0x96A1, 0x5475, 0x99E8, 0x5476, 0x99F1, 0x5477, 0x99EC, 0x547B, 0x99EF, 0x547C, 0x8CC4, + 0x547D, 0x96BD, 0x5480, 0x99F0, 0x5484, 0x99F2, 0x5486, 0x99F4, 0x548A, 0xFA92, 0x548B, 0x8DEE, 0x548C, 0x9861, 0x548E, 0x99E9, + 0x548F, 0x99E7, 0x5490, 0x99F3, 0x5492, 0x99EE, 0x549C, 0xFA91, 0x54A2, 0x99F6, 0x54A4, 0x9A42, 0x54A5, 0x99F8, 0x54A8, 0x99FC, + 0x54A9, 0xFA93, 0x54AB, 0x9A40, 0x54AC, 0x99F9, 0x54AF, 0x9A5D, 0x54B2, 0x8DE7, 0x54B3, 0x8A50, 0x54B8, 0x99F7, 0x54BC, 0x9A44, + 0x54BD, 0x88F4, 0x54BE, 0x9A43, 0x54C0, 0x88A3, 0x54C1, 0x9569, 0x54C2, 0x9A41, 0x54C4, 0x99FA, 0x54C7, 0x99F5, 0x54C8, 0x99FB, + 0x54C9, 0x8DC6, 0x54D8, 0x9A45, 0x54E1, 0x88F5, 0x54E2, 0x9A4E, 0x54E5, 0x9A46, 0x54E6, 0x9A47, 0x54E8, 0x8FA3, 0x54E9, 0x9689, + 0x54ED, 0x9A4C, 0x54EE, 0x9A4B, 0x54F2, 0x934E, 0x54FA, 0x9A4D, 0x54FD, 0x9A4A, 0x54FF, 0xFA94, 0x5504, 0x8953, 0x5506, 0x8DB4, + 0x5507, 0x904F, 0x550F, 0x9A48, 0x5510, 0x9382, 0x5514, 0x9A49, 0x5516, 0x88A0, 0x552E, 0x9A53, 0x552F, 0x9742, 0x5531, 0x8FA5, + 0x5533, 0x9A59, 0x5538, 0x9A58, 0x5539, 0x9A4F, 0x553E, 0x91C1, 0x5540, 0x9A50, 0x5544, 0x91ED, 0x5545, 0x9A55, 0x5546, 0x8FA4, + 0x554C, 0x9A52, 0x554F, 0x96E2, 0x5553, 0x8C5B, 0x5556, 0x9A56, 0x5557, 0x9A57, 0x555C, 0x9A54, 0x555D, 0x9A5A, 0x5563, 0x9A51, + 0x557B, 0x9A60, 0x557C, 0x9A65, 0x557E, 0x9A61, 0x5580, 0x9A5C, 0x5583, 0x9A66, 0x5584, 0x9150, 0x5586, 0xFA95, 0x5587, 0x9A68, + 0x5589, 0x8D41, 0x558A, 0x9A5E, 0x558B, 0x929D, 0x5598, 0x9A62, 0x5599, 0x9A5B, 0x559A, 0x8AAB, 0x559C, 0x8AEC, 0x559D, 0x8A85, + 0x559E, 0x9A63, 0x559F, 0x9A5F, 0x55A7, 0x8C96, 0x55A8, 0x9A69, 0x55A9, 0x9A67, 0x55AA, 0x9172, 0x55AB, 0x8B69, 0x55AC, 0x8BAA, + 0x55AE, 0x9A64, 0x55B0, 0x8BF2, 0x55B6, 0x8963, 0x55C4, 0x9A6D, 0x55C5, 0x9A6B, 0x55C7, 0x9AA5, 0x55D4, 0x9A70, 0x55DA, 0x9A6A, + 0x55DC, 0x9A6E, 0x55DF, 0x9A6C, 0x55E3, 0x8E6B, 0x55E4, 0x9A6F, 0x55F7, 0x9A72, 0x55F9, 0x9A77, 0x55FD, 0x9A75, 0x55FE, 0x9A74, + 0x5606, 0x9251, 0x5609, 0x89C3, 0x5614, 0x9A71, 0x5616, 0x9A73, 0x5617, 0x8FA6, 0x5618, 0x8952, 0x561B, 0x9A76, 0x5629, 0x89DC, + 0x562F, 0x9A82, 0x5631, 0x8FFA, 0x5632, 0x9A7D, 0x5634, 0x9A7B, 0x5636, 0x9A7C, 0x5638, 0x9A7E, 0x5642, 0x895C, 0x564C, 0x9158, + 0x564E, 0x9A78, 0x5650, 0x9A79, 0x565B, 0x8A9A, 0x5664, 0x9A81, 0x5668, 0x8AED, 0x566A, 0x9A84, 0x566B, 0x9A80, 0x566C, 0x9A83, + 0x5674, 0x95AC, 0x5678, 0x93D3, 0x567A, 0x94B6, 0x5680, 0x9A86, 0x5686, 0x9A85, 0x5687, 0x8A64, 0x568A, 0x9A87, 0x568F, 0x9A8A, + 0x5694, 0x9A89, 0x56A0, 0x9A88, 0x56A2, 0x9458, 0x56A5, 0x9A8B, 0x56AE, 0x9A8C, 0x56B4, 0x9A8E, 0x56B6, 0x9A8D, 0x56BC, 0x9A90, + 0x56C0, 0x9A93, 0x56C1, 0x9A91, 0x56C2, 0x9A8F, 0x56C3, 0x9A92, 0x56C8, 0x9A94, 0x56CE, 0x9A95, 0x56D1, 0x9A96, 0x56D3, 0x9A97, + 0x56D7, 0x9A98, 0x56D8, 0x9964, 0x56DA, 0x8EFA, 0x56DB, 0x8E6C, 0x56DE, 0x89F1, 0x56E0, 0x88F6, 0x56E3, 0x9263, 0x56EE, 0x9A99, + 0x56F0, 0x8DA2, 0x56F2, 0x88CD, 0x56F3, 0x907D, 0x56F9, 0x9A9A, 0x56FA, 0x8CC5, 0x56FD, 0x8D91, 0x56FF, 0x9A9C, 0x5700, 0x9A9B, + 0x5703, 0x95DE, 0x5704, 0x9A9D, 0x5708, 0x9A9F, 0x5709, 0x9A9E, 0x570B, 0x9AA0, 0x570D, 0x9AA1, 0x570F, 0x8C97, 0x5712, 0x8980, + 0x5713, 0x9AA2, 0x5716, 0x9AA4, 0x5718, 0x9AA3, 0x571C, 0x9AA6, 0x571F, 0x9379, 0x5726, 0x9AA7, 0x5727, 0x88B3, 0x5728, 0x8DDD, + 0x572D, 0x8C5C, 0x5730, 0x926E, 0x5737, 0x9AA8, 0x5738, 0x9AA9, 0x573B, 0x9AAB, 0x5740, 0x9AAC, 0x5742, 0x8DE2, 0x5747, 0x8BCF, + 0x574A, 0x9656, 0x574E, 0x9AAA, 0x574F, 0x9AAD, 0x5750, 0x8DBF, 0x5751, 0x8D42, 0x5759, 0xFA96, 0x5761, 0x9AB1, 0x5764, 0x8DA3, + 0x5765, 0xFA97, 0x5766, 0x9252, 0x5769, 0x9AAE, 0x576A, 0x92D8, 0x577F, 0x9AB2, 0x5782, 0x9082, 0x5788, 0x9AB0, 0x5789, 0x9AB3, + 0x578B, 0x8C5E, 0x5793, 0x9AB4, 0x57A0, 0x9AB5, 0x57A2, 0x8D43, 0x57A3, 0x8A5F, 0x57A4, 0x9AB7, 0x57AA, 0x9AB8, 0x57AC, 0xFA98, + 0x57B0, 0x9AB9, 0x57B3, 0x9AB6, 0x57C0, 0x9AAF, 0x57C3, 0x9ABA, 0x57C6, 0x9ABB, 0x57C7, 0xFA9A, 0x57C8, 0xFA99, 0x57CB, 0x9684, + 0x57CE, 0x8FE9, 0x57D2, 0x9ABD, 0x57D3, 0x9ABE, 0x57D4, 0x9ABC, 0x57D6, 0x9AC0, 0x57DC, 0x9457, 0x57DF, 0x88E6, 0x57E0, 0x9575, + 0x57E3, 0x9AC1, 0x57F4, 0x8FFB, 0x57F7, 0x8EB7, 0x57F9, 0x947C, 0x57FA, 0x8AEE, 0x57FC, 0x8DE9, 0x5800, 0x9678, 0x5802, 0x93B0, + 0x5805, 0x8C98, 0x5806, 0x91CD, 0x580A, 0x9ABF, 0x580B, 0x9AC2, 0x5815, 0x91C2, 0x5819, 0x9AC3, 0x581D, 0x9AC4, 0x5821, 0x9AC6, + 0x5824, 0x92E7, 0x582A, 0x8AAC, 0x582F, 0xEA9F, 0x5830, 0x8981, 0x5831, 0x95F1, 0x5834, 0x8FEA, 0x5835, 0x9367, 0x583A, 0x8DE4, + 0x583D, 0x9ACC, 0x5840, 0x95BB, 0x5841, 0x97DB, 0x584A, 0x89F2, 0x584B, 0x9AC8, 0x5851, 0x9159, 0x5852, 0x9ACB, 0x5854, 0x9383, + 0x5857, 0x9368, 0x5858, 0x9384, 0x5859, 0x94B7, 0x585A, 0x92CB, 0x585E, 0x8DC7, 0x5862, 0x9AC7, 0x5869, 0x8996, 0x586B, 0x9355, + 0x5870, 0x9AC9, 0x5872, 0x9AC5, 0x5875, 0x906F, 0x5879, 0x9ACD, 0x587E, 0x8F6D, 0x5883, 0x8BAB, 0x5885, 0x9ACE, 0x5893, 0x95E6, + 0x5897, 0x919D, 0x589C, 0x92C4, 0x589E, 0xFA9D, 0x589F, 0x9AD0, 0x58A8, 0x966E, 0x58AB, 0x9AD1, 0x58AE, 0x9AD6, 0x58B2, 0xFA9E, + 0x58B3, 0x95AD, 0x58B8, 0x9AD5, 0x58B9, 0x9ACF, 0x58BA, 0x9AD2, 0x58BB, 0x9AD4, 0x58BE, 0x8DA4, 0x58C1, 0x95C7, 0x58C5, 0x9AD7, + 0x58C7, 0x9264, 0x58CA, 0x89F3, 0x58CC, 0x8FEB, 0x58D1, 0x9AD9, 0x58D3, 0x9AD8, 0x58D5, 0x8D88, 0x58D7, 0x9ADA, 0x58D8, 0x9ADC, + 0x58D9, 0x9ADB, 0x58DC, 0x9ADE, 0x58DE, 0x9AD3, 0x58DF, 0x9AE0, 0x58E4, 0x9ADF, 0x58E5, 0x9ADD, 0x58EB, 0x8E6D, 0x58EC, 0x9070, + 0x58EE, 0x9173, 0x58EF, 0x9AE1, 0x58F0, 0x90BA, 0x58F1, 0x88EB, 0x58F2, 0x9484, 0x58F7, 0x92D9, 0x58F9, 0x9AE3, 0x58FA, 0x9AE2, + 0x58FB, 0x9AE4, 0x58FC, 0x9AE5, 0x58FD, 0x9AE6, 0x5902, 0x9AE7, 0x5909, 0x95CF, 0x590A, 0x9AE8, 0x590B, 0xFA9F, 0x590F, 0x89C4, + 0x5910, 0x9AE9, 0x5915, 0x975B, 0x5916, 0x8A4F, 0x5918, 0x99C7, 0x5919, 0x8F67, 0x591A, 0x91BD, 0x591B, 0x9AEA, 0x591C, 0x96E9, + 0x5922, 0x96B2, 0x5925, 0x9AEC, 0x5927, 0x91E5, 0x5929, 0x9356, 0x592A, 0x91BE, 0x592B, 0x9576, 0x592C, 0x9AED, 0x592D, 0x9AEE, + 0x592E, 0x899B, 0x5931, 0x8EB8, 0x5932, 0x9AEF, 0x5937, 0x88CE, 0x5938, 0x9AF0, 0x593E, 0x9AF1, 0x5944, 0x8982, 0x5947, 0x8AEF, + 0x5948, 0x93DE, 0x5949, 0x95F2, 0x594E, 0x9AF5, 0x594F, 0x9174, 0x5950, 0x9AF4, 0x5951, 0x8C5F, 0x5953, 0xFAA0, 0x5954, 0x967A, + 0x5955, 0x9AF3, 0x5957, 0x9385, 0x5958, 0x9AF7, 0x595A, 0x9AF6, 0x595B, 0xFAA1, 0x595D, 0xFAA2, 0x5960, 0x9AF9, 0x5962, 0x9AF8, + 0x5963, 0xFAA3, 0x5965, 0x899C, 0x5967, 0x9AFA, 0x5968, 0x8FA7, 0x5969, 0x9AFC, 0x596A, 0x9244, 0x596C, 0x9AFB, 0x596E, 0x95B1, + 0x5973, 0x8F97, 0x5974, 0x937A, 0x5978, 0x9B40, 0x597D, 0x8D44, 0x5981, 0x9B41, 0x5982, 0x9440, 0x5983, 0x94DC, 0x5984, 0x96CF, + 0x598A, 0x9444, 0x598D, 0x9B4A, 0x5993, 0x8B57, 0x5996, 0x9764, 0x5999, 0x96AD, 0x599B, 0x9BAA, 0x599D, 0x9B42, 0x59A3, 0x9B45, + 0x59A4, 0xFAA4, 0x59A5, 0x91C3, 0x59A8, 0x9657, 0x59AC, 0x9369, 0x59B2, 0x9B46, 0x59B9, 0x9685, 0x59BA, 0xFAA5, 0x59BB, 0x8DC8, + 0x59BE, 0x8FA8, 0x59C6, 0x9B47, 0x59C9, 0x8E6F, 0x59CB, 0x8E6E, 0x59D0, 0x88B7, 0x59D1, 0x8CC6, 0x59D3, 0x90A9, 0x59D4, 0x88CF, + 0x59D9, 0x9B4B, 0x59DA, 0x9B4C, 0x59DC, 0x9B49, 0x59E5, 0x8957, 0x59E6, 0x8AAD, 0x59E8, 0x9B48, 0x59EA, 0x96C3, 0x59EB, 0x9550, + 0x59F6, 0x88A6, 0x59FB, 0x88F7, 0x59FF, 0x8E70, 0x5A01, 0x88D0, 0x5A03, 0x88A1, 0x5A09, 0x9B51, 0x5A11, 0x9B4F, 0x5A18, 0x96BA, + 0x5A1A, 0x9B52, 0x5A1C, 0x9B50, 0x5A1F, 0x9B4E, 0x5A20, 0x9050, 0x5A25, 0x9B4D, 0x5A29, 0x95D8, 0x5A2F, 0x8CE2, 0x5A35, 0x9B56, + 0x5A36, 0x9B57, 0x5A3C, 0x8FA9, 0x5A40, 0x9B53, 0x5A41, 0x984B, 0x5A46, 0x946B, 0x5A49, 0x9B55, 0x5A5A, 0x8DA5, 0x5A62, 0x9B58, + 0x5A66, 0x9577, 0x5A6A, 0x9B59, 0x5A6C, 0x9B54, 0x5A7F, 0x96B9, 0x5A92, 0x947D, 0x5A9A, 0x9B5A, 0x5A9B, 0x9551, 0x5ABC, 0x9B5B, + 0x5ABD, 0x9B5F, 0x5ABE, 0x9B5C, 0x5AC1, 0x89C5, 0x5AC2, 0x9B5E, 0x5AC9, 0x8EB9, 0x5ACB, 0x9B5D, 0x5ACC, 0x8C99, 0x5AD0, 0x9B6B, + 0x5AD6, 0x9B64, 0x5AD7, 0x9B61, 0x5AE1, 0x9284, 0x5AE3, 0x9B60, 0x5AE6, 0x9B62, 0x5AE9, 0x9B63, 0x5AFA, 0x9B65, 0x5AFB, 0x9B66, + 0x5B09, 0x8AF0, 0x5B0B, 0x9B68, 0x5B0C, 0x9B67, 0x5B16, 0x9B69, 0x5B22, 0x8FEC, 0x5B2A, 0x9B6C, 0x5B2C, 0x92DA, 0x5B30, 0x8964, + 0x5B32, 0x9B6A, 0x5B36, 0x9B6D, 0x5B3E, 0x9B6E, 0x5B40, 0x9B71, 0x5B43, 0x9B6F, 0x5B45, 0x9B70, 0x5B50, 0x8E71, 0x5B51, 0x9B72, + 0x5B54, 0x8D45, 0x5B55, 0x9B73, 0x5B56, 0xFAA6, 0x5B57, 0x8E9A, 0x5B58, 0x91B6, 0x5B5A, 0x9B74, 0x5B5B, 0x9B75, 0x5B5C, 0x8E79, + 0x5B5D, 0x8D46, 0x5B5F, 0x96D0, 0x5B63, 0x8B47, 0x5B64, 0x8CC7, 0x5B65, 0x9B76, 0x5B66, 0x8A77, 0x5B69, 0x9B77, 0x5B6B, 0x91B7, + 0x5B70, 0x9B78, 0x5B71, 0x9BA1, 0x5B73, 0x9B79, 0x5B75, 0x9B7A, 0x5B78, 0x9B7B, 0x5B7A, 0x9B7D, 0x5B80, 0x9B7E, 0x5B83, 0x9B80, + 0x5B85, 0x91EE, 0x5B87, 0x8946, 0x5B88, 0x8EE7, 0x5B89, 0x88C0, 0x5B8B, 0x9176, 0x5B8C, 0x8AAE, 0x5B8D, 0x8EB3, 0x5B8F, 0x8D47, + 0x5B95, 0x9386, 0x5B97, 0x8F40, 0x5B98, 0x8AAF, 0x5B99, 0x9288, 0x5B9A, 0x92E8, 0x5B9B, 0x88B6, 0x5B9C, 0x8B58, 0x5B9D, 0x95F3, + 0x5B9F, 0x8EC0, 0x5BA2, 0x8B71, 0x5BA3, 0x90E9, 0x5BA4, 0x8EBA, 0x5BA5, 0x9747, 0x5BA6, 0x9B81, 0x5BAE, 0x8B7B, 0x5BB0, 0x8DC9, + 0x5BB3, 0x8A51, 0x5BB4, 0x8983, 0x5BB5, 0x8FAA, 0x5BB6, 0x89C6, 0x5BB8, 0x9B82, 0x5BB9, 0x9765, 0x5BBF, 0x8F68, 0x5BC0, 0xFAA7, + 0x5BC2, 0x8EE2, 0x5BC3, 0x9B83, 0x5BC4, 0x8AF1, 0x5BC5, 0x93D0, 0x5BC6, 0x96A7, 0x5BC7, 0x9B84, 0x5BC9, 0x9B85, 0x5BCC, 0x9578, + 0x5BD0, 0x9B87, 0x5BD2, 0x8AA6, 0x5BD3, 0x8BF5, 0x5BD4, 0x9B86, 0x5BD8, 0xFAA9, 0x5BDB, 0x8AB0, 0x5BDD, 0x9051, 0x5BDE, 0x9B8B, + 0x5BDF, 0x8E40, 0x5BE1, 0x89C7, 0x5BE2, 0x9B8A, 0x5BE4, 0x9B88, 0x5BE5, 0x9B8C, 0x5BE6, 0x9B89, 0x5BE7, 0x944A, 0x5BE8, 0x9ECB, + 0x5BE9, 0x9052, 0x5BEB, 0x9B8D, 0x5BEC, 0xFAAA, 0x5BEE, 0x97BE, 0x5BF0, 0x9B8E, 0x5BF3, 0x9B90, 0x5BF5, 0x929E, 0x5BF6, 0x9B8F, + 0x5BF8, 0x90A1, 0x5BFA, 0x8E9B, 0x5BFE, 0x91CE, 0x5BFF, 0x8EF5, 0x5C01, 0x9595, 0x5C02, 0x90EA, 0x5C04, 0x8ECB, 0x5C05, 0x9B91, + 0x5C06, 0x8FAB, 0x5C07, 0x9B92, 0x5C08, 0x9B93, 0x5C09, 0x88D1, 0x5C0A, 0x91B8, 0x5C0B, 0x9071, 0x5C0D, 0x9B94, 0x5C0E, 0x93B1, + 0x5C0F, 0x8FAC, 0x5C11, 0x8FAD, 0x5C13, 0x9B95, 0x5C16, 0x90EB, 0x5C1A, 0x8FAE, 0x5C1E, 0xFAAB, 0x5C20, 0x9B96, 0x5C22, 0x9B97, + 0x5C24, 0x96DE, 0x5C28, 0x9B98, 0x5C2D, 0x8BC4, 0x5C31, 0x8F41, 0x5C38, 0x9B99, 0x5C39, 0x9B9A, 0x5C3A, 0x8EDA, 0x5C3B, 0x904B, + 0x5C3C, 0x93F2, 0x5C3D, 0x9073, 0x5C3E, 0x94F6, 0x5C3F, 0x9441, 0x5C40, 0x8BC7, 0x5C41, 0x9B9B, 0x5C45, 0x8B8F, 0x5C46, 0x9B9C, + 0x5C48, 0x8BFC, 0x5C4A, 0x93CD, 0x5C4B, 0x89AE, 0x5C4D, 0x8E72, 0x5C4E, 0x9B9D, 0x5C4F, 0x9BA0, 0x5C50, 0x9B9F, 0x5C51, 0x8BFB, + 0x5C53, 0x9B9E, 0x5C55, 0x9357, 0x5C5E, 0x91AE, 0x5C60, 0x936A, 0x5C61, 0x8EC6, 0x5C64, 0x9177, 0x5C65, 0x979A, 0x5C6C, 0x9BA2, + 0x5C6E, 0x9BA3, 0x5C6F, 0x93D4, 0x5C71, 0x8E52, 0x5C76, 0x9BA5, 0x5C79, 0x9BA6, 0x5C8C, 0x9BA7, 0x5C90, 0x8AF2, 0x5C91, 0x9BA8, + 0x5C94, 0x9BA9, 0x5CA1, 0x89AA, 0x5CA6, 0xFAAC, 0x5CA8, 0x915A, 0x5CA9, 0x8AE2, 0x5CAB, 0x9BAB, 0x5CAC, 0x96A6, 0x5CB1, 0x91D0, + 0x5CB3, 0x8A78, 0x5CB6, 0x9BAD, 0x5CB7, 0x9BAF, 0x5CB8, 0x8ADD, 0x5CBA, 0xFAAD, 0x5CBB, 0x9BAC, 0x5CBC, 0x9BAE, 0x5CBE, 0x9BB1, + 0x5CC5, 0x9BB0, 0x5CC7, 0x9BB2, 0x5CD9, 0x9BB3, 0x5CE0, 0x93BB, 0x5CE1, 0x8BAC, 0x5CE8, 0x89E3, 0x5CE9, 0x9BB4, 0x5CEA, 0x9BB9, + 0x5CED, 0x9BB7, 0x5CEF, 0x95F5, 0x5CF0, 0x95F4, 0x5CF5, 0xFAAE, 0x5CF6, 0x9387, 0x5CFA, 0x9BB6, 0x5CFB, 0x8F73, 0x5CFD, 0x9BB5, + 0x5D07, 0x9092, 0x5D0B, 0x9BBA, 0x5D0E, 0x8DE8, 0x5D11, 0x9BC0, 0x5D14, 0x9BC1, 0x5D15, 0x9BBB, 0x5D16, 0x8A52, 0x5D17, 0x9BBC, + 0x5D18, 0x9BC5, 0x5D19, 0x9BC4, 0x5D1A, 0x9BC3, 0x5D1B, 0x9BBF, 0x5D1F, 0x9BBE, 0x5D22, 0x9BC2, 0x5D27, 0xFAAF, 0x5D29, 0x95F6, + 0x5D42, 0xFAB2, 0x5D4B, 0x9BC9, 0x5D4C, 0x9BC6, 0x5D4E, 0x9BC8, 0x5D50, 0x9792, 0x5D52, 0x9BC7, 0x5D53, 0xFAB0, 0x5D5C, 0x9BBD, + 0x5D69, 0x9093, 0x5D6C, 0x9BCA, 0x5D6D, 0xFAB3, 0x5D6F, 0x8DB5, 0x5D73, 0x9BCB, 0x5D76, 0x9BCC, 0x5D82, 0x9BCF, 0x5D84, 0x9BCE, + 0x5D87, 0x9BCD, 0x5D8B, 0x9388, 0x5D8C, 0x9BB8, 0x5D90, 0x9BD5, 0x5D9D, 0x9BD1, 0x5DA2, 0x9BD0, 0x5DAC, 0x9BD2, 0x5DAE, 0x9BD3, + 0x5DB7, 0x9BD6, 0x5DB8, 0xFAB4, 0x5DB9, 0xFAB5, 0x5DBA, 0x97E4, 0x5DBC, 0x9BD7, 0x5DBD, 0x9BD4, 0x5DC9, 0x9BD8, 0x5DCC, 0x8ADE, + 0x5DCD, 0x9BD9, 0x5DD0, 0xFAB6, 0x5DD2, 0x9BDB, 0x5DD3, 0x9BDA, 0x5DD6, 0x9BDC, 0x5DDB, 0x9BDD, 0x5DDD, 0x90EC, 0x5DDE, 0x8F42, + 0x5DE1, 0x8F84, 0x5DE3, 0x9183, 0x5DE5, 0x8D48, 0x5DE6, 0x8DB6, 0x5DE7, 0x8D49, 0x5DE8, 0x8B90, 0x5DEB, 0x9BDE, 0x5DEE, 0x8DB7, + 0x5DF1, 0x8CC8, 0x5DF2, 0x9BDF, 0x5DF3, 0x96A4, 0x5DF4, 0x9462, 0x5DF5, 0x9BE0, 0x5DF7, 0x8D4A, 0x5DFB, 0x8AAA, 0x5DFD, 0x9246, + 0x5DFE, 0x8BD0, 0x5E02, 0x8E73, 0x5E03, 0x957A, 0x5E06, 0x94BF, 0x5E0B, 0x9BE1, 0x5E0C, 0x8AF3, 0x5E11, 0x9BE4, 0x5E16, 0x929F, + 0x5E19, 0x9BE3, 0x5E1A, 0x9BE2, 0x5E1B, 0x9BE5, 0x5E1D, 0x92E9, 0x5E25, 0x9083, 0x5E2B, 0x8E74, 0x5E2D, 0x90C8, 0x5E2F, 0x91D1, + 0x5E30, 0x8B41, 0x5E33, 0x92A0, 0x5E36, 0x9BE6, 0x5E37, 0x9BE7, 0x5E38, 0x8FED, 0x5E3D, 0x9658, 0x5E40, 0x9BEA, 0x5E43, 0x9BE9, + 0x5E44, 0x9BE8, 0x5E45, 0x959D, 0x5E47, 0x9BF1, 0x5E4C, 0x9679, 0x5E4E, 0x9BEB, 0x5E54, 0x9BED, 0x5E55, 0x968B, 0x5E57, 0x9BEC, + 0x5E5F, 0x9BEE, 0x5E61, 0x94A6, 0x5E62, 0x9BEF, 0x5E63, 0x95BC, 0x5E64, 0x9BF0, 0x5E72, 0x8AB1, 0x5E73, 0x95BD, 0x5E74, 0x944E, + 0x5E75, 0x9BF2, 0x5E76, 0x9BF3, 0x5E78, 0x8D4B, 0x5E79, 0x8AB2, 0x5E7A, 0x9BF4, 0x5E7B, 0x8CB6, 0x5E7C, 0x9763, 0x5E7D, 0x9748, + 0x5E7E, 0x8AF4, 0x5E7F, 0x9BF6, 0x5E81, 0x92A1, 0x5E83, 0x8D4C, 0x5E84, 0x8FAF, 0x5E87, 0x94DD, 0x5E8A, 0x8FB0, 0x5E8F, 0x8F98, + 0x5E95, 0x92EA, 0x5E96, 0x95F7, 0x5E97, 0x9358, 0x5E9A, 0x8D4D, 0x5E9C, 0x957B, 0x5EA0, 0x9BF7, 0x5EA6, 0x9378, 0x5EA7, 0x8DC0, + 0x5EAB, 0x8CC9, 0x5EAD, 0x92EB, 0x5EB5, 0x88C1, 0x5EB6, 0x8F8E, 0x5EB7, 0x8D4E, 0x5EB8, 0x9766, 0x5EC1, 0x9BF8, 0x5EC2, 0x9BF9, + 0x5EC3, 0x9470, 0x5EC8, 0x9BFA, 0x5EC9, 0x97F5, 0x5ECA, 0x984C, 0x5ECF, 0x9BFC, 0x5ED0, 0x9BFB, 0x5ED3, 0x8A66, 0x5ED6, 0x9C40, + 0x5EDA, 0x9C43, 0x5EDB, 0x9C44, 0x5EDD, 0x9C42, 0x5EDF, 0x955F, 0x5EE0, 0x8FB1, 0x5EE1, 0x9C46, 0x5EE2, 0x9C45, 0x5EE3, 0x9C41, + 0x5EE8, 0x9C47, 0x5EE9, 0x9C48, 0x5EEC, 0x9C49, 0x5EF0, 0x9C4C, 0x5EF1, 0x9C4A, 0x5EF3, 0x9C4B, 0x5EF4, 0x9C4D, 0x5EF6, 0x8984, + 0x5EF7, 0x92EC, 0x5EF8, 0x9C4E, 0x5EFA, 0x8C9A, 0x5EFB, 0x89F4, 0x5EFC, 0x9455, 0x5EFE, 0x9C4F, 0x5EFF, 0x93F9, 0x5F01, 0x95D9, + 0x5F03, 0x9C50, 0x5F04, 0x984D, 0x5F09, 0x9C51, 0x5F0A, 0x95BE, 0x5F0B, 0x9C54, 0x5F0C, 0x989F, 0x5F0D, 0x98AF, 0x5F0F, 0x8EAE, + 0x5F10, 0x93F3, 0x5F11, 0x9C55, 0x5F13, 0x8B7C, 0x5F14, 0x92A2, 0x5F15, 0x88F8, 0x5F16, 0x9C56, 0x5F17, 0x95A4, 0x5F18, 0x8D4F, + 0x5F1B, 0x926F, 0x5F1F, 0x92ED, 0x5F21, 0xFAB7, 0x5F25, 0x96ED, 0x5F26, 0x8CB7, 0x5F27, 0x8CCA, 0x5F29, 0x9C57, 0x5F2D, 0x9C58, + 0x5F2F, 0x9C5E, 0x5F31, 0x8EE3, 0x5F34, 0xFAB8, 0x5F35, 0x92A3, 0x5F37, 0x8BAD, 0x5F38, 0x9C59, 0x5F3C, 0x954A, 0x5F3E, 0x9265, + 0x5F41, 0x9C5A, 0x5F45, 0xFA67, 0x5F48, 0x9C5B, 0x5F4A, 0x8BAE, 0x5F4C, 0x9C5C, 0x5F4E, 0x9C5D, 0x5F51, 0x9C5F, 0x5F53, 0x9396, + 0x5F56, 0x9C60, 0x5F57, 0x9C61, 0x5F59, 0x9C62, 0x5F5C, 0x9C53, 0x5F5D, 0x9C52, 0x5F61, 0x9C63, 0x5F62, 0x8C60, 0x5F66, 0x9546, + 0x5F67, 0xFAB9, 0x5F69, 0x8DCA, 0x5F6A, 0x9556, 0x5F6B, 0x92A4, 0x5F6C, 0x956A, 0x5F6D, 0x9C64, 0x5F70, 0x8FB2, 0x5F71, 0x8965, + 0x5F73, 0x9C65, 0x5F77, 0x9C66, 0x5F79, 0x96F0, 0x5F7C, 0x94DE, 0x5F7F, 0x9C69, 0x5F80, 0x899D, 0x5F81, 0x90AA, 0x5F82, 0x9C68, + 0x5F83, 0x9C67, 0x5F84, 0x8C61, 0x5F85, 0x91D2, 0x5F87, 0x9C6D, 0x5F88, 0x9C6B, 0x5F8A, 0x9C6A, 0x5F8B, 0x97A5, 0x5F8C, 0x8CE3, + 0x5F90, 0x8F99, 0x5F91, 0x9C6C, 0x5F92, 0x936B, 0x5F93, 0x8F5D, 0x5F97, 0x93BE, 0x5F98, 0x9C70, 0x5F99, 0x9C6F, 0x5F9E, 0x9C6E, + 0x5FA0, 0x9C71, 0x5FA1, 0x8CE4, 0x5FA8, 0x9C72, 0x5FA9, 0x959C, 0x5FAA, 0x8F7A, 0x5FAD, 0x9C73, 0x5FAE, 0x94F7, 0x5FB3, 0x93BF, + 0x5FB4, 0x92A5, 0x5FB7, 0xFABA, 0x5FB9, 0x934F, 0x5FBC, 0x9C74, 0x5FBD, 0x8B4A, 0x5FC3, 0x9053, 0x5FC5, 0x954B, 0x5FCC, 0x8AF5, + 0x5FCD, 0x9445, 0x5FD6, 0x9C75, 0x5FD7, 0x8E75, 0x5FD8, 0x9659, 0x5FD9, 0x965A, 0x5FDC, 0x899E, 0x5FDD, 0x9C7A, 0x5FDE, 0xFABB, + 0x5FE0, 0x9289, 0x5FE4, 0x9C77, 0x5FEB, 0x89F5, 0x5FF0, 0x9CAB, 0x5FF1, 0x9C79, 0x5FF5, 0x944F, 0x5FF8, 0x9C78, 0x5FFB, 0x9C76, + 0x5FFD, 0x8D9A, 0x5FFF, 0x9C7C, 0x600E, 0x9C83, 0x600F, 0x9C89, 0x6010, 0x9C81, 0x6012, 0x937B, 0x6015, 0x9C86, 0x6016, 0x957C, + 0x6019, 0x9C80, 0x601B, 0x9C85, 0x601C, 0x97E5, 0x601D, 0x8E76, 0x6020, 0x91D3, 0x6021, 0x9C7D, 0x6025, 0x8B7D, 0x6026, 0x9C88, + 0x6027, 0x90AB, 0x6028, 0x8985, 0x6029, 0x9C82, 0x602A, 0x89F6, 0x602B, 0x9C87, 0x602F, 0x8BAF, 0x6031, 0x9C84, 0x603A, 0x9C8A, + 0x6041, 0x9C8C, 0x6042, 0x9C96, 0x6043, 0x9C94, 0x6046, 0x9C91, 0x604A, 0x9C90, 0x604B, 0x97F6, 0x604D, 0x9C92, 0x6050, 0x8BB0, + 0x6052, 0x8D50, 0x6055, 0x8F9A, 0x6059, 0x9C99, 0x605A, 0x9C8B, 0x605D, 0xFABC, 0x605F, 0x9C8F, 0x6060, 0x9C7E, 0x6062, 0x89F8, + 0x6063, 0x9C93, 0x6064, 0x9C95, 0x6065, 0x9270, 0x6068, 0x8DA6, 0x6069, 0x89B6, 0x606A, 0x9C8D, 0x606B, 0x9C98, 0x606C, 0x9C97, + 0x606D, 0x8BB1, 0x606F, 0x91A7, 0x6070, 0x8A86, 0x6075, 0x8C62, 0x6077, 0x9C8E, 0x6081, 0x9C9A, 0x6083, 0x9C9D, 0x6084, 0x9C9F, + 0x6085, 0xFABD, 0x6089, 0x8EBB, 0x608A, 0xFABE, 0x608B, 0x9CA5, 0x608C, 0x92EE, 0x608D, 0x9C9B, 0x6092, 0x9CA3, 0x6094, 0x89F7, + 0x6096, 0x9CA1, 0x6097, 0x9CA2, 0x609A, 0x9C9E, 0x609B, 0x9CA0, 0x609F, 0x8CE5, 0x60A0, 0x9749, 0x60A3, 0x8AB3, 0x60A6, 0x8978, + 0x60A7, 0x9CA4, 0x60A9, 0x9459, 0x60AA, 0x88AB, 0x60B2, 0x94DF, 0x60B3, 0x9C7B, 0x60B4, 0x9CAA, 0x60B5, 0x9CAE, 0x60B6, 0x96E3, + 0x60B8, 0x9CA7, 0x60BC, 0x9389, 0x60BD, 0x9CAC, 0x60C5, 0x8FEE, 0x60C6, 0x9CAD, 0x60C7, 0x93D5, 0x60D1, 0x9866, 0x60D3, 0x9CA9, + 0x60D5, 0xFAC0, 0x60D8, 0x9CAF, 0x60DA, 0x8D9B, 0x60DC, 0x90C9, 0x60DE, 0xFABF, 0x60DF, 0x88D2, 0x60E0, 0x9CA8, 0x60E1, 0x9CA6, + 0x60E3, 0x9179, 0x60E7, 0x9C9C, 0x60E8, 0x8E53, 0x60F0, 0x91C4, 0x60F1, 0x9CBB, 0x60F2, 0xFAC2, 0x60F3, 0x917A, 0x60F4, 0x9CB6, + 0x60F6, 0x9CB3, 0x60F7, 0x9CB4, 0x60F9, 0x8EE4, 0x60FA, 0x9CB7, 0x60FB, 0x9CBA, 0x6100, 0x9CB5, 0x6101, 0x8F44, 0x6103, 0x9CB8, + 0x6106, 0x9CB2, 0x6108, 0x96FA, 0x6109, 0x96F9, 0x610D, 0x9CBC, 0x610E, 0x9CBD, 0x610F, 0x88D3, 0x6111, 0xFAC3, 0x6115, 0x9CB1, + 0x611A, 0x8BF0, 0x611B, 0x88A4, 0x611F, 0x8AB4, 0x6120, 0xFAC1, 0x6121, 0x9CB9, 0x6127, 0x9CC1, 0x6128, 0x9CC0, 0x612C, 0x9CC5, + 0x6130, 0xFAC5, 0x6134, 0x9CC6, 0x6137, 0xFAC4, 0x613C, 0x9CC4, 0x613D, 0x9CC7, 0x613E, 0x9CBF, 0x613F, 0x9CC3, 0x6142, 0x9CC8, + 0x6144, 0x9CC9, 0x6147, 0x9CBE, 0x6148, 0x8E9C, 0x614A, 0x9CC2, 0x614B, 0x91D4, 0x614C, 0x8D51, 0x614D, 0x9CB0, 0x614E, 0x9054, + 0x6153, 0x9CD6, 0x6155, 0x95E7, 0x6158, 0x9CCC, 0x6159, 0x9CCD, 0x615A, 0x9CCE, 0x615D, 0x9CD5, 0x615F, 0x9CD4, 0x6162, 0x969D, + 0x6163, 0x8AB5, 0x6165, 0x9CD2, 0x6167, 0x8C64, 0x6168, 0x8A53, 0x616B, 0x9CCF, 0x616E, 0x97B6, 0x616F, 0x9CD1, 0x6170, 0x88D4, + 0x6171, 0x9CD3, 0x6173, 0x9CCA, 0x6174, 0x9CD0, 0x6175, 0x9CD7, 0x6176, 0x8C63, 0x6177, 0x9CCB, 0x617E, 0x977C, 0x6182, 0x974A, + 0x6187, 0x9CDA, 0x618A, 0x9CDE, 0x618E, 0x919E, 0x6190, 0x97F7, 0x6191, 0x9CDF, 0x6194, 0x9CDC, 0x6196, 0x9CD9, 0x6198, 0xFAC6, + 0x6199, 0x9CD8, 0x619A, 0x9CDD, 0x61A4, 0x95AE, 0x61A7, 0x93B2, 0x61A9, 0x8C65, 0x61AB, 0x9CE0, 0x61AC, 0x9CDB, 0x61AE, 0x9CE1, + 0x61B2, 0x8C9B, 0x61B6, 0x89AF, 0x61BA, 0x9CE9, 0x61BE, 0x8AB6, 0x61C3, 0x9CE7, 0x61C6, 0x9CE8, 0x61C7, 0x8DA7, 0x61C8, 0x9CE6, + 0x61C9, 0x9CE4, 0x61CA, 0x9CE3, 0x61CB, 0x9CEA, 0x61CC, 0x9CE2, 0x61CD, 0x9CEC, 0x61D0, 0x89F9, 0x61E3, 0x9CEE, 0x61E6, 0x9CED, + 0x61F2, 0x92A6, 0x61F4, 0x9CF1, 0x61F6, 0x9CEF, 0x61F7, 0x9CE5, 0x61F8, 0x8C9C, 0x61FA, 0x9CF0, 0x61FC, 0x9CF4, 0x61FD, 0x9CF3, + 0x61FE, 0x9CF5, 0x61FF, 0x9CF2, 0x6200, 0x9CF6, 0x6208, 0x9CF7, 0x6209, 0x9CF8, 0x620A, 0x95E8, 0x620C, 0x9CFA, 0x620D, 0x9CF9, + 0x620E, 0x8F5E, 0x6210, 0x90AC, 0x6211, 0x89E4, 0x6212, 0x89FA, 0x6213, 0xFAC7, 0x6214, 0x9CFB, 0x6216, 0x88BD, 0x621A, 0x90CA, + 0x621B, 0x9CFC, 0x621D, 0xE6C1, 0x621E, 0x9D40, 0x621F, 0x8C81, 0x6221, 0x9D41, 0x6226, 0x90ED, 0x622A, 0x9D42, 0x622E, 0x9D43, + 0x622F, 0x8B59, 0x6230, 0x9D44, 0x6232, 0x9D45, 0x6233, 0x9D46, 0x6234, 0x91D5, 0x6238, 0x8CCB, 0x623B, 0x96DF, 0x623F, 0x965B, + 0x6240, 0x8F8A, 0x6241, 0x9D47, 0x6247, 0x90EE, 0x6248, 0xE7BB, 0x6249, 0x94E0, 0x624B, 0x8EE8, 0x624D, 0x8DCB, 0x624E, 0x9D48, + 0x6253, 0x91C5, 0x6255, 0x95A5, 0x6258, 0x91EF, 0x625B, 0x9D4B, 0x625E, 0x9D49, 0x6260, 0x9D4C, 0x6263, 0x9D4A, 0x6268, 0x9D4D, + 0x626E, 0x95AF, 0x6271, 0x88B5, 0x6276, 0x957D, 0x6279, 0x94E1, 0x627C, 0x9D4E, 0x627E, 0x9D51, 0x627F, 0x8FB3, 0x6280, 0x8B5A, + 0x6282, 0x9D4F, 0x6283, 0x9D56, 0x6284, 0x8FB4, 0x6289, 0x9D50, 0x628A, 0x9463, 0x6291, 0x977D, 0x6292, 0x9D52, 0x6293, 0x9D53, + 0x6294, 0x9D57, 0x6295, 0x938A, 0x6296, 0x9D54, 0x6297, 0x8D52, 0x6298, 0x90DC, 0x629B, 0x9D65, 0x629C, 0x94B2, 0x629E, 0x91F0, + 0x62A6, 0xFAC8, 0x62AB, 0x94E2, 0x62AC, 0x9DAB, 0x62B1, 0x95F8, 0x62B5, 0x92EF, 0x62B9, 0x9695, 0x62BB, 0x9D5A, 0x62BC, 0x899F, + 0x62BD, 0x928A, 0x62C2, 0x9D63, 0x62C5, 0x9253, 0x62C6, 0x9D5D, 0x62C7, 0x9D64, 0x62C8, 0x9D5F, 0x62C9, 0x9D66, 0x62CA, 0x9D62, + 0x62CC, 0x9D61, 0x62CD, 0x948F, 0x62CF, 0x9D5B, 0x62D0, 0x89FB, 0x62D1, 0x9D59, 0x62D2, 0x8B91, 0x62D3, 0x91F1, 0x62D4, 0x9D55, + 0x62D7, 0x9D58, 0x62D8, 0x8D53, 0x62D9, 0x90D9, 0x62DB, 0x8FB5, 0x62DC, 0x9D60, 0x62DD, 0x9471, 0x62E0, 0x8B92, 0x62E1, 0x8A67, + 0x62EC, 0x8A87, 0x62ED, 0x9040, 0x62EE, 0x9D68, 0x62EF, 0x9D6D, 0x62F1, 0x9D69, 0x62F3, 0x8C9D, 0x62F5, 0x9D6E, 0x62F6, 0x8E41, + 0x62F7, 0x8D89, 0x62FE, 0x8F45, 0x62FF, 0x9D5C, 0x6301, 0x8E9D, 0x6302, 0x9D6B, 0x6307, 0x8E77, 0x6308, 0x9D6C, 0x6309, 0x88C2, + 0x630C, 0x9D67, 0x6311, 0x92A7, 0x6319, 0x8B93, 0x631F, 0x8BB2, 0x6327, 0x9D6A, 0x6328, 0x88A5, 0x632B, 0x8DC1, 0x632F, 0x9055, + 0x633A, 0x92F0, 0x633D, 0x94D2, 0x633E, 0x9D70, 0x633F, 0x917D, 0x6349, 0x91A8, 0x634C, 0x8E4A, 0x634D, 0x9D71, 0x634F, 0x9D73, + 0x6350, 0x9D6F, 0x6355, 0x95DF, 0x6357, 0x92BB, 0x635C, 0x917B, 0x6367, 0x95F9, 0x6368, 0x8ECC, 0x6369, 0x9D80, 0x636B, 0x9D7E, + 0x636E, 0x9098, 0x6372, 0x8C9E, 0x6376, 0x9D78, 0x6377, 0x8FB7, 0x637A, 0x93E6, 0x637B, 0x9450, 0x6380, 0x9D76, 0x6383, 0x917C, + 0x6388, 0x8EF6, 0x6389, 0x9D7B, 0x638C, 0x8FB6, 0x638E, 0x9D75, 0x638F, 0x9D7A, 0x6392, 0x9472, 0x6396, 0x9D74, 0x6398, 0x8C40, + 0x639B, 0x8A7C, 0x639F, 0x9D7C, 0x63A0, 0x97A9, 0x63A1, 0x8DCC, 0x63A2, 0x9254, 0x63A3, 0x9D79, 0x63A5, 0x90DA, 0x63A7, 0x8D54, + 0x63A8, 0x9084, 0x63A9, 0x8986, 0x63AA, 0x915B, 0x63AB, 0x9D77, 0x63AC, 0x8B64, 0x63B2, 0x8C66, 0x63B4, 0x92CD, 0x63B5, 0x9D7D, + 0x63BB, 0x917E, 0x63BE, 0x9D81, 0x63C0, 0x9D83, 0x63C3, 0x91B5, 0x63C4, 0x9D89, 0x63C6, 0x9D84, 0x63C9, 0x9D86, 0x63CF, 0x9560, + 0x63D0, 0x92F1, 0x63D2, 0x9D87, 0x63D6, 0x974B, 0x63DA, 0x9767, 0x63DB, 0x8AB7, 0x63E1, 0x88AC, 0x63E3, 0x9D85, 0x63E9, 0x9D82, + 0x63EE, 0x8AF6, 0x63F4, 0x8987, 0x63F5, 0xFAC9, 0x63F6, 0x9D88, 0x63FA, 0x9768, 0x6406, 0x9D8C, 0x640D, 0x91B9, 0x640F, 0x9D93, + 0x6413, 0x9D8D, 0x6416, 0x9D8A, 0x6417, 0x9D91, 0x641C, 0x9D72, 0x6426, 0x9D8E, 0x6428, 0x9D92, 0x642C, 0x94C0, 0x642D, 0x938B, + 0x6434, 0x9D8B, 0x6436, 0x9D8F, 0x643A, 0x8C67, 0x643E, 0x8DEF, 0x6442, 0x90DB, 0x644E, 0x9D97, 0x6458, 0x9345, 0x6460, 0xFACA, + 0x6467, 0x9D94, 0x6469, 0x9680, 0x646F, 0x9D95, 0x6476, 0x9D96, 0x6478, 0x96CC, 0x647A, 0x90A0, 0x6483, 0x8C82, 0x6488, 0x9D9D, + 0x6492, 0x8E54, 0x6493, 0x9D9A, 0x6495, 0x9D99, 0x649A, 0x9451, 0x649D, 0xFACB, 0x649E, 0x93B3, 0x64A4, 0x9350, 0x64A5, 0x9D9B, + 0x64A9, 0x9D9C, 0x64AB, 0x958F, 0x64AD, 0x9464, 0x64AE, 0x8E42, 0x64B0, 0x90EF, 0x64B2, 0x966F, 0x64B9, 0x8A68, 0x64BB, 0x9DA3, + 0x64BC, 0x9D9E, 0x64C1, 0x9769, 0x64C2, 0x9DA5, 0x64C5, 0x9DA1, 0x64C7, 0x9DA2, 0x64CD, 0x9180, 0x64CE, 0xFACC, 0x64D2, 0x9DA0, + 0x64D4, 0x9D5E, 0x64D8, 0x9DA4, 0x64DA, 0x9D9F, 0x64E0, 0x9DA9, 0x64E1, 0x9DAA, 0x64E2, 0x9346, 0x64E3, 0x9DAC, 0x64E6, 0x8E43, + 0x64E7, 0x9DA7, 0x64EC, 0x8B5B, 0x64EF, 0x9DAD, 0x64F1, 0x9DA6, 0x64F2, 0x9DB1, 0x64F4, 0x9DB0, 0x64F6, 0x9DAF, 0x64FA, 0x9DB2, + 0x64FD, 0x9DB4, 0x64FE, 0x8FEF, 0x6500, 0x9DB3, 0x6505, 0x9DB7, 0x6518, 0x9DB5, 0x651C, 0x9DB6, 0x651D, 0x9D90, 0x6523, 0x9DB9, + 0x6524, 0x9DB8, 0x652A, 0x9D98, 0x652B, 0x9DBA, 0x652C, 0x9DAE, 0x652F, 0x8E78, 0x6534, 0x9DBB, 0x6535, 0x9DBC, 0x6536, 0x9DBE, + 0x6537, 0x9DBD, 0x6538, 0x9DBF, 0x6539, 0x89FC, 0x653B, 0x8D55, 0x653E, 0x95FA, 0x653F, 0x90AD, 0x6545, 0x8CCC, 0x6548, 0x9DC1, + 0x654D, 0x9DC4, 0x654E, 0xFACD, 0x654F, 0x9571, 0x6551, 0x8B7E, 0x6555, 0x9DC3, 0x6556, 0x9DC2, 0x6557, 0x9473, 0x6558, 0x9DC5, + 0x6559, 0x8BB3, 0x655D, 0x9DC7, 0x655E, 0x9DC6, 0x6562, 0x8AB8, 0x6563, 0x8E55, 0x6566, 0x93D6, 0x656C, 0x8C68, 0x6570, 0x9094, + 0x6572, 0x9DC8, 0x6574, 0x90AE, 0x6575, 0x9347, 0x6577, 0x957E, 0x6578, 0x9DC9, 0x6582, 0x9DCA, 0x6583, 0x9DCB, 0x6587, 0x95B6, + 0x6588, 0x9B7C, 0x6589, 0x90C4, 0x658C, 0x956B, 0x658E, 0x8DD6, 0x6590, 0x94E3, 0x6591, 0x94C1, 0x6597, 0x936C, 0x6599, 0x97BF, + 0x659B, 0x9DCD, 0x659C, 0x8ECE, 0x659F, 0x9DCE, 0x65A1, 0x88B4, 0x65A4, 0x8BD2, 0x65A5, 0x90CB, 0x65A7, 0x9580, 0x65AB, 0x9DCF, + 0x65AC, 0x8E61, 0x65AD, 0x9266, 0x65AF, 0x8E7A, 0x65B0, 0x9056, 0x65B7, 0x9DD0, 0x65B9, 0x95FB, 0x65BC, 0x8997, 0x65BD, 0x8E7B, + 0x65C1, 0x9DD3, 0x65C3, 0x9DD1, 0x65C4, 0x9DD4, 0x65C5, 0x97B7, 0x65C6, 0x9DD2, 0x65CB, 0x90F9, 0x65CC, 0x9DD5, 0x65CF, 0x91B0, + 0x65D2, 0x9DD6, 0x65D7, 0x8AF8, 0x65D9, 0x9DD8, 0x65DB, 0x9DD7, 0x65E0, 0x9DD9, 0x65E1, 0x9DDA, 0x65E2, 0x8AF9, 0x65E5, 0x93FA, + 0x65E6, 0x9255, 0x65E7, 0x8B8C, 0x65E8, 0x8E7C, 0x65E9, 0x9181, 0x65EC, 0x8F7B, 0x65ED, 0x88AE, 0x65F1, 0x9DDB, 0x65FA, 0x89A0, + 0x65FB, 0x9DDF, 0x6600, 0xFACE, 0x6602, 0x8D56, 0x6603, 0x9DDE, 0x6606, 0x8DA9, 0x6607, 0x8FB8, 0x6609, 0xFAD1, 0x660A, 0x9DDD, + 0x660C, 0x8FB9, 0x660E, 0x96BE, 0x660F, 0x8DA8, 0x6613, 0x88D5, 0x6614, 0x90CC, 0x6615, 0xFACF, 0x661C, 0x9DE4, 0x661E, 0xFAD3, + 0x661F, 0x90AF, 0x6620, 0x8966, 0x6624, 0xFAD4, 0x6625, 0x8F74, 0x6627, 0x9686, 0x6628, 0x8DF0, 0x662D, 0x8FBA, 0x662E, 0xFAD2, + 0x662F, 0x90A5, 0x6631, 0xFA63, 0x6634, 0x9DE3, 0x6635, 0x9DE1, 0x6636, 0x9DE2, 0x663B, 0xFAD0, 0x663C, 0x928B, 0x663F, 0x9E45, + 0x6641, 0x9DE8, 0x6642, 0x8E9E, 0x6643, 0x8D57, 0x6644, 0x9DE6, 0x6649, 0x9DE7, 0x664B, 0x9057, 0x664F, 0x9DE5, 0x6652, 0x8E4E, + 0x6657, 0xFAD6, 0x6659, 0xFAD7, 0x665D, 0x9DEA, 0x665E, 0x9DE9, 0x665F, 0x9DEE, 0x6662, 0x9DEF, 0x6664, 0x9DEB, 0x6665, 0xFAD5, + 0x6666, 0x8A41, 0x6667, 0x9DEC, 0x6668, 0x9DED, 0x6669, 0x94D3, 0x666E, 0x9581, 0x666F, 0x8C69, 0x6670, 0x9DF0, 0x6673, 0xFAD9, + 0x6674, 0x90B0, 0x6676, 0x8FBB, 0x667A, 0x9271, 0x6681, 0x8BC5, 0x6683, 0x9DF1, 0x6684, 0x9DF5, 0x6687, 0x89C9, 0x6688, 0x9DF2, + 0x6689, 0x9DF4, 0x668E, 0x9DF3, 0x6691, 0x8F8B, 0x6696, 0x9267, 0x6697, 0x88C3, 0x6698, 0x9DF6, 0x6699, 0xFADA, 0x669D, 0x9DF7, + 0x66A0, 0xFADB, 0x66A2, 0x92A8, 0x66A6, 0x97EF, 0x66AB, 0x8E62, 0x66AE, 0x95E9, 0x66B2, 0xFADC, 0x66B4, 0x965C, 0x66B8, 0x9E41, + 0x66B9, 0x9DF9, 0x66BC, 0x9DFC, 0x66BE, 0x9DFB, 0x66BF, 0xFADD, 0x66C1, 0x9DF8, 0x66C4, 0x9E40, 0x66C7, 0x93DC, 0x66C9, 0x9DFA, + 0x66D6, 0x9E42, 0x66D9, 0x8F8C, 0x66DA, 0x9E43, 0x66DC, 0x976A, 0x66DD, 0x9498, 0x66E0, 0x9E44, 0x66E6, 0x9E46, 0x66E9, 0x9E47, + 0x66F0, 0x9E48, 0x66F2, 0x8BC8, 0x66F3, 0x8967, 0x66F4, 0x8D58, 0x66F5, 0x9E49, 0x66F7, 0x9E4A, 0x66F8, 0x8F91, 0x66F9, 0x9182, + 0x66FA, 0xFADE, 0x66FB, 0xFA66, 0x66FC, 0x99D6, 0x66FD, 0x915D, 0x66FE, 0x915C, 0x66FF, 0x91D6, 0x6700, 0x8DC5, 0x6703, 0x98F0, + 0x6708, 0x8C8E, 0x6709, 0x974C, 0x670B, 0x95FC, 0x670D, 0x959E, 0x670E, 0xFADF, 0x670F, 0x9E4B, 0x6714, 0x8DF1, 0x6715, 0x92BD, + 0x6716, 0x9E4C, 0x6717, 0x984E, 0x671B, 0x965D, 0x671D, 0x92A9, 0x671E, 0x9E4D, 0x671F, 0x8AFA, 0x6726, 0x9E4E, 0x6727, 0x9E4F, + 0x6728, 0x96D8, 0x672A, 0x96A2, 0x672B, 0x9696, 0x672C, 0x967B, 0x672D, 0x8E44, 0x672E, 0x9E51, 0x6731, 0x8EE9, 0x6734, 0x9670, + 0x6736, 0x9E53, 0x6737, 0x9E56, 0x6738, 0x9E55, 0x673A, 0x8AF7, 0x673D, 0x8B80, 0x673F, 0x9E52, 0x6741, 0x9E54, 0x6746, 0x9E57, + 0x6749, 0x9099, 0x674E, 0x979B, 0x674F, 0x88C7, 0x6750, 0x8DDE, 0x6751, 0x91BA, 0x6753, 0x8EDB, 0x6756, 0x8FF1, 0x6759, 0x9E5A, + 0x675C, 0x936D, 0x675E, 0x9E58, 0x675F, 0x91A9, 0x6760, 0x9E59, 0x6761, 0x8FF0, 0x6762, 0x96DB, 0x6763, 0x9E5B, 0x6764, 0x9E5C, + 0x6765, 0x9788, 0x6766, 0xFAE1, 0x676A, 0x9E61, 0x676D, 0x8D59, 0x676F, 0x9474, 0x6770, 0x9E5E, 0x6771, 0x938C, 0x6772, 0x9DDC, + 0x6773, 0x9DE0, 0x6775, 0x8B6E, 0x6777, 0x9466, 0x677C, 0x9E60, 0x677E, 0x8FBC, 0x677F, 0x94C2, 0x6785, 0x9E66, 0x6787, 0x94F8, + 0x6789, 0x9E5D, 0x678B, 0x9E63, 0x678C, 0x9E62, 0x6790, 0x90CD, 0x6795, 0x968D, 0x6797, 0x97D1, 0x679A, 0x9687, 0x679C, 0x89CA, + 0x679D, 0x8E7D, 0x67A0, 0x9867, 0x67A1, 0x9E65, 0x67A2, 0x9095, 0x67A6, 0x9E64, 0x67A9, 0x9E5F, 0x67AF, 0x8CCD, 0x67B3, 0x9E6B, + 0x67B4, 0x9E69, 0x67B6, 0x89CB, 0x67B7, 0x9E67, 0x67B8, 0x9E6D, 0x67B9, 0x9E73, 0x67BB, 0xFAE2, 0x67C0, 0xFAE4, 0x67C1, 0x91C6, + 0x67C4, 0x95BF, 0x67C6, 0x9E75, 0x67CA, 0x9541, 0x67CE, 0x9E74, 0x67CF, 0x9490, 0x67D0, 0x965E, 0x67D1, 0x8AB9, 0x67D3, 0x90F5, + 0x67D4, 0x8F5F, 0x67D8, 0x92D1, 0x67DA, 0x974D, 0x67DD, 0x9E70, 0x67DE, 0x9E6F, 0x67E2, 0x9E71, 0x67E4, 0x9E6E, 0x67E7, 0x9E76, + 0x67E9, 0x9E6C, 0x67EC, 0x9E6A, 0x67EE, 0x9E72, 0x67EF, 0x9E68, 0x67F1, 0x928C, 0x67F3, 0x96F6, 0x67F4, 0x8EC4, 0x67F5, 0x8DF2, + 0x67FB, 0x8DB8, 0x67FE, 0x968F, 0x67FF, 0x8A60, 0x6801, 0xFAE5, 0x6802, 0x92CC, 0x6803, 0x93C8, 0x6804, 0x8968, 0x6813, 0x90F0, + 0x6816, 0x90B2, 0x6817, 0x8C49, 0x681E, 0x9E78, 0x6821, 0x8D5A, 0x6822, 0x8A9C, 0x6829, 0x9E7A, 0x682A, 0x8A94, 0x682B, 0x9E81, + 0x6832, 0x9E7D, 0x6834, 0x90F1, 0x6838, 0x8A6A, 0x6839, 0x8DAA, 0x683C, 0x8A69, 0x683D, 0x8DCD, 0x6840, 0x9E7B, 0x6841, 0x8C85, + 0x6842, 0x8C6A, 0x6843, 0x938D, 0x6844, 0xFAE6, 0x6846, 0x9E79, 0x6848, 0x88C4, 0x684D, 0x9E7C, 0x684E, 0x9E7E, 0x6850, 0x8BCB, + 0x6851, 0x8C4B, 0x6852, 0xFAE3, 0x6853, 0x8ABA, 0x6854, 0x8B6A, 0x6859, 0x9E82, 0x685C, 0x8DF7, 0x685D, 0x9691, 0x685F, 0x8E56, + 0x6863, 0x9E83, 0x6867, 0x954F, 0x6874, 0x9E8F, 0x6876, 0x89B1, 0x6877, 0x9E84, 0x687E, 0x9E95, 0x687F, 0x9E85, 0x6881, 0x97C0, + 0x6883, 0x9E8C, 0x6885, 0x947E, 0x688D, 0x9E94, 0x688F, 0x9E87, 0x6893, 0x88B2, 0x6894, 0x9E89, 0x6897, 0x8D5B, 0x689B, 0x9E8B, + 0x689D, 0x9E8A, 0x689F, 0x9E86, 0x68A0, 0x9E91, 0x68A2, 0x8FBD, 0x68A6, 0x9AEB, 0x68A7, 0x8CE6, 0x68A8, 0x979C, 0x68AD, 0x9E88, + 0x68AF, 0x92F2, 0x68B0, 0x8A42, 0x68B1, 0x8DAB, 0x68B3, 0x9E80, 0x68B5, 0x9E90, 0x68B6, 0x8A81, 0x68B9, 0x9E8E, 0x68BA, 0x9E92, + 0x68BC, 0x938E, 0x68C4, 0x8AFC, 0x68C6, 0x9EB0, 0x68C8, 0xFA64, 0x68C9, 0x96C7, 0x68CA, 0x9E97, 0x68CB, 0x8AFB, 0x68CD, 0x9E9E, + 0x68CF, 0xFAE7, 0x68D2, 0x965F, 0x68D4, 0x9E9F, 0x68D5, 0x9EA1, 0x68D7, 0x9EA5, 0x68D8, 0x9E99, 0x68DA, 0x9249, 0x68DF, 0x938F, + 0x68E0, 0x9EA9, 0x68E1, 0x9E9C, 0x68E3, 0x9EA6, 0x68E7, 0x9EA0, 0x68EE, 0x9058, 0x68EF, 0x9EAA, 0x68F2, 0x90B1, 0x68F9, 0x9EA8, + 0x68FA, 0x8ABB, 0x6900, 0x986F, 0x6901, 0x9E96, 0x6904, 0x9EA4, 0x6905, 0x88D6, 0x6908, 0x9E98, 0x690B, 0x96B8, 0x690C, 0x9E9D, + 0x690D, 0x9041, 0x690E, 0x92C5, 0x690F, 0x9E93, 0x6912, 0x9EA3, 0x6919, 0x909A, 0x691A, 0x9EAD, 0x691B, 0x8A91, 0x691C, 0x8C9F, + 0x6921, 0x9EAF, 0x6922, 0x9E9A, 0x6923, 0x9EAE, 0x6925, 0x9EA7, 0x6926, 0x9E9B, 0x6928, 0x9EAB, 0x692A, 0x9EAC, 0x6930, 0x9EBD, + 0x6934, 0x93CC, 0x6936, 0x9EA2, 0x6939, 0x9EB9, 0x693D, 0x9EBB, 0x693F, 0x92D6, 0x694A, 0x976B, 0x6953, 0x9596, 0x6954, 0x9EB6, + 0x6955, 0x91C8, 0x6959, 0x9EBC, 0x695A, 0x915E, 0x695C, 0x9EB3, 0x695D, 0x9EC0, 0x695E, 0x9EBF, 0x6960, 0x93ED, 0x6961, 0x9EBE, + 0x6962, 0x93E8, 0x6968, 0xFAE9, 0x696A, 0x9EC2, 0x696B, 0x9EB5, 0x696D, 0x8BC6, 0x696E, 0x9EB8, 0x696F, 0x8F7C, 0x6973, 0x9480, + 0x6974, 0x9EBA, 0x6975, 0x8BC9, 0x6977, 0x9EB2, 0x6978, 0x9EB4, 0x6979, 0x9EB1, 0x697C, 0x984F, 0x697D, 0x8A79, 0x697E, 0x9EB7, + 0x6981, 0x9EC1, 0x6982, 0x8A54, 0x698A, 0x8DE5, 0x698E, 0x897C, 0x6991, 0x9ED2, 0x6994, 0x9850, 0x6995, 0x9ED5, 0x6998, 0xFAEB, + 0x699B, 0x9059, 0x699C, 0x9ED4, 0x69A0, 0x9ED3, 0x69A7, 0x9ED0, 0x69AE, 0x9EC4, 0x69B1, 0x9EE1, 0x69B2, 0x9EC3, 0x69B4, 0x9ED6, + 0x69BB, 0x9ECE, 0x69BE, 0x9EC9, 0x69BF, 0x9EC6, 0x69C1, 0x9EC7, 0x69C3, 0x9ECF, 0x69C7, 0xEAA0, 0x69CA, 0x9ECC, 0x69CB, 0x8D5C, + 0x69CC, 0x92C6, 0x69CD, 0x9184, 0x69CE, 0x9ECA, 0x69D0, 0x9EC5, 0x69D3, 0x9EC8, 0x69D8, 0x976C, 0x69D9, 0x968A, 0x69DD, 0x9ECD, + 0x69DE, 0x9ED7, 0x69E2, 0xFAEC, 0x69E7, 0x9EDF, 0x69E8, 0x9ED8, 0x69EB, 0x9EE5, 0x69ED, 0x9EE3, 0x69F2, 0x9EDE, 0x69F9, 0x9EDD, + 0x69FB, 0x92CE, 0x69FD, 0x9185, 0x69FF, 0x9EDB, 0x6A02, 0x9ED9, 0x6A05, 0x9EE0, 0x6A0A, 0x9EE6, 0x6A0B, 0x94F3, 0x6A0C, 0x9EEC, + 0x6A12, 0x9EE7, 0x6A13, 0x9EEA, 0x6A14, 0x9EE4, 0x6A17, 0x9294, 0x6A19, 0x9557, 0x6A1B, 0x9EDA, 0x6A1E, 0x9EE2, 0x6A1F, 0x8FBE, + 0x6A21, 0x96CD, 0x6A22, 0x9EF6, 0x6A23, 0x9EE9, 0x6A29, 0x8CA0, 0x6A2A, 0x89A1, 0x6A2B, 0x8A7E, 0x6A2E, 0x9ED1, 0x6A30, 0xFAED, + 0x6A35, 0x8FBF, 0x6A36, 0x9EEE, 0x6A38, 0x9EF5, 0x6A39, 0x8EF7, 0x6A3A, 0x8A92, 0x6A3D, 0x924D, 0x6A44, 0x9EEB, 0x6A46, 0xFAEF, + 0x6A47, 0x9EF0, 0x6A48, 0x9EF4, 0x6A4B, 0x8BB4, 0x6A58, 0x8B6B, 0x6A59, 0x9EF2, 0x6A5F, 0x8B40, 0x6A61, 0x93C9, 0x6A62, 0x9EF1, + 0x6A66, 0x9EF3, 0x6A6B, 0xFAEE, 0x6A72, 0x9EED, 0x6A73, 0xFAF0, 0x6A78, 0x9EEF, 0x6A7E, 0xFAF1, 0x6A7F, 0x8A80, 0x6A80, 0x9268, + 0x6A84, 0x9EFA, 0x6A8D, 0x9EF8, 0x6A8E, 0x8CE7, 0x6A90, 0x9EF7, 0x6A97, 0x9F40, 0x6A9C, 0x9E77, 0x6AA0, 0x9EF9, 0x6AA2, 0x9EFB, + 0x6AA3, 0x9EFC, 0x6AAA, 0x9F4B, 0x6AAC, 0x9F47, 0x6AAE, 0x9E8D, 0x6AB3, 0x9F46, 0x6AB8, 0x9F45, 0x6ABB, 0x9F42, 0x6AC1, 0x9EE8, + 0x6AC2, 0x9F44, 0x6AC3, 0x9F43, 0x6AD1, 0x9F49, 0x6AD3, 0x9845, 0x6ADA, 0x9F4C, 0x6ADB, 0x8BF9, 0x6ADE, 0x9F48, 0x6ADF, 0x9F4A, + 0x6AE2, 0xFAF2, 0x6AE4, 0xFAF3, 0x6AE8, 0x94A5, 0x6AEA, 0x9F4D, 0x6AFA, 0x9F51, 0x6AFB, 0x9F4E, 0x6B04, 0x9793, 0x6B05, 0x9F4F, + 0x6B0A, 0x9EDC, 0x6B12, 0x9F52, 0x6B16, 0x9F53, 0x6B1D, 0x8954, 0x6B1F, 0x9F55, 0x6B20, 0x8C87, 0x6B21, 0x8E9F, 0x6B23, 0x8BD3, + 0x6B27, 0x89A2, 0x6B32, 0x977E, 0x6B37, 0x9F57, 0x6B38, 0x9F56, 0x6B39, 0x9F59, 0x6B3A, 0x8B5C, 0x6B3D, 0x8BD4, 0x6B3E, 0x8ABC, + 0x6B43, 0x9F5C, 0x6B47, 0x9F5B, 0x6B49, 0x9F5D, 0x6B4C, 0x89CC, 0x6B4E, 0x9256, 0x6B50, 0x9F5E, 0x6B53, 0x8ABD, 0x6B54, 0x9F60, + 0x6B59, 0x9F5F, 0x6B5B, 0x9F61, 0x6B5F, 0x9F62, 0x6B61, 0x9F63, 0x6B62, 0x8E7E, 0x6B63, 0x90B3, 0x6B64, 0x8D9F, 0x6B66, 0x9590, + 0x6B69, 0x95E0, 0x6B6A, 0x9863, 0x6B6F, 0x8E95, 0x6B73, 0x8DCE, 0x6B74, 0x97F0, 0x6B78, 0x9F64, 0x6B79, 0x9F65, 0x6B7B, 0x8E80, + 0x6B7F, 0x9F66, 0x6B80, 0x9F67, 0x6B83, 0x9F69, 0x6B84, 0x9F68, 0x6B86, 0x9677, 0x6B89, 0x8F7D, 0x6B8A, 0x8EEA, 0x6B8B, 0x8E63, + 0x6B8D, 0x9F6A, 0x6B95, 0x9F6C, 0x6B96, 0x9042, 0x6B98, 0x9F6B, 0x6B9E, 0x9F6D, 0x6BA4, 0x9F6E, 0x6BAA, 0x9F6F, 0x6BAB, 0x9F70, + 0x6BAF, 0x9F71, 0x6BB1, 0x9F73, 0x6BB2, 0x9F72, 0x6BB3, 0x9F74, 0x6BB4, 0x89A3, 0x6BB5, 0x9269, 0x6BB7, 0x9F75, 0x6BBA, 0x8E45, + 0x6BBB, 0x8A6B, 0x6BBC, 0x9F76, 0x6BBF, 0x9361, 0x6BC0, 0x9ACA, 0x6BC5, 0x8B42, 0x6BC6, 0x9F77, 0x6BCB, 0x9F78, 0x6BCD, 0x95EA, + 0x6BCE, 0x9688, 0x6BD2, 0x93C5, 0x6BD3, 0x9F79, 0x6BD4, 0x94E4, 0x6BD6, 0xFAF4, 0x6BD8, 0x94F9, 0x6BDB, 0x96D1, 0x6BDF, 0x9F7A, + 0x6BEB, 0x9F7C, 0x6BEC, 0x9F7B, 0x6BEF, 0x9F7E, 0x6BF3, 0x9F7D, 0x6C08, 0x9F81, 0x6C0F, 0x8E81, 0x6C11, 0x96AF, 0x6C13, 0x9F82, + 0x6C14, 0x9F83, 0x6C17, 0x8B43, 0x6C1B, 0x9F84, 0x6C23, 0x9F86, 0x6C24, 0x9F85, 0x6C34, 0x9085, 0x6C37, 0x9558, 0x6C38, 0x8969, + 0x6C3E, 0x94C3, 0x6C3F, 0xFAF5, 0x6C40, 0x92F3, 0x6C41, 0x8F60, 0x6C42, 0x8B81, 0x6C4E, 0x94C4, 0x6C50, 0x8EAC, 0x6C55, 0x9F88, + 0x6C57, 0x8ABE, 0x6C5A, 0x8998, 0x6C5C, 0xFAF6, 0x6C5D, 0x93F0, 0x6C5E, 0x9F87, 0x6C5F, 0x8D5D, 0x6C60, 0x9272, 0x6C62, 0x9F89, + 0x6C68, 0x9F91, 0x6C6A, 0x9F8A, 0x6C6F, 0xFAF8, 0x6C70, 0x91BF, 0x6C72, 0x8B82, 0x6C73, 0x9F92, 0x6C7A, 0x8C88, 0x6C7D, 0x8B44, + 0x6C7E, 0x9F90, 0x6C81, 0x9F8E, 0x6C82, 0x9F8B, 0x6C83, 0x9780, 0x6C86, 0xFAF7, 0x6C88, 0x92BE, 0x6C8C, 0x93D7, 0x6C8D, 0x9F8C, + 0x6C90, 0x9F94, 0x6C92, 0x9F93, 0x6C93, 0x8C42, 0x6C96, 0x89AB, 0x6C99, 0x8DB9, 0x6C9A, 0x9F8D, 0x6C9B, 0x9F8F, 0x6CA1, 0x9676, + 0x6CA2, 0x91F2, 0x6CAB, 0x9697, 0x6CAE, 0x9F9C, 0x6CB1, 0x9F9D, 0x6CB3, 0x89CD, 0x6CB8, 0x95A6, 0x6CB9, 0x96FB, 0x6CBA, 0x9F9F, + 0x6CBB, 0x8EA1, 0x6CBC, 0x8FC0, 0x6CBD, 0x9F98, 0x6CBE, 0x9F9E, 0x6CBF, 0x8988, 0x6CC1, 0x8BB5, 0x6CC4, 0x9F95, 0x6CC5, 0x9F9A, + 0x6CC9, 0x90F2, 0x6CCA, 0x9491, 0x6CCC, 0x94E5, 0x6CD3, 0x9F97, 0x6CD5, 0x9640, 0x6CD7, 0x9F99, 0x6CD9, 0x9FA2, 0x6CDA, 0xFAF9, + 0x6CDB, 0x9FA0, 0x6CDD, 0x9F9B, 0x6CE1, 0x9641, 0x6CE2, 0x9467, 0x6CE3, 0x8B83, 0x6CE5, 0x9344, 0x6CE8, 0x928D, 0x6CEA, 0x9FA3, + 0x6CEF, 0x9FA1, 0x6CF0, 0x91D7, 0x6CF1, 0x9F96, 0x6CF3, 0x896A, 0x6D04, 0xFAFA, 0x6D0B, 0x976D, 0x6D0C, 0x9FAE, 0x6D12, 0x9FAD, + 0x6D17, 0x90F4, 0x6D19, 0x9FAA, 0x6D1B, 0x978C, 0x6D1E, 0x93B4, 0x6D1F, 0x9FA4, 0x6D25, 0x92C3, 0x6D29, 0x896B, 0x6D2A, 0x8D5E, + 0x6D2B, 0x9FA7, 0x6D32, 0x8F46, 0x6D33, 0x9FAC, 0x6D35, 0x9FAB, 0x6D36, 0x9FA6, 0x6D38, 0x9FA9, 0x6D3B, 0x8A88, 0x6D3D, 0x9FA8, + 0x6D3E, 0x9468, 0x6D41, 0x97AC, 0x6D44, 0x8FF2, 0x6D45, 0x90F3, 0x6D59, 0x9FB4, 0x6D5A, 0x9FB2, 0x6D5C, 0x956C, 0x6D63, 0x9FAF, + 0x6D64, 0x9FB1, 0x6D66, 0x8959, 0x6D69, 0x8D5F, 0x6D6A, 0x9851, 0x6D6C, 0x8A5C, 0x6D6E, 0x9582, 0x6D6F, 0xFAFC, 0x6D74, 0x9781, + 0x6D77, 0x8A43, 0x6D78, 0x905A, 0x6D79, 0x9FB3, 0x6D85, 0x9FB8, 0x6D87, 0xFAFB, 0x6D88, 0x8FC1, 0x6D8C, 0x974F, 0x6D8E, 0x9FB5, + 0x6D93, 0x9FB0, 0x6D95, 0x9FB6, 0x6D96, 0xFB40, 0x6D99, 0x97DC, 0x6D9B, 0x9393, 0x6D9C, 0x93C0, 0x6DAC, 0xFB41, 0x6DAF, 0x8A55, + 0x6DB2, 0x8974, 0x6DB5, 0x9FBC, 0x6DB8, 0x9FBF, 0x6DBC, 0x97C1, 0x6DC0, 0x9784, 0x6DC5, 0x9FC6, 0x6DC6, 0x9FC0, 0x6DC7, 0x9FBD, + 0x6DCB, 0x97D2, 0x6DCC, 0x9FC3, 0x6DCF, 0xFB42, 0x6DD1, 0x8F69, 0x6DD2, 0x9FC5, 0x6DD5, 0x9FCA, 0x6DD8, 0x9391, 0x6DD9, 0x9FC8, + 0x6DDE, 0x9FC2, 0x6DE1, 0x9257, 0x6DE4, 0x9FC9, 0x6DE6, 0x9FBE, 0x6DE8, 0x9FC4, 0x6DEA, 0x9FCB, 0x6DEB, 0x88FA, 0x6DEC, 0x9FC1, + 0x6DEE, 0x9FCC, 0x6DF1, 0x905B, 0x6DF2, 0xFB44, 0x6DF3, 0x8F7E, 0x6DF5, 0x95A3, 0x6DF7, 0x8DAC, 0x6DF8, 0xFB43, 0x6DF9, 0x9FB9, + 0x6DFA, 0x9FC7, 0x6DFB, 0x9359, 0x6DFC, 0xFB45, 0x6E05, 0x90B4, 0x6E07, 0x8A89, 0x6E08, 0x8DCF, 0x6E09, 0x8FC2, 0x6E0A, 0x9FBB, + 0x6E0B, 0x8F61, 0x6E13, 0x8C6B, 0x6E15, 0x9FBA, 0x6E19, 0x9FD0, 0x6E1A, 0x8F8D, 0x6E1B, 0x8CB8, 0x6E1D, 0x9FDF, 0x6E1F, 0x9FD9, + 0x6E20, 0x8B94, 0x6E21, 0x936E, 0x6E23, 0x9FD4, 0x6E24, 0x9FDD, 0x6E25, 0x88AD, 0x6E26, 0x8951, 0x6E27, 0xFB48, 0x6E29, 0x89B7, + 0x6E2B, 0x9FD6, 0x6E2C, 0x91AA, 0x6E2D, 0x9FCD, 0x6E2E, 0x9FCF, 0x6E2F, 0x8D60, 0x6E38, 0x9FE0, 0x6E39, 0xFB46, 0x6E3A, 0x9FDB, + 0x6E3C, 0xFB49, 0x6E3E, 0x9FD3, 0x6E43, 0x9FDA, 0x6E4A, 0x96A9, 0x6E4D, 0x9FD8, 0x6E4E, 0x9FDC, 0x6E56, 0x8CCE, 0x6E58, 0x8FC3, + 0x6E5B, 0x9258, 0x6E5C, 0xFB47, 0x6E5F, 0x9FD2, 0x6E67, 0x974E, 0x6E6B, 0x9FD5, 0x6E6E, 0x9FCE, 0x6E6F, 0x9392, 0x6E72, 0x9FD1, + 0x6E76, 0x9FD7, 0x6E7E, 0x9870, 0x6E7F, 0x8EBC, 0x6E80, 0x969E, 0x6E82, 0x9FE1, 0x6E8C, 0x94AC, 0x6E8F, 0x9FED, 0x6E90, 0x8CB9, + 0x6E96, 0x8F80, 0x6E98, 0x9FE3, 0x6E9C, 0x97AD, 0x6E9D, 0x8D61, 0x6E9F, 0x9FF0, 0x6EA2, 0x88EC, 0x6EA5, 0x9FEE, 0x6EAA, 0x9FE2, + 0x6EAF, 0x9FE8, 0x6EB2, 0x9FEA, 0x6EB6, 0x976E, 0x6EB7, 0x9FE5, 0x6EBA, 0x934D, 0x6EBD, 0x9FE7, 0x6EBF, 0xFB4A, 0x6EC2, 0x9FEF, + 0x6EC4, 0x9FE9, 0x6EC5, 0x96C5, 0x6EC9, 0x9FE4, 0x6ECB, 0x8EA0, 0x6ECC, 0x9FFC, 0x6ED1, 0x8A8A, 0x6ED3, 0x9FE6, 0x6ED4, 0x9FEB, + 0x6ED5, 0x9FEC, 0x6EDD, 0x91EA, 0x6EDE, 0x91D8, 0x6EEC, 0x9FF4, 0x6EEF, 0x9FFA, 0x6EF2, 0x9FF8, 0x6EF4, 0x9348, 0x6EF7, 0xE042, + 0x6EF8, 0x9FF5, 0x6EFE, 0x9FF6, 0x6EFF, 0x9FDE, 0x6F01, 0x8B99, 0x6F02, 0x9559, 0x6F06, 0x8EBD, 0x6F09, 0x8D97, 0x6F0F, 0x9852, + 0x6F11, 0x9FF2, 0x6F13, 0xE041, 0x6F14, 0x8989, 0x6F15, 0x9186, 0x6F20, 0x9499, 0x6F22, 0x8ABF, 0x6F23, 0x97F8, 0x6F2B, 0x969F, + 0x6F2C, 0x92D0, 0x6F31, 0x9FF9, 0x6F32, 0x9FFB, 0x6F38, 0x9151, 0x6F3E, 0xE040, 0x6F3F, 0x9FF7, 0x6F41, 0x9FF1, 0x6F45, 0x8AC1, + 0x6F54, 0x8C89, 0x6F58, 0xE04E, 0x6F5B, 0xE049, 0x6F5C, 0x90F6, 0x6F5F, 0x8A83, 0x6F64, 0x8F81, 0x6F66, 0xE052, 0x6F6D, 0xE04B, + 0x6F6E, 0x92AA, 0x6F6F, 0xE048, 0x6F70, 0x92D7, 0x6F74, 0xE06B, 0x6F78, 0xE045, 0x6F7A, 0xE044, 0x6F7C, 0xE04D, 0x6F80, 0xE047, + 0x6F81, 0xE046, 0x6F82, 0xE04C, 0x6F84, 0x909F, 0x6F86, 0xE043, 0x6F88, 0xFB4B, 0x6F8E, 0xE04F, 0x6F91, 0xE050, 0x6F97, 0x8AC0, + 0x6FA1, 0xE055, 0x6FA3, 0xE054, 0x6FA4, 0xE056, 0x6FAA, 0xE059, 0x6FB1, 0x9362, 0x6FB3, 0xE053, 0x6FB5, 0xFB4C, 0x6FB9, 0xE057, + 0x6FC0, 0x8C83, 0x6FC1, 0x91F7, 0x6FC2, 0xE051, 0x6FC3, 0x945A, 0x6FC6, 0xE058, 0x6FD4, 0xE05D, 0x6FD5, 0xE05B, 0x6FD8, 0xE05E, + 0x6FDB, 0xE061, 0x6FDF, 0xE05A, 0x6FE0, 0x8D8A, 0x6FE1, 0x9447, 0x6FE4, 0x9FB7, 0x6FEB, 0x9794, 0x6FEC, 0xE05C, 0x6FEE, 0xE060, + 0x6FEF, 0x91F3, 0x6FF1, 0xE05F, 0x6FF3, 0xE04A, 0x6FF5, 0xFB4D, 0x6FF6, 0xE889, 0x6FFA, 0xE064, 0x6FFE, 0xE068, 0x7001, 0xE066, + 0x7005, 0xFB4E, 0x7007, 0xFB4F, 0x7009, 0xE062, 0x700B, 0xE063, 0x700F, 0xE067, 0x7011, 0xE065, 0x7015, 0x956D, 0x7018, 0xE06D, + 0x701A, 0xE06A, 0x701B, 0xE069, 0x701D, 0xE06C, 0x701E, 0x93D2, 0x701F, 0xE06E, 0x7026, 0x9295, 0x7027, 0x91EB, 0x7028, 0xFB50, + 0x702C, 0x90A3, 0x7030, 0xE06F, 0x7032, 0xE071, 0x703E, 0xE070, 0x704C, 0x9FF3, 0x7051, 0xE072, 0x7058, 0x93E5, 0x7063, 0xE073, + 0x706B, 0x89CE, 0x706F, 0x9394, 0x7070, 0x8A44, 0x7078, 0x8B84, 0x707C, 0x8EDC, 0x707D, 0x8DD0, 0x7085, 0xFB51, 0x7089, 0x9846, + 0x708A, 0x9086, 0x708E, 0x898A, 0x7092, 0xE075, 0x7099, 0xE074, 0x70AB, 0xFB52, 0x70AC, 0xE078, 0x70AD, 0x9259, 0x70AE, 0xE07B, + 0x70AF, 0xE076, 0x70B3, 0xE07A, 0x70B8, 0xE079, 0x70B9, 0x935F, 0x70BA, 0x88D7, 0x70BB, 0xFA62, 0x70C8, 0x97F3, 0x70CB, 0xE07D, + 0x70CF, 0x8947, 0x70D9, 0xE080, 0x70DD, 0xE07E, 0x70DF, 0xE07C, 0x70F1, 0xE077, 0x70F9, 0x9642, 0x70FD, 0xE082, 0x7104, 0xFB54, + 0x7109, 0xE081, 0x710F, 0xFB53, 0x7114, 0x898B, 0x7119, 0xE084, 0x711A, 0x95B0, 0x711C, 0xE083, 0x7121, 0x96B3, 0x7126, 0x8FC5, + 0x7136, 0x9152, 0x713C, 0x8FC4, 0x7146, 0xFB56, 0x7147, 0xFB57, 0x7149, 0x97F9, 0x714C, 0xE08A, 0x714E, 0x90F7, 0x7155, 0xE086, + 0x7156, 0xE08B, 0x7159, 0x898C, 0x715C, 0xFB55, 0x7162, 0xE089, 0x7164, 0x9481, 0x7165, 0xE085, 0x7166, 0xE088, 0x7167, 0x8FC6, + 0x7169, 0x94CF, 0x716C, 0xE08C, 0x716E, 0x8ECF, 0x717D, 0x90F8, 0x7184, 0xE08F, 0x7188, 0xE087, 0x718A, 0x8C46, 0x718F, 0xE08D, + 0x7194, 0x976F, 0x7195, 0xE090, 0x7199, 0xEAA4, 0x719F, 0x8F6E, 0x71A8, 0xE091, 0x71AC, 0xE092, 0x71B1, 0x944D, 0x71B9, 0xE094, + 0x71BE, 0xE095, 0x71C1, 0xFB59, 0x71C3, 0x9452, 0x71C8, 0x9395, 0x71C9, 0xE097, 0x71CE, 0xE099, 0x71D0, 0x97D3, 0x71D2, 0xE096, + 0x71D4, 0xE098, 0x71D5, 0x898D, 0x71D7, 0xE093, 0x71DF, 0x9A7A, 0x71E0, 0xE09A, 0x71E5, 0x9187, 0x71E6, 0x8E57, 0x71E7, 0xE09C, + 0x71EC, 0xE09B, 0x71ED, 0x9043, 0x71EE, 0x99D7, 0x71F5, 0xE09D, 0x71F9, 0xE09F, 0x71FB, 0xE08E, 0x71FC, 0xE09E, 0x71FE, 0xFB5A, + 0x71FF, 0xE0A0, 0x7206, 0x949A, 0x720D, 0xE0A1, 0x7210, 0xE0A2, 0x721B, 0xE0A3, 0x7228, 0xE0A4, 0x722A, 0x92DC, 0x722C, 0xE0A6, + 0x722D, 0xE0A5, 0x7230, 0xE0A7, 0x7232, 0xE0A8, 0x7235, 0x8EDD, 0x7236, 0x9583, 0x723A, 0x96EA, 0x723B, 0xE0A9, 0x723C, 0xE0AA, + 0x723D, 0x9175, 0x723E, 0x8EA2, 0x723F, 0xE0AB, 0x7240, 0xE0AC, 0x7246, 0xE0AD, 0x7247, 0x95D0, 0x7248, 0x94C5, 0x724B, 0xE0AE, + 0x724C, 0x9476, 0x7252, 0x92AB, 0x7258, 0xE0AF, 0x7259, 0x89E5, 0x725B, 0x8B8D, 0x725D, 0x96C4, 0x725F, 0x96B4, 0x7261, 0x89B2, + 0x7262, 0x9853, 0x7267, 0x9671, 0x7269, 0x95A8, 0x7272, 0x90B5, 0x7274, 0xE0B0, 0x7279, 0x93C1, 0x727D, 0x8CA1, 0x727E, 0xE0B1, + 0x7280, 0x8DD2, 0x7281, 0xE0B3, 0x7282, 0xE0B2, 0x7287, 0xE0B4, 0x7292, 0xE0B5, 0x7296, 0xE0B6, 0x72A0, 0x8B5D, 0x72A2, 0xE0B7, + 0x72A7, 0xE0B8, 0x72AC, 0x8CA2, 0x72AF, 0x94C6, 0x72B1, 0xFB5B, 0x72B2, 0xE0BA, 0x72B6, 0x8FF3, 0x72B9, 0xE0B9, 0x72BE, 0xFB5C, + 0x72C2, 0x8BB6, 0x72C3, 0xE0BB, 0x72C4, 0xE0BD, 0x72C6, 0xE0BC, 0x72CE, 0xE0BE, 0x72D0, 0x8CCF, 0x72D2, 0xE0BF, 0x72D7, 0x8BE7, + 0x72D9, 0x915F, 0x72DB, 0x8D9D, 0x72E0, 0xE0C1, 0x72E1, 0xE0C2, 0x72E2, 0xE0C0, 0x72E9, 0x8EEB, 0x72EC, 0x93C6, 0x72ED, 0x8BB7, + 0x72F7, 0xE0C4, 0x72F8, 0x924B, 0x72F9, 0xE0C3, 0x72FC, 0x9854, 0x72FD, 0x9482, 0x730A, 0xE0C7, 0x7316, 0xE0C9, 0x7317, 0xE0C6, + 0x731B, 0x96D2, 0x731C, 0xE0C8, 0x731D, 0xE0CA, 0x731F, 0x97C2, 0x7324, 0xFB5D, 0x7325, 0xE0CE, 0x7329, 0xE0CD, 0x732A, 0x9296, + 0x732B, 0x944C, 0x732E, 0x8CA3, 0x732F, 0xE0CC, 0x7334, 0xE0CB, 0x7336, 0x9750, 0x7337, 0x9751, 0x733E, 0xE0CF, 0x733F, 0x898E, + 0x7344, 0x8D96, 0x7345, 0x8E82, 0x734E, 0xE0D0, 0x734F, 0xE0D1, 0x7357, 0xE0D3, 0x7363, 0x8F62, 0x7368, 0xE0D5, 0x736A, 0xE0D4, + 0x7370, 0xE0D6, 0x7372, 0x8A6C, 0x7375, 0xE0D8, 0x7377, 0xFB5F, 0x7378, 0xE0D7, 0x737A, 0xE0DA, 0x737B, 0xE0D9, 0x7384, 0x8CBA, + 0x7387, 0x97A6, 0x7389, 0x8BCA, 0x738B, 0x89A4, 0x7396, 0x8BE8, 0x73A9, 0x8ADF, 0x73B2, 0x97E6, 0x73B3, 0xE0DC, 0x73BB, 0xE0DE, + 0x73BD, 0xFB60, 0x73C0, 0xE0DF, 0x73C2, 0x89CF, 0x73C8, 0xE0DB, 0x73C9, 0xFB61, 0x73CA, 0x8E58, 0x73CD, 0x92BF, 0x73CE, 0xE0DD, + 0x73D2, 0xFB64, 0x73D6, 0xFB62, 0x73DE, 0xE0E2, 0x73E0, 0x8EEC, 0x73E3, 0xFB63, 0x73E5, 0xE0E0, 0x73EA, 0x8C5D, 0x73ED, 0x94C7, + 0x73EE, 0xE0E1, 0x73F1, 0xE0FC, 0x73F5, 0xFB66, 0x73F8, 0xE0E7, 0x73FE, 0x8CBB, 0x7403, 0x8B85, 0x7405, 0xE0E4, 0x7406, 0x979D, + 0x7407, 0xFB65, 0x7409, 0x97AE, 0x7422, 0x91F4, 0x7425, 0xE0E6, 0x7426, 0xFB67, 0x7429, 0xFB69, 0x742A, 0xFB68, 0x742E, 0xFB6A, + 0x7432, 0xE0E8, 0x7433, 0x97D4, 0x7434, 0x8BD5, 0x7435, 0x94FA, 0x7436, 0x9469, 0x743A, 0xE0E9, 0x743F, 0xE0EB, 0x7441, 0xE0EE, + 0x7455, 0xE0EA, 0x7459, 0xE0ED, 0x745A, 0x8CE8, 0x745B, 0x896C, 0x745C, 0xE0EF, 0x745E, 0x9090, 0x745F, 0xE0EC, 0x7460, 0x97DA, + 0x7462, 0xFB6B, 0x7463, 0xE0F2, 0x7464, 0xEAA2, 0x7469, 0xE0F0, 0x746A, 0xE0F3, 0x746F, 0xE0E5, 0x7470, 0xE0F1, 0x7473, 0x8DBA, + 0x7476, 0xE0F4, 0x747E, 0xE0F5, 0x7483, 0x979E, 0x7489, 0xFB6C, 0x748B, 0xE0F6, 0x749E, 0xE0F7, 0x749F, 0xFB6D, 0x74A2, 0xE0E3, + 0x74A7, 0xE0F8, 0x74B0, 0x8AC2, 0x74BD, 0x8EA3, 0x74CA, 0xE0F9, 0x74CF, 0xE0FA, 0x74D4, 0xE0FB, 0x74DC, 0x895A, 0x74E0, 0xE140, + 0x74E2, 0x955A, 0x74E3, 0xE141, 0x74E6, 0x8AA2, 0x74E7, 0xE142, 0x74E9, 0xE143, 0x74EE, 0xE144, 0x74F0, 0xE146, 0x74F1, 0xE147, + 0x74F2, 0xE145, 0x74F6, 0x9572, 0x74F7, 0xE149, 0x74F8, 0xE148, 0x7501, 0xFB6E, 0x7503, 0xE14B, 0x7504, 0xE14A, 0x7505, 0xE14C, + 0x750C, 0xE14D, 0x750D, 0xE14F, 0x750E, 0xE14E, 0x7511, 0x8D99, 0x7513, 0xE151, 0x7515, 0xE150, 0x7518, 0x8AC3, 0x751A, 0x9072, + 0x751C, 0x935B, 0x751E, 0xE152, 0x751F, 0x90B6, 0x7523, 0x8E59, 0x7525, 0x8999, 0x7526, 0xE153, 0x7528, 0x9770, 0x752B, 0x95E1, + 0x752C, 0xE154, 0x752F, 0xFAA8, 0x7530, 0x9363, 0x7531, 0x9752, 0x7532, 0x8D62, 0x7533, 0x905C, 0x7537, 0x926A, 0x7538, 0x99B2, + 0x753A, 0x92AC, 0x753B, 0x89E6, 0x753C, 0xE155, 0x7544, 0xE156, 0x7546, 0xE15B, 0x7549, 0xE159, 0x754A, 0xE158, 0x754B, 0x9DC0, + 0x754C, 0x8A45, 0x754D, 0xE157, 0x754F, 0x88D8, 0x7551, 0x94A8, 0x7554, 0x94C8, 0x7559, 0x97AF, 0x755A, 0xE15C, 0x755B, 0xE15A, + 0x755C, 0x927B, 0x755D, 0x90A4, 0x7560, 0x94A9, 0x7562, 0x954C, 0x7564, 0xE15E, 0x7565, 0x97AA, 0x7566, 0x8C6C, 0x7567, 0xE15F, + 0x7569, 0xE15D, 0x756A, 0x94D4, 0x756B, 0xE160, 0x756D, 0xE161, 0x756F, 0xFB6F, 0x7570, 0x88D9, 0x7573, 0x8FF4, 0x7574, 0xE166, + 0x7576, 0xE163, 0x7577, 0x93EB, 0x7578, 0xE162, 0x757F, 0x8B45, 0x7582, 0xE169, 0x7586, 0xE164, 0x7587, 0xE165, 0x7589, 0xE168, + 0x758A, 0xE167, 0x758B, 0x9544, 0x758E, 0x9161, 0x758F, 0x9160, 0x7591, 0x8B5E, 0x7594, 0xE16A, 0x759A, 0xE16B, 0x759D, 0xE16C, + 0x75A3, 0xE16E, 0x75A5, 0xE16D, 0x75AB, 0x8975, 0x75B1, 0xE176, 0x75B2, 0x94E6, 0x75B3, 0xE170, 0x75B5, 0xE172, 0x75B8, 0xE174, + 0x75B9, 0x905D, 0x75BC, 0xE175, 0x75BD, 0xE173, 0x75BE, 0x8EBE, 0x75C2, 0xE16F, 0x75C3, 0xE171, 0x75C5, 0x9561, 0x75C7, 0x8FC7, + 0x75CA, 0xE178, 0x75CD, 0xE177, 0x75D2, 0xE179, 0x75D4, 0x8EA4, 0x75D5, 0x8DAD, 0x75D8, 0x9397, 0x75D9, 0xE17A, 0x75DB, 0x92C9, + 0x75DE, 0xE17C, 0x75E2, 0x979F, 0x75E3, 0xE17B, 0x75E9, 0x9189, 0x75F0, 0xE182, 0x75F2, 0xE184, 0x75F3, 0xE185, 0x75F4, 0x9273, + 0x75FA, 0xE183, 0x75FC, 0xE180, 0x75FE, 0xE17D, 0x75FF, 0xE17E, 0x7601, 0xE181, 0x7609, 0xE188, 0x760B, 0xE186, 0x760D, 0xE187, + 0x761F, 0xE189, 0x7620, 0xE18B, 0x7621, 0xE18C, 0x7622, 0xE18D, 0x7624, 0xE18E, 0x7627, 0xE18A, 0x7630, 0xE190, 0x7634, 0xE18F, + 0x763B, 0xE191, 0x7642, 0x97C3, 0x7646, 0xE194, 0x7647, 0xE192, 0x7648, 0xE193, 0x764C, 0x8AE0, 0x7652, 0x96FC, 0x7656, 0x95C8, + 0x7658, 0xE196, 0x765C, 0xE195, 0x7661, 0xE197, 0x7662, 0xE198, 0x7667, 0xE19C, 0x7668, 0xE199, 0x7669, 0xE19A, 0x766A, 0xE19B, + 0x766C, 0xE19D, 0x7670, 0xE19E, 0x7672, 0xE19F, 0x7676, 0xE1A0, 0x7678, 0xE1A1, 0x767A, 0x94AD, 0x767B, 0x936F, 0x767C, 0xE1A2, + 0x767D, 0x9492, 0x767E, 0x9553, 0x7680, 0xE1A3, 0x7682, 0xFB70, 0x7683, 0xE1A4, 0x7684, 0x9349, 0x7686, 0x8A46, 0x7687, 0x8D63, + 0x7688, 0xE1A5, 0x768B, 0xE1A6, 0x768E, 0xE1A7, 0x7690, 0x8E48, 0x7693, 0xE1A9, 0x7696, 0xE1A8, 0x7699, 0xE1AA, 0x769A, 0xE1AB, + 0x769B, 0xFB73, 0x769C, 0xFB71, 0x769E, 0xFB72, 0x76A6, 0xFB74, 0x76AE, 0x94E7, 0x76B0, 0xE1AC, 0x76B4, 0xE1AD, 0x76B7, 0xEA89, + 0x76B8, 0xE1AE, 0x76B9, 0xE1AF, 0x76BA, 0xE1B0, 0x76BF, 0x8E4D, 0x76C2, 0xE1B1, 0x76C3, 0x9475, 0x76C6, 0x967E, 0x76C8, 0x896D, + 0x76CA, 0x8976, 0x76CD, 0xE1B2, 0x76D2, 0xE1B4, 0x76D6, 0xE1B3, 0x76D7, 0x9390, 0x76DB, 0x90B7, 0x76DC, 0x9F58, 0x76DE, 0xE1B5, + 0x76DF, 0x96BF, 0x76E1, 0xE1B6, 0x76E3, 0x8AC4, 0x76E4, 0x94D5, 0x76E5, 0xE1B7, 0x76E7, 0xE1B8, 0x76EA, 0xE1B9, 0x76EE, 0x96DA, + 0x76F2, 0x96D3, 0x76F4, 0x92BC, 0x76F8, 0x918A, 0x76FB, 0xE1BB, 0x76FE, 0x8F82, 0x7701, 0x8FC8, 0x7704, 0xE1BE, 0x7707, 0xE1BD, + 0x7708, 0xE1BC, 0x7709, 0x94FB, 0x770B, 0x8AC5, 0x770C, 0x8CA7, 0x771B, 0xE1C4, 0x771E, 0xE1C1, 0x771F, 0x905E, 0x7720, 0x96B0, + 0x7724, 0xE1C0, 0x7725, 0xE1C2, 0x7726, 0xE1C3, 0x7729, 0xE1BF, 0x7737, 0xE1C5, 0x7738, 0xE1C6, 0x773A, 0x92AD, 0x773C, 0x8AE1, + 0x7740, 0x9285, 0x7746, 0xFB76, 0x7747, 0xE1C7, 0x775A, 0xE1C8, 0x775B, 0xE1CB, 0x7761, 0x9087, 0x7763, 0x93C2, 0x7765, 0xE1CC, + 0x7766, 0x9672, 0x7768, 0xE1C9, 0x776B, 0xE1CA, 0x7779, 0xE1CF, 0x777E, 0xE1CE, 0x777F, 0xE1CD, 0x778B, 0xE1D1, 0x778E, 0xE1D0, + 0x7791, 0xE1D2, 0x779E, 0xE1D4, 0x77A0, 0xE1D3, 0x77A5, 0x95CB, 0x77AC, 0x8F75, 0x77AD, 0x97C4, 0x77B0, 0xE1D5, 0x77B3, 0x93B5, + 0x77B6, 0xE1D6, 0x77B9, 0xE1D7, 0x77BB, 0xE1DB, 0x77BC, 0xE1D9, 0x77BD, 0xE1DA, 0x77BF, 0xE1D8, 0x77C7, 0xE1DC, 0x77CD, 0xE1DD, + 0x77D7, 0xE1DE, 0x77DA, 0xE1DF, 0x77DB, 0x96B5, 0x77DC, 0xE1E0, 0x77E2, 0x96EE, 0x77E3, 0xE1E1, 0x77E5, 0x926D, 0x77E7, 0x948A, + 0x77E9, 0x8BE9, 0x77ED, 0x925A, 0x77EE, 0xE1E2, 0x77EF, 0x8BB8, 0x77F3, 0x90CE, 0x77FC, 0xE1E3, 0x7802, 0x8DBB, 0x780C, 0xE1E4, + 0x7812, 0xE1E5, 0x7814, 0x8CA4, 0x7815, 0x8DD3, 0x7820, 0xE1E7, 0x7821, 0xFB78, 0x7825, 0x9375, 0x7826, 0x8DD4, 0x7827, 0x8B6D, + 0x7832, 0x9643, 0x7834, 0x946A, 0x783A, 0x9376, 0x783F, 0x8D7B, 0x7845, 0xE1E9, 0x784E, 0xFB79, 0x785D, 0x8FC9, 0x7864, 0xFB7A, + 0x786B, 0x97B0, 0x786C, 0x8D64, 0x786F, 0x8CA5, 0x7872, 0x94A1, 0x7874, 0xE1EB, 0x787A, 0xFB7B, 0x787C, 0xE1ED, 0x7881, 0x8CE9, + 0x7886, 0xE1EC, 0x7887, 0x92F4, 0x788C, 0xE1EF, 0x788D, 0x8A56, 0x788E, 0xE1EA, 0x7891, 0x94E8, 0x7893, 0x894F, 0x7895, 0x8DEA, + 0x7897, 0x9871, 0x789A, 0xE1EE, 0x78A3, 0xE1F0, 0x78A7, 0x95C9, 0x78A9, 0x90D7, 0x78AA, 0xE1F2, 0x78AF, 0xE1F3, 0x78B5, 0xE1F1, + 0x78BA, 0x8A6D, 0x78BC, 0xE1F9, 0x78BE, 0xE1F8, 0x78C1, 0x8EA5, 0x78C5, 0xE1FA, 0x78C6, 0xE1F5, 0x78CA, 0xE1FB, 0x78CB, 0xE1F6, + 0x78D0, 0x94D6, 0x78D1, 0xE1F4, 0x78D4, 0xE1F7, 0x78DA, 0xE241, 0x78E7, 0xE240, 0x78E8, 0x9681, 0x78EC, 0xE1FC, 0x78EF, 0x88E9, + 0x78F4, 0xE243, 0x78FD, 0xE242, 0x7901, 0x8FCA, 0x7907, 0xE244, 0x790E, 0x9162, 0x7911, 0xE246, 0x7912, 0xE245, 0x7919, 0xE247, + 0x7926, 0xE1E6, 0x792A, 0xE1E8, 0x792B, 0xE249, 0x792C, 0xE248, 0x7930, 0xFB7C, 0x793A, 0x8EA6, 0x793C, 0x97E7, 0x793E, 0x8ED0, + 0x7940, 0xE24A, 0x7941, 0x8C56, 0x7947, 0x8B5F, 0x7948, 0x8B46, 0x7949, 0x8E83, 0x7950, 0x9753, 0x7953, 0xE250, 0x7955, 0xE24F, + 0x7956, 0x9163, 0x7957, 0xE24C, 0x795A, 0xE24E, 0x795D, 0x8F6A, 0x795E, 0x905F, 0x795F, 0xE24D, 0x7960, 0xE24B, 0x7962, 0x9449, + 0x7965, 0x8FCB, 0x7968, 0x955B, 0x796D, 0x8DD5, 0x7977, 0x9398, 0x797A, 0xE251, 0x797F, 0xE252, 0x7980, 0xE268, 0x7981, 0x8BD6, + 0x7984, 0x985C, 0x7985, 0x9154, 0x798A, 0xE253, 0x798D, 0x89D0, 0x798E, 0x92F5, 0x798F, 0x959F, 0x7994, 0xFB81, 0x799B, 0xFB83, + 0x799D, 0xE254, 0x79A6, 0x8B9A, 0x79A7, 0xE255, 0x79AA, 0xE257, 0x79AE, 0xE258, 0x79B0, 0x9448, 0x79B3, 0xE259, 0x79B9, 0xE25A, + 0x79BA, 0xE25B, 0x79BD, 0x8BD7, 0x79BE, 0x89D1, 0x79BF, 0x93C3, 0x79C0, 0x8F47, 0x79C1, 0x8E84, 0x79C9, 0xE25C, 0x79CB, 0x8F48, + 0x79D1, 0x89C8, 0x79D2, 0x9562, 0x79D5, 0xE25D, 0x79D8, 0x94E9, 0x79DF, 0x9164, 0x79E1, 0xE260, 0x79E3, 0xE261, 0x79E4, 0x9489, + 0x79E6, 0x9060, 0x79E7, 0xE25E, 0x79E9, 0x9281, 0x79EC, 0xE25F, 0x79F0, 0x8FCC, 0x79FB, 0x88DA, 0x7A00, 0x8B48, 0x7A08, 0xE262, + 0x7A0B, 0x92F6, 0x7A0D, 0xE263, 0x7A0E, 0x90C5, 0x7A14, 0x96AB, 0x7A17, 0x9542, 0x7A18, 0xE264, 0x7A19, 0xE265, 0x7A1A, 0x9274, + 0x7A1C, 0x97C5, 0x7A1F, 0xE267, 0x7A20, 0xE266, 0x7A2E, 0x8EED, 0x7A31, 0xE269, 0x7A32, 0x88EE, 0x7A37, 0xE26C, 0x7A3B, 0xE26A, + 0x7A3C, 0x89D2, 0x7A3D, 0x8C6D, 0x7A3E, 0xE26B, 0x7A3F, 0x8D65, 0x7A40, 0x8D92, 0x7A42, 0x95E4, 0x7A43, 0xE26D, 0x7A46, 0x9673, + 0x7A49, 0xE26F, 0x7A4D, 0x90CF, 0x7A4E, 0x896E, 0x7A4F, 0x89B8, 0x7A50, 0x88AA, 0x7A57, 0xE26E, 0x7A61, 0xE270, 0x7A62, 0xE271, + 0x7A63, 0x8FF5, 0x7A69, 0xE272, 0x7A6B, 0x8A6E, 0x7A70, 0xE274, 0x7A74, 0x8C8A, 0x7A76, 0x8B86, 0x7A79, 0xE275, 0x7A7A, 0x8BF3, + 0x7A7D, 0xE276, 0x7A7F, 0x90FA, 0x7A81, 0x93CB, 0x7A83, 0x90DE, 0x7A84, 0x8DF3, 0x7A88, 0xE277, 0x7A92, 0x9282, 0x7A93, 0x918B, + 0x7A95, 0xE279, 0x7A96, 0xE27B, 0x7A97, 0xE278, 0x7A98, 0xE27A, 0x7A9F, 0x8C41, 0x7AA9, 0xE27C, 0x7AAA, 0x8C45, 0x7AAE, 0x8B87, + 0x7AAF, 0x9771, 0x7AB0, 0xE27E, 0x7AB6, 0xE280, 0x7ABA, 0x894D, 0x7ABF, 0xE283, 0x7AC3, 0x8A96, 0x7AC4, 0xE282, 0x7AC5, 0xE281, + 0x7AC7, 0xE285, 0x7AC8, 0xE27D, 0x7ACA, 0xE286, 0x7ACB, 0x97A7, 0x7ACD, 0xE287, 0x7ACF, 0xE288, 0x7AD1, 0xFB84, 0x7AD2, 0x9AF2, + 0x7AD3, 0xE28A, 0x7AD5, 0xE289, 0x7AD9, 0xE28B, 0x7ADA, 0xE28C, 0x7ADC, 0x97B3, 0x7ADD, 0xE28D, 0x7ADF, 0xE8ED, 0x7AE0, 0x8FCD, + 0x7AE1, 0xE28E, 0x7AE2, 0xE28F, 0x7AE3, 0x8F76, 0x7AE5, 0x93B6, 0x7AE6, 0xE290, 0x7AE7, 0xFB85, 0x7AEA, 0x9247, 0x7AEB, 0xFB87, + 0x7AED, 0xE291, 0x7AEF, 0x925B, 0x7AF0, 0xE292, 0x7AF6, 0x8BA3, 0x7AF8, 0x995E, 0x7AF9, 0x927C, 0x7AFA, 0x8EB1, 0x7AFF, 0x8AC6, + 0x7B02, 0xE293, 0x7B04, 0xE2A0, 0x7B06, 0xE296, 0x7B08, 0x8B88, 0x7B0A, 0xE295, 0x7B0B, 0xE2A2, 0x7B0F, 0xE294, 0x7B11, 0x8FCE, + 0x7B18, 0xE298, 0x7B19, 0xE299, 0x7B1B, 0x934A, 0x7B1E, 0xE29A, 0x7B20, 0x8A7D, 0x7B25, 0x9079, 0x7B26, 0x9584, 0x7B28, 0xE29C, + 0x7B2C, 0x91E6, 0x7B33, 0xE297, 0x7B35, 0xE29B, 0x7B36, 0xE29D, 0x7B39, 0x8DF9, 0x7B45, 0xE2A4, 0x7B46, 0x954D, 0x7B48, 0x94A4, + 0x7B49, 0x9399, 0x7B4B, 0x8BD8, 0x7B4C, 0xE2A3, 0x7B4D, 0xE2A1, 0x7B4F, 0x94B3, 0x7B50, 0xE29E, 0x7B51, 0x927D, 0x7B52, 0x939B, + 0x7B54, 0x939A, 0x7B56, 0x8DF4, 0x7B5D, 0xE2B6, 0x7B65, 0xE2A6, 0x7B67, 0xE2A8, 0x7B6C, 0xE2AB, 0x7B6E, 0xE2AC, 0x7B70, 0xE2A9, + 0x7B71, 0xE2AA, 0x7B74, 0xE2A7, 0x7B75, 0xE2A5, 0x7B7A, 0xE29F, 0x7B86, 0x95CD, 0x7B87, 0x89D3, 0x7B8B, 0xE2B3, 0x7B8D, 0xE2B0, + 0x7B8F, 0xE2B5, 0x7B92, 0xE2B4, 0x7B94, 0x9493, 0x7B95, 0x96A5, 0x7B97, 0x8E5A, 0x7B98, 0xE2AE, 0x7B99, 0xE2B7, 0x7B9A, 0xE2B2, + 0x7B9C, 0xE2B1, 0x7B9D, 0xE2AD, 0x7B9E, 0xFB88, 0x7B9F, 0xE2AF, 0x7BA1, 0x8AC7, 0x7BAA, 0x925C, 0x7BAD, 0x90FB, 0x7BB1, 0x94A0, + 0x7BB4, 0xE2BC, 0x7BB8, 0x94A2, 0x7BC0, 0x90DF, 0x7BC1, 0xE2B9, 0x7BC4, 0x94CD, 0x7BC6, 0xE2BD, 0x7BC7, 0x95D1, 0x7BC9, 0x927A, + 0x7BCB, 0xE2B8, 0x7BCC, 0xE2BA, 0x7BCF, 0xE2BB, 0x7BDD, 0xE2BE, 0x7BE0, 0x8EC2, 0x7BE4, 0x93C4, 0x7BE5, 0xE2C3, 0x7BE6, 0xE2C2, + 0x7BE9, 0xE2BF, 0x7BED, 0x9855, 0x7BF3, 0xE2C8, 0x7BF6, 0xE2CC, 0x7BF7, 0xE2C9, 0x7C00, 0xE2C5, 0x7C07, 0xE2C6, 0x7C0D, 0xE2CB, + 0x7C11, 0xE2C0, 0x7C12, 0x99D3, 0x7C13, 0xE2C7, 0x7C14, 0xE2C1, 0x7C17, 0xE2CA, 0x7C1F, 0xE2D0, 0x7C21, 0x8AC8, 0x7C23, 0xE2CD, + 0x7C27, 0xE2CE, 0x7C2A, 0xE2CF, 0x7C2B, 0xE2D2, 0x7C37, 0xE2D1, 0x7C38, 0x94F4, 0x7C3D, 0xE2D3, 0x7C3E, 0x97FA, 0x7C3F, 0x95EB, + 0x7C40, 0xE2D8, 0x7C43, 0xE2D5, 0x7C4C, 0xE2D4, 0x7C4D, 0x90D0, 0x7C4F, 0xE2D7, 0x7C50, 0xE2D9, 0x7C54, 0xE2D6, 0x7C56, 0xE2DD, + 0x7C58, 0xE2DA, 0x7C5F, 0xE2DB, 0x7C60, 0xE2C4, 0x7C64, 0xE2DC, 0x7C65, 0xE2DE, 0x7C6C, 0xE2DF, 0x7C73, 0x95C4, 0x7C75, 0xE2E0, + 0x7C7E, 0x96E0, 0x7C81, 0x8BCC, 0x7C82, 0x8C48, 0x7C83, 0xE2E1, 0x7C89, 0x95B2, 0x7C8B, 0x9088, 0x7C8D, 0x96AE, 0x7C90, 0xE2E2, + 0x7C92, 0x97B1, 0x7C95, 0x9494, 0x7C97, 0x9165, 0x7C98, 0x9453, 0x7C9B, 0x8F6C, 0x7C9F, 0x88BE, 0x7CA1, 0xE2E7, 0x7CA2, 0xE2E5, + 0x7CA4, 0xE2E3, 0x7CA5, 0x8A9F, 0x7CA7, 0x8FCF, 0x7CA8, 0xE2E8, 0x7CAB, 0xE2E6, 0x7CAD, 0xE2E4, 0x7CAE, 0xE2EC, 0x7CB1, 0xE2EB, + 0x7CB2, 0xE2EA, 0x7CB3, 0xE2E9, 0x7CB9, 0xE2ED, 0x7CBD, 0xE2EE, 0x7CBE, 0x90B8, 0x7CC0, 0xE2EF, 0x7CC2, 0xE2F1, 0x7CC5, 0xE2F0, + 0x7CCA, 0x8CD0, 0x7CCE, 0x9157, 0x7CD2, 0xE2F3, 0x7CD6, 0x939C, 0x7CD8, 0xE2F2, 0x7CDC, 0xE2F4, 0x7CDE, 0x95B3, 0x7CDF, 0x918C, + 0x7CE0, 0x8D66, 0x7CE2, 0xE2F5, 0x7CE7, 0x97C6, 0x7CEF, 0xE2F7, 0x7CF2, 0xE2F8, 0x7CF4, 0xE2F9, 0x7CF6, 0xE2FA, 0x7CF8, 0x8E85, + 0x7CFA, 0xE2FB, 0x7CFB, 0x8C6E, 0x7CFE, 0x8B8A, 0x7D00, 0x8B49, 0x7D02, 0xE340, 0x7D04, 0x96F1, 0x7D05, 0x8D67, 0x7D06, 0xE2FC, + 0x7D0A, 0xE343, 0x7D0B, 0x96E4, 0x7D0D, 0x945B, 0x7D10, 0x9552, 0x7D14, 0x8F83, 0x7D15, 0xE342, 0x7D17, 0x8ED1, 0x7D18, 0x8D68, + 0x7D19, 0x8E86, 0x7D1A, 0x8B89, 0x7D1B, 0x95B4, 0x7D1C, 0xE341, 0x7D20, 0x9166, 0x7D21, 0x9661, 0x7D22, 0x8DF5, 0x7D2B, 0x8E87, + 0x7D2C, 0x92DB, 0x7D2E, 0xE346, 0x7D2F, 0x97DD, 0x7D30, 0x8DD7, 0x7D32, 0xE347, 0x7D33, 0x9061, 0x7D35, 0xE349, 0x7D39, 0x8FD0, + 0x7D3A, 0x8DAE, 0x7D3F, 0xE348, 0x7D42, 0x8F49, 0x7D43, 0x8CBC, 0x7D44, 0x9167, 0x7D45, 0xE344, 0x7D46, 0xE34A, 0x7D48, 0xFB8A, + 0x7D4B, 0xE345, 0x7D4C, 0x8C6F, 0x7D4E, 0xE34D, 0x7D4F, 0xE351, 0x7D50, 0x8C8B, 0x7D56, 0xE34C, 0x7D5B, 0xE355, 0x7D5C, 0xFB8B, + 0x7D5E, 0x8D69, 0x7D61, 0x978D, 0x7D62, 0x88BA, 0x7D63, 0xE352, 0x7D66, 0x8B8B, 0x7D68, 0xE34F, 0x7D6E, 0xE350, 0x7D71, 0x939D, + 0x7D72, 0xE34E, 0x7D73, 0xE34B, 0x7D75, 0x8A47, 0x7D76, 0x90E2, 0x7D79, 0x8CA6, 0x7D7D, 0xE357, 0x7D89, 0xE354, 0x7D8F, 0xE356, + 0x7D93, 0xE353, 0x7D99, 0x8C70, 0x7D9A, 0x91B1, 0x7D9B, 0xE358, 0x7D9C, 0x918E, 0x7D9F, 0xE365, 0x7DA0, 0xFB8D, 0x7DA2, 0xE361, + 0x7DA3, 0xE35B, 0x7DAB, 0xE35F, 0x7DAC, 0x8EF8, 0x7DAD, 0x88DB, 0x7DAE, 0xE35A, 0x7DAF, 0xE362, 0x7DB0, 0xE366, 0x7DB1, 0x8D6A, + 0x7DB2, 0x96D4, 0x7DB4, 0x92D4, 0x7DB5, 0xE35C, 0x7DB7, 0xFB8C, 0x7DB8, 0xE364, 0x7DBA, 0xE359, 0x7DBB, 0x925D, 0x7DBD, 0xE35E, + 0x7DBE, 0x88BB, 0x7DBF, 0x96C8, 0x7DC7, 0xE35D, 0x7DCA, 0x8BD9, 0x7DCB, 0x94EA, 0x7DCF, 0x918D, 0x7DD1, 0x97CE, 0x7DD2, 0x8F8F, + 0x7DD5, 0xE38E, 0x7DD6, 0xFB8E, 0x7DD8, 0xE367, 0x7DDA, 0x90FC, 0x7DDC, 0xE363, 0x7DDD, 0xE368, 0x7DDE, 0xE36A, 0x7DE0, 0x92F7, + 0x7DE1, 0xE36D, 0x7DE4, 0xE369, 0x7DE8, 0x95D2, 0x7DE9, 0x8AC9, 0x7DEC, 0x96C9, 0x7DEF, 0x88DC, 0x7DF2, 0xE36C, 0x7DF4, 0x97FB, + 0x7DFB, 0xE36B, 0x7E01, 0x898F, 0x7E04, 0x93EA, 0x7E05, 0xE36E, 0x7E09, 0xE375, 0x7E0A, 0xE36F, 0x7E0B, 0xE376, 0x7E12, 0xE372, + 0x7E1B, 0x949B, 0x7E1E, 0x8EC8, 0x7E1F, 0xE374, 0x7E21, 0xE371, 0x7E22, 0xE377, 0x7E23, 0xE370, 0x7E26, 0x8F63, 0x7E2B, 0x9644, + 0x7E2E, 0x8F6B, 0x7E31, 0xE373, 0x7E32, 0xE380, 0x7E35, 0xE37B, 0x7E37, 0xE37E, 0x7E39, 0xE37C, 0x7E3A, 0xE381, 0x7E3B, 0xE37A, + 0x7E3D, 0xE360, 0x7E3E, 0x90D1, 0x7E41, 0x94C9, 0x7E43, 0xE37D, 0x7E46, 0xE378, 0x7E4A, 0x9140, 0x7E4B, 0x8C71, 0x7E4D, 0x8F4A, + 0x7E52, 0xFB8F, 0x7E54, 0x9044, 0x7E55, 0x9155, 0x7E56, 0xE384, 0x7E59, 0xE386, 0x7E5A, 0xE387, 0x7E5D, 0xE383, 0x7E5E, 0xE385, + 0x7E66, 0xE379, 0x7E67, 0xE382, 0x7E69, 0xE38A, 0x7E6A, 0xE389, 0x7E6D, 0x969A, 0x7E70, 0x8C4A, 0x7E79, 0xE388, 0x7E7B, 0xE38C, + 0x7E7C, 0xE38B, 0x7E7D, 0xE38F, 0x7E7F, 0xE391, 0x7E82, 0x8E5B, 0x7E83, 0xE38D, 0x7E88, 0xE392, 0x7E89, 0xE393, 0x7E8A, 0xFA5C, + 0x7E8C, 0xE394, 0x7E8E, 0xE39A, 0x7E8F, 0x935A, 0x7E90, 0xE396, 0x7E92, 0xE395, 0x7E93, 0xE397, 0x7E94, 0xE398, 0x7E96, 0xE399, + 0x7E9B, 0xE39B, 0x7E9C, 0xE39C, 0x7F36, 0x8ACA, 0x7F38, 0xE39D, 0x7F3A, 0xE39E, 0x7F45, 0xE39F, 0x7F47, 0xFB90, 0x7F4C, 0xE3A0, + 0x7F4D, 0xE3A1, 0x7F4E, 0xE3A2, 0x7F50, 0xE3A3, 0x7F51, 0xE3A4, 0x7F54, 0xE3A6, 0x7F55, 0xE3A5, 0x7F58, 0xE3A7, 0x7F5F, 0xE3A8, + 0x7F60, 0xE3A9, 0x7F67, 0xE3AC, 0x7F68, 0xE3AA, 0x7F69, 0xE3AB, 0x7F6A, 0x8DDF, 0x7F6B, 0x8C72, 0x7F6E, 0x9275, 0x7F70, 0x94B1, + 0x7F72, 0x8F90, 0x7F75, 0x946C, 0x7F77, 0x94EB, 0x7F78, 0xE3AD, 0x7F79, 0x9CEB, 0x7F82, 0xE3AE, 0x7F83, 0xE3B0, 0x7F85, 0x9785, + 0x7F86, 0xE3AF, 0x7F87, 0xE3B2, 0x7F88, 0xE3B1, 0x7F8A, 0x9772, 0x7F8C, 0xE3B3, 0x7F8E, 0x94FC, 0x7F94, 0xE3B4, 0x7F9A, 0xE3B7, + 0x7F9D, 0xE3B6, 0x7F9E, 0xE3B5, 0x7FA1, 0xFB91, 0x7FA3, 0xE3B8, 0x7FA4, 0x8C51, 0x7FA8, 0x9141, 0x7FA9, 0x8B60, 0x7FAE, 0xE3BC, + 0x7FAF, 0xE3B9, 0x7FB2, 0xE3BA, 0x7FB6, 0xE3BD, 0x7FB8, 0xE3BE, 0x7FB9, 0xE3BB, 0x7FBD, 0x8948, 0x7FC1, 0x89A5, 0x7FC5, 0xE3C0, + 0x7FC6, 0xE3C1, 0x7FCA, 0xE3C2, 0x7FCC, 0x9782, 0x7FD2, 0x8F4B, 0x7FD4, 0xE3C4, 0x7FD5, 0xE3C3, 0x7FE0, 0x9089, 0x7FE1, 0xE3C5, + 0x7FE6, 0xE3C6, 0x7FE9, 0xE3C7, 0x7FEB, 0x8AE3, 0x7FF0, 0x8ACB, 0x7FF3, 0xE3C8, 0x7FF9, 0xE3C9, 0x7FFB, 0x967C, 0x7FFC, 0x9783, + 0x8000, 0x9773, 0x8001, 0x9856, 0x8003, 0x8D6C, 0x8004, 0xE3CC, 0x8005, 0x8ED2, 0x8006, 0xE3CB, 0x800B, 0xE3CD, 0x800C, 0x8EA7, + 0x8010, 0x91CF, 0x8012, 0xE3CE, 0x8015, 0x8D6B, 0x8017, 0x96D5, 0x8018, 0xE3CF, 0x8019, 0xE3D0, 0x801C, 0xE3D1, 0x8021, 0xE3D2, + 0x8028, 0xE3D3, 0x8033, 0x8EA8, 0x8036, 0x96EB, 0x803B, 0xE3D5, 0x803D, 0x925E, 0x803F, 0xE3D4, 0x8046, 0xE3D7, 0x804A, 0xE3D6, + 0x8052, 0xE3D8, 0x8056, 0x90B9, 0x8058, 0xE3D9, 0x805A, 0xE3DA, 0x805E, 0x95B7, 0x805F, 0xE3DB, 0x8061, 0x918F, 0x8062, 0xE3DC, + 0x8068, 0xE3DD, 0x806F, 0x97FC, 0x8070, 0xE3E0, 0x8072, 0xE3DF, 0x8073, 0xE3DE, 0x8074, 0x92AE, 0x8076, 0xE3E1, 0x8077, 0x9045, + 0x8079, 0xE3E2, 0x807D, 0xE3E3, 0x807E, 0x9857, 0x807F, 0xE3E4, 0x8084, 0xE3E5, 0x8085, 0xE3E7, 0x8086, 0xE3E6, 0x8087, 0x94A3, + 0x8089, 0x93F7, 0x808B, 0x985D, 0x808C, 0x94A7, 0x8093, 0xE3E9, 0x8096, 0x8FD1, 0x8098, 0x9549, 0x809A, 0xE3EA, 0x809B, 0xE3E8, + 0x809D, 0x8ACC, 0x80A1, 0x8CD2, 0x80A2, 0x8E88, 0x80A5, 0x94EC, 0x80A9, 0x8CA8, 0x80AA, 0x9662, 0x80AC, 0xE3ED, 0x80AD, 0xE3EB, + 0x80AF, 0x8D6D, 0x80B1, 0x8D6E, 0x80B2, 0x88E7, 0x80B4, 0x8DE6, 0x80BA, 0x9478, 0x80C3, 0x88DD, 0x80C4, 0xE3F2, 0x80C6, 0x925F, + 0x80CC, 0x9477, 0x80CE, 0x91D9, 0x80D6, 0xE3F4, 0x80D9, 0xE3F0, 0x80DA, 0xE3F3, 0x80DB, 0xE3EE, 0x80DD, 0xE3F1, 0x80DE, 0x9645, + 0x80E1, 0x8CD3, 0x80E4, 0x88FB, 0x80E5, 0xE3EF, 0x80EF, 0xE3F6, 0x80F1, 0xE3F7, 0x80F4, 0x93B7, 0x80F8, 0x8BB9, 0x80FC, 0xE445, + 0x80FD, 0x945C, 0x8102, 0x8E89, 0x8105, 0x8BBA, 0x8106, 0x90C6, 0x8107, 0x9865, 0x8108, 0x96AC, 0x8109, 0xE3F5, 0x810A, 0x90D2, + 0x811A, 0x8B72, 0x811B, 0xE3F8, 0x8123, 0xE3FA, 0x8129, 0xE3F9, 0x812F, 0xE3FB, 0x8131, 0x9245, 0x8133, 0x945D, 0x8139, 0x92AF, + 0x813E, 0xE442, 0x8146, 0xE441, 0x814B, 0xE3FC, 0x814E, 0x9074, 0x8150, 0x9585, 0x8151, 0xE444, 0x8153, 0xE443, 0x8154, 0x8D6F, + 0x8155, 0x9872, 0x815F, 0xE454, 0x8165, 0xE448, 0x8166, 0xE449, 0x816B, 0x8EEE, 0x816E, 0xE447, 0x8170, 0x8D98, 0x8171, 0xE446, + 0x8174, 0xE44A, 0x8178, 0x92B0, 0x8179, 0x95A0, 0x817A, 0x9142, 0x817F, 0x91DA, 0x8180, 0xE44E, 0x8182, 0xE44F, 0x8183, 0xE44B, + 0x8188, 0xE44C, 0x818A, 0xE44D, 0x818F, 0x8D70, 0x8193, 0xE455, 0x8195, 0xE451, 0x819A, 0x9586, 0x819C, 0x968C, 0x819D, 0x9547, + 0x81A0, 0xE450, 0x81A3, 0xE453, 0x81A4, 0xE452, 0x81A8, 0x9663, 0x81A9, 0xE456, 0x81B0, 0xE457, 0x81B3, 0x9156, 0x81B5, 0xE458, + 0x81B8, 0xE45A, 0x81BA, 0xE45E, 0x81BD, 0xE45B, 0x81BE, 0xE459, 0x81BF, 0x945E, 0x81C0, 0xE45C, 0x81C2, 0xE45D, 0x81C6, 0x89B0, + 0x81C8, 0xE464, 0x81C9, 0xE45F, 0x81CD, 0xE460, 0x81D1, 0xE461, 0x81D3, 0x919F, 0x81D8, 0xE463, 0x81D9, 0xE462, 0x81DA, 0xE465, + 0x81DF, 0xE466, 0x81E0, 0xE467, 0x81E3, 0x9062, 0x81E5, 0x89E7, 0x81E7, 0xE468, 0x81E8, 0x97D5, 0x81EA, 0x8EA9, 0x81ED, 0x8F4C, + 0x81F3, 0x8E8A, 0x81F4, 0x9276, 0x81FA, 0xE469, 0x81FB, 0xE46A, 0x81FC, 0x8950, 0x81FE, 0xE46B, 0x8201, 0xE46C, 0x8202, 0xE46D, + 0x8205, 0xE46E, 0x8207, 0xE46F, 0x8208, 0x8BBB, 0x8209, 0x9DA8, 0x820A, 0xE470, 0x820C, 0x90E3, 0x820D, 0xE471, 0x820E, 0x8EC9, + 0x8210, 0xE472, 0x8212, 0x98AE, 0x8216, 0xE473, 0x8217, 0x95DC, 0x8218, 0x8ADA, 0x821B, 0x9143, 0x821C, 0x8F77, 0x821E, 0x9591, + 0x821F, 0x8F4D, 0x8229, 0xE474, 0x822A, 0x8D71, 0x822B, 0xE475, 0x822C, 0x94CA, 0x822E, 0xE484, 0x8233, 0xE477, 0x8235, 0x91C7, + 0x8236, 0x9495, 0x8237, 0x8CBD, 0x8238, 0xE476, 0x8239, 0x9144, 0x8240, 0xE478, 0x8247, 0x92F8, 0x8258, 0xE47A, 0x8259, 0xE479, + 0x825A, 0xE47C, 0x825D, 0xE47B, 0x825F, 0xE47D, 0x8262, 0xE480, 0x8264, 0xE47E, 0x8266, 0x8ACD, 0x8268, 0xE481, 0x826A, 0xE482, + 0x826B, 0xE483, 0x826E, 0x8DAF, 0x826F, 0x97C7, 0x8271, 0xE485, 0x8272, 0x9046, 0x8276, 0x8990, 0x8277, 0xE486, 0x8278, 0xE487, + 0x827E, 0xE488, 0x828B, 0x88F0, 0x828D, 0xE489, 0x8292, 0xE48A, 0x8299, 0x9587, 0x829D, 0x8EC5, 0x829F, 0xE48C, 0x82A5, 0x8A48, + 0x82A6, 0x88B0, 0x82AB, 0xE48B, 0x82AC, 0xE48E, 0x82AD, 0x946D, 0x82AF, 0x9063, 0x82B1, 0x89D4, 0x82B3, 0x9646, 0x82B8, 0x8C7C, + 0x82B9, 0x8BDA, 0x82BB, 0xE48D, 0x82BD, 0x89E8, 0x82C5, 0x8AA1, 0x82D1, 0x8991, 0x82D2, 0xE492, 0x82D3, 0x97E8, 0x82D4, 0x91DB, + 0x82D7, 0x9563, 0x82D9, 0xE49E, 0x82DB, 0x89D5, 0x82DC, 0xE49C, 0x82DE, 0xE49A, 0x82DF, 0xE491, 0x82E1, 0xE48F, 0x82E3, 0xE490, + 0x82E5, 0x8EE1, 0x82E6, 0x8BEA, 0x82E7, 0x9297, 0x82EB, 0x93CF, 0x82F1, 0x8970, 0x82F3, 0xE494, 0x82F4, 0xE493, 0x82F9, 0xE499, + 0x82FA, 0xE495, 0x82FB, 0xE498, 0x8301, 0xFB93, 0x8302, 0x96CE, 0x8303, 0xE497, 0x8304, 0x89D6, 0x8305, 0x8A9D, 0x8306, 0xE49B, + 0x8309, 0xE49D, 0x830E, 0x8C73, 0x8316, 0xE4A1, 0x8317, 0xE4AA, 0x8318, 0xE4AB, 0x831C, 0x88A9, 0x8323, 0xE4B2, 0x8328, 0x88EF, + 0x832B, 0xE4A9, 0x832F, 0xE4A8, 0x8331, 0xE4A3, 0x8332, 0xE4A2, 0x8334, 0xE4A0, 0x8335, 0xE49F, 0x8336, 0x9283, 0x8338, 0x91F9, + 0x8339, 0xE4A5, 0x8340, 0xE4A4, 0x8345, 0xE4A7, 0x8349, 0x9190, 0x834A, 0x8C74, 0x834F, 0x8960, 0x8350, 0xE4A6, 0x8352, 0x8D72, + 0x8358, 0x9191, 0x8362, 0xFB94, 0x8373, 0xE4B8, 0x8375, 0xE4B9, 0x8377, 0x89D7, 0x837B, 0x89AC, 0x837C, 0xE4B6, 0x837F, 0xFB95, + 0x8385, 0xE4AC, 0x8387, 0xE4B4, 0x8389, 0xE4BB, 0x838A, 0xE4B5, 0x838E, 0xE4B3, 0x8393, 0xE496, 0x8396, 0xE4B1, 0x839A, 0xE4AD, + 0x839E, 0x8ACE, 0x839F, 0xE4AF, 0x83A0, 0xE4BA, 0x83A2, 0xE4B0, 0x83A8, 0xE4BC, 0x83AA, 0xE4AE, 0x83AB, 0x949C, 0x83B1, 0x9789, + 0x83B5, 0xE4B7, 0x83BD, 0xE4CD, 0x83C1, 0xE4C5, 0x83C5, 0x909B, 0x83C7, 0xFB96, 0x83CA, 0x8B65, 0x83CC, 0x8BDB, 0x83CE, 0xE4C0, + 0x83D3, 0x89D9, 0x83D6, 0x8FD2, 0x83D8, 0xE4C3, 0x83DC, 0x8DD8, 0x83DF, 0x9370, 0x83E0, 0xE4C8, 0x83E9, 0x95EC, 0x83EB, 0xE4BF, + 0x83EF, 0x89D8, 0x83F0, 0x8CD4, 0x83F1, 0x9548, 0x83F2, 0xE4C9, 0x83F4, 0xE4BD, 0x83F6, 0xFB97, 0x83F7, 0xE4C6, 0x83FB, 0xE4D0, + 0x83FD, 0xE4C1, 0x8403, 0xE4C2, 0x8404, 0x93B8, 0x8407, 0xE4C7, 0x840B, 0xE4C4, 0x840C, 0x9647, 0x840D, 0xE4CA, 0x840E, 0x88DE, + 0x8413, 0xE4BE, 0x8420, 0xE4CC, 0x8422, 0xE4CB, 0x8429, 0x948B, 0x842A, 0xE4D2, 0x842C, 0xE4DD, 0x8431, 0x8A9E, 0x8435, 0xE4E0, + 0x8438, 0xE4CE, 0x843C, 0xE4D3, 0x843D, 0x978E, 0x8446, 0xE4DC, 0x8448, 0xFB98, 0x8449, 0x9774, 0x844E, 0x97A8, 0x8457, 0x9298, + 0x845B, 0x8A8B, 0x8461, 0x9592, 0x8462, 0xE4E2, 0x8463, 0x939F, 0x8466, 0x88AF, 0x8469, 0xE4DB, 0x846B, 0xE4D7, 0x846C, 0x9192, + 0x846D, 0xE4D1, 0x846E, 0xE4D9, 0x846F, 0xE4DE, 0x8471, 0x944B, 0x8475, 0x88A8, 0x8477, 0xE4D6, 0x8479, 0xE4DF, 0x847A, 0x9598, + 0x8482, 0xE4DA, 0x8484, 0xE4D5, 0x848B, 0x8FD3, 0x8490, 0x8F4E, 0x8494, 0x8EAA, 0x8499, 0x96D6, 0x849C, 0x9566, 0x849F, 0xE4E5, + 0x84A1, 0xE4EE, 0x84AD, 0xE4D8, 0x84B2, 0x8A97, 0x84B4, 0xFB99, 0x84B8, 0x8FF6, 0x84B9, 0xE4E3, 0x84BB, 0xE4E8, 0x84BC, 0x9193, + 0x84BF, 0xE4E4, 0x84C1, 0xE4EB, 0x84C4, 0x927E, 0x84C6, 0xE4EC, 0x84C9, 0x9775, 0x84CA, 0xE4E1, 0x84CB, 0x8A57, 0x84CD, 0xE4E7, + 0x84D0, 0xE4EA, 0x84D1, 0x96AA, 0x84D6, 0xE4ED, 0x84D9, 0xE4E6, 0x84DA, 0xE4E9, 0x84DC, 0xFA60, 0x84EC, 0x9648, 0x84EE, 0x9840, + 0x84F4, 0xE4F1, 0x84FC, 0xE4F8, 0x84FF, 0xE4F0, 0x8500, 0x8EC1, 0x8506, 0xE4CF, 0x8511, 0x95CC, 0x8513, 0x96A0, 0x8514, 0xE4F7, + 0x8515, 0xE4F6, 0x8517, 0xE4F2, 0x8518, 0xE4F3, 0x851A, 0x8955, 0x851F, 0xE4F5, 0x8521, 0xE4EF, 0x8526, 0x92D3, 0x852C, 0xE4F4, + 0x852D, 0x88FC, 0x8535, 0x91A0, 0x853D, 0x95C1, 0x8540, 0xE4F9, 0x8541, 0xE540, 0x8543, 0x94D7, 0x8548, 0xE4FC, 0x8549, 0x8FD4, + 0x854A, 0x8EC7, 0x854B, 0xE542, 0x854E, 0x8BBC, 0x8553, 0xFB9A, 0x8555, 0xE543, 0x8557, 0x9599, 0x8558, 0xE4FB, 0x8559, 0xFB9B, + 0x855A, 0xE4D4, 0x8563, 0xE4FA, 0x8568, 0x986E, 0x8569, 0x93A0, 0x856A, 0x9593, 0x856B, 0xFB9C, 0x856D, 0xE54A, 0x8577, 0xE550, + 0x857E, 0xE551, 0x8580, 0xE544, 0x8584, 0x9496, 0x8587, 0xE54E, 0x8588, 0xE546, 0x858A, 0xE548, 0x8590, 0xE552, 0x8591, 0xE547, + 0x8594, 0xE54B, 0x8597, 0x8992, 0x8599, 0x93E3, 0x859B, 0xE54C, 0x859C, 0xE54F, 0x85A4, 0xE545, 0x85A6, 0x9145, 0x85A8, 0xE549, + 0x85A9, 0x8E46, 0x85AA, 0x9064, 0x85AB, 0x8C4F, 0x85AC, 0x96F2, 0x85AE, 0x96F7, 0x85AF, 0x8F92, 0x85B0, 0xFB9E, 0x85B9, 0xE556, + 0x85BA, 0xE554, 0x85C1, 0x986D, 0x85C9, 0xE553, 0x85CD, 0x9795, 0x85CF, 0xE555, 0x85D0, 0xE557, 0x85D5, 0xE558, 0x85DC, 0xE55B, + 0x85DD, 0xE559, 0x85E4, 0x93A1, 0x85E5, 0xE55A, 0x85E9, 0x94CB, 0x85EA, 0xE54D, 0x85F7, 0x8F93, 0x85F9, 0xE55C, 0x85FA, 0xE561, + 0x85FB, 0x9194, 0x85FE, 0xE560, 0x8602, 0xE541, 0x8606, 0xE562, 0x8607, 0x9168, 0x860A, 0xE55D, 0x860B, 0xE55F, 0x8613, 0xE55E, + 0x8616, 0x9F50, 0x8617, 0x9F41, 0x861A, 0xE564, 0x8622, 0xE563, 0x862D, 0x9796, 0x862F, 0xE1BA, 0x8630, 0xE565, 0x863F, 0xE566, + 0x864D, 0xE567, 0x864E, 0x8CD5, 0x8650, 0x8B73, 0x8654, 0xE569, 0x8655, 0x997C, 0x865A, 0x8B95, 0x865C, 0x97B8, 0x865E, 0x8BF1, + 0x865F, 0xE56A, 0x8667, 0xE56B, 0x866B, 0x928E, 0x8671, 0xE56C, 0x8679, 0x93F8, 0x867B, 0x88B8, 0x868A, 0x89E1, 0x868B, 0xE571, + 0x868C, 0xE572, 0x8693, 0xE56D, 0x8695, 0x8E5C, 0x86A3, 0xE56E, 0x86A4, 0x9461, 0x86A9, 0xE56F, 0x86AA, 0xE570, 0x86AB, 0xE57A, + 0x86AF, 0xE574, 0x86B0, 0xE577, 0x86B6, 0xE573, 0x86C4, 0xE575, 0x86C6, 0xE576, 0x86C7, 0x8ED6, 0x86C9, 0xE578, 0x86CB, 0x9260, + 0x86CD, 0x8C75, 0x86CE, 0x8A61, 0x86D4, 0xE57B, 0x86D9, 0x8A5E, 0x86DB, 0xE581, 0x86DE, 0xE57C, 0x86DF, 0xE580, 0x86E4, 0x94B8, + 0x86E9, 0xE57D, 0x86EC, 0xE57E, 0x86ED, 0x9567, 0x86EE, 0x94D8, 0x86EF, 0xE582, 0x86F8, 0x91FB, 0x86F9, 0xE58C, 0x86FB, 0xE588, + 0x86FE, 0x89E9, 0x8700, 0xE586, 0x8702, 0x9649, 0x8703, 0xE587, 0x8706, 0xE584, 0x8708, 0xE585, 0x8709, 0xE58A, 0x870A, 0xE58D, + 0x870D, 0xE58B, 0x8711, 0xE589, 0x8712, 0xE583, 0x8718, 0x9277, 0x871A, 0xE594, 0x871C, 0x96A8, 0x8725, 0xE592, 0x8729, 0xE593, + 0x8734, 0xE58E, 0x8737, 0xE590, 0x873B, 0xE591, 0x873F, 0xE58F, 0x8749, 0x90E4, 0x874B, 0x9858, 0x874C, 0xE598, 0x874E, 0xE599, + 0x8753, 0xE59F, 0x8755, 0x9049, 0x8757, 0xE59B, 0x8759, 0xE59E, 0x875F, 0xE596, 0x8760, 0xE595, 0x8763, 0xE5A0, 0x8766, 0x89DA, + 0x8768, 0xE59C, 0x876A, 0xE5A1, 0x876E, 0xE59D, 0x8774, 0xE59A, 0x8776, 0x92B1, 0x8778, 0xE597, 0x877F, 0x9488, 0x8782, 0xE5A5, + 0x878D, 0x975A, 0x879F, 0xE5A4, 0x87A2, 0xE5A3, 0x87AB, 0xE5AC, 0x87AF, 0xE5A6, 0x87B3, 0xE5AE, 0x87BA, 0x9786, 0x87BB, 0xE5B1, + 0x87BD, 0xE5A8, 0x87C0, 0xE5A9, 0x87C4, 0xE5AD, 0x87C6, 0xE5B0, 0x87C7, 0xE5AF, 0x87CB, 0xE5A7, 0x87D0, 0xE5AA, 0x87D2, 0xE5BB, + 0x87E0, 0xE5B4, 0x87EF, 0xE5B2, 0x87F2, 0xE5B3, 0x87F6, 0xE5B8, 0x87F7, 0xE5B9, 0x87F9, 0x8A49, 0x87FB, 0x8B61, 0x87FE, 0xE5B7, + 0x8805, 0xE5A2, 0x8807, 0xFBA1, 0x880D, 0xE5B6, 0x880E, 0xE5BA, 0x880F, 0xE5B5, 0x8811, 0xE5BC, 0x8815, 0xE5BE, 0x8816, 0xE5BD, + 0x8821, 0xE5C0, 0x8822, 0xE5BF, 0x8823, 0xE579, 0x8827, 0xE5C4, 0x8831, 0xE5C1, 0x8836, 0xE5C2, 0x8839, 0xE5C3, 0x883B, 0xE5C5, + 0x8840, 0x8C8C, 0x8842, 0xE5C7, 0x8844, 0xE5C6, 0x8846, 0x8F4F, 0x884C, 0x8D73, 0x884D, 0x9FA5, 0x8852, 0xE5C8, 0x8853, 0x8F70, + 0x8857, 0x8A58, 0x8859, 0xE5C9, 0x885B, 0x8971, 0x885D, 0x8FD5, 0x885E, 0xE5CA, 0x8861, 0x8D74, 0x8862, 0xE5CB, 0x8863, 0x88DF, + 0x8868, 0x955C, 0x886B, 0xE5CC, 0x8870, 0x908A, 0x8872, 0xE5D3, 0x8875, 0xE5D0, 0x8877, 0x928F, 0x887D, 0xE5D1, 0x887E, 0xE5CE, + 0x887F, 0x8BDC, 0x8881, 0xE5CD, 0x8882, 0xE5D4, 0x8888, 0x8C55, 0x888B, 0x91DC, 0x888D, 0xE5DA, 0x8892, 0xE5D6, 0x8896, 0x91B3, + 0x8897, 0xE5D5, 0x8899, 0xE5D8, 0x889E, 0xE5CF, 0x88A2, 0xE5D9, 0x88A4, 0xE5DB, 0x88AB, 0x94ED, 0x88AE, 0xE5D7, 0x88B0, 0xE5DC, + 0x88B1, 0xE5DE, 0x88B4, 0x8CD1, 0x88B5, 0xE5D2, 0x88B7, 0x88BF, 0x88BF, 0xE5DD, 0x88C1, 0x8DD9, 0x88C2, 0x97F4, 0x88C3, 0xE5DF, + 0x88C4, 0xE5E0, 0x88C5, 0x9195, 0x88CF, 0x97A0, 0x88D4, 0xE5E1, 0x88D5, 0x9754, 0x88D8, 0xE5E2, 0x88D9, 0xE5E3, 0x88DC, 0x95E2, + 0x88DD, 0xE5E4, 0x88DF, 0x8DBE, 0x88E1, 0x97A1, 0x88E8, 0xE5E9, 0x88F2, 0xE5EA, 0x88F3, 0x8FD6, 0x88F4, 0xE5E8, 0x88F5, 0xFBA2, + 0x88F8, 0x9787, 0x88F9, 0xE5E5, 0x88FC, 0xE5E7, 0x88FD, 0x90BB, 0x88FE, 0x909E, 0x8902, 0xE5E6, 0x8904, 0xE5EB, 0x8907, 0x95A1, + 0x890A, 0xE5ED, 0x890C, 0xE5EC, 0x8910, 0x8A8C, 0x8912, 0x964A, 0x8913, 0xE5EE, 0x891C, 0xFA5D, 0x891D, 0xE5FA, 0x891E, 0xE5F0, + 0x8925, 0xE5F1, 0x892A, 0xE5F2, 0x892B, 0xE5F3, 0x8936, 0xE5F7, 0x8938, 0xE5F8, 0x893B, 0xE5F6, 0x8941, 0xE5F4, 0x8943, 0xE5EF, + 0x8944, 0xE5F5, 0x894C, 0xE5F9, 0x894D, 0xE8B5, 0x8956, 0x89A6, 0x895E, 0xE5FC, 0x895F, 0x8BDD, 0x8960, 0xE5FB, 0x8964, 0xE641, + 0x8966, 0xE640, 0x896A, 0xE643, 0x896D, 0xE642, 0x896F, 0xE644, 0x8972, 0x8F50, 0x8974, 0xE645, 0x8977, 0xE646, 0x897E, 0xE647, + 0x897F, 0x90BC, 0x8981, 0x9776, 0x8983, 0xE648, 0x8986, 0x95A2, 0x8987, 0x9465, 0x8988, 0xE649, 0x898A, 0xE64A, 0x898B, 0x8CA9, + 0x898F, 0x8B4B, 0x8993, 0xE64B, 0x8996, 0x8E8B, 0x8997, 0x9460, 0x8998, 0xE64C, 0x899A, 0x8A6F, 0x89A1, 0xE64D, 0x89A6, 0xE64F, + 0x89A7, 0x9797, 0x89A9, 0xE64E, 0x89AA, 0x9065, 0x89AC, 0xE650, 0x89AF, 0xE651, 0x89B2, 0xE652, 0x89B3, 0x8ACF, 0x89BA, 0xE653, + 0x89BD, 0xE654, 0x89BF, 0xE655, 0x89C0, 0xE656, 0x89D2, 0x8A70, 0x89DA, 0xE657, 0x89DC, 0xE658, 0x89DD, 0xE659, 0x89E3, 0x89F0, + 0x89E6, 0x9047, 0x89E7, 0xE65A, 0x89F4, 0xE65B, 0x89F8, 0xE65C, 0x8A00, 0x8CBE, 0x8A02, 0x92F9, 0x8A03, 0xE65D, 0x8A08, 0x8C76, + 0x8A0A, 0x9075, 0x8A0C, 0xE660, 0x8A0E, 0x93A2, 0x8A10, 0xE65F, 0x8A12, 0xFBA3, 0x8A13, 0x8C50, 0x8A16, 0xE65E, 0x8A17, 0x91F5, + 0x8A18, 0x8B4C, 0x8A1B, 0xE661, 0x8A1D, 0xE662, 0x8A1F, 0x8FD7, 0x8A23, 0x8C8D, 0x8A25, 0xE663, 0x8A2A, 0x964B, 0x8A2D, 0x90DD, + 0x8A31, 0x8B96, 0x8A33, 0x96F3, 0x8A34, 0x9169, 0x8A36, 0xE664, 0x8A37, 0xFBA4, 0x8A3A, 0x9066, 0x8A3B, 0x9290, 0x8A3C, 0x8FD8, + 0x8A41, 0xE665, 0x8A46, 0xE668, 0x8A48, 0xE669, 0x8A50, 0x8DBC, 0x8A51, 0x91C0, 0x8A52, 0xE667, 0x8A54, 0x8FD9, 0x8A55, 0x955D, + 0x8A5B, 0xE666, 0x8A5E, 0x8E8C, 0x8A60, 0x8972, 0x8A62, 0xE66D, 0x8A63, 0x8C77, 0x8A66, 0x8E8E, 0x8A69, 0x8E8D, 0x8A6B, 0x986C, + 0x8A6C, 0xE66C, 0x8A6D, 0xE66B, 0x8A6E, 0x9146, 0x8A70, 0x8B6C, 0x8A71, 0x9862, 0x8A72, 0x8A59, 0x8A73, 0x8FDA, 0x8A79, 0xFBA5, + 0x8A7C, 0xE66A, 0x8A82, 0xE66F, 0x8A84, 0xE670, 0x8A85, 0xE66E, 0x8A87, 0x8CD6, 0x8A89, 0x975F, 0x8A8C, 0x8E8F, 0x8A8D, 0x9446, + 0x8A91, 0xE673, 0x8A93, 0x90BE, 0x8A95, 0x9261, 0x8A98, 0x9755, 0x8A9A, 0xE676, 0x8A9E, 0x8CEA, 0x8AA0, 0x90BD, 0x8AA1, 0xE672, + 0x8AA3, 0xE677, 0x8AA4, 0x8CEB, 0x8AA5, 0xE674, 0x8AA6, 0xE675, 0x8AA7, 0xFBA6, 0x8AA8, 0xE671, 0x8AAC, 0x90E0, 0x8AAD, 0x93C7, + 0x8AB0, 0x924E, 0x8AB2, 0x89DB, 0x8AB9, 0x94EE, 0x8ABC, 0x8B62, 0x8ABE, 0xFBA7, 0x8ABF, 0x92B2, 0x8AC2, 0xE67A, 0x8AC4, 0xE678, + 0x8AC7, 0x926B, 0x8ACB, 0x90BF, 0x8ACC, 0x8AD0, 0x8ACD, 0xE679, 0x8ACF, 0x907A, 0x8AD2, 0x97C8, 0x8AD6, 0x985F, 0x8ADA, 0xE67B, + 0x8ADB, 0xE687, 0x8ADC, 0x92B3, 0x8ADE, 0xE686, 0x8ADF, 0xFBA8, 0x8AE0, 0xE683, 0x8AE1, 0xE68B, 0x8AE2, 0xE684, 0x8AE4, 0xE680, + 0x8AE6, 0x92FA, 0x8AE7, 0xE67E, 0x8AEB, 0xE67C, 0x8AED, 0x9740, 0x8AEE, 0x8E90, 0x8AF1, 0xE681, 0x8AF3, 0xE67D, 0x8AF6, 0xFBAA, + 0x8AF7, 0xE685, 0x8AF8, 0x8F94, 0x8AFA, 0x8CBF, 0x8AFE, 0x91F8, 0x8B00, 0x9664, 0x8B01, 0x8979, 0x8B02, 0x88E0, 0x8B04, 0x93A3, + 0x8B07, 0xE689, 0x8B0C, 0xE688, 0x8B0E, 0x93E4, 0x8B10, 0xE68D, 0x8B14, 0xE682, 0x8B16, 0xE68C, 0x8B17, 0xE68E, 0x8B19, 0x8CAA, + 0x8B1A, 0xE68A, 0x8B1B, 0x8D75, 0x8B1D, 0x8ED3, 0x8B20, 0xE68F, 0x8B21, 0x9777, 0x8B26, 0xE692, 0x8B28, 0xE695, 0x8B2B, 0xE693, + 0x8B2C, 0x9554, 0x8B33, 0xE690, 0x8B39, 0x8BDE, 0x8B3E, 0xE694, 0x8B41, 0xE696, 0x8B49, 0xE69A, 0x8B4C, 0xE697, 0x8B4E, 0xE699, + 0x8B4F, 0xE698, 0x8B53, 0xFBAB, 0x8B56, 0xE69B, 0x8B58, 0x8EAF, 0x8B5A, 0xE69D, 0x8B5B, 0xE69C, 0x8B5C, 0x9588, 0x8B5F, 0xE69F, + 0x8B66, 0x8C78, 0x8B6B, 0xE69E, 0x8B6C, 0xE6A0, 0x8B6F, 0xE6A1, 0x8B70, 0x8B63, 0x8B71, 0xE3BF, 0x8B72, 0x8FF7, 0x8B74, 0xE6A2, + 0x8B77, 0x8CEC, 0x8B7D, 0xE6A3, 0x8B7F, 0xFBAC, 0x8B80, 0xE6A4, 0x8B83, 0x8E5D, 0x8B8A, 0x9DCC, 0x8B8C, 0xE6A5, 0x8B8E, 0xE6A6, + 0x8B90, 0x8F51, 0x8B92, 0xE6A7, 0x8B93, 0xE6A8, 0x8B96, 0xE6A9, 0x8B99, 0xE6AA, 0x8B9A, 0xE6AB, 0x8C37, 0x924A, 0x8C3A, 0xE6AC, + 0x8C3F, 0xE6AE, 0x8C41, 0xE6AD, 0x8C46, 0x93A4, 0x8C48, 0xE6AF, 0x8C4A, 0x964C, 0x8C4C, 0xE6B0, 0x8C4E, 0xE6B1, 0x8C50, 0xE6B2, + 0x8C55, 0xE6B3, 0x8C5A, 0x93D8, 0x8C61, 0x8FDB, 0x8C62, 0xE6B4, 0x8C6A, 0x8D8B, 0x8C6B, 0x98AC, 0x8C6C, 0xE6B5, 0x8C78, 0xE6B6, + 0x8C79, 0x955E, 0x8C7A, 0xE6B7, 0x8C7C, 0xE6BF, 0x8C82, 0xE6B8, 0x8C85, 0xE6BA, 0x8C89, 0xE6B9, 0x8C8A, 0xE6BB, 0x8C8C, 0x9665, + 0x8C8D, 0xE6BC, 0x8C8E, 0xE6BD, 0x8C94, 0xE6BE, 0x8C98, 0xE6C0, 0x8C9D, 0x8A4C, 0x8C9E, 0x92E5, 0x8CA0, 0x9589, 0x8CA1, 0x8DE0, + 0x8CA2, 0x8D76, 0x8CA7, 0x956E, 0x8CA8, 0x89DD, 0x8CA9, 0x94CC, 0x8CAA, 0xE6C3, 0x8CAB, 0x8AD1, 0x8CAC, 0x90D3, 0x8CAD, 0xE6C2, + 0x8CAE, 0xE6C7, 0x8CAF, 0x9299, 0x8CB0, 0x96E1, 0x8CB2, 0xE6C5, 0x8CB3, 0xE6C6, 0x8CB4, 0x8B4D, 0x8CB6, 0xE6C8, 0x8CB7, 0x9483, + 0x8CB8, 0x91DD, 0x8CBB, 0x94EF, 0x8CBC, 0x935C, 0x8CBD, 0xE6C4, 0x8CBF, 0x9666, 0x8CC0, 0x89EA, 0x8CC1, 0xE6CA, 0x8CC2, 0x9847, + 0x8CC3, 0x92C0, 0x8CC4, 0x9864, 0x8CC7, 0x8E91, 0x8CC8, 0xE6C9, 0x8CCA, 0x91AF, 0x8CCD, 0xE6DA, 0x8CCE, 0x9147, 0x8CD1, 0x93F6, + 0x8CD3, 0x956F, 0x8CDA, 0xE6CD, 0x8CDB, 0x8E5E, 0x8CDC, 0x8E92, 0x8CDE, 0x8FDC, 0x8CE0, 0x9485, 0x8CE2, 0x8CAB, 0x8CE3, 0xE6CC, + 0x8CE4, 0xE6CB, 0x8CE6, 0x958A, 0x8CEA, 0x8EBF, 0x8CED, 0x9371, 0x8CF0, 0xFBAD, 0x8CF4, 0xFBAE, 0x8CFA, 0xE6CF, 0x8CFB, 0xE6D0, + 0x8CFC, 0x8D77, 0x8CFD, 0xE6CE, 0x8D04, 0xE6D1, 0x8D05, 0xE6D2, 0x8D07, 0xE6D4, 0x8D08, 0x91A1, 0x8D0A, 0xE6D3, 0x8D0B, 0x8AE4, + 0x8D0D, 0xE6D6, 0x8D0F, 0xE6D5, 0x8D10, 0xE6D7, 0x8D12, 0xFBAF, 0x8D13, 0xE6D9, 0x8D14, 0xE6DB, 0x8D16, 0xE6DC, 0x8D64, 0x90D4, + 0x8D66, 0x8ECD, 0x8D67, 0xE6DD, 0x8D6B, 0x8A71, 0x8D6D, 0xE6DE, 0x8D70, 0x9196, 0x8D71, 0xE6DF, 0x8D73, 0xE6E0, 0x8D74, 0x958B, + 0x8D76, 0xFBB0, 0x8D77, 0x8B4E, 0x8D81, 0xE6E1, 0x8D85, 0x92B4, 0x8D8A, 0x897A, 0x8D99, 0xE6E2, 0x8DA3, 0x8EEF, 0x8DA8, 0x9096, + 0x8DB3, 0x91AB, 0x8DBA, 0xE6E5, 0x8DBE, 0xE6E4, 0x8DC2, 0xE6E3, 0x8DCB, 0xE6EB, 0x8DCC, 0xE6E9, 0x8DCF, 0xE6E6, 0x8DD6, 0xE6E8, + 0x8DDA, 0xE6E7, 0x8DDB, 0xE6EA, 0x8DDD, 0x8B97, 0x8DDF, 0xE6EE, 0x8DE1, 0x90D5, 0x8DE3, 0xE6EF, 0x8DE8, 0x8CD7, 0x8DEA, 0xE6EC, + 0x8DEB, 0xE6ED, 0x8DEF, 0x9848, 0x8DF3, 0x92B5, 0x8DF5, 0x9148, 0x8DFC, 0xE6F0, 0x8DFF, 0xE6F3, 0x8E08, 0xE6F1, 0x8E09, 0xE6F2, + 0x8E0A, 0x9778, 0x8E0F, 0x93A5, 0x8E10, 0xE6F6, 0x8E1D, 0xE6F4, 0x8E1E, 0xE6F5, 0x8E1F, 0xE6F7, 0x8E2A, 0xE748, 0x8E30, 0xE6FA, + 0x8E34, 0xE6FB, 0x8E35, 0xE6F9, 0x8E42, 0xE6F8, 0x8E44, 0x92FB, 0x8E47, 0xE740, 0x8E48, 0xE744, 0x8E49, 0xE741, 0x8E4A, 0xE6FC, + 0x8E4C, 0xE742, 0x8E50, 0xE743, 0x8E55, 0xE74A, 0x8E59, 0xE745, 0x8E5F, 0x90D6, 0x8E60, 0xE747, 0x8E63, 0xE749, 0x8E64, 0xE746, + 0x8E72, 0xE74C, 0x8E74, 0x8F52, 0x8E76, 0xE74B, 0x8E7C, 0xE74D, 0x8E81, 0xE74E, 0x8E84, 0xE751, 0x8E85, 0xE750, 0x8E87, 0xE74F, + 0x8E8A, 0xE753, 0x8E8B, 0xE752, 0x8E8D, 0x96F4, 0x8E91, 0xE755, 0x8E93, 0xE754, 0x8E94, 0xE756, 0x8E99, 0xE757, 0x8EA1, 0xE759, + 0x8EAA, 0xE758, 0x8EAB, 0x9067, 0x8EAC, 0xE75A, 0x8EAF, 0x8BEB, 0x8EB0, 0xE75B, 0x8EB1, 0xE75D, 0x8EBE, 0xE75E, 0x8EC5, 0xE75F, + 0x8EC6, 0xE75C, 0x8EC8, 0xE760, 0x8ECA, 0x8ED4, 0x8ECB, 0xE761, 0x8ECC, 0x8B4F, 0x8ECD, 0x8C52, 0x8ECF, 0xFBB2, 0x8ED2, 0x8CAC, + 0x8EDB, 0xE762, 0x8EDF, 0x93EE, 0x8EE2, 0x935D, 0x8EE3, 0xE763, 0x8EEB, 0xE766, 0x8EF8, 0x8EB2, 0x8EFB, 0xE765, 0x8EFC, 0xE764, + 0x8EFD, 0x8C79, 0x8EFE, 0xE767, 0x8F03, 0x8A72, 0x8F05, 0xE769, 0x8F09, 0x8DDA, 0x8F0A, 0xE768, 0x8F0C, 0xE771, 0x8F12, 0xE76B, + 0x8F13, 0xE76D, 0x8F14, 0x95E3, 0x8F15, 0xE76A, 0x8F19, 0xE76C, 0x8F1B, 0xE770, 0x8F1C, 0xE76E, 0x8F1D, 0x8B50, 0x8F1F, 0xE76F, + 0x8F26, 0xE772, 0x8F29, 0x9479, 0x8F2A, 0x97D6, 0x8F2F, 0x8F53, 0x8F33, 0xE773, 0x8F38, 0x9741, 0x8F39, 0xE775, 0x8F3B, 0xE774, + 0x8F3E, 0xE778, 0x8F3F, 0x9760, 0x8F42, 0xE777, 0x8F44, 0x8A8D, 0x8F45, 0xE776, 0x8F46, 0xE77B, 0x8F49, 0xE77A, 0x8F4C, 0xE779, + 0x8F4D, 0x9351, 0x8F4E, 0xE77C, 0x8F57, 0xE77D, 0x8F5C, 0xE77E, 0x8F5F, 0x8D8C, 0x8F61, 0x8C44, 0x8F62, 0xE780, 0x8F63, 0xE781, + 0x8F64, 0xE782, 0x8F9B, 0x9068, 0x8F9C, 0xE783, 0x8F9E, 0x8EAB, 0x8F9F, 0xE784, 0x8FA3, 0xE785, 0x8FA7, 0x999F, 0x8FA8, 0x999E, + 0x8FAD, 0xE786, 0x8FAE, 0xE390, 0x8FAF, 0xE787, 0x8FB0, 0x9243, 0x8FB1, 0x904A, 0x8FB2, 0x945F, 0x8FB7, 0xE788, 0x8FBA, 0x95D3, + 0x8FBB, 0x92D2, 0x8FBC, 0x8D9E, 0x8FBF, 0x9248, 0x8FC2, 0x8949, 0x8FC4, 0x9698, 0x8FC5, 0x9076, 0x8FCE, 0x8C7D, 0x8FD1, 0x8BDF, + 0x8FD4, 0x95D4, 0x8FDA, 0xE789, 0x8FE2, 0xE78B, 0x8FE5, 0xE78A, 0x8FE6, 0x89DE, 0x8FE9, 0x93F4, 0x8FEA, 0xE78C, 0x8FEB, 0x9497, + 0x8FED, 0x9352, 0x8FEF, 0xE78D, 0x8FF0, 0x8F71, 0x8FF4, 0xE78F, 0x8FF7, 0x96C0, 0x8FF8, 0xE79E, 0x8FF9, 0xE791, 0x8FFA, 0xE792, + 0x8FFD, 0x92C7, 0x9000, 0x91DE, 0x9001, 0x9197, 0x9003, 0x93A6, 0x9005, 0xE790, 0x9006, 0x8B74, 0x900B, 0xE799, 0x900D, 0xE796, + 0x900E, 0xE7A3, 0x900F, 0x93A7, 0x9010, 0x9280, 0x9011, 0xE793, 0x9013, 0x92FC, 0x9014, 0x9372, 0x9015, 0xE794, 0x9016, 0xE798, + 0x9017, 0x9080, 0x9019, 0x9487, 0x901A, 0x92CA, 0x901D, 0x90C0, 0x901E, 0xE797, 0x901F, 0x91AC, 0x9020, 0x91A2, 0x9021, 0xE795, + 0x9022, 0x88A7, 0x9023, 0x9841, 0x9027, 0xE79A, 0x902E, 0x91DF, 0x9031, 0x8F54, 0x9032, 0x9069, 0x9035, 0xE79C, 0x9036, 0xE79B, + 0x9038, 0x88ED, 0x9039, 0xE79D, 0x903C, 0x954E, 0x903E, 0xE7A5, 0x9041, 0x93D9, 0x9042, 0x908B, 0x9045, 0x9278, 0x9047, 0x8BF6, + 0x9049, 0xE7A4, 0x904A, 0x9756, 0x904B, 0x895E, 0x904D, 0x95D5, 0x904E, 0x89DF, 0x904F, 0xE79F, 0x9050, 0xE7A0, 0x9051, 0xE7A1, + 0x9052, 0xE7A2, 0x9053, 0x93B9, 0x9054, 0x9242, 0x9055, 0x88E1, 0x9056, 0xE7A6, 0x9058, 0xE7A7, 0x9059, 0xEAA1, 0x905C, 0x91BB, + 0x905E, 0xE7A8, 0x9060, 0x8993, 0x9061, 0x916B, 0x9063, 0x8CAD, 0x9065, 0x9779, 0x9067, 0xFBB5, 0x9068, 0xE7A9, 0x9069, 0x934B, + 0x906D, 0x9198, 0x906E, 0x8ED5, 0x906F, 0xE7AA, 0x9072, 0xE7AD, 0x9075, 0x8F85, 0x9076, 0xE7AB, 0x9077, 0x914A, 0x9078, 0x9149, + 0x907A, 0x88E2, 0x907C, 0x97C9, 0x907D, 0xE7AF, 0x907F, 0x94F0, 0x9080, 0xE7B1, 0x9081, 0xE7B0, 0x9082, 0xE7AE, 0x9083, 0xE284, + 0x9084, 0x8AD2, 0x9087, 0xE78E, 0x9089, 0xE7B3, 0x908A, 0xE7B2, 0x908F, 0xE7B4, 0x9091, 0x9757, 0x90A3, 0x93DF, 0x90A6, 0x964D, + 0x90A8, 0xE7B5, 0x90AA, 0x8ED7, 0x90AF, 0xE7B6, 0x90B1, 0xE7B7, 0x90B5, 0xE7B8, 0x90B8, 0x9340, 0x90C1, 0x88E8, 0x90CA, 0x8D78, + 0x90CE, 0x9859, 0x90DB, 0xE7BC, 0x90DE, 0xFBB6, 0x90E1, 0x8C53, 0x90E2, 0xE7B9, 0x90E4, 0xE7BA, 0x90E8, 0x9594, 0x90ED, 0x8A73, + 0x90F5, 0x9758, 0x90F7, 0x8BBD, 0x90FD, 0x9373, 0x9102, 0xE7BD, 0x9112, 0xE7BE, 0x9115, 0xFBB8, 0x9119, 0xE7BF, 0x9127, 0xFBB9, + 0x912D, 0x9341, 0x9130, 0xE7C1, 0x9132, 0xE7C0, 0x9149, 0x93D1, 0x914A, 0xE7C2, 0x914B, 0x8F55, 0x914C, 0x8EDE, 0x914D, 0x947A, + 0x914E, 0x9291, 0x9152, 0x8EF0, 0x9154, 0x908C, 0x9156, 0xE7C3, 0x9158, 0xE7C4, 0x9162, 0x907C, 0x9163, 0xE7C5, 0x9165, 0xE7C6, + 0x9169, 0xE7C7, 0x916A, 0x978F, 0x916C, 0x8F56, 0x9172, 0xE7C9, 0x9173, 0xE7C8, 0x9175, 0x8D79, 0x9177, 0x8D93, 0x9178, 0x8E5F, + 0x9182, 0xE7CC, 0x9187, 0x8F86, 0x9189, 0xE7CB, 0x918B, 0xE7CA, 0x918D, 0x91E7, 0x9190, 0x8CED, 0x9192, 0x90C1, 0x9197, 0x94AE, + 0x919C, 0x8F58, 0x91A2, 0xE7CD, 0x91A4, 0x8FDD, 0x91AA, 0xE7D0, 0x91AB, 0xE7CE, 0x91AF, 0xE7CF, 0x91B4, 0xE7D2, 0x91B5, 0xE7D1, + 0x91B8, 0x8FF8, 0x91BA, 0xE7D3, 0x91C0, 0xE7D4, 0x91C1, 0xE7D5, 0x91C6, 0x94CE, 0x91C7, 0x8DD1, 0x91C8, 0x8EDF, 0x91C9, 0xE7D6, + 0x91CB, 0xE7D7, 0x91CC, 0x97A2, 0x91CD, 0x8F64, 0x91CE, 0x96EC, 0x91CF, 0x97CA, 0x91D0, 0xE7D8, 0x91D1, 0x8BE0, 0x91D6, 0xE7D9, + 0x91D7, 0xFBBB, 0x91D8, 0x9342, 0x91DA, 0xFBBA, 0x91DB, 0xE7DC, 0x91DC, 0x8A98, 0x91DD, 0x906A, 0x91DE, 0xFBBC, 0x91DF, 0xE7DA, + 0x91E1, 0xE7DB, 0x91E3, 0x92DE, 0x91E4, 0xFBBF, 0x91E5, 0xFBC0, 0x91E6, 0x9674, 0x91E7, 0x8BFA, 0x91ED, 0xFBBD, 0x91EE, 0xFBBE, + 0x91F5, 0xE7DE, 0x91F6, 0xE7DF, 0x91FC, 0xE7DD, 0x91FF, 0xE7E1, 0x9206, 0xFBC1, 0x920A, 0xFBC3, 0x920D, 0x93DD, 0x920E, 0x8A62, + 0x9210, 0xFBC2, 0x9211, 0xE7E5, 0x9214, 0xE7E2, 0x9215, 0xE7E4, 0x921E, 0xE7E0, 0x9229, 0xE86E, 0x922C, 0xE7E3, 0x9234, 0x97E9, + 0x9237, 0x8CD8, 0x9239, 0xFBCA, 0x923A, 0xFBC4, 0x923C, 0xFBC6, 0x923F, 0xE7ED, 0x9240, 0xFBC5, 0x9244, 0x9353, 0x9245, 0xE7E8, + 0x9248, 0xE7EB, 0x9249, 0xE7E9, 0x924B, 0xE7EE, 0x924E, 0xFBC7, 0x9250, 0xE7EF, 0x9251, 0xFBC9, 0x9257, 0xE7E7, 0x9259, 0xFBC8, + 0x925A, 0xE7F4, 0x925B, 0x8994, 0x925E, 0xE7E6, 0x9262, 0x94AB, 0x9264, 0xE7EA, 0x9266, 0x8FDE, 0x9267, 0xFBCB, 0x9271, 0x8D7A, + 0x9277, 0xFBCD, 0x9278, 0xFBCE, 0x927E, 0x9667, 0x9280, 0x8BE2, 0x9283, 0x8F65, 0x9285, 0x93BA, 0x9288, 0xFA5F, 0x9291, 0x914C, + 0x9293, 0xE7F2, 0x9295, 0xE7EC, 0x9296, 0xE7F1, 0x9298, 0x96C1, 0x929A, 0x92B6, 0x929B, 0xE7F3, 0x929C, 0xE7F0, 0x92A7, 0xFBCC, + 0x92AD, 0x914B, 0x92B7, 0xE7F7, 0x92B9, 0xE7F6, 0x92CF, 0xE7F5, 0x92D0, 0xFBD2, 0x92D2, 0x964E, 0x92D3, 0xFBD6, 0x92D5, 0xFBD4, + 0x92D7, 0xFBD0, 0x92D9, 0xFBD1, 0x92E0, 0xFBD5, 0x92E4, 0x8F9B, 0x92E7, 0xFBCF, 0x92E9, 0xE7F8, 0x92EA, 0x95DD, 0x92ED, 0x8973, + 0x92F2, 0x9565, 0x92F3, 0x9292, 0x92F8, 0x8B98, 0x92F9, 0xFA65, 0x92FA, 0xE7FA, 0x92FB, 0xFBD9, 0x92FC, 0x8D7C, 0x92FF, 0xFBDC, + 0x9302, 0xFBDE, 0x9306, 0x8E4B, 0x930F, 0xE7F9, 0x9310, 0x908D, 0x9318, 0x908E, 0x9319, 0xE840, 0x931A, 0xE842, 0x931D, 0xFBDD, + 0x931E, 0xFBDB, 0x9320, 0x8FF9, 0x9321, 0xFBD8, 0x9322, 0xE841, 0x9323, 0xE843, 0x9325, 0xFBD7, 0x9326, 0x8BD1, 0x9328, 0x9564, + 0x932B, 0x8EE0, 0x932C, 0x9842, 0x932E, 0xE7FC, 0x932F, 0x8DF6, 0x9332, 0x985E, 0x9335, 0xE845, 0x933A, 0xE844, 0x933B, 0xE846, + 0x9344, 0xE7FB, 0x9348, 0xFA5E, 0x934B, 0x93E7, 0x934D, 0x9374, 0x9354, 0x92D5, 0x9356, 0xE84B, 0x9357, 0xFBE0, 0x935B, 0x9262, + 0x935C, 0xE847, 0x9360, 0xE848, 0x936C, 0x8C4C, 0x936E, 0xE84A, 0x9370, 0xFBDF, 0x9375, 0x8CAE, 0x937C, 0xE849, 0x937E, 0x8FDF, + 0x938C, 0x8A99, 0x9394, 0xE84F, 0x9396, 0x8DBD, 0x9397, 0x9199, 0x939A, 0x92C8, 0x93A4, 0xFBE1, 0x93A7, 0x8A5A, 0x93AC, 0xE84D, + 0x93AD, 0xE84E, 0x93AE, 0x92C1, 0x93B0, 0xE84C, 0x93B9, 0xE850, 0x93C3, 0xE856, 0x93C6, 0xFBE2, 0x93C8, 0xE859, 0x93D0, 0xE858, + 0x93D1, 0x934C, 0x93D6, 0xE851, 0x93D7, 0xE852, 0x93D8, 0xE855, 0x93DD, 0xE857, 0x93DE, 0xFBE3, 0x93E1, 0x8BBE, 0x93E4, 0xE85A, + 0x93E5, 0xE854, 0x93E8, 0xE853, 0x93F8, 0xFBE4, 0x9403, 0xE85E, 0x9407, 0xE85F, 0x9410, 0xE860, 0x9413, 0xE85D, 0x9414, 0xE85C, + 0x9418, 0x8FE0, 0x9419, 0x93A8, 0x941A, 0xE85B, 0x9421, 0xE864, 0x942B, 0xE862, 0x9431, 0xFBE5, 0x9435, 0xE863, 0x9436, 0xE861, + 0x9438, 0x91F6, 0x943A, 0xE865, 0x9441, 0xE866, 0x9444, 0xE868, 0x9445, 0xFBE6, 0x9448, 0xFBE7, 0x9451, 0x8AD3, 0x9452, 0xE867, + 0x9453, 0x96F8, 0x945A, 0xE873, 0x945B, 0xE869, 0x945E, 0xE86C, 0x9460, 0xE86A, 0x9462, 0xE86B, 0x946A, 0xE86D, 0x9470, 0xE86F, + 0x9475, 0xE870, 0x9477, 0xE871, 0x947C, 0xE874, 0x947D, 0xE872, 0x947E, 0xE875, 0x947F, 0xE877, 0x9481, 0xE876, 0x9577, 0x92B7, + 0x9580, 0x96E5, 0x9582, 0xE878, 0x9583, 0x914D, 0x9587, 0xE879, 0x9589, 0x95C2, 0x958A, 0xE87A, 0x958B, 0x8A4A, 0x958F, 0x895B, + 0x9591, 0x8AD5, 0x9592, 0xFBE8, 0x9593, 0x8AD4, 0x9594, 0xE87B, 0x9596, 0xE87C, 0x9598, 0xE87D, 0x9599, 0xE87E, 0x95A0, 0xE880, + 0x95A2, 0x8AD6, 0x95A3, 0x8A74, 0x95A4, 0x8D7D, 0x95A5, 0x94B4, 0x95A7, 0xE882, 0x95A8, 0xE881, 0x95AD, 0xE883, 0x95B2, 0x897B, + 0x95B9, 0xE886, 0x95BB, 0xE885, 0x95BC, 0xE884, 0x95BE, 0xE887, 0x95C3, 0xE88A, 0x95C7, 0x88C5, 0x95CA, 0xE888, 0x95CC, 0xE88C, + 0x95CD, 0xE88B, 0x95D4, 0xE88E, 0x95D5, 0xE88D, 0x95D6, 0xE88F, 0x95D8, 0x93AC, 0x95DC, 0xE890, 0x95E1, 0xE891, 0x95E2, 0xE893, + 0x95E5, 0xE892, 0x961C, 0x958C, 0x9621, 0xE894, 0x9628, 0xE895, 0x962A, 0x8DE3, 0x962E, 0xE896, 0x962F, 0xE897, 0x9632, 0x9668, + 0x963B, 0x916A, 0x963F, 0x88A2, 0x9640, 0x91C9, 0x9642, 0xE898, 0x9644, 0x958D, 0x964B, 0xE89B, 0x964C, 0xE899, 0x964D, 0x8D7E, + 0x964F, 0xE89A, 0x9650, 0x8CC0, 0x965B, 0x95C3, 0x965C, 0xE89D, 0x965D, 0xE89F, 0x965E, 0xE89E, 0x965F, 0xE8A0, 0x9662, 0x8940, + 0x9663, 0x9077, 0x9664, 0x8F9C, 0x9665, 0x8AD7, 0x9666, 0xE8A1, 0x966A, 0x9486, 0x966C, 0xE8A3, 0x9670, 0x8941, 0x9672, 0xE8A2, + 0x9673, 0x92C2, 0x9675, 0x97CB, 0x9676, 0x93A9, 0x9677, 0xE89C, 0x9678, 0x97A4, 0x967A, 0x8CAF, 0x967D, 0x977A, 0x9685, 0x8BF7, + 0x9686, 0x97B2, 0x9688, 0x8C47, 0x968A, 0x91E0, 0x968B, 0xE440, 0x968D, 0xE8A4, 0x968E, 0x8A4B, 0x968F, 0x908F, 0x9694, 0x8A75, + 0x9695, 0xE8A6, 0x9697, 0xE8A7, 0x9698, 0xE8A5, 0x9699, 0x8C84, 0x969B, 0x8DDB, 0x969C, 0x8FE1, 0x969D, 0xFBEB, 0x96A0, 0x8942, + 0x96A3, 0x97D7, 0x96A7, 0xE8A9, 0x96A8, 0xE7AC, 0x96AA, 0xE8A8, 0x96AF, 0xFBEC, 0x96B0, 0xE8AC, 0x96B1, 0xE8AA, 0x96B2, 0xE8AB, + 0x96B4, 0xE8AD, 0x96B6, 0xE8AE, 0x96B7, 0x97EA, 0x96B8, 0xE8AF, 0x96B9, 0xE8B0, 0x96BB, 0x90C7, 0x96BC, 0x94B9, 0x96C0, 0x909D, + 0x96C1, 0x8AE5, 0x96C4, 0x9759, 0x96C5, 0x89EB, 0x96C6, 0x8F57, 0x96C7, 0x8CD9, 0x96C9, 0xE8B3, 0x96CB, 0xE8B2, 0x96CC, 0x8E93, + 0x96CD, 0xE8B4, 0x96CE, 0xE8B1, 0x96D1, 0x8E47, 0x96D5, 0xE8B8, 0x96D6, 0xE5AB, 0x96D9, 0x99D4, 0x96DB, 0x9097, 0x96DC, 0xE8B6, + 0x96E2, 0x97A3, 0x96E3, 0x93EF, 0x96E8, 0x894A, 0x96EA, 0x90E1, 0x96EB, 0x8EB4, 0x96F0, 0x95B5, 0x96F2, 0x895F, 0x96F6, 0x97EB, + 0x96F7, 0x978B, 0x96F9, 0xE8B9, 0x96FB, 0x9364, 0x9700, 0x8EF9, 0x9704, 0xE8BA, 0x9706, 0xE8BB, 0x9707, 0x906B, 0x9708, 0xE8BC, + 0x970A, 0x97EC, 0x970D, 0xE8B7, 0x970E, 0xE8BE, 0x970F, 0xE8C0, 0x9711, 0xE8BF, 0x9713, 0xE8BD, 0x9716, 0xE8C1, 0x9719, 0xE8C2, + 0x971C, 0x919A, 0x971E, 0x89E0, 0x9724, 0xE8C3, 0x9727, 0x96B6, 0x972A, 0xE8C4, 0x9730, 0xE8C5, 0x9732, 0x9849, 0x9733, 0xFBED, + 0x9738, 0x9E50, 0x9739, 0xE8C6, 0x973B, 0xFBEE, 0x973D, 0xE8C7, 0x973E, 0xE8C8, 0x9742, 0xE8CC, 0x9743, 0xFBEF, 0x9744, 0xE8C9, + 0x9746, 0xE8CA, 0x9748, 0xE8CB, 0x9749, 0xE8CD, 0x974D, 0xFBF0, 0x974F, 0xFBF1, 0x9751, 0xFBF2, 0x9752, 0x90C2, 0x9755, 0xFBF3, + 0x9756, 0x96F5, 0x9759, 0x90C3, 0x975C, 0xE8CE, 0x975E, 0x94F1, 0x9760, 0xE8CF, 0x9761, 0xEA72, 0x9762, 0x96CA, 0x9764, 0xE8D0, + 0x9766, 0xE8D1, 0x9768, 0xE8D2, 0x9769, 0x8A76, 0x976B, 0xE8D4, 0x976D, 0x9078, 0x9771, 0xE8D5, 0x9774, 0x8C43, 0x9779, 0xE8D6, + 0x977A, 0xE8DA, 0x977C, 0xE8D8, 0x9781, 0xE8D9, 0x9784, 0x8A93, 0x9785, 0xE8D7, 0x9786, 0xE8DB, 0x978B, 0xE8DC, 0x978D, 0x88C6, + 0x978F, 0xE8DD, 0x9790, 0xE8DE, 0x9798, 0x8FE2, 0x979C, 0xE8DF, 0x97A0, 0x8B66, 0x97A3, 0xE8E2, 0x97A6, 0xE8E1, 0x97A8, 0xE8E0, + 0x97AB, 0xE691, 0x97AD, 0x95DA, 0x97B3, 0xE8E3, 0x97B4, 0xE8E4, 0x97C3, 0xE8E5, 0x97C6, 0xE8E6, 0x97C8, 0xE8E7, 0x97CB, 0xE8E8, + 0x97D3, 0x8AD8, 0x97DC, 0xE8E9, 0x97ED, 0xE8EA, 0x97EE, 0x9442, 0x97F2, 0xE8EC, 0x97F3, 0x89B9, 0x97F5, 0xE8EF, 0x97F6, 0xE8EE, + 0x97FB, 0x8943, 0x97FF, 0x8BBF, 0x9801, 0x95C5, 0x9802, 0x92B8, 0x9803, 0x8DA0, 0x9805, 0x8D80, 0x9806, 0x8F87, 0x9808, 0x907B, + 0x980C, 0xE8F1, 0x980F, 0xE8F0, 0x9810, 0x9761, 0x9811, 0x8AE6, 0x9812, 0x94D0, 0x9813, 0x93DA, 0x9817, 0x909C, 0x9818, 0x97CC, + 0x981A, 0x8C7A, 0x9821, 0xE8F4, 0x9824, 0xE8F3, 0x982C, 0x966A, 0x982D, 0x93AA, 0x9834, 0x896F, 0x9837, 0xE8F5, 0x9838, 0xE8F2, + 0x983B, 0x9570, 0x983C, 0x978A, 0x983D, 0xE8F6, 0x9846, 0xE8F7, 0x984B, 0xE8F9, 0x984C, 0x91E8, 0x984D, 0x8A7A, 0x984E, 0x8A7B, + 0x984F, 0xE8F8, 0x9854, 0x8AE7, 0x9855, 0x8CB0, 0x9857, 0xFBF4, 0x9858, 0x8AE8, 0x985B, 0x935E, 0x985E, 0x97DE, 0x9865, 0xFBF5, + 0x9867, 0x8CDA, 0x986B, 0xE8FA, 0x986F, 0xE8FB, 0x9870, 0xE8FC, 0x9871, 0xE940, 0x9873, 0xE942, 0x9874, 0xE941, 0x98A8, 0x9597, + 0x98AA, 0xE943, 0x98AF, 0xE944, 0x98B1, 0xE945, 0x98B6, 0xE946, 0x98C3, 0xE948, 0x98C4, 0xE947, 0x98C6, 0xE949, 0x98DB, 0x94F2, + 0x98DC, 0xE3CA, 0x98DF, 0x9048, 0x98E2, 0x8B51, 0x98E9, 0xE94A, 0x98EB, 0xE94B, 0x98ED, 0x99AA, 0x98EE, 0x9F5A, 0x98EF, 0x94D1, + 0x98F2, 0x88F9, 0x98F4, 0x88B9, 0x98FC, 0x8E94, 0x98FD, 0x964F, 0x98FE, 0x8FFC, 0x9903, 0xE94C, 0x9905, 0x96DD, 0x9909, 0xE94D, + 0x990A, 0x977B, 0x990C, 0x8961, 0x9910, 0x8E60, 0x9912, 0xE94E, 0x9913, 0x89EC, 0x9914, 0xE94F, 0x9918, 0xE950, 0x991D, 0xE952, + 0x991E, 0xE953, 0x9920, 0xE955, 0x9921, 0xE951, 0x9924, 0xE954, 0x9927, 0xFBF8, 0x9928, 0x8AD9, 0x992C, 0xE956, 0x992E, 0xE957, + 0x993D, 0xE958, 0x993E, 0xE959, 0x9942, 0xE95A, 0x9945, 0xE95C, 0x9949, 0xE95B, 0x994B, 0xE95E, 0x994C, 0xE961, 0x9950, 0xE95D, + 0x9951, 0xE95F, 0x9952, 0xE960, 0x9955, 0xE962, 0x9957, 0x8BC0, 0x9996, 0x8EF1, 0x9997, 0xE963, 0x9998, 0xE964, 0x9999, 0x8D81, + 0x999E, 0xFBFA, 0x99A5, 0xE965, 0x99A8, 0x8A5D, 0x99AC, 0x946E, 0x99AD, 0xE966, 0x99AE, 0xE967, 0x99B3, 0x9279, 0x99B4, 0x93E9, + 0x99BC, 0xE968, 0x99C1, 0x949D, 0x99C4, 0x91CA, 0x99C5, 0x8977, 0x99C6, 0x8BEC, 0x99C8, 0x8BED, 0x99D0, 0x9293, 0x99D1, 0xE96D, + 0x99D2, 0x8BEE, 0x99D5, 0x89ED, 0x99D8, 0xE96C, 0x99DB, 0xE96A, 0x99DD, 0xE96B, 0x99DF, 0xE969, 0x99E2, 0xE977, 0x99ED, 0xE96E, + 0x99EE, 0xE96F, 0x99F1, 0xE970, 0x99F2, 0xE971, 0x99F8, 0xE973, 0x99FB, 0xE972, 0x99FF, 0x8F78, 0x9A01, 0xE974, 0x9A05, 0xE976, + 0x9A0E, 0x8B52, 0x9A0F, 0xE975, 0x9A12, 0x919B, 0x9A13, 0x8CB1, 0x9A19, 0xE978, 0x9A28, 0x91CB, 0x9A2B, 0xE979, 0x9A30, 0x93AB, + 0x9A37, 0xE97A, 0x9A3E, 0xE980, 0x9A40, 0xE97D, 0x9A42, 0xE97C, 0x9A43, 0xE97E, 0x9A45, 0xE97B, 0x9A4D, 0xE982, 0x9A4E, 0xFBFB, + 0x9A55, 0xE981, 0x9A57, 0xE984, 0x9A5A, 0x8BC1, 0x9A5B, 0xE983, 0x9A5F, 0xE985, 0x9A62, 0xE986, 0x9A64, 0xE988, 0x9A65, 0xE987, + 0x9A69, 0xE989, 0x9A6A, 0xE98B, 0x9A6B, 0xE98A, 0x9AA8, 0x8D9C, 0x9AAD, 0xE98C, 0x9AB0, 0xE98D, 0x9AB8, 0x8A5B, 0x9ABC, 0xE98E, + 0x9AC0, 0xE98F, 0x9AC4, 0x9091, 0x9ACF, 0xE990, 0x9AD1, 0xE991, 0x9AD3, 0xE992, 0x9AD4, 0xE993, 0x9AD8, 0x8D82, 0x9AD9, 0xFBFC, + 0x9ADC, 0xFC40, 0x9ADE, 0xE994, 0x9ADF, 0xE995, 0x9AE2, 0xE996, 0x9AE3, 0xE997, 0x9AE6, 0xE998, 0x9AEA, 0x94AF, 0x9AEB, 0xE99A, + 0x9AED, 0x9545, 0x9AEE, 0xE99B, 0x9AEF, 0xE999, 0x9AF1, 0xE99D, 0x9AF4, 0xE99C, 0x9AF7, 0xE99E, 0x9AFB, 0xE99F, 0x9B06, 0xE9A0, + 0x9B18, 0xE9A1, 0x9B1A, 0xE9A2, 0x9B1F, 0xE9A3, 0x9B22, 0xE9A4, 0x9B23, 0xE9A5, 0x9B25, 0xE9A6, 0x9B27, 0xE9A7, 0x9B28, 0xE9A8, + 0x9B29, 0xE9A9, 0x9B2A, 0xE9AA, 0x9B2E, 0xE9AB, 0x9B2F, 0xE9AC, 0x9B31, 0x9F54, 0x9B32, 0xE9AD, 0x9B3B, 0xE2F6, 0x9B3C, 0x8B53, + 0x9B41, 0x8A40, 0x9B42, 0x8DB0, 0x9B43, 0xE9AF, 0x9B44, 0xE9AE, 0x9B45, 0x96A3, 0x9B4D, 0xE9B1, 0x9B4E, 0xE9B2, 0x9B4F, 0xE9B0, + 0x9B51, 0xE9B3, 0x9B54, 0x9682, 0x9B58, 0xE9B4, 0x9B5A, 0x8B9B, 0x9B6F, 0x9844, 0x9B72, 0xFC42, 0x9B74, 0xE9B5, 0x9B75, 0xFC41, + 0x9B83, 0xE9B7, 0x9B8E, 0x88BC, 0x9B8F, 0xFC43, 0x9B91, 0xE9B8, 0x9B92, 0x95A9, 0x9B93, 0xE9B6, 0x9B96, 0xE9B9, 0x9B97, 0xE9BA, + 0x9B9F, 0xE9BB, 0x9BA0, 0xE9BC, 0x9BA8, 0xE9BD, 0x9BAA, 0x968E, 0x9BAB, 0x8E4C, 0x9BAD, 0x8DF8, 0x9BAE, 0x914E, 0x9BB1, 0xFC44, + 0x9BB4, 0xE9BE, 0x9BB9, 0xE9C1, 0x9BBB, 0xFC45, 0x9BC0, 0xE9BF, 0x9BC6, 0xE9C2, 0x9BC9, 0x8CEF, 0x9BCA, 0xE9C0, 0x9BCF, 0xE9C3, + 0x9BD1, 0xE9C4, 0x9BD2, 0xE9C5, 0x9BD4, 0xE9C9, 0x9BD6, 0x8E49, 0x9BDB, 0x91E2, 0x9BE1, 0xE9CA, 0x9BE2, 0xE9C7, 0x9BE3, 0xE9C6, + 0x9BE4, 0xE9C8, 0x9BE8, 0x8C7E, 0x9BF0, 0xE9CE, 0x9BF1, 0xE9CD, 0x9BF2, 0xE9CC, 0x9BF5, 0x88B1, 0x9C00, 0xFC46, 0x9C04, 0xE9D8, + 0x9C06, 0xE9D4, 0x9C08, 0xE9D5, 0x9C09, 0xE9D1, 0x9C0A, 0xE9D7, 0x9C0C, 0xE9D3, 0x9C0D, 0x8A82, 0x9C10, 0x986B, 0x9C12, 0xE9D6, + 0x9C13, 0xE9D2, 0x9C14, 0xE9D0, 0x9C15, 0xE9CF, 0x9C1B, 0xE9DA, 0x9C21, 0xE9DD, 0x9C24, 0xE9DC, 0x9C25, 0xE9DB, 0x9C2D, 0x9568, + 0x9C2E, 0xE9D9, 0x9C2F, 0x88F1, 0x9C30, 0xE9DE, 0x9C32, 0xE9E0, 0x9C39, 0x8A8F, 0x9C3A, 0xE9CB, 0x9C3B, 0x8956, 0x9C3E, 0xE9E2, + 0x9C46, 0xE9E1, 0x9C47, 0xE9DF, 0x9C48, 0x924C, 0x9C52, 0x9690, 0x9C57, 0x97D8, 0x9C5A, 0xE9E3, 0x9C60, 0xE9E4, 0x9C67, 0xE9E5, + 0x9C76, 0xE9E6, 0x9C78, 0xE9E7, 0x9CE5, 0x92B9, 0x9CE7, 0xE9E8, 0x9CE9, 0x94B5, 0x9CEB, 0xE9ED, 0x9CEC, 0xE9E9, 0x9CF0, 0xE9EA, + 0x9CF3, 0x9650, 0x9CF4, 0x96C2, 0x9CF6, 0x93CE, 0x9D03, 0xE9EE, 0x9D06, 0xE9EF, 0x9D07, 0x93BC, 0x9D08, 0xE9EC, 0x9D09, 0xE9EB, + 0x9D0E, 0x89A8, 0x9D12, 0xE9F7, 0x9D15, 0xE9F6, 0x9D1B, 0x8995, 0x9D1F, 0xE9F4, 0x9D23, 0xE9F3, 0x9D26, 0xE9F1, 0x9D28, 0x8A9B, + 0x9D2A, 0xE9F0, 0x9D2B, 0x8EB0, 0x9D2C, 0x89A7, 0x9D3B, 0x8D83, 0x9D3E, 0xE9FA, 0x9D3F, 0xE9F9, 0x9D41, 0xE9F8, 0x9D44, 0xE9F5, + 0x9D46, 0xE9FB, 0x9D48, 0xE9FC, 0x9D50, 0xEA44, 0x9D51, 0xEA43, 0x9D59, 0xEA45, 0x9D5C, 0x894C, 0x9D5D, 0xEA40, 0x9D5E, 0xEA41, + 0x9D60, 0x8D94, 0x9D61, 0x96B7, 0x9D64, 0xEA42, 0x9D6B, 0xFC48, 0x9D6C, 0x9651, 0x9D6F, 0xEA4A, 0x9D70, 0xFC47, 0x9D72, 0xEA46, + 0x9D7A, 0xEA4B, 0x9D87, 0xEA48, 0x9D89, 0xEA47, 0x9D8F, 0x8C7B, 0x9D9A, 0xEA4C, 0x9DA4, 0xEA4D, 0x9DA9, 0xEA4E, 0x9DAB, 0xEA49, + 0x9DAF, 0xE9F2, 0x9DB2, 0xEA4F, 0x9DB4, 0x92DF, 0x9DB8, 0xEA53, 0x9DBA, 0xEA54, 0x9DBB, 0xEA52, 0x9DC1, 0xEA51, 0x9DC2, 0xEA57, + 0x9DC4, 0xEA50, 0x9DC6, 0xEA55, 0x9DCF, 0xEA56, 0x9DD3, 0xEA59, 0x9DD9, 0xEA58, 0x9DE6, 0xEA5B, 0x9DED, 0xEA5C, 0x9DEF, 0xEA5D, + 0x9DF2, 0x9868, 0x9DF8, 0xEA5A, 0x9DF9, 0x91E9, 0x9DFA, 0x8DEB, 0x9DFD, 0xEA5E, 0x9E19, 0xFC4A, 0x9E1A, 0xEA5F, 0x9E1B, 0xEA60, + 0x9E1E, 0xEA61, 0x9E75, 0xEA62, 0x9E78, 0x8CB2, 0x9E79, 0xEA63, 0x9E7D, 0xEA64, 0x9E7F, 0x8EAD, 0x9E81, 0xEA65, 0x9E88, 0xEA66, + 0x9E8B, 0xEA67, 0x9E8C, 0xEA68, 0x9E91, 0xEA6B, 0x9E92, 0xEA69, 0x9E93, 0x985B, 0x9E95, 0xEA6A, 0x9E97, 0x97ED, 0x9E9D, 0xEA6C, + 0x9E9F, 0x97D9, 0x9EA5, 0xEA6D, 0x9EA6, 0x949E, 0x9EA9, 0xEA6E, 0x9EAA, 0xEA70, 0x9EAD, 0xEA71, 0x9EB8, 0xEA6F, 0x9EB9, 0x8D8D, + 0x9EBA, 0x96CB, 0x9EBB, 0x9683, 0x9EBC, 0x9BF5, 0x9EBE, 0x9F80, 0x9EBF, 0x969B, 0x9EC4, 0x89A9, 0x9ECC, 0xEA73, 0x9ECD, 0x8B6F, + 0x9ECE, 0xEA74, 0x9ECF, 0xEA75, 0x9ED0, 0xEA76, 0x9ED1, 0xFC4B, 0x9ED2, 0x8D95, 0x9ED4, 0xEA77, 0x9ED8, 0xE0D2, 0x9ED9, 0x96D9, + 0x9EDB, 0x91E1, 0x9EDC, 0xEA78, 0x9EDD, 0xEA7A, 0x9EDE, 0xEA79, 0x9EE0, 0xEA7B, 0x9EE5, 0xEA7C, 0x9EE8, 0xEA7D, 0x9EEF, 0xEA7E, + 0x9EF4, 0xEA80, 0x9EF6, 0xEA81, 0x9EF7, 0xEA82, 0x9EF9, 0xEA83, 0x9EFB, 0xEA84, 0x9EFC, 0xEA85, 0x9EFD, 0xEA86, 0x9F07, 0xEA87, + 0x9F08, 0xEA88, 0x9F0E, 0x9343, 0x9F13, 0x8CDB, 0x9F15, 0xEA8A, 0x9F20, 0x916C, 0x9F21, 0xEA8B, 0x9F2C, 0xEA8C, 0x9F3B, 0x9540, + 0x9F3E, 0xEA8D, 0x9F4A, 0xEA8E, 0x9F4B, 0xE256, 0x9F4E, 0xE6D8, 0x9F4F, 0xE8EB, 0x9F52, 0xEA8F, 0x9F54, 0xEA90, 0x9F5F, 0xEA92, + 0x9F60, 0xEA93, 0x9F61, 0xEA94, 0x9F62, 0x97EE, 0x9F63, 0xEA91, 0x9F66, 0xEA95, 0x9F67, 0xEA96, 0x9F6A, 0xEA98, 0x9F6C, 0xEA97, + 0x9F72, 0xEA9A, 0x9F76, 0xEA9B, 0x9F77, 0xEA99, 0x9F8D, 0x97B4, 0x9F95, 0xEA9C, 0x9F9C, 0xEA9D, 0x9F9D, 0xE273, 0x9FA0, 0xEA9E, + 0xF929, 0xFAE0, 0xF9DC, 0xFBE9, 0xFA0E, 0xFA90, 0xFA0F, 0xFA9B, 0xFA10, 0xFA9C, 0xFA11, 0xFAB1, 0xFA12, 0xFAD8, 0xFA13, 0xFAE8, + 0xFA14, 0xFAEA, 0xFA15, 0xFB58, 0xFA16, 0xFB5E, 0xFA17, 0xFB75, 0xFA18, 0xFB7D, 0xFA19, 0xFB7E, 0xFA1A, 0xFB80, 0xFA1B, 0xFB82, + 0xFA1C, 0xFB86, 0xFA1D, 0xFB89, 0xFA1E, 0xFB92, 0xFA1F, 0xFB9D, 0xFA20, 0xFB9F, 0xFA21, 0xFBA0, 0xFA22, 0xFBA9, 0xFA23, 0xFBB1, + 0xFA24, 0xFBB3, 0xFA25, 0xFBB4, 0xFA26, 0xFBB7, 0xFA27, 0xFBD3, 0xFA28, 0xFBDA, 0xFA29, 0xFBEA, 0xFA2A, 0xFBF6, 0xFA2B, 0xFBF7, + 0xFA2C, 0xFBF9, 0xFA2D, 0xFC49, 0xFF01, 0x8149, 0xFF02, 0xFA57, 0xFF03, 0x8194, 0xFF04, 0x8190, 0xFF05, 0x8193, 0xFF06, 0x8195, + 0xFF07, 0xFA56, 0xFF08, 0x8169, 0xFF09, 0x816A, 0xFF0A, 0x8196, 0xFF0B, 0x817B, 0xFF0C, 0x8143, 0xFF0D, 0x817C, 0xFF0E, 0x8144, + 0xFF0F, 0x815E, 0xFF10, 0x824F, 0xFF11, 0x8250, 0xFF12, 0x8251, 0xFF13, 0x8252, 0xFF14, 0x8253, 0xFF15, 0x8254, 0xFF16, 0x8255, + 0xFF17, 0x8256, 0xFF18, 0x8257, 0xFF19, 0x8258, 0xFF1A, 0x8146, 0xFF1B, 0x8147, 0xFF1C, 0x8183, 0xFF1D, 0x8181, 0xFF1E, 0x8184, + 0xFF1F, 0x8148, 0xFF20, 0x8197, 0xFF21, 0x8260, 0xFF22, 0x8261, 0xFF23, 0x8262, 0xFF24, 0x8263, 0xFF25, 0x8264, 0xFF26, 0x8265, + 0xFF27, 0x8266, 0xFF28, 0x8267, 0xFF29, 0x8268, 0xFF2A, 0x8269, 0xFF2B, 0x826A, 0xFF2C, 0x826B, 0xFF2D, 0x826C, 0xFF2E, 0x826D, + 0xFF2F, 0x826E, 0xFF30, 0x826F, 0xFF31, 0x8270, 0xFF32, 0x8271, 0xFF33, 0x8272, 0xFF34, 0x8273, 0xFF35, 0x8274, 0xFF36, 0x8275, + 0xFF37, 0x8276, 0xFF38, 0x8277, 0xFF39, 0x8278, 0xFF3A, 0x8279, 0xFF3B, 0x816D, 0xFF3C, 0x815F, 0xFF3D, 0x816E, 0xFF3E, 0x814F, + 0xFF3F, 0x8151, 0xFF40, 0x814D, 0xFF41, 0x8281, 0xFF42, 0x8282, 0xFF43, 0x8283, 0xFF44, 0x8284, 0xFF45, 0x8285, 0xFF46, 0x8286, + 0xFF47, 0x8287, 0xFF48, 0x8288, 0xFF49, 0x8289, 0xFF4A, 0x828A, 0xFF4B, 0x828B, 0xFF4C, 0x828C, 0xFF4D, 0x828D, 0xFF4E, 0x828E, + 0xFF4F, 0x828F, 0xFF50, 0x8290, 0xFF51, 0x8291, 0xFF52, 0x8292, 0xFF53, 0x8293, 0xFF54, 0x8294, 0xFF55, 0x8295, 0xFF56, 0x8296, + 0xFF57, 0x8297, 0xFF58, 0x8298, 0xFF59, 0x8299, 0xFF5A, 0x829A, 0xFF5B, 0x816F, 0xFF5C, 0x8162, 0xFF5D, 0x8170, 0xFF5E, 0x8160, + 0xFF61, 0x00A1, 0xFF62, 0x00A2, 0xFF63, 0x00A3, 0xFF64, 0x00A4, 0xFF65, 0x00A5, 0xFF66, 0x00A6, 0xFF67, 0x00A7, 0xFF68, 0x00A8, + 0xFF69, 0x00A9, 0xFF6A, 0x00AA, 0xFF6B, 0x00AB, 0xFF6C, 0x00AC, 0xFF6D, 0x00AD, 0xFF6E, 0x00AE, 0xFF6F, 0x00AF, 0xFF70, 0x00B0, + 0xFF71, 0x00B1, 0xFF72, 0x00B2, 0xFF73, 0x00B3, 0xFF74, 0x00B4, 0xFF75, 0x00B5, 0xFF76, 0x00B6, 0xFF77, 0x00B7, 0xFF78, 0x00B8, + 0xFF79, 0x00B9, 0xFF7A, 0x00BA, 0xFF7B, 0x00BB, 0xFF7C, 0x00BC, 0xFF7D, 0x00BD, 0xFF7E, 0x00BE, 0xFF7F, 0x00BF, 0xFF80, 0x00C0, + 0xFF81, 0x00C1, 0xFF82, 0x00C2, 0xFF83, 0x00C3, 0xFF84, 0x00C4, 0xFF85, 0x00C5, 0xFF86, 0x00C6, 0xFF87, 0x00C7, 0xFF88, 0x00C8, + 0xFF89, 0x00C9, 0xFF8A, 0x00CA, 0xFF8B, 0x00CB, 0xFF8C, 0x00CC, 0xFF8D, 0x00CD, 0xFF8E, 0x00CE, 0xFF8F, 0x00CF, 0xFF90, 0x00D0, + 0xFF91, 0x00D1, 0xFF92, 0x00D2, 0xFF93, 0x00D3, 0xFF94, 0x00D4, 0xFF95, 0x00D5, 0xFF96, 0x00D6, 0xFF97, 0x00D7, 0xFF98, 0x00D8, + 0xFF99, 0x00D9, 0xFF9A, 0x00DA, 0xFF9B, 0x00DB, 0xFF9C, 0x00DC, 0xFF9D, 0x00DD, 0xFF9E, 0x00DE, 0xFF9F, 0x00DF, 0xFFE0, 0x8191, + 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0 +}; + +static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ + 0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68, + 0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70, + 0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78, + 0x00B9, 0xFF79, 0x00BA, 0xFF7A, 0x00BB, 0xFF7B, 0x00BC, 0xFF7C, 0x00BD, 0xFF7D, 0x00BE, 0xFF7E, 0x00BF, 0xFF7F, 0x00C0, 0xFF80, + 0x00C1, 0xFF81, 0x00C2, 0xFF82, 0x00C3, 0xFF83, 0x00C4, 0xFF84, 0x00C5, 0xFF85, 0x00C6, 0xFF86, 0x00C7, 0xFF87, 0x00C8, 0xFF88, + 0x00C9, 0xFF89, 0x00CA, 0xFF8A, 0x00CB, 0xFF8B, 0x00CC, 0xFF8C, 0x00CD, 0xFF8D, 0x00CE, 0xFF8E, 0x00CF, 0xFF8F, 0x00D0, 0xFF90, + 0x00D1, 0xFF91, 0x00D2, 0xFF92, 0x00D3, 0xFF93, 0x00D4, 0xFF94, 0x00D5, 0xFF95, 0x00D6, 0xFF96, 0x00D7, 0xFF97, 0x00D8, 0xFF98, + 0x00D9, 0xFF99, 0x00DA, 0xFF9A, 0x00DB, 0xFF9B, 0x00DC, 0xFF9C, 0x00DD, 0xFF9D, 0x00DE, 0xFF9E, 0x00DF, 0xFF9F, 0x8140, 0x3000, + 0x8141, 0x3001, 0x8142, 0x3002, 0x8143, 0xFF0C, 0x8144, 0xFF0E, 0x8145, 0x30FB, 0x8146, 0xFF1A, 0x8147, 0xFF1B, 0x8148, 0xFF1F, + 0x8149, 0xFF01, 0x814A, 0x309B, 0x814B, 0x309C, 0x814C, 0x00B4, 0x814D, 0xFF40, 0x814E, 0x00A8, 0x814F, 0xFF3E, 0x8150, 0xFFE3, + 0x8151, 0xFF3F, 0x8152, 0x30FD, 0x8153, 0x30FE, 0x8154, 0x309D, 0x8155, 0x309E, 0x8156, 0x3003, 0x8157, 0x4EDD, 0x8158, 0x3005, + 0x8159, 0x3006, 0x815A, 0x3007, 0x815B, 0x30FC, 0x815C, 0x2015, 0x815D, 0x2010, 0x815E, 0xFF0F, 0x815F, 0xFF3C, 0x8160, 0xFF5E, + 0x8161, 0x2225, 0x8162, 0xFF5C, 0x8163, 0x2026, 0x8164, 0x2025, 0x8165, 0x2018, 0x8166, 0x2019, 0x8167, 0x201C, 0x8168, 0x201D, + 0x8169, 0xFF08, 0x816A, 0xFF09, 0x816B, 0x3014, 0x816C, 0x3015, 0x816D, 0xFF3B, 0x816E, 0xFF3D, 0x816F, 0xFF5B, 0x8170, 0xFF5D, + 0x8171, 0x3008, 0x8172, 0x3009, 0x8173, 0x300A, 0x8174, 0x300B, 0x8175, 0x300C, 0x8176, 0x300D, 0x8177, 0x300E, 0x8178, 0x300F, + 0x8179, 0x3010, 0x817A, 0x3011, 0x817B, 0xFF0B, 0x817C, 0xFF0D, 0x817D, 0x00B1, 0x817E, 0x00D7, 0x8180, 0x00F7, 0x8181, 0xFF1D, + 0x8182, 0x2260, 0x8183, 0xFF1C, 0x8184, 0xFF1E, 0x8185, 0x2266, 0x8186, 0x2267, 0x8187, 0x221E, 0x8188, 0x2234, 0x8189, 0x2642, + 0x818A, 0x2640, 0x818B, 0x00B0, 0x818C, 0x2032, 0x818D, 0x2033, 0x818E, 0x2103, 0x818F, 0xFFE5, 0x8190, 0xFF04, 0x8191, 0xFFE0, + 0x8192, 0xFFE1, 0x8193, 0xFF05, 0x8194, 0xFF03, 0x8195, 0xFF06, 0x8196, 0xFF0A, 0x8197, 0xFF20, 0x8198, 0x00A7, 0x8199, 0x2606, + 0x819A, 0x2605, 0x819B, 0x25CB, 0x819C, 0x25CF, 0x819D, 0x25CE, 0x819E, 0x25C7, 0x819F, 0x25C6, 0x81A0, 0x25A1, 0x81A1, 0x25A0, + 0x81A2, 0x25B3, 0x81A3, 0x25B2, 0x81A4, 0x25BD, 0x81A5, 0x25BC, 0x81A6, 0x203B, 0x81A7, 0x3012, 0x81A8, 0x2192, 0x81A9, 0x2190, + 0x81AA, 0x2191, 0x81AB, 0x2193, 0x81AC, 0x3013, 0x81B8, 0x2208, 0x81B9, 0x220B, 0x81BA, 0x2286, 0x81BB, 0x2287, 0x81BC, 0x2282, + 0x81BD, 0x2283, 0x81BE, 0x222A, 0x81BF, 0x2229, 0x81C8, 0x2227, 0x81C9, 0x2228, 0x81CA, 0xFFE2, 0x81CB, 0x21D2, 0x81CC, 0x21D4, + 0x81CD, 0x2200, 0x81CE, 0x2203, 0x81DA, 0x2220, 0x81DB, 0x22A5, 0x81DC, 0x2312, 0x81DD, 0x2202, 0x81DE, 0x2207, 0x81DF, 0x2261, + 0x81E0, 0x2252, 0x81E1, 0x226A, 0x81E2, 0x226B, 0x81E3, 0x221A, 0x81E4, 0x223D, 0x81E5, 0x221D, 0x81E6, 0x2235, 0x81E7, 0x222B, + 0x81E8, 0x222C, 0x81F0, 0x212B, 0x81F1, 0x2030, 0x81F2, 0x266F, 0x81F3, 0x266D, 0x81F4, 0x266A, 0x81F5, 0x2020, 0x81F6, 0x2021, + 0x81F7, 0x00B6, 0x81FC, 0x25EF, 0x824F, 0xFF10, 0x8250, 0xFF11, 0x8251, 0xFF12, 0x8252, 0xFF13, 0x8253, 0xFF14, 0x8254, 0xFF15, + 0x8255, 0xFF16, 0x8256, 0xFF17, 0x8257, 0xFF18, 0x8258, 0xFF19, 0x8260, 0xFF21, 0x8261, 0xFF22, 0x8262, 0xFF23, 0x8263, 0xFF24, + 0x8264, 0xFF25, 0x8265, 0xFF26, 0x8266, 0xFF27, 0x8267, 0xFF28, 0x8268, 0xFF29, 0x8269, 0xFF2A, 0x826A, 0xFF2B, 0x826B, 0xFF2C, + 0x826C, 0xFF2D, 0x826D, 0xFF2E, 0x826E, 0xFF2F, 0x826F, 0xFF30, 0x8270, 0xFF31, 0x8271, 0xFF32, 0x8272, 0xFF33, 0x8273, 0xFF34, + 0x8274, 0xFF35, 0x8275, 0xFF36, 0x8276, 0xFF37, 0x8277, 0xFF38, 0x8278, 0xFF39, 0x8279, 0xFF3A, 0x8281, 0xFF41, 0x8282, 0xFF42, + 0x8283, 0xFF43, 0x8284, 0xFF44, 0x8285, 0xFF45, 0x8286, 0xFF46, 0x8287, 0xFF47, 0x8288, 0xFF48, 0x8289, 0xFF49, 0x828A, 0xFF4A, + 0x828B, 0xFF4B, 0x828C, 0xFF4C, 0x828D, 0xFF4D, 0x828E, 0xFF4E, 0x828F, 0xFF4F, 0x8290, 0xFF50, 0x8291, 0xFF51, 0x8292, 0xFF52, + 0x8293, 0xFF53, 0x8294, 0xFF54, 0x8295, 0xFF55, 0x8296, 0xFF56, 0x8297, 0xFF57, 0x8298, 0xFF58, 0x8299, 0xFF59, 0x829A, 0xFF5A, + 0x829F, 0x3041, 0x82A0, 0x3042, 0x82A1, 0x3043, 0x82A2, 0x3044, 0x82A3, 0x3045, 0x82A4, 0x3046, 0x82A5, 0x3047, 0x82A6, 0x3048, + 0x82A7, 0x3049, 0x82A8, 0x304A, 0x82A9, 0x304B, 0x82AA, 0x304C, 0x82AB, 0x304D, 0x82AC, 0x304E, 0x82AD, 0x304F, 0x82AE, 0x3050, + 0x82AF, 0x3051, 0x82B0, 0x3052, 0x82B1, 0x3053, 0x82B2, 0x3054, 0x82B3, 0x3055, 0x82B4, 0x3056, 0x82B5, 0x3057, 0x82B6, 0x3058, + 0x82B7, 0x3059, 0x82B8, 0x305A, 0x82B9, 0x305B, 0x82BA, 0x305C, 0x82BB, 0x305D, 0x82BC, 0x305E, 0x82BD, 0x305F, 0x82BE, 0x3060, + 0x82BF, 0x3061, 0x82C0, 0x3062, 0x82C1, 0x3063, 0x82C2, 0x3064, 0x82C3, 0x3065, 0x82C4, 0x3066, 0x82C5, 0x3067, 0x82C6, 0x3068, + 0x82C7, 0x3069, 0x82C8, 0x306A, 0x82C9, 0x306B, 0x82CA, 0x306C, 0x82CB, 0x306D, 0x82CC, 0x306E, 0x82CD, 0x306F, 0x82CE, 0x3070, + 0x82CF, 0x3071, 0x82D0, 0x3072, 0x82D1, 0x3073, 0x82D2, 0x3074, 0x82D3, 0x3075, 0x82D4, 0x3076, 0x82D5, 0x3077, 0x82D6, 0x3078, + 0x82D7, 0x3079, 0x82D8, 0x307A, 0x82D9, 0x307B, 0x82DA, 0x307C, 0x82DB, 0x307D, 0x82DC, 0x307E, 0x82DD, 0x307F, 0x82DE, 0x3080, + 0x82DF, 0x3081, 0x82E0, 0x3082, 0x82E1, 0x3083, 0x82E2, 0x3084, 0x82E3, 0x3085, 0x82E4, 0x3086, 0x82E5, 0x3087, 0x82E6, 0x3088, + 0x82E7, 0x3089, 0x82E8, 0x308A, 0x82E9, 0x308B, 0x82EA, 0x308C, 0x82EB, 0x308D, 0x82EC, 0x308E, 0x82ED, 0x308F, 0x82EE, 0x3090, + 0x82EF, 0x3091, 0x82F0, 0x3092, 0x82F1, 0x3093, 0x8340, 0x30A1, 0x8341, 0x30A2, 0x8342, 0x30A3, 0x8343, 0x30A4, 0x8344, 0x30A5, + 0x8345, 0x30A6, 0x8346, 0x30A7, 0x8347, 0x30A8, 0x8348, 0x30A9, 0x8349, 0x30AA, 0x834A, 0x30AB, 0x834B, 0x30AC, 0x834C, 0x30AD, + 0x834D, 0x30AE, 0x834E, 0x30AF, 0x834F, 0x30B0, 0x8350, 0x30B1, 0x8351, 0x30B2, 0x8352, 0x30B3, 0x8353, 0x30B4, 0x8354, 0x30B5, + 0x8355, 0x30B6, 0x8356, 0x30B7, 0x8357, 0x30B8, 0x8358, 0x30B9, 0x8359, 0x30BA, 0x835A, 0x30BB, 0x835B, 0x30BC, 0x835C, 0x30BD, + 0x835D, 0x30BE, 0x835E, 0x30BF, 0x835F, 0x30C0, 0x8360, 0x30C1, 0x8361, 0x30C2, 0x8362, 0x30C3, 0x8363, 0x30C4, 0x8364, 0x30C5, + 0x8365, 0x30C6, 0x8366, 0x30C7, 0x8367, 0x30C8, 0x8368, 0x30C9, 0x8369, 0x30CA, 0x836A, 0x30CB, 0x836B, 0x30CC, 0x836C, 0x30CD, + 0x836D, 0x30CE, 0x836E, 0x30CF, 0x836F, 0x30D0, 0x8370, 0x30D1, 0x8371, 0x30D2, 0x8372, 0x30D3, 0x8373, 0x30D4, 0x8374, 0x30D5, + 0x8375, 0x30D6, 0x8376, 0x30D7, 0x8377, 0x30D8, 0x8378, 0x30D9, 0x8379, 0x30DA, 0x837A, 0x30DB, 0x837B, 0x30DC, 0x837C, 0x30DD, + 0x837D, 0x30DE, 0x837E, 0x30DF, 0x8380, 0x30E0, 0x8381, 0x30E1, 0x8382, 0x30E2, 0x8383, 0x30E3, 0x8384, 0x30E4, 0x8385, 0x30E5, + 0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9, 0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED, + 0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1, 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4, 0x8395, 0x30F5, + 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392, 0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396, 0x83A5, 0x0397, + 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A, 0x83A9, 0x039B, 0x83AA, 0x039C, 0x83AB, 0x039D, 0x83AC, 0x039E, 0x83AD, 0x039F, + 0x83AE, 0x03A0, 0x83AF, 0x03A1, 0x83B0, 0x03A3, 0x83B1, 0x03A4, 0x83B2, 0x03A5, 0x83B3, 0x03A6, 0x83B4, 0x03A7, 0x83B5, 0x03A8, + 0x83B6, 0x03A9, 0x83BF, 0x03B1, 0x83C0, 0x03B2, 0x83C1, 0x03B3, 0x83C2, 0x03B4, 0x83C3, 0x03B5, 0x83C4, 0x03B6, 0x83C5, 0x03B7, + 0x83C6, 0x03B8, 0x83C7, 0x03B9, 0x83C8, 0x03BA, 0x83C9, 0x03BB, 0x83CA, 0x03BC, 0x83CB, 0x03BD, 0x83CC, 0x03BE, 0x83CD, 0x03BF, + 0x83CE, 0x03C0, 0x83CF, 0x03C1, 0x83D0, 0x03C3, 0x83D1, 0x03C4, 0x83D2, 0x03C5, 0x83D3, 0x03C6, 0x83D4, 0x03C7, 0x83D5, 0x03C8, + 0x83D6, 0x03C9, 0x8440, 0x0410, 0x8441, 0x0411, 0x8442, 0x0412, 0x8443, 0x0413, 0x8444, 0x0414, 0x8445, 0x0415, 0x8446, 0x0401, + 0x8447, 0x0416, 0x8448, 0x0417, 0x8449, 0x0418, 0x844A, 0x0419, 0x844B, 0x041A, 0x844C, 0x041B, 0x844D, 0x041C, 0x844E, 0x041D, + 0x844F, 0x041E, 0x8450, 0x041F, 0x8451, 0x0420, 0x8452, 0x0421, 0x8453, 0x0422, 0x8454, 0x0423, 0x8455, 0x0424, 0x8456, 0x0425, + 0x8457, 0x0426, 0x8458, 0x0427, 0x8459, 0x0428, 0x845A, 0x0429, 0x845B, 0x042A, 0x845C, 0x042B, 0x845D, 0x042C, 0x845E, 0x042D, + 0x845F, 0x042E, 0x8460, 0x042F, 0x8470, 0x0430, 0x8471, 0x0431, 0x8472, 0x0432, 0x8473, 0x0433, 0x8474, 0x0434, 0x8475, 0x0435, + 0x8476, 0x0451, 0x8477, 0x0436, 0x8478, 0x0437, 0x8479, 0x0438, 0x847A, 0x0439, 0x847B, 0x043A, 0x847C, 0x043B, 0x847D, 0x043C, + 0x847E, 0x043D, 0x8480, 0x043E, 0x8481, 0x043F, 0x8482, 0x0440, 0x8483, 0x0441, 0x8484, 0x0442, 0x8485, 0x0443, 0x8486, 0x0444, + 0x8487, 0x0445, 0x8488, 0x0446, 0x8489, 0x0447, 0x848A, 0x0448, 0x848B, 0x0449, 0x848C, 0x044A, 0x848D, 0x044B, 0x848E, 0x044C, + 0x848F, 0x044D, 0x8490, 0x044E, 0x8491, 0x044F, 0x849F, 0x2500, 0x84A0, 0x2502, 0x84A1, 0x250C, 0x84A2, 0x2510, 0x84A3, 0x2518, + 0x84A4, 0x2514, 0x84A5, 0x251C, 0x84A6, 0x252C, 0x84A7, 0x2524, 0x84A8, 0x2534, 0x84A9, 0x253C, 0x84AA, 0x2501, 0x84AB, 0x2503, + 0x84AC, 0x250F, 0x84AD, 0x2513, 0x84AE, 0x251B, 0x84AF, 0x2517, 0x84B0, 0x2523, 0x84B1, 0x2533, 0x84B2, 0x252B, 0x84B3, 0x253B, + 0x84B4, 0x254B, 0x84B5, 0x2520, 0x84B6, 0x252F, 0x84B7, 0x2528, 0x84B8, 0x2537, 0x84B9, 0x253F, 0x84BA, 0x251D, 0x84BB, 0x2530, + 0x84BC, 0x2525, 0x84BD, 0x2538, 0x84BE, 0x2542, 0x8740, 0x2460, 0x8741, 0x2461, 0x8742, 0x2462, 0x8743, 0x2463, 0x8744, 0x2464, + 0x8745, 0x2465, 0x8746, 0x2466, 0x8747, 0x2467, 0x8748, 0x2468, 0x8749, 0x2469, 0x874A, 0x246A, 0x874B, 0x246B, 0x874C, 0x246C, + 0x874D, 0x246D, 0x874E, 0x246E, 0x874F, 0x246F, 0x8750, 0x2470, 0x8751, 0x2471, 0x8752, 0x2472, 0x8753, 0x2473, 0x8754, 0x2160, + 0x8755, 0x2161, 0x8756, 0x2162, 0x8757, 0x2163, 0x8758, 0x2164, 0x8759, 0x2165, 0x875A, 0x2166, 0x875B, 0x2167, 0x875C, 0x2168, + 0x875D, 0x2169, 0x875F, 0x3349, 0x8760, 0x3314, 0x8761, 0x3322, 0x8762, 0x334D, 0x8763, 0x3318, 0x8764, 0x3327, 0x8765, 0x3303, + 0x8766, 0x3336, 0x8767, 0x3351, 0x8768, 0x3357, 0x8769, 0x330D, 0x876A, 0x3326, 0x876B, 0x3323, 0x876C, 0x332B, 0x876D, 0x334A, + 0x876E, 0x333B, 0x876F, 0x339C, 0x8770, 0x339D, 0x8771, 0x339E, 0x8772, 0x338E, 0x8773, 0x338F, 0x8774, 0x33C4, 0x8775, 0x33A1, + 0x877E, 0x337B, 0x8780, 0x301D, 0x8781, 0x301F, 0x8782, 0x2116, 0x8783, 0x33CD, 0x8784, 0x2121, 0x8785, 0x32A4, 0x8786, 0x32A5, + 0x8787, 0x32A6, 0x8788, 0x32A7, 0x8789, 0x32A8, 0x878A, 0x3231, 0x878B, 0x3232, 0x878C, 0x3239, 0x878D, 0x337E, 0x878E, 0x337D, + 0x878F, 0x337C, 0x8793, 0x222E, 0x8794, 0x2211, 0x8798, 0x221F, 0x8799, 0x22BF, 0x889F, 0x4E9C, 0x88A0, 0x5516, 0x88A1, 0x5A03, + 0x88A2, 0x963F, 0x88A3, 0x54C0, 0x88A4, 0x611B, 0x88A5, 0x6328, 0x88A6, 0x59F6, 0x88A7, 0x9022, 0x88A8, 0x8475, 0x88A9, 0x831C, + 0x88AA, 0x7A50, 0x88AB, 0x60AA, 0x88AC, 0x63E1, 0x88AD, 0x6E25, 0x88AE, 0x65ED, 0x88AF, 0x8466, 0x88B0, 0x82A6, 0x88B1, 0x9BF5, + 0x88B2, 0x6893, 0x88B3, 0x5727, 0x88B4, 0x65A1, 0x88B5, 0x6271, 0x88B6, 0x5B9B, 0x88B7, 0x59D0, 0x88B8, 0x867B, 0x88B9, 0x98F4, + 0x88BA, 0x7D62, 0x88BB, 0x7DBE, 0x88BC, 0x9B8E, 0x88BD, 0x6216, 0x88BE, 0x7C9F, 0x88BF, 0x88B7, 0x88C0, 0x5B89, 0x88C1, 0x5EB5, + 0x88C2, 0x6309, 0x88C3, 0x6697, 0x88C4, 0x6848, 0x88C5, 0x95C7, 0x88C6, 0x978D, 0x88C7, 0x674F, 0x88C8, 0x4EE5, 0x88C9, 0x4F0A, + 0x88CA, 0x4F4D, 0x88CB, 0x4F9D, 0x88CC, 0x5049, 0x88CD, 0x56F2, 0x88CE, 0x5937, 0x88CF, 0x59D4, 0x88D0, 0x5A01, 0x88D1, 0x5C09, + 0x88D2, 0x60DF, 0x88D3, 0x610F, 0x88D4, 0x6170, 0x88D5, 0x6613, 0x88D6, 0x6905, 0x88D7, 0x70BA, 0x88D8, 0x754F, 0x88D9, 0x7570, + 0x88DA, 0x79FB, 0x88DB, 0x7DAD, 0x88DC, 0x7DEF, 0x88DD, 0x80C3, 0x88DE, 0x840E, 0x88DF, 0x8863, 0x88E0, 0x8B02, 0x88E1, 0x9055, + 0x88E2, 0x907A, 0x88E3, 0x533B, 0x88E4, 0x4E95, 0x88E5, 0x4EA5, 0x88E6, 0x57DF, 0x88E7, 0x80B2, 0x88E8, 0x90C1, 0x88E9, 0x78EF, + 0x88EA, 0x4E00, 0x88EB, 0x58F1, 0x88EC, 0x6EA2, 0x88ED, 0x9038, 0x88EE, 0x7A32, 0x88EF, 0x8328, 0x88F0, 0x828B, 0x88F1, 0x9C2F, + 0x88F2, 0x5141, 0x88F3, 0x5370, 0x88F4, 0x54BD, 0x88F5, 0x54E1, 0x88F6, 0x56E0, 0x88F7, 0x59FB, 0x88F8, 0x5F15, 0x88F9, 0x98F2, + 0x88FA, 0x6DEB, 0x88FB, 0x80E4, 0x88FC, 0x852D, 0x8940, 0x9662, 0x8941, 0x9670, 0x8942, 0x96A0, 0x8943, 0x97FB, 0x8944, 0x540B, + 0x8945, 0x53F3, 0x8946, 0x5B87, 0x8947, 0x70CF, 0x8948, 0x7FBD, 0x8949, 0x8FC2, 0x894A, 0x96E8, 0x894B, 0x536F, 0x894C, 0x9D5C, + 0x894D, 0x7ABA, 0x894E, 0x4E11, 0x894F, 0x7893, 0x8950, 0x81FC, 0x8951, 0x6E26, 0x8952, 0x5618, 0x8953, 0x5504, 0x8954, 0x6B1D, + 0x8955, 0x851A, 0x8956, 0x9C3B, 0x8957, 0x59E5, 0x8958, 0x53A9, 0x8959, 0x6D66, 0x895A, 0x74DC, 0x895B, 0x958F, 0x895C, 0x5642, + 0x895D, 0x4E91, 0x895E, 0x904B, 0x895F, 0x96F2, 0x8960, 0x834F, 0x8961, 0x990C, 0x8962, 0x53E1, 0x8963, 0x55B6, 0x8964, 0x5B30, + 0x8965, 0x5F71, 0x8966, 0x6620, 0x8967, 0x66F3, 0x8968, 0x6804, 0x8969, 0x6C38, 0x896A, 0x6CF3, 0x896B, 0x6D29, 0x896C, 0x745B, + 0x896D, 0x76C8, 0x896E, 0x7A4E, 0x896F, 0x9834, 0x8970, 0x82F1, 0x8971, 0x885B, 0x8972, 0x8A60, 0x8973, 0x92ED, 0x8974, 0x6DB2, + 0x8975, 0x75AB, 0x8976, 0x76CA, 0x8977, 0x99C5, 0x8978, 0x60A6, 0x8979, 0x8B01, 0x897A, 0x8D8A, 0x897B, 0x95B2, 0x897C, 0x698E, + 0x897D, 0x53AD, 0x897E, 0x5186, 0x8980, 0x5712, 0x8981, 0x5830, 0x8982, 0x5944, 0x8983, 0x5BB4, 0x8984, 0x5EF6, 0x8985, 0x6028, + 0x8986, 0x63A9, 0x8987, 0x63F4, 0x8988, 0x6CBF, 0x8989, 0x6F14, 0x898A, 0x708E, 0x898B, 0x7114, 0x898C, 0x7159, 0x898D, 0x71D5, + 0x898E, 0x733F, 0x898F, 0x7E01, 0x8990, 0x8276, 0x8991, 0x82D1, 0x8992, 0x8597, 0x8993, 0x9060, 0x8994, 0x925B, 0x8995, 0x9D1B, + 0x8996, 0x5869, 0x8997, 0x65BC, 0x8998, 0x6C5A, 0x8999, 0x7525, 0x899A, 0x51F9, 0x899B, 0x592E, 0x899C, 0x5965, 0x899D, 0x5F80, + 0x899E, 0x5FDC, 0x899F, 0x62BC, 0x89A0, 0x65FA, 0x89A1, 0x6A2A, 0x89A2, 0x6B27, 0x89A3, 0x6BB4, 0x89A4, 0x738B, 0x89A5, 0x7FC1, + 0x89A6, 0x8956, 0x89A7, 0x9D2C, 0x89A8, 0x9D0E, 0x89A9, 0x9EC4, 0x89AA, 0x5CA1, 0x89AB, 0x6C96, 0x89AC, 0x837B, 0x89AD, 0x5104, + 0x89AE, 0x5C4B, 0x89AF, 0x61B6, 0x89B0, 0x81C6, 0x89B1, 0x6876, 0x89B2, 0x7261, 0x89B3, 0x4E59, 0x89B4, 0x4FFA, 0x89B5, 0x5378, + 0x89B6, 0x6069, 0x89B7, 0x6E29, 0x89B8, 0x7A4F, 0x89B9, 0x97F3, 0x89BA, 0x4E0B, 0x89BB, 0x5316, 0x89BC, 0x4EEE, 0x89BD, 0x4F55, + 0x89BE, 0x4F3D, 0x89BF, 0x4FA1, 0x89C0, 0x4F73, 0x89C1, 0x52A0, 0x89C2, 0x53EF, 0x89C3, 0x5609, 0x89C4, 0x590F, 0x89C5, 0x5AC1, + 0x89C6, 0x5BB6, 0x89C7, 0x5BE1, 0x89C8, 0x79D1, 0x89C9, 0x6687, 0x89CA, 0x679C, 0x89CB, 0x67B6, 0x89CC, 0x6B4C, 0x89CD, 0x6CB3, + 0x89CE, 0x706B, 0x89CF, 0x73C2, 0x89D0, 0x798D, 0x89D1, 0x79BE, 0x89D2, 0x7A3C, 0x89D3, 0x7B87, 0x89D4, 0x82B1, 0x89D5, 0x82DB, + 0x89D6, 0x8304, 0x89D7, 0x8377, 0x89D8, 0x83EF, 0x89D9, 0x83D3, 0x89DA, 0x8766, 0x89DB, 0x8AB2, 0x89DC, 0x5629, 0x89DD, 0x8CA8, + 0x89DE, 0x8FE6, 0x89DF, 0x904E, 0x89E0, 0x971E, 0x89E1, 0x868A, 0x89E2, 0x4FC4, 0x89E3, 0x5CE8, 0x89E4, 0x6211, 0x89E5, 0x7259, + 0x89E6, 0x753B, 0x89E7, 0x81E5, 0x89E8, 0x82BD, 0x89E9, 0x86FE, 0x89EA, 0x8CC0, 0x89EB, 0x96C5, 0x89EC, 0x9913, 0x89ED, 0x99D5, + 0x89EE, 0x4ECB, 0x89EF, 0x4F1A, 0x89F0, 0x89E3, 0x89F1, 0x56DE, 0x89F2, 0x584A, 0x89F3, 0x58CA, 0x89F4, 0x5EFB, 0x89F5, 0x5FEB, + 0x89F6, 0x602A, 0x89F7, 0x6094, 0x89F8, 0x6062, 0x89F9, 0x61D0, 0x89FA, 0x6212, 0x89FB, 0x62D0, 0x89FC, 0x6539, 0x8A40, 0x9B41, + 0x8A41, 0x6666, 0x8A42, 0x68B0, 0x8A43, 0x6D77, 0x8A44, 0x7070, 0x8A45, 0x754C, 0x8A46, 0x7686, 0x8A47, 0x7D75, 0x8A48, 0x82A5, + 0x8A49, 0x87F9, 0x8A4A, 0x958B, 0x8A4B, 0x968E, 0x8A4C, 0x8C9D, 0x8A4D, 0x51F1, 0x8A4E, 0x52BE, 0x8A4F, 0x5916, 0x8A50, 0x54B3, + 0x8A51, 0x5BB3, 0x8A52, 0x5D16, 0x8A53, 0x6168, 0x8A54, 0x6982, 0x8A55, 0x6DAF, 0x8A56, 0x788D, 0x8A57, 0x84CB, 0x8A58, 0x8857, + 0x8A59, 0x8A72, 0x8A5A, 0x93A7, 0x8A5B, 0x9AB8, 0x8A5C, 0x6D6C, 0x8A5D, 0x99A8, 0x8A5E, 0x86D9, 0x8A5F, 0x57A3, 0x8A60, 0x67FF, + 0x8A61, 0x86CE, 0x8A62, 0x920E, 0x8A63, 0x5283, 0x8A64, 0x5687, 0x8A65, 0x5404, 0x8A66, 0x5ED3, 0x8A67, 0x62E1, 0x8A68, 0x64B9, + 0x8A69, 0x683C, 0x8A6A, 0x6838, 0x8A6B, 0x6BBB, 0x8A6C, 0x7372, 0x8A6D, 0x78BA, 0x8A6E, 0x7A6B, 0x8A6F, 0x899A, 0x8A70, 0x89D2, + 0x8A71, 0x8D6B, 0x8A72, 0x8F03, 0x8A73, 0x90ED, 0x8A74, 0x95A3, 0x8A75, 0x9694, 0x8A76, 0x9769, 0x8A77, 0x5B66, 0x8A78, 0x5CB3, + 0x8A79, 0x697D, 0x8A7A, 0x984D, 0x8A7B, 0x984E, 0x8A7C, 0x639B, 0x8A7D, 0x7B20, 0x8A7E, 0x6A2B, 0x8A80, 0x6A7F, 0x8A81, 0x68B6, + 0x8A82, 0x9C0D, 0x8A83, 0x6F5F, 0x8A84, 0x5272, 0x8A85, 0x559D, 0x8A86, 0x6070, 0x8A87, 0x62EC, 0x8A88, 0x6D3B, 0x8A89, 0x6E07, + 0x8A8A, 0x6ED1, 0x8A8B, 0x845B, 0x8A8C, 0x8910, 0x8A8D, 0x8F44, 0x8A8E, 0x4E14, 0x8A8F, 0x9C39, 0x8A90, 0x53F6, 0x8A91, 0x691B, + 0x8A92, 0x6A3A, 0x8A93, 0x9784, 0x8A94, 0x682A, 0x8A95, 0x515C, 0x8A96, 0x7AC3, 0x8A97, 0x84B2, 0x8A98, 0x91DC, 0x8A99, 0x938C, + 0x8A9A, 0x565B, 0x8A9B, 0x9D28, 0x8A9C, 0x6822, 0x8A9D, 0x8305, 0x8A9E, 0x8431, 0x8A9F, 0x7CA5, 0x8AA0, 0x5208, 0x8AA1, 0x82C5, + 0x8AA2, 0x74E6, 0x8AA3, 0x4E7E, 0x8AA4, 0x4F83, 0x8AA5, 0x51A0, 0x8AA6, 0x5BD2, 0x8AA7, 0x520A, 0x8AA8, 0x52D8, 0x8AA9, 0x52E7, + 0x8AAA, 0x5DFB, 0x8AAB, 0x559A, 0x8AAC, 0x582A, 0x8AAD, 0x59E6, 0x8AAE, 0x5B8C, 0x8AAF, 0x5B98, 0x8AB0, 0x5BDB, 0x8AB1, 0x5E72, + 0x8AB2, 0x5E79, 0x8AB3, 0x60A3, 0x8AB4, 0x611F, 0x8AB5, 0x6163, 0x8AB6, 0x61BE, 0x8AB7, 0x63DB, 0x8AB8, 0x6562, 0x8AB9, 0x67D1, + 0x8ABA, 0x6853, 0x8ABB, 0x68FA, 0x8ABC, 0x6B3E, 0x8ABD, 0x6B53, 0x8ABE, 0x6C57, 0x8ABF, 0x6F22, 0x8AC0, 0x6F97, 0x8AC1, 0x6F45, + 0x8AC2, 0x74B0, 0x8AC3, 0x7518, 0x8AC4, 0x76E3, 0x8AC5, 0x770B, 0x8AC6, 0x7AFF, 0x8AC7, 0x7BA1, 0x8AC8, 0x7C21, 0x8AC9, 0x7DE9, + 0x8ACA, 0x7F36, 0x8ACB, 0x7FF0, 0x8ACC, 0x809D, 0x8ACD, 0x8266, 0x8ACE, 0x839E, 0x8ACF, 0x89B3, 0x8AD0, 0x8ACC, 0x8AD1, 0x8CAB, + 0x8AD2, 0x9084, 0x8AD3, 0x9451, 0x8AD4, 0x9593, 0x8AD5, 0x9591, 0x8AD6, 0x95A2, 0x8AD7, 0x9665, 0x8AD8, 0x97D3, 0x8AD9, 0x9928, + 0x8ADA, 0x8218, 0x8ADB, 0x4E38, 0x8ADC, 0x542B, 0x8ADD, 0x5CB8, 0x8ADE, 0x5DCC, 0x8ADF, 0x73A9, 0x8AE0, 0x764C, 0x8AE1, 0x773C, + 0x8AE2, 0x5CA9, 0x8AE3, 0x7FEB, 0x8AE4, 0x8D0B, 0x8AE5, 0x96C1, 0x8AE6, 0x9811, 0x8AE7, 0x9854, 0x8AE8, 0x9858, 0x8AE9, 0x4F01, + 0x8AEA, 0x4F0E, 0x8AEB, 0x5371, 0x8AEC, 0x559C, 0x8AED, 0x5668, 0x8AEE, 0x57FA, 0x8AEF, 0x5947, 0x8AF0, 0x5B09, 0x8AF1, 0x5BC4, + 0x8AF2, 0x5C90, 0x8AF3, 0x5E0C, 0x8AF4, 0x5E7E, 0x8AF5, 0x5FCC, 0x8AF6, 0x63EE, 0x8AF7, 0x673A, 0x8AF8, 0x65D7, 0x8AF9, 0x65E2, + 0x8AFA, 0x671F, 0x8AFB, 0x68CB, 0x8AFC, 0x68C4, 0x8B40, 0x6A5F, 0x8B41, 0x5E30, 0x8B42, 0x6BC5, 0x8B43, 0x6C17, 0x8B44, 0x6C7D, + 0x8B45, 0x757F, 0x8B46, 0x7948, 0x8B47, 0x5B63, 0x8B48, 0x7A00, 0x8B49, 0x7D00, 0x8B4A, 0x5FBD, 0x8B4B, 0x898F, 0x8B4C, 0x8A18, + 0x8B4D, 0x8CB4, 0x8B4E, 0x8D77, 0x8B4F, 0x8ECC, 0x8B50, 0x8F1D, 0x8B51, 0x98E2, 0x8B52, 0x9A0E, 0x8B53, 0x9B3C, 0x8B54, 0x4E80, + 0x8B55, 0x507D, 0x8B56, 0x5100, 0x8B57, 0x5993, 0x8B58, 0x5B9C, 0x8B59, 0x622F, 0x8B5A, 0x6280, 0x8B5B, 0x64EC, 0x8B5C, 0x6B3A, + 0x8B5D, 0x72A0, 0x8B5E, 0x7591, 0x8B5F, 0x7947, 0x8B60, 0x7FA9, 0x8B61, 0x87FB, 0x8B62, 0x8ABC, 0x8B63, 0x8B70, 0x8B64, 0x63AC, + 0x8B65, 0x83CA, 0x8B66, 0x97A0, 0x8B67, 0x5409, 0x8B68, 0x5403, 0x8B69, 0x55AB, 0x8B6A, 0x6854, 0x8B6B, 0x6A58, 0x8B6C, 0x8A70, + 0x8B6D, 0x7827, 0x8B6E, 0x6775, 0x8B6F, 0x9ECD, 0x8B70, 0x5374, 0x8B71, 0x5BA2, 0x8B72, 0x811A, 0x8B73, 0x8650, 0x8B74, 0x9006, + 0x8B75, 0x4E18, 0x8B76, 0x4E45, 0x8B77, 0x4EC7, 0x8B78, 0x4F11, 0x8B79, 0x53CA, 0x8B7A, 0x5438, 0x8B7B, 0x5BAE, 0x8B7C, 0x5F13, + 0x8B7D, 0x6025, 0x8B7E, 0x6551, 0x8B80, 0x673D, 0x8B81, 0x6C42, 0x8B82, 0x6C72, 0x8B83, 0x6CE3, 0x8B84, 0x7078, 0x8B85, 0x7403, + 0x8B86, 0x7A76, 0x8B87, 0x7AAE, 0x8B88, 0x7B08, 0x8B89, 0x7D1A, 0x8B8A, 0x7CFE, 0x8B8B, 0x7D66, 0x8B8C, 0x65E7, 0x8B8D, 0x725B, + 0x8B8E, 0x53BB, 0x8B8F, 0x5C45, 0x8B90, 0x5DE8, 0x8B91, 0x62D2, 0x8B92, 0x62E0, 0x8B93, 0x6319, 0x8B94, 0x6E20, 0x8B95, 0x865A, + 0x8B96, 0x8A31, 0x8B97, 0x8DDD, 0x8B98, 0x92F8, 0x8B99, 0x6F01, 0x8B9A, 0x79A6, 0x8B9B, 0x9B5A, 0x8B9C, 0x4EA8, 0x8B9D, 0x4EAB, + 0x8B9E, 0x4EAC, 0x8B9F, 0x4F9B, 0x8BA0, 0x4FA0, 0x8BA1, 0x50D1, 0x8BA2, 0x5147, 0x8BA3, 0x7AF6, 0x8BA4, 0x5171, 0x8BA5, 0x51F6, + 0x8BA6, 0x5354, 0x8BA7, 0x5321, 0x8BA8, 0x537F, 0x8BA9, 0x53EB, 0x8BAA, 0x55AC, 0x8BAB, 0x5883, 0x8BAC, 0x5CE1, 0x8BAD, 0x5F37, + 0x8BAE, 0x5F4A, 0x8BAF, 0x602F, 0x8BB0, 0x6050, 0x8BB1, 0x606D, 0x8BB2, 0x631F, 0x8BB3, 0x6559, 0x8BB4, 0x6A4B, 0x8BB5, 0x6CC1, + 0x8BB6, 0x72C2, 0x8BB7, 0x72ED, 0x8BB8, 0x77EF, 0x8BB9, 0x80F8, 0x8BBA, 0x8105, 0x8BBB, 0x8208, 0x8BBC, 0x854E, 0x8BBD, 0x90F7, + 0x8BBE, 0x93E1, 0x8BBF, 0x97FF, 0x8BC0, 0x9957, 0x8BC1, 0x9A5A, 0x8BC2, 0x4EF0, 0x8BC3, 0x51DD, 0x8BC4, 0x5C2D, 0x8BC5, 0x6681, + 0x8BC6, 0x696D, 0x8BC7, 0x5C40, 0x8BC8, 0x66F2, 0x8BC9, 0x6975, 0x8BCA, 0x7389, 0x8BCB, 0x6850, 0x8BCC, 0x7C81, 0x8BCD, 0x50C5, + 0x8BCE, 0x52E4, 0x8BCF, 0x5747, 0x8BD0, 0x5DFE, 0x8BD1, 0x9326, 0x8BD2, 0x65A4, 0x8BD3, 0x6B23, 0x8BD4, 0x6B3D, 0x8BD5, 0x7434, + 0x8BD6, 0x7981, 0x8BD7, 0x79BD, 0x8BD8, 0x7B4B, 0x8BD9, 0x7DCA, 0x8BDA, 0x82B9, 0x8BDB, 0x83CC, 0x8BDC, 0x887F, 0x8BDD, 0x895F, + 0x8BDE, 0x8B39, 0x8BDF, 0x8FD1, 0x8BE0, 0x91D1, 0x8BE1, 0x541F, 0x8BE2, 0x9280, 0x8BE3, 0x4E5D, 0x8BE4, 0x5036, 0x8BE5, 0x53E5, + 0x8BE6, 0x533A, 0x8BE7, 0x72D7, 0x8BE8, 0x7396, 0x8BE9, 0x77E9, 0x8BEA, 0x82E6, 0x8BEB, 0x8EAF, 0x8BEC, 0x99C6, 0x8BED, 0x99C8, + 0x8BEE, 0x99D2, 0x8BEF, 0x5177, 0x8BF0, 0x611A, 0x8BF1, 0x865E, 0x8BF2, 0x55B0, 0x8BF3, 0x7A7A, 0x8BF4, 0x5076, 0x8BF5, 0x5BD3, + 0x8BF6, 0x9047, 0x8BF7, 0x9685, 0x8BF8, 0x4E32, 0x8BF9, 0x6ADB, 0x8BFA, 0x91E7, 0x8BFB, 0x5C51, 0x8BFC, 0x5C48, 0x8C40, 0x6398, + 0x8C41, 0x7A9F, 0x8C42, 0x6C93, 0x8C43, 0x9774, 0x8C44, 0x8F61, 0x8C45, 0x7AAA, 0x8C46, 0x718A, 0x8C47, 0x9688, 0x8C48, 0x7C82, + 0x8C49, 0x6817, 0x8C4A, 0x7E70, 0x8C4B, 0x6851, 0x8C4C, 0x936C, 0x8C4D, 0x52F2, 0x8C4E, 0x541B, 0x8C4F, 0x85AB, 0x8C50, 0x8A13, + 0x8C51, 0x7FA4, 0x8C52, 0x8ECD, 0x8C53, 0x90E1, 0x8C54, 0x5366, 0x8C55, 0x8888, 0x8C56, 0x7941, 0x8C57, 0x4FC2, 0x8C58, 0x50BE, + 0x8C59, 0x5211, 0x8C5A, 0x5144, 0x8C5B, 0x5553, 0x8C5C, 0x572D, 0x8C5D, 0x73EA, 0x8C5E, 0x578B, 0x8C5F, 0x5951, 0x8C60, 0x5F62, + 0x8C61, 0x5F84, 0x8C62, 0x6075, 0x8C63, 0x6176, 0x8C64, 0x6167, 0x8C65, 0x61A9, 0x8C66, 0x63B2, 0x8C67, 0x643A, 0x8C68, 0x656C, + 0x8C69, 0x666F, 0x8C6A, 0x6842, 0x8C6B, 0x6E13, 0x8C6C, 0x7566, 0x8C6D, 0x7A3D, 0x8C6E, 0x7CFB, 0x8C6F, 0x7D4C, 0x8C70, 0x7D99, + 0x8C71, 0x7E4B, 0x8C72, 0x7F6B, 0x8C73, 0x830E, 0x8C74, 0x834A, 0x8C75, 0x86CD, 0x8C76, 0x8A08, 0x8C77, 0x8A63, 0x8C78, 0x8B66, + 0x8C79, 0x8EFD, 0x8C7A, 0x981A, 0x8C7B, 0x9D8F, 0x8C7C, 0x82B8, 0x8C7D, 0x8FCE, 0x8C7E, 0x9BE8, 0x8C80, 0x5287, 0x8C81, 0x621F, + 0x8C82, 0x6483, 0x8C83, 0x6FC0, 0x8C84, 0x9699, 0x8C85, 0x6841, 0x8C86, 0x5091, 0x8C87, 0x6B20, 0x8C88, 0x6C7A, 0x8C89, 0x6F54, + 0x8C8A, 0x7A74, 0x8C8B, 0x7D50, 0x8C8C, 0x8840, 0x8C8D, 0x8A23, 0x8C8E, 0x6708, 0x8C8F, 0x4EF6, 0x8C90, 0x5039, 0x8C91, 0x5026, + 0x8C92, 0x5065, 0x8C93, 0x517C, 0x8C94, 0x5238, 0x8C95, 0x5263, 0x8C96, 0x55A7, 0x8C97, 0x570F, 0x8C98, 0x5805, 0x8C99, 0x5ACC, + 0x8C9A, 0x5EFA, 0x8C9B, 0x61B2, 0x8C9C, 0x61F8, 0x8C9D, 0x62F3, 0x8C9E, 0x6372, 0x8C9F, 0x691C, 0x8CA0, 0x6A29, 0x8CA1, 0x727D, + 0x8CA2, 0x72AC, 0x8CA3, 0x732E, 0x8CA4, 0x7814, 0x8CA5, 0x786F, 0x8CA6, 0x7D79, 0x8CA7, 0x770C, 0x8CA8, 0x80A9, 0x8CA9, 0x898B, + 0x8CAA, 0x8B19, 0x8CAB, 0x8CE2, 0x8CAC, 0x8ED2, 0x8CAD, 0x9063, 0x8CAE, 0x9375, 0x8CAF, 0x967A, 0x8CB0, 0x9855, 0x8CB1, 0x9A13, + 0x8CB2, 0x9E78, 0x8CB3, 0x5143, 0x8CB4, 0x539F, 0x8CB5, 0x53B3, 0x8CB6, 0x5E7B, 0x8CB7, 0x5F26, 0x8CB8, 0x6E1B, 0x8CB9, 0x6E90, + 0x8CBA, 0x7384, 0x8CBB, 0x73FE, 0x8CBC, 0x7D43, 0x8CBD, 0x8237, 0x8CBE, 0x8A00, 0x8CBF, 0x8AFA, 0x8CC0, 0x9650, 0x8CC1, 0x4E4E, + 0x8CC2, 0x500B, 0x8CC3, 0x53E4, 0x8CC4, 0x547C, 0x8CC5, 0x56FA, 0x8CC6, 0x59D1, 0x8CC7, 0x5B64, 0x8CC8, 0x5DF1, 0x8CC9, 0x5EAB, + 0x8CCA, 0x5F27, 0x8CCB, 0x6238, 0x8CCC, 0x6545, 0x8CCD, 0x67AF, 0x8CCE, 0x6E56, 0x8CCF, 0x72D0, 0x8CD0, 0x7CCA, 0x8CD1, 0x88B4, + 0x8CD2, 0x80A1, 0x8CD3, 0x80E1, 0x8CD4, 0x83F0, 0x8CD5, 0x864E, 0x8CD6, 0x8A87, 0x8CD7, 0x8DE8, 0x8CD8, 0x9237, 0x8CD9, 0x96C7, + 0x8CDA, 0x9867, 0x8CDB, 0x9F13, 0x8CDC, 0x4E94, 0x8CDD, 0x4E92, 0x8CDE, 0x4F0D, 0x8CDF, 0x5348, 0x8CE0, 0x5449, 0x8CE1, 0x543E, + 0x8CE2, 0x5A2F, 0x8CE3, 0x5F8C, 0x8CE4, 0x5FA1, 0x8CE5, 0x609F, 0x8CE6, 0x68A7, 0x8CE7, 0x6A8E, 0x8CE8, 0x745A, 0x8CE9, 0x7881, + 0x8CEA, 0x8A9E, 0x8CEB, 0x8AA4, 0x8CEC, 0x8B77, 0x8CED, 0x9190, 0x8CEE, 0x4E5E, 0x8CEF, 0x9BC9, 0x8CF0, 0x4EA4, 0x8CF1, 0x4F7C, + 0x8CF2, 0x4FAF, 0x8CF3, 0x5019, 0x8CF4, 0x5016, 0x8CF5, 0x5149, 0x8CF6, 0x516C, 0x8CF7, 0x529F, 0x8CF8, 0x52B9, 0x8CF9, 0x52FE, + 0x8CFA, 0x539A, 0x8CFB, 0x53E3, 0x8CFC, 0x5411, 0x8D40, 0x540E, 0x8D41, 0x5589, 0x8D42, 0x5751, 0x8D43, 0x57A2, 0x8D44, 0x597D, + 0x8D45, 0x5B54, 0x8D46, 0x5B5D, 0x8D47, 0x5B8F, 0x8D48, 0x5DE5, 0x8D49, 0x5DE7, 0x8D4A, 0x5DF7, 0x8D4B, 0x5E78, 0x8D4C, 0x5E83, + 0x8D4D, 0x5E9A, 0x8D4E, 0x5EB7, 0x8D4F, 0x5F18, 0x8D50, 0x6052, 0x8D51, 0x614C, 0x8D52, 0x6297, 0x8D53, 0x62D8, 0x8D54, 0x63A7, + 0x8D55, 0x653B, 0x8D56, 0x6602, 0x8D57, 0x6643, 0x8D58, 0x66F4, 0x8D59, 0x676D, 0x8D5A, 0x6821, 0x8D5B, 0x6897, 0x8D5C, 0x69CB, + 0x8D5D, 0x6C5F, 0x8D5E, 0x6D2A, 0x8D5F, 0x6D69, 0x8D60, 0x6E2F, 0x8D61, 0x6E9D, 0x8D62, 0x7532, 0x8D63, 0x7687, 0x8D64, 0x786C, + 0x8D65, 0x7A3F, 0x8D66, 0x7CE0, 0x8D67, 0x7D05, 0x8D68, 0x7D18, 0x8D69, 0x7D5E, 0x8D6A, 0x7DB1, 0x8D6B, 0x8015, 0x8D6C, 0x8003, + 0x8D6D, 0x80AF, 0x8D6E, 0x80B1, 0x8D6F, 0x8154, 0x8D70, 0x818F, 0x8D71, 0x822A, 0x8D72, 0x8352, 0x8D73, 0x884C, 0x8D74, 0x8861, + 0x8D75, 0x8B1B, 0x8D76, 0x8CA2, 0x8D77, 0x8CFC, 0x8D78, 0x90CA, 0x8D79, 0x9175, 0x8D7A, 0x9271, 0x8D7B, 0x783F, 0x8D7C, 0x92FC, + 0x8D7D, 0x95A4, 0x8D7E, 0x964D, 0x8D80, 0x9805, 0x8D81, 0x9999, 0x8D82, 0x9AD8, 0x8D83, 0x9D3B, 0x8D84, 0x525B, 0x8D85, 0x52AB, + 0x8D86, 0x53F7, 0x8D87, 0x5408, 0x8D88, 0x58D5, 0x8D89, 0x62F7, 0x8D8A, 0x6FE0, 0x8D8B, 0x8C6A, 0x8D8C, 0x8F5F, 0x8D8D, 0x9EB9, + 0x8D8E, 0x514B, 0x8D8F, 0x523B, 0x8D90, 0x544A, 0x8D91, 0x56FD, 0x8D92, 0x7A40, 0x8D93, 0x9177, 0x8D94, 0x9D60, 0x8D95, 0x9ED2, + 0x8D96, 0x7344, 0x8D97, 0x6F09, 0x8D98, 0x8170, 0x8D99, 0x7511, 0x8D9A, 0x5FFD, 0x8D9B, 0x60DA, 0x8D9C, 0x9AA8, 0x8D9D, 0x72DB, + 0x8D9E, 0x8FBC, 0x8D9F, 0x6B64, 0x8DA0, 0x9803, 0x8DA1, 0x4ECA, 0x8DA2, 0x56F0, 0x8DA3, 0x5764, 0x8DA4, 0x58BE, 0x8DA5, 0x5A5A, + 0x8DA6, 0x6068, 0x8DA7, 0x61C7, 0x8DA8, 0x660F, 0x8DA9, 0x6606, 0x8DAA, 0x6839, 0x8DAB, 0x68B1, 0x8DAC, 0x6DF7, 0x8DAD, 0x75D5, + 0x8DAE, 0x7D3A, 0x8DAF, 0x826E, 0x8DB0, 0x9B42, 0x8DB1, 0x4E9B, 0x8DB2, 0x4F50, 0x8DB3, 0x53C9, 0x8DB4, 0x5506, 0x8DB5, 0x5D6F, + 0x8DB6, 0x5DE6, 0x8DB7, 0x5DEE, 0x8DB8, 0x67FB, 0x8DB9, 0x6C99, 0x8DBA, 0x7473, 0x8DBB, 0x7802, 0x8DBC, 0x8A50, 0x8DBD, 0x9396, + 0x8DBE, 0x88DF, 0x8DBF, 0x5750, 0x8DC0, 0x5EA7, 0x8DC1, 0x632B, 0x8DC2, 0x50B5, 0x8DC3, 0x50AC, 0x8DC4, 0x518D, 0x8DC5, 0x6700, + 0x8DC6, 0x54C9, 0x8DC7, 0x585E, 0x8DC8, 0x59BB, 0x8DC9, 0x5BB0, 0x8DCA, 0x5F69, 0x8DCB, 0x624D, 0x8DCC, 0x63A1, 0x8DCD, 0x683D, + 0x8DCE, 0x6B73, 0x8DCF, 0x6E08, 0x8DD0, 0x707D, 0x8DD1, 0x91C7, 0x8DD2, 0x7280, 0x8DD3, 0x7815, 0x8DD4, 0x7826, 0x8DD5, 0x796D, + 0x8DD6, 0x658E, 0x8DD7, 0x7D30, 0x8DD8, 0x83DC, 0x8DD9, 0x88C1, 0x8DDA, 0x8F09, 0x8DDB, 0x969B, 0x8DDC, 0x5264, 0x8DDD, 0x5728, + 0x8DDE, 0x6750, 0x8DDF, 0x7F6A, 0x8DE0, 0x8CA1, 0x8DE1, 0x51B4, 0x8DE2, 0x5742, 0x8DE3, 0x962A, 0x8DE4, 0x583A, 0x8DE5, 0x698A, + 0x8DE6, 0x80B4, 0x8DE7, 0x54B2, 0x8DE8, 0x5D0E, 0x8DE9, 0x57FC, 0x8DEA, 0x7895, 0x8DEB, 0x9DFA, 0x8DEC, 0x4F5C, 0x8DED, 0x524A, + 0x8DEE, 0x548B, 0x8DEF, 0x643E, 0x8DF0, 0x6628, 0x8DF1, 0x6714, 0x8DF2, 0x67F5, 0x8DF3, 0x7A84, 0x8DF4, 0x7B56, 0x8DF5, 0x7D22, + 0x8DF6, 0x932F, 0x8DF7, 0x685C, 0x8DF8, 0x9BAD, 0x8DF9, 0x7B39, 0x8DFA, 0x5319, 0x8DFB, 0x518A, 0x8DFC, 0x5237, 0x8E40, 0x5BDF, + 0x8E41, 0x62F6, 0x8E42, 0x64AE, 0x8E43, 0x64E6, 0x8E44, 0x672D, 0x8E45, 0x6BBA, 0x8E46, 0x85A9, 0x8E47, 0x96D1, 0x8E48, 0x7690, + 0x8E49, 0x9BD6, 0x8E4A, 0x634C, 0x8E4B, 0x9306, 0x8E4C, 0x9BAB, 0x8E4D, 0x76BF, 0x8E4E, 0x6652, 0x8E4F, 0x4E09, 0x8E50, 0x5098, + 0x8E51, 0x53C2, 0x8E52, 0x5C71, 0x8E53, 0x60E8, 0x8E54, 0x6492, 0x8E55, 0x6563, 0x8E56, 0x685F, 0x8E57, 0x71E6, 0x8E58, 0x73CA, + 0x8E59, 0x7523, 0x8E5A, 0x7B97, 0x8E5B, 0x7E82, 0x8E5C, 0x8695, 0x8E5D, 0x8B83, 0x8E5E, 0x8CDB, 0x8E5F, 0x9178, 0x8E60, 0x9910, + 0x8E61, 0x65AC, 0x8E62, 0x66AB, 0x8E63, 0x6B8B, 0x8E64, 0x4ED5, 0x8E65, 0x4ED4, 0x8E66, 0x4F3A, 0x8E67, 0x4F7F, 0x8E68, 0x523A, + 0x8E69, 0x53F8, 0x8E6A, 0x53F2, 0x8E6B, 0x55E3, 0x8E6C, 0x56DB, 0x8E6D, 0x58EB, 0x8E6E, 0x59CB, 0x8E6F, 0x59C9, 0x8E70, 0x59FF, + 0x8E71, 0x5B50, 0x8E72, 0x5C4D, 0x8E73, 0x5E02, 0x8E74, 0x5E2B, 0x8E75, 0x5FD7, 0x8E76, 0x601D, 0x8E77, 0x6307, 0x8E78, 0x652F, + 0x8E79, 0x5B5C, 0x8E7A, 0x65AF, 0x8E7B, 0x65BD, 0x8E7C, 0x65E8, 0x8E7D, 0x679D, 0x8E7E, 0x6B62, 0x8E80, 0x6B7B, 0x8E81, 0x6C0F, + 0x8E82, 0x7345, 0x8E83, 0x7949, 0x8E84, 0x79C1, 0x8E85, 0x7CF8, 0x8E86, 0x7D19, 0x8E87, 0x7D2B, 0x8E88, 0x80A2, 0x8E89, 0x8102, + 0x8E8A, 0x81F3, 0x8E8B, 0x8996, 0x8E8C, 0x8A5E, 0x8E8D, 0x8A69, 0x8E8E, 0x8A66, 0x8E8F, 0x8A8C, 0x8E90, 0x8AEE, 0x8E91, 0x8CC7, + 0x8E92, 0x8CDC, 0x8E93, 0x96CC, 0x8E94, 0x98FC, 0x8E95, 0x6B6F, 0x8E96, 0x4E8B, 0x8E97, 0x4F3C, 0x8E98, 0x4F8D, 0x8E99, 0x5150, + 0x8E9A, 0x5B57, 0x8E9B, 0x5BFA, 0x8E9C, 0x6148, 0x8E9D, 0x6301, 0x8E9E, 0x6642, 0x8E9F, 0x6B21, 0x8EA0, 0x6ECB, 0x8EA1, 0x6CBB, + 0x8EA2, 0x723E, 0x8EA3, 0x74BD, 0x8EA4, 0x75D4, 0x8EA5, 0x78C1, 0x8EA6, 0x793A, 0x8EA7, 0x800C, 0x8EA8, 0x8033, 0x8EA9, 0x81EA, + 0x8EAA, 0x8494, 0x8EAB, 0x8F9E, 0x8EAC, 0x6C50, 0x8EAD, 0x9E7F, 0x8EAE, 0x5F0F, 0x8EAF, 0x8B58, 0x8EB0, 0x9D2B, 0x8EB1, 0x7AFA, + 0x8EB2, 0x8EF8, 0x8EB3, 0x5B8D, 0x8EB4, 0x96EB, 0x8EB5, 0x4E03, 0x8EB6, 0x53F1, 0x8EB7, 0x57F7, 0x8EB8, 0x5931, 0x8EB9, 0x5AC9, + 0x8EBA, 0x5BA4, 0x8EBB, 0x6089, 0x8EBC, 0x6E7F, 0x8EBD, 0x6F06, 0x8EBE, 0x75BE, 0x8EBF, 0x8CEA, 0x8EC0, 0x5B9F, 0x8EC1, 0x8500, + 0x8EC2, 0x7BE0, 0x8EC3, 0x5072, 0x8EC4, 0x67F4, 0x8EC5, 0x829D, 0x8EC6, 0x5C61, 0x8EC7, 0x854A, 0x8EC8, 0x7E1E, 0x8EC9, 0x820E, + 0x8ECA, 0x5199, 0x8ECB, 0x5C04, 0x8ECC, 0x6368, 0x8ECD, 0x8D66, 0x8ECE, 0x659C, 0x8ECF, 0x716E, 0x8ED0, 0x793E, 0x8ED1, 0x7D17, + 0x8ED2, 0x8005, 0x8ED3, 0x8B1D, 0x8ED4, 0x8ECA, 0x8ED5, 0x906E, 0x8ED6, 0x86C7, 0x8ED7, 0x90AA, 0x8ED8, 0x501F, 0x8ED9, 0x52FA, + 0x8EDA, 0x5C3A, 0x8EDB, 0x6753, 0x8EDC, 0x707C, 0x8EDD, 0x7235, 0x8EDE, 0x914C, 0x8EDF, 0x91C8, 0x8EE0, 0x932B, 0x8EE1, 0x82E5, + 0x8EE2, 0x5BC2, 0x8EE3, 0x5F31, 0x8EE4, 0x60F9, 0x8EE5, 0x4E3B, 0x8EE6, 0x53D6, 0x8EE7, 0x5B88, 0x8EE8, 0x624B, 0x8EE9, 0x6731, + 0x8EEA, 0x6B8A, 0x8EEB, 0x72E9, 0x8EEC, 0x73E0, 0x8EED, 0x7A2E, 0x8EEE, 0x816B, 0x8EEF, 0x8DA3, 0x8EF0, 0x9152, 0x8EF1, 0x9996, + 0x8EF2, 0x5112, 0x8EF3, 0x53D7, 0x8EF4, 0x546A, 0x8EF5, 0x5BFF, 0x8EF6, 0x6388, 0x8EF7, 0x6A39, 0x8EF8, 0x7DAC, 0x8EF9, 0x9700, + 0x8EFA, 0x56DA, 0x8EFB, 0x53CE, 0x8EFC, 0x5468, 0x8F40, 0x5B97, 0x8F41, 0x5C31, 0x8F42, 0x5DDE, 0x8F43, 0x4FEE, 0x8F44, 0x6101, + 0x8F45, 0x62FE, 0x8F46, 0x6D32, 0x8F47, 0x79C0, 0x8F48, 0x79CB, 0x8F49, 0x7D42, 0x8F4A, 0x7E4D, 0x8F4B, 0x7FD2, 0x8F4C, 0x81ED, + 0x8F4D, 0x821F, 0x8F4E, 0x8490, 0x8F4F, 0x8846, 0x8F50, 0x8972, 0x8F51, 0x8B90, 0x8F52, 0x8E74, 0x8F53, 0x8F2F, 0x8F54, 0x9031, + 0x8F55, 0x914B, 0x8F56, 0x916C, 0x8F57, 0x96C6, 0x8F58, 0x919C, 0x8F59, 0x4EC0, 0x8F5A, 0x4F4F, 0x8F5B, 0x5145, 0x8F5C, 0x5341, + 0x8F5D, 0x5F93, 0x8F5E, 0x620E, 0x8F5F, 0x67D4, 0x8F60, 0x6C41, 0x8F61, 0x6E0B, 0x8F62, 0x7363, 0x8F63, 0x7E26, 0x8F64, 0x91CD, + 0x8F65, 0x9283, 0x8F66, 0x53D4, 0x8F67, 0x5919, 0x8F68, 0x5BBF, 0x8F69, 0x6DD1, 0x8F6A, 0x795D, 0x8F6B, 0x7E2E, 0x8F6C, 0x7C9B, + 0x8F6D, 0x587E, 0x8F6E, 0x719F, 0x8F6F, 0x51FA, 0x8F70, 0x8853, 0x8F71, 0x8FF0, 0x8F72, 0x4FCA, 0x8F73, 0x5CFB, 0x8F74, 0x6625, + 0x8F75, 0x77AC, 0x8F76, 0x7AE3, 0x8F77, 0x821C, 0x8F78, 0x99FF, 0x8F79, 0x51C6, 0x8F7A, 0x5FAA, 0x8F7B, 0x65EC, 0x8F7C, 0x696F, + 0x8F7D, 0x6B89, 0x8F7E, 0x6DF3, 0x8F80, 0x6E96, 0x8F81, 0x6F64, 0x8F82, 0x76FE, 0x8F83, 0x7D14, 0x8F84, 0x5DE1, 0x8F85, 0x9075, + 0x8F86, 0x9187, 0x8F87, 0x9806, 0x8F88, 0x51E6, 0x8F89, 0x521D, 0x8F8A, 0x6240, 0x8F8B, 0x6691, 0x8F8C, 0x66D9, 0x8F8D, 0x6E1A, + 0x8F8E, 0x5EB6, 0x8F8F, 0x7DD2, 0x8F90, 0x7F72, 0x8F91, 0x66F8, 0x8F92, 0x85AF, 0x8F93, 0x85F7, 0x8F94, 0x8AF8, 0x8F95, 0x52A9, + 0x8F96, 0x53D9, 0x8F97, 0x5973, 0x8F98, 0x5E8F, 0x8F99, 0x5F90, 0x8F9A, 0x6055, 0x8F9B, 0x92E4, 0x8F9C, 0x9664, 0x8F9D, 0x50B7, + 0x8F9E, 0x511F, 0x8F9F, 0x52DD, 0x8FA0, 0x5320, 0x8FA1, 0x5347, 0x8FA2, 0x53EC, 0x8FA3, 0x54E8, 0x8FA4, 0x5546, 0x8FA5, 0x5531, + 0x8FA6, 0x5617, 0x8FA7, 0x5968, 0x8FA8, 0x59BE, 0x8FA9, 0x5A3C, 0x8FAA, 0x5BB5, 0x8FAB, 0x5C06, 0x8FAC, 0x5C0F, 0x8FAD, 0x5C11, + 0x8FAE, 0x5C1A, 0x8FAF, 0x5E84, 0x8FB0, 0x5E8A, 0x8FB1, 0x5EE0, 0x8FB2, 0x5F70, 0x8FB3, 0x627F, 0x8FB4, 0x6284, 0x8FB5, 0x62DB, + 0x8FB6, 0x638C, 0x8FB7, 0x6377, 0x8FB8, 0x6607, 0x8FB9, 0x660C, 0x8FBA, 0x662D, 0x8FBB, 0x6676, 0x8FBC, 0x677E, 0x8FBD, 0x68A2, + 0x8FBE, 0x6A1F, 0x8FBF, 0x6A35, 0x8FC0, 0x6CBC, 0x8FC1, 0x6D88, 0x8FC2, 0x6E09, 0x8FC3, 0x6E58, 0x8FC4, 0x713C, 0x8FC5, 0x7126, + 0x8FC6, 0x7167, 0x8FC7, 0x75C7, 0x8FC8, 0x7701, 0x8FC9, 0x785D, 0x8FCA, 0x7901, 0x8FCB, 0x7965, 0x8FCC, 0x79F0, 0x8FCD, 0x7AE0, + 0x8FCE, 0x7B11, 0x8FCF, 0x7CA7, 0x8FD0, 0x7D39, 0x8FD1, 0x8096, 0x8FD2, 0x83D6, 0x8FD3, 0x848B, 0x8FD4, 0x8549, 0x8FD5, 0x885D, + 0x8FD6, 0x88F3, 0x8FD7, 0x8A1F, 0x8FD8, 0x8A3C, 0x8FD9, 0x8A54, 0x8FDA, 0x8A73, 0x8FDB, 0x8C61, 0x8FDC, 0x8CDE, 0x8FDD, 0x91A4, + 0x8FDE, 0x9266, 0x8FDF, 0x937E, 0x8FE0, 0x9418, 0x8FE1, 0x969C, 0x8FE2, 0x9798, 0x8FE3, 0x4E0A, 0x8FE4, 0x4E08, 0x8FE5, 0x4E1E, + 0x8FE6, 0x4E57, 0x8FE7, 0x5197, 0x8FE8, 0x5270, 0x8FE9, 0x57CE, 0x8FEA, 0x5834, 0x8FEB, 0x58CC, 0x8FEC, 0x5B22, 0x8FED, 0x5E38, + 0x8FEE, 0x60C5, 0x8FEF, 0x64FE, 0x8FF0, 0x6761, 0x8FF1, 0x6756, 0x8FF2, 0x6D44, 0x8FF3, 0x72B6, 0x8FF4, 0x7573, 0x8FF5, 0x7A63, + 0x8FF6, 0x84B8, 0x8FF7, 0x8B72, 0x8FF8, 0x91B8, 0x8FF9, 0x9320, 0x8FFA, 0x5631, 0x8FFB, 0x57F4, 0x8FFC, 0x98FE, 0x9040, 0x62ED, + 0x9041, 0x690D, 0x9042, 0x6B96, 0x9043, 0x71ED, 0x9044, 0x7E54, 0x9045, 0x8077, 0x9046, 0x8272, 0x9047, 0x89E6, 0x9048, 0x98DF, + 0x9049, 0x8755, 0x904A, 0x8FB1, 0x904B, 0x5C3B, 0x904C, 0x4F38, 0x904D, 0x4FE1, 0x904E, 0x4FB5, 0x904F, 0x5507, 0x9050, 0x5A20, + 0x9051, 0x5BDD, 0x9052, 0x5BE9, 0x9053, 0x5FC3, 0x9054, 0x614E, 0x9055, 0x632F, 0x9056, 0x65B0, 0x9057, 0x664B, 0x9058, 0x68EE, + 0x9059, 0x699B, 0x905A, 0x6D78, 0x905B, 0x6DF1, 0x905C, 0x7533, 0x905D, 0x75B9, 0x905E, 0x771F, 0x905F, 0x795E, 0x9060, 0x79E6, + 0x9061, 0x7D33, 0x9062, 0x81E3, 0x9063, 0x82AF, 0x9064, 0x85AA, 0x9065, 0x89AA, 0x9066, 0x8A3A, 0x9067, 0x8EAB, 0x9068, 0x8F9B, + 0x9069, 0x9032, 0x906A, 0x91DD, 0x906B, 0x9707, 0x906C, 0x4EBA, 0x906D, 0x4EC1, 0x906E, 0x5203, 0x906F, 0x5875, 0x9070, 0x58EC, + 0x9071, 0x5C0B, 0x9072, 0x751A, 0x9073, 0x5C3D, 0x9074, 0x814E, 0x9075, 0x8A0A, 0x9076, 0x8FC5, 0x9077, 0x9663, 0x9078, 0x976D, + 0x9079, 0x7B25, 0x907A, 0x8ACF, 0x907B, 0x9808, 0x907C, 0x9162, 0x907D, 0x56F3, 0x907E, 0x53A8, 0x9080, 0x9017, 0x9081, 0x5439, + 0x9082, 0x5782, 0x9083, 0x5E25, 0x9084, 0x63A8, 0x9085, 0x6C34, 0x9086, 0x708A, 0x9087, 0x7761, 0x9088, 0x7C8B, 0x9089, 0x7FE0, + 0x908A, 0x8870, 0x908B, 0x9042, 0x908C, 0x9154, 0x908D, 0x9310, 0x908E, 0x9318, 0x908F, 0x968F, 0x9090, 0x745E, 0x9091, 0x9AC4, + 0x9092, 0x5D07, 0x9093, 0x5D69, 0x9094, 0x6570, 0x9095, 0x67A2, 0x9096, 0x8DA8, 0x9097, 0x96DB, 0x9098, 0x636E, 0x9099, 0x6749, + 0x909A, 0x6919, 0x909B, 0x83C5, 0x909C, 0x9817, 0x909D, 0x96C0, 0x909E, 0x88FE, 0x909F, 0x6F84, 0x90A0, 0x647A, 0x90A1, 0x5BF8, + 0x90A2, 0x4E16, 0x90A3, 0x702C, 0x90A4, 0x755D, 0x90A5, 0x662F, 0x90A6, 0x51C4, 0x90A7, 0x5236, 0x90A8, 0x52E2, 0x90A9, 0x59D3, + 0x90AA, 0x5F81, 0x90AB, 0x6027, 0x90AC, 0x6210, 0x90AD, 0x653F, 0x90AE, 0x6574, 0x90AF, 0x661F, 0x90B0, 0x6674, 0x90B1, 0x68F2, + 0x90B2, 0x6816, 0x90B3, 0x6B63, 0x90B4, 0x6E05, 0x90B5, 0x7272, 0x90B6, 0x751F, 0x90B7, 0x76DB, 0x90B8, 0x7CBE, 0x90B9, 0x8056, + 0x90BA, 0x58F0, 0x90BB, 0x88FD, 0x90BC, 0x897F, 0x90BD, 0x8AA0, 0x90BE, 0x8A93, 0x90BF, 0x8ACB, 0x90C0, 0x901D, 0x90C1, 0x9192, + 0x90C2, 0x9752, 0x90C3, 0x9759, 0x90C4, 0x6589, 0x90C5, 0x7A0E, 0x90C6, 0x8106, 0x90C7, 0x96BB, 0x90C8, 0x5E2D, 0x90C9, 0x60DC, + 0x90CA, 0x621A, 0x90CB, 0x65A5, 0x90CC, 0x6614, 0x90CD, 0x6790, 0x90CE, 0x77F3, 0x90CF, 0x7A4D, 0x90D0, 0x7C4D, 0x90D1, 0x7E3E, + 0x90D2, 0x810A, 0x90D3, 0x8CAC, 0x90D4, 0x8D64, 0x90D5, 0x8DE1, 0x90D6, 0x8E5F, 0x90D7, 0x78A9, 0x90D8, 0x5207, 0x90D9, 0x62D9, + 0x90DA, 0x63A5, 0x90DB, 0x6442, 0x90DC, 0x6298, 0x90DD, 0x8A2D, 0x90DE, 0x7A83, 0x90DF, 0x7BC0, 0x90E0, 0x8AAC, 0x90E1, 0x96EA, + 0x90E2, 0x7D76, 0x90E3, 0x820C, 0x90E4, 0x8749, 0x90E5, 0x4ED9, 0x90E6, 0x5148, 0x90E7, 0x5343, 0x90E8, 0x5360, 0x90E9, 0x5BA3, + 0x90EA, 0x5C02, 0x90EB, 0x5C16, 0x90EC, 0x5DDD, 0x90ED, 0x6226, 0x90EE, 0x6247, 0x90EF, 0x64B0, 0x90F0, 0x6813, 0x90F1, 0x6834, + 0x90F2, 0x6CC9, 0x90F3, 0x6D45, 0x90F4, 0x6D17, 0x90F5, 0x67D3, 0x90F6, 0x6F5C, 0x90F7, 0x714E, 0x90F8, 0x717D, 0x90F9, 0x65CB, + 0x90FA, 0x7A7F, 0x90FB, 0x7BAD, 0x90FC, 0x7DDA, 0x9140, 0x7E4A, 0x9141, 0x7FA8, 0x9142, 0x817A, 0x9143, 0x821B, 0x9144, 0x8239, + 0x9145, 0x85A6, 0x9146, 0x8A6E, 0x9147, 0x8CCE, 0x9148, 0x8DF5, 0x9149, 0x9078, 0x914A, 0x9077, 0x914B, 0x92AD, 0x914C, 0x9291, + 0x914D, 0x9583, 0x914E, 0x9BAE, 0x914F, 0x524D, 0x9150, 0x5584, 0x9151, 0x6F38, 0x9152, 0x7136, 0x9153, 0x5168, 0x9154, 0x7985, + 0x9155, 0x7E55, 0x9156, 0x81B3, 0x9157, 0x7CCE, 0x9158, 0x564C, 0x9159, 0x5851, 0x915A, 0x5CA8, 0x915B, 0x63AA, 0x915C, 0x66FE, + 0x915D, 0x66FD, 0x915E, 0x695A, 0x915F, 0x72D9, 0x9160, 0x758F, 0x9161, 0x758E, 0x9162, 0x790E, 0x9163, 0x7956, 0x9164, 0x79DF, + 0x9165, 0x7C97, 0x9166, 0x7D20, 0x9167, 0x7D44, 0x9168, 0x8607, 0x9169, 0x8A34, 0x916A, 0x963B, 0x916B, 0x9061, 0x916C, 0x9F20, + 0x916D, 0x50E7, 0x916E, 0x5275, 0x916F, 0x53CC, 0x9170, 0x53E2, 0x9171, 0x5009, 0x9172, 0x55AA, 0x9173, 0x58EE, 0x9174, 0x594F, + 0x9175, 0x723D, 0x9176, 0x5B8B, 0x9177, 0x5C64, 0x9178, 0x531D, 0x9179, 0x60E3, 0x917A, 0x60F3, 0x917B, 0x635C, 0x917C, 0x6383, + 0x917D, 0x633F, 0x917E, 0x63BB, 0x9180, 0x64CD, 0x9181, 0x65E9, 0x9182, 0x66F9, 0x9183, 0x5DE3, 0x9184, 0x69CD, 0x9185, 0x69FD, + 0x9186, 0x6F15, 0x9187, 0x71E5, 0x9188, 0x4E89, 0x9189, 0x75E9, 0x918A, 0x76F8, 0x918B, 0x7A93, 0x918C, 0x7CDF, 0x918D, 0x7DCF, + 0x918E, 0x7D9C, 0x918F, 0x8061, 0x9190, 0x8349, 0x9191, 0x8358, 0x9192, 0x846C, 0x9193, 0x84BC, 0x9194, 0x85FB, 0x9195, 0x88C5, + 0x9196, 0x8D70, 0x9197, 0x9001, 0x9198, 0x906D, 0x9199, 0x9397, 0x919A, 0x971C, 0x919B, 0x9A12, 0x919C, 0x50CF, 0x919D, 0x5897, + 0x919E, 0x618E, 0x919F, 0x81D3, 0x91A0, 0x8535, 0x91A1, 0x8D08, 0x91A2, 0x9020, 0x91A3, 0x4FC3, 0x91A4, 0x5074, 0x91A5, 0x5247, + 0x91A6, 0x5373, 0x91A7, 0x606F, 0x91A8, 0x6349, 0x91A9, 0x675F, 0x91AA, 0x6E2C, 0x91AB, 0x8DB3, 0x91AC, 0x901F, 0x91AD, 0x4FD7, + 0x91AE, 0x5C5E, 0x91AF, 0x8CCA, 0x91B0, 0x65CF, 0x91B1, 0x7D9A, 0x91B2, 0x5352, 0x91B3, 0x8896, 0x91B4, 0x5176, 0x91B5, 0x63C3, + 0x91B6, 0x5B58, 0x91B7, 0x5B6B, 0x91B8, 0x5C0A, 0x91B9, 0x640D, 0x91BA, 0x6751, 0x91BB, 0x905C, 0x91BC, 0x4ED6, 0x91BD, 0x591A, + 0x91BE, 0x592A, 0x91BF, 0x6C70, 0x91C0, 0x8A51, 0x91C1, 0x553E, 0x91C2, 0x5815, 0x91C3, 0x59A5, 0x91C4, 0x60F0, 0x91C5, 0x6253, + 0x91C6, 0x67C1, 0x91C7, 0x8235, 0x91C8, 0x6955, 0x91C9, 0x9640, 0x91CA, 0x99C4, 0x91CB, 0x9A28, 0x91CC, 0x4F53, 0x91CD, 0x5806, + 0x91CE, 0x5BFE, 0x91CF, 0x8010, 0x91D0, 0x5CB1, 0x91D1, 0x5E2F, 0x91D2, 0x5F85, 0x91D3, 0x6020, 0x91D4, 0x614B, 0x91D5, 0x6234, + 0x91D6, 0x66FF, 0x91D7, 0x6CF0, 0x91D8, 0x6EDE, 0x91D9, 0x80CE, 0x91DA, 0x817F, 0x91DB, 0x82D4, 0x91DC, 0x888B, 0x91DD, 0x8CB8, + 0x91DE, 0x9000, 0x91DF, 0x902E, 0x91E0, 0x968A, 0x91E1, 0x9EDB, 0x91E2, 0x9BDB, 0x91E3, 0x4EE3, 0x91E4, 0x53F0, 0x91E5, 0x5927, + 0x91E6, 0x7B2C, 0x91E7, 0x918D, 0x91E8, 0x984C, 0x91E9, 0x9DF9, 0x91EA, 0x6EDD, 0x91EB, 0x7027, 0x91EC, 0x5353, 0x91ED, 0x5544, + 0x91EE, 0x5B85, 0x91EF, 0x6258, 0x91F0, 0x629E, 0x91F1, 0x62D3, 0x91F2, 0x6CA2, 0x91F3, 0x6FEF, 0x91F4, 0x7422, 0x91F5, 0x8A17, + 0x91F6, 0x9438, 0x91F7, 0x6FC1, 0x91F8, 0x8AFE, 0x91F9, 0x8338, 0x91FA, 0x51E7, 0x91FB, 0x86F8, 0x91FC, 0x53EA, 0x9240, 0x53E9, + 0x9241, 0x4F46, 0x9242, 0x9054, 0x9243, 0x8FB0, 0x9244, 0x596A, 0x9245, 0x8131, 0x9246, 0x5DFD, 0x9247, 0x7AEA, 0x9248, 0x8FBF, + 0x9249, 0x68DA, 0x924A, 0x8C37, 0x924B, 0x72F8, 0x924C, 0x9C48, 0x924D, 0x6A3D, 0x924E, 0x8AB0, 0x924F, 0x4E39, 0x9250, 0x5358, + 0x9251, 0x5606, 0x9252, 0x5766, 0x9253, 0x62C5, 0x9254, 0x63A2, 0x9255, 0x65E6, 0x9256, 0x6B4E, 0x9257, 0x6DE1, 0x9258, 0x6E5B, + 0x9259, 0x70AD, 0x925A, 0x77ED, 0x925B, 0x7AEF, 0x925C, 0x7BAA, 0x925D, 0x7DBB, 0x925E, 0x803D, 0x925F, 0x80C6, 0x9260, 0x86CB, + 0x9261, 0x8A95, 0x9262, 0x935B, 0x9263, 0x56E3, 0x9264, 0x58C7, 0x9265, 0x5F3E, 0x9266, 0x65AD, 0x9267, 0x6696, 0x9268, 0x6A80, + 0x9269, 0x6BB5, 0x926A, 0x7537, 0x926B, 0x8AC7, 0x926C, 0x5024, 0x926D, 0x77E5, 0x926E, 0x5730, 0x926F, 0x5F1B, 0x9270, 0x6065, + 0x9271, 0x667A, 0x9272, 0x6C60, 0x9273, 0x75F4, 0x9274, 0x7A1A, 0x9275, 0x7F6E, 0x9276, 0x81F4, 0x9277, 0x8718, 0x9278, 0x9045, + 0x9279, 0x99B3, 0x927A, 0x7BC9, 0x927B, 0x755C, 0x927C, 0x7AF9, 0x927D, 0x7B51, 0x927E, 0x84C4, 0x9280, 0x9010, 0x9281, 0x79E9, + 0x9282, 0x7A92, 0x9283, 0x8336, 0x9284, 0x5AE1, 0x9285, 0x7740, 0x9286, 0x4E2D, 0x9287, 0x4EF2, 0x9288, 0x5B99, 0x9289, 0x5FE0, + 0x928A, 0x62BD, 0x928B, 0x663C, 0x928C, 0x67F1, 0x928D, 0x6CE8, 0x928E, 0x866B, 0x928F, 0x8877, 0x9290, 0x8A3B, 0x9291, 0x914E, + 0x9292, 0x92F3, 0x9293, 0x99D0, 0x9294, 0x6A17, 0x9295, 0x7026, 0x9296, 0x732A, 0x9297, 0x82E7, 0x9298, 0x8457, 0x9299, 0x8CAF, + 0x929A, 0x4E01, 0x929B, 0x5146, 0x929C, 0x51CB, 0x929D, 0x558B, 0x929E, 0x5BF5, 0x929F, 0x5E16, 0x92A0, 0x5E33, 0x92A1, 0x5E81, + 0x92A2, 0x5F14, 0x92A3, 0x5F35, 0x92A4, 0x5F6B, 0x92A5, 0x5FB4, 0x92A6, 0x61F2, 0x92A7, 0x6311, 0x92A8, 0x66A2, 0x92A9, 0x671D, + 0x92AA, 0x6F6E, 0x92AB, 0x7252, 0x92AC, 0x753A, 0x92AD, 0x773A, 0x92AE, 0x8074, 0x92AF, 0x8139, 0x92B0, 0x8178, 0x92B1, 0x8776, + 0x92B2, 0x8ABF, 0x92B3, 0x8ADC, 0x92B4, 0x8D85, 0x92B5, 0x8DF3, 0x92B6, 0x929A, 0x92B7, 0x9577, 0x92B8, 0x9802, 0x92B9, 0x9CE5, + 0x92BA, 0x52C5, 0x92BB, 0x6357, 0x92BC, 0x76F4, 0x92BD, 0x6715, 0x92BE, 0x6C88, 0x92BF, 0x73CD, 0x92C0, 0x8CC3, 0x92C1, 0x93AE, + 0x92C2, 0x9673, 0x92C3, 0x6D25, 0x92C4, 0x589C, 0x92C5, 0x690E, 0x92C6, 0x69CC, 0x92C7, 0x8FFD, 0x92C8, 0x939A, 0x92C9, 0x75DB, + 0x92CA, 0x901A, 0x92CB, 0x585A, 0x92CC, 0x6802, 0x92CD, 0x63B4, 0x92CE, 0x69FB, 0x92CF, 0x4F43, 0x92D0, 0x6F2C, 0x92D1, 0x67D8, + 0x92D2, 0x8FBB, 0x92D3, 0x8526, 0x92D4, 0x7DB4, 0x92D5, 0x9354, 0x92D6, 0x693F, 0x92D7, 0x6F70, 0x92D8, 0x576A, 0x92D9, 0x58F7, + 0x92DA, 0x5B2C, 0x92DB, 0x7D2C, 0x92DC, 0x722A, 0x92DD, 0x540A, 0x92DE, 0x91E3, 0x92DF, 0x9DB4, 0x92E0, 0x4EAD, 0x92E1, 0x4F4E, + 0x92E2, 0x505C, 0x92E3, 0x5075, 0x92E4, 0x5243, 0x92E5, 0x8C9E, 0x92E6, 0x5448, 0x92E7, 0x5824, 0x92E8, 0x5B9A, 0x92E9, 0x5E1D, + 0x92EA, 0x5E95, 0x92EB, 0x5EAD, 0x92EC, 0x5EF7, 0x92ED, 0x5F1F, 0x92EE, 0x608C, 0x92EF, 0x62B5, 0x92F0, 0x633A, 0x92F1, 0x63D0, + 0x92F2, 0x68AF, 0x92F3, 0x6C40, 0x92F4, 0x7887, 0x92F5, 0x798E, 0x92F6, 0x7A0B, 0x92F7, 0x7DE0, 0x92F8, 0x8247, 0x92F9, 0x8A02, + 0x92FA, 0x8AE6, 0x92FB, 0x8E44, 0x92FC, 0x9013, 0x9340, 0x90B8, 0x9341, 0x912D, 0x9342, 0x91D8, 0x9343, 0x9F0E, 0x9344, 0x6CE5, + 0x9345, 0x6458, 0x9346, 0x64E2, 0x9347, 0x6575, 0x9348, 0x6EF4, 0x9349, 0x7684, 0x934A, 0x7B1B, 0x934B, 0x9069, 0x934C, 0x93D1, + 0x934D, 0x6EBA, 0x934E, 0x54F2, 0x934F, 0x5FB9, 0x9350, 0x64A4, 0x9351, 0x8F4D, 0x9352, 0x8FED, 0x9353, 0x9244, 0x9354, 0x5178, + 0x9355, 0x586B, 0x9356, 0x5929, 0x9357, 0x5C55, 0x9358, 0x5E97, 0x9359, 0x6DFB, 0x935A, 0x7E8F, 0x935B, 0x751C, 0x935C, 0x8CBC, + 0x935D, 0x8EE2, 0x935E, 0x985B, 0x935F, 0x70B9, 0x9360, 0x4F1D, 0x9361, 0x6BBF, 0x9362, 0x6FB1, 0x9363, 0x7530, 0x9364, 0x96FB, + 0x9365, 0x514E, 0x9366, 0x5410, 0x9367, 0x5835, 0x9368, 0x5857, 0x9369, 0x59AC, 0x936A, 0x5C60, 0x936B, 0x5F92, 0x936C, 0x6597, + 0x936D, 0x675C, 0x936E, 0x6E21, 0x936F, 0x767B, 0x9370, 0x83DF, 0x9371, 0x8CED, 0x9372, 0x9014, 0x9373, 0x90FD, 0x9374, 0x934D, + 0x9375, 0x7825, 0x9376, 0x783A, 0x9377, 0x52AA, 0x9378, 0x5EA6, 0x9379, 0x571F, 0x937A, 0x5974, 0x937B, 0x6012, 0x937C, 0x5012, + 0x937D, 0x515A, 0x937E, 0x51AC, 0x9380, 0x51CD, 0x9381, 0x5200, 0x9382, 0x5510, 0x9383, 0x5854, 0x9384, 0x5858, 0x9385, 0x5957, + 0x9386, 0x5B95, 0x9387, 0x5CF6, 0x9388, 0x5D8B, 0x9389, 0x60BC, 0x938A, 0x6295, 0x938B, 0x642D, 0x938C, 0x6771, 0x938D, 0x6843, + 0x938E, 0x68BC, 0x938F, 0x68DF, 0x9390, 0x76D7, 0x9391, 0x6DD8, 0x9392, 0x6E6F, 0x9393, 0x6D9B, 0x9394, 0x706F, 0x9395, 0x71C8, + 0x9396, 0x5F53, 0x9397, 0x75D8, 0x9398, 0x7977, 0x9399, 0x7B49, 0x939A, 0x7B54, 0x939B, 0x7B52, 0x939C, 0x7CD6, 0x939D, 0x7D71, + 0x939E, 0x5230, 0x939F, 0x8463, 0x93A0, 0x8569, 0x93A1, 0x85E4, 0x93A2, 0x8A0E, 0x93A3, 0x8B04, 0x93A4, 0x8C46, 0x93A5, 0x8E0F, + 0x93A6, 0x9003, 0x93A7, 0x900F, 0x93A8, 0x9419, 0x93A9, 0x9676, 0x93AA, 0x982D, 0x93AB, 0x9A30, 0x93AC, 0x95D8, 0x93AD, 0x50CD, + 0x93AE, 0x52D5, 0x93AF, 0x540C, 0x93B0, 0x5802, 0x93B1, 0x5C0E, 0x93B2, 0x61A7, 0x93B3, 0x649E, 0x93B4, 0x6D1E, 0x93B5, 0x77B3, + 0x93B6, 0x7AE5, 0x93B7, 0x80F4, 0x93B8, 0x8404, 0x93B9, 0x9053, 0x93BA, 0x9285, 0x93BB, 0x5CE0, 0x93BC, 0x9D07, 0x93BD, 0x533F, + 0x93BE, 0x5F97, 0x93BF, 0x5FB3, 0x93C0, 0x6D9C, 0x93C1, 0x7279, 0x93C2, 0x7763, 0x93C3, 0x79BF, 0x93C4, 0x7BE4, 0x93C5, 0x6BD2, + 0x93C6, 0x72EC, 0x93C7, 0x8AAD, 0x93C8, 0x6803, 0x93C9, 0x6A61, 0x93CA, 0x51F8, 0x93CB, 0x7A81, 0x93CC, 0x6934, 0x93CD, 0x5C4A, + 0x93CE, 0x9CF6, 0x93CF, 0x82EB, 0x93D0, 0x5BC5, 0x93D1, 0x9149, 0x93D2, 0x701E, 0x93D3, 0x5678, 0x93D4, 0x5C6F, 0x93D5, 0x60C7, + 0x93D6, 0x6566, 0x93D7, 0x6C8C, 0x93D8, 0x8C5A, 0x93D9, 0x9041, 0x93DA, 0x9813, 0x93DB, 0x5451, 0x93DC, 0x66C7, 0x93DD, 0x920D, + 0x93DE, 0x5948, 0x93DF, 0x90A3, 0x93E0, 0x5185, 0x93E1, 0x4E4D, 0x93E2, 0x51EA, 0x93E3, 0x8599, 0x93E4, 0x8B0E, 0x93E5, 0x7058, + 0x93E6, 0x637A, 0x93E7, 0x934B, 0x93E8, 0x6962, 0x93E9, 0x99B4, 0x93EA, 0x7E04, 0x93EB, 0x7577, 0x93EC, 0x5357, 0x93ED, 0x6960, + 0x93EE, 0x8EDF, 0x93EF, 0x96E3, 0x93F0, 0x6C5D, 0x93F1, 0x4E8C, 0x93F2, 0x5C3C, 0x93F3, 0x5F10, 0x93F4, 0x8FE9, 0x93F5, 0x5302, + 0x93F6, 0x8CD1, 0x93F7, 0x8089, 0x93F8, 0x8679, 0x93F9, 0x5EFF, 0x93FA, 0x65E5, 0x93FB, 0x4E73, 0x93FC, 0x5165, 0x9440, 0x5982, + 0x9441, 0x5C3F, 0x9442, 0x97EE, 0x9443, 0x4EFB, 0x9444, 0x598A, 0x9445, 0x5FCD, 0x9446, 0x8A8D, 0x9447, 0x6FE1, 0x9448, 0x79B0, + 0x9449, 0x7962, 0x944A, 0x5BE7, 0x944B, 0x8471, 0x944C, 0x732B, 0x944D, 0x71B1, 0x944E, 0x5E74, 0x944F, 0x5FF5, 0x9450, 0x637B, + 0x9451, 0x649A, 0x9452, 0x71C3, 0x9453, 0x7C98, 0x9454, 0x4E43, 0x9455, 0x5EFC, 0x9456, 0x4E4B, 0x9457, 0x57DC, 0x9458, 0x56A2, + 0x9459, 0x60A9, 0x945A, 0x6FC3, 0x945B, 0x7D0D, 0x945C, 0x80FD, 0x945D, 0x8133, 0x945E, 0x81BF, 0x945F, 0x8FB2, 0x9460, 0x8997, + 0x9461, 0x86A4, 0x9462, 0x5DF4, 0x9463, 0x628A, 0x9464, 0x64AD, 0x9465, 0x8987, 0x9466, 0x6777, 0x9467, 0x6CE2, 0x9468, 0x6D3E, + 0x9469, 0x7436, 0x946A, 0x7834, 0x946B, 0x5A46, 0x946C, 0x7F75, 0x946D, 0x82AD, 0x946E, 0x99AC, 0x946F, 0x4FF3, 0x9470, 0x5EC3, + 0x9471, 0x62DD, 0x9472, 0x6392, 0x9473, 0x6557, 0x9474, 0x676F, 0x9475, 0x76C3, 0x9476, 0x724C, 0x9477, 0x80CC, 0x9478, 0x80BA, + 0x9479, 0x8F29, 0x947A, 0x914D, 0x947B, 0x500D, 0x947C, 0x57F9, 0x947D, 0x5A92, 0x947E, 0x6885, 0x9480, 0x6973, 0x9481, 0x7164, + 0x9482, 0x72FD, 0x9483, 0x8CB7, 0x9484, 0x58F2, 0x9485, 0x8CE0, 0x9486, 0x966A, 0x9487, 0x9019, 0x9488, 0x877F, 0x9489, 0x79E4, + 0x948A, 0x77E7, 0x948B, 0x8429, 0x948C, 0x4F2F, 0x948D, 0x5265, 0x948E, 0x535A, 0x948F, 0x62CD, 0x9490, 0x67CF, 0x9491, 0x6CCA, + 0x9492, 0x767D, 0x9493, 0x7B94, 0x9494, 0x7C95, 0x9495, 0x8236, 0x9496, 0x8584, 0x9497, 0x8FEB, 0x9498, 0x66DD, 0x9499, 0x6F20, + 0x949A, 0x7206, 0x949B, 0x7E1B, 0x949C, 0x83AB, 0x949D, 0x99C1, 0x949E, 0x9EA6, 0x949F, 0x51FD, 0x94A0, 0x7BB1, 0x94A1, 0x7872, + 0x94A2, 0x7BB8, 0x94A3, 0x8087, 0x94A4, 0x7B48, 0x94A5, 0x6AE8, 0x94A6, 0x5E61, 0x94A7, 0x808C, 0x94A8, 0x7551, 0x94A9, 0x7560, + 0x94AA, 0x516B, 0x94AB, 0x9262, 0x94AC, 0x6E8C, 0x94AD, 0x767A, 0x94AE, 0x9197, 0x94AF, 0x9AEA, 0x94B0, 0x4F10, 0x94B1, 0x7F70, + 0x94B2, 0x629C, 0x94B3, 0x7B4F, 0x94B4, 0x95A5, 0x94B5, 0x9CE9, 0x94B6, 0x567A, 0x94B7, 0x5859, 0x94B8, 0x86E4, 0x94B9, 0x96BC, + 0x94BA, 0x4F34, 0x94BB, 0x5224, 0x94BC, 0x534A, 0x94BD, 0x53CD, 0x94BE, 0x53DB, 0x94BF, 0x5E06, 0x94C0, 0x642C, 0x94C1, 0x6591, + 0x94C2, 0x677F, 0x94C3, 0x6C3E, 0x94C4, 0x6C4E, 0x94C5, 0x7248, 0x94C6, 0x72AF, 0x94C7, 0x73ED, 0x94C8, 0x7554, 0x94C9, 0x7E41, + 0x94CA, 0x822C, 0x94CB, 0x85E9, 0x94CC, 0x8CA9, 0x94CD, 0x7BC4, 0x94CE, 0x91C6, 0x94CF, 0x7169, 0x94D0, 0x9812, 0x94D1, 0x98EF, + 0x94D2, 0x633D, 0x94D3, 0x6669, 0x94D4, 0x756A, 0x94D5, 0x76E4, 0x94D6, 0x78D0, 0x94D7, 0x8543, 0x94D8, 0x86EE, 0x94D9, 0x532A, + 0x94DA, 0x5351, 0x94DB, 0x5426, 0x94DC, 0x5983, 0x94DD, 0x5E87, 0x94DE, 0x5F7C, 0x94DF, 0x60B2, 0x94E0, 0x6249, 0x94E1, 0x6279, + 0x94E2, 0x62AB, 0x94E3, 0x6590, 0x94E4, 0x6BD4, 0x94E5, 0x6CCC, 0x94E6, 0x75B2, 0x94E7, 0x76AE, 0x94E8, 0x7891, 0x94E9, 0x79D8, + 0x94EA, 0x7DCB, 0x94EB, 0x7F77, 0x94EC, 0x80A5, 0x94ED, 0x88AB, 0x94EE, 0x8AB9, 0x94EF, 0x8CBB, 0x94F0, 0x907F, 0x94F1, 0x975E, + 0x94F2, 0x98DB, 0x94F3, 0x6A0B, 0x94F4, 0x7C38, 0x94F5, 0x5099, 0x94F6, 0x5C3E, 0x94F7, 0x5FAE, 0x94F8, 0x6787, 0x94F9, 0x6BD8, + 0x94FA, 0x7435, 0x94FB, 0x7709, 0x94FC, 0x7F8E, 0x9540, 0x9F3B, 0x9541, 0x67CA, 0x9542, 0x7A17, 0x9543, 0x5339, 0x9544, 0x758B, + 0x9545, 0x9AED, 0x9546, 0x5F66, 0x9547, 0x819D, 0x9548, 0x83F1, 0x9549, 0x8098, 0x954A, 0x5F3C, 0x954B, 0x5FC5, 0x954C, 0x7562, + 0x954D, 0x7B46, 0x954E, 0x903C, 0x954F, 0x6867, 0x9550, 0x59EB, 0x9551, 0x5A9B, 0x9552, 0x7D10, 0x9553, 0x767E, 0x9554, 0x8B2C, + 0x9555, 0x4FF5, 0x9556, 0x5F6A, 0x9557, 0x6A19, 0x9558, 0x6C37, 0x9559, 0x6F02, 0x955A, 0x74E2, 0x955B, 0x7968, 0x955C, 0x8868, + 0x955D, 0x8A55, 0x955E, 0x8C79, 0x955F, 0x5EDF, 0x9560, 0x63CF, 0x9561, 0x75C5, 0x9562, 0x79D2, 0x9563, 0x82D7, 0x9564, 0x9328, + 0x9565, 0x92F2, 0x9566, 0x849C, 0x9567, 0x86ED, 0x9568, 0x9C2D, 0x9569, 0x54C1, 0x956A, 0x5F6C, 0x956B, 0x658C, 0x956C, 0x6D5C, + 0x956D, 0x7015, 0x956E, 0x8CA7, 0x956F, 0x8CD3, 0x9570, 0x983B, 0x9571, 0x654F, 0x9572, 0x74F6, 0x9573, 0x4E0D, 0x9574, 0x4ED8, + 0x9575, 0x57E0, 0x9576, 0x592B, 0x9577, 0x5A66, 0x9578, 0x5BCC, 0x9579, 0x51A8, 0x957A, 0x5E03, 0x957B, 0x5E9C, 0x957C, 0x6016, + 0x957D, 0x6276, 0x957E, 0x6577, 0x9580, 0x65A7, 0x9581, 0x666E, 0x9582, 0x6D6E, 0x9583, 0x7236, 0x9584, 0x7B26, 0x9585, 0x8150, + 0x9586, 0x819A, 0x9587, 0x8299, 0x9588, 0x8B5C, 0x9589, 0x8CA0, 0x958A, 0x8CE6, 0x958B, 0x8D74, 0x958C, 0x961C, 0x958D, 0x9644, + 0x958E, 0x4FAE, 0x958F, 0x64AB, 0x9590, 0x6B66, 0x9591, 0x821E, 0x9592, 0x8461, 0x9593, 0x856A, 0x9594, 0x90E8, 0x9595, 0x5C01, + 0x9596, 0x6953, 0x9597, 0x98A8, 0x9598, 0x847A, 0x9599, 0x8557, 0x959A, 0x4F0F, 0x959B, 0x526F, 0x959C, 0x5FA9, 0x959D, 0x5E45, + 0x959E, 0x670D, 0x959F, 0x798F, 0x95A0, 0x8179, 0x95A1, 0x8907, 0x95A2, 0x8986, 0x95A3, 0x6DF5, 0x95A4, 0x5F17, 0x95A5, 0x6255, + 0x95A6, 0x6CB8, 0x95A7, 0x4ECF, 0x95A8, 0x7269, 0x95A9, 0x9B92, 0x95AA, 0x5206, 0x95AB, 0x543B, 0x95AC, 0x5674, 0x95AD, 0x58B3, + 0x95AE, 0x61A4, 0x95AF, 0x626E, 0x95B0, 0x711A, 0x95B1, 0x596E, 0x95B2, 0x7C89, 0x95B3, 0x7CDE, 0x95B4, 0x7D1B, 0x95B5, 0x96F0, + 0x95B6, 0x6587, 0x95B7, 0x805E, 0x95B8, 0x4E19, 0x95B9, 0x4F75, 0x95BA, 0x5175, 0x95BB, 0x5840, 0x95BC, 0x5E63, 0x95BD, 0x5E73, + 0x95BE, 0x5F0A, 0x95BF, 0x67C4, 0x95C0, 0x4E26, 0x95C1, 0x853D, 0x95C2, 0x9589, 0x95C3, 0x965B, 0x95C4, 0x7C73, 0x95C5, 0x9801, + 0x95C6, 0x50FB, 0x95C7, 0x58C1, 0x95C8, 0x7656, 0x95C9, 0x78A7, 0x95CA, 0x5225, 0x95CB, 0x77A5, 0x95CC, 0x8511, 0x95CD, 0x7B86, + 0x95CE, 0x504F, 0x95CF, 0x5909, 0x95D0, 0x7247, 0x95D1, 0x7BC7, 0x95D2, 0x7DE8, 0x95D3, 0x8FBA, 0x95D4, 0x8FD4, 0x95D5, 0x904D, + 0x95D6, 0x4FBF, 0x95D7, 0x52C9, 0x95D8, 0x5A29, 0x95D9, 0x5F01, 0x95DA, 0x97AD, 0x95DB, 0x4FDD, 0x95DC, 0x8217, 0x95DD, 0x92EA, + 0x95DE, 0x5703, 0x95DF, 0x6355, 0x95E0, 0x6B69, 0x95E1, 0x752B, 0x95E2, 0x88DC, 0x95E3, 0x8F14, 0x95E4, 0x7A42, 0x95E5, 0x52DF, + 0x95E6, 0x5893, 0x95E7, 0x6155, 0x95E8, 0x620A, 0x95E9, 0x66AE, 0x95EA, 0x6BCD, 0x95EB, 0x7C3F, 0x95EC, 0x83E9, 0x95ED, 0x5023, + 0x95EE, 0x4FF8, 0x95EF, 0x5305, 0x95F0, 0x5446, 0x95F1, 0x5831, 0x95F2, 0x5949, 0x95F3, 0x5B9D, 0x95F4, 0x5CF0, 0x95F5, 0x5CEF, + 0x95F6, 0x5D29, 0x95F7, 0x5E96, 0x95F8, 0x62B1, 0x95F9, 0x6367, 0x95FA, 0x653E, 0x95FB, 0x65B9, 0x95FC, 0x670B, 0x9640, 0x6CD5, + 0x9641, 0x6CE1, 0x9642, 0x70F9, 0x9643, 0x7832, 0x9644, 0x7E2B, 0x9645, 0x80DE, 0x9646, 0x82B3, 0x9647, 0x840C, 0x9648, 0x84EC, + 0x9649, 0x8702, 0x964A, 0x8912, 0x964B, 0x8A2A, 0x964C, 0x8C4A, 0x964D, 0x90A6, 0x964E, 0x92D2, 0x964F, 0x98FD, 0x9650, 0x9CF3, + 0x9651, 0x9D6C, 0x9652, 0x4E4F, 0x9653, 0x4EA1, 0x9654, 0x508D, 0x9655, 0x5256, 0x9656, 0x574A, 0x9657, 0x59A8, 0x9658, 0x5E3D, + 0x9659, 0x5FD8, 0x965A, 0x5FD9, 0x965B, 0x623F, 0x965C, 0x66B4, 0x965D, 0x671B, 0x965E, 0x67D0, 0x965F, 0x68D2, 0x9660, 0x5192, + 0x9661, 0x7D21, 0x9662, 0x80AA, 0x9663, 0x81A8, 0x9664, 0x8B00, 0x9665, 0x8C8C, 0x9666, 0x8CBF, 0x9667, 0x927E, 0x9668, 0x9632, + 0x9669, 0x5420, 0x966A, 0x982C, 0x966B, 0x5317, 0x966C, 0x50D5, 0x966D, 0x535C, 0x966E, 0x58A8, 0x966F, 0x64B2, 0x9670, 0x6734, + 0x9671, 0x7267, 0x9672, 0x7766, 0x9673, 0x7A46, 0x9674, 0x91E6, 0x9675, 0x52C3, 0x9676, 0x6CA1, 0x9677, 0x6B86, 0x9678, 0x5800, + 0x9679, 0x5E4C, 0x967A, 0x5954, 0x967B, 0x672C, 0x967C, 0x7FFB, 0x967D, 0x51E1, 0x967E, 0x76C6, 0x9680, 0x6469, 0x9681, 0x78E8, + 0x9682, 0x9B54, 0x9683, 0x9EBB, 0x9684, 0x57CB, 0x9685, 0x59B9, 0x9686, 0x6627, 0x9687, 0x679A, 0x9688, 0x6BCE, 0x9689, 0x54E9, + 0x968A, 0x69D9, 0x968B, 0x5E55, 0x968C, 0x819C, 0x968D, 0x6795, 0x968E, 0x9BAA, 0x968F, 0x67FE, 0x9690, 0x9C52, 0x9691, 0x685D, + 0x9692, 0x4EA6, 0x9693, 0x4FE3, 0x9694, 0x53C8, 0x9695, 0x62B9, 0x9696, 0x672B, 0x9697, 0x6CAB, 0x9698, 0x8FC4, 0x9699, 0x4FAD, + 0x969A, 0x7E6D, 0x969B, 0x9EBF, 0x969C, 0x4E07, 0x969D, 0x6162, 0x969E, 0x6E80, 0x969F, 0x6F2B, 0x96A0, 0x8513, 0x96A1, 0x5473, + 0x96A2, 0x672A, 0x96A3, 0x9B45, 0x96A4, 0x5DF3, 0x96A5, 0x7B95, 0x96A6, 0x5CAC, 0x96A7, 0x5BC6, 0x96A8, 0x871C, 0x96A9, 0x6E4A, + 0x96AA, 0x84D1, 0x96AB, 0x7A14, 0x96AC, 0x8108, 0x96AD, 0x5999, 0x96AE, 0x7C8D, 0x96AF, 0x6C11, 0x96B0, 0x7720, 0x96B1, 0x52D9, + 0x96B2, 0x5922, 0x96B3, 0x7121, 0x96B4, 0x725F, 0x96B5, 0x77DB, 0x96B6, 0x9727, 0x96B7, 0x9D61, 0x96B8, 0x690B, 0x96B9, 0x5A7F, + 0x96BA, 0x5A18, 0x96BB, 0x51A5, 0x96BC, 0x540D, 0x96BD, 0x547D, 0x96BE, 0x660E, 0x96BF, 0x76DF, 0x96C0, 0x8FF7, 0x96C1, 0x9298, + 0x96C2, 0x9CF4, 0x96C3, 0x59EA, 0x96C4, 0x725D, 0x96C5, 0x6EC5, 0x96C6, 0x514D, 0x96C7, 0x68C9, 0x96C8, 0x7DBF, 0x96C9, 0x7DEC, + 0x96CA, 0x9762, 0x96CB, 0x9EBA, 0x96CC, 0x6478, 0x96CD, 0x6A21, 0x96CE, 0x8302, 0x96CF, 0x5984, 0x96D0, 0x5B5F, 0x96D1, 0x6BDB, + 0x96D2, 0x731B, 0x96D3, 0x76F2, 0x96D4, 0x7DB2, 0x96D5, 0x8017, 0x96D6, 0x8499, 0x96D7, 0x5132, 0x96D8, 0x6728, 0x96D9, 0x9ED9, + 0x96DA, 0x76EE, 0x96DB, 0x6762, 0x96DC, 0x52FF, 0x96DD, 0x9905, 0x96DE, 0x5C24, 0x96DF, 0x623B, 0x96E0, 0x7C7E, 0x96E1, 0x8CB0, + 0x96E2, 0x554F, 0x96E3, 0x60B6, 0x96E4, 0x7D0B, 0x96E5, 0x9580, 0x96E6, 0x5301, 0x96E7, 0x4E5F, 0x96E8, 0x51B6, 0x96E9, 0x591C, + 0x96EA, 0x723A, 0x96EB, 0x8036, 0x96EC, 0x91CE, 0x96ED, 0x5F25, 0x96EE, 0x77E2, 0x96EF, 0x5384, 0x96F0, 0x5F79, 0x96F1, 0x7D04, + 0x96F2, 0x85AC, 0x96F3, 0x8A33, 0x96F4, 0x8E8D, 0x96F5, 0x9756, 0x96F6, 0x67F3, 0x96F7, 0x85AE, 0x96F8, 0x9453, 0x96F9, 0x6109, + 0x96FA, 0x6108, 0x96FB, 0x6CB9, 0x96FC, 0x7652, 0x9740, 0x8AED, 0x9741, 0x8F38, 0x9742, 0x552F, 0x9743, 0x4F51, 0x9744, 0x512A, + 0x9745, 0x52C7, 0x9746, 0x53CB, 0x9747, 0x5BA5, 0x9748, 0x5E7D, 0x9749, 0x60A0, 0x974A, 0x6182, 0x974B, 0x63D6, 0x974C, 0x6709, + 0x974D, 0x67DA, 0x974E, 0x6E67, 0x974F, 0x6D8C, 0x9750, 0x7336, 0x9751, 0x7337, 0x9752, 0x7531, 0x9753, 0x7950, 0x9754, 0x88D5, + 0x9755, 0x8A98, 0x9756, 0x904A, 0x9757, 0x9091, 0x9758, 0x90F5, 0x9759, 0x96C4, 0x975A, 0x878D, 0x975B, 0x5915, 0x975C, 0x4E88, + 0x975D, 0x4F59, 0x975E, 0x4E0E, 0x975F, 0x8A89, 0x9760, 0x8F3F, 0x9761, 0x9810, 0x9762, 0x50AD, 0x9763, 0x5E7C, 0x9764, 0x5996, + 0x9765, 0x5BB9, 0x9766, 0x5EB8, 0x9767, 0x63DA, 0x9768, 0x63FA, 0x9769, 0x64C1, 0x976A, 0x66DC, 0x976B, 0x694A, 0x976C, 0x69D8, + 0x976D, 0x6D0B, 0x976E, 0x6EB6, 0x976F, 0x7194, 0x9770, 0x7528, 0x9771, 0x7AAF, 0x9772, 0x7F8A, 0x9773, 0x8000, 0x9774, 0x8449, + 0x9775, 0x84C9, 0x9776, 0x8981, 0x9777, 0x8B21, 0x9778, 0x8E0A, 0x9779, 0x9065, 0x977A, 0x967D, 0x977B, 0x990A, 0x977C, 0x617E, + 0x977D, 0x6291, 0x977E, 0x6B32, 0x9780, 0x6C83, 0x9781, 0x6D74, 0x9782, 0x7FCC, 0x9783, 0x7FFC, 0x9784, 0x6DC0, 0x9785, 0x7F85, + 0x9786, 0x87BA, 0x9787, 0x88F8, 0x9788, 0x6765, 0x9789, 0x83B1, 0x978A, 0x983C, 0x978B, 0x96F7, 0x978C, 0x6D1B, 0x978D, 0x7D61, + 0x978E, 0x843D, 0x978F, 0x916A, 0x9790, 0x4E71, 0x9791, 0x5375, 0x9792, 0x5D50, 0x9793, 0x6B04, 0x9794, 0x6FEB, 0x9795, 0x85CD, + 0x9796, 0x862D, 0x9797, 0x89A7, 0x9798, 0x5229, 0x9799, 0x540F, 0x979A, 0x5C65, 0x979B, 0x674E, 0x979C, 0x68A8, 0x979D, 0x7406, + 0x979E, 0x7483, 0x979F, 0x75E2, 0x97A0, 0x88CF, 0x97A1, 0x88E1, 0x97A2, 0x91CC, 0x97A3, 0x96E2, 0x97A4, 0x9678, 0x97A5, 0x5F8B, + 0x97A6, 0x7387, 0x97A7, 0x7ACB, 0x97A8, 0x844E, 0x97A9, 0x63A0, 0x97AA, 0x7565, 0x97AB, 0x5289, 0x97AC, 0x6D41, 0x97AD, 0x6E9C, + 0x97AE, 0x7409, 0x97AF, 0x7559, 0x97B0, 0x786B, 0x97B1, 0x7C92, 0x97B2, 0x9686, 0x97B3, 0x7ADC, 0x97B4, 0x9F8D, 0x97B5, 0x4FB6, + 0x97B6, 0x616E, 0x97B7, 0x65C5, 0x97B8, 0x865C, 0x97B9, 0x4E86, 0x97BA, 0x4EAE, 0x97BB, 0x50DA, 0x97BC, 0x4E21, 0x97BD, 0x51CC, + 0x97BE, 0x5BEE, 0x97BF, 0x6599, 0x97C0, 0x6881, 0x97C1, 0x6DBC, 0x97C2, 0x731F, 0x97C3, 0x7642, 0x97C4, 0x77AD, 0x97C5, 0x7A1C, + 0x97C6, 0x7CE7, 0x97C7, 0x826F, 0x97C8, 0x8AD2, 0x97C9, 0x907C, 0x97CA, 0x91CF, 0x97CB, 0x9675, 0x97CC, 0x9818, 0x97CD, 0x529B, + 0x97CE, 0x7DD1, 0x97CF, 0x502B, 0x97D0, 0x5398, 0x97D1, 0x6797, 0x97D2, 0x6DCB, 0x97D3, 0x71D0, 0x97D4, 0x7433, 0x97D5, 0x81E8, + 0x97D6, 0x8F2A, 0x97D7, 0x96A3, 0x97D8, 0x9C57, 0x97D9, 0x9E9F, 0x97DA, 0x7460, 0x97DB, 0x5841, 0x97DC, 0x6D99, 0x97DD, 0x7D2F, + 0x97DE, 0x985E, 0x97DF, 0x4EE4, 0x97E0, 0x4F36, 0x97E1, 0x4F8B, 0x97E2, 0x51B7, 0x97E3, 0x52B1, 0x97E4, 0x5DBA, 0x97E5, 0x601C, + 0x97E6, 0x73B2, 0x97E7, 0x793C, 0x97E8, 0x82D3, 0x97E9, 0x9234, 0x97EA, 0x96B7, 0x97EB, 0x96F6, 0x97EC, 0x970A, 0x97ED, 0x9E97, + 0x97EE, 0x9F62, 0x97EF, 0x66A6, 0x97F0, 0x6B74, 0x97F1, 0x5217, 0x97F2, 0x52A3, 0x97F3, 0x70C8, 0x97F4, 0x88C2, 0x97F5, 0x5EC9, + 0x97F6, 0x604B, 0x97F7, 0x6190, 0x97F8, 0x6F23, 0x97F9, 0x7149, 0x97FA, 0x7C3E, 0x97FB, 0x7DF4, 0x97FC, 0x806F, 0x9840, 0x84EE, + 0x9841, 0x9023, 0x9842, 0x932C, 0x9843, 0x5442, 0x9844, 0x9B6F, 0x9845, 0x6AD3, 0x9846, 0x7089, 0x9847, 0x8CC2, 0x9848, 0x8DEF, + 0x9849, 0x9732, 0x984A, 0x52B4, 0x984B, 0x5A41, 0x984C, 0x5ECA, 0x984D, 0x5F04, 0x984E, 0x6717, 0x984F, 0x697C, 0x9850, 0x6994, + 0x9851, 0x6D6A, 0x9852, 0x6F0F, 0x9853, 0x7262, 0x9854, 0x72FC, 0x9855, 0x7BED, 0x9856, 0x8001, 0x9857, 0x807E, 0x9858, 0x874B, + 0x9859, 0x90CE, 0x985A, 0x516D, 0x985B, 0x9E93, 0x985C, 0x7984, 0x985D, 0x808B, 0x985E, 0x9332, 0x985F, 0x8AD6, 0x9860, 0x502D, + 0x9861, 0x548C, 0x9862, 0x8A71, 0x9863, 0x6B6A, 0x9864, 0x8CC4, 0x9865, 0x8107, 0x9866, 0x60D1, 0x9867, 0x67A0, 0x9868, 0x9DF2, + 0x9869, 0x4E99, 0x986A, 0x4E98, 0x986B, 0x9C10, 0x986C, 0x8A6B, 0x986D, 0x85C1, 0x986E, 0x8568, 0x986F, 0x6900, 0x9870, 0x6E7E, + 0x9871, 0x7897, 0x9872, 0x8155, 0x989F, 0x5F0C, 0x98A0, 0x4E10, 0x98A1, 0x4E15, 0x98A2, 0x4E2A, 0x98A3, 0x4E31, 0x98A4, 0x4E36, + 0x98A5, 0x4E3C, 0x98A6, 0x4E3F, 0x98A7, 0x4E42, 0x98A8, 0x4E56, 0x98A9, 0x4E58, 0x98AA, 0x4E82, 0x98AB, 0x4E85, 0x98AC, 0x8C6B, + 0x98AD, 0x4E8A, 0x98AE, 0x8212, 0x98AF, 0x5F0D, 0x98B0, 0x4E8E, 0x98B1, 0x4E9E, 0x98B2, 0x4E9F, 0x98B3, 0x4EA0, 0x98B4, 0x4EA2, + 0x98B5, 0x4EB0, 0x98B6, 0x4EB3, 0x98B7, 0x4EB6, 0x98B8, 0x4ECE, 0x98B9, 0x4ECD, 0x98BA, 0x4EC4, 0x98BB, 0x4EC6, 0x98BC, 0x4EC2, + 0x98BD, 0x4ED7, 0x98BE, 0x4EDE, 0x98BF, 0x4EED, 0x98C0, 0x4EDF, 0x98C1, 0x4EF7, 0x98C2, 0x4F09, 0x98C3, 0x4F5A, 0x98C4, 0x4F30, + 0x98C5, 0x4F5B, 0x98C6, 0x4F5D, 0x98C7, 0x4F57, 0x98C8, 0x4F47, 0x98C9, 0x4F76, 0x98CA, 0x4F88, 0x98CB, 0x4F8F, 0x98CC, 0x4F98, + 0x98CD, 0x4F7B, 0x98CE, 0x4F69, 0x98CF, 0x4F70, 0x98D0, 0x4F91, 0x98D1, 0x4F6F, 0x98D2, 0x4F86, 0x98D3, 0x4F96, 0x98D4, 0x5118, + 0x98D5, 0x4FD4, 0x98D6, 0x4FDF, 0x98D7, 0x4FCE, 0x98D8, 0x4FD8, 0x98D9, 0x4FDB, 0x98DA, 0x4FD1, 0x98DB, 0x4FDA, 0x98DC, 0x4FD0, + 0x98DD, 0x4FE4, 0x98DE, 0x4FE5, 0x98DF, 0x501A, 0x98E0, 0x5028, 0x98E1, 0x5014, 0x98E2, 0x502A, 0x98E3, 0x5025, 0x98E4, 0x5005, + 0x98E5, 0x4F1C, 0x98E6, 0x4FF6, 0x98E7, 0x5021, 0x98E8, 0x5029, 0x98E9, 0x502C, 0x98EA, 0x4FFE, 0x98EB, 0x4FEF, 0x98EC, 0x5011, + 0x98ED, 0x5006, 0x98EE, 0x5043, 0x98EF, 0x5047, 0x98F0, 0x6703, 0x98F1, 0x5055, 0x98F2, 0x5050, 0x98F3, 0x5048, 0x98F4, 0x505A, + 0x98F5, 0x5056, 0x98F6, 0x506C, 0x98F7, 0x5078, 0x98F8, 0x5080, 0x98F9, 0x509A, 0x98FA, 0x5085, 0x98FB, 0x50B4, 0x98FC, 0x50B2, + 0x9940, 0x50C9, 0x9941, 0x50CA, 0x9942, 0x50B3, 0x9943, 0x50C2, 0x9944, 0x50D6, 0x9945, 0x50DE, 0x9946, 0x50E5, 0x9947, 0x50ED, + 0x9948, 0x50E3, 0x9949, 0x50EE, 0x994A, 0x50F9, 0x994B, 0x50F5, 0x994C, 0x5109, 0x994D, 0x5101, 0x994E, 0x5102, 0x994F, 0x5116, + 0x9950, 0x5115, 0x9951, 0x5114, 0x9952, 0x511A, 0x9953, 0x5121, 0x9954, 0x513A, 0x9955, 0x5137, 0x9956, 0x513C, 0x9957, 0x513B, + 0x9958, 0x513F, 0x9959, 0x5140, 0x995A, 0x5152, 0x995B, 0x514C, 0x995C, 0x5154, 0x995D, 0x5162, 0x995E, 0x7AF8, 0x995F, 0x5169, + 0x9960, 0x516A, 0x9961, 0x516E, 0x9962, 0x5180, 0x9963, 0x5182, 0x9964, 0x56D8, 0x9965, 0x518C, 0x9966, 0x5189, 0x9967, 0x518F, + 0x9968, 0x5191, 0x9969, 0x5193, 0x996A, 0x5195, 0x996B, 0x5196, 0x996C, 0x51A4, 0x996D, 0x51A6, 0x996E, 0x51A2, 0x996F, 0x51A9, + 0x9970, 0x51AA, 0x9971, 0x51AB, 0x9972, 0x51B3, 0x9973, 0x51B1, 0x9974, 0x51B2, 0x9975, 0x51B0, 0x9976, 0x51B5, 0x9977, 0x51BD, + 0x9978, 0x51C5, 0x9979, 0x51C9, 0x997A, 0x51DB, 0x997B, 0x51E0, 0x997C, 0x8655, 0x997D, 0x51E9, 0x997E, 0x51ED, 0x9980, 0x51F0, + 0x9981, 0x51F5, 0x9982, 0x51FE, 0x9983, 0x5204, 0x9984, 0x520B, 0x9985, 0x5214, 0x9986, 0x520E, 0x9987, 0x5227, 0x9988, 0x522A, + 0x9989, 0x522E, 0x998A, 0x5233, 0x998B, 0x5239, 0x998C, 0x524F, 0x998D, 0x5244, 0x998E, 0x524B, 0x998F, 0x524C, 0x9990, 0x525E, + 0x9991, 0x5254, 0x9992, 0x526A, 0x9993, 0x5274, 0x9994, 0x5269, 0x9995, 0x5273, 0x9996, 0x527F, 0x9997, 0x527D, 0x9998, 0x528D, + 0x9999, 0x5294, 0x999A, 0x5292, 0x999B, 0x5271, 0x999C, 0x5288, 0x999D, 0x5291, 0x999E, 0x8FA8, 0x999F, 0x8FA7, 0x99A0, 0x52AC, + 0x99A1, 0x52AD, 0x99A2, 0x52BC, 0x99A3, 0x52B5, 0x99A4, 0x52C1, 0x99A5, 0x52CD, 0x99A6, 0x52D7, 0x99A7, 0x52DE, 0x99A8, 0x52E3, + 0x99A9, 0x52E6, 0x99AA, 0x98ED, 0x99AB, 0x52E0, 0x99AC, 0x52F3, 0x99AD, 0x52F5, 0x99AE, 0x52F8, 0x99AF, 0x52F9, 0x99B0, 0x5306, + 0x99B1, 0x5308, 0x99B2, 0x7538, 0x99B3, 0x530D, 0x99B4, 0x5310, 0x99B5, 0x530F, 0x99B6, 0x5315, 0x99B7, 0x531A, 0x99B8, 0x5323, + 0x99B9, 0x532F, 0x99BA, 0x5331, 0x99BB, 0x5333, 0x99BC, 0x5338, 0x99BD, 0x5340, 0x99BE, 0x5346, 0x99BF, 0x5345, 0x99C0, 0x4E17, + 0x99C1, 0x5349, 0x99C2, 0x534D, 0x99C3, 0x51D6, 0x99C4, 0x535E, 0x99C5, 0x5369, 0x99C6, 0x536E, 0x99C7, 0x5918, 0x99C8, 0x537B, + 0x99C9, 0x5377, 0x99CA, 0x5382, 0x99CB, 0x5396, 0x99CC, 0x53A0, 0x99CD, 0x53A6, 0x99CE, 0x53A5, 0x99CF, 0x53AE, 0x99D0, 0x53B0, + 0x99D1, 0x53B6, 0x99D2, 0x53C3, 0x99D3, 0x7C12, 0x99D4, 0x96D9, 0x99D5, 0x53DF, 0x99D6, 0x66FC, 0x99D7, 0x71EE, 0x99D8, 0x53EE, + 0x99D9, 0x53E8, 0x99DA, 0x53ED, 0x99DB, 0x53FA, 0x99DC, 0x5401, 0x99DD, 0x543D, 0x99DE, 0x5440, 0x99DF, 0x542C, 0x99E0, 0x542D, + 0x99E1, 0x543C, 0x99E2, 0x542E, 0x99E3, 0x5436, 0x99E4, 0x5429, 0x99E5, 0x541D, 0x99E6, 0x544E, 0x99E7, 0x548F, 0x99E8, 0x5475, + 0x99E9, 0x548E, 0x99EA, 0x545F, 0x99EB, 0x5471, 0x99EC, 0x5477, 0x99ED, 0x5470, 0x99EE, 0x5492, 0x99EF, 0x547B, 0x99F0, 0x5480, + 0x99F1, 0x5476, 0x99F2, 0x5484, 0x99F3, 0x5490, 0x99F4, 0x5486, 0x99F5, 0x54C7, 0x99F6, 0x54A2, 0x99F7, 0x54B8, 0x99F8, 0x54A5, + 0x99F9, 0x54AC, 0x99FA, 0x54C4, 0x99FB, 0x54C8, 0x99FC, 0x54A8, 0x9A40, 0x54AB, 0x9A41, 0x54C2, 0x9A42, 0x54A4, 0x9A43, 0x54BE, + 0x9A44, 0x54BC, 0x9A45, 0x54D8, 0x9A46, 0x54E5, 0x9A47, 0x54E6, 0x9A48, 0x550F, 0x9A49, 0x5514, 0x9A4A, 0x54FD, 0x9A4B, 0x54EE, + 0x9A4C, 0x54ED, 0x9A4D, 0x54FA, 0x9A4E, 0x54E2, 0x9A4F, 0x5539, 0x9A50, 0x5540, 0x9A51, 0x5563, 0x9A52, 0x554C, 0x9A53, 0x552E, + 0x9A54, 0x555C, 0x9A55, 0x5545, 0x9A56, 0x5556, 0x9A57, 0x5557, 0x9A58, 0x5538, 0x9A59, 0x5533, 0x9A5A, 0x555D, 0x9A5B, 0x5599, + 0x9A5C, 0x5580, 0x9A5D, 0x54AF, 0x9A5E, 0x558A, 0x9A5F, 0x559F, 0x9A60, 0x557B, 0x9A61, 0x557E, 0x9A62, 0x5598, 0x9A63, 0x559E, + 0x9A64, 0x55AE, 0x9A65, 0x557C, 0x9A66, 0x5583, 0x9A67, 0x55A9, 0x9A68, 0x5587, 0x9A69, 0x55A8, 0x9A6A, 0x55DA, 0x9A6B, 0x55C5, + 0x9A6C, 0x55DF, 0x9A6D, 0x55C4, 0x9A6E, 0x55DC, 0x9A6F, 0x55E4, 0x9A70, 0x55D4, 0x9A71, 0x5614, 0x9A72, 0x55F7, 0x9A73, 0x5616, + 0x9A74, 0x55FE, 0x9A75, 0x55FD, 0x9A76, 0x561B, 0x9A77, 0x55F9, 0x9A78, 0x564E, 0x9A79, 0x5650, 0x9A7A, 0x71DF, 0x9A7B, 0x5634, + 0x9A7C, 0x5636, 0x9A7D, 0x5632, 0x9A7E, 0x5638, 0x9A80, 0x566B, 0x9A81, 0x5664, 0x9A82, 0x562F, 0x9A83, 0x566C, 0x9A84, 0x566A, + 0x9A85, 0x5686, 0x9A86, 0x5680, 0x9A87, 0x568A, 0x9A88, 0x56A0, 0x9A89, 0x5694, 0x9A8A, 0x568F, 0x9A8B, 0x56A5, 0x9A8C, 0x56AE, + 0x9A8D, 0x56B6, 0x9A8E, 0x56B4, 0x9A8F, 0x56C2, 0x9A90, 0x56BC, 0x9A91, 0x56C1, 0x9A92, 0x56C3, 0x9A93, 0x56C0, 0x9A94, 0x56C8, + 0x9A95, 0x56CE, 0x9A96, 0x56D1, 0x9A97, 0x56D3, 0x9A98, 0x56D7, 0x9A99, 0x56EE, 0x9A9A, 0x56F9, 0x9A9B, 0x5700, 0x9A9C, 0x56FF, + 0x9A9D, 0x5704, 0x9A9E, 0x5709, 0x9A9F, 0x5708, 0x9AA0, 0x570B, 0x9AA1, 0x570D, 0x9AA2, 0x5713, 0x9AA3, 0x5718, 0x9AA4, 0x5716, + 0x9AA5, 0x55C7, 0x9AA6, 0x571C, 0x9AA7, 0x5726, 0x9AA8, 0x5737, 0x9AA9, 0x5738, 0x9AAA, 0x574E, 0x9AAB, 0x573B, 0x9AAC, 0x5740, + 0x9AAD, 0x574F, 0x9AAE, 0x5769, 0x9AAF, 0x57C0, 0x9AB0, 0x5788, 0x9AB1, 0x5761, 0x9AB2, 0x577F, 0x9AB3, 0x5789, 0x9AB4, 0x5793, + 0x9AB5, 0x57A0, 0x9AB6, 0x57B3, 0x9AB7, 0x57A4, 0x9AB8, 0x57AA, 0x9AB9, 0x57B0, 0x9ABA, 0x57C3, 0x9ABB, 0x57C6, 0x9ABC, 0x57D4, + 0x9ABD, 0x57D2, 0x9ABE, 0x57D3, 0x9ABF, 0x580A, 0x9AC0, 0x57D6, 0x9AC1, 0x57E3, 0x9AC2, 0x580B, 0x9AC3, 0x5819, 0x9AC4, 0x581D, + 0x9AC5, 0x5872, 0x9AC6, 0x5821, 0x9AC7, 0x5862, 0x9AC8, 0x584B, 0x9AC9, 0x5870, 0x9ACA, 0x6BC0, 0x9ACB, 0x5852, 0x9ACC, 0x583D, + 0x9ACD, 0x5879, 0x9ACE, 0x5885, 0x9ACF, 0x58B9, 0x9AD0, 0x589F, 0x9AD1, 0x58AB, 0x9AD2, 0x58BA, 0x9AD3, 0x58DE, 0x9AD4, 0x58BB, + 0x9AD5, 0x58B8, 0x9AD6, 0x58AE, 0x9AD7, 0x58C5, 0x9AD8, 0x58D3, 0x9AD9, 0x58D1, 0x9ADA, 0x58D7, 0x9ADB, 0x58D9, 0x9ADC, 0x58D8, + 0x9ADD, 0x58E5, 0x9ADE, 0x58DC, 0x9ADF, 0x58E4, 0x9AE0, 0x58DF, 0x9AE1, 0x58EF, 0x9AE2, 0x58FA, 0x9AE3, 0x58F9, 0x9AE4, 0x58FB, + 0x9AE5, 0x58FC, 0x9AE6, 0x58FD, 0x9AE7, 0x5902, 0x9AE8, 0x590A, 0x9AE9, 0x5910, 0x9AEA, 0x591B, 0x9AEB, 0x68A6, 0x9AEC, 0x5925, + 0x9AED, 0x592C, 0x9AEE, 0x592D, 0x9AEF, 0x5932, 0x9AF0, 0x5938, 0x9AF1, 0x593E, 0x9AF2, 0x7AD2, 0x9AF3, 0x5955, 0x9AF4, 0x5950, + 0x9AF5, 0x594E, 0x9AF6, 0x595A, 0x9AF7, 0x5958, 0x9AF8, 0x5962, 0x9AF9, 0x5960, 0x9AFA, 0x5967, 0x9AFB, 0x596C, 0x9AFC, 0x5969, + 0x9B40, 0x5978, 0x9B41, 0x5981, 0x9B42, 0x599D, 0x9B43, 0x4F5E, 0x9B44, 0x4FAB, 0x9B45, 0x59A3, 0x9B46, 0x59B2, 0x9B47, 0x59C6, + 0x9B48, 0x59E8, 0x9B49, 0x59DC, 0x9B4A, 0x598D, 0x9B4B, 0x59D9, 0x9B4C, 0x59DA, 0x9B4D, 0x5A25, 0x9B4E, 0x5A1F, 0x9B4F, 0x5A11, + 0x9B50, 0x5A1C, 0x9B51, 0x5A09, 0x9B52, 0x5A1A, 0x9B53, 0x5A40, 0x9B54, 0x5A6C, 0x9B55, 0x5A49, 0x9B56, 0x5A35, 0x9B57, 0x5A36, + 0x9B58, 0x5A62, 0x9B59, 0x5A6A, 0x9B5A, 0x5A9A, 0x9B5B, 0x5ABC, 0x9B5C, 0x5ABE, 0x9B5D, 0x5ACB, 0x9B5E, 0x5AC2, 0x9B5F, 0x5ABD, + 0x9B60, 0x5AE3, 0x9B61, 0x5AD7, 0x9B62, 0x5AE6, 0x9B63, 0x5AE9, 0x9B64, 0x5AD6, 0x9B65, 0x5AFA, 0x9B66, 0x5AFB, 0x9B67, 0x5B0C, + 0x9B68, 0x5B0B, 0x9B69, 0x5B16, 0x9B6A, 0x5B32, 0x9B6B, 0x5AD0, 0x9B6C, 0x5B2A, 0x9B6D, 0x5B36, 0x9B6E, 0x5B3E, 0x9B6F, 0x5B43, + 0x9B70, 0x5B45, 0x9B71, 0x5B40, 0x9B72, 0x5B51, 0x9B73, 0x5B55, 0x9B74, 0x5B5A, 0x9B75, 0x5B5B, 0x9B76, 0x5B65, 0x9B77, 0x5B69, + 0x9B78, 0x5B70, 0x9B79, 0x5B73, 0x9B7A, 0x5B75, 0x9B7B, 0x5B78, 0x9B7C, 0x6588, 0x9B7D, 0x5B7A, 0x9B7E, 0x5B80, 0x9B80, 0x5B83, + 0x9B81, 0x5BA6, 0x9B82, 0x5BB8, 0x9B83, 0x5BC3, 0x9B84, 0x5BC7, 0x9B85, 0x5BC9, 0x9B86, 0x5BD4, 0x9B87, 0x5BD0, 0x9B88, 0x5BE4, + 0x9B89, 0x5BE6, 0x9B8A, 0x5BE2, 0x9B8B, 0x5BDE, 0x9B8C, 0x5BE5, 0x9B8D, 0x5BEB, 0x9B8E, 0x5BF0, 0x9B8F, 0x5BF6, 0x9B90, 0x5BF3, + 0x9B91, 0x5C05, 0x9B92, 0x5C07, 0x9B93, 0x5C08, 0x9B94, 0x5C0D, 0x9B95, 0x5C13, 0x9B96, 0x5C20, 0x9B97, 0x5C22, 0x9B98, 0x5C28, + 0x9B99, 0x5C38, 0x9B9A, 0x5C39, 0x9B9B, 0x5C41, 0x9B9C, 0x5C46, 0x9B9D, 0x5C4E, 0x9B9E, 0x5C53, 0x9B9F, 0x5C50, 0x9BA0, 0x5C4F, + 0x9BA1, 0x5B71, 0x9BA2, 0x5C6C, 0x9BA3, 0x5C6E, 0x9BA4, 0x4E62, 0x9BA5, 0x5C76, 0x9BA6, 0x5C79, 0x9BA7, 0x5C8C, 0x9BA8, 0x5C91, + 0x9BA9, 0x5C94, 0x9BAA, 0x599B, 0x9BAB, 0x5CAB, 0x9BAC, 0x5CBB, 0x9BAD, 0x5CB6, 0x9BAE, 0x5CBC, 0x9BAF, 0x5CB7, 0x9BB0, 0x5CC5, + 0x9BB1, 0x5CBE, 0x9BB2, 0x5CC7, 0x9BB3, 0x5CD9, 0x9BB4, 0x5CE9, 0x9BB5, 0x5CFD, 0x9BB6, 0x5CFA, 0x9BB7, 0x5CED, 0x9BB8, 0x5D8C, + 0x9BB9, 0x5CEA, 0x9BBA, 0x5D0B, 0x9BBB, 0x5D15, 0x9BBC, 0x5D17, 0x9BBD, 0x5D5C, 0x9BBE, 0x5D1F, 0x9BBF, 0x5D1B, 0x9BC0, 0x5D11, + 0x9BC1, 0x5D14, 0x9BC2, 0x5D22, 0x9BC3, 0x5D1A, 0x9BC4, 0x5D19, 0x9BC5, 0x5D18, 0x9BC6, 0x5D4C, 0x9BC7, 0x5D52, 0x9BC8, 0x5D4E, + 0x9BC9, 0x5D4B, 0x9BCA, 0x5D6C, 0x9BCB, 0x5D73, 0x9BCC, 0x5D76, 0x9BCD, 0x5D87, 0x9BCE, 0x5D84, 0x9BCF, 0x5D82, 0x9BD0, 0x5DA2, + 0x9BD1, 0x5D9D, 0x9BD2, 0x5DAC, 0x9BD3, 0x5DAE, 0x9BD4, 0x5DBD, 0x9BD5, 0x5D90, 0x9BD6, 0x5DB7, 0x9BD7, 0x5DBC, 0x9BD8, 0x5DC9, + 0x9BD9, 0x5DCD, 0x9BDA, 0x5DD3, 0x9BDB, 0x5DD2, 0x9BDC, 0x5DD6, 0x9BDD, 0x5DDB, 0x9BDE, 0x5DEB, 0x9BDF, 0x5DF2, 0x9BE0, 0x5DF5, + 0x9BE1, 0x5E0B, 0x9BE2, 0x5E1A, 0x9BE3, 0x5E19, 0x9BE4, 0x5E11, 0x9BE5, 0x5E1B, 0x9BE6, 0x5E36, 0x9BE7, 0x5E37, 0x9BE8, 0x5E44, + 0x9BE9, 0x5E43, 0x9BEA, 0x5E40, 0x9BEB, 0x5E4E, 0x9BEC, 0x5E57, 0x9BED, 0x5E54, 0x9BEE, 0x5E5F, 0x9BEF, 0x5E62, 0x9BF0, 0x5E64, + 0x9BF1, 0x5E47, 0x9BF2, 0x5E75, 0x9BF3, 0x5E76, 0x9BF4, 0x5E7A, 0x9BF5, 0x9EBC, 0x9BF6, 0x5E7F, 0x9BF7, 0x5EA0, 0x9BF8, 0x5EC1, + 0x9BF9, 0x5EC2, 0x9BFA, 0x5EC8, 0x9BFB, 0x5ED0, 0x9BFC, 0x5ECF, 0x9C40, 0x5ED6, 0x9C41, 0x5EE3, 0x9C42, 0x5EDD, 0x9C43, 0x5EDA, + 0x9C44, 0x5EDB, 0x9C45, 0x5EE2, 0x9C46, 0x5EE1, 0x9C47, 0x5EE8, 0x9C48, 0x5EE9, 0x9C49, 0x5EEC, 0x9C4A, 0x5EF1, 0x9C4B, 0x5EF3, + 0x9C4C, 0x5EF0, 0x9C4D, 0x5EF4, 0x9C4E, 0x5EF8, 0x9C4F, 0x5EFE, 0x9C50, 0x5F03, 0x9C51, 0x5F09, 0x9C52, 0x5F5D, 0x9C53, 0x5F5C, + 0x9C54, 0x5F0B, 0x9C55, 0x5F11, 0x9C56, 0x5F16, 0x9C57, 0x5F29, 0x9C58, 0x5F2D, 0x9C59, 0x5F38, 0x9C5A, 0x5F41, 0x9C5B, 0x5F48, + 0x9C5C, 0x5F4C, 0x9C5D, 0x5F4E, 0x9C5E, 0x5F2F, 0x9C5F, 0x5F51, 0x9C60, 0x5F56, 0x9C61, 0x5F57, 0x9C62, 0x5F59, 0x9C63, 0x5F61, + 0x9C64, 0x5F6D, 0x9C65, 0x5F73, 0x9C66, 0x5F77, 0x9C67, 0x5F83, 0x9C68, 0x5F82, 0x9C69, 0x5F7F, 0x9C6A, 0x5F8A, 0x9C6B, 0x5F88, + 0x9C6C, 0x5F91, 0x9C6D, 0x5F87, 0x9C6E, 0x5F9E, 0x9C6F, 0x5F99, 0x9C70, 0x5F98, 0x9C71, 0x5FA0, 0x9C72, 0x5FA8, 0x9C73, 0x5FAD, + 0x9C74, 0x5FBC, 0x9C75, 0x5FD6, 0x9C76, 0x5FFB, 0x9C77, 0x5FE4, 0x9C78, 0x5FF8, 0x9C79, 0x5FF1, 0x9C7A, 0x5FDD, 0x9C7B, 0x60B3, + 0x9C7C, 0x5FFF, 0x9C7D, 0x6021, 0x9C7E, 0x6060, 0x9C80, 0x6019, 0x9C81, 0x6010, 0x9C82, 0x6029, 0x9C83, 0x600E, 0x9C84, 0x6031, + 0x9C85, 0x601B, 0x9C86, 0x6015, 0x9C87, 0x602B, 0x9C88, 0x6026, 0x9C89, 0x600F, 0x9C8A, 0x603A, 0x9C8B, 0x605A, 0x9C8C, 0x6041, + 0x9C8D, 0x606A, 0x9C8E, 0x6077, 0x9C8F, 0x605F, 0x9C90, 0x604A, 0x9C91, 0x6046, 0x9C92, 0x604D, 0x9C93, 0x6063, 0x9C94, 0x6043, + 0x9C95, 0x6064, 0x9C96, 0x6042, 0x9C97, 0x606C, 0x9C98, 0x606B, 0x9C99, 0x6059, 0x9C9A, 0x6081, 0x9C9B, 0x608D, 0x9C9C, 0x60E7, + 0x9C9D, 0x6083, 0x9C9E, 0x609A, 0x9C9F, 0x6084, 0x9CA0, 0x609B, 0x9CA1, 0x6096, 0x9CA2, 0x6097, 0x9CA3, 0x6092, 0x9CA4, 0x60A7, + 0x9CA5, 0x608B, 0x9CA6, 0x60E1, 0x9CA7, 0x60B8, 0x9CA8, 0x60E0, 0x9CA9, 0x60D3, 0x9CAA, 0x60B4, 0x9CAB, 0x5FF0, 0x9CAC, 0x60BD, + 0x9CAD, 0x60C6, 0x9CAE, 0x60B5, 0x9CAF, 0x60D8, 0x9CB0, 0x614D, 0x9CB1, 0x6115, 0x9CB2, 0x6106, 0x9CB3, 0x60F6, 0x9CB4, 0x60F7, + 0x9CB5, 0x6100, 0x9CB6, 0x60F4, 0x9CB7, 0x60FA, 0x9CB8, 0x6103, 0x9CB9, 0x6121, 0x9CBA, 0x60FB, 0x9CBB, 0x60F1, 0x9CBC, 0x610D, + 0x9CBD, 0x610E, 0x9CBE, 0x6147, 0x9CBF, 0x613E, 0x9CC0, 0x6128, 0x9CC1, 0x6127, 0x9CC2, 0x614A, 0x9CC3, 0x613F, 0x9CC4, 0x613C, + 0x9CC5, 0x612C, 0x9CC6, 0x6134, 0x9CC7, 0x613D, 0x9CC8, 0x6142, 0x9CC9, 0x6144, 0x9CCA, 0x6173, 0x9CCB, 0x6177, 0x9CCC, 0x6158, + 0x9CCD, 0x6159, 0x9CCE, 0x615A, 0x9CCF, 0x616B, 0x9CD0, 0x6174, 0x9CD1, 0x616F, 0x9CD2, 0x6165, 0x9CD3, 0x6171, 0x9CD4, 0x615F, + 0x9CD5, 0x615D, 0x9CD6, 0x6153, 0x9CD7, 0x6175, 0x9CD8, 0x6199, 0x9CD9, 0x6196, 0x9CDA, 0x6187, 0x9CDB, 0x61AC, 0x9CDC, 0x6194, + 0x9CDD, 0x619A, 0x9CDE, 0x618A, 0x9CDF, 0x6191, 0x9CE0, 0x61AB, 0x9CE1, 0x61AE, 0x9CE2, 0x61CC, 0x9CE3, 0x61CA, 0x9CE4, 0x61C9, + 0x9CE5, 0x61F7, 0x9CE6, 0x61C8, 0x9CE7, 0x61C3, 0x9CE8, 0x61C6, 0x9CE9, 0x61BA, 0x9CEA, 0x61CB, 0x9CEB, 0x7F79, 0x9CEC, 0x61CD, + 0x9CED, 0x61E6, 0x9CEE, 0x61E3, 0x9CEF, 0x61F6, 0x9CF0, 0x61FA, 0x9CF1, 0x61F4, 0x9CF2, 0x61FF, 0x9CF3, 0x61FD, 0x9CF4, 0x61FC, + 0x9CF5, 0x61FE, 0x9CF6, 0x6200, 0x9CF7, 0x6208, 0x9CF8, 0x6209, 0x9CF9, 0x620D, 0x9CFA, 0x620C, 0x9CFB, 0x6214, 0x9CFC, 0x621B, + 0x9D40, 0x621E, 0x9D41, 0x6221, 0x9D42, 0x622A, 0x9D43, 0x622E, 0x9D44, 0x6230, 0x9D45, 0x6232, 0x9D46, 0x6233, 0x9D47, 0x6241, + 0x9D48, 0x624E, 0x9D49, 0x625E, 0x9D4A, 0x6263, 0x9D4B, 0x625B, 0x9D4C, 0x6260, 0x9D4D, 0x6268, 0x9D4E, 0x627C, 0x9D4F, 0x6282, + 0x9D50, 0x6289, 0x9D51, 0x627E, 0x9D52, 0x6292, 0x9D53, 0x6293, 0x9D54, 0x6296, 0x9D55, 0x62D4, 0x9D56, 0x6283, 0x9D57, 0x6294, + 0x9D58, 0x62D7, 0x9D59, 0x62D1, 0x9D5A, 0x62BB, 0x9D5B, 0x62CF, 0x9D5C, 0x62FF, 0x9D5D, 0x62C6, 0x9D5E, 0x64D4, 0x9D5F, 0x62C8, + 0x9D60, 0x62DC, 0x9D61, 0x62CC, 0x9D62, 0x62CA, 0x9D63, 0x62C2, 0x9D64, 0x62C7, 0x9D65, 0x629B, 0x9D66, 0x62C9, 0x9D67, 0x630C, + 0x9D68, 0x62EE, 0x9D69, 0x62F1, 0x9D6A, 0x6327, 0x9D6B, 0x6302, 0x9D6C, 0x6308, 0x9D6D, 0x62EF, 0x9D6E, 0x62F5, 0x9D6F, 0x6350, + 0x9D70, 0x633E, 0x9D71, 0x634D, 0x9D72, 0x641C, 0x9D73, 0x634F, 0x9D74, 0x6396, 0x9D75, 0x638E, 0x9D76, 0x6380, 0x9D77, 0x63AB, + 0x9D78, 0x6376, 0x9D79, 0x63A3, 0x9D7A, 0x638F, 0x9D7B, 0x6389, 0x9D7C, 0x639F, 0x9D7D, 0x63B5, 0x9D7E, 0x636B, 0x9D80, 0x6369, + 0x9D81, 0x63BE, 0x9D82, 0x63E9, 0x9D83, 0x63C0, 0x9D84, 0x63C6, 0x9D85, 0x63E3, 0x9D86, 0x63C9, 0x9D87, 0x63D2, 0x9D88, 0x63F6, + 0x9D89, 0x63C4, 0x9D8A, 0x6416, 0x9D8B, 0x6434, 0x9D8C, 0x6406, 0x9D8D, 0x6413, 0x9D8E, 0x6426, 0x9D8F, 0x6436, 0x9D90, 0x651D, + 0x9D91, 0x6417, 0x9D92, 0x6428, 0x9D93, 0x640F, 0x9D94, 0x6467, 0x9D95, 0x646F, 0x9D96, 0x6476, 0x9D97, 0x644E, 0x9D98, 0x652A, + 0x9D99, 0x6495, 0x9D9A, 0x6493, 0x9D9B, 0x64A5, 0x9D9C, 0x64A9, 0x9D9D, 0x6488, 0x9D9E, 0x64BC, 0x9D9F, 0x64DA, 0x9DA0, 0x64D2, + 0x9DA1, 0x64C5, 0x9DA2, 0x64C7, 0x9DA3, 0x64BB, 0x9DA4, 0x64D8, 0x9DA5, 0x64C2, 0x9DA6, 0x64F1, 0x9DA7, 0x64E7, 0x9DA8, 0x8209, + 0x9DA9, 0x64E0, 0x9DAA, 0x64E1, 0x9DAB, 0x62AC, 0x9DAC, 0x64E3, 0x9DAD, 0x64EF, 0x9DAE, 0x652C, 0x9DAF, 0x64F6, 0x9DB0, 0x64F4, + 0x9DB1, 0x64F2, 0x9DB2, 0x64FA, 0x9DB3, 0x6500, 0x9DB4, 0x64FD, 0x9DB5, 0x6518, 0x9DB6, 0x651C, 0x9DB7, 0x6505, 0x9DB8, 0x6524, + 0x9DB9, 0x6523, 0x9DBA, 0x652B, 0x9DBB, 0x6534, 0x9DBC, 0x6535, 0x9DBD, 0x6537, 0x9DBE, 0x6536, 0x9DBF, 0x6538, 0x9DC0, 0x754B, + 0x9DC1, 0x6548, 0x9DC2, 0x6556, 0x9DC3, 0x6555, 0x9DC4, 0x654D, 0x9DC5, 0x6558, 0x9DC6, 0x655E, 0x9DC7, 0x655D, 0x9DC8, 0x6572, + 0x9DC9, 0x6578, 0x9DCA, 0x6582, 0x9DCB, 0x6583, 0x9DCC, 0x8B8A, 0x9DCD, 0x659B, 0x9DCE, 0x659F, 0x9DCF, 0x65AB, 0x9DD0, 0x65B7, + 0x9DD1, 0x65C3, 0x9DD2, 0x65C6, 0x9DD3, 0x65C1, 0x9DD4, 0x65C4, 0x9DD5, 0x65CC, 0x9DD6, 0x65D2, 0x9DD7, 0x65DB, 0x9DD8, 0x65D9, + 0x9DD9, 0x65E0, 0x9DDA, 0x65E1, 0x9DDB, 0x65F1, 0x9DDC, 0x6772, 0x9DDD, 0x660A, 0x9DDE, 0x6603, 0x9DDF, 0x65FB, 0x9DE0, 0x6773, + 0x9DE1, 0x6635, 0x9DE2, 0x6636, 0x9DE3, 0x6634, 0x9DE4, 0x661C, 0x9DE5, 0x664F, 0x9DE6, 0x6644, 0x9DE7, 0x6649, 0x9DE8, 0x6641, + 0x9DE9, 0x665E, 0x9DEA, 0x665D, 0x9DEB, 0x6664, 0x9DEC, 0x6667, 0x9DED, 0x6668, 0x9DEE, 0x665F, 0x9DEF, 0x6662, 0x9DF0, 0x6670, + 0x9DF1, 0x6683, 0x9DF2, 0x6688, 0x9DF3, 0x668E, 0x9DF4, 0x6689, 0x9DF5, 0x6684, 0x9DF6, 0x6698, 0x9DF7, 0x669D, 0x9DF8, 0x66C1, + 0x9DF9, 0x66B9, 0x9DFA, 0x66C9, 0x9DFB, 0x66BE, 0x9DFC, 0x66BC, 0x9E40, 0x66C4, 0x9E41, 0x66B8, 0x9E42, 0x66D6, 0x9E43, 0x66DA, + 0x9E44, 0x66E0, 0x9E45, 0x663F, 0x9E46, 0x66E6, 0x9E47, 0x66E9, 0x9E48, 0x66F0, 0x9E49, 0x66F5, 0x9E4A, 0x66F7, 0x9E4B, 0x670F, + 0x9E4C, 0x6716, 0x9E4D, 0x671E, 0x9E4E, 0x6726, 0x9E4F, 0x6727, 0x9E50, 0x9738, 0x9E51, 0x672E, 0x9E52, 0x673F, 0x9E53, 0x6736, + 0x9E54, 0x6741, 0x9E55, 0x6738, 0x9E56, 0x6737, 0x9E57, 0x6746, 0x9E58, 0x675E, 0x9E59, 0x6760, 0x9E5A, 0x6759, 0x9E5B, 0x6763, + 0x9E5C, 0x6764, 0x9E5D, 0x6789, 0x9E5E, 0x6770, 0x9E5F, 0x67A9, 0x9E60, 0x677C, 0x9E61, 0x676A, 0x9E62, 0x678C, 0x9E63, 0x678B, + 0x9E64, 0x67A6, 0x9E65, 0x67A1, 0x9E66, 0x6785, 0x9E67, 0x67B7, 0x9E68, 0x67EF, 0x9E69, 0x67B4, 0x9E6A, 0x67EC, 0x9E6B, 0x67B3, + 0x9E6C, 0x67E9, 0x9E6D, 0x67B8, 0x9E6E, 0x67E4, 0x9E6F, 0x67DE, 0x9E70, 0x67DD, 0x9E71, 0x67E2, 0x9E72, 0x67EE, 0x9E73, 0x67B9, + 0x9E74, 0x67CE, 0x9E75, 0x67C6, 0x9E76, 0x67E7, 0x9E77, 0x6A9C, 0x9E78, 0x681E, 0x9E79, 0x6846, 0x9E7A, 0x6829, 0x9E7B, 0x6840, + 0x9E7C, 0x684D, 0x9E7D, 0x6832, 0x9E7E, 0x684E, 0x9E80, 0x68B3, 0x9E81, 0x682B, 0x9E82, 0x6859, 0x9E83, 0x6863, 0x9E84, 0x6877, + 0x9E85, 0x687F, 0x9E86, 0x689F, 0x9E87, 0x688F, 0x9E88, 0x68AD, 0x9E89, 0x6894, 0x9E8A, 0x689D, 0x9E8B, 0x689B, 0x9E8C, 0x6883, + 0x9E8D, 0x6AAE, 0x9E8E, 0x68B9, 0x9E8F, 0x6874, 0x9E90, 0x68B5, 0x9E91, 0x68A0, 0x9E92, 0x68BA, 0x9E93, 0x690F, 0x9E94, 0x688D, + 0x9E95, 0x687E, 0x9E96, 0x6901, 0x9E97, 0x68CA, 0x9E98, 0x6908, 0x9E99, 0x68D8, 0x9E9A, 0x6922, 0x9E9B, 0x6926, 0x9E9C, 0x68E1, + 0x9E9D, 0x690C, 0x9E9E, 0x68CD, 0x9E9F, 0x68D4, 0x9EA0, 0x68E7, 0x9EA1, 0x68D5, 0x9EA2, 0x6936, 0x9EA3, 0x6912, 0x9EA4, 0x6904, + 0x9EA5, 0x68D7, 0x9EA6, 0x68E3, 0x9EA7, 0x6925, 0x9EA8, 0x68F9, 0x9EA9, 0x68E0, 0x9EAA, 0x68EF, 0x9EAB, 0x6928, 0x9EAC, 0x692A, + 0x9EAD, 0x691A, 0x9EAE, 0x6923, 0x9EAF, 0x6921, 0x9EB0, 0x68C6, 0x9EB1, 0x6979, 0x9EB2, 0x6977, 0x9EB3, 0x695C, 0x9EB4, 0x6978, + 0x9EB5, 0x696B, 0x9EB6, 0x6954, 0x9EB7, 0x697E, 0x9EB8, 0x696E, 0x9EB9, 0x6939, 0x9EBA, 0x6974, 0x9EBB, 0x693D, 0x9EBC, 0x6959, + 0x9EBD, 0x6930, 0x9EBE, 0x6961, 0x9EBF, 0x695E, 0x9EC0, 0x695D, 0x9EC1, 0x6981, 0x9EC2, 0x696A, 0x9EC3, 0x69B2, 0x9EC4, 0x69AE, + 0x9EC5, 0x69D0, 0x9EC6, 0x69BF, 0x9EC7, 0x69C1, 0x9EC8, 0x69D3, 0x9EC9, 0x69BE, 0x9ECA, 0x69CE, 0x9ECB, 0x5BE8, 0x9ECC, 0x69CA, + 0x9ECD, 0x69DD, 0x9ECE, 0x69BB, 0x9ECF, 0x69C3, 0x9ED0, 0x69A7, 0x9ED1, 0x6A2E, 0x9ED2, 0x6991, 0x9ED3, 0x69A0, 0x9ED4, 0x699C, + 0x9ED5, 0x6995, 0x9ED6, 0x69B4, 0x9ED7, 0x69DE, 0x9ED8, 0x69E8, 0x9ED9, 0x6A02, 0x9EDA, 0x6A1B, 0x9EDB, 0x69FF, 0x9EDC, 0x6B0A, + 0x9EDD, 0x69F9, 0x9EDE, 0x69F2, 0x9EDF, 0x69E7, 0x9EE0, 0x6A05, 0x9EE1, 0x69B1, 0x9EE2, 0x6A1E, 0x9EE3, 0x69ED, 0x9EE4, 0x6A14, + 0x9EE5, 0x69EB, 0x9EE6, 0x6A0A, 0x9EE7, 0x6A12, 0x9EE8, 0x6AC1, 0x9EE9, 0x6A23, 0x9EEA, 0x6A13, 0x9EEB, 0x6A44, 0x9EEC, 0x6A0C, + 0x9EED, 0x6A72, 0x9EEE, 0x6A36, 0x9EEF, 0x6A78, 0x9EF0, 0x6A47, 0x9EF1, 0x6A62, 0x9EF2, 0x6A59, 0x9EF3, 0x6A66, 0x9EF4, 0x6A48, + 0x9EF5, 0x6A38, 0x9EF6, 0x6A22, 0x9EF7, 0x6A90, 0x9EF8, 0x6A8D, 0x9EF9, 0x6AA0, 0x9EFA, 0x6A84, 0x9EFB, 0x6AA2, 0x9EFC, 0x6AA3, + 0x9F40, 0x6A97, 0x9F41, 0x8617, 0x9F42, 0x6ABB, 0x9F43, 0x6AC3, 0x9F44, 0x6AC2, 0x9F45, 0x6AB8, 0x9F46, 0x6AB3, 0x9F47, 0x6AAC, + 0x9F48, 0x6ADE, 0x9F49, 0x6AD1, 0x9F4A, 0x6ADF, 0x9F4B, 0x6AAA, 0x9F4C, 0x6ADA, 0x9F4D, 0x6AEA, 0x9F4E, 0x6AFB, 0x9F4F, 0x6B05, + 0x9F50, 0x8616, 0x9F51, 0x6AFA, 0x9F52, 0x6B12, 0x9F53, 0x6B16, 0x9F54, 0x9B31, 0x9F55, 0x6B1F, 0x9F56, 0x6B38, 0x9F57, 0x6B37, + 0x9F58, 0x76DC, 0x9F59, 0x6B39, 0x9F5A, 0x98EE, 0x9F5B, 0x6B47, 0x9F5C, 0x6B43, 0x9F5D, 0x6B49, 0x9F5E, 0x6B50, 0x9F5F, 0x6B59, + 0x9F60, 0x6B54, 0x9F61, 0x6B5B, 0x9F62, 0x6B5F, 0x9F63, 0x6B61, 0x9F64, 0x6B78, 0x9F65, 0x6B79, 0x9F66, 0x6B7F, 0x9F67, 0x6B80, + 0x9F68, 0x6B84, 0x9F69, 0x6B83, 0x9F6A, 0x6B8D, 0x9F6B, 0x6B98, 0x9F6C, 0x6B95, 0x9F6D, 0x6B9E, 0x9F6E, 0x6BA4, 0x9F6F, 0x6BAA, + 0x9F70, 0x6BAB, 0x9F71, 0x6BAF, 0x9F72, 0x6BB2, 0x9F73, 0x6BB1, 0x9F74, 0x6BB3, 0x9F75, 0x6BB7, 0x9F76, 0x6BBC, 0x9F77, 0x6BC6, + 0x9F78, 0x6BCB, 0x9F79, 0x6BD3, 0x9F7A, 0x6BDF, 0x9F7B, 0x6BEC, 0x9F7C, 0x6BEB, 0x9F7D, 0x6BF3, 0x9F7E, 0x6BEF, 0x9F80, 0x9EBE, + 0x9F81, 0x6C08, 0x9F82, 0x6C13, 0x9F83, 0x6C14, 0x9F84, 0x6C1B, 0x9F85, 0x6C24, 0x9F86, 0x6C23, 0x9F87, 0x6C5E, 0x9F88, 0x6C55, + 0x9F89, 0x6C62, 0x9F8A, 0x6C6A, 0x9F8B, 0x6C82, 0x9F8C, 0x6C8D, 0x9F8D, 0x6C9A, 0x9F8E, 0x6C81, 0x9F8F, 0x6C9B, 0x9F90, 0x6C7E, + 0x9F91, 0x6C68, 0x9F92, 0x6C73, 0x9F93, 0x6C92, 0x9F94, 0x6C90, 0x9F95, 0x6CC4, 0x9F96, 0x6CF1, 0x9F97, 0x6CD3, 0x9F98, 0x6CBD, + 0x9F99, 0x6CD7, 0x9F9A, 0x6CC5, 0x9F9B, 0x6CDD, 0x9F9C, 0x6CAE, 0x9F9D, 0x6CB1, 0x9F9E, 0x6CBE, 0x9F9F, 0x6CBA, 0x9FA0, 0x6CDB, + 0x9FA1, 0x6CEF, 0x9FA2, 0x6CD9, 0x9FA3, 0x6CEA, 0x9FA4, 0x6D1F, 0x9FA5, 0x884D, 0x9FA6, 0x6D36, 0x9FA7, 0x6D2B, 0x9FA8, 0x6D3D, + 0x9FA9, 0x6D38, 0x9FAA, 0x6D19, 0x9FAB, 0x6D35, 0x9FAC, 0x6D33, 0x9FAD, 0x6D12, 0x9FAE, 0x6D0C, 0x9FAF, 0x6D63, 0x9FB0, 0x6D93, + 0x9FB1, 0x6D64, 0x9FB2, 0x6D5A, 0x9FB3, 0x6D79, 0x9FB4, 0x6D59, 0x9FB5, 0x6D8E, 0x9FB6, 0x6D95, 0x9FB7, 0x6FE4, 0x9FB8, 0x6D85, + 0x9FB9, 0x6DF9, 0x9FBA, 0x6E15, 0x9FBB, 0x6E0A, 0x9FBC, 0x6DB5, 0x9FBD, 0x6DC7, 0x9FBE, 0x6DE6, 0x9FBF, 0x6DB8, 0x9FC0, 0x6DC6, + 0x9FC1, 0x6DEC, 0x9FC2, 0x6DDE, 0x9FC3, 0x6DCC, 0x9FC4, 0x6DE8, 0x9FC5, 0x6DD2, 0x9FC6, 0x6DC5, 0x9FC7, 0x6DFA, 0x9FC8, 0x6DD9, + 0x9FC9, 0x6DE4, 0x9FCA, 0x6DD5, 0x9FCB, 0x6DEA, 0x9FCC, 0x6DEE, 0x9FCD, 0x6E2D, 0x9FCE, 0x6E6E, 0x9FCF, 0x6E2E, 0x9FD0, 0x6E19, + 0x9FD1, 0x6E72, 0x9FD2, 0x6E5F, 0x9FD3, 0x6E3E, 0x9FD4, 0x6E23, 0x9FD5, 0x6E6B, 0x9FD6, 0x6E2B, 0x9FD7, 0x6E76, 0x9FD8, 0x6E4D, + 0x9FD9, 0x6E1F, 0x9FDA, 0x6E43, 0x9FDB, 0x6E3A, 0x9FDC, 0x6E4E, 0x9FDD, 0x6E24, 0x9FDE, 0x6EFF, 0x9FDF, 0x6E1D, 0x9FE0, 0x6E38, + 0x9FE1, 0x6E82, 0x9FE2, 0x6EAA, 0x9FE3, 0x6E98, 0x9FE4, 0x6EC9, 0x9FE5, 0x6EB7, 0x9FE6, 0x6ED3, 0x9FE7, 0x6EBD, 0x9FE8, 0x6EAF, + 0x9FE9, 0x6EC4, 0x9FEA, 0x6EB2, 0x9FEB, 0x6ED4, 0x9FEC, 0x6ED5, 0x9FED, 0x6E8F, 0x9FEE, 0x6EA5, 0x9FEF, 0x6EC2, 0x9FF0, 0x6E9F, + 0x9FF1, 0x6F41, 0x9FF2, 0x6F11, 0x9FF3, 0x704C, 0x9FF4, 0x6EEC, 0x9FF5, 0x6EF8, 0x9FF6, 0x6EFE, 0x9FF7, 0x6F3F, 0x9FF8, 0x6EF2, + 0x9FF9, 0x6F31, 0x9FFA, 0x6EEF, 0x9FFB, 0x6F32, 0x9FFC, 0x6ECC, 0xE040, 0x6F3E, 0xE041, 0x6F13, 0xE042, 0x6EF7, 0xE043, 0x6F86, + 0xE044, 0x6F7A, 0xE045, 0x6F78, 0xE046, 0x6F81, 0xE047, 0x6F80, 0xE048, 0x6F6F, 0xE049, 0x6F5B, 0xE04A, 0x6FF3, 0xE04B, 0x6F6D, + 0xE04C, 0x6F82, 0xE04D, 0x6F7C, 0xE04E, 0x6F58, 0xE04F, 0x6F8E, 0xE050, 0x6F91, 0xE051, 0x6FC2, 0xE052, 0x6F66, 0xE053, 0x6FB3, + 0xE054, 0x6FA3, 0xE055, 0x6FA1, 0xE056, 0x6FA4, 0xE057, 0x6FB9, 0xE058, 0x6FC6, 0xE059, 0x6FAA, 0xE05A, 0x6FDF, 0xE05B, 0x6FD5, + 0xE05C, 0x6FEC, 0xE05D, 0x6FD4, 0xE05E, 0x6FD8, 0xE05F, 0x6FF1, 0xE060, 0x6FEE, 0xE061, 0x6FDB, 0xE062, 0x7009, 0xE063, 0x700B, + 0xE064, 0x6FFA, 0xE065, 0x7011, 0xE066, 0x7001, 0xE067, 0x700F, 0xE068, 0x6FFE, 0xE069, 0x701B, 0xE06A, 0x701A, 0xE06B, 0x6F74, + 0xE06C, 0x701D, 0xE06D, 0x7018, 0xE06E, 0x701F, 0xE06F, 0x7030, 0xE070, 0x703E, 0xE071, 0x7032, 0xE072, 0x7051, 0xE073, 0x7063, + 0xE074, 0x7099, 0xE075, 0x7092, 0xE076, 0x70AF, 0xE077, 0x70F1, 0xE078, 0x70AC, 0xE079, 0x70B8, 0xE07A, 0x70B3, 0xE07B, 0x70AE, + 0xE07C, 0x70DF, 0xE07D, 0x70CB, 0xE07E, 0x70DD, 0xE080, 0x70D9, 0xE081, 0x7109, 0xE082, 0x70FD, 0xE083, 0x711C, 0xE084, 0x7119, + 0xE085, 0x7165, 0xE086, 0x7155, 0xE087, 0x7188, 0xE088, 0x7166, 0xE089, 0x7162, 0xE08A, 0x714C, 0xE08B, 0x7156, 0xE08C, 0x716C, + 0xE08D, 0x718F, 0xE08E, 0x71FB, 0xE08F, 0x7184, 0xE090, 0x7195, 0xE091, 0x71A8, 0xE092, 0x71AC, 0xE093, 0x71D7, 0xE094, 0x71B9, + 0xE095, 0x71BE, 0xE096, 0x71D2, 0xE097, 0x71C9, 0xE098, 0x71D4, 0xE099, 0x71CE, 0xE09A, 0x71E0, 0xE09B, 0x71EC, 0xE09C, 0x71E7, + 0xE09D, 0x71F5, 0xE09E, 0x71FC, 0xE09F, 0x71F9, 0xE0A0, 0x71FF, 0xE0A1, 0x720D, 0xE0A2, 0x7210, 0xE0A3, 0x721B, 0xE0A4, 0x7228, + 0xE0A5, 0x722D, 0xE0A6, 0x722C, 0xE0A7, 0x7230, 0xE0A8, 0x7232, 0xE0A9, 0x723B, 0xE0AA, 0x723C, 0xE0AB, 0x723F, 0xE0AC, 0x7240, + 0xE0AD, 0x7246, 0xE0AE, 0x724B, 0xE0AF, 0x7258, 0xE0B0, 0x7274, 0xE0B1, 0x727E, 0xE0B2, 0x7282, 0xE0B3, 0x7281, 0xE0B4, 0x7287, + 0xE0B5, 0x7292, 0xE0B6, 0x7296, 0xE0B7, 0x72A2, 0xE0B8, 0x72A7, 0xE0B9, 0x72B9, 0xE0BA, 0x72B2, 0xE0BB, 0x72C3, 0xE0BC, 0x72C6, + 0xE0BD, 0x72C4, 0xE0BE, 0x72CE, 0xE0BF, 0x72D2, 0xE0C0, 0x72E2, 0xE0C1, 0x72E0, 0xE0C2, 0x72E1, 0xE0C3, 0x72F9, 0xE0C4, 0x72F7, + 0xE0C5, 0x500F, 0xE0C6, 0x7317, 0xE0C7, 0x730A, 0xE0C8, 0x731C, 0xE0C9, 0x7316, 0xE0CA, 0x731D, 0xE0CB, 0x7334, 0xE0CC, 0x732F, + 0xE0CD, 0x7329, 0xE0CE, 0x7325, 0xE0CF, 0x733E, 0xE0D0, 0x734E, 0xE0D1, 0x734F, 0xE0D2, 0x9ED8, 0xE0D3, 0x7357, 0xE0D4, 0x736A, + 0xE0D5, 0x7368, 0xE0D6, 0x7370, 0xE0D7, 0x7378, 0xE0D8, 0x7375, 0xE0D9, 0x737B, 0xE0DA, 0x737A, 0xE0DB, 0x73C8, 0xE0DC, 0x73B3, + 0xE0DD, 0x73CE, 0xE0DE, 0x73BB, 0xE0DF, 0x73C0, 0xE0E0, 0x73E5, 0xE0E1, 0x73EE, 0xE0E2, 0x73DE, 0xE0E3, 0x74A2, 0xE0E4, 0x7405, + 0xE0E5, 0x746F, 0xE0E6, 0x7425, 0xE0E7, 0x73F8, 0xE0E8, 0x7432, 0xE0E9, 0x743A, 0xE0EA, 0x7455, 0xE0EB, 0x743F, 0xE0EC, 0x745F, + 0xE0ED, 0x7459, 0xE0EE, 0x7441, 0xE0EF, 0x745C, 0xE0F0, 0x7469, 0xE0F1, 0x7470, 0xE0F2, 0x7463, 0xE0F3, 0x746A, 0xE0F4, 0x7476, + 0xE0F5, 0x747E, 0xE0F6, 0x748B, 0xE0F7, 0x749E, 0xE0F8, 0x74A7, 0xE0F9, 0x74CA, 0xE0FA, 0x74CF, 0xE0FB, 0x74D4, 0xE0FC, 0x73F1, + 0xE140, 0x74E0, 0xE141, 0x74E3, 0xE142, 0x74E7, 0xE143, 0x74E9, 0xE144, 0x74EE, 0xE145, 0x74F2, 0xE146, 0x74F0, 0xE147, 0x74F1, + 0xE148, 0x74F8, 0xE149, 0x74F7, 0xE14A, 0x7504, 0xE14B, 0x7503, 0xE14C, 0x7505, 0xE14D, 0x750C, 0xE14E, 0x750E, 0xE14F, 0x750D, + 0xE150, 0x7515, 0xE151, 0x7513, 0xE152, 0x751E, 0xE153, 0x7526, 0xE154, 0x752C, 0xE155, 0x753C, 0xE156, 0x7544, 0xE157, 0x754D, + 0xE158, 0x754A, 0xE159, 0x7549, 0xE15A, 0x755B, 0xE15B, 0x7546, 0xE15C, 0x755A, 0xE15D, 0x7569, 0xE15E, 0x7564, 0xE15F, 0x7567, + 0xE160, 0x756B, 0xE161, 0x756D, 0xE162, 0x7578, 0xE163, 0x7576, 0xE164, 0x7586, 0xE165, 0x7587, 0xE166, 0x7574, 0xE167, 0x758A, + 0xE168, 0x7589, 0xE169, 0x7582, 0xE16A, 0x7594, 0xE16B, 0x759A, 0xE16C, 0x759D, 0xE16D, 0x75A5, 0xE16E, 0x75A3, 0xE16F, 0x75C2, + 0xE170, 0x75B3, 0xE171, 0x75C3, 0xE172, 0x75B5, 0xE173, 0x75BD, 0xE174, 0x75B8, 0xE175, 0x75BC, 0xE176, 0x75B1, 0xE177, 0x75CD, + 0xE178, 0x75CA, 0xE179, 0x75D2, 0xE17A, 0x75D9, 0xE17B, 0x75E3, 0xE17C, 0x75DE, 0xE17D, 0x75FE, 0xE17E, 0x75FF, 0xE180, 0x75FC, + 0xE181, 0x7601, 0xE182, 0x75F0, 0xE183, 0x75FA, 0xE184, 0x75F2, 0xE185, 0x75F3, 0xE186, 0x760B, 0xE187, 0x760D, 0xE188, 0x7609, + 0xE189, 0x761F, 0xE18A, 0x7627, 0xE18B, 0x7620, 0xE18C, 0x7621, 0xE18D, 0x7622, 0xE18E, 0x7624, 0xE18F, 0x7634, 0xE190, 0x7630, + 0xE191, 0x763B, 0xE192, 0x7647, 0xE193, 0x7648, 0xE194, 0x7646, 0xE195, 0x765C, 0xE196, 0x7658, 0xE197, 0x7661, 0xE198, 0x7662, + 0xE199, 0x7668, 0xE19A, 0x7669, 0xE19B, 0x766A, 0xE19C, 0x7667, 0xE19D, 0x766C, 0xE19E, 0x7670, 0xE19F, 0x7672, 0xE1A0, 0x7676, + 0xE1A1, 0x7678, 0xE1A2, 0x767C, 0xE1A3, 0x7680, 0xE1A4, 0x7683, 0xE1A5, 0x7688, 0xE1A6, 0x768B, 0xE1A7, 0x768E, 0xE1A8, 0x7696, + 0xE1A9, 0x7693, 0xE1AA, 0x7699, 0xE1AB, 0x769A, 0xE1AC, 0x76B0, 0xE1AD, 0x76B4, 0xE1AE, 0x76B8, 0xE1AF, 0x76B9, 0xE1B0, 0x76BA, + 0xE1B1, 0x76C2, 0xE1B2, 0x76CD, 0xE1B3, 0x76D6, 0xE1B4, 0x76D2, 0xE1B5, 0x76DE, 0xE1B6, 0x76E1, 0xE1B7, 0x76E5, 0xE1B8, 0x76E7, + 0xE1B9, 0x76EA, 0xE1BA, 0x862F, 0xE1BB, 0x76FB, 0xE1BC, 0x7708, 0xE1BD, 0x7707, 0xE1BE, 0x7704, 0xE1BF, 0x7729, 0xE1C0, 0x7724, + 0xE1C1, 0x771E, 0xE1C2, 0x7725, 0xE1C3, 0x7726, 0xE1C4, 0x771B, 0xE1C5, 0x7737, 0xE1C6, 0x7738, 0xE1C7, 0x7747, 0xE1C8, 0x775A, + 0xE1C9, 0x7768, 0xE1CA, 0x776B, 0xE1CB, 0x775B, 0xE1CC, 0x7765, 0xE1CD, 0x777F, 0xE1CE, 0x777E, 0xE1CF, 0x7779, 0xE1D0, 0x778E, + 0xE1D1, 0x778B, 0xE1D2, 0x7791, 0xE1D3, 0x77A0, 0xE1D4, 0x779E, 0xE1D5, 0x77B0, 0xE1D6, 0x77B6, 0xE1D7, 0x77B9, 0xE1D8, 0x77BF, + 0xE1D9, 0x77BC, 0xE1DA, 0x77BD, 0xE1DB, 0x77BB, 0xE1DC, 0x77C7, 0xE1DD, 0x77CD, 0xE1DE, 0x77D7, 0xE1DF, 0x77DA, 0xE1E0, 0x77DC, + 0xE1E1, 0x77E3, 0xE1E2, 0x77EE, 0xE1E3, 0x77FC, 0xE1E4, 0x780C, 0xE1E5, 0x7812, 0xE1E6, 0x7926, 0xE1E7, 0x7820, 0xE1E8, 0x792A, + 0xE1E9, 0x7845, 0xE1EA, 0x788E, 0xE1EB, 0x7874, 0xE1EC, 0x7886, 0xE1ED, 0x787C, 0xE1EE, 0x789A, 0xE1EF, 0x788C, 0xE1F0, 0x78A3, + 0xE1F1, 0x78B5, 0xE1F2, 0x78AA, 0xE1F3, 0x78AF, 0xE1F4, 0x78D1, 0xE1F5, 0x78C6, 0xE1F6, 0x78CB, 0xE1F7, 0x78D4, 0xE1F8, 0x78BE, + 0xE1F9, 0x78BC, 0xE1FA, 0x78C5, 0xE1FB, 0x78CA, 0xE1FC, 0x78EC, 0xE240, 0x78E7, 0xE241, 0x78DA, 0xE242, 0x78FD, 0xE243, 0x78F4, + 0xE244, 0x7907, 0xE245, 0x7912, 0xE246, 0x7911, 0xE247, 0x7919, 0xE248, 0x792C, 0xE249, 0x792B, 0xE24A, 0x7940, 0xE24B, 0x7960, + 0xE24C, 0x7957, 0xE24D, 0x795F, 0xE24E, 0x795A, 0xE24F, 0x7955, 0xE250, 0x7953, 0xE251, 0x797A, 0xE252, 0x797F, 0xE253, 0x798A, + 0xE254, 0x799D, 0xE255, 0x79A7, 0xE256, 0x9F4B, 0xE257, 0x79AA, 0xE258, 0x79AE, 0xE259, 0x79B3, 0xE25A, 0x79B9, 0xE25B, 0x79BA, + 0xE25C, 0x79C9, 0xE25D, 0x79D5, 0xE25E, 0x79E7, 0xE25F, 0x79EC, 0xE260, 0x79E1, 0xE261, 0x79E3, 0xE262, 0x7A08, 0xE263, 0x7A0D, + 0xE264, 0x7A18, 0xE265, 0x7A19, 0xE266, 0x7A20, 0xE267, 0x7A1F, 0xE268, 0x7980, 0xE269, 0x7A31, 0xE26A, 0x7A3B, 0xE26B, 0x7A3E, + 0xE26C, 0x7A37, 0xE26D, 0x7A43, 0xE26E, 0x7A57, 0xE26F, 0x7A49, 0xE270, 0x7A61, 0xE271, 0x7A62, 0xE272, 0x7A69, 0xE273, 0x9F9D, + 0xE274, 0x7A70, 0xE275, 0x7A79, 0xE276, 0x7A7D, 0xE277, 0x7A88, 0xE278, 0x7A97, 0xE279, 0x7A95, 0xE27A, 0x7A98, 0xE27B, 0x7A96, + 0xE27C, 0x7AA9, 0xE27D, 0x7AC8, 0xE27E, 0x7AB0, 0xE280, 0x7AB6, 0xE281, 0x7AC5, 0xE282, 0x7AC4, 0xE283, 0x7ABF, 0xE284, 0x9083, + 0xE285, 0x7AC7, 0xE286, 0x7ACA, 0xE287, 0x7ACD, 0xE288, 0x7ACF, 0xE289, 0x7AD5, 0xE28A, 0x7AD3, 0xE28B, 0x7AD9, 0xE28C, 0x7ADA, + 0xE28D, 0x7ADD, 0xE28E, 0x7AE1, 0xE28F, 0x7AE2, 0xE290, 0x7AE6, 0xE291, 0x7AED, 0xE292, 0x7AF0, 0xE293, 0x7B02, 0xE294, 0x7B0F, + 0xE295, 0x7B0A, 0xE296, 0x7B06, 0xE297, 0x7B33, 0xE298, 0x7B18, 0xE299, 0x7B19, 0xE29A, 0x7B1E, 0xE29B, 0x7B35, 0xE29C, 0x7B28, + 0xE29D, 0x7B36, 0xE29E, 0x7B50, 0xE29F, 0x7B7A, 0xE2A0, 0x7B04, 0xE2A1, 0x7B4D, 0xE2A2, 0x7B0B, 0xE2A3, 0x7B4C, 0xE2A4, 0x7B45, + 0xE2A5, 0x7B75, 0xE2A6, 0x7B65, 0xE2A7, 0x7B74, 0xE2A8, 0x7B67, 0xE2A9, 0x7B70, 0xE2AA, 0x7B71, 0xE2AB, 0x7B6C, 0xE2AC, 0x7B6E, + 0xE2AD, 0x7B9D, 0xE2AE, 0x7B98, 0xE2AF, 0x7B9F, 0xE2B0, 0x7B8D, 0xE2B1, 0x7B9C, 0xE2B2, 0x7B9A, 0xE2B3, 0x7B8B, 0xE2B4, 0x7B92, + 0xE2B5, 0x7B8F, 0xE2B6, 0x7B5D, 0xE2B7, 0x7B99, 0xE2B8, 0x7BCB, 0xE2B9, 0x7BC1, 0xE2BA, 0x7BCC, 0xE2BB, 0x7BCF, 0xE2BC, 0x7BB4, + 0xE2BD, 0x7BC6, 0xE2BE, 0x7BDD, 0xE2BF, 0x7BE9, 0xE2C0, 0x7C11, 0xE2C1, 0x7C14, 0xE2C2, 0x7BE6, 0xE2C3, 0x7BE5, 0xE2C4, 0x7C60, + 0xE2C5, 0x7C00, 0xE2C6, 0x7C07, 0xE2C7, 0x7C13, 0xE2C8, 0x7BF3, 0xE2C9, 0x7BF7, 0xE2CA, 0x7C17, 0xE2CB, 0x7C0D, 0xE2CC, 0x7BF6, + 0xE2CD, 0x7C23, 0xE2CE, 0x7C27, 0xE2CF, 0x7C2A, 0xE2D0, 0x7C1F, 0xE2D1, 0x7C37, 0xE2D2, 0x7C2B, 0xE2D3, 0x7C3D, 0xE2D4, 0x7C4C, + 0xE2D5, 0x7C43, 0xE2D6, 0x7C54, 0xE2D7, 0x7C4F, 0xE2D8, 0x7C40, 0xE2D9, 0x7C50, 0xE2DA, 0x7C58, 0xE2DB, 0x7C5F, 0xE2DC, 0x7C64, + 0xE2DD, 0x7C56, 0xE2DE, 0x7C65, 0xE2DF, 0x7C6C, 0xE2E0, 0x7C75, 0xE2E1, 0x7C83, 0xE2E2, 0x7C90, 0xE2E3, 0x7CA4, 0xE2E4, 0x7CAD, + 0xE2E5, 0x7CA2, 0xE2E6, 0x7CAB, 0xE2E7, 0x7CA1, 0xE2E8, 0x7CA8, 0xE2E9, 0x7CB3, 0xE2EA, 0x7CB2, 0xE2EB, 0x7CB1, 0xE2EC, 0x7CAE, + 0xE2ED, 0x7CB9, 0xE2EE, 0x7CBD, 0xE2EF, 0x7CC0, 0xE2F0, 0x7CC5, 0xE2F1, 0x7CC2, 0xE2F2, 0x7CD8, 0xE2F3, 0x7CD2, 0xE2F4, 0x7CDC, + 0xE2F5, 0x7CE2, 0xE2F6, 0x9B3B, 0xE2F7, 0x7CEF, 0xE2F8, 0x7CF2, 0xE2F9, 0x7CF4, 0xE2FA, 0x7CF6, 0xE2FB, 0x7CFA, 0xE2FC, 0x7D06, + 0xE340, 0x7D02, 0xE341, 0x7D1C, 0xE342, 0x7D15, 0xE343, 0x7D0A, 0xE344, 0x7D45, 0xE345, 0x7D4B, 0xE346, 0x7D2E, 0xE347, 0x7D32, + 0xE348, 0x7D3F, 0xE349, 0x7D35, 0xE34A, 0x7D46, 0xE34B, 0x7D73, 0xE34C, 0x7D56, 0xE34D, 0x7D4E, 0xE34E, 0x7D72, 0xE34F, 0x7D68, + 0xE350, 0x7D6E, 0xE351, 0x7D4F, 0xE352, 0x7D63, 0xE353, 0x7D93, 0xE354, 0x7D89, 0xE355, 0x7D5B, 0xE356, 0x7D8F, 0xE357, 0x7D7D, + 0xE358, 0x7D9B, 0xE359, 0x7DBA, 0xE35A, 0x7DAE, 0xE35B, 0x7DA3, 0xE35C, 0x7DB5, 0xE35D, 0x7DC7, 0xE35E, 0x7DBD, 0xE35F, 0x7DAB, + 0xE360, 0x7E3D, 0xE361, 0x7DA2, 0xE362, 0x7DAF, 0xE363, 0x7DDC, 0xE364, 0x7DB8, 0xE365, 0x7D9F, 0xE366, 0x7DB0, 0xE367, 0x7DD8, + 0xE368, 0x7DDD, 0xE369, 0x7DE4, 0xE36A, 0x7DDE, 0xE36B, 0x7DFB, 0xE36C, 0x7DF2, 0xE36D, 0x7DE1, 0xE36E, 0x7E05, 0xE36F, 0x7E0A, + 0xE370, 0x7E23, 0xE371, 0x7E21, 0xE372, 0x7E12, 0xE373, 0x7E31, 0xE374, 0x7E1F, 0xE375, 0x7E09, 0xE376, 0x7E0B, 0xE377, 0x7E22, + 0xE378, 0x7E46, 0xE379, 0x7E66, 0xE37A, 0x7E3B, 0xE37B, 0x7E35, 0xE37C, 0x7E39, 0xE37D, 0x7E43, 0xE37E, 0x7E37, 0xE380, 0x7E32, + 0xE381, 0x7E3A, 0xE382, 0x7E67, 0xE383, 0x7E5D, 0xE384, 0x7E56, 0xE385, 0x7E5E, 0xE386, 0x7E59, 0xE387, 0x7E5A, 0xE388, 0x7E79, + 0xE389, 0x7E6A, 0xE38A, 0x7E69, 0xE38B, 0x7E7C, 0xE38C, 0x7E7B, 0xE38D, 0x7E83, 0xE38E, 0x7DD5, 0xE38F, 0x7E7D, 0xE390, 0x8FAE, + 0xE391, 0x7E7F, 0xE392, 0x7E88, 0xE393, 0x7E89, 0xE394, 0x7E8C, 0xE395, 0x7E92, 0xE396, 0x7E90, 0xE397, 0x7E93, 0xE398, 0x7E94, + 0xE399, 0x7E96, 0xE39A, 0x7E8E, 0xE39B, 0x7E9B, 0xE39C, 0x7E9C, 0xE39D, 0x7F38, 0xE39E, 0x7F3A, 0xE39F, 0x7F45, 0xE3A0, 0x7F4C, + 0xE3A1, 0x7F4D, 0xE3A2, 0x7F4E, 0xE3A3, 0x7F50, 0xE3A4, 0x7F51, 0xE3A5, 0x7F55, 0xE3A6, 0x7F54, 0xE3A7, 0x7F58, 0xE3A8, 0x7F5F, + 0xE3A9, 0x7F60, 0xE3AA, 0x7F68, 0xE3AB, 0x7F69, 0xE3AC, 0x7F67, 0xE3AD, 0x7F78, 0xE3AE, 0x7F82, 0xE3AF, 0x7F86, 0xE3B0, 0x7F83, + 0xE3B1, 0x7F88, 0xE3B2, 0x7F87, 0xE3B3, 0x7F8C, 0xE3B4, 0x7F94, 0xE3B5, 0x7F9E, 0xE3B6, 0x7F9D, 0xE3B7, 0x7F9A, 0xE3B8, 0x7FA3, + 0xE3B9, 0x7FAF, 0xE3BA, 0x7FB2, 0xE3BB, 0x7FB9, 0xE3BC, 0x7FAE, 0xE3BD, 0x7FB6, 0xE3BE, 0x7FB8, 0xE3BF, 0x8B71, 0xE3C0, 0x7FC5, + 0xE3C1, 0x7FC6, 0xE3C2, 0x7FCA, 0xE3C3, 0x7FD5, 0xE3C4, 0x7FD4, 0xE3C5, 0x7FE1, 0xE3C6, 0x7FE6, 0xE3C7, 0x7FE9, 0xE3C8, 0x7FF3, + 0xE3C9, 0x7FF9, 0xE3CA, 0x98DC, 0xE3CB, 0x8006, 0xE3CC, 0x8004, 0xE3CD, 0x800B, 0xE3CE, 0x8012, 0xE3CF, 0x8018, 0xE3D0, 0x8019, + 0xE3D1, 0x801C, 0xE3D2, 0x8021, 0xE3D3, 0x8028, 0xE3D4, 0x803F, 0xE3D5, 0x803B, 0xE3D6, 0x804A, 0xE3D7, 0x8046, 0xE3D8, 0x8052, + 0xE3D9, 0x8058, 0xE3DA, 0x805A, 0xE3DB, 0x805F, 0xE3DC, 0x8062, 0xE3DD, 0x8068, 0xE3DE, 0x8073, 0xE3DF, 0x8072, 0xE3E0, 0x8070, + 0xE3E1, 0x8076, 0xE3E2, 0x8079, 0xE3E3, 0x807D, 0xE3E4, 0x807F, 0xE3E5, 0x8084, 0xE3E6, 0x8086, 0xE3E7, 0x8085, 0xE3E8, 0x809B, + 0xE3E9, 0x8093, 0xE3EA, 0x809A, 0xE3EB, 0x80AD, 0xE3EC, 0x5190, 0xE3ED, 0x80AC, 0xE3EE, 0x80DB, 0xE3EF, 0x80E5, 0xE3F0, 0x80D9, + 0xE3F1, 0x80DD, 0xE3F2, 0x80C4, 0xE3F3, 0x80DA, 0xE3F4, 0x80D6, 0xE3F5, 0x8109, 0xE3F6, 0x80EF, 0xE3F7, 0x80F1, 0xE3F8, 0x811B, + 0xE3F9, 0x8129, 0xE3FA, 0x8123, 0xE3FB, 0x812F, 0xE3FC, 0x814B, 0xE440, 0x968B, 0xE441, 0x8146, 0xE442, 0x813E, 0xE443, 0x8153, + 0xE444, 0x8151, 0xE445, 0x80FC, 0xE446, 0x8171, 0xE447, 0x816E, 0xE448, 0x8165, 0xE449, 0x8166, 0xE44A, 0x8174, 0xE44B, 0x8183, + 0xE44C, 0x8188, 0xE44D, 0x818A, 0xE44E, 0x8180, 0xE44F, 0x8182, 0xE450, 0x81A0, 0xE451, 0x8195, 0xE452, 0x81A4, 0xE453, 0x81A3, + 0xE454, 0x815F, 0xE455, 0x8193, 0xE456, 0x81A9, 0xE457, 0x81B0, 0xE458, 0x81B5, 0xE459, 0x81BE, 0xE45A, 0x81B8, 0xE45B, 0x81BD, + 0xE45C, 0x81C0, 0xE45D, 0x81C2, 0xE45E, 0x81BA, 0xE45F, 0x81C9, 0xE460, 0x81CD, 0xE461, 0x81D1, 0xE462, 0x81D9, 0xE463, 0x81D8, + 0xE464, 0x81C8, 0xE465, 0x81DA, 0xE466, 0x81DF, 0xE467, 0x81E0, 0xE468, 0x81E7, 0xE469, 0x81FA, 0xE46A, 0x81FB, 0xE46B, 0x81FE, + 0xE46C, 0x8201, 0xE46D, 0x8202, 0xE46E, 0x8205, 0xE46F, 0x8207, 0xE470, 0x820A, 0xE471, 0x820D, 0xE472, 0x8210, 0xE473, 0x8216, + 0xE474, 0x8229, 0xE475, 0x822B, 0xE476, 0x8238, 0xE477, 0x8233, 0xE478, 0x8240, 0xE479, 0x8259, 0xE47A, 0x8258, 0xE47B, 0x825D, + 0xE47C, 0x825A, 0xE47D, 0x825F, 0xE47E, 0x8264, 0xE480, 0x8262, 0xE481, 0x8268, 0xE482, 0x826A, 0xE483, 0x826B, 0xE484, 0x822E, + 0xE485, 0x8271, 0xE486, 0x8277, 0xE487, 0x8278, 0xE488, 0x827E, 0xE489, 0x828D, 0xE48A, 0x8292, 0xE48B, 0x82AB, 0xE48C, 0x829F, + 0xE48D, 0x82BB, 0xE48E, 0x82AC, 0xE48F, 0x82E1, 0xE490, 0x82E3, 0xE491, 0x82DF, 0xE492, 0x82D2, 0xE493, 0x82F4, 0xE494, 0x82F3, + 0xE495, 0x82FA, 0xE496, 0x8393, 0xE497, 0x8303, 0xE498, 0x82FB, 0xE499, 0x82F9, 0xE49A, 0x82DE, 0xE49B, 0x8306, 0xE49C, 0x82DC, + 0xE49D, 0x8309, 0xE49E, 0x82D9, 0xE49F, 0x8335, 0xE4A0, 0x8334, 0xE4A1, 0x8316, 0xE4A2, 0x8332, 0xE4A3, 0x8331, 0xE4A4, 0x8340, + 0xE4A5, 0x8339, 0xE4A6, 0x8350, 0xE4A7, 0x8345, 0xE4A8, 0x832F, 0xE4A9, 0x832B, 0xE4AA, 0x8317, 0xE4AB, 0x8318, 0xE4AC, 0x8385, + 0xE4AD, 0x839A, 0xE4AE, 0x83AA, 0xE4AF, 0x839F, 0xE4B0, 0x83A2, 0xE4B1, 0x8396, 0xE4B2, 0x8323, 0xE4B3, 0x838E, 0xE4B4, 0x8387, + 0xE4B5, 0x838A, 0xE4B6, 0x837C, 0xE4B7, 0x83B5, 0xE4B8, 0x8373, 0xE4B9, 0x8375, 0xE4BA, 0x83A0, 0xE4BB, 0x8389, 0xE4BC, 0x83A8, + 0xE4BD, 0x83F4, 0xE4BE, 0x8413, 0xE4BF, 0x83EB, 0xE4C0, 0x83CE, 0xE4C1, 0x83FD, 0xE4C2, 0x8403, 0xE4C3, 0x83D8, 0xE4C4, 0x840B, + 0xE4C5, 0x83C1, 0xE4C6, 0x83F7, 0xE4C7, 0x8407, 0xE4C8, 0x83E0, 0xE4C9, 0x83F2, 0xE4CA, 0x840D, 0xE4CB, 0x8422, 0xE4CC, 0x8420, + 0xE4CD, 0x83BD, 0xE4CE, 0x8438, 0xE4CF, 0x8506, 0xE4D0, 0x83FB, 0xE4D1, 0x846D, 0xE4D2, 0x842A, 0xE4D3, 0x843C, 0xE4D4, 0x855A, + 0xE4D5, 0x8484, 0xE4D6, 0x8477, 0xE4D7, 0x846B, 0xE4D8, 0x84AD, 0xE4D9, 0x846E, 0xE4DA, 0x8482, 0xE4DB, 0x8469, 0xE4DC, 0x8446, + 0xE4DD, 0x842C, 0xE4DE, 0x846F, 0xE4DF, 0x8479, 0xE4E0, 0x8435, 0xE4E1, 0x84CA, 0xE4E2, 0x8462, 0xE4E3, 0x84B9, 0xE4E4, 0x84BF, + 0xE4E5, 0x849F, 0xE4E6, 0x84D9, 0xE4E7, 0x84CD, 0xE4E8, 0x84BB, 0xE4E9, 0x84DA, 0xE4EA, 0x84D0, 0xE4EB, 0x84C1, 0xE4EC, 0x84C6, + 0xE4ED, 0x84D6, 0xE4EE, 0x84A1, 0xE4EF, 0x8521, 0xE4F0, 0x84FF, 0xE4F1, 0x84F4, 0xE4F2, 0x8517, 0xE4F3, 0x8518, 0xE4F4, 0x852C, + 0xE4F5, 0x851F, 0xE4F6, 0x8515, 0xE4F7, 0x8514, 0xE4F8, 0x84FC, 0xE4F9, 0x8540, 0xE4FA, 0x8563, 0xE4FB, 0x8558, 0xE4FC, 0x8548, + 0xE540, 0x8541, 0xE541, 0x8602, 0xE542, 0x854B, 0xE543, 0x8555, 0xE544, 0x8580, 0xE545, 0x85A4, 0xE546, 0x8588, 0xE547, 0x8591, + 0xE548, 0x858A, 0xE549, 0x85A8, 0xE54A, 0x856D, 0xE54B, 0x8594, 0xE54C, 0x859B, 0xE54D, 0x85EA, 0xE54E, 0x8587, 0xE54F, 0x859C, + 0xE550, 0x8577, 0xE551, 0x857E, 0xE552, 0x8590, 0xE553, 0x85C9, 0xE554, 0x85BA, 0xE555, 0x85CF, 0xE556, 0x85B9, 0xE557, 0x85D0, + 0xE558, 0x85D5, 0xE559, 0x85DD, 0xE55A, 0x85E5, 0xE55B, 0x85DC, 0xE55C, 0x85F9, 0xE55D, 0x860A, 0xE55E, 0x8613, 0xE55F, 0x860B, + 0xE560, 0x85FE, 0xE561, 0x85FA, 0xE562, 0x8606, 0xE563, 0x8622, 0xE564, 0x861A, 0xE565, 0x8630, 0xE566, 0x863F, 0xE567, 0x864D, + 0xE568, 0x4E55, 0xE569, 0x8654, 0xE56A, 0x865F, 0xE56B, 0x8667, 0xE56C, 0x8671, 0xE56D, 0x8693, 0xE56E, 0x86A3, 0xE56F, 0x86A9, + 0xE570, 0x86AA, 0xE571, 0x868B, 0xE572, 0x868C, 0xE573, 0x86B6, 0xE574, 0x86AF, 0xE575, 0x86C4, 0xE576, 0x86C6, 0xE577, 0x86B0, + 0xE578, 0x86C9, 0xE579, 0x8823, 0xE57A, 0x86AB, 0xE57B, 0x86D4, 0xE57C, 0x86DE, 0xE57D, 0x86E9, 0xE57E, 0x86EC, 0xE580, 0x86DF, + 0xE581, 0x86DB, 0xE582, 0x86EF, 0xE583, 0x8712, 0xE584, 0x8706, 0xE585, 0x8708, 0xE586, 0x8700, 0xE587, 0x8703, 0xE588, 0x86FB, + 0xE589, 0x8711, 0xE58A, 0x8709, 0xE58B, 0x870D, 0xE58C, 0x86F9, 0xE58D, 0x870A, 0xE58E, 0x8734, 0xE58F, 0x873F, 0xE590, 0x8737, + 0xE591, 0x873B, 0xE592, 0x8725, 0xE593, 0x8729, 0xE594, 0x871A, 0xE595, 0x8760, 0xE596, 0x875F, 0xE597, 0x8778, 0xE598, 0x874C, + 0xE599, 0x874E, 0xE59A, 0x8774, 0xE59B, 0x8757, 0xE59C, 0x8768, 0xE59D, 0x876E, 0xE59E, 0x8759, 0xE59F, 0x8753, 0xE5A0, 0x8763, + 0xE5A1, 0x876A, 0xE5A2, 0x8805, 0xE5A3, 0x87A2, 0xE5A4, 0x879F, 0xE5A5, 0x8782, 0xE5A6, 0x87AF, 0xE5A7, 0x87CB, 0xE5A8, 0x87BD, + 0xE5A9, 0x87C0, 0xE5AA, 0x87D0, 0xE5AB, 0x96D6, 0xE5AC, 0x87AB, 0xE5AD, 0x87C4, 0xE5AE, 0x87B3, 0xE5AF, 0x87C7, 0xE5B0, 0x87C6, + 0xE5B1, 0x87BB, 0xE5B2, 0x87EF, 0xE5B3, 0x87F2, 0xE5B4, 0x87E0, 0xE5B5, 0x880F, 0xE5B6, 0x880D, 0xE5B7, 0x87FE, 0xE5B8, 0x87F6, + 0xE5B9, 0x87F7, 0xE5BA, 0x880E, 0xE5BB, 0x87D2, 0xE5BC, 0x8811, 0xE5BD, 0x8816, 0xE5BE, 0x8815, 0xE5BF, 0x8822, 0xE5C0, 0x8821, + 0xE5C1, 0x8831, 0xE5C2, 0x8836, 0xE5C3, 0x8839, 0xE5C4, 0x8827, 0xE5C5, 0x883B, 0xE5C6, 0x8844, 0xE5C7, 0x8842, 0xE5C8, 0x8852, + 0xE5C9, 0x8859, 0xE5CA, 0x885E, 0xE5CB, 0x8862, 0xE5CC, 0x886B, 0xE5CD, 0x8881, 0xE5CE, 0x887E, 0xE5CF, 0x889E, 0xE5D0, 0x8875, + 0xE5D1, 0x887D, 0xE5D2, 0x88B5, 0xE5D3, 0x8872, 0xE5D4, 0x8882, 0xE5D5, 0x8897, 0xE5D6, 0x8892, 0xE5D7, 0x88AE, 0xE5D8, 0x8899, + 0xE5D9, 0x88A2, 0xE5DA, 0x888D, 0xE5DB, 0x88A4, 0xE5DC, 0x88B0, 0xE5DD, 0x88BF, 0xE5DE, 0x88B1, 0xE5DF, 0x88C3, 0xE5E0, 0x88C4, + 0xE5E1, 0x88D4, 0xE5E2, 0x88D8, 0xE5E3, 0x88D9, 0xE5E4, 0x88DD, 0xE5E5, 0x88F9, 0xE5E6, 0x8902, 0xE5E7, 0x88FC, 0xE5E8, 0x88F4, + 0xE5E9, 0x88E8, 0xE5EA, 0x88F2, 0xE5EB, 0x8904, 0xE5EC, 0x890C, 0xE5ED, 0x890A, 0xE5EE, 0x8913, 0xE5EF, 0x8943, 0xE5F0, 0x891E, + 0xE5F1, 0x8925, 0xE5F2, 0x892A, 0xE5F3, 0x892B, 0xE5F4, 0x8941, 0xE5F5, 0x8944, 0xE5F6, 0x893B, 0xE5F7, 0x8936, 0xE5F8, 0x8938, + 0xE5F9, 0x894C, 0xE5FA, 0x891D, 0xE5FB, 0x8960, 0xE5FC, 0x895E, 0xE640, 0x8966, 0xE641, 0x8964, 0xE642, 0x896D, 0xE643, 0x896A, + 0xE644, 0x896F, 0xE645, 0x8974, 0xE646, 0x8977, 0xE647, 0x897E, 0xE648, 0x8983, 0xE649, 0x8988, 0xE64A, 0x898A, 0xE64B, 0x8993, + 0xE64C, 0x8998, 0xE64D, 0x89A1, 0xE64E, 0x89A9, 0xE64F, 0x89A6, 0xE650, 0x89AC, 0xE651, 0x89AF, 0xE652, 0x89B2, 0xE653, 0x89BA, + 0xE654, 0x89BD, 0xE655, 0x89BF, 0xE656, 0x89C0, 0xE657, 0x89DA, 0xE658, 0x89DC, 0xE659, 0x89DD, 0xE65A, 0x89E7, 0xE65B, 0x89F4, + 0xE65C, 0x89F8, 0xE65D, 0x8A03, 0xE65E, 0x8A16, 0xE65F, 0x8A10, 0xE660, 0x8A0C, 0xE661, 0x8A1B, 0xE662, 0x8A1D, 0xE663, 0x8A25, + 0xE664, 0x8A36, 0xE665, 0x8A41, 0xE666, 0x8A5B, 0xE667, 0x8A52, 0xE668, 0x8A46, 0xE669, 0x8A48, 0xE66A, 0x8A7C, 0xE66B, 0x8A6D, + 0xE66C, 0x8A6C, 0xE66D, 0x8A62, 0xE66E, 0x8A85, 0xE66F, 0x8A82, 0xE670, 0x8A84, 0xE671, 0x8AA8, 0xE672, 0x8AA1, 0xE673, 0x8A91, + 0xE674, 0x8AA5, 0xE675, 0x8AA6, 0xE676, 0x8A9A, 0xE677, 0x8AA3, 0xE678, 0x8AC4, 0xE679, 0x8ACD, 0xE67A, 0x8AC2, 0xE67B, 0x8ADA, + 0xE67C, 0x8AEB, 0xE67D, 0x8AF3, 0xE67E, 0x8AE7, 0xE680, 0x8AE4, 0xE681, 0x8AF1, 0xE682, 0x8B14, 0xE683, 0x8AE0, 0xE684, 0x8AE2, + 0xE685, 0x8AF7, 0xE686, 0x8ADE, 0xE687, 0x8ADB, 0xE688, 0x8B0C, 0xE689, 0x8B07, 0xE68A, 0x8B1A, 0xE68B, 0x8AE1, 0xE68C, 0x8B16, + 0xE68D, 0x8B10, 0xE68E, 0x8B17, 0xE68F, 0x8B20, 0xE690, 0x8B33, 0xE691, 0x97AB, 0xE692, 0x8B26, 0xE693, 0x8B2B, 0xE694, 0x8B3E, + 0xE695, 0x8B28, 0xE696, 0x8B41, 0xE697, 0x8B4C, 0xE698, 0x8B4F, 0xE699, 0x8B4E, 0xE69A, 0x8B49, 0xE69B, 0x8B56, 0xE69C, 0x8B5B, + 0xE69D, 0x8B5A, 0xE69E, 0x8B6B, 0xE69F, 0x8B5F, 0xE6A0, 0x8B6C, 0xE6A1, 0x8B6F, 0xE6A2, 0x8B74, 0xE6A3, 0x8B7D, 0xE6A4, 0x8B80, + 0xE6A5, 0x8B8C, 0xE6A6, 0x8B8E, 0xE6A7, 0x8B92, 0xE6A8, 0x8B93, 0xE6A9, 0x8B96, 0xE6AA, 0x8B99, 0xE6AB, 0x8B9A, 0xE6AC, 0x8C3A, + 0xE6AD, 0x8C41, 0xE6AE, 0x8C3F, 0xE6AF, 0x8C48, 0xE6B0, 0x8C4C, 0xE6B1, 0x8C4E, 0xE6B2, 0x8C50, 0xE6B3, 0x8C55, 0xE6B4, 0x8C62, + 0xE6B5, 0x8C6C, 0xE6B6, 0x8C78, 0xE6B7, 0x8C7A, 0xE6B8, 0x8C82, 0xE6B9, 0x8C89, 0xE6BA, 0x8C85, 0xE6BB, 0x8C8A, 0xE6BC, 0x8C8D, + 0xE6BD, 0x8C8E, 0xE6BE, 0x8C94, 0xE6BF, 0x8C7C, 0xE6C0, 0x8C98, 0xE6C1, 0x621D, 0xE6C2, 0x8CAD, 0xE6C3, 0x8CAA, 0xE6C4, 0x8CBD, + 0xE6C5, 0x8CB2, 0xE6C6, 0x8CB3, 0xE6C7, 0x8CAE, 0xE6C8, 0x8CB6, 0xE6C9, 0x8CC8, 0xE6CA, 0x8CC1, 0xE6CB, 0x8CE4, 0xE6CC, 0x8CE3, + 0xE6CD, 0x8CDA, 0xE6CE, 0x8CFD, 0xE6CF, 0x8CFA, 0xE6D0, 0x8CFB, 0xE6D1, 0x8D04, 0xE6D2, 0x8D05, 0xE6D3, 0x8D0A, 0xE6D4, 0x8D07, + 0xE6D5, 0x8D0F, 0xE6D6, 0x8D0D, 0xE6D7, 0x8D10, 0xE6D8, 0x9F4E, 0xE6D9, 0x8D13, 0xE6DA, 0x8CCD, 0xE6DB, 0x8D14, 0xE6DC, 0x8D16, + 0xE6DD, 0x8D67, 0xE6DE, 0x8D6D, 0xE6DF, 0x8D71, 0xE6E0, 0x8D73, 0xE6E1, 0x8D81, 0xE6E2, 0x8D99, 0xE6E3, 0x8DC2, 0xE6E4, 0x8DBE, + 0xE6E5, 0x8DBA, 0xE6E6, 0x8DCF, 0xE6E7, 0x8DDA, 0xE6E8, 0x8DD6, 0xE6E9, 0x8DCC, 0xE6EA, 0x8DDB, 0xE6EB, 0x8DCB, 0xE6EC, 0x8DEA, + 0xE6ED, 0x8DEB, 0xE6EE, 0x8DDF, 0xE6EF, 0x8DE3, 0xE6F0, 0x8DFC, 0xE6F1, 0x8E08, 0xE6F2, 0x8E09, 0xE6F3, 0x8DFF, 0xE6F4, 0x8E1D, + 0xE6F5, 0x8E1E, 0xE6F6, 0x8E10, 0xE6F7, 0x8E1F, 0xE6F8, 0x8E42, 0xE6F9, 0x8E35, 0xE6FA, 0x8E30, 0xE6FB, 0x8E34, 0xE6FC, 0x8E4A, + 0xE740, 0x8E47, 0xE741, 0x8E49, 0xE742, 0x8E4C, 0xE743, 0x8E50, 0xE744, 0x8E48, 0xE745, 0x8E59, 0xE746, 0x8E64, 0xE747, 0x8E60, + 0xE748, 0x8E2A, 0xE749, 0x8E63, 0xE74A, 0x8E55, 0xE74B, 0x8E76, 0xE74C, 0x8E72, 0xE74D, 0x8E7C, 0xE74E, 0x8E81, 0xE74F, 0x8E87, + 0xE750, 0x8E85, 0xE751, 0x8E84, 0xE752, 0x8E8B, 0xE753, 0x8E8A, 0xE754, 0x8E93, 0xE755, 0x8E91, 0xE756, 0x8E94, 0xE757, 0x8E99, + 0xE758, 0x8EAA, 0xE759, 0x8EA1, 0xE75A, 0x8EAC, 0xE75B, 0x8EB0, 0xE75C, 0x8EC6, 0xE75D, 0x8EB1, 0xE75E, 0x8EBE, 0xE75F, 0x8EC5, + 0xE760, 0x8EC8, 0xE761, 0x8ECB, 0xE762, 0x8EDB, 0xE763, 0x8EE3, 0xE764, 0x8EFC, 0xE765, 0x8EFB, 0xE766, 0x8EEB, 0xE767, 0x8EFE, + 0xE768, 0x8F0A, 0xE769, 0x8F05, 0xE76A, 0x8F15, 0xE76B, 0x8F12, 0xE76C, 0x8F19, 0xE76D, 0x8F13, 0xE76E, 0x8F1C, 0xE76F, 0x8F1F, + 0xE770, 0x8F1B, 0xE771, 0x8F0C, 0xE772, 0x8F26, 0xE773, 0x8F33, 0xE774, 0x8F3B, 0xE775, 0x8F39, 0xE776, 0x8F45, 0xE777, 0x8F42, + 0xE778, 0x8F3E, 0xE779, 0x8F4C, 0xE77A, 0x8F49, 0xE77B, 0x8F46, 0xE77C, 0x8F4E, 0xE77D, 0x8F57, 0xE77E, 0x8F5C, 0xE780, 0x8F62, + 0xE781, 0x8F63, 0xE782, 0x8F64, 0xE783, 0x8F9C, 0xE784, 0x8F9F, 0xE785, 0x8FA3, 0xE786, 0x8FAD, 0xE787, 0x8FAF, 0xE788, 0x8FB7, + 0xE789, 0x8FDA, 0xE78A, 0x8FE5, 0xE78B, 0x8FE2, 0xE78C, 0x8FEA, 0xE78D, 0x8FEF, 0xE78E, 0x9087, 0xE78F, 0x8FF4, 0xE790, 0x9005, + 0xE791, 0x8FF9, 0xE792, 0x8FFA, 0xE793, 0x9011, 0xE794, 0x9015, 0xE795, 0x9021, 0xE796, 0x900D, 0xE797, 0x901E, 0xE798, 0x9016, + 0xE799, 0x900B, 0xE79A, 0x9027, 0xE79B, 0x9036, 0xE79C, 0x9035, 0xE79D, 0x9039, 0xE79E, 0x8FF8, 0xE79F, 0x904F, 0xE7A0, 0x9050, + 0xE7A1, 0x9051, 0xE7A2, 0x9052, 0xE7A3, 0x900E, 0xE7A4, 0x9049, 0xE7A5, 0x903E, 0xE7A6, 0x9056, 0xE7A7, 0x9058, 0xE7A8, 0x905E, + 0xE7A9, 0x9068, 0xE7AA, 0x906F, 0xE7AB, 0x9076, 0xE7AC, 0x96A8, 0xE7AD, 0x9072, 0xE7AE, 0x9082, 0xE7AF, 0x907D, 0xE7B0, 0x9081, + 0xE7B1, 0x9080, 0xE7B2, 0x908A, 0xE7B3, 0x9089, 0xE7B4, 0x908F, 0xE7B5, 0x90A8, 0xE7B6, 0x90AF, 0xE7B7, 0x90B1, 0xE7B8, 0x90B5, + 0xE7B9, 0x90E2, 0xE7BA, 0x90E4, 0xE7BB, 0x6248, 0xE7BC, 0x90DB, 0xE7BD, 0x9102, 0xE7BE, 0x9112, 0xE7BF, 0x9119, 0xE7C0, 0x9132, + 0xE7C1, 0x9130, 0xE7C2, 0x914A, 0xE7C3, 0x9156, 0xE7C4, 0x9158, 0xE7C5, 0x9163, 0xE7C6, 0x9165, 0xE7C7, 0x9169, 0xE7C8, 0x9173, + 0xE7C9, 0x9172, 0xE7CA, 0x918B, 0xE7CB, 0x9189, 0xE7CC, 0x9182, 0xE7CD, 0x91A2, 0xE7CE, 0x91AB, 0xE7CF, 0x91AF, 0xE7D0, 0x91AA, + 0xE7D1, 0x91B5, 0xE7D2, 0x91B4, 0xE7D3, 0x91BA, 0xE7D4, 0x91C0, 0xE7D5, 0x91C1, 0xE7D6, 0x91C9, 0xE7D7, 0x91CB, 0xE7D8, 0x91D0, + 0xE7D9, 0x91D6, 0xE7DA, 0x91DF, 0xE7DB, 0x91E1, 0xE7DC, 0x91DB, 0xE7DD, 0x91FC, 0xE7DE, 0x91F5, 0xE7DF, 0x91F6, 0xE7E0, 0x921E, + 0xE7E1, 0x91FF, 0xE7E2, 0x9214, 0xE7E3, 0x922C, 0xE7E4, 0x9215, 0xE7E5, 0x9211, 0xE7E6, 0x925E, 0xE7E7, 0x9257, 0xE7E8, 0x9245, + 0xE7E9, 0x9249, 0xE7EA, 0x9264, 0xE7EB, 0x9248, 0xE7EC, 0x9295, 0xE7ED, 0x923F, 0xE7EE, 0x924B, 0xE7EF, 0x9250, 0xE7F0, 0x929C, + 0xE7F1, 0x9296, 0xE7F2, 0x9293, 0xE7F3, 0x929B, 0xE7F4, 0x925A, 0xE7F5, 0x92CF, 0xE7F6, 0x92B9, 0xE7F7, 0x92B7, 0xE7F8, 0x92E9, + 0xE7F9, 0x930F, 0xE7FA, 0x92FA, 0xE7FB, 0x9344, 0xE7FC, 0x932E, 0xE840, 0x9319, 0xE841, 0x9322, 0xE842, 0x931A, 0xE843, 0x9323, + 0xE844, 0x933A, 0xE845, 0x9335, 0xE846, 0x933B, 0xE847, 0x935C, 0xE848, 0x9360, 0xE849, 0x937C, 0xE84A, 0x936E, 0xE84B, 0x9356, + 0xE84C, 0x93B0, 0xE84D, 0x93AC, 0xE84E, 0x93AD, 0xE84F, 0x9394, 0xE850, 0x93B9, 0xE851, 0x93D6, 0xE852, 0x93D7, 0xE853, 0x93E8, + 0xE854, 0x93E5, 0xE855, 0x93D8, 0xE856, 0x93C3, 0xE857, 0x93DD, 0xE858, 0x93D0, 0xE859, 0x93C8, 0xE85A, 0x93E4, 0xE85B, 0x941A, + 0xE85C, 0x9414, 0xE85D, 0x9413, 0xE85E, 0x9403, 0xE85F, 0x9407, 0xE860, 0x9410, 0xE861, 0x9436, 0xE862, 0x942B, 0xE863, 0x9435, + 0xE864, 0x9421, 0xE865, 0x943A, 0xE866, 0x9441, 0xE867, 0x9452, 0xE868, 0x9444, 0xE869, 0x945B, 0xE86A, 0x9460, 0xE86B, 0x9462, + 0xE86C, 0x945E, 0xE86D, 0x946A, 0xE86E, 0x9229, 0xE86F, 0x9470, 0xE870, 0x9475, 0xE871, 0x9477, 0xE872, 0x947D, 0xE873, 0x945A, + 0xE874, 0x947C, 0xE875, 0x947E, 0xE876, 0x9481, 0xE877, 0x947F, 0xE878, 0x9582, 0xE879, 0x9587, 0xE87A, 0x958A, 0xE87B, 0x9594, + 0xE87C, 0x9596, 0xE87D, 0x9598, 0xE87E, 0x9599, 0xE880, 0x95A0, 0xE881, 0x95A8, 0xE882, 0x95A7, 0xE883, 0x95AD, 0xE884, 0x95BC, + 0xE885, 0x95BB, 0xE886, 0x95B9, 0xE887, 0x95BE, 0xE888, 0x95CA, 0xE889, 0x6FF6, 0xE88A, 0x95C3, 0xE88B, 0x95CD, 0xE88C, 0x95CC, + 0xE88D, 0x95D5, 0xE88E, 0x95D4, 0xE88F, 0x95D6, 0xE890, 0x95DC, 0xE891, 0x95E1, 0xE892, 0x95E5, 0xE893, 0x95E2, 0xE894, 0x9621, + 0xE895, 0x9628, 0xE896, 0x962E, 0xE897, 0x962F, 0xE898, 0x9642, 0xE899, 0x964C, 0xE89A, 0x964F, 0xE89B, 0x964B, 0xE89C, 0x9677, + 0xE89D, 0x965C, 0xE89E, 0x965E, 0xE89F, 0x965D, 0xE8A0, 0x965F, 0xE8A1, 0x9666, 0xE8A2, 0x9672, 0xE8A3, 0x966C, 0xE8A4, 0x968D, + 0xE8A5, 0x9698, 0xE8A6, 0x9695, 0xE8A7, 0x9697, 0xE8A8, 0x96AA, 0xE8A9, 0x96A7, 0xE8AA, 0x96B1, 0xE8AB, 0x96B2, 0xE8AC, 0x96B0, + 0xE8AD, 0x96B4, 0xE8AE, 0x96B6, 0xE8AF, 0x96B8, 0xE8B0, 0x96B9, 0xE8B1, 0x96CE, 0xE8B2, 0x96CB, 0xE8B3, 0x96C9, 0xE8B4, 0x96CD, + 0xE8B5, 0x894D, 0xE8B6, 0x96DC, 0xE8B7, 0x970D, 0xE8B8, 0x96D5, 0xE8B9, 0x96F9, 0xE8BA, 0x9704, 0xE8BB, 0x9706, 0xE8BC, 0x9708, + 0xE8BD, 0x9713, 0xE8BE, 0x970E, 0xE8BF, 0x9711, 0xE8C0, 0x970F, 0xE8C1, 0x9716, 0xE8C2, 0x9719, 0xE8C3, 0x9724, 0xE8C4, 0x972A, + 0xE8C5, 0x9730, 0xE8C6, 0x9739, 0xE8C7, 0x973D, 0xE8C8, 0x973E, 0xE8C9, 0x9744, 0xE8CA, 0x9746, 0xE8CB, 0x9748, 0xE8CC, 0x9742, + 0xE8CD, 0x9749, 0xE8CE, 0x975C, 0xE8CF, 0x9760, 0xE8D0, 0x9764, 0xE8D1, 0x9766, 0xE8D2, 0x9768, 0xE8D3, 0x52D2, 0xE8D4, 0x976B, + 0xE8D5, 0x9771, 0xE8D6, 0x9779, 0xE8D7, 0x9785, 0xE8D8, 0x977C, 0xE8D9, 0x9781, 0xE8DA, 0x977A, 0xE8DB, 0x9786, 0xE8DC, 0x978B, + 0xE8DD, 0x978F, 0xE8DE, 0x9790, 0xE8DF, 0x979C, 0xE8E0, 0x97A8, 0xE8E1, 0x97A6, 0xE8E2, 0x97A3, 0xE8E3, 0x97B3, 0xE8E4, 0x97B4, + 0xE8E5, 0x97C3, 0xE8E6, 0x97C6, 0xE8E7, 0x97C8, 0xE8E8, 0x97CB, 0xE8E9, 0x97DC, 0xE8EA, 0x97ED, 0xE8EB, 0x9F4F, 0xE8EC, 0x97F2, + 0xE8ED, 0x7ADF, 0xE8EE, 0x97F6, 0xE8EF, 0x97F5, 0xE8F0, 0x980F, 0xE8F1, 0x980C, 0xE8F2, 0x9838, 0xE8F3, 0x9824, 0xE8F4, 0x9821, + 0xE8F5, 0x9837, 0xE8F6, 0x983D, 0xE8F7, 0x9846, 0xE8F8, 0x984F, 0xE8F9, 0x984B, 0xE8FA, 0x986B, 0xE8FB, 0x986F, 0xE8FC, 0x9870, + 0xE940, 0x9871, 0xE941, 0x9874, 0xE942, 0x9873, 0xE943, 0x98AA, 0xE944, 0x98AF, 0xE945, 0x98B1, 0xE946, 0x98B6, 0xE947, 0x98C4, + 0xE948, 0x98C3, 0xE949, 0x98C6, 0xE94A, 0x98E9, 0xE94B, 0x98EB, 0xE94C, 0x9903, 0xE94D, 0x9909, 0xE94E, 0x9912, 0xE94F, 0x9914, + 0xE950, 0x9918, 0xE951, 0x9921, 0xE952, 0x991D, 0xE953, 0x991E, 0xE954, 0x9924, 0xE955, 0x9920, 0xE956, 0x992C, 0xE957, 0x992E, + 0xE958, 0x993D, 0xE959, 0x993E, 0xE95A, 0x9942, 0xE95B, 0x9949, 0xE95C, 0x9945, 0xE95D, 0x9950, 0xE95E, 0x994B, 0xE95F, 0x9951, + 0xE960, 0x9952, 0xE961, 0x994C, 0xE962, 0x9955, 0xE963, 0x9997, 0xE964, 0x9998, 0xE965, 0x99A5, 0xE966, 0x99AD, 0xE967, 0x99AE, + 0xE968, 0x99BC, 0xE969, 0x99DF, 0xE96A, 0x99DB, 0xE96B, 0x99DD, 0xE96C, 0x99D8, 0xE96D, 0x99D1, 0xE96E, 0x99ED, 0xE96F, 0x99EE, + 0xE970, 0x99F1, 0xE971, 0x99F2, 0xE972, 0x99FB, 0xE973, 0x99F8, 0xE974, 0x9A01, 0xE975, 0x9A0F, 0xE976, 0x9A05, 0xE977, 0x99E2, + 0xE978, 0x9A19, 0xE979, 0x9A2B, 0xE97A, 0x9A37, 0xE97B, 0x9A45, 0xE97C, 0x9A42, 0xE97D, 0x9A40, 0xE97E, 0x9A43, 0xE980, 0x9A3E, + 0xE981, 0x9A55, 0xE982, 0x9A4D, 0xE983, 0x9A5B, 0xE984, 0x9A57, 0xE985, 0x9A5F, 0xE986, 0x9A62, 0xE987, 0x9A65, 0xE988, 0x9A64, + 0xE989, 0x9A69, 0xE98A, 0x9A6B, 0xE98B, 0x9A6A, 0xE98C, 0x9AAD, 0xE98D, 0x9AB0, 0xE98E, 0x9ABC, 0xE98F, 0x9AC0, 0xE990, 0x9ACF, + 0xE991, 0x9AD1, 0xE992, 0x9AD3, 0xE993, 0x9AD4, 0xE994, 0x9ADE, 0xE995, 0x9ADF, 0xE996, 0x9AE2, 0xE997, 0x9AE3, 0xE998, 0x9AE6, + 0xE999, 0x9AEF, 0xE99A, 0x9AEB, 0xE99B, 0x9AEE, 0xE99C, 0x9AF4, 0xE99D, 0x9AF1, 0xE99E, 0x9AF7, 0xE99F, 0x9AFB, 0xE9A0, 0x9B06, + 0xE9A1, 0x9B18, 0xE9A2, 0x9B1A, 0xE9A3, 0x9B1F, 0xE9A4, 0x9B22, 0xE9A5, 0x9B23, 0xE9A6, 0x9B25, 0xE9A7, 0x9B27, 0xE9A8, 0x9B28, + 0xE9A9, 0x9B29, 0xE9AA, 0x9B2A, 0xE9AB, 0x9B2E, 0xE9AC, 0x9B2F, 0xE9AD, 0x9B32, 0xE9AE, 0x9B44, 0xE9AF, 0x9B43, 0xE9B0, 0x9B4F, + 0xE9B1, 0x9B4D, 0xE9B2, 0x9B4E, 0xE9B3, 0x9B51, 0xE9B4, 0x9B58, 0xE9B5, 0x9B74, 0xE9B6, 0x9B93, 0xE9B7, 0x9B83, 0xE9B8, 0x9B91, + 0xE9B9, 0x9B96, 0xE9BA, 0x9B97, 0xE9BB, 0x9B9F, 0xE9BC, 0x9BA0, 0xE9BD, 0x9BA8, 0xE9BE, 0x9BB4, 0xE9BF, 0x9BC0, 0xE9C0, 0x9BCA, + 0xE9C1, 0x9BB9, 0xE9C2, 0x9BC6, 0xE9C3, 0x9BCF, 0xE9C4, 0x9BD1, 0xE9C5, 0x9BD2, 0xE9C6, 0x9BE3, 0xE9C7, 0x9BE2, 0xE9C8, 0x9BE4, + 0xE9C9, 0x9BD4, 0xE9CA, 0x9BE1, 0xE9CB, 0x9C3A, 0xE9CC, 0x9BF2, 0xE9CD, 0x9BF1, 0xE9CE, 0x9BF0, 0xE9CF, 0x9C15, 0xE9D0, 0x9C14, + 0xE9D1, 0x9C09, 0xE9D2, 0x9C13, 0xE9D3, 0x9C0C, 0xE9D4, 0x9C06, 0xE9D5, 0x9C08, 0xE9D6, 0x9C12, 0xE9D7, 0x9C0A, 0xE9D8, 0x9C04, + 0xE9D9, 0x9C2E, 0xE9DA, 0x9C1B, 0xE9DB, 0x9C25, 0xE9DC, 0x9C24, 0xE9DD, 0x9C21, 0xE9DE, 0x9C30, 0xE9DF, 0x9C47, 0xE9E0, 0x9C32, + 0xE9E1, 0x9C46, 0xE9E2, 0x9C3E, 0xE9E3, 0x9C5A, 0xE9E4, 0x9C60, 0xE9E5, 0x9C67, 0xE9E6, 0x9C76, 0xE9E7, 0x9C78, 0xE9E8, 0x9CE7, + 0xE9E9, 0x9CEC, 0xE9EA, 0x9CF0, 0xE9EB, 0x9D09, 0xE9EC, 0x9D08, 0xE9ED, 0x9CEB, 0xE9EE, 0x9D03, 0xE9EF, 0x9D06, 0xE9F0, 0x9D2A, + 0xE9F1, 0x9D26, 0xE9F2, 0x9DAF, 0xE9F3, 0x9D23, 0xE9F4, 0x9D1F, 0xE9F5, 0x9D44, 0xE9F6, 0x9D15, 0xE9F7, 0x9D12, 0xE9F8, 0x9D41, + 0xE9F9, 0x9D3F, 0xE9FA, 0x9D3E, 0xE9FB, 0x9D46, 0xE9FC, 0x9D48, 0xEA40, 0x9D5D, 0xEA41, 0x9D5E, 0xEA42, 0x9D64, 0xEA43, 0x9D51, + 0xEA44, 0x9D50, 0xEA45, 0x9D59, 0xEA46, 0x9D72, 0xEA47, 0x9D89, 0xEA48, 0x9D87, 0xEA49, 0x9DAB, 0xEA4A, 0x9D6F, 0xEA4B, 0x9D7A, + 0xEA4C, 0x9D9A, 0xEA4D, 0x9DA4, 0xEA4E, 0x9DA9, 0xEA4F, 0x9DB2, 0xEA50, 0x9DC4, 0xEA51, 0x9DC1, 0xEA52, 0x9DBB, 0xEA53, 0x9DB8, + 0xEA54, 0x9DBA, 0xEA55, 0x9DC6, 0xEA56, 0x9DCF, 0xEA57, 0x9DC2, 0xEA58, 0x9DD9, 0xEA59, 0x9DD3, 0xEA5A, 0x9DF8, 0xEA5B, 0x9DE6, + 0xEA5C, 0x9DED, 0xEA5D, 0x9DEF, 0xEA5E, 0x9DFD, 0xEA5F, 0x9E1A, 0xEA60, 0x9E1B, 0xEA61, 0x9E1E, 0xEA62, 0x9E75, 0xEA63, 0x9E79, + 0xEA64, 0x9E7D, 0xEA65, 0x9E81, 0xEA66, 0x9E88, 0xEA67, 0x9E8B, 0xEA68, 0x9E8C, 0xEA69, 0x9E92, 0xEA6A, 0x9E95, 0xEA6B, 0x9E91, + 0xEA6C, 0x9E9D, 0xEA6D, 0x9EA5, 0xEA6E, 0x9EA9, 0xEA6F, 0x9EB8, 0xEA70, 0x9EAA, 0xEA71, 0x9EAD, 0xEA72, 0x9761, 0xEA73, 0x9ECC, + 0xEA74, 0x9ECE, 0xEA75, 0x9ECF, 0xEA76, 0x9ED0, 0xEA77, 0x9ED4, 0xEA78, 0x9EDC, 0xEA79, 0x9EDE, 0xEA7A, 0x9EDD, 0xEA7B, 0x9EE0, + 0xEA7C, 0x9EE5, 0xEA7D, 0x9EE8, 0xEA7E, 0x9EEF, 0xEA80, 0x9EF4, 0xEA81, 0x9EF6, 0xEA82, 0x9EF7, 0xEA83, 0x9EF9, 0xEA84, 0x9EFB, + 0xEA85, 0x9EFC, 0xEA86, 0x9EFD, 0xEA87, 0x9F07, 0xEA88, 0x9F08, 0xEA89, 0x76B7, 0xEA8A, 0x9F15, 0xEA8B, 0x9F21, 0xEA8C, 0x9F2C, + 0xEA8D, 0x9F3E, 0xEA8E, 0x9F4A, 0xEA8F, 0x9F52, 0xEA90, 0x9F54, 0xEA91, 0x9F63, 0xEA92, 0x9F5F, 0xEA93, 0x9F60, 0xEA94, 0x9F61, + 0xEA95, 0x9F66, 0xEA96, 0x9F67, 0xEA97, 0x9F6C, 0xEA98, 0x9F6A, 0xEA99, 0x9F77, 0xEA9A, 0x9F72, 0xEA9B, 0x9F76, 0xEA9C, 0x9F95, + 0xEA9D, 0x9F9C, 0xEA9E, 0x9FA0, 0xEA9F, 0x582F, 0xEAA0, 0x69C7, 0xEAA1, 0x9059, 0xEAA2, 0x7464, 0xEAA3, 0x51DC, 0xEAA4, 0x7199, + 0xFA40, 0x2170, 0xFA41, 0x2171, 0xFA42, 0x2172, 0xFA43, 0x2173, 0xFA44, 0x2174, 0xFA45, 0x2175, 0xFA46, 0x2176, 0xFA47, 0x2177, + 0xFA48, 0x2178, 0xFA49, 0x2179, 0xFA55, 0xFFE4, 0xFA56, 0xFF07, 0xFA57, 0xFF02, 0xFA5C, 0x7E8A, 0xFA5D, 0x891C, 0xFA5E, 0x9348, + 0xFA5F, 0x9288, 0xFA60, 0x84DC, 0xFA61, 0x4FC9, 0xFA62, 0x70BB, 0xFA63, 0x6631, 0xFA64, 0x68C8, 0xFA65, 0x92F9, 0xFA66, 0x66FB, + 0xFA67, 0x5F45, 0xFA68, 0x4E28, 0xFA69, 0x4EE1, 0xFA6A, 0x4EFC, 0xFA6B, 0x4F00, 0xFA6C, 0x4F03, 0xFA6D, 0x4F39, 0xFA6E, 0x4F56, + 0xFA6F, 0x4F92, 0xFA70, 0x4F8A, 0xFA71, 0x4F9A, 0xFA72, 0x4F94, 0xFA73, 0x4FCD, 0xFA74, 0x5040, 0xFA75, 0x5022, 0xFA76, 0x4FFF, + 0xFA77, 0x501E, 0xFA78, 0x5046, 0xFA79, 0x5070, 0xFA7A, 0x5042, 0xFA7B, 0x5094, 0xFA7C, 0x50F4, 0xFA7D, 0x50D8, 0xFA7E, 0x514A, + 0xFA80, 0x5164, 0xFA81, 0x519D, 0xFA82, 0x51BE, 0xFA83, 0x51EC, 0xFA84, 0x5215, 0xFA85, 0x529C, 0xFA86, 0x52A6, 0xFA87, 0x52C0, + 0xFA88, 0x52DB, 0xFA89, 0x5300, 0xFA8A, 0x5307, 0xFA8B, 0x5324, 0xFA8C, 0x5372, 0xFA8D, 0x5393, 0xFA8E, 0x53B2, 0xFA8F, 0x53DD, + 0xFA90, 0xFA0E, 0xFA91, 0x549C, 0xFA92, 0x548A, 0xFA93, 0x54A9, 0xFA94, 0x54FF, 0xFA95, 0x5586, 0xFA96, 0x5759, 0xFA97, 0x5765, + 0xFA98, 0x57AC, 0xFA99, 0x57C8, 0xFA9A, 0x57C7, 0xFA9B, 0xFA0F, 0xFA9C, 0xFA10, 0xFA9D, 0x589E, 0xFA9E, 0x58B2, 0xFA9F, 0x590B, + 0xFAA0, 0x5953, 0xFAA1, 0x595B, 0xFAA2, 0x595D, 0xFAA3, 0x5963, 0xFAA4, 0x59A4, 0xFAA5, 0x59BA, 0xFAA6, 0x5B56, 0xFAA7, 0x5BC0, + 0xFAA8, 0x752F, 0xFAA9, 0x5BD8, 0xFAAA, 0x5BEC, 0xFAAB, 0x5C1E, 0xFAAC, 0x5CA6, 0xFAAD, 0x5CBA, 0xFAAE, 0x5CF5, 0xFAAF, 0x5D27, + 0xFAB0, 0x5D53, 0xFAB1, 0xFA11, 0xFAB2, 0x5D42, 0xFAB3, 0x5D6D, 0xFAB4, 0x5DB8, 0xFAB5, 0x5DB9, 0xFAB6, 0x5DD0, 0xFAB7, 0x5F21, + 0xFAB8, 0x5F34, 0xFAB9, 0x5F67, 0xFABA, 0x5FB7, 0xFABB, 0x5FDE, 0xFABC, 0x605D, 0xFABD, 0x6085, 0xFABE, 0x608A, 0xFABF, 0x60DE, + 0xFAC0, 0x60D5, 0xFAC1, 0x6120, 0xFAC2, 0x60F2, 0xFAC3, 0x6111, 0xFAC4, 0x6137, 0xFAC5, 0x6130, 0xFAC6, 0x6198, 0xFAC7, 0x6213, + 0xFAC8, 0x62A6, 0xFAC9, 0x63F5, 0xFACA, 0x6460, 0xFACB, 0x649D, 0xFACC, 0x64CE, 0xFACD, 0x654E, 0xFACE, 0x6600, 0xFACF, 0x6615, + 0xFAD0, 0x663B, 0xFAD1, 0x6609, 0xFAD2, 0x662E, 0xFAD3, 0x661E, 0xFAD4, 0x6624, 0xFAD5, 0x6665, 0xFAD6, 0x6657, 0xFAD7, 0x6659, + 0xFAD8, 0xFA12, 0xFAD9, 0x6673, 0xFADA, 0x6699, 0xFADB, 0x66A0, 0xFADC, 0x66B2, 0xFADD, 0x66BF, 0xFADE, 0x66FA, 0xFADF, 0x670E, + 0xFAE0, 0xF929, 0xFAE1, 0x6766, 0xFAE2, 0x67BB, 0xFAE3, 0x6852, 0xFAE4, 0x67C0, 0xFAE5, 0x6801, 0xFAE6, 0x6844, 0xFAE7, 0x68CF, + 0xFAE8, 0xFA13, 0xFAE9, 0x6968, 0xFAEA, 0xFA14, 0xFAEB, 0x6998, 0xFAEC, 0x69E2, 0xFAED, 0x6A30, 0xFAEE, 0x6A6B, 0xFAEF, 0x6A46, + 0xFAF0, 0x6A73, 0xFAF1, 0x6A7E, 0xFAF2, 0x6AE2, 0xFAF3, 0x6AE4, 0xFAF4, 0x6BD6, 0xFAF5, 0x6C3F, 0xFAF6, 0x6C5C, 0xFAF7, 0x6C86, + 0xFAF8, 0x6C6F, 0xFAF9, 0x6CDA, 0xFAFA, 0x6D04, 0xFAFB, 0x6D87, 0xFAFC, 0x6D6F, 0xFB40, 0x6D96, 0xFB41, 0x6DAC, 0xFB42, 0x6DCF, + 0xFB43, 0x6DF8, 0xFB44, 0x6DF2, 0xFB45, 0x6DFC, 0xFB46, 0x6E39, 0xFB47, 0x6E5C, 0xFB48, 0x6E27, 0xFB49, 0x6E3C, 0xFB4A, 0x6EBF, + 0xFB4B, 0x6F88, 0xFB4C, 0x6FB5, 0xFB4D, 0x6FF5, 0xFB4E, 0x7005, 0xFB4F, 0x7007, 0xFB50, 0x7028, 0xFB51, 0x7085, 0xFB52, 0x70AB, + 0xFB53, 0x710F, 0xFB54, 0x7104, 0xFB55, 0x715C, 0xFB56, 0x7146, 0xFB57, 0x7147, 0xFB58, 0xFA15, 0xFB59, 0x71C1, 0xFB5A, 0x71FE, + 0xFB5B, 0x72B1, 0xFB5C, 0x72BE, 0xFB5D, 0x7324, 0xFB5E, 0xFA16, 0xFB5F, 0x7377, 0xFB60, 0x73BD, 0xFB61, 0x73C9, 0xFB62, 0x73D6, + 0xFB63, 0x73E3, 0xFB64, 0x73D2, 0xFB65, 0x7407, 0xFB66, 0x73F5, 0xFB67, 0x7426, 0xFB68, 0x742A, 0xFB69, 0x7429, 0xFB6A, 0x742E, + 0xFB6B, 0x7462, 0xFB6C, 0x7489, 0xFB6D, 0x749F, 0xFB6E, 0x7501, 0xFB6F, 0x756F, 0xFB70, 0x7682, 0xFB71, 0x769C, 0xFB72, 0x769E, + 0xFB73, 0x769B, 0xFB74, 0x76A6, 0xFB75, 0xFA17, 0xFB76, 0x7746, 0xFB77, 0x52AF, 0xFB78, 0x7821, 0xFB79, 0x784E, 0xFB7A, 0x7864, + 0xFB7B, 0x787A, 0xFB7C, 0x7930, 0xFB7D, 0xFA18, 0xFB7E, 0xFA19, 0xFB80, 0xFA1A, 0xFB81, 0x7994, 0xFB82, 0xFA1B, 0xFB83, 0x799B, + 0xFB84, 0x7AD1, 0xFB85, 0x7AE7, 0xFB86, 0xFA1C, 0xFB87, 0x7AEB, 0xFB88, 0x7B9E, 0xFB89, 0xFA1D, 0xFB8A, 0x7D48, 0xFB8B, 0x7D5C, + 0xFB8C, 0x7DB7, 0xFB8D, 0x7DA0, 0xFB8E, 0x7DD6, 0xFB8F, 0x7E52, 0xFB90, 0x7F47, 0xFB91, 0x7FA1, 0xFB92, 0xFA1E, 0xFB93, 0x8301, + 0xFB94, 0x8362, 0xFB95, 0x837F, 0xFB96, 0x83C7, 0xFB97, 0x83F6, 0xFB98, 0x8448, 0xFB99, 0x84B4, 0xFB9A, 0x8553, 0xFB9B, 0x8559, + 0xFB9C, 0x856B, 0xFB9D, 0xFA1F, 0xFB9E, 0x85B0, 0xFB9F, 0xFA20, 0xFBA0, 0xFA21, 0xFBA1, 0x8807, 0xFBA2, 0x88F5, 0xFBA3, 0x8A12, + 0xFBA4, 0x8A37, 0xFBA5, 0x8A79, 0xFBA6, 0x8AA7, 0xFBA7, 0x8ABE, 0xFBA8, 0x8ADF, 0xFBA9, 0xFA22, 0xFBAA, 0x8AF6, 0xFBAB, 0x8B53, + 0xFBAC, 0x8B7F, 0xFBAD, 0x8CF0, 0xFBAE, 0x8CF4, 0xFBAF, 0x8D12, 0xFBB0, 0x8D76, 0xFBB1, 0xFA23, 0xFBB2, 0x8ECF, 0xFBB3, 0xFA24, + 0xFBB4, 0xFA25, 0xFBB5, 0x9067, 0xFBB6, 0x90DE, 0xFBB7, 0xFA26, 0xFBB8, 0x9115, 0xFBB9, 0x9127, 0xFBBA, 0x91DA, 0xFBBB, 0x91D7, + 0xFBBC, 0x91DE, 0xFBBD, 0x91ED, 0xFBBE, 0x91EE, 0xFBBF, 0x91E4, 0xFBC0, 0x91E5, 0xFBC1, 0x9206, 0xFBC2, 0x9210, 0xFBC3, 0x920A, + 0xFBC4, 0x923A, 0xFBC5, 0x9240, 0xFBC6, 0x923C, 0xFBC7, 0x924E, 0xFBC8, 0x9259, 0xFBC9, 0x9251, 0xFBCA, 0x9239, 0xFBCB, 0x9267, + 0xFBCC, 0x92A7, 0xFBCD, 0x9277, 0xFBCE, 0x9278, 0xFBCF, 0x92E7, 0xFBD0, 0x92D7, 0xFBD1, 0x92D9, 0xFBD2, 0x92D0, 0xFBD3, 0xFA27, + 0xFBD4, 0x92D5, 0xFBD5, 0x92E0, 0xFBD6, 0x92D3, 0xFBD7, 0x9325, 0xFBD8, 0x9321, 0xFBD9, 0x92FB, 0xFBDA, 0xFA28, 0xFBDB, 0x931E, + 0xFBDC, 0x92FF, 0xFBDD, 0x931D, 0xFBDE, 0x9302, 0xFBDF, 0x9370, 0xFBE0, 0x9357, 0xFBE1, 0x93A4, 0xFBE2, 0x93C6, 0xFBE3, 0x93DE, + 0xFBE4, 0x93F8, 0xFBE5, 0x9431, 0xFBE6, 0x9445, 0xFBE7, 0x9448, 0xFBE8, 0x9592, 0xFBE9, 0xF9DC, 0xFBEA, 0xFA29, 0xFBEB, 0x969D, + 0xFBEC, 0x96AF, 0xFBED, 0x9733, 0xFBEE, 0x973B, 0xFBEF, 0x9743, 0xFBF0, 0x974D, 0xFBF1, 0x974F, 0xFBF2, 0x9751, 0xFBF3, 0x9755, + 0xFBF4, 0x9857, 0xFBF5, 0x9865, 0xFBF6, 0xFA2A, 0xFBF7, 0xFA2B, 0xFBF8, 0x9927, 0xFBF9, 0xFA2C, 0xFBFA, 0x999E, 0xFBFB, 0x9A4E, + 0xFBFC, 0x9AD9, 0xFC40, 0x9ADC, 0xFC41, 0x9B75, 0xFC42, 0x9B72, 0xFC43, 0x9B8F, 0xFC44, 0x9BB1, 0xFC45, 0x9BBB, 0xFC46, 0x9C00, + 0xFC47, 0x9D70, 0xFC48, 0x9D6B, 0xFC49, 0xFA2D, 0xFC4A, 0x9E19, 0xFC4B, 0x9ED1, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */ +static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ + 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, + 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, + 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, + 0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1, 0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3, + 0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8, 0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5, + 0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1, 0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5, + 0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9, 0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD, + 0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1, 0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5, + 0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1, 0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5, + 0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9, 0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD, + 0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1, 0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5, + 0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7, 0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4, + 0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9, 0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD, + 0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1, 0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5, + 0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9, 0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD, + 0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1, 0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4, + 0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9, 0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD, + 0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1, 0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5, + 0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9, 0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED, + 0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1, 0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA, + 0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD, + 0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846, 0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847, + 0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1, 0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5, + 0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9, 0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1, + 0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5, 0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9, + 0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA, 0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B, + 0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6, 0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE, + 0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE, 0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8, + 0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF, 0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6, + 0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4, 0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852, + 0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1, 0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9, + 0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD, 0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1, + 0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7, 0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB, + 0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF, 0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3, + 0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7, 0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3, + 0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7, 0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB, + 0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF, 0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3, + 0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6, 0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA, + 0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE, 0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2, + 0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6, 0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA, + 0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE, 0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2, + 0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6, 0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA, + 0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE, 0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2, + 0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6, 0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA, + 0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE, 0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2, + 0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6, 0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA, + 0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE, 0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856, + 0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A, 0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E, + 0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862, 0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866, + 0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A, 0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E, + 0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872, 0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876, + 0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A, 0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E, + 0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883, 0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887, + 0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6, 0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B, + 0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0, 0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E, + 0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE, 0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1, + 0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9, 0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5, + 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF, + 0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895, + 0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943, 0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947, + 0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3, 0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7, + 0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB, 0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF, + 0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3, 0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7, + 0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB, 0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF, + 0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3, 0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7, + 0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB, 0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF, + 0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3, 0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7, + 0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB, 0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF, + 0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3, 0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7, + 0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB, 0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF, + 0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3, 0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967, + 0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4, 0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8, + 0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC, 0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0, + 0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4, 0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8, + 0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC, 0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0, + 0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4, 0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8, + 0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC, 0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0, + 0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4, 0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8, + 0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC, 0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0, + 0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4, 0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8, + 0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC, 0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0, + 0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4, 0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963, + 0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7, 0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB, + 0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF, 0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3, + 0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7, 0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB, + 0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF, 0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3, + 0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7, 0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6, + 0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA, 0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE, + 0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B, 0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F, + 0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953, 0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140, + 0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143, 0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF, + 0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB, 0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145, + 0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0, 0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5, + 0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9, 0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA, + 0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B, 0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6, + 0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D, 0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE, + 0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC, 0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA, + 0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9, 0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156, + 0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158, 0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159, + 0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5, 0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9, + 0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4, 0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D, + 0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2, 0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F, + 0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9, 0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165, + 0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169, 0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B, + 0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E, 0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172, + 0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC, 0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179, + 0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB, 0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E, + 0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA, 0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5, + 0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181, 0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7, + 0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186, 0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA, + 0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0, 0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188, + 0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1, 0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7, + 0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D, 0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB, + 0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193, 0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC, + 0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD, 0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1, + 0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3, 0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198, + 0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB, 0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199, + 0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0, 0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D, + 0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E, 0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7, + 0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2, 0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9, + 0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE, 0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8, + 0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA, 0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC, + 0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0, 0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1, + 0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF, 0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5, + 0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9, 0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1, + 0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1, 0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3, + 0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7, 0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1, + 0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2, 0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3, + 0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6, 0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5, + 0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9, 0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD, + 0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB, 0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3, + 0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD, 0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6, + 0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8, 0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD, + 0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA, 0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA, + 0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB, 0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD, + 0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0, 0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2, + 0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5, 0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7, + 0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB, 0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB, + 0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED, 0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF, + 0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1, 0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3, + 0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6, 0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9, + 0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB, 0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE, + 0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC, 0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD, + 0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA, 0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245, + 0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248, 0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C, + 0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250, 0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253, + 0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254, 0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1, + 0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE, 0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B, + 0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F, 0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5, + 0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1, 0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263, + 0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1, 0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3, + 0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE, 0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A, + 0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D, 0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3, + 0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2, 0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276, + 0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A, 0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E, + 0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281, 0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9, + 0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286, 0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0, + 0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A, 0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C, + 0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB, 0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF, + 0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0, 0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294, + 0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298, 0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE, + 0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3, 0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1, + 0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4, 0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6, + 0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB, 0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB, + 0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE, 0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6, + 0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4, 0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8, + 0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB, 0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF, + 0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2, 0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6, + 0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC, 0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC, + 0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7, 0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0, + 0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3, 0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6, + 0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9, 0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD, + 0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1, 0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5, + 0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9, 0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED, + 0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF, 0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0, + 0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3, 0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1, + 0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA, 0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1, + 0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341, 0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345, + 0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349, 0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D, + 0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351, 0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354, + 0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2, 0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5, + 0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E, 0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362, + 0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6, 0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368, + 0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7, 0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D, + 0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F, 0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373, + 0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376, 0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A, + 0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3, 0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381, + 0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384, 0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5, + 0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B, 0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F, + 0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393, 0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396, + 0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A, 0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E, + 0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2, 0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6, + 0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA, 0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE, + 0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2, 0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3, + 0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7, 0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5, + 0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7, 0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA, + 0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0, 0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3, + 0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1, 0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4, + 0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7, 0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA, + 0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2, 0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC, + 0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4, 0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD, + 0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE, 0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7, + 0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2, 0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4, + 0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6, 0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0, + 0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2, 0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD, + 0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF, 0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3, + 0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3, 0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7, + 0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9, 0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5, + 0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1, 0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED, + 0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE, 0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1, + 0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC, 0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5, + 0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7, 0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9, + 0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD, 0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442, + 0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444, 0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446, + 0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449, 0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D, + 0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F, 0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451, + 0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7, 0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6, + 0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454, 0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6, + 0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6, 0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF, + 0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8, 0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE, + 0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE, 0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5, + 0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460, 0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463, + 0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466, 0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468, + 0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE, 0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C, + 0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6, 0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC, + 0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470, 0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1, + 0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473, 0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7, + 0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478, 0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A, + 0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA, 0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481, + 0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE, 0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486, + 0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489, 0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4, + 0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E, 0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE, + 0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494, 0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498, + 0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B, 0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3, + 0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0, 0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3, + 0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7, 0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA, + 0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD, 0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1, + 0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC, 0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD, + 0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5, 0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC, + 0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7, 0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2, + 0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC, 0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0, + 0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0, 0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6, + 0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9, 0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB, + 0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE, 0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5, + 0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3, 0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6, + 0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA, 0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD, + 0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0, 0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4, + 0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8, 0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB, + 0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF, 0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7, + 0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4, 0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6, + 0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2, 0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB, + 0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE, 0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541, + 0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF, 0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE, + 0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547, 0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549, + 0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0, 0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB, + 0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1, 0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555, + 0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559, 0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8, + 0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2, 0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F, + 0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561, 0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB, + 0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA, 0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4, + 0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4, 0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9, + 0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5, 0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC, + 0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4, 0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D, + 0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4, 0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570, + 0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571, 0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1, + 0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576, 0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7, + 0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA, 0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C, + 0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D, 0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582, + 0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585, 0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1, + 0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A, 0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1, + 0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3, 0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F, + 0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB, 0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596, + 0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC, 0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D, + 0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0, 0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE, + 0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5, 0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0, + 0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7, 0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA, + 0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1, 0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD, + 0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0, 0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2, + 0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED, 0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB, + 0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3, 0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7, + 0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6, 0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5, + 0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6, 0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9, + 0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA, 0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5, + 0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3, 0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8, + 0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9, 0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0, + 0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC, 0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2, + 0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1, 0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5, + 0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1, 0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5, + 0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8, 0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA, + 0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1, 0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE, + 0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4, 0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6, + 0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5, 0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC, + 0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF, 0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8, + 0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA, 0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8, + 0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF, 0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2, + 0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6, 0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA, + 0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE, 0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB, + 0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC, 0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6, + 0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8, 0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4, + 0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC, 0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4, + 0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7, 0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB, + 0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB, 0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640, + 0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7, 0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4, + 0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642, 0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644, + 0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646, 0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649, + 0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B, 0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3, + 0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF, 0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E, + 0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5, 0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5, + 0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650, 0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1, + 0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8, 0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655, + 0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6, 0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4, + 0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8, 0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC, + 0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F, 0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8, + 0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664, 0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666, + 0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4, 0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B, + 0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F, 0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670, + 0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673, 0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677, + 0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A, 0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF, + 0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E, 0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4, + 0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB, 0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684, + 0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687, 0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A, + 0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9, 0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E, + 0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC, 0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1, + 0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695, 0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698, + 0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2, 0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E, + 0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1, 0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4, + 0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2, 0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE, + 0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6, 0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC, + 0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4, 0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0, + 0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1, 0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9, + 0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4, 0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0, + 0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7, 0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9, + 0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC, 0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE, + 0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0, 0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3, + 0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7, 0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA, + 0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE, 0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1, + 0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3, 0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5, + 0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7, 0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA, + 0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC, 0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF, + 0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1, 0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA, + 0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2, 0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8, + 0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA, 0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC, + 0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2, 0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA, + 0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0, 0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7, + 0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4, 0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7, + 0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5, 0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB, + 0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740, 0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742, + 0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2, 0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747, + 0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B, 0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E, + 0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF, 0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753, + 0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755, 0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758, + 0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A, 0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0, + 0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB, 0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761, + 0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764, 0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767, + 0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B, 0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F, + 0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD, 0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774, + 0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777, 0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778, + 0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B, 0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE, + 0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782, 0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB, + 0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785, 0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788, + 0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1, 0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F, + 0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791, 0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795, + 0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3, 0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B, + 0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF, 0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1, + 0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4, 0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8, + 0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC, 0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0, + 0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3, 0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7, + 0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB, 0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE, + 0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2, 0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5, + 0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8, 0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC, + 0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0, 0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2, + 0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7, 0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB, + 0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE, 0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4, + 0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8, 0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5, + 0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4, 0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8, + 0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA, 0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC, + 0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE, 0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC, + 0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC, 0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5, + 0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2, 0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5, + 0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB, 0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840, + 0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844, 0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848, + 0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B, 0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E, + 0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851, 0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9, + 0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC, 0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855, + 0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858, 0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1, + 0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8, 0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0, + 0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862, 0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB, + 0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2, 0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866, + 0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A, 0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1, + 0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB, 0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D, + 0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9, 0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA, + 0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872, 0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875, + 0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9, 0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A, + 0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C, 0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9, + 0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4, 0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884, + 0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886, 0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD, + 0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C, 0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890, + 0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893, 0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8, + 0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1, 0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897, + 0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5, 0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE, + 0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E, 0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1, + 0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5, 0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1, + 0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB, 0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF, + 0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7, 0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8, + 0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5, 0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6, + 0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9, 0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB, + 0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE, 0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2, + 0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5, 0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8, + 0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB, 0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9, + 0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF, 0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3, + 0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1, 0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7, + 0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9, 0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC, + 0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF, 0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2, + 0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6, 0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7, + 0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA, 0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0, + 0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1, 0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4, + 0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7, 0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB, + 0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940, 0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944, + 0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947, 0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B, + 0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D, 0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950, + 0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953, 0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956, + 0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB, 0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D, + 0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960, 0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964, + 0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966, 0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A, + 0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E, 0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972, + 0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3, 0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977, + 0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979, 0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C, + 0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981, 0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA, + 0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987, 0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE, + 0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6, 0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F, + 0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993, 0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995, + 0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999, 0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D, + 0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1, 0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5, + 0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8, 0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB, + 0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE, 0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2, + 0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6, 0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9, + 0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC, 0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0, + 0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4, 0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8, + 0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB, 0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF, + 0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3, 0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3, + 0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8, 0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8, + 0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC, 0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA, + 0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2, 0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5, + 0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8, 0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB, + 0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2, 0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0, + 0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1, 0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4, + 0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6, 0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB, + 0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB, 0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA, + 0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD, 0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1, + 0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41, 0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC, + 0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46, 0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47, + 0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC, 0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B, + 0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1, 0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9, + 0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51, 0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD, + 0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56, 0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A, + 0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E, 0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62, + 0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC, 0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65, + 0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68, 0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7, + 0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1, 0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1, + 0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F, 0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA, + 0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD, 0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76, + 0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4, 0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D, + 0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E, 0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD, + 0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD, 0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7, + 0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88, 0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B, + 0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA, 0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91, + 0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7, 0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2, + 0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A, 0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6, + 0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D, 0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6, + 0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0, 0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4, + 0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6, 0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9, + 0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC, 0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0, + 0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4, 0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7, + 0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA, 0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC, + 0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC, 0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD, + 0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0, 0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3, + 0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6, 0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9, + 0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC, 0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE, + 0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0, 0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3, + 0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7, 0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4, + 0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2, 0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF, + 0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2, 0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5, + 0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5, 0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB, + 0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE, 0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2, + 0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5, 0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9, + 0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC, 0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE, + 0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44, 0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7, + 0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A, 0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E, + 0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4, 0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4, + 0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55, 0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58, + 0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C, 0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60, + 0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64, 0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD, + 0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B, 0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4, + 0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71, 0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75, + 0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79, 0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1, + 0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81, 0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7, + 0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86, 0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89, + 0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5, 0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9, + 0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92, 0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95, + 0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98, 0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8, + 0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE, 0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0, + 0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3, 0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5, + 0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF, 0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA, + 0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD, 0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0, + 0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4, 0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8, + 0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC, 0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0, + 0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4, 0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7, + 0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB, 0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF, + 0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4, 0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5, + 0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9, 0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD, + 0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1, 0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5, + 0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9, 0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5, + 0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF, 0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2, + 0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6, 0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9, + 0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD, 0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42, + 0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46, 0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48, + 0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49, 0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA, + 0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A, 0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF, + 0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7, 0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF, + 0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51, 0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53, + 0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55, 0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6, + 0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B, 0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D, + 0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E, 0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F, + 0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61, 0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64, + 0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66, 0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8, + 0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5, 0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD, + 0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2, 0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC, + 0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D, 0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70, + 0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2, 0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72, + 0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6, 0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5, + 0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC, 0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A, + 0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D, 0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE, + 0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83, 0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87, + 0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF, 0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B, + 0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D, 0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90, + 0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC, 0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96, + 0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A, 0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2, + 0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D, 0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F, + 0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB, 0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0, + 0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7, 0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9, + 0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2, 0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0, + 0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE, 0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC, + 0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3, 0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6, + 0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9, 0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC, + 0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF, 0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF, + 0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2, 0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3, + 0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3, 0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC, + 0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA, 0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7, + 0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA, 0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD, + 0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4, 0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2, + 0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0, 0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7, + 0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8, 0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC, + 0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0, 0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8, + 0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6, 0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1, + 0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB, 0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE, + 0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0, 0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2, + 0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB, 0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0, + 0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6, 0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3, + 0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC, 0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40, + 0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41, 0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44, + 0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46, 0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48, + 0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B, 0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D, + 0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50, 0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54, + 0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57, 0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC, + 0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E, 0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61, + 0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65, 0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68, + 0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD, 0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8, + 0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E, 0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71, + 0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75, 0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79, + 0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C, 0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0, + 0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7, 0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85, + 0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9, 0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C, + 0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2, 0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92, + 0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6, 0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98, + 0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3, 0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C, + 0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4, 0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2, + 0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5, 0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9, + 0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA, 0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF, + 0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3, 0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3, + 0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7, 0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB, + 0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF, 0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2, + 0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4, 0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8, + 0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC, 0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF, + 0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1, 0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4, + 0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7, 0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB, + 0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF, 0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6, + 0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6, 0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA, + 0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE, 0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2, + 0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6, 0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9, + 0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC, 0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41, + 0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45, 0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49, + 0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D, 0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51, + 0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55, 0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58, + 0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C, 0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60, + 0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63, 0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67, + 0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A, 0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E, + 0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72, 0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76, + 0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD, 0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2, + 0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3, 0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C, + 0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE, 0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1, + 0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82, 0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85, + 0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED, 0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0, + 0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB, 0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D, + 0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90, 0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91, + 0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB, 0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3, + 0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94, 0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98, + 0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8, 0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E, + 0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF, 0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3, + 0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7, 0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9, + 0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA, 0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD, + 0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF, 0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3, + 0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6, 0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA, + 0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC, 0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0, + 0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5, 0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1, + 0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8, 0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC, + 0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0, 0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9, + 0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2, 0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB, + 0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7, 0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9, + 0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC, 0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2, + 0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0, 0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1, + 0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2, 0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD, + 0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3, 0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6, + 0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8, 0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB, + 0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE, 0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2, + 0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC, 0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4, + 0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7, 0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB, + 0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40, 0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8, + 0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46, 0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA, + 0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE, 0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E, + 0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51, 0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55, + 0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59, 0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE, + 0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F, 0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63, + 0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3, 0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8, + 0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3, 0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC, + 0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C, 0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7, + 0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71, 0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73, + 0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75, 0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77, + 0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A, 0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C, + 0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2, 0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2, + 0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83, 0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85, + 0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89, 0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF, + 0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E, 0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91, + 0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95, 0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99, + 0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D, 0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9, + 0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8, 0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2, + 0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5, 0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE, + 0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5, 0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB, + 0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD, 0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF, + 0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2, 0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4, + 0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6, 0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE, + 0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9, 0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2, + 0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB, 0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD, + 0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0, 0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1, + 0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4, 0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7, + 0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB, 0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD, + 0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2, 0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3, + 0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6, 0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9, + 0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB, 0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF, + 0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4, 0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2, + 0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4, 0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF, + 0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2, 0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8, + 0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB, 0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED, + 0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0, 0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC, + 0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5, 0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6, + 0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9, 0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC, + 0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9, 0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB, + 0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB, 0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7, + 0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5, 0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD, + 0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0, 0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049, + 0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A, 0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C, + 0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1, 0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6, + 0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051, 0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054, + 0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057, 0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B, + 0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D, 0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE, + 0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061, 0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065, + 0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067, 0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3, + 0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C, 0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3, + 0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071, 0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6, + 0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076, 0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1, + 0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077, 0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079, + 0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1, 0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD, + 0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D, 0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081, + 0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083, 0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086, + 0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088, 0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8, + 0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3, 0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4, + 0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092, 0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094, + 0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3, 0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099, + 0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A, 0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF, + 0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E, 0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1, + 0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3, 0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7, + 0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0, 0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA, + 0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF, 0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2, + 0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5, 0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1, + 0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9, 0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB, + 0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB, 0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF, + 0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC, 0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1, + 0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC, 0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA, + 0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8, 0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA, + 0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9, 0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF, + 0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9, 0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4, + 0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7, 0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE, + 0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE, 0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0, + 0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4, 0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4, + 0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7, 0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB, + 0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF, 0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3, + 0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7, 0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA, + 0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE, 0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB, + 0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7, 0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146, + 0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149, 0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D, + 0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150, 0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD, + 0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157, 0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159, + 0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D, 0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160, + 0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163, 0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166, + 0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A, 0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E, + 0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172, 0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176, + 0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7, 0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C, + 0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180, 0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184, + 0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187, 0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B, + 0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F, 0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190, + 0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193, 0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197, + 0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B, 0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E, + 0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6, 0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE, + 0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8, 0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3, + 0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD, 0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1, + 0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2, 0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6, + 0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA, 0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE, + 0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3, 0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5, + 0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9, 0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD, + 0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0, 0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4, + 0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8, 0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB, + 0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0, 0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC, + 0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6, 0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4, + 0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2, 0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD, + 0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6, 0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB, + 0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9, 0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8, + 0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE, 0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2, + 0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4, 0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7, + 0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5, 0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA, + 0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD, 0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE, + 0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA, 0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7, + 0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243, 0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246, + 0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249, 0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D, + 0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4, 0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1, + 0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7, 0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252, + 0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6, 0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257, + 0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2, 0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B, + 0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E, 0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1, + 0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264, 0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3, + 0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6, 0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7, + 0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B, 0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0, + 0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D, 0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270, + 0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272, 0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275, + 0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278, 0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B, + 0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C, 0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7, + 0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0, 0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4, + 0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0, 0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC, + 0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF, 0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5, + 0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286, 0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3, + 0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9, 0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A, + 0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7, 0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D, + 0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9, 0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291, + 0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0, 0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2, + 0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297, 0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298, + 0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6, 0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E, + 0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA, 0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF, + 0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2, 0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8, + 0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6, 0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2, + 0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB, 0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD, + 0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1, 0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6, + 0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6, 0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6, + 0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6, 0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD, + 0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3, 0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF, + 0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2, 0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6, + 0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC, 0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB, + 0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD, 0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF, + 0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD, 0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4, + 0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7, 0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0, + 0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC, 0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0, + 0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2, 0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5, + 0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1, 0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5, + 0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4, 0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB, + 0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF, 0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD, + 0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3, 0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB, + 0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7, 0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7, + 0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9, 0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4, + 0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2, 0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341, + 0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1, 0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346, + 0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF, 0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5, + 0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE, 0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350, + 0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE, 0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355, + 0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358, 0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE, + 0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D, 0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9, + 0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE, 0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365, + 0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368, 0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7, + 0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B, 0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F, + 0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371, 0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373, + 0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375, 0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379, + 0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3, 0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C, + 0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9, 0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2, + 0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385, 0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389, + 0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C, 0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF, + 0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392, 0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394, + 0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA, 0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF, + 0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A, 0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0, + 0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0, 0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3, + 0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB, 0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA, + 0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE, 0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0, + 0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3, 0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7, + 0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB, 0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1, + 0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0, 0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC, + 0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5, 0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8, + 0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC, 0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6, + 0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE, 0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3, + 0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2, 0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA, + 0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD, 0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0, + 0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9, 0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4, + 0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7, 0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5, + 0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB, 0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE, + 0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0, 0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4, + 0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6, 0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC, + 0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC, 0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE, + 0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3, 0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA, + 0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1, 0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B, + 0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F, 0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453, + 0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457, 0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B, + 0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F, 0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462, + 0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466, 0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469, + 0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D, 0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC, + 0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474, 0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477, + 0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B, 0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480, + 0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483, 0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487, + 0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD, 0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C, + 0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5, 0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F, + 0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5, 0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494, + 0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497, 0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499, + 0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C, 0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E, + 0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD, 0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3, + 0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8, 0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2, + 0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8, 0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD, + 0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF, 0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3, + 0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4, 0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7, + 0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB, 0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF, + 0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3, 0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6, + 0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8, 0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA, + 0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD, 0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF, + 0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1, 0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3, + 0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5, 0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7, + 0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9, 0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB, + 0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF, 0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2, + 0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4, 0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7, + 0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7, 0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB, + 0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB, 0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC, + 0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD, 0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4, + 0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8, 0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8, + 0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9, 0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD, + 0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8, 0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540, + 0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1, 0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA, + 0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549, 0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA, + 0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5, 0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB, + 0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7, 0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555, + 0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556, 0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559, + 0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C, 0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E, + 0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561, 0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563, + 0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566, 0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568, + 0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6, 0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D, + 0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4, 0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572, + 0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575, 0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579, + 0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B, 0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9, + 0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD, 0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED, + 0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584, 0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586, + 0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE, 0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B, + 0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5, 0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590, + 0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7, 0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7, + 0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0, 0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD, + 0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D, 0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0, + 0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3, 0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6, + 0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF, 0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC, + 0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF, 0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3, + 0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7, 0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9, + 0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA, 0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0, + 0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3, 0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6, + 0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5, 0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD, + 0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1, 0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5, + 0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9, 0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD, + 0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1, 0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4, + 0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5, 0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9, + 0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8, 0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF, + 0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3, 0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA, + 0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7, 0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9, + 0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8, 0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD, + 0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642, 0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3, + 0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645, 0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648, + 0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A, 0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D, + 0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F, 0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652, + 0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC, 0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4, + 0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658, 0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A, + 0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C, 0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA, + 0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662, 0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3, + 0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB, 0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668, + 0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE, 0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B, + 0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8, 0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671, + 0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD, 0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674, + 0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677, 0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2, + 0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B, 0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD, + 0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E, 0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682, + 0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9, 0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686, + 0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689, 0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B, + 0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E, 0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691, + 0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694, 0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6, + 0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8, 0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0, + 0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B, 0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9, + 0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E, 0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0, + 0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC, 0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3, + 0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7, 0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA, + 0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC, 0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0, + 0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4, 0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2, + 0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6, 0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6, + 0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5, 0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC, + 0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD, 0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0, + 0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3, 0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4, + 0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6, 0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA, + 0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD, 0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF, + 0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2, 0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0, + 0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD, 0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5, + 0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC, 0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA, + 0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD, 0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0, + 0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4, 0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA, + 0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA, 0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0, + 0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0, 0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1, + 0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF, 0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0, + 0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2, 0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0, + 0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4, 0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8, + 0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9, 0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD, + 0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742, 0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5, + 0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB, 0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744, + 0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747, 0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B, + 0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0, 0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750, + 0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754, 0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757, + 0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0, 0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C, + 0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760, 0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763, + 0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766, 0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769, + 0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D, 0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2, + 0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE, 0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775, + 0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778, 0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A, + 0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C, 0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781, + 0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785, 0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9, + 0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B, 0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E, + 0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790, 0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4, + 0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796, 0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF, + 0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C, 0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F, + 0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2, 0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6, + 0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD, 0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB, + 0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE, 0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7, + 0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3, 0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6, + 0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9, 0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD, + 0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5, 0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7, + 0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4, 0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8, + 0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC, 0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE, + 0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1, 0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5, + 0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8, 0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB, + 0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE, 0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1, + 0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4, 0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB, + 0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA, 0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE, + 0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2, 0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6, + 0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9, 0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE, + 0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3, 0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841, + 0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8, 0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847, + 0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA, 0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C, + 0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850, 0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851, + 0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854, 0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5, + 0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC, 0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859, + 0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C, 0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860, + 0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862, 0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865, + 0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867, 0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B, + 0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F, 0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871, + 0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873, 0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876, + 0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879, 0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C, + 0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880, 0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883, + 0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887, 0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3, + 0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6, 0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F, + 0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892, 0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896, + 0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899, 0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B, + 0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F, 0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3, + 0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6, 0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE, + 0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD, 0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1, + 0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4, 0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7, + 0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB, 0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE, + 0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2, 0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6, + 0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA, 0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC, + 0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0, 0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2, + 0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6, 0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1, + 0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC, 0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE, + 0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1, 0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5, + 0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0, 0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB, + 0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE, 0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1, + 0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5, 0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8, + 0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC, 0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE, + 0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942, 0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945, + 0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948, 0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C, + 0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950, 0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953, + 0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957, 0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A, + 0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D, 0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960, + 0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963, 0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967, + 0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5, 0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C, + 0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970, 0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973, + 0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977, 0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A, + 0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E, 0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982, + 0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984, 0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988, + 0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C, 0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990, + 0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994, 0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998, + 0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C, 0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0, + 0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4, 0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8, + 0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC, 0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0, + 0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4, 0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8, + 0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC, 0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0, + 0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4, 0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8, + 0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC, 0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0, + 0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4, 0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8, + 0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC, 0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0, + 0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4, 0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8, + 0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC, 0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0, + 0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4, 0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6, + 0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7, 0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA, + 0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE, 0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB, + 0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46, 0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB, + 0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE, 0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E, + 0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7, 0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52, + 0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55, 0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59, + 0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D, 0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60, + 0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64, 0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9, + 0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4, 0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1, + 0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D, 0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71, + 0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75, 0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78, + 0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A, 0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3, + 0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9, 0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2, + 0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81, 0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6, + 0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3, 0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9, + 0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C, 0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F, + 0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93, 0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC, + 0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A, 0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E, + 0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F, 0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2, + 0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6, 0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1, + 0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA, 0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE, + 0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0, 0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE, + 0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1, 0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4, + 0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7, 0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA, + 0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE, 0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4, + 0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4, 0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7, + 0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9, 0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC, + 0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF, 0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3, + 0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB, 0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8, + 0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB, 0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC, + 0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA, 0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0, + 0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0, 0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2, + 0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4, 0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4, + 0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA, 0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5, + 0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9, 0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC, + 0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF, 0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3, + 0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0, 0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2, + 0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8, 0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB, + 0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD, 0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41, + 0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF, 0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42, + 0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45, 0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4, + 0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A, 0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3, + 0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB, 0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51, + 0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA, 0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA, + 0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC, 0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58, + 0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B, 0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D, + 0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F, 0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62, + 0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65, 0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67, + 0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9, 0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6, + 0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA, 0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5, + 0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E, 0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70, + 0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4, 0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73, + 0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75, 0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4, + 0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A, 0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D, + 0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7, 0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81, + 0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2, 0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8, + 0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86, 0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1, + 0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA, 0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B, + 0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4, 0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8, + 0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE, 0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90, + 0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93, 0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96, + 0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9, 0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7, + 0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E, 0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE, + 0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4, 0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5, + 0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8, 0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9, + 0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC, 0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE, + 0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0, 0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3, + 0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9, 0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6, + 0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC, 0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7, + 0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3, 0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0, + 0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC, 0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3, + 0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7, 0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3, + 0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6, 0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB, + 0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1, 0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD, + 0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0, 0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2, + 0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5, 0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF, + 0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB, 0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD, + 0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1, 0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2, + 0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3, 0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7, + 0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5, 0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9, + 0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3, 0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2, + 0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC, 0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA, + 0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1, 0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4, + 0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8, 0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA, + 0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD, 0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE, + 0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41, 0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44, + 0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7, 0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49, + 0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1, 0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D, + 0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6, 0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53, + 0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4, 0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57, + 0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A, 0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C, + 0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E, 0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62, + 0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65, 0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8, + 0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2, 0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B, + 0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9, 0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE, + 0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72, 0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74, + 0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75, 0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78, + 0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A, 0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6, + 0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80, 0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC, + 0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86, 0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A, + 0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C, 0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90, + 0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF, 0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96, + 0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE, 0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A, + 0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D, 0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0, + 0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4, 0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8, + 0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE, 0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE, + 0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2, 0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6, + 0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5, 0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC, + 0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3, 0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0, + 0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4, 0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6, + 0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA, 0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD, + 0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0, 0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7, + 0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5, 0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA, + 0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB, 0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1, + 0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC, 0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7, + 0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2, 0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8, + 0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8, 0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB, + 0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE, 0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0, + 0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1, 0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6, + 0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD, 0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE, + 0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0, 0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9, + 0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD, 0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42, + 0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45, 0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48, + 0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C, 0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF, + 0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1, 0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55, + 0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59, 0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C, + 0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D, 0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61, + 0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65, 0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68, + 0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B, 0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4, + 0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F, 0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71, + 0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1, 0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77, + 0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA, 0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E, + 0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB, 0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85, + 0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87, 0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B, + 0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F, 0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92, + 0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA, 0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA, + 0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA, 0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E, + 0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1, 0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB, + 0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6, 0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD, + 0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB, 0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF, + 0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2, 0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4, + 0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC, 0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9, + 0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD, 0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1, + 0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4, 0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7, + 0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB, 0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE, + 0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2, 0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6, + 0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4, 0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB, + 0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF, 0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5, + 0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5, 0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8, + 0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC, 0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4, + 0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2, 0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6, + 0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8, 0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB, + 0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40, 0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44, + 0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7, 0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A, + 0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E, 0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52, + 0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56, 0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A, + 0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E, 0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62, + 0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66, 0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69, + 0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D, 0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB, + 0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73, 0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77, + 0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A, 0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E, + 0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83, 0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87, + 0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A, 0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D, + 0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91, 0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95, + 0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99, 0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D, + 0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0, 0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3, + 0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7, 0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB, + 0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1, 0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2, + 0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6, 0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA, + 0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB, 0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD, + 0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE, 0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2, + 0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6, 0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6, + 0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9, 0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6, + 0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7, 0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4, + 0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0, 0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5, + 0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7, 0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB, + 0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF, 0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3, + 0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA, 0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5, + 0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8, 0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9, + 0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA, 0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3, + 0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE, 0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8, + 0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4, 0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8, + 0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC, 0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE, + 0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42, 0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45, + 0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3, 0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48, + 0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49, 0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C, + 0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50, 0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52, + 0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55, 0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59, + 0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D, 0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8, + 0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63, 0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66, + 0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB, 0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9, + 0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C, 0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70, + 0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9, 0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77, + 0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B, 0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C, + 0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB, 0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84, + 0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88, 0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C, + 0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F, 0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3, + 0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5, 0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98, + 0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C, 0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0, + 0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7, 0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6, + 0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3, 0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA, + 0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3, 0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2, + 0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3, 0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5, + 0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8, 0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC, + 0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF, 0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC, + 0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6, 0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9, + 0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC, 0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE, + 0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2, 0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4, + 0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8, 0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB, + 0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE, 0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2, + 0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4, 0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7, + 0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB, 0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF, + 0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2, 0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6, + 0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7, 0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD, + 0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040, 0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044, + 0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048, 0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B, + 0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E, 0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051, + 0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6, 0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058, + 0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C, 0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F, + 0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063, 0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067, + 0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC, 0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E, + 0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072, 0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076, + 0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A, 0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E, + 0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082, 0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086, + 0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A, 0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6, + 0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F, 0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091, + 0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8, 0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094, + 0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096, 0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099, + 0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D, 0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F, + 0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1, 0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA, + 0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB, 0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA, + 0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC, 0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE, + 0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3, 0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2, + 0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0, 0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC, + 0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA, 0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE, + 0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5, 0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0, + 0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3, 0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF, + 0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8, 0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB, + 0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE, 0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2, + 0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6, 0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9, + 0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD, 0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1, + 0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3, 0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5, + 0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4, 0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8, + 0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC, 0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1, + 0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0, 0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3, + 0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2, 0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4, + 0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB, 0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD, + 0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC, 0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43, + 0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47, 0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49, + 0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8, 0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8, + 0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C, 0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE, + 0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F, 0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52, + 0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55, 0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5, + 0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4, 0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F, + 0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE, 0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63, + 0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6, 0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9, + 0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68, 0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED, + 0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7, 0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E, + 0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71, 0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72, + 0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB, 0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78, + 0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C, 0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81, + 0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84, 0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1, + 0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A, 0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D, + 0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91, 0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94, + 0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98, 0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C, + 0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E, 0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40, + 0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44, 0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48, + 0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5, 0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F, + 0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52, 0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54, + 0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0, 0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59, + 0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1, 0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60, + 0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63, 0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3, + 0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69, 0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C, + 0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2, 0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1, + 0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72, 0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4, + 0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77, 0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6, + 0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D, 0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA, + 0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82, 0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83, + 0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87, 0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A, + 0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3, 0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90, + 0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93, 0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95, + 0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98, 0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5, + 0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F, 0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42, + 0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46, 0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A, + 0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED, 0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0, + 0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51, 0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53, + 0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57, 0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2, + 0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D, 0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1, + 0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9, 0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7, + 0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD, 0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69, + 0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3, 0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D, + 0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70, 0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73, + 0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77, 0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B, + 0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80, 0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84, + 0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87, 0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7, + 0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0, 0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C, + 0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90, 0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94, + 0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97, 0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A, + 0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE, 0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0, + 0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA, 0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44, + 0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47, 0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A, + 0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC, 0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F, + 0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53, 0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57, + 0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1, 0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D, + 0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61, 0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62, + 0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66, 0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A, + 0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E, 0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7, + 0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75, 0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79, + 0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D, 0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82, + 0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86, 0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6, + 0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D, 0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91, + 0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC, 0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0, + 0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF, 0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A, + 0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD, 0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0, + 0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF, 0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44, + 0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48, 0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B, + 0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E, 0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52, + 0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55, 0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57, + 0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A, 0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5, + 0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E, 0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61, + 0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64, 0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66, + 0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67, 0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7, + 0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69, 0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE, + 0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE, 0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F, + 0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72, 0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75, + 0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0, 0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79, + 0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C, 0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE, + 0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81, 0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85, + 0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8, 0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC, + 0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E, 0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4, + 0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94, 0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96, + 0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A, 0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D, + 0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE, 0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42, + 0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45, 0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA, + 0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC, 0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE, + 0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C, 0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D, + 0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E, 0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52, + 0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF, 0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3, + 0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54, 0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56, + 0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2, 0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8, + 0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B, 0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC, + 0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E, 0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7, + 0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9, 0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65, + 0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6, 0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1, + 0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED, 0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE, + 0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F, 0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71, + 0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74, 0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77, + 0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A, 0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B, + 0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D, 0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA, + 0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84, 0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87, + 0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A, 0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B, + 0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E, 0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3, + 0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD, 0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1, + 0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94, 0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97, + 0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98, 0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B, + 0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB, 0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F, + 0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041, 0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045, + 0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047, 0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B, + 0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1, 0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051, + 0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE, 0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057, + 0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A, 0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E, + 0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061, 0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064, + 0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068, 0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B, + 0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9, 0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED, + 0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4, 0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073, + 0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8, 0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078, + 0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE, 0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D, + 0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082, 0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086, + 0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089, 0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D, + 0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4, 0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4, + 0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095, 0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099, + 0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D, 0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB, + 0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8, 0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6, + 0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB, 0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0, + 0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7, 0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148, + 0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B, 0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E, + 0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151, 0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155, + 0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF, 0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4, + 0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C, 0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E, + 0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC, 0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163, + 0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166, 0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167, + 0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169, 0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D, + 0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171, 0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2, + 0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177, 0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3, + 0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6, 0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D, + 0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181, 0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184, + 0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4, 0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7, + 0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A, 0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C, + 0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F, 0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192, + 0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196, 0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198, + 0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C, 0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD, + 0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241, 0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1, + 0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0, 0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247, + 0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249, 0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D, + 0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251, 0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254, + 0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA, 0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258, + 0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A, 0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E, + 0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9, 0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7, + 0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265, 0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269, + 0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D, 0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB, + 0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271, 0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9, + 0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275, 0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278, + 0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A, 0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E, + 0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281, 0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284, + 0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288, 0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C, + 0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F, 0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293, + 0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297, 0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A, + 0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C, 0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8, + 0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340, 0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342, + 0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB, 0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346, + 0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6, 0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B, + 0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF, 0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0, + 0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351, 0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354, + 0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356, 0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8, + 0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9, 0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2, + 0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D, 0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360, + 0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE, 0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363, + 0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365, 0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368, + 0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B, 0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2, + 0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9, 0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F, + 0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372, 0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375, + 0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA, 0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8, + 0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC, 0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E, + 0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382, 0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386, + 0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A, 0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2, + 0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7, 0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391, + 0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395, 0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398, + 0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B, 0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F, + 0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442, 0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444, + 0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9, 0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448, + 0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B, 0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5, + 0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E, 0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450, + 0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452, 0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455, + 0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459, 0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA, + 0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C, 0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F, + 0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB, 0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465, + 0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468, 0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA, + 0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D, 0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470, + 0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472, 0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475, + 0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479, 0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D, + 0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482, 0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485, + 0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488, 0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1, + 0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E, 0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7, + 0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494, 0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497, + 0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A, 0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E, + 0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541, 0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545, + 0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548, 0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C, + 0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6, 0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553, + 0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556, 0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A, + 0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E, 0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562, + 0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565, 0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE, + 0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7, 0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B, + 0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC, 0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570, + 0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574, 0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578, + 0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6, 0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1, + 0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1, 0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2, + 0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581, 0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583, + 0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586, 0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589, + 0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D, 0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7, + 0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592, 0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594, + 0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596, 0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9, + 0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D, 0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0, + 0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643, 0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA, + 0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A, 0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E, + 0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652, 0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655, + 0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659, 0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D, + 0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660, 0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE, + 0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC, 0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665, + 0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1, 0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A, + 0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C, 0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB, + 0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671, 0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674, + 0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678, 0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B, + 0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8, 0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E, + 0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681, 0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683, + 0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687, 0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A, + 0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C, 0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC, + 0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9, 0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694, + 0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0, 0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699, + 0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C, 0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9, + 0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD, 0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743, + 0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746, 0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A, + 0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E, 0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752, + 0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755, 0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757, + 0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758, 0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B, + 0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2, 0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762, + 0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766, 0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769, + 0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D, 0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770, + 0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774, 0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778, + 0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C, 0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781, + 0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785, 0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788, + 0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF, 0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5, + 0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E, 0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F, + 0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9, 0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793, + 0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796, 0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF, + 0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1, 0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C, + 0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E, 0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0, + 0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC, 0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844, + 0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846, 0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A, + 0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D, 0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851, + 0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855, 0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858, + 0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C, 0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860, + 0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863, 0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867, + 0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA, 0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D, + 0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA, 0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872, + 0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5, 0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877, + 0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A, 0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D, + 0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882, 0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3, + 0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887, 0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A, + 0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA, 0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9, + 0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890, 0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892, + 0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894, 0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897, + 0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7, 0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C, + 0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB, 0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE, + 0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0, 0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942, + 0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945, 0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3, + 0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6, 0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D, + 0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950, 0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952, + 0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954, 0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2, + 0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF, 0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9, + 0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A, 0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1, + 0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960, 0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964, + 0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF, 0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2, + 0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C, 0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E, + 0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9, 0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973, + 0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976, 0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A, + 0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D, 0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981, + 0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983, 0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986, + 0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988, 0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE, + 0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5, 0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC, + 0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E, 0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991, + 0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994, 0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997, + 0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B, 0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E, + 0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD, 0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43, + 0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46, 0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49, + 0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C, 0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5, + 0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51, 0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54, + 0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7, 0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8, + 0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA, 0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F, + 0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63, 0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66, + 0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA, 0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C, + 0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70, 0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73, + 0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75, 0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78, + 0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD, 0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80, + 0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84, 0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87, + 0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3, 0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2, + 0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90, 0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94, + 0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98, 0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B, + 0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F, 0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0, + 0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43, 0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47, + 0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A, 0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E, + 0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52, 0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56, + 0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A, 0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E, + 0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62, 0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66, + 0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A, 0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E, + 0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70, 0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74, + 0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75, 0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79, + 0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D, 0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81, + 0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85, 0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3, + 0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A, 0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C, + 0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1, 0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2, + 0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91, 0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0, + 0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8, 0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3, + 0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C, 0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F, + 0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB, 0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42, + 0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45, 0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD, + 0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48, 0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C, + 0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7, 0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50, + 0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53, 0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55, + 0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59, 0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C, + 0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60, 0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63, + 0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67, 0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A, + 0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D, 0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71, + 0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75, 0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9, + 0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C, 0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81, + 0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85, 0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89, + 0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D, 0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7, + 0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93, 0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96, + 0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99, 0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C, + 0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0, 0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43, + 0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47, 0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B, + 0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F, 0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53, + 0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57, 0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B, + 0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F, 0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63, + 0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67, 0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B, + 0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F, 0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73, + 0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5, 0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A, + 0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E, 0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82, + 0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86, 0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A, + 0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E, 0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92, + 0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96, 0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A, + 0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E, 0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41, + 0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45, 0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49, + 0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB, 0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50, + 0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC, 0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57, + 0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B, 0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F, + 0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63, 0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67, + 0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B, 0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F, + 0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73, 0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77, + 0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B, 0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80, + 0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84, 0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88, + 0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C, 0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90, + 0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94, 0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98, + 0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C, 0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0, + 0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43, 0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47, + 0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B, 0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F, + 0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53, 0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57, + 0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B, 0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F, + 0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63, 0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67, + 0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B, 0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F, + 0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73, 0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77, + 0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B, 0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80, + 0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83, 0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86, + 0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A, 0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D, + 0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91, 0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95, + 0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99, 0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D, + 0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040, 0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044, + 0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048, 0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C, + 0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050, 0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054, + 0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058, 0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C, + 0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060, 0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB, + 0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067, 0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B, + 0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F, 0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073, + 0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077, 0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B, + 0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E, 0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC, + 0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC, 0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD, + 0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080, 0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9, + 0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA, 0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4, + 0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3, 0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6, + 0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8, 0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED, + 0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF, 0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE, + 0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084, 0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4, + 0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA, 0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE, + 0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0, 0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7, + 0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2, 0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5, + 0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7, 0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8, + 0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA, 0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC, + 0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2, 0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088, + 0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0, 0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4, + 0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0, 0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF, + 0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A, 0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB, + 0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF, 0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1, + 0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9, 0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8, + 0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE, 0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1, + 0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090, 0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF, + 0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095, 0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099, + 0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D, 0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F, + 0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140, 0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3, + 0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145, 0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5, + 0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A, 0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF, + 0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3, 0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0, + 0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153, 0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156, + 0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0, 0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C, + 0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160, 0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2, + 0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0, 0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169, + 0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C, 0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7, + 0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF, 0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173, + 0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176, 0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179, + 0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D, 0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB, + 0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183, 0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185, + 0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187, 0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189, + 0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C, 0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4, + 0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1, 0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195, + 0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197, 0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A, + 0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E, 0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F, + 0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5, 0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243, + 0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7, 0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248, + 0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B, 0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F, + 0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251, 0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253, + 0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8, 0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257, + 0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258, 0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7, + 0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9, 0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C, + 0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F, 0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC, + 0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE, 0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5, + 0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267, 0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A, + 0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE, 0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D, + 0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F, 0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4, + 0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6, 0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4, + 0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277, 0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8, + 0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D, 0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB, + 0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284, 0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288, + 0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C, 0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF, + 0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292, 0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295, + 0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299, 0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D, + 0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340, 0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342, + 0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1, 0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345, + 0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347, 0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B, + 0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4, 0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7, + 0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350, 0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB, + 0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352, 0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE, + 0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9, 0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD, + 0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359, 0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE, + 0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6, 0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF, + 0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8, 0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361, + 0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5, 0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366, + 0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6, 0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF, + 0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB, 0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D, + 0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F, 0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD, + 0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370, 0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC, + 0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA, 0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7, + 0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375, 0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC, + 0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0, 0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9, + 0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB, 0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF, + 0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1, 0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5, + 0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2, 0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A, + 0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E, 0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392, + 0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395, 0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5, + 0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1, 0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C, + 0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2, 0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442, + 0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3, 0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0, + 0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449, 0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B, + 0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C, 0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB, + 0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452, 0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455, + 0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458, 0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A, + 0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9, 0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E, + 0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461, 0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9, + 0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA, 0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6, + 0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468, 0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2, + 0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E, 0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470, + 0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474, 0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477, + 0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478, 0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C, + 0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2, 0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA, + 0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485, 0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489, + 0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C, 0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF, + 0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492, 0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB, + 0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC, 0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD, + 0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B, 0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F, + 0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542, 0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546, + 0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A, 0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E, + 0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551, 0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4, + 0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555, 0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559, + 0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B, 0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F, + 0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7, 0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9, + 0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF, 0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566, + 0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568, 0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6, + 0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D, 0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571, + 0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8, 0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE, + 0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576, 0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD, + 0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579, 0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A, + 0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0, 0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B, + 0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8, 0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582, + 0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585, 0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587, + 0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A, 0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D, + 0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591, 0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD, + 0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597, 0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A, + 0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E, 0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640, + 0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE, 0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB, + 0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646, 0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5, + 0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC, 0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA, + 0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F, 0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7, + 0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA, 0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2, + 0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657, 0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658, + 0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A, 0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C, + 0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB, 0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE, + 0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7, 0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F, + 0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661, 0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662, + 0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0, 0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667, + 0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A, 0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3, + 0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1, 0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB, + 0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D, 0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F, + 0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA, 0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671, + 0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0, 0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675, + 0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678, 0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A, + 0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D, 0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680, + 0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683, 0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF, + 0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2, 0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686, + 0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5, 0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A, + 0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C, 0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1, + 0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690, 0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694, + 0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698, 0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A, + 0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B, 0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D, + 0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8, 0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB, + 0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740, 0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743, + 0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3, 0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747, + 0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B, 0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4, + 0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E, 0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4, + 0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1, 0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753, + 0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD, 0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5, + 0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7, 0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756, + 0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A, 0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C, + 0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D, 0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761, + 0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE, 0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766, + 0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF, 0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC, + 0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F, 0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772, + 0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8, 0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776, + 0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A, 0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD, + 0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E, 0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB, + 0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2, 0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA, + 0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783, 0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785, + 0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788, 0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5, + 0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D, 0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790, + 0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5, 0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795, + 0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797, 0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798, + 0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B, 0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0, + 0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840, 0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6, + 0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845, 0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847, + 0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A, 0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D, + 0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9, 0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852, + 0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE, 0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854, + 0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858, 0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B, + 0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D, 0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861, + 0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3, 0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864, + 0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868, 0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B, + 0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F, 0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872, + 0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874, 0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878, + 0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1, 0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880, + 0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884, 0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887, + 0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B, 0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8, + 0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E, 0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891, + 0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894, 0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897, + 0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898, 0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B, + 0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3, 0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD, + 0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941, 0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9, + 0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948, 0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949, + 0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5, 0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E, + 0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952, 0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954, + 0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957, 0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A, + 0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E, 0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962, + 0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966, 0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1, + 0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B, 0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0, + 0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F, 0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971, + 0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974, 0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE, + 0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979, 0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B, + 0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD, 0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982, + 0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985, 0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987, + 0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB, 0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C, + 0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F, 0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992, + 0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996, 0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A, + 0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D, 0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0, + 0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43, 0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47, + 0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A, 0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D, + 0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50, 0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5, + 0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56, 0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58, + 0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C, 0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60, + 0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62, 0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66, + 0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A, 0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE, + 0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B, 0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F, + 0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72, 0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF, + 0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77, 0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B, + 0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1, 0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82, + 0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9, 0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89, + 0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C, 0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F, + 0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93, 0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD, + 0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99, 0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA, + 0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9, 0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40, + 0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42, 0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45, + 0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49, 0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C, + 0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50, 0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54, + 0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56, 0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A, + 0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D, 0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD, + 0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4, 0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64, + 0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68, 0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A, + 0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E, 0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71, + 0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75, 0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78, + 0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C, 0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E, + 0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81, 0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85, + 0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88, 0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C, + 0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F, 0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92, + 0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96, 0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A, + 0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E, 0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41, + 0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44, 0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47, + 0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A, 0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E, + 0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52, 0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55, + 0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1, 0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C, + 0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60, 0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64, + 0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68, 0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A, + 0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E, 0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72, + 0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76, 0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79, + 0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C, 0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81, + 0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85, 0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89, + 0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2, 0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C, + 0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F, 0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9, + 0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD, 0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD, + 0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C, 0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0, + 0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1, 0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43, + 0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47, 0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3, + 0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA, 0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC, + 0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D, 0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3, + 0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51, 0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55, + 0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57, 0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B, + 0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D, 0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61, + 0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63, 0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD, + 0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66, 0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67, + 0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0, 0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5, + 0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F, 0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72, + 0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9, 0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6, + 0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3, 0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78, + 0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B, 0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D, + 0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2, 0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83, + 0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86, 0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89, + 0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9, 0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD, + 0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E, 0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90, + 0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA, 0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4, + 0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98, 0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB, + 0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B, 0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1, + 0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0, 0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3, + 0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0, 0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC, + 0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46, 0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49, + 0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2, 0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F, + 0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52, 0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55, + 0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4, 0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A, + 0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E, 0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F, + 0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB, 0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65, + 0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68, 0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A, + 0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E, 0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71, + 0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72, 0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76, + 0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3, 0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C, + 0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB, 0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83, + 0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE, 0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB, + 0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88, 0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B, + 0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D, 0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91, + 0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94, 0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97, + 0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B, 0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E, + 0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41, 0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44, + 0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45, 0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48, + 0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A, 0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD, + 0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50, 0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53, + 0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1, 0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1, + 0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C, 0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE, + 0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61, 0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65, + 0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68, 0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B, + 0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E, 0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3, + 0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5, 0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78, + 0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C, 0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80, + 0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8, 0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87, + 0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A, 0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9, + 0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91, 0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95, + 0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6, 0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A, + 0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D, 0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0, + 0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042, 0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046, + 0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A, 0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3, + 0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051, 0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054, + 0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057, 0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A, + 0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C, 0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060, + 0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062, 0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066, + 0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069, 0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B, + 0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F, 0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9, + 0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072, 0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074, + 0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2, 0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4, + 0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B, 0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E, + 0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0, 0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7, + 0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084, 0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087, + 0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089, 0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB, + 0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4, 0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093, + 0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096, 0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8, + 0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C, 0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0, + 0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141, 0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144, + 0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148, 0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B, + 0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E, 0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1, + 0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9, 0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155, + 0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE, 0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6, + 0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D, 0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F, + 0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163, 0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD, + 0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166, 0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169, + 0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D, 0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F, + 0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171, 0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173, + 0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5, 0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3, + 0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C, 0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB, + 0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184, 0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD, + 0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189, 0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2, + 0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E, 0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191, + 0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194, 0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA, + 0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A, 0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D, + 0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE, 0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242, + 0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246, 0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249, + 0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C, 0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250, + 0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254, 0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258, + 0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C, 0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260, + 0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5, 0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266, + 0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0, 0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D, + 0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271, 0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275, + 0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279, 0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D, + 0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281, 0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283, + 0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2, 0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289, + 0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D, 0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291, + 0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295, 0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299, + 0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D, 0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340, + 0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344, 0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348, + 0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C, 0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350, + 0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354, 0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358, + 0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C, 0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB, + 0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3, 0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9, + 0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC, 0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7, + 0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB, 0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD, + 0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC, 0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C, + 0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5, 0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371, + 0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374, 0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377, + 0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A, 0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E, + 0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383, 0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386, + 0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A, 0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D, + 0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391, 0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395, + 0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399, 0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D, + 0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440, 0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444, + 0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448, 0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C, + 0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450, 0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454, + 0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458, 0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C, + 0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4, 0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463, + 0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467, 0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A, + 0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E, 0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472, + 0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476, 0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A, + 0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E, 0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483, + 0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487, 0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B, + 0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F, 0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493, + 0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497, 0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A, + 0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E, 0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541, + 0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545, 0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC, + 0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B, 0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F, + 0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552, 0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556, + 0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A, 0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E, + 0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562, 0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566, + 0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A, 0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E, + 0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572, 0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576, + 0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A, 0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E, + 0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583, 0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587, + 0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B, 0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F, + 0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593, 0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597, + 0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B, 0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F, + 0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642, 0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646, + 0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A, 0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E, + 0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652, 0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656, + 0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A, 0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E, + 0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662, 0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665, + 0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669, 0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D, + 0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671, 0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675, + 0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679, 0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D, + 0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5, 0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685, + 0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689, 0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D, + 0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691, 0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695, + 0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699, 0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D, + 0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740, 0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744, + 0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748, 0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C, + 0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750, 0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754, + 0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758, 0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C, + 0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF, 0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763, + 0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766, 0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A, + 0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E, 0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772, + 0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776, 0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A, + 0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E, 0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783, + 0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787, 0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B, + 0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F, 0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793, + 0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797, 0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9, + 0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6, 0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8, + 0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9, 0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2, + 0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8, 0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB, + 0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8, 0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC, + 0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6, 0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF, + 0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0, 0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1, + 0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4, 0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF, + 0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE, 0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF, + 0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA, 0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E, + 0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD, 0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5, + 0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0, 0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5, + 0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE, 0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5, + 0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB, 0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA, + 0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1, 0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB, + 0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE, 0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8, + 0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0, 0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB, + 0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB, 0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8, + 0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA, 0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC, + 0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF, 0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842, + 0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846, 0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849, + 0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9, 0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E, + 0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851, 0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855, + 0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858, 0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0, + 0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F, 0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF, + 0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865, 0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0, + 0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B, 0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F, + 0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872, 0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2, + 0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877, 0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5, + 0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D, 0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6, + 0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883, 0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887, + 0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A, 0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D, + 0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891, 0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895, + 0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899, 0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D, + 0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940, 0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944, + 0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948, 0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C, + 0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950, 0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954, + 0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958, 0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C, + 0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960, 0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964, + 0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968, 0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C, + 0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970, 0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974, + 0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978, 0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C, + 0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981, 0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985, + 0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989, 0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D, + 0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991, 0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995, + 0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999, 0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D, + 0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40, 0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44, + 0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48, 0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C, + 0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA, 0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6, + 0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB, 0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0, + 0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC, 0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA, + 0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC, 0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8, + 0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6, 0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8, + 0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1, 0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE, + 0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA, 0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51, + 0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5, 0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC, + 0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE, 0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE, + 0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2, 0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57, + 0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59, 0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C, + 0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF, 0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F, + 0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63, 0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66, + 0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68, 0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD, + 0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E, 0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71, + 0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74, 0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78, + 0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C, 0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80, + 0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83, 0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87, + 0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B, 0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E, + 0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F, 0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3, + 0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA, 0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96, + 0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC, 0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B, + 0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9, 0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E, + 0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5, 0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7, + 0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8, 0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46, + 0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48, 0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2, + 0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C, 0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F, + 0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51, 0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5, + 0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53, 0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57, + 0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A, 0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB, + 0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F, 0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62, + 0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65, 0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69, + 0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1, 0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF, + 0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70, 0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9, + 0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA, 0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76, + 0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79, 0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD, + 0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E, 0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5, + 0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83, 0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8, + 0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86, 0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7, + 0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C, 0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F, + 0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93, 0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97, + 0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4, 0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D, + 0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F, 0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7, + 0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA, 0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45, + 0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48, 0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A, + 0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D, 0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50, + 0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54, 0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56, + 0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59, 0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D, + 0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3, 0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63, + 0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67, 0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B, + 0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D, 0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3, + 0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73, 0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9, + 0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A, 0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E, + 0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83, 0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87, + 0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6, 0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E, + 0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92, 0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96, + 0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A, 0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E, + 0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41, 0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45, + 0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49, 0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D, + 0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51, 0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55, + 0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59, 0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D, + 0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61, 0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65, + 0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69, 0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D, + 0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71, 0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75, + 0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79, 0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D, + 0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82, 0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86, + 0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A, 0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E, + 0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92, 0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96, + 0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A, 0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E, + 0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41, 0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45, + 0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49, 0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D, + 0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51, 0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55, + 0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59, 0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D, + 0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5, 0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61, + 0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6, 0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0, + 0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3, 0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7, + 0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9, 0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB, + 0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE, 0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5, + 0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2, 0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64, + 0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD, 0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5, + 0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7, 0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68, + 0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B, 0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D, + 0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70, 0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72, + 0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1, 0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78, + 0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF, 0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8, + 0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E, 0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81, + 0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD, 0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86, + 0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87, 0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89, + 0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC, 0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6, + 0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8, 0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF, + 0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5, 0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91, + 0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94, 0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95, + 0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98, 0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA, + 0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6, 0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7, + 0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D, 0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD, + 0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1, 0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8, + 0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1, 0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA, + 0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE, 0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48, + 0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE, 0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D, + 0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4, 0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52, + 0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2, 0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC, + 0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58, 0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B, + 0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E, 0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9, + 0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61, 0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63, + 0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66, 0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD, + 0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B, 0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E, + 0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA, 0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74, + 0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76, 0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A, + 0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D, 0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2, + 0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82, 0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85, + 0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88, 0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B, + 0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D, 0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F, + 0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91, 0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF, + 0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE, 0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0, + 0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA, 0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B, + 0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD, 0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE, + 0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5, 0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040, + 0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042, 0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC, + 0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9, 0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048, + 0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B, 0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E, + 0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F, 0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB, + 0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA, 0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056, + 0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058, 0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B, + 0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E, 0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061, + 0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1, 0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5, + 0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069, 0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D, + 0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071, 0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075, + 0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079, 0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C, + 0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4, 0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3, + 0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086, 0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A, + 0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E, 0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090, + 0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094, 0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097, + 0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B, 0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F, + 0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA, 0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA, + 0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC, 0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6, + 0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147, 0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3, + 0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA, 0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1, + 0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E, 0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2, + 0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA, 0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8, + 0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8, 0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154, + 0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7, 0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159, + 0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C, 0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E, + 0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F, 0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1, + 0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164, 0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1, + 0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A, 0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0, + 0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170, 0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2, + 0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4, 0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178, + 0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A, 0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8, + 0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182, 0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186, + 0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A, 0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD, + 0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0, 0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E, + 0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192, 0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196, + 0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199, 0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D, + 0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240, 0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244, + 0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248, 0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C, + 0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250, 0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254, + 0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258, 0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C, + 0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260, 0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264, + 0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268, 0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C, + 0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270, 0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274, + 0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278, 0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C, + 0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281, 0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285, + 0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289, 0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D, + 0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291, 0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295, + 0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299, 0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D, + 0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340, 0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344, + 0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348, 0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C, + 0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350, 0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354, + 0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358, 0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C, + 0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360, 0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364, + 0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368, 0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C, + 0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F, 0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373, + 0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377, 0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B, + 0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380, 0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384, + 0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6, 0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B, + 0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F, 0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393, + 0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397, 0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B, + 0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F, 0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442, + 0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7, 0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449, + 0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D, 0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451, + 0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455, 0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459, + 0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D, 0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460, + 0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464, 0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468, + 0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C, 0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470, + 0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474, 0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478, + 0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C, 0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481, + 0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485, 0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489, + 0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D, 0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491, + 0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495, 0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499, + 0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D, 0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540, + 0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544, 0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548, + 0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C, 0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550, + 0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554, 0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558, + 0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C, 0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560, + 0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564, 0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568, + 0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C, 0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570, + 0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9, 0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577, + 0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B, 0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580, + 0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584, 0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588, + 0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C, 0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590, + 0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594, 0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598, + 0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C, 0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA, + 0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642, 0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646, + 0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A, 0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E, + 0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652, 0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656, + 0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A, 0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E, + 0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662, 0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665, + 0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669, 0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D, + 0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671, 0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675, + 0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679, 0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D, + 0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682, 0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686, + 0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A, 0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E, + 0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692, 0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696, + 0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A, 0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB, + 0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740, 0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744, + 0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9, 0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B, + 0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F, 0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753, + 0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757, 0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B, + 0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F, 0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763, + 0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767, 0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B, + 0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F, 0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773, + 0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777, 0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B, + 0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780, 0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784, + 0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788, 0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C, + 0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790, 0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794, + 0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798, 0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C, + 0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0, 0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843, + 0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847, 0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B, + 0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD, 0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852, + 0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856, 0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A, + 0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E, 0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862, + 0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866, 0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A, + 0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E, 0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872, + 0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876, 0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A, + 0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D, 0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882, + 0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886, 0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A, + 0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E, 0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892, + 0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5, 0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8, + 0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5, 0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0, + 0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896, 0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0, + 0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE, 0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6, + 0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5, 0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6, + 0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5, 0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB, + 0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD, 0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1, + 0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8, 0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC, + 0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD, 0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8, + 0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC, 0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF, + 0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1, 0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C, + 0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6, 0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9, + 0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D, 0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE, + 0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3, 0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9, + 0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8, 0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC, + 0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4, 0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE, + 0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF, 0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2, + 0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4, 0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6, + 0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA, 0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA, + 0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE, 0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0, + 0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5, 0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1, + 0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC, 0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6, + 0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8, 0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1, + 0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC, 0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE, + 0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2, 0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7, + 0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5, 0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7, + 0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA, 0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947, + 0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF, 0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3, + 0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6, 0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA, + 0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949, 0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF, + 0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2, 0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F, + 0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953, 0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956, + 0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A, 0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E, + 0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962, 0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966, + 0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A, 0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E, + 0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972, 0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976, + 0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A, 0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E, + 0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983, 0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987, + 0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B, 0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F, + 0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993, 0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997, + 0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B, 0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F, + 0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42, 0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46, + 0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A, 0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E, + 0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52, 0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56, + 0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A, 0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1, + 0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA, 0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0, + 0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA, 0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB, + 0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC, 0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2, + 0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF, 0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1, + 0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6, 0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6, + 0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8, 0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB, + 0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62, 0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3, + 0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67, 0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6, + 0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE, 0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0, + 0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7, 0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73, + 0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74, 0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9, + 0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD, 0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77, + 0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78, 0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B, + 0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D, 0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82, + 0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85, 0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA, + 0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89, 0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3, + 0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C, 0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF, + 0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5, 0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93, + 0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97, 0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B, + 0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1, 0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0, + 0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41, 0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43, + 0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46, 0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47, + 0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A, 0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E, + 0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52, 0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55, + 0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59, 0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C, + 0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5, 0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61, + 0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1, 0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64, + 0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF, 0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67, + 0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2, 0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3, + 0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D, 0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71, + 0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75, 0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78, + 0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C, 0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9, + 0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82, 0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85, + 0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3, 0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89, + 0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED, 0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E, + 0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA, 0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91, + 0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE, 0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96, + 0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8, 0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C, + 0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC, 0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41, + 0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45, 0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF, + 0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B, 0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6, + 0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51, 0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53, + 0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2, 0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A, + 0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E, 0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62, + 0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66, 0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0, + 0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8, 0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E, + 0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7, 0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6, + 0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74, 0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77, + 0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B, 0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80, + 0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0, 0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85, + 0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88, 0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C, + 0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F, 0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93, + 0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95, 0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3, + 0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A, 0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D, + 0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40, 0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43, + 0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46, 0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A, + 0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C, 0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8, + 0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51, 0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55, + 0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59, 0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D, + 0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61, 0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65, + 0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69, 0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D, + 0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71, 0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75, + 0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79, 0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D, + 0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4, 0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8, + 0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83, 0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87, + 0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8, 0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C, + 0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90, 0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94, + 0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98, 0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C, + 0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0, 0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43, + 0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47, 0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B, + 0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F, 0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53, + 0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57, 0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B, + 0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F, 0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63, + 0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67, 0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B, + 0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F, 0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73, + 0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77, 0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B, + 0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80, 0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84, + 0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88, 0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C, + 0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90, 0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94, + 0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98, 0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C, + 0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0, 0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43, + 0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5, 0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3, + 0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB, 0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC, + 0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC, 0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5, + 0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47, 0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48, + 0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1, 0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6, + 0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8, 0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB, + 0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD, 0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E, + 0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52, 0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56, + 0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A, 0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E, + 0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62, 0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66, + 0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A, 0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E, + 0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7, 0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA, + 0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75, 0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE, + 0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9, 0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C, + 0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81, 0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83, + 0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87, 0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B, + 0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F, 0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93, + 0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97, 0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B, + 0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F, 0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042, + 0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045, 0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048, + 0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C, 0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050, + 0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054, 0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058, + 0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C, 0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060, + 0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1, 0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067, + 0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B, 0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F, + 0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073, 0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077, + 0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B, 0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080, + 0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084, 0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088, + 0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A, 0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E, + 0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092, 0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096, + 0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098, 0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF, + 0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB, 0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7, + 0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4, 0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8, + 0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D, 0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E, + 0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD, 0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8, + 0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141, 0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8, + 0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7, 0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142, + 0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146, 0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A, + 0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D, 0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150, + 0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154, 0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158, + 0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C, 0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160, + 0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164, 0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168, + 0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C, 0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170, + 0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174, 0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178, + 0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C, 0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181, + 0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185, 0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189, + 0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D, 0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191, + 0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195, 0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199, + 0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D, 0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240, + 0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244, 0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248, + 0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C, 0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250, + 0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254, 0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258, + 0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C, 0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260, + 0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264, 0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268, + 0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C, 0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270, + 0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274, 0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278, + 0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C, 0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281, + 0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285, 0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289, + 0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D, 0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291, + 0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295, 0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299, + 0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D, 0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340, + 0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344, 0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348, + 0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C, 0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350, + 0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4, 0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352, + 0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB, 0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3, + 0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD, 0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE, + 0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6, 0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA, + 0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356, 0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC, + 0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE, 0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7, + 0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9, 0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5, + 0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A, 0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C, + 0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360, 0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362, + 0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE, 0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF, + 0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369, 0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4, + 0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D, 0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371, + 0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373, 0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376, + 0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379, 0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C, + 0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381, 0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383, + 0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6, 0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A, + 0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C, 0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F, + 0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393, 0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396, + 0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399, 0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D, + 0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0, 0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442, + 0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446, 0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449, + 0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C, 0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450, + 0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454, 0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457, + 0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A, 0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E, + 0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462, 0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA, + 0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468, 0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C, + 0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E, 0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA, + 0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471, 0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472, + 0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475, 0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477, + 0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A, 0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E, + 0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483, 0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487, + 0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B, 0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F, + 0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493, 0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497, + 0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B, 0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F, + 0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542, 0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546, + 0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A, 0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E, + 0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552, 0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556, + 0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A, 0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E, + 0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562, 0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566, + 0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A, 0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E, + 0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572, 0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576, + 0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A, 0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E, + 0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583, 0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587, + 0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B, 0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F, + 0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593, 0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597, + 0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B, 0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F, + 0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642, 0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646, + 0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A, 0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E, + 0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652, 0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656, + 0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A, 0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E, + 0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662, 0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666, + 0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A, 0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E, + 0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672, 0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676, + 0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A, 0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E, + 0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683, 0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687, + 0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B, 0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F, + 0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693, 0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697, + 0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B, 0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F, + 0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742, 0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746, + 0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A, 0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E, + 0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752, 0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756, + 0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A, 0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E, + 0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762, 0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766, + 0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A, 0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E, + 0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772, 0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776, + 0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A, 0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E, + 0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782, 0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0, + 0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2, 0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787, + 0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7, 0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA, + 0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B, 0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD, + 0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF, 0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3, + 0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6, 0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790, + 0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC, 0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF, + 0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3, 0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5, + 0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794, 0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798, + 0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB, 0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD, + 0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3, 0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C, + 0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE, 0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D, + 0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB, 0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF, + 0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843, 0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847, + 0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B, 0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F, + 0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853, 0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857, + 0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B, 0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F, + 0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863, 0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867, + 0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B, 0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F, + 0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873, 0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877, + 0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B, 0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880, + 0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884, 0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888, + 0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C, 0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890, + 0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894, 0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898, + 0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C, 0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0, + 0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943, 0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947, + 0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B, 0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F, + 0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953, 0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957, + 0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B, 0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F, + 0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963, 0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967, + 0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B, 0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F, + 0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973, 0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977, + 0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B, 0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980, + 0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984, 0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988, + 0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C, 0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990, + 0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994, 0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998, + 0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C, 0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0, + 0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43, 0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47, + 0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B, 0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F, + 0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53, 0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57, + 0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B, 0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F, + 0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63, 0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67, + 0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B, 0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F, + 0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73, 0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77, + 0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B, 0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80, + 0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84, 0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88, + 0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C, 0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90, + 0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94, 0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98, + 0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C, 0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0, + 0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43, 0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47, + 0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B, 0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F, + 0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53, 0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57, + 0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B, 0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0, + 0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB, 0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3, + 0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E, 0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6, + 0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8, 0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC, + 0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD, 0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF, + 0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1, 0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5, + 0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7, 0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66, + 0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69, 0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB, + 0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE, 0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F, + 0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0, 0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4, + 0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71, 0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73, + 0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76, 0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A, + 0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA, 0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4, + 0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84, 0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86, + 0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89, 0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8, + 0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F, 0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93, + 0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96, 0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99, + 0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3, 0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0, + 0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43, 0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47, + 0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A, 0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D, + 0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2, 0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52, + 0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55, 0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58, + 0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8, 0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C, + 0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F, 0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62, + 0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63, 0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1, + 0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67, 0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5, + 0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C, 0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F, + 0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73, 0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76, + 0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC, 0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B, + 0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80, 0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84, + 0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6, 0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88, + 0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B, 0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D, + 0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91, 0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7, + 0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97, 0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B, + 0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E, 0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40, + 0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44, 0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46, + 0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD, 0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B, + 0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E, 0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52, + 0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56, 0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58, + 0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C, 0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60, + 0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64, 0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68, + 0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C, 0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70, + 0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74, 0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78, + 0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C, 0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81, + 0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85, 0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87, + 0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6, 0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA, + 0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89, 0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D, + 0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91, 0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8, + 0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96, 0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98, + 0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C, 0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0, + 0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43, 0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47, + 0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B, 0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F, + 0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5, 0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1, + 0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF, 0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5, + 0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB, 0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B, + 0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F, 0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973, + 0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977, 0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B, + 0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980, 0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984, + 0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA, 0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4, + 0, 0 +}; + +static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ + 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, + 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, + 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, + 0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51, 0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B, + 0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65, 0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B, + 0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F, 0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76, + 0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A, 0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F, + 0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83, 0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A, + 0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99, 0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3, + 0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1, 0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8, + 0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE, 0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0, + 0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC, 0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7, + 0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF, 0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9, + 0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00, 0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05, + 0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B, 0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14, + 0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D, 0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29, + 0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31, 0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40, 0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45, + 0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A, 0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54, + 0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66, 0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D, + 0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75, 0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A, + 0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82, 0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92, 0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98, + 0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E, 0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4, + 0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1, 0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6, + 0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA, 0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE, + 0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6, 0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB, + 0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3, 0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9, + 0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4, 0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC, + 0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5, 0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB, + 0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000, 0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004, + 0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008, 0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E, + 0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015, 0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D, + 0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023, 0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F, + 0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033, 0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037, + 0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D, 0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042, + 0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049, 0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050, + 0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054, 0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059, + 0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F, 0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063, + 0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068, 0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D, + 0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071, 0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075, + 0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C, 0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083, + 0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089, 0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E, + 0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092, 0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096, + 0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A, 0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E, + 0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2, 0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB, + 0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0, 0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5, + 0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9, 0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF, + 0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3, 0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7, + 0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB, 0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0, + 0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4, 0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9, + 0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE, 0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2, + 0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8, 0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF, + 0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4, 0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9, + 0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE, 0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102, + 0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108, 0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D, + 0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111, 0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116, + 0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A, 0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E, + 0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123, 0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127, + 0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B, 0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F, + 0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133, 0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137, + 0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B, 0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142, + 0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E, 0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153, + 0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B, 0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160, + 0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166, 0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F, + 0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F, 0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187, + 0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F, 0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194, + 0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E, 0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6, + 0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA, 0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8, + 0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF, 0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5, + 0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE, 0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4, + 0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8, 0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE, + 0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5, 0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9, + 0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1, 0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE, + 0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B, 0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213, + 0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E, 0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223, + 0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A, 0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232, + 0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E, 0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247, + 0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E, 0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255, + 0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A, 0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260, + 0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266, 0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D, + 0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273, 0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277, + 0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B, 0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283, + 0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287, 0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C, + 0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291, 0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296, + 0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A, 0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6, + 0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0, 0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7, + 0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB, 0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1, + 0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6, 0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD, + 0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3, 0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9, + 0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD, 0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2, + 0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7, 0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB, + 0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF, 0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4, + 0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8, 0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301, + 0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307, 0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C, + 0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313, 0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C, + 0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324, 0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329, + 0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F, 0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333, + 0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337, 0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340, + 0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B, 0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354, + 0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D, 0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C, + 0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379, 0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E, + 0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387, 0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F, + 0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393, 0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399, + 0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0, 0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA, + 0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF, 0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3, + 0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8, 0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD, + 0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4, 0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE, + 0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3, 0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD, + 0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7, 0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF, + 0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407, 0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419, + 0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424, 0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433, + 0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D, 0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444, + 0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C, 0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451, + 0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F, 0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465, + 0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B, 0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F, + 0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A, 0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483, + 0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489, 0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493, + 0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E, 0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2, + 0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2, 0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9, + 0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3, 0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6, + 0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1, 0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB, + 0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1, 0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7, + 0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE, 0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504, + 0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B, 0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512, + 0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517, 0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C, + 0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521, 0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529, + 0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534, 0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539, + 0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540, 0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548, + 0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E, 0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553, + 0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559, 0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E, + 0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563, 0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F, + 0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573, 0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D, + 0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C, 0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592, + 0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597, 0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0, + 0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4, 0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9, + 0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD, 0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2, + 0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA, 0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1, + 0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7, 0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE, + 0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7, 0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB, + 0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7, 0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0, + 0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8, 0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC, + 0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604, 0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A, + 0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611, 0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615, + 0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A, 0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621, + 0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628, 0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E, + 0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635, 0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C, + 0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641, 0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645, + 0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649, 0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650, + 0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655, 0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D, + 0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661, 0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667, + 0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670, 0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675, + 0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A, 0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680, + 0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684, 0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A, + 0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690, 0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695, + 0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699, 0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D, + 0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1, 0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6, + 0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA, 0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE, + 0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3, 0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8, + 0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD, 0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1, + 0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5, 0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9, + 0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE, 0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2, + 0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8, 0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5, + 0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9, 0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF, + 0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7, 0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700, + 0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707, 0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E, + 0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712, 0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716, + 0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A, 0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720, + 0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725, 0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731, + 0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736, 0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D, + 0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744, 0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749, + 0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754, 0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759, + 0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767, 0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771, + 0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778, 0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E, + 0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787, 0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D, + 0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791, 0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797, + 0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C, 0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5, + 0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF, 0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5, + 0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA, 0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE, + 0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4, 0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8, + 0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD, 0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6, + 0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE, 0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5, + 0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9, 0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE, + 0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3, 0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB, + 0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801, 0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808, + 0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E, 0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813, + 0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818, 0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D, + 0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825, 0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829, + 0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E, 0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833, + 0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838, 0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C, + 0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840, 0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845, + 0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849, 0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F, + 0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855, 0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A, + 0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F, 0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863, + 0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868, 0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E, + 0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872, 0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876, + 0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A, 0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F, + 0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887, 0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C, + 0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890, 0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896, + 0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C, 0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2, + 0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6, 0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC, + 0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0, 0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4, + 0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8, 0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD, + 0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2, 0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7, + 0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB, 0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF, + 0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4, 0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9, + 0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD, 0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1, + 0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6, 0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA, + 0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2, 0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8, + 0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD, 0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901, + 0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908, 0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C, + 0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912, 0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B, + 0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921, 0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928, + 0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933, 0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D, + 0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943, 0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C, + 0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953, 0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D, + 0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963, 0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968, + 0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C, 0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970, + 0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977, 0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E, + 0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989, 0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F, + 0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995, 0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C, + 0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1, 0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC, + 0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3, 0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7, + 0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD, 0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2, + 0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7, 0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD, + 0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6, 0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF, + 0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4, 0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA, + 0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF, 0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3, + 0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7, 0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD, + 0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A, 0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F, + 0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15, 0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A, + 0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21, 0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27, + 0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C, 0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30, + 0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38, 0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D, + 0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42, 0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47, + 0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D, 0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51, + 0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56, 0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B, + 0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F, 0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64, + 0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69, 0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E, + 0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72, 0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B, + 0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80, 0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84, + 0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88, 0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C, + 0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90, 0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95, + 0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99, 0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F, + 0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3, 0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7, + 0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC, 0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0, + 0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7, 0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC, + 0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3, 0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7, + 0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD, 0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1, + 0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9, 0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE, + 0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5, 0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC, + 0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0, 0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5, + 0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9, 0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD, + 0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01, 0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05, + 0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A, 0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E, + 0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12, 0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18, + 0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C, 0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20, + 0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24, 0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28, + 0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C, 0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30, + 0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36, 0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B, + 0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F, 0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44, + 0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48, 0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C, + 0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52, 0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61, + 0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D, 0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74, + 0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79, 0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F, + 0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D, 0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92, + 0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7, 0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD, + 0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2, 0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC, + 0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8, 0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD, + 0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4, 0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8, + 0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC, 0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6, + 0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB, 0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1, + 0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5, 0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE, + 0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05, 0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C, + 0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12, 0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B, + 0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21, 0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29, + 0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E, 0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33, + 0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43, 0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C, + 0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54, 0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A, + 0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F, 0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68, + 0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C, 0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73, + 0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77, 0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D, + 0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84, 0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89, + 0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F, 0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D, + 0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1, 0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7, + 0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF, 0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6, + 0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC, 0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3, + 0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8, 0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD, + 0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1, 0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6, + 0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB, 0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF, + 0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7, 0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE, + 0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3, 0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7, + 0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC, 0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00, + 0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08, 0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C, + 0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11, 0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17, + 0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C, 0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21, + 0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28, 0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F, + 0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33, 0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38, + 0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C, 0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42, + 0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46, 0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E, + 0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52, 0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56, + 0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C, 0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61, + 0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65, 0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A, + 0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71, 0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76, + 0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A, 0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E, + 0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83, 0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87, + 0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B, 0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F, + 0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93, 0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97, + 0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C, 0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1, + 0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5, 0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9, + 0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD, 0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1, + 0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5, 0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA, + 0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE, 0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2, + 0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7, 0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB, + 0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0, 0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4, + 0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8, 0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF, + 0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA, 0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5, + 0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA, 0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00, + 0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A, 0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12, + 0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F, 0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23, + 0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29, 0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F, + 0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34, 0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A, + 0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41, 0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48, + 0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D, 0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51, + 0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57, 0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C, + 0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63, 0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67, + 0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B, 0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F, + 0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77, 0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82, + 0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89, 0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1, 0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8, + 0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC, 0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1, + 0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB, 0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0, + 0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4, 0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8, + 0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE, 0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5, + 0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA, 0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF, + 0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3, 0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7, + 0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED, 0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1, + 0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8, 0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD, + 0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09, 0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10, + 0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19, 0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E, + 0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24, 0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34, 0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38, + 0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F, 0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44, + 0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48, 0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C, + 0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51, 0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B, + 0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60, 0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68, + 0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72, 0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F, 0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E, + 0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94, 0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D, + 0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2, 0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6, + 0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC, 0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2, + 0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8, 0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE, + 0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2, 0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB, + 0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5, 0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE, + 0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5, 0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC, + 0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3, 0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9, + 0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008, 0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010, + 0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018, 0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022, + 0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D, 0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032, + 0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037, 0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D, + 0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045, 0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049, + 0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F, 0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056, + 0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C, 0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061, + 0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071, 0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077, + 0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082, 0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088, + 0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F, 0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095, + 0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C, 0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4, + 0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA, 0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5, + 0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA, 0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0, + 0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4, 0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC, + 0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0, 0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6, + 0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE, 0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4, + 0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2, 0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB, + 0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF, 0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105, + 0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C, 0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113, + 0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118, 0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D, + 0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125, 0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C, + 0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130, 0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134, + 0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138, 0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C, + 0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141, 0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145, + 0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B, 0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152, + 0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157, 0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B, + 0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160, 0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165, + 0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B, 0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F, + 0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174, 0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A, + 0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E, 0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182, + 0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186, 0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A, + 0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190, 0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195, + 0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199, 0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E, + 0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2, 0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6, + 0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE, 0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2, + 0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6, 0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB, + 0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0, 0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5, + 0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC, 0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0, + 0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7, 0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB, + 0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF, 0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3, + 0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8, 0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC, + 0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0, 0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4, + 0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9, 0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD, + 0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202, 0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207, + 0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219, 0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220, + 0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228, 0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F, + 0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235, 0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A, + 0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244, 0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F, + 0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257, 0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D, + 0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261, 0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268, + 0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275, 0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B, + 0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283, 0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288, + 0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E, 0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299, + 0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3, 0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA, + 0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0, 0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6, + 0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE, 0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB, + 0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD, 0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4, + 0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2, 0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA, + 0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304, 0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B, + 0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310, 0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315, + 0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C, 0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C, + 0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331, 0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336, + 0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C, 0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341, + 0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A, 0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354, + 0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359, 0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D, + 0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366, 0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C, + 0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373, 0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379, + 0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F, 0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385, + 0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391, 0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397, + 0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C, 0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1, + 0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF, 0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6, + 0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF, 0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3, + 0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA, 0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3, + 0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8, 0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC, + 0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4, 0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8, + 0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF, 0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5, + 0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB, 0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404, + 0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409, 0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411, + 0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417, 0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D, + 0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424, 0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429, + 0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430, 0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435, + 0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439, 0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440, + 0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B, 0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F, + 0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455, 0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A, + 0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F, 0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463, + 0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468, 0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E, + 0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472, 0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476, + 0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D, 0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481, + 0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489, 0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D, + 0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493, 0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A, + 0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F, 0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3, + 0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8, 0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1, + 0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6, 0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE, + 0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4, 0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9, + 0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF, 0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5, + 0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB, 0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0, + 0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7, 0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB, + 0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF, 0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3, + 0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7, 0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB, + 0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF, 0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504, + 0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508, 0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D, + 0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511, 0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516, + 0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B, 0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F, + 0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523, 0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528, + 0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D, 0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533, + 0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D, 0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543, + 0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A, 0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550, + 0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557, 0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F, + 0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565, 0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A, + 0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571, 0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578, + 0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C, 0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580, + 0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584, 0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589, + 0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F, 0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596, + 0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E, 0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6, + 0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE, 0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4, + 0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8, 0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF, + 0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8, 0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0, + 0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5, 0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB, + 0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF, 0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA, + 0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4, 0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB, + 0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF, 0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607, + 0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D, 0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616, + 0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B, 0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622, + 0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629, 0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E, + 0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637, 0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B, + 0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642, 0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647, + 0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D, 0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658, + 0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D, 0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663, + 0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A, 0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671, + 0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678, 0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D, + 0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683, 0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689, + 0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E, 0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693, + 0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699, 0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E, + 0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2, 0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6, + 0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC, 0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1, + 0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6, 0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB, + 0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0, 0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4, + 0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8, 0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC, + 0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0, 0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4, + 0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8, 0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0, + 0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4, 0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA, + 0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE, 0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6, + 0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD, 0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704, + 0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C, 0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712, + 0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719, 0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720, + 0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724, 0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E, + 0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736, 0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B, + 0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741, 0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A, + 0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754, 0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759, + 0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762, 0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767, + 0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771, 0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779, + 0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780, 0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786, + 0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D, 0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792, + 0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799, 0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1, + 0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC, 0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4, + 0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC, 0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0, + 0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7, 0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB, + 0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5, 0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF, + 0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6, 0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB, + 0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5, 0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9, + 0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE, 0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804, + 0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812, 0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819, + 0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E, 0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823, + 0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827, 0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D, + 0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831, 0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A, + 0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B, 0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856, + 0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A, 0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E, + 0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D, 0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871, + 0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878, 0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C, + 0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880, 0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888, + 0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C, 0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891, + 0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896, 0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B, + 0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F, 0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4, + 0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB, 0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2, + 0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8, 0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC, + 0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1, 0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6, + 0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC, 0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1, + 0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7, 0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD, + 0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2, 0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7, + 0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB, 0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2, + 0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7, 0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE, + 0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903, 0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908, + 0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F, 0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915, + 0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919, 0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D, + 0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923, 0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928, + 0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C, 0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932, + 0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937, 0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C, + 0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943, 0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947, + 0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B, 0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F, + 0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953, 0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959, + 0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961, 0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967, + 0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C, 0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972, + 0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976, 0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E, + 0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985, 0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E, + 0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992, 0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999, + 0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F, 0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3, + 0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9, 0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF, + 0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5, 0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA, + 0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF, 0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4, + 0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8, 0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF, + 0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5, 0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9, + 0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE, 0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4, + 0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8, 0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC, + 0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1, 0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6, + 0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA, 0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00, + 0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04, 0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08, + 0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D, 0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11, + 0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15, 0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B, + 0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20, 0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25, + 0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B, 0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30, + 0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36, 0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A, + 0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40, 0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45, + 0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A, 0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E, + 0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53, 0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57, + 0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E, 0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63, + 0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68, 0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C, + 0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70, 0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75, + 0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A, 0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F, + 0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85, 0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89, + 0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D, 0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94, + 0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99, 0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D, + 0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2, 0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6, + 0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD, 0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1, + 0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5, 0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9, + 0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD, 0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1, + 0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5, 0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9, + 0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD, 0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1, + 0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5, 0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9, + 0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD, 0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1, + 0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5, 0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9, + 0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED, 0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1, + 0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5, 0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9, + 0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD, 0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01, + 0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05, 0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09, + 0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D, 0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11, + 0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15, 0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19, + 0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D, 0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26, + 0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B, 0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F, + 0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34, 0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B, + 0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40, 0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45, + 0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D, 0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51, + 0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55, 0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A, + 0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E, 0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68, + 0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D, 0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71, + 0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75, 0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A, + 0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80, 0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E, + 0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94, 0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99, + 0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F, 0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4, + 0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8, 0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD, + 0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1, 0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9, + 0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD, 0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4, + 0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9, 0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0, + 0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC, 0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0, + 0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5, 0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9, + 0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0, 0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6, + 0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB, 0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00, + 0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04, 0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B, + 0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17, 0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C, 0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36, + 0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B, 0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43, + 0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B, 0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F, + 0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56, 0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62, + 0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67, 0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E, + 0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75, 0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B, + 0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84, 0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D, + 0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95, 0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A, + 0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0, 0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF, + 0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6, 0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1, + 0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7, 0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE, + 0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8, 0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD, + 0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7, 0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00, 0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06, + 0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D, 0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13, + 0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18, 0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20, + 0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24, 0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C, + 0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34, 0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A, + 0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44, 0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55, + 0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B, 0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62, + 0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68, 0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70, + 0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75, 0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B, + 0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80, 0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86, + 0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D, 0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96, + 0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A, 0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC, + 0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3, 0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9, + 0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD, 0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3, + 0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD, 0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2, + 0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7, 0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF, + 0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7, 0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED, + 0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4, 0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA, + 0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00, 0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04, + 0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09, 0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13, + 0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B, 0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22, + 0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A, 0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31, + 0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37, 0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D, + 0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41, 0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47, + 0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B, 0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51, + 0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59, 0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E, + 0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63, 0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67, + 0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C, 0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71, + 0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75, 0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79, + 0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D, 0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84, + 0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B, 0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91, + 0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95, 0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A, + 0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0, 0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6, + 0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC, 0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC, 0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3, + 0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8, 0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD, + 0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6, 0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC, + 0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA, 0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE, + 0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2, 0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7, + 0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC, 0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00, + 0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05, 0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B, + 0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10, 0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17, + 0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B, 0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F, + 0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25, 0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34, 0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39, + 0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D, 0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42, + 0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48, 0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E, + 0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52, 0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56, + 0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B, 0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61, + 0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67, 0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B, + 0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71, 0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77, + 0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E, 0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82, + 0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87, 0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90, + 0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94, 0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98, + 0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D, 0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2, + 0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6, 0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB, + 0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF, 0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4, + 0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA, 0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE, + 0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4, 0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8, + 0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD, 0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3, + 0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7, 0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB, + 0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2, 0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6, + 0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA, 0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0, + 0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4, 0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8, + 0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC, 0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000, + 0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004, 0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008, + 0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C, 0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010, + 0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015, 0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019, + 0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F, 0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024, + 0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028, 0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C, + 0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030, 0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034, + 0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A, 0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E, + 0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042, 0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046, + 0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A, 0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050, + 0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054, 0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058, + 0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C, 0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061, + 0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065, 0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069, + 0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072, 0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079, + 0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081, 0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086, + 0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C, 0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091, + 0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A, 0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0, + 0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4, 0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8, + 0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2, 0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA, + 0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5, 0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB, + 0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF, 0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3, + 0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7, 0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE, + 0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3, 0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0, + 0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4, 0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA, + 0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF, 0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103, + 0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107, 0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D, + 0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112, 0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C, + 0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120, 0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124, + 0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129, 0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D, + 0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134, 0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139, + 0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D, 0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141, + 0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146, 0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B, + 0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151, 0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155, + 0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159, 0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F, + 0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163, 0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B, + 0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170, 0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176, + 0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C, 0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181, + 0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186, 0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B, + 0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190, 0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195, + 0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B, 0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1, + 0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5, 0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA, + 0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF, 0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4, + 0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA, 0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE, + 0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2, 0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7, + 0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB, 0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0, + 0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6, 0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA, + 0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE, 0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3, + 0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9, 0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED, + 0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2, 0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6, + 0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB, 0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF, + 0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203, 0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208, + 0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C, 0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210, + 0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214, 0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218, + 0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C, 0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221, + 0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225, 0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B, + 0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232, 0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C, + 0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242, 0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246, + 0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E, 0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253, + 0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258, 0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260, + 0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268, 0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D, + 0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274, 0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B, + 0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283, 0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288, + 0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290, 0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295, + 0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299, 0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D, + 0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2, 0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6, + 0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA, 0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2, + 0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB, 0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF, + 0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7, 0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC, + 0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4, 0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA, + 0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E, 0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019, + 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, + 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011, + 0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236, 0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F, + 0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237, 0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220, + 0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E, 0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D, + 0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F, 0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235, + 0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0, 0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030, 0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7, 0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190, 0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170, + 0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174, 0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178, + 0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A, 0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E, + 0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492, 0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496, + 0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A, 0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476, + 0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A, 0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E, + 0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482, 0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486, + 0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462, 0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466, + 0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220, 0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224, + 0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228, 0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162, + 0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166, 0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A, + 0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041, + 0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045, 0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049, + 0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D, 0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051, + 0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055, 0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059, + 0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D, 0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061, + 0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065, 0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069, + 0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D, 0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071, + 0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075, 0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079, + 0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D, 0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081, + 0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085, 0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089, + 0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D, 0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091, + 0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2, 0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6, + 0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA, 0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE, + 0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2, 0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6, + 0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA, 0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE, + 0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2, 0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6, + 0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA, 0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE, + 0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2, 0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6, + 0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA, 0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE, + 0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2, 0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6, + 0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA, 0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE, + 0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2, 0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6, + 0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394, 0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398, + 0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C, 0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0, + 0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5, 0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9, + 0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4, 0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8, + 0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC, 0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0, + 0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5, 0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9, + 0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A, 0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E, + 0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44, 0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38, + 0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410, 0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414, + 0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417, 0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B, + 0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F, 0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423, + 0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427, 0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B, + 0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F, 0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433, + 0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436, 0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A, + 0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E, 0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442, + 0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446, 0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A, + 0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E, 0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9, + 0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035, 0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197, + 0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F, 0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267, + 0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552, 0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556, + 0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A, 0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E, + 0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562, 0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566, + 0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A, 0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E, + 0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572, 0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583, + 0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587, 0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B, + 0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F, 0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC, + 0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4, 0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012, + 0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1, 0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED, 0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA, 0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA, 0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261, + 0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108, 0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C, + 0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110, 0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114, + 0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118, 0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C, + 0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120, 0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124, + 0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128, 0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023, + 0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027, 0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E, + 0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E, 0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1, + 0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2, 0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010, + 0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD, 0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E, + 0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C, 0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50, + 0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55, 0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A, + 0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E, 0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62, + 0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66, 0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B, + 0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502, 0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506, + 0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A, 0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E, + 0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512, 0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516, + 0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A, 0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E, + 0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522, 0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526, + 0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A, 0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E, + 0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532, 0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536, + 0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A, 0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E, + 0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542, 0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546, + 0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A, 0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF, + 0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5, 0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB, + 0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD, 0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302, + 0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307, 0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C, + 0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311, 0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319, + 0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323, 0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328, + 0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332, 0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A, + 0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340, 0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344, + 0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348, 0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C, + 0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353, 0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358, + 0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C, 0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361, + 0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365, 0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369, + 0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370, 0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374, + 0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378, 0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C, + 0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381, 0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386, + 0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D, 0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393, + 0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398, 0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D, + 0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3, 0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7, + 0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD, 0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6, + 0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD, 0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3, + 0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7, 0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2, + 0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6, 0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB, + 0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1, 0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6, + 0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC, 0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1, + 0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6, 0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA, + 0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE, 0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402, + 0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B, 0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411, + 0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415, 0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419, + 0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F, 0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424, + 0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D, 0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437, + 0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B, 0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440, + 0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445, 0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449, + 0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D, 0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451, + 0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456, 0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461, + 0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465, 0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469, + 0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E, 0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473, + 0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479, 0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D, + 0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485, 0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A, + 0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491, 0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495, + 0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499, 0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F, + 0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3, 0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA, + 0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE, 0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2, + 0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6, 0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB, + 0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF, 0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3, + 0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7, 0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB, + 0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF, 0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4, + 0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8, 0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD, + 0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7, 0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB, + 0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1, 0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8, + 0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC, 0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501, + 0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506, 0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A, + 0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510, 0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516, + 0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E, 0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523, + 0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A, 0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539, + 0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541, 0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546, + 0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D, 0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553, + 0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558, 0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560, + 0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564, 0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B, + 0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F, 0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575, + 0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B, 0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580, + 0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585, 0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A, + 0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590, 0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B, + 0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6, 0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA, + 0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA, 0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1, + 0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE, 0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3, + 0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC, 0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1, + 0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED, 0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3, + 0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8, 0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE, + 0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607, 0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D, + 0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612, 0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A, + 0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621, 0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C, + 0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632, 0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A, + 0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642, 0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647, + 0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B, 0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651, + 0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657, 0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B, + 0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661, 0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666, + 0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A, 0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670, + 0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674, 0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679, + 0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680, 0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689, + 0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F, 0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695, + 0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B, 0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F, + 0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3, 0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8, + 0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC, 0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3, + 0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8, 0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC, + 0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1, 0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0, 0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698, 0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA, 0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1, 0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252, 0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB, 0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D, + 0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D, 0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591, 0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C, + 0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E, 0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A, + 0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E, 0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551, 0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4, 0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC, + 0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA, 0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0, + 0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4, 0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9, + 0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED, 0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6, + 0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD, 0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703, + 0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C, 0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711, + 0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715, 0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B, + 0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721, 0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727, + 0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E, 0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733, + 0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D, 0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744, + 0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749, 0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D, + 0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753, 0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757, + 0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584, 0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4, 0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F, + 0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317, 0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB, 0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7, 0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119, 0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6, 0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F, 0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C, 0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E, + 0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D, 0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A, 0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0, 0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F, 0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769, + 0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F, 0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773, + 0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777, 0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C, + 0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786, 0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A, + 0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793, 0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797, + 0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B, 0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1, + 0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8, 0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF, + 0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6, 0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA, + 0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1, 0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5, + 0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9, 0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE, + 0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2, 0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6, + 0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD, 0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1, + 0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB, 0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F, 0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24, 0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D, 0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1, 0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC, 0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F, 0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD, 0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42, 0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C, + 0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D, 0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400, 0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610, 0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6, + 0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0, 0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5, + 0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB, 0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805, + 0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A, 0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810, + 0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B, 0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822, + 0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B, 0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832, + 0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D, 0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843, + 0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849, 0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F, + 0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858, 0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C, + 0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861, 0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865, + 0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869, 0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872, + 0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876, 0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B, + 0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880, 0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F, 0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545, + 0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284, 0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66, 0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0, 0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491, 0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210, + 0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9, 0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4, 0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F, 0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2, 0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20, 0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D, 0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664, 0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886, + 0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F, 0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895, + 0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E, 0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6, + 0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB, 0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF, + 0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8, 0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD, + 0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3, 0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8, + 0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF, 0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6, + 0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB, 0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF, + 0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3, 0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7, + 0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED, 0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1, + 0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8, 0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD, + 0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902, 0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907, + 0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B, 0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3, 0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE, 0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376, 0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F, + 0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF, 0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E, 0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A, 0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B, 0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC, 0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8, 0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE, 0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927, + 0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234, 0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D, 0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911, + 0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916, 0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A, + 0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F, 0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923, + 0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928, 0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C, + 0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930, 0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935, + 0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939, 0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943, + 0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A, 0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E, + 0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952, 0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959, + 0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966, 0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C, + 0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972, 0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976, + 0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D, 0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983, + 0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989, 0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E, + 0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020, 0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6, 0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53, 0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863, + 0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012, 0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7, 0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA, 0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B, 0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482, 0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7, 0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538, 0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5, 0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A, + 0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239, 0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995, 0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999, + 0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E, 0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2, + 0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6, 0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB, + 0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF, 0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4, + 0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8, 0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4, + 0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA, 0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0, + 0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7, 0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC, + 0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1, 0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA, + 0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2, 0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6, + 0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC, 0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04, + 0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09, 0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10, + 0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15, 0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B, + 0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE, 0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C, 0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB, 0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597, + 0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8, 0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779, 0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF, 0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F, 0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D, 0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2, 0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8, 0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C, 0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069, + 0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14, 0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D, + 0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24, 0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28, + 0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C, 0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30, + 0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35, 0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E, + 0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43, 0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48, + 0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C, 0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50, + 0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55, 0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A, + 0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E, 0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62, + 0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66, 0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A, + 0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E, 0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73, + 0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D, 0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87, + 0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C, 0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93, + 0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B, 0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10, 0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB, 0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4, 0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9, 0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E, 0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420, 0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B, 0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD, 0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0, 0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD, 0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426, + 0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75, 0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8, 0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7, + 0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE, 0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2, + 0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7, 0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB, + 0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0, 0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4, + 0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8, 0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD, + 0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1, 0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5, + 0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB, 0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2, + 0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9, 0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE, + 0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3, 0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7, + 0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE, 0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05, + 0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D, 0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13, + 0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A, 0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21, + 0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29, 0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A, 0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150, 0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C, 0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A, 0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6, 0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76, 0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38, 0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8, 0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E, + 0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5, 0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769, 0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601, + 0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404, 0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F, 0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35, + 0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B, 0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41, + 0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46, 0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E, + 0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59, 0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61, + 0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66, 0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A, + 0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F, 0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76, + 0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D, 0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83, + 0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88, 0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C, + 0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92, 0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99, + 0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F, 0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5, + 0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2, 0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7, + 0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC, 0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0, + 0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2, 0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B, + 0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B, 0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21, 0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784, 0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD, 0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1, 0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1, 0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98, 0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F, 0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52, 0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC, 0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED, 0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9, 0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE, + 0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4, 0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8, + 0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF, 0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4, + 0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB, 0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0, + 0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5, 0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA, + 0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00, 0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04, + 0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09, 0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10, + 0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14, 0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19, + 0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D, 0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22, + 0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28, 0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D, + 0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31, 0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35, + 0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A, 0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E, + 0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77, 0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9, 0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC, 0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D, + 0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F, 0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D, 0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475, + 0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838, 0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408, + 0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3, 0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5, 0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052, 0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18, 0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334, + 0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E, 0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774, 0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43, + 0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47, 0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B, + 0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50, 0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54, + 0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58, 0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C, + 0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60, 0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64, + 0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68, 0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C, + 0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70, 0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76, + 0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A, 0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81, + 0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85, 0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A, + 0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E, 0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94, + 0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B, 0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6, + 0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB, 0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0, + 0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7, 0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92, 0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B, 0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F, 0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524, 0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C, 0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C, 0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD, 0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0, 0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2, 0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41, 0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27, 0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF, 0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2, + 0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9, 0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0, + 0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4, 0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD, + 0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3, 0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7, + 0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC, 0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1, + 0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5, 0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA, + 0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF, 0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03, + 0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07, 0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C, + 0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10, 0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14, + 0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18, 0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C, + 0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21, 0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26, + 0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C, 0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31, + 0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35, 0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC, 0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6, 0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324, 0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E, 0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0, 0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7, 0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532, 0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C, 0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9, 0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877, 0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB, 0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37, 0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B, + 0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F, 0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43, + 0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47, 0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B, + 0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F, 0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53, + 0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57, 0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B, + 0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F, 0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63, + 0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67, 0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B, + 0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70, 0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74, + 0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79, 0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D, + 0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81, 0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85, + 0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89, 0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D, + 0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91, 0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95, + 0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065, 0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5, 0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956, 0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D, + 0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126, 0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405, 0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34, 0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96, 0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB, 0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377, + 0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3, 0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB, 0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA, 0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773, 0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B, 0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F, + 0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3, 0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8, + 0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC, 0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1, + 0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5, 0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9, + 0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD, 0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1, + 0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5, 0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9, + 0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD, 0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1, + 0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5, 0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9, + 0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD, 0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1, + 0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5, 0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9, + 0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED, 0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1, + 0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5, 0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9, + 0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346, 0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE, 0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883, 0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0, 0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45, 0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205, 0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0, + 0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45, 0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480, + 0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A, 0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1, 0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267, + 0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026, 0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485, + 0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014, 0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7, 0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB, + 0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF, 0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03, + 0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07, 0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B, + 0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F, 0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13, + 0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17, 0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B, + 0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F, 0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23, + 0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27, 0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B, + 0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F, 0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33, + 0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37, 0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C, + 0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40, 0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45, + 0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A, 0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E, + 0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52, 0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56, + 0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A, 0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F, 0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF, 0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7, 0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7, 0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897, 0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2, 0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A, 0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF, 0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE, 0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD, 0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7, 0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41, 0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60, + 0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64, 0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68, + 0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C, 0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70, + 0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74, 0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78, + 0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C, 0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80, + 0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85, 0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89, + 0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D, 0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91, + 0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95, 0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99, + 0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E, 0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC, + 0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9, 0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37, + 0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D, 0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41, + 0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48, 0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C, + 0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52, 0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0, 0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614, + 0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721, 0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A, 0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611, + 0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD, 0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC, 0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001, 0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7, 0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B, 0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281, 0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC, 0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354, + 0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389, 0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229, + 0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56, 0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D, + 0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64, 0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B, + 0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70, 0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77, + 0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C, 0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82, + 0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86, 0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B, + 0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91, 0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96, + 0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B, 0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3, + 0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9, 0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD, + 0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4, 0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA, + 0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2, 0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7, + 0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD, 0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2, + 0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9, 0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD, + 0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2, 0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9, 0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18, 0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9, 0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE, 0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD, 0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2, 0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433, + 0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34, 0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2, 0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075, 0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4, 0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218, + 0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D, 0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8, 0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED, + 0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5, 0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9, + 0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF, 0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009, + 0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011, 0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D, + 0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023, 0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D, + 0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032, 0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C, + 0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044, 0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049, + 0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051, 0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057, + 0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D, 0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061, + 0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065, 0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B, + 0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F, 0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074, + 0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078, 0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C, + 0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2, 0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6, 0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81, 0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984, 0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5, 0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4, 0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0, 0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA, 0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B, + 0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8, 0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801, 0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B, + 0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6, 0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792, + 0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513, 0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E, + 0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088, 0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F, + 0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094, 0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E, + 0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8, 0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5, + 0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB, 0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9, + 0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0, 0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4, + 0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0, 0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE, + 0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB, 0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101, + 0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107, 0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115, + 0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C, 0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121, + 0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125, 0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129, + 0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E, 0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135, + 0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B, 0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13, 0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305, + 0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6, 0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB, 0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709, + 0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92, 0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8, 0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B, 0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A, + 0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C, 0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42, 0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195, + 0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05, 0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99, 0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF, 0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C, 0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142, + 0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147, 0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F, + 0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158, 0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E, + 0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163, 0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A, + 0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172, 0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177, + 0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184, 0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189, + 0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E, 0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194, + 0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199, 0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0, + 0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5, 0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC, + 0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0, 0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5, + 0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9, 0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF, + 0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8, 0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE, + 0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2, 0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54, 0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE, 0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6, 0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE, 0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3, 0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357, 0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320, + 0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6, 0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A, 0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA, 0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18, 0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F, + 0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A, 0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4, 0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8, + 0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC, 0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0, + 0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5, 0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB, + 0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1, 0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7, + 0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD, 0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208, + 0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E, 0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215, + 0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219, 0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224, + 0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229, 0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C, + 0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241, 0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246, + 0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D, 0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252, + 0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256, 0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C, + 0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261, 0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265, + 0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7, 0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C, 0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012, + 0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F, 0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4, 0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15, 0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392, + 0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E, 0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB, 0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228, 0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4, 0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830, 0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7, 0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739, 0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C, 0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276, + 0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C, 0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285, + 0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C, 0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295, + 0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E, 0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7, + 0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA, 0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0, + 0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6, 0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9, + 0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7, 0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC, + 0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2, 0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8, + 0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE, 0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B, + 0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313, 0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D, + 0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321, 0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325, + 0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E, 0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B, + 0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2, 0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F, 0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5, 0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9, 0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC, 0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251, 0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734, 0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A, 0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F, 0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50, 0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01, 0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D, 0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E, + 0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344, 0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B, + 0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353, 0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358, + 0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370, 0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374, + 0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A, 0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381, + 0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387, 0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C, + 0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391, 0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397, + 0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F, 0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4, + 0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC, 0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5, + 0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2, 0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8, + 0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE, 0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3, + 0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA, 0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3, + 0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8, 0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E, 0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4, 0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811, 0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899, 0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865, 0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED, 0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6, 0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD, 0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05, 0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C, 0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B, 0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71, 0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3, + 0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7, 0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE, + 0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405, 0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A, + 0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414, 0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419, + 0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F, 0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423, + 0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C, 0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430, + 0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435, 0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A, + 0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440, 0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444, + 0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449, 0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D, + 0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452, 0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456, + 0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F, 0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465, + 0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A, 0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472, + 0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B, 0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7, 0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238, 0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638, + 0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E, 0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4, 0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9, 0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4, 0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338, 0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197, 0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339, + 0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982, 0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165, + 0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A, 0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12, 0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D, 0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481, + 0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486, 0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490, + 0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494, 0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A, + 0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F, 0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4, + 0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8, 0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC, + 0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1, 0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7, + 0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0, 0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6, + 0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC, 0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4, + 0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9, 0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE, + 0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7, 0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB, + 0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1, 0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5, + 0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9, 0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE, + 0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E, 0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2, 0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740, 0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652, 0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA, 0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E, 0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3, 0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11, 0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D, 0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837, 0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E, 0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0, 0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505, 0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509, + 0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E, 0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514, + 0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519, 0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E, + 0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524, 0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528, + 0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E, 0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532, + 0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536, 0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541, + 0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546, 0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D, + 0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551, 0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555, + 0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B, 0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560, + 0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565, 0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A, + 0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E, 0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573, + 0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578, 0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580, + 0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269, 0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7, 0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF, 0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76, 0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED, 0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5, 0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6, 0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E, 0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C, + 0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292, 0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70, 0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20, 0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811, + 0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885, 0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582, + 0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589, 0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D, + 0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592, 0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596, + 0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A, 0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0, + 0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5, 0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB, + 0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2, 0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6, + 0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC, 0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0, + 0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5, 0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA, + 0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE, 0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6, + 0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA, 0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF, + 0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3, 0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8, + 0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED, 0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1, + 0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5, 0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055, + 0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870, 0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01, 0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4, 0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1, 0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A, 0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E, + 0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001, 0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C, + 0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF, 0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF, 0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178, + 0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B, 0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7, 0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29, 0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240, + 0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979, 0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC, + 0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601, 0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606, + 0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A, 0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E, + 0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613, 0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618, + 0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C, 0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620, + 0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624, 0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A, + 0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E, 0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632, + 0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636, 0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B, + 0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640, 0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644, + 0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648, 0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C, + 0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656, 0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B, + 0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660, 0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665, + 0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669, 0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC, 0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A, + 0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A, 0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D, 0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD, 0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6, 0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4, 0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957, 0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22, 0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F, 0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530, 0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146, + 0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A, 0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D, 0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673, + 0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677, 0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685, + 0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689, 0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691, + 0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697, 0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B, + 0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1, 0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB, + 0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3, 0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB, + 0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF, 0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5, + 0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2, 0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7, + 0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0, 0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5, + 0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA, 0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5, + 0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB, 0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701, + 0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B, 0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710, + 0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40, 0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850, 0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345, 0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077, + 0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8, 0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F, 0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715, 0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131, 0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E, 0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A, 0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7, 0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A, + 0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49, 0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80, 0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D, 0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726, + 0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B, 0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730, + 0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736, 0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C, + 0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742, 0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746, + 0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F, 0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754, + 0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A, 0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E, + 0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766, 0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A, + 0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F, 0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775, + 0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A, 0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784, + 0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A, 0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790, + 0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795, 0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A, + 0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E, 0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3, + 0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371, 0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D, 0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC, 0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D, 0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170, + 0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A, 0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1, 0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717, + 0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1, 0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB, + 0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61, 0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB, 0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348, + 0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E, 0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF, 0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F, + 0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B, 0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5, + 0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA, 0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2, + 0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8, 0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE, + 0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3, 0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8, + 0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE, 0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5, + 0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9, 0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE, + 0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3, 0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8, + 0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED, 0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2, + 0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6, 0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB, + 0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800, 0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805, + 0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809, 0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E, + 0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812, 0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819, + 0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E, 0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D, 0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84, 0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB, 0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E, + 0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96, 0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413, 0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24, 0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669, 0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A, + 0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677, 0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944, 0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB, 0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D, 0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6, 0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826, + 0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A, 0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E, + 0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833, 0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837, + 0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D, 0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842, + 0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848, 0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E, + 0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852, 0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858, + 0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D, 0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866, + 0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F, 0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875, + 0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A, 0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883, + 0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A, 0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890, + 0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895, 0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A, + 0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F, 0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5, + 0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9, 0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821, + 0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548, 0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E, + 0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A, 0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9, 0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C, 0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F, 0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174, + 0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2, 0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F, + 0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6, 0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E, 0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C, 0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157, 0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C, + 0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA, 0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC, 0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2, + 0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6, 0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB, + 0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0, 0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8, + 0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD, 0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3, + 0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB, 0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0, + 0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9, 0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED, + 0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5, 0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB, + 0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901, 0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906, + 0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B, 0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F, + 0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916, 0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D, + 0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922, 0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927, + 0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D, 0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932, + 0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009, 0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774, + 0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA, 0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F, 0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B, 0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C, 0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109, 0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712, 0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C, + 0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944, 0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C, 0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C, 0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1, 0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837, 0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996, + 0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A, 0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E, + 0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943, 0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948, + 0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C, 0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950, + 0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954, 0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958, + 0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C, 0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962, + 0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967, 0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B, + 0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F, 0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973, + 0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977, 0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C, + 0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982, 0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988, + 0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C, 0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990, + 0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994, 0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998, + 0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C, 0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0, + 0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065, 0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000, 0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875, 0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00, 0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890, 0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C, 0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681, + 0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3, 0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613, + 0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79, 0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5, 0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1, 0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7, 0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E, 0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2, + 0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6, 0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA, + 0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE, 0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2, + 0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6, 0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA, + 0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE, 0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD, + 0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7, 0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD, + 0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2, 0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9, + 0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE, 0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4, + 0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8, 0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC, + 0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01, 0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05, + 0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A, 0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E, + 0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12, 0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16, + 0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A, 0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70, 0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424, + 0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE, 0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896, + 0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5, 0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F, 0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18, 0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9, 0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1, 0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E, 0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D, 0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9, 0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401, 0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2, 0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20, + 0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24, 0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28, + 0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C, 0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30, + 0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34, 0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38, + 0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C, 0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41, + 0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45, 0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A, + 0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E, 0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52, + 0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56, 0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A, + 0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E, 0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62, + 0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66, 0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A, + 0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E, 0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72, + 0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76, 0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B, + 0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F, 0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33, 0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95, 0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1, 0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5, 0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7, 0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5, 0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742, + 0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0, 0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43, 0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9, 0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A, + 0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5, 0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E, 0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81, 0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85, + 0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B, 0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F, + 0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94, 0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98, + 0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C, 0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0, + 0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4, 0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8, + 0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC, 0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0, + 0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4, 0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8, + 0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC, 0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0, + 0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4, 0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8, + 0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC, 0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0, + 0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4, 0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8, + 0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC, 0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0, + 0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1, 0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8, 0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1, 0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55, 0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F, 0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08, 0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D, 0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC, 0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517, 0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F, + 0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB, 0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F, 0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323, + 0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89, 0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6, 0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA, + 0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE, 0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2, + 0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6, 0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA, + 0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE, 0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02, + 0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06, 0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B, + 0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F, 0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13, + 0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17, 0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B, + 0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F, 0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23, + 0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28, 0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C, + 0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30, 0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34, + 0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38, 0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C, + 0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40, 0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44, + 0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1, 0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F, + 0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2, 0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96, 0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740, + 0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA, 0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E, 0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099, 0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F, 0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F, 0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A, 0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB, 0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E, 0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0, 0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46, + 0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A, 0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E, + 0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52, 0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56, + 0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A, 0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E, + 0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62, 0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67, + 0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B, 0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70, + 0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74, 0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78, + 0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C, 0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80, + 0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84, 0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88, + 0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C, 0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90, + 0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94, 0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98, + 0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C, 0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0, 0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293, 0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6, 0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986, + 0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E, 0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349, 0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422, + 0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740, 0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4, 0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D, 0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5, 0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF, 0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189, 0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075, + 0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE, 0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7, + 0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B, 0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F, + 0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44, 0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B, + 0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50, 0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54, + 0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59, 0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E, + 0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64, 0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68, + 0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E, 0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72, + 0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77, 0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E, + 0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83, 0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88, + 0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F, 0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93, + 0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99, 0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D, + 0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1, 0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5, + 0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9, 0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD, + 0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10, 0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669, 0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E, 0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36, 0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C, 0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765, 0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326, + 0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366, 0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E, + 0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240, 0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281, 0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2, 0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64, 0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538, 0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF, + 0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3, 0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7, + 0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB, 0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF, + 0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3, 0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7, + 0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB, 0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF, + 0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3, 0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7, + 0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB, 0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF, + 0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3, 0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7, + 0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB, 0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF, + 0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3, 0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7, + 0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB, 0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF, + 0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03, 0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07, + 0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B, 0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74, 0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C, 0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3, 0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C, 0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028, 0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048, + 0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5, 0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6, 0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE, 0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181, 0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155, 0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2, 0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC, 0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11, + 0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15, 0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19, + 0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20, 0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A, 0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71, + 0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A, 0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E, + 0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83, 0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89, + 0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F, 0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95, + 0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99, 0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D, + 0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2, 0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7, + 0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB, 0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF, + 0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7, 0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0, + 0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7, 0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4, 0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA, 0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2, + 0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE, 0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6, + 0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF, 0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9, + 0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6, 0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00, + 0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C, 0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14, + 0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B, 0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20, + 0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A, 0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32, + 0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369, 0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621, + 0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C, 0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F, + 0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674, 0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099, 0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8, 0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1, + 0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7, 0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0, + 0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6, 0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00, + 0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04, 0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B, + 0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11, 0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16, + 0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A, 0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21, + 0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27, 0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30, + 0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36, 0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C, + 0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45, 0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E, + 0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54, 0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58, + 0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D, 0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61, + 0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65, 0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B, + 0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0, 0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6, 0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104, 0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131, + 0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146, 0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC, + 0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0, 0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC, 0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1, 0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733, 0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C, + 0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785, 0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B, + 0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773, 0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793, 0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4, 0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78, 0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D, + 0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83, 0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89, + 0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D, 0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93, + 0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98, 0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D, + 0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2, 0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6, + 0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA, 0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1, + 0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6, 0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB, + 0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF, 0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3, + 0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7, 0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB, + 0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0, 0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4, + 0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8, 0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC, + 0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0, 0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4, + 0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED, 0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844, + 0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881, 0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D, 0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297, 0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3, 0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB, + 0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4, 0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309, 0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8, 0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311, + 0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315, 0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351, + 0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392, 0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B, + 0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347, 0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317, + 0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333, 0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6, + 0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA, 0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE, + 0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2, 0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6, + 0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA, 0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE, + 0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02, 0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06, + 0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A, 0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E, + 0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12, 0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16, + 0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A, 0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E, + 0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22, 0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26, + 0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A, 0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E, + 0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32, 0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36, + 0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A, 0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E, + 0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42, 0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B, + 0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D, 0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3, + 0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393, 0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B, 0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5, 0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C, 0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8, 0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C, 0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473, + 0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489, 0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469, + 0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431, 0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA, 0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5, 0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A, 0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48, + 0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C, 0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50, + 0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54, 0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58, + 0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C, 0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60, + 0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64, 0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1, 0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6, + 0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD, 0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3, + 0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8, 0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF, + 0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9, 0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD, + 0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7, 0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1, 0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6, + 0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE, 0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C, + 0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018, 0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564, 0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543, + 0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8, 0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7, 0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629, 0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955, 0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22, + 0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C, 0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA, + 0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322, 0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A, 0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC, 0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452, 0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441, + 0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C, 0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484, + 0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C, 0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027, + 0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B, 0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032, + 0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039, 0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040, + 0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048, 0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C, + 0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056, 0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D, + 0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061, 0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069, + 0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F, 0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073, + 0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079, 0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E, + 0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086, 0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C, + 0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090, 0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098, + 0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F, 0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7, + 0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD, 0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD, + 0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7, 0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2, 0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F, 0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406, 0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454, + 0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457, 0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482, + 0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464, 0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476, + 0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD, 0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472, 0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC, 0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7, 0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3, + 0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511, 0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541, 0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C, + 0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8, 0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD, + 0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6, 0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE, + 0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4, 0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC, + 0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2, 0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7, + 0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC, 0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103, + 0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108, 0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C, + 0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110, 0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114, + 0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118, 0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D, + 0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124, 0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128, + 0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C, 0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132, + 0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136, 0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B, + 0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F, 0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144, + 0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576, 0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C, + 0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1, 0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F, + 0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B, 0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594, + 0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9, 0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC, + 0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4, 0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3, + 0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5, 0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608, + 0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623, 0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D, + 0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C, 0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C, + 0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664, 0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C, + 0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4, 0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704, 0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31, 0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147, + 0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154, 0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159, + 0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160, 0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B, + 0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B, 0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182, + 0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188, 0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193, + 0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197, 0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D, + 0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1, 0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7, + 0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC, 0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3, + 0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9, 0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE, + 0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2, 0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6, + 0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2, 0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6, + 0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA, 0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF, + 0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3, 0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61, 0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99, 0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB, 0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB, 0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E, 0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B, 0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82, 0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82, 0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD, 0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7, 0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF, 0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA, 0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9, + 0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED, 0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1, + 0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5, 0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9, + 0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD, 0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201, + 0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205, 0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209, + 0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D, 0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211, + 0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215, 0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219, + 0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D, 0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221, + 0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225, 0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229, + 0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D, 0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231, + 0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235, 0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239, + 0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D, 0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241, + 0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245, 0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321, + 0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315, 0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C, + 0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D, 0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F, + 0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7, 0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967, + 0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B, 0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D, + 0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A, 0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993, + 0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91, 0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3, 0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4, 0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4, 0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035, 0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D, + 0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F, 0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B, + 0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247, 0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B, + 0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F, 0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253, + 0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257, 0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B, + 0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F, 0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263, + 0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267, 0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B, + 0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F, 0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273, + 0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278, 0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C, + 0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280, 0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284, + 0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288, 0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C, + 0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291, 0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295, + 0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299, 0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D, + 0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1, 0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5, + 0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D, 0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D, + 0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B, 0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4, 0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B, 0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5, 0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6, 0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604, + 0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B, 0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612, + 0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619, 0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A, 0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74, 0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8, 0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE, 0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE, + 0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB, 0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0, + 0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4, 0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8, + 0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC, 0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0, + 0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4, 0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9, + 0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD, 0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1, + 0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5, 0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9, + 0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD, 0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1, + 0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5, 0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9, + 0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED, 0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1, + 0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5, 0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9, + 0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD, 0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301, + 0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305, 0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309, + 0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43, 0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E, 0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F, 0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93, + 0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C, 0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0, 0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE, 0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53, 0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0, 0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7, 0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47, 0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A, 0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C, 0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B, + 0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F, 0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313, + 0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317, 0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B, + 0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F, 0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323, + 0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327, 0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B, + 0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F, 0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333, + 0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337, 0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B, + 0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340, 0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344, + 0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348, 0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C, + 0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350, 0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354, + 0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358, 0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C, + 0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360, 0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364, + 0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368, 0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1, 0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039, 0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5, 0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0, 0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4, 0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026, 0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021, + 0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F, 0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050, + 0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B, 0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082, + 0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50, 0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71, 0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C, 0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983, + 0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3, 0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F, + 0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373, 0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377, + 0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B, 0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F, + 0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383, 0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387, + 0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B, 0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390, + 0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394, 0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398, + 0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C, 0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0, + 0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4, 0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8, + 0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC, 0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0, + 0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4, 0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8, + 0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC, 0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0, + 0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4, 0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8, + 0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD, 0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF, 0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06, + 0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8, 0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13, 0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC, 0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2, 0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8, 0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15, 0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75, 0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85, 0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92, + 0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B, 0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0, + 0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7, 0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5, + 0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF, 0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3, + 0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8, 0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC, + 0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0, 0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4, + 0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8, 0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC, + 0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0, 0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4, + 0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8, 0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC, + 0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400, 0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404, + 0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408, 0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C, + 0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410, 0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414, + 0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418, 0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C, + 0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420, 0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424, + 0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428, 0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C, + 0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0, 0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2, + 0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0, 0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0, + 0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE, 0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE, 0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07, + 0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F, 0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21, 0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25, + 0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B, 0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30, + 0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35, 0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E, + 0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE, 0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0, 0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7, 0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F, + 0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425, 0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C, + 0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432, 0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436, + 0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A, 0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F, + 0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443, 0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447, + 0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B, 0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F, + 0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453, 0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457, + 0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B, 0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F, + 0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463, 0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467, + 0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C, 0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470, + 0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474, 0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478, + 0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C, 0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480, + 0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484, 0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7, + 0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA, 0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520, + 0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C, 0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477, + 0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E, 0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B, + 0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490, 0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA, + 0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753, 0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798, 0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C, 0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9, 0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2, 0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832, + 0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E, 0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883, + 0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841, 0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A, + 0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F, 0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F, 0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533, + 0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B, 0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E, + 0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578, 0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C, + 0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581, 0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585, + 0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589, 0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D, + 0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591, 0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595, + 0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599, 0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D, + 0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1, 0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5, + 0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9, 0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD, + 0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1, 0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5, + 0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9, 0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD, + 0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1, 0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5, + 0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9, 0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3, 0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960, + 0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B, 0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE, 0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979, + 0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB, 0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0, 0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED, + 0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2, 0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79, 0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97, 0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81, + 0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92, 0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B, + 0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D, 0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75, + 0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79, 0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81, + 0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B, 0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF, + 0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3, 0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7, + 0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB, 0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF, + 0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3, 0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7, + 0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613, 0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620, + 0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626, 0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B, + 0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630, 0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A, + 0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A, 0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652, + 0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658, 0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D, + 0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665, 0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E, + 0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673, 0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B, + 0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F, 0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683, + 0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A, 0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217, 0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221, + 0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7, 0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F, + 0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE, 0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619, + 0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600, 0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634, + 0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006, 0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F, + 0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677, 0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6, 0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45, 0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7, 0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE, + 0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E, 0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F, + 0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B, 0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308, + 0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E, 0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695, + 0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D, 0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1, + 0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5, 0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA, + 0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE, 0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4, + 0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA, 0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3, + 0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0, 0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6, + 0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA, 0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE, + 0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3, 0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7, + 0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE, 0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4, + 0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB, 0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702, + 0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B, 0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712, + 0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718, 0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D, + 0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8, 0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07, 0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18, + 0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29, 0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535, + 0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252, 0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216, + 0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC, 0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7, 0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD, 0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D, 0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715, + 0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E, 0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148, + 0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159, 0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169, + 0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167, 0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182, + 0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA, 0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB, + 0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724, 0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728, + 0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E, 0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734, + 0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A, 0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F, + 0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743, 0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747, + 0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B, 0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F, + 0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755, 0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C, + 0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764, 0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A, + 0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E, 0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772, + 0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779, 0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E, + 0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782, 0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787, + 0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C, 0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793, + 0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799, 0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D, + 0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37, 0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59, + 0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5, 0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51, 0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4, + 0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2, 0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096, + 0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7, 0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA, + 0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F, 0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168, + 0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178, 0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5, + 0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4, 0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228, + 0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9, 0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248, + 0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946, 0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953, + 0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960, 0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985, + 0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3, 0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F, + 0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5, 0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9, + 0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0, 0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6, + 0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA, 0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE, + 0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2, 0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6, + 0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA, 0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE, + 0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2, 0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6, + 0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA, 0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE, + 0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2, 0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8, + 0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1, 0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8, + 0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC, 0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800, + 0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804, 0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808, + 0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C, 0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D, + 0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059, 0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D, + 0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB, 0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6, 0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817, + 0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D, 0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A, + 0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825, 0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E, + 0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826, 0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A, + 0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887, 0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9, 0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E, 0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB, + 0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D, 0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A, + 0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726, 0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751, + 0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768, 0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812, + 0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816, 0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A, + 0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E, 0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822, + 0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826, 0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A, + 0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E, 0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832, + 0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836, 0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A, + 0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E, 0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842, + 0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846, 0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A, + 0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E, 0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852, + 0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856, 0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A, + 0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E, 0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862, + 0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866, 0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A, + 0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E, 0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D, + 0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791, 0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E, 0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572, + 0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61, 0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E, 0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485, + 0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A, 0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490, + 0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A, 0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4, + 0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC, 0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4, + 0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9, 0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA, 0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE, + 0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5, 0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0, 0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7, + 0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870, 0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874, + 0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895, 0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9, + 0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD, 0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1, + 0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5, 0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9, + 0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD, 0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1, + 0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5, 0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9, + 0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD, 0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6, + 0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD, 0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3, + 0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9, 0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED, + 0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1, 0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5, + 0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9, 0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD, + 0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901, 0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905, + 0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB, 0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4, + 0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC, 0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502, + 0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A, 0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512, + 0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516, 0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E, + 0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B, 0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532, + 0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538, 0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542, + 0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546, 0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F, + 0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556, 0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B, + 0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561, 0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566, + 0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A, 0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571, + 0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7, 0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47, 0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14, + 0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B, 0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911, + 0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915, 0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919, + 0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D, 0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921, + 0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925, 0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929, + 0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D, 0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932, + 0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936, 0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A, + 0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E, 0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942, + 0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946, 0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A, + 0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E, 0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952, + 0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958, 0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C, + 0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960, 0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966, + 0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B, 0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF, 0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E, + 0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE, 0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22, + 0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B, 0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A, 0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44, + 0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49, 0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B, 0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66, + 0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A, 0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596, 0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3, + 0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4, 0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8, 0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF, 0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C, + 0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618, 0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E, + 0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D, 0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1, + 0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6, 0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB, + 0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF, 0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3, + 0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7, 0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB, + 0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF, 0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3, + 0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7, 0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB, + 0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF, 0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3, + 0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7, 0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB, + 0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF, 0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3, + 0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7, 0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB, + 0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF, 0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3, + 0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7, 0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C, + 0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D, 0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643, + 0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E, 0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B, + 0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78, 0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC, 0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864, + 0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F, 0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE, 0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0, 0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B, + 0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936, 0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC, 0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C, + 0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026, 0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031, + 0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046, 0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071, + 0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883, 0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD, + 0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01, 0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05, + 0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09, 0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D, + 0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11, 0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15, + 0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19, 0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D, + 0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21, 0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25, + 0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29, 0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D, + 0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31, 0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35, + 0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39, 0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D, + 0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41, 0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45, + 0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49, 0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D, + 0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51, 0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55, + 0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59, 0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F, + 0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E, 0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5, + 0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C, 0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C, + 0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B, 0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6, 0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9, 0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1, + 0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0, 0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707, 0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D, + 0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E, 0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E, + 0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729, 0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722, + 0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760, 0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B, + 0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764, 0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B, 0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F, + 0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63, 0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67, + 0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B, 0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D, + 0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99, 0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB, + 0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF, 0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5, + 0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE, 0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6, + 0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA, 0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0, + 0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6, 0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB, + 0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0, 0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5, + 0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA, 0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1, + 0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5, 0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA, + 0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF, 0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04, + 0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788, 0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5, 0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB, 0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816, + 0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B, 0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210, 0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03, + 0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B, 0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20, 0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45, 0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72, 0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7, + 0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8, 0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1, 0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5, + 0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE, 0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B, 0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10, + 0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15, 0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19, + 0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D, 0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22, + 0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27, 0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B, + 0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30, 0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35, + 0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39, 0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F, + 0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B, 0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52, + 0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57, 0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B, + 0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F, 0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63, + 0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67, 0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B, + 0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F, 0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73, + 0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77, 0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B, + 0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38, 0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201, + 0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844, 0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D, + 0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238, 0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E, + 0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F, 0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E, + 0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF, 0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7, + 0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C, 0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC, 0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC, + 0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7, 0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1, 0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE, 0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91, 0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E, 0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D, + 0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81, 0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85, + 0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89, 0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D, + 0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91, 0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95, + 0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99, 0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D, + 0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1, 0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5, + 0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9, 0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD, + 0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1, 0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5, + 0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9, 0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD, + 0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1, 0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5, + 0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9, 0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD, + 0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1, 0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5, + 0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9, 0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161, + 0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D, 0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179, + 0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D, 0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA, + 0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5, 0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59, 0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7, 0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF, + 0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7, 0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14, 0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40, 0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51, 0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85, 0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A, 0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC, 0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF, + 0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3, 0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7, + 0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB, 0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF, + 0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3, 0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7, + 0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB, 0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF, + 0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03, 0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07, + 0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B, 0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F, + 0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13, 0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17, + 0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B, 0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F, + 0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23, 0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27, + 0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B, 0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F, + 0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33, 0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37, + 0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B, 0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3, 0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708, + 0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D, 0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83, + 0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88, 0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC, 0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8, 0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F, + 0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82, 0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88, + 0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90, 0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95, + 0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F, 0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3, + 0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8, 0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE, + 0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3, 0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7, + 0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD, 0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7, + 0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D, 0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41, + 0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45, 0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49, + 0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D, 0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51, + 0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55, 0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59, + 0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D, 0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61, + 0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65, 0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69, + 0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D, 0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71, + 0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75, 0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79, + 0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E, 0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89, + 0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93, 0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99, + 0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF, 0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0, + 0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9, 0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB, + 0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD, 0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3, + 0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8, 0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791, 0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1, 0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0, 0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC, + 0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47, 0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955, 0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED, 0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE, 0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88, + 0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D, 0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD, + 0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9, 0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39, 0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44, + 0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6, 0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA, + 0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE, 0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2, + 0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6, 0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA, + 0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE, 0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02, + 0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06, 0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A, + 0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E, 0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12, + 0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16, 0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A, + 0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E, 0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22, + 0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26, 0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A, + 0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E, 0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32, + 0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36, 0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A, + 0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E, 0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42, + 0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46, 0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A, + 0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E, 0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52, + 0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56, 0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A, + 0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E, 0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62, + 0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66, 0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A, + 0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E, 0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72, + 0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76, 0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A, + 0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E, 0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82, + 0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86, 0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A, + 0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E, 0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92, + 0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96, 0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A, + 0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E, 0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2, + 0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6, 0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA, + 0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE, 0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2, + 0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6, 0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA, + 0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE, 0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2, + 0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6, 0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA, + 0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE, 0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2, + 0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6, 0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA, + 0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE, 0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2, + 0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6, 0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA, + 0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE, 0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2, + 0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6, 0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA, + 0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE, 0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02, + 0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06, 0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A, + 0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E, 0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12, + 0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16, 0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A, + 0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E, 0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40, 0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53, + 0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D, 0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62, + 0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72, 0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77, + 0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B, 0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81, + 0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86, 0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D, + 0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91, 0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97, + 0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B, 0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1, + 0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5, 0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA, + 0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE, 0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2, + 0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7, 0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF, + 0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3, 0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8, + 0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0, 0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6, + 0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE, 0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED, 0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2, + 0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6, 0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD, + 0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02, 0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06, + 0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A, 0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12, + 0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18, 0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D, + 0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23, 0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27, + 0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B, 0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31, + 0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35, 0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C, + 0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42, 0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47, + 0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B, 0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F, + 0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55, 0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59, + 0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D, 0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61, + 0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65, 0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69, + 0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D, 0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71, + 0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75, 0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79, + 0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D, 0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D, + 0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91, 0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95, + 0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C, 0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2, + 0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C, 0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1, + 0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F, 0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18, + 0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23, 0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */ +static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ + 0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6, + 0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6, + 0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF, + 0x00D8, 0xA8AA, 0x00DE, 0xA8AD, 0x00DF, 0xA9AC, 0x00E6, 0xA9A1, 0x00F0, 0xA9A3, 0x00F7, 0xA1C0, 0x00F8, 0xA9AA, 0x00FE, 0xA9AD, + 0x0111, 0xA9A2, 0x0126, 0xA8A4, 0x0127, 0xA9A4, 0x0131, 0xA9A5, 0x0132, 0xA8A6, 0x0133, 0xA9A6, 0x0138, 0xA9A7, 0x013F, 0xA8A8, + 0x0140, 0xA9A8, 0x0141, 0xA8A9, 0x0142, 0xA9A9, 0x0149, 0xA9B0, 0x014A, 0xA8AF, 0x014B, 0xA9AF, 0x0152, 0xA8AB, 0x0153, 0xA9AB, + 0x0166, 0xA8AE, 0x0167, 0xA9AE, 0x02C7, 0xA2A7, 0x02D0, 0xA2B0, 0x02D8, 0xA2A8, 0x02D9, 0xA2AB, 0x02DA, 0xA2AA, 0x02DB, 0xA2AD, + 0x02DD, 0xA2A9, 0x0391, 0xA5C1, 0x0392, 0xA5C2, 0x0393, 0xA5C3, 0x0394, 0xA5C4, 0x0395, 0xA5C5, 0x0396, 0xA5C6, 0x0397, 0xA5C7, + 0x0398, 0xA5C8, 0x0399, 0xA5C9, 0x039A, 0xA5CA, 0x039B, 0xA5CB, 0x039C, 0xA5CC, 0x039D, 0xA5CD, 0x039E, 0xA5CE, 0x039F, 0xA5CF, + 0x03A0, 0xA5D0, 0x03A1, 0xA5D1, 0x03A3, 0xA5D2, 0x03A4, 0xA5D3, 0x03A5, 0xA5D4, 0x03A6, 0xA5D5, 0x03A7, 0xA5D6, 0x03A8, 0xA5D7, + 0x03A9, 0xA5D8, 0x03B1, 0xA5E1, 0x03B2, 0xA5E2, 0x03B3, 0xA5E3, 0x03B4, 0xA5E4, 0x03B5, 0xA5E5, 0x03B6, 0xA5E6, 0x03B7, 0xA5E7, + 0x03B8, 0xA5E8, 0x03B9, 0xA5E9, 0x03BA, 0xA5EA, 0x03BB, 0xA5EB, 0x03BC, 0xA5EC, 0x03BD, 0xA5ED, 0x03BE, 0xA5EE, 0x03BF, 0xA5EF, + 0x03C0, 0xA5F0, 0x03C1, 0xA5F1, 0x03C3, 0xA5F2, 0x03C4, 0xA5F3, 0x03C5, 0xA5F4, 0x03C6, 0xA5F5, 0x03C7, 0xA5F6, 0x03C8, 0xA5F7, + 0x03C9, 0xA5F8, 0x0401, 0xACA7, 0x0410, 0xACA1, 0x0411, 0xACA2, 0x0412, 0xACA3, 0x0413, 0xACA4, 0x0414, 0xACA5, 0x0415, 0xACA6, + 0x0416, 0xACA8, 0x0417, 0xACA9, 0x0418, 0xACAA, 0x0419, 0xACAB, 0x041A, 0xACAC, 0x041B, 0xACAD, 0x041C, 0xACAE, 0x041D, 0xACAF, + 0x041E, 0xACB0, 0x041F, 0xACB1, 0x0420, 0xACB2, 0x0421, 0xACB3, 0x0422, 0xACB4, 0x0423, 0xACB5, 0x0424, 0xACB6, 0x0425, 0xACB7, + 0x0426, 0xACB8, 0x0427, 0xACB9, 0x0428, 0xACBA, 0x0429, 0xACBB, 0x042A, 0xACBC, 0x042B, 0xACBD, 0x042C, 0xACBE, 0x042D, 0xACBF, + 0x042E, 0xACC0, 0x042F, 0xACC1, 0x0430, 0xACD1, 0x0431, 0xACD2, 0x0432, 0xACD3, 0x0433, 0xACD4, 0x0434, 0xACD5, 0x0435, 0xACD6, + 0x0436, 0xACD8, 0x0437, 0xACD9, 0x0438, 0xACDA, 0x0439, 0xACDB, 0x043A, 0xACDC, 0x043B, 0xACDD, 0x043C, 0xACDE, 0x043D, 0xACDF, + 0x043E, 0xACE0, 0x043F, 0xACE1, 0x0440, 0xACE2, 0x0441, 0xACE3, 0x0442, 0xACE4, 0x0443, 0xACE5, 0x0444, 0xACE6, 0x0445, 0xACE7, + 0x0446, 0xACE8, 0x0447, 0xACE9, 0x0448, 0xACEA, 0x0449, 0xACEB, 0x044A, 0xACEC, 0x044B, 0xACED, 0x044C, 0xACEE, 0x044D, 0xACEF, + 0x044E, 0xACF0, 0x044F, 0xACF1, 0x0451, 0xACD7, 0x2015, 0xA1AA, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, + 0x2020, 0xA2D3, 0x2021, 0xA2D4, 0x2025, 0xA1A5, 0x2026, 0xA1A6, 0x2030, 0xA2B6, 0x2032, 0xA1C7, 0x2033, 0xA1C8, 0x203B, 0xA1D8, + 0x2074, 0xA9F9, 0x207F, 0xA9FA, 0x2081, 0xA9FB, 0x2082, 0xA9FC, 0x2083, 0xA9FD, 0x2084, 0xA9FE, 0x20AC, 0xA2E6, 0x2103, 0xA1C9, + 0x2109, 0xA2B5, 0x2113, 0xA7A4, 0x2116, 0xA2E0, 0x2121, 0xA2E5, 0x2122, 0xA2E2, 0x2126, 0xA7D9, 0x212B, 0xA1CA, 0x2153, 0xA8F7, + 0x2154, 0xA8F8, 0x215B, 0xA8FB, 0x215C, 0xA8FC, 0x215D, 0xA8FD, 0x215E, 0xA8FE, 0x2160, 0xA5B0, 0x2161, 0xA5B1, 0x2162, 0xA5B2, + 0x2163, 0xA5B3, 0x2164, 0xA5B4, 0x2165, 0xA5B5, 0x2166, 0xA5B6, 0x2167, 0xA5B7, 0x2168, 0xA5B8, 0x2169, 0xA5B9, 0x2170, 0xA5A1, + 0x2171, 0xA5A2, 0x2172, 0xA5A3, 0x2173, 0xA5A4, 0x2174, 0xA5A5, 0x2175, 0xA5A6, 0x2176, 0xA5A7, 0x2177, 0xA5A8, 0x2178, 0xA5A9, + 0x2179, 0xA5AA, 0x2190, 0xA1E7, 0x2191, 0xA1E8, 0x2192, 0xA1E6, 0x2193, 0xA1E9, 0x2194, 0xA1EA, 0x2195, 0xA2D5, 0x2196, 0xA2D8, + 0x2197, 0xA2D6, 0x2198, 0xA2D9, 0x2199, 0xA2D7, 0x21D2, 0xA2A1, 0x21D4, 0xA2A2, 0x2200, 0xA2A3, 0x2202, 0xA1D3, 0x2203, 0xA2A4, + 0x2207, 0xA1D4, 0x2208, 0xA1F4, 0x220B, 0xA1F5, 0x220F, 0xA2B3, 0x2211, 0xA2B2, 0x221A, 0xA1EE, 0x221D, 0xA1F0, 0x221E, 0xA1C4, + 0x2220, 0xA1D0, 0x2225, 0xA1AB, 0x2227, 0xA1FC, 0x2228, 0xA1FD, 0x2229, 0xA1FB, 0x222A, 0xA1FA, 0x222B, 0xA1F2, 0x222C, 0xA1F3, + 0x222E, 0xA2B1, 0x2234, 0xA1C5, 0x2235, 0xA1F1, 0x223C, 0xA1AD, 0x223D, 0xA1EF, 0x2252, 0xA1D6, 0x2260, 0xA1C1, 0x2261, 0xA1D5, + 0x2264, 0xA1C2, 0x2265, 0xA1C3, 0x226A, 0xA1EC, 0x226B, 0xA1ED, 0x2282, 0xA1F8, 0x2283, 0xA1F9, 0x2286, 0xA1F6, 0x2287, 0xA1F7, + 0x2299, 0xA2C1, 0x22A5, 0xA1D1, 0x2312, 0xA1D2, 0x2460, 0xA8E7, 0x2461, 0xA8E8, 0x2462, 0xA8E9, 0x2463, 0xA8EA, 0x2464, 0xA8EB, + 0x2465, 0xA8EC, 0x2466, 0xA8ED, 0x2467, 0xA8EE, 0x2468, 0xA8EF, 0x2469, 0xA8F0, 0x246A, 0xA8F1, 0x246B, 0xA8F2, 0x246C, 0xA8F3, + 0x246D, 0xA8F4, 0x246E, 0xA8F5, 0x2474, 0xA9E7, 0x2475, 0xA9E8, 0x2476, 0xA9E9, 0x2477, 0xA9EA, 0x2478, 0xA9EB, 0x2479, 0xA9EC, + 0x247A, 0xA9ED, 0x247B, 0xA9EE, 0x247C, 0xA9EF, 0x247D, 0xA9F0, 0x247E, 0xA9F1, 0x247F, 0xA9F2, 0x2480, 0xA9F3, 0x2481, 0xA9F4, + 0x2482, 0xA9F5, 0x249C, 0xA9CD, 0x249D, 0xA9CE, 0x249E, 0xA9CF, 0x249F, 0xA9D0, 0x24A0, 0xA9D1, 0x24A1, 0xA9D2, 0x24A2, 0xA9D3, + 0x24A3, 0xA9D4, 0x24A4, 0xA9D5, 0x24A5, 0xA9D6, 0x24A6, 0xA9D7, 0x24A7, 0xA9D8, 0x24A8, 0xA9D9, 0x24A9, 0xA9DA, 0x24AA, 0xA9DB, + 0x24AB, 0xA9DC, 0x24AC, 0xA9DD, 0x24AD, 0xA9DE, 0x24AE, 0xA9DF, 0x24AF, 0xA9E0, 0x24B0, 0xA9E1, 0x24B1, 0xA9E2, 0x24B2, 0xA9E3, + 0x24B3, 0xA9E4, 0x24B4, 0xA9E5, 0x24B5, 0xA9E6, 0x24D0, 0xA8CD, 0x24D1, 0xA8CE, 0x24D2, 0xA8CF, 0x24D3, 0xA8D0, 0x24D4, 0xA8D1, + 0x24D5, 0xA8D2, 0x24D6, 0xA8D3, 0x24D7, 0xA8D4, 0x24D8, 0xA8D5, 0x24D9, 0xA8D6, 0x24DA, 0xA8D7, 0x24DB, 0xA8D8, 0x24DC, 0xA8D9, + 0x24DD, 0xA8DA, 0x24DE, 0xA8DB, 0x24DF, 0xA8DC, 0x24E0, 0xA8DD, 0x24E1, 0xA8DE, 0x24E2, 0xA8DF, 0x24E3, 0xA8E0, 0x24E4, 0xA8E1, + 0x24E5, 0xA8E2, 0x24E6, 0xA8E3, 0x24E7, 0xA8E4, 0x24E8, 0xA8E5, 0x24E9, 0xA8E6, 0x2500, 0xA6A1, 0x2501, 0xA6AC, 0x2502, 0xA6A2, + 0x2503, 0xA6AD, 0x250C, 0xA6A3, 0x250D, 0xA6C8, 0x250E, 0xA6C7, 0x250F, 0xA6AE, 0x2510, 0xA6A4, 0x2511, 0xA6C2, 0x2512, 0xA6C1, + 0x2513, 0xA6AF, 0x2514, 0xA6A6, 0x2515, 0xA6C6, 0x2516, 0xA6C5, 0x2517, 0xA6B1, 0x2518, 0xA6A5, 0x2519, 0xA6C4, 0x251A, 0xA6C3, + 0x251B, 0xA6B0, 0x251C, 0xA6A7, 0x251D, 0xA6BC, 0x251E, 0xA6C9, 0x251F, 0xA6CA, 0x2520, 0xA6B7, 0x2521, 0xA6CB, 0x2522, 0xA6CC, + 0x2523, 0xA6B2, 0x2524, 0xA6A9, 0x2525, 0xA6BE, 0x2526, 0xA6CD, 0x2527, 0xA6CE, 0x2528, 0xA6B9, 0x2529, 0xA6CF, 0x252A, 0xA6D0, + 0x252B, 0xA6B4, 0x252C, 0xA6A8, 0x252D, 0xA6D1, 0x252E, 0xA6D2, 0x252F, 0xA6B8, 0x2530, 0xA6BD, 0x2531, 0xA6D3, 0x2532, 0xA6D4, + 0x2533, 0xA6B3, 0x2534, 0xA6AA, 0x2535, 0xA6D5, 0x2536, 0xA6D6, 0x2537, 0xA6BA, 0x2538, 0xA6BF, 0x2539, 0xA6D7, 0x253A, 0xA6D8, + 0x253B, 0xA6B5, 0x253C, 0xA6AB, 0x253D, 0xA6D9, 0x253E, 0xA6DA, 0x253F, 0xA6BB, 0x2540, 0xA6DB, 0x2541, 0xA6DC, 0x2542, 0xA6C0, + 0x2543, 0xA6DD, 0x2544, 0xA6DE, 0x2545, 0xA6DF, 0x2546, 0xA6E0, 0x2547, 0xA6E1, 0x2548, 0xA6E2, 0x2549, 0xA6E3, 0x254A, 0xA6E4, + 0x254B, 0xA6B6, 0x2592, 0xA2C6, 0x25A0, 0xA1E1, 0x25A1, 0xA1E0, 0x25A3, 0xA2C3, 0x25A4, 0xA2C7, 0x25A5, 0xA2C8, 0x25A6, 0xA2CB, + 0x25A7, 0xA2CA, 0x25A8, 0xA2C9, 0x25A9, 0xA2CC, 0x25B2, 0xA1E3, 0x25B3, 0xA1E2, 0x25B6, 0xA2BA, 0x25B7, 0xA2B9, 0x25BC, 0xA1E5, + 0x25BD, 0xA1E4, 0x25C0, 0xA2B8, 0x25C1, 0xA2B7, 0x25C6, 0xA1DF, 0x25C7, 0xA1DE, 0x25C8, 0xA2C2, 0x25CB, 0xA1DB, 0x25CE, 0xA1DD, + 0x25CF, 0xA1DC, 0x25D0, 0xA2C4, 0x25D1, 0xA2C5, 0x2605, 0xA1DA, 0x2606, 0xA1D9, 0x260E, 0xA2CF, 0x260F, 0xA2CE, 0x261C, 0xA2D0, + 0x261E, 0xA2D1, 0x2640, 0xA1CF, 0x2642, 0xA1CE, 0x2660, 0xA2BC, 0x2661, 0xA2BD, 0x2663, 0xA2C0, 0x2664, 0xA2BB, 0x2665, 0xA2BE, + 0x2667, 0xA2BF, 0x2668, 0xA2CD, 0x2669, 0xA2DB, 0x266A, 0xA2DC, 0x266C, 0xA2DD, 0x266D, 0xA2DA, 0x3000, 0xA1A1, 0x3001, 0xA1A2, + 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3008, 0xA1B4, 0x3009, 0xA1B5, 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, + 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BC, 0x3011, 0xA1BD, 0x3013, 0xA1EB, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3041, 0xAAA1, + 0x3042, 0xAAA2, 0x3043, 0xAAA3, 0x3044, 0xAAA4, 0x3045, 0xAAA5, 0x3046, 0xAAA6, 0x3047, 0xAAA7, 0x3048, 0xAAA8, 0x3049, 0xAAA9, + 0x304A, 0xAAAA, 0x304B, 0xAAAB, 0x304C, 0xAAAC, 0x304D, 0xAAAD, 0x304E, 0xAAAE, 0x304F, 0xAAAF, 0x3050, 0xAAB0, 0x3051, 0xAAB1, + 0x3052, 0xAAB2, 0x3053, 0xAAB3, 0x3054, 0xAAB4, 0x3055, 0xAAB5, 0x3056, 0xAAB6, 0x3057, 0xAAB7, 0x3058, 0xAAB8, 0x3059, 0xAAB9, + 0x305A, 0xAABA, 0x305B, 0xAABB, 0x305C, 0xAABC, 0x305D, 0xAABD, 0x305E, 0xAABE, 0x305F, 0xAABF, 0x3060, 0xAAC0, 0x3061, 0xAAC1, + 0x3062, 0xAAC2, 0x3063, 0xAAC3, 0x3064, 0xAAC4, 0x3065, 0xAAC5, 0x3066, 0xAAC6, 0x3067, 0xAAC7, 0x3068, 0xAAC8, 0x3069, 0xAAC9, + 0x306A, 0xAACA, 0x306B, 0xAACB, 0x306C, 0xAACC, 0x306D, 0xAACD, 0x306E, 0xAACE, 0x306F, 0xAACF, 0x3070, 0xAAD0, 0x3071, 0xAAD1, + 0x3072, 0xAAD2, 0x3073, 0xAAD3, 0x3074, 0xAAD4, 0x3075, 0xAAD5, 0x3076, 0xAAD6, 0x3077, 0xAAD7, 0x3078, 0xAAD8, 0x3079, 0xAAD9, + 0x307A, 0xAADA, 0x307B, 0xAADB, 0x307C, 0xAADC, 0x307D, 0xAADD, 0x307E, 0xAADE, 0x307F, 0xAADF, 0x3080, 0xAAE0, 0x3081, 0xAAE1, + 0x3082, 0xAAE2, 0x3083, 0xAAE3, 0x3084, 0xAAE4, 0x3085, 0xAAE5, 0x3086, 0xAAE6, 0x3087, 0xAAE7, 0x3088, 0xAAE8, 0x3089, 0xAAE9, + 0x308A, 0xAAEA, 0x308B, 0xAAEB, 0x308C, 0xAAEC, 0x308D, 0xAAED, 0x308E, 0xAAEE, 0x308F, 0xAAEF, 0x3090, 0xAAF0, 0x3091, 0xAAF1, + 0x3092, 0xAAF2, 0x3093, 0xAAF3, 0x30A1, 0xABA1, 0x30A2, 0xABA2, 0x30A3, 0xABA3, 0x30A4, 0xABA4, 0x30A5, 0xABA5, 0x30A6, 0xABA6, + 0x30A7, 0xABA7, 0x30A8, 0xABA8, 0x30A9, 0xABA9, 0x30AA, 0xABAA, 0x30AB, 0xABAB, 0x30AC, 0xABAC, 0x30AD, 0xABAD, 0x30AE, 0xABAE, + 0x30AF, 0xABAF, 0x30B0, 0xABB0, 0x30B1, 0xABB1, 0x30B2, 0xABB2, 0x30B3, 0xABB3, 0x30B4, 0xABB4, 0x30B5, 0xABB5, 0x30B6, 0xABB6, + 0x30B7, 0xABB7, 0x30B8, 0xABB8, 0x30B9, 0xABB9, 0x30BA, 0xABBA, 0x30BB, 0xABBB, 0x30BC, 0xABBC, 0x30BD, 0xABBD, 0x30BE, 0xABBE, + 0x30BF, 0xABBF, 0x30C0, 0xABC0, 0x30C1, 0xABC1, 0x30C2, 0xABC2, 0x30C3, 0xABC3, 0x30C4, 0xABC4, 0x30C5, 0xABC5, 0x30C6, 0xABC6, + 0x30C7, 0xABC7, 0x30C8, 0xABC8, 0x30C9, 0xABC9, 0x30CA, 0xABCA, 0x30CB, 0xABCB, 0x30CC, 0xABCC, 0x30CD, 0xABCD, 0x30CE, 0xABCE, + 0x30CF, 0xABCF, 0x30D0, 0xABD0, 0x30D1, 0xABD1, 0x30D2, 0xABD2, 0x30D3, 0xABD3, 0x30D4, 0xABD4, 0x30D5, 0xABD5, 0x30D6, 0xABD6, + 0x30D7, 0xABD7, 0x30D8, 0xABD8, 0x30D9, 0xABD9, 0x30DA, 0xABDA, 0x30DB, 0xABDB, 0x30DC, 0xABDC, 0x30DD, 0xABDD, 0x30DE, 0xABDE, + 0x30DF, 0xABDF, 0x30E0, 0xABE0, 0x30E1, 0xABE1, 0x30E2, 0xABE2, 0x30E3, 0xABE3, 0x30E4, 0xABE4, 0x30E5, 0xABE5, 0x30E6, 0xABE6, + 0x30E7, 0xABE7, 0x30E8, 0xABE8, 0x30E9, 0xABE9, 0x30EA, 0xABEA, 0x30EB, 0xABEB, 0x30EC, 0xABEC, 0x30ED, 0xABED, 0x30EE, 0xABEE, + 0x30EF, 0xABEF, 0x30F0, 0xABF0, 0x30F1, 0xABF1, 0x30F2, 0xABF2, 0x30F3, 0xABF3, 0x30F4, 0xABF4, 0x30F5, 0xABF5, 0x30F6, 0xABF6, + 0x3131, 0xA4A1, 0x3132, 0xA4A2, 0x3133, 0xA4A3, 0x3134, 0xA4A4, 0x3135, 0xA4A5, 0x3136, 0xA4A6, 0x3137, 0xA4A7, 0x3138, 0xA4A8, + 0x3139, 0xA4A9, 0x313A, 0xA4AA, 0x313B, 0xA4AB, 0x313C, 0xA4AC, 0x313D, 0xA4AD, 0x313E, 0xA4AE, 0x313F, 0xA4AF, 0x3140, 0xA4B0, + 0x3141, 0xA4B1, 0x3142, 0xA4B2, 0x3143, 0xA4B3, 0x3144, 0xA4B4, 0x3145, 0xA4B5, 0x3146, 0xA4B6, 0x3147, 0xA4B7, 0x3148, 0xA4B8, + 0x3149, 0xA4B9, 0x314A, 0xA4BA, 0x314B, 0xA4BB, 0x314C, 0xA4BC, 0x314D, 0xA4BD, 0x314E, 0xA4BE, 0x314F, 0xA4BF, 0x3150, 0xA4C0, + 0x3151, 0xA4C1, 0x3152, 0xA4C2, 0x3153, 0xA4C3, 0x3154, 0xA4C4, 0x3155, 0xA4C5, 0x3156, 0xA4C6, 0x3157, 0xA4C7, 0x3158, 0xA4C8, + 0x3159, 0xA4C9, 0x315A, 0xA4CA, 0x315B, 0xA4CB, 0x315C, 0xA4CC, 0x315D, 0xA4CD, 0x315E, 0xA4CE, 0x315F, 0xA4CF, 0x3160, 0xA4D0, + 0x3161, 0xA4D1, 0x3162, 0xA4D2, 0x3163, 0xA4D3, 0x3164, 0xA4D4, 0x3165, 0xA4D5, 0x3166, 0xA4D6, 0x3167, 0xA4D7, 0x3168, 0xA4D8, + 0x3169, 0xA4D9, 0x316A, 0xA4DA, 0x316B, 0xA4DB, 0x316C, 0xA4DC, 0x316D, 0xA4DD, 0x316E, 0xA4DE, 0x316F, 0xA4DF, 0x3170, 0xA4E0, + 0x3171, 0xA4E1, 0x3172, 0xA4E2, 0x3173, 0xA4E3, 0x3174, 0xA4E4, 0x3175, 0xA4E5, 0x3176, 0xA4E6, 0x3177, 0xA4E7, 0x3178, 0xA4E8, + 0x3179, 0xA4E9, 0x317A, 0xA4EA, 0x317B, 0xA4EB, 0x317C, 0xA4EC, 0x317D, 0xA4ED, 0x317E, 0xA4EE, 0x317F, 0xA4EF, 0x3180, 0xA4F0, + 0x3181, 0xA4F1, 0x3182, 0xA4F2, 0x3183, 0xA4F3, 0x3184, 0xA4F4, 0x3185, 0xA4F5, 0x3186, 0xA4F6, 0x3187, 0xA4F7, 0x3188, 0xA4F8, + 0x3189, 0xA4F9, 0x318A, 0xA4FA, 0x318B, 0xA4FB, 0x318C, 0xA4FC, 0x318D, 0xA4FD, 0x318E, 0xA4FE, 0x3200, 0xA9B1, 0x3201, 0xA9B2, + 0x3202, 0xA9B3, 0x3203, 0xA9B4, 0x3204, 0xA9B5, 0x3205, 0xA9B6, 0x3206, 0xA9B7, 0x3207, 0xA9B8, 0x3208, 0xA9B9, 0x3209, 0xA9BA, + 0x320A, 0xA9BB, 0x320B, 0xA9BC, 0x320C, 0xA9BD, 0x320D, 0xA9BE, 0x320E, 0xA9BF, 0x320F, 0xA9C0, 0x3210, 0xA9C1, 0x3211, 0xA9C2, + 0x3212, 0xA9C3, 0x3213, 0xA9C4, 0x3214, 0xA9C5, 0x3215, 0xA9C6, 0x3216, 0xA9C7, 0x3217, 0xA9C8, 0x3218, 0xA9C9, 0x3219, 0xA9CA, + 0x321A, 0xA9CB, 0x321B, 0xA9CC, 0x321C, 0xA2DF, 0x3260, 0xA8B1, 0x3261, 0xA8B2, 0x3262, 0xA8B3, 0x3263, 0xA8B4, 0x3264, 0xA8B5, + 0x3265, 0xA8B6, 0x3266, 0xA8B7, 0x3267, 0xA8B8, 0x3268, 0xA8B9, 0x3269, 0xA8BA, 0x326A, 0xA8BB, 0x326B, 0xA8BC, 0x326C, 0xA8BD, + 0x326D, 0xA8BE, 0x326E, 0xA8BF, 0x326F, 0xA8C0, 0x3270, 0xA8C1, 0x3271, 0xA8C2, 0x3272, 0xA8C3, 0x3273, 0xA8C4, 0x3274, 0xA8C5, + 0x3275, 0xA8C6, 0x3276, 0xA8C7, 0x3277, 0xA8C8, 0x3278, 0xA8C9, 0x3279, 0xA8CA, 0x327A, 0xA8CB, 0x327B, 0xA8CC, 0x327F, 0xA2DE, + 0x3380, 0xA7C9, 0x3381, 0xA7CA, 0x3382, 0xA7CB, 0x3383, 0xA7CC, 0x3384, 0xA7CD, 0x3388, 0xA7BA, 0x3389, 0xA7BB, 0x338A, 0xA7DC, + 0x338B, 0xA7DD, 0x338C, 0xA7DE, 0x338D, 0xA7B6, 0x338E, 0xA7B7, 0x338F, 0xA7B8, 0x3390, 0xA7D4, 0x3391, 0xA7D5, 0x3392, 0xA7D6, + 0x3393, 0xA7D7, 0x3394, 0xA7D8, 0x3395, 0xA7A1, 0x3396, 0xA7A2, 0x3397, 0xA7A3, 0x3398, 0xA7A5, 0x3399, 0xA7AB, 0x339A, 0xA7AC, + 0x339B, 0xA7AD, 0x339C, 0xA7AE, 0x339D, 0xA7AF, 0x339E, 0xA7B0, 0x339F, 0xA7B1, 0x33A0, 0xA7B2, 0x33A1, 0xA7B3, 0x33A2, 0xA7B4, + 0x33A3, 0xA7A7, 0x33A4, 0xA7A8, 0x33A5, 0xA7A9, 0x33A6, 0xA7AA, 0x33A7, 0xA7BD, 0x33A8, 0xA7BE, 0x33A9, 0xA7E5, 0x33AA, 0xA7E6, + 0x33AB, 0xA7E7, 0x33AC, 0xA7E8, 0x33AD, 0xA7E1, 0x33AE, 0xA7E2, 0x33AF, 0xA7E3, 0x33B0, 0xA7BF, 0x33B1, 0xA7C0, 0x33B2, 0xA7C1, + 0x33B3, 0xA7C2, 0x33B4, 0xA7C3, 0x33B5, 0xA7C4, 0x33B6, 0xA7C5, 0x33B7, 0xA7C6, 0x33B8, 0xA7C7, 0x33B9, 0xA7C8, 0x33BA, 0xA7CE, + 0x33BB, 0xA7CF, 0x33BC, 0xA7D0, 0x33BD, 0xA7D1, 0x33BE, 0xA7D2, 0x33BF, 0xA7D3, 0x33C0, 0xA7DA, 0x33C1, 0xA7DB, 0x33C2, 0xA2E3, + 0x33C3, 0xA7EC, 0x33C4, 0xA7A6, 0x33C5, 0xA7E0, 0x33C6, 0xA7EF, 0x33C7, 0xA2E1, 0x33C8, 0xA7BC, 0x33C9, 0xA7ED, 0x33CA, 0xA7B5, + 0x33CF, 0xA7B9, 0x33D0, 0xA7EA, 0x33D3, 0xA7EB, 0x33D6, 0xA7DF, 0x33D8, 0xA2E4, 0x33DB, 0xA7E4, 0x33DC, 0xA7EE, 0x33DD, 0xA7E9, + 0x4E00, 0xECE9, 0x4E01, 0xEFCB, 0x4E03, 0xF6D2, 0x4E07, 0xD8B2, 0x4E08, 0xEDDB, 0x4E09, 0xDFB2, 0x4E0A, 0xDFBE, 0x4E0B, 0xF9BB, + 0x4E0D, 0xDCF4, 0x4E11, 0xF5E4, 0x4E14, 0xF3A6, 0x4E15, 0xDDE0, 0x4E16, 0xE1A6, 0x4E18, 0xCEF8, 0x4E19, 0xDCB0, 0x4E1E, 0xE3AA, + 0x4E2D, 0xF1E9, 0x4E32, 0xCDFA, 0x4E38, 0xFCAF, 0x4E39, 0xD3A1, 0x4E3B, 0xF1AB, 0x4E42, 0xE7D1, 0x4E43, 0xD2AC, 0x4E45, 0xCEF9, + 0x4E4B, 0xF1FD, 0x4E4D, 0xDEBF, 0x4E4E, 0xFBBA, 0x4E4F, 0xF9B9, 0x4E56, 0xCED2, 0x4E58, 0xE3AB, 0x4E59, 0xEBE0, 0x4E5D, 0xCEFA, + 0x4E5E, 0xCBF7, 0x4E5F, 0xE5A5, 0x4E6B, 0xCAE1, 0x4E6D, 0xD4CC, 0x4E73, 0xEAE1, 0x4E76, 0xDCE3, 0x4E77, 0xDFAD, 0x4E7E, 0xCBEB, + 0x4E82, 0xD5AF, 0x4E86, 0xD6F5, 0x4E88, 0xE5F8, 0x4E8B, 0xDEC0, 0x4E8C, 0xECA3, 0x4E8E, 0xE9CD, 0x4E90, 0xEAA7, 0x4E91, 0xE9F6, + 0x4E92, 0xFBBB, 0x4E94, 0xE7E9, 0x4E95, 0xEFCC, 0x4E98, 0xD0E6, 0x4E9B, 0xDEC1, 0x4E9E, 0xE4AC, 0x4EA1, 0xD8CC, 0x4EA2, 0xF9F1, + 0x4EA4, 0xCEDF, 0x4EA5, 0xFAA4, 0x4EA6, 0xE6B2, 0x4EA8, 0xFAFB, 0x4EAB, 0xFABD, 0x4EAC, 0xCCC8, 0x4EAD, 0xEFCD, 0x4EAE, 0xD5D5, + 0x4EB6, 0xD3A2, 0x4EBA, 0xECD1, 0x4EC0, 0xE4A7, 0x4EC1, 0xECD2, 0x4EC4, 0xF6B1, 0x4EC7, 0xCEFB, 0x4ECA, 0xD0D1, 0x4ECB, 0xCBBF, + 0x4ECD, 0xEDA4, 0x4ED4, 0xEDA8, 0x4ED5, 0xDEC2, 0x4ED6, 0xF6E2, 0x4ED7, 0xEDDC, 0x4ED8, 0xDCF5, 0x4ED9, 0xE0B9, 0x4EDD, 0xD4CE, + 0x4EDF, 0xF4B5, 0x4EE3, 0xD3DB, 0x4EE4, 0xD6B5, 0x4EE5, 0xECA4, 0x4EF0, 0xE4E6, 0x4EF2, 0xF1EA, 0x4EF6, 0xCBEC, 0x4EF7, 0xCBC0, + 0x4EFB, 0xECF2, 0x4F01, 0xD0EA, 0x4F09, 0xF9F2, 0x4F0A, 0xECA5, 0x4F0B, 0xD0DF, 0x4F0D, 0xE7EA, 0x4F0E, 0xD0EB, 0x4F0F, 0xDCD1, + 0x4F10, 0xDBE9, 0x4F11, 0xFDCC, 0x4F2F, 0xDBD7, 0x4F34, 0xDAE1, 0x4F36, 0xD6B6, 0x4F38, 0xE3DF, 0x4F3A, 0xDEC3, 0x4F3C, 0xDEC4, + 0x4F3D, 0xCAA1, 0x4F43, 0xEEEC, 0x4F46, 0xD3A3, 0x4F47, 0xEEB7, 0x4F48, 0xF8CF, 0x4F4D, 0xEAC8, 0x4F4E, 0xEEB8, 0x4F4F, 0xF1AC, + 0x4F50, 0xF1A5, 0x4F51, 0xE9CE, 0x4F55, 0xF9BC, 0x4F59, 0xE5F9, 0x4F5A, 0xECEA, 0x4F5B, 0xDDD6, 0x4F5C, 0xEDC2, 0x4F69, 0xF8A5, + 0x4F6F, 0xE5BA, 0x4F70, 0xDBD8, 0x4F73, 0xCAA2, 0x4F76, 0xD1CD, 0x4F7A, 0xEEED, 0x4F7E, 0xECEB, 0x4F7F, 0xDEC5, 0x4F81, 0xE3E0, + 0x4F83, 0xCAC9, 0x4F84, 0xF2E9, 0x4F86, 0xD5CE, 0x4F88, 0xF6B6, 0x4F8A, 0xCEC2, 0x4F8B, 0xD6C7, 0x4F8D, 0xE3B4, 0x4F8F, 0xF1AD, + 0x4F91, 0xEAE2, 0x4F96, 0xD7C2, 0x4F98, 0xF3A7, 0x4F9B, 0xCDEA, 0x4F9D, 0xEBEE, 0x4FAE, 0xD9B2, 0x4FAF, 0xFDA5, 0x4FB5, 0xF6D5, + 0x4FB6, 0xD5E2, 0x4FBF, 0xF8B5, 0x4FC2, 0xCCF5, 0x4FC3, 0xF5B5, 0x4FC4, 0xE4AD, 0x4FC9, 0xE7EB, 0x4FCA, 0xF1D5, 0x4FCE, 0xF0BB, + 0x4FD1, 0xE9B5, 0x4FD3, 0xCCC9, 0x4FD4, 0xFAD5, 0x4FD7, 0xE1D4, 0x4FDA, 0xD7D6, 0x4FDD, 0xDCC1, 0x4FDF, 0xDEC6, 0x4FE0, 0xFAEF, + 0x4FE1, 0xE3E1, 0x4FEE, 0xE1F3, 0x4FEF, 0xDCF6, 0x4FF1, 0xCEFC, 0x4FF3, 0xDBC4, 0x4FF5, 0xF8F1, 0x4FF8, 0xDCE4, 0x4FFA, 0xE5EF, + 0x5002, 0xDCB1, 0x5006, 0xD5D6, 0x5009, 0xF3DA, 0x500B, 0xCBC1, 0x500D, 0xDBC3, 0x5011, 0xD9FA, 0x5012, 0xD3EE, 0x5016, 0xFAB8, + 0x5019, 0xFDA6, 0x501A, 0xEBEF, 0x501C, 0xF4A6, 0x501E, 0xCCCA, 0x501F, 0xF3A8, 0x5021, 0xF3DB, 0x5023, 0xDBA7, 0x5024, 0xF6B7, + 0x5026, 0xCFE6, 0x5027, 0xF0F2, 0x5028, 0xCBDA, 0x502A, 0xE7D2, 0x502B, 0xD7C3, 0x502C, 0xF6F0, 0x502D, 0xE8DE, 0x503B, 0xE5A6, + 0x5043, 0xE5E7, 0x5047, 0xCAA3, 0x5048, 0xCCA7, 0x5049, 0xEAC9, 0x504F, 0xF8B6, 0x5055, 0xFAA5, 0x505A, 0xF1AE, 0x505C, 0xEFCE, + 0x5065, 0xCBED, 0x5074, 0xF6B0, 0x5075, 0xEFCF, 0x5076, 0xE9CF, 0x5078, 0xF7DE, 0x5080, 0xCED3, 0x5085, 0xDCF7, 0x508D, 0xDBA8, + 0x5091, 0xCBF8, 0x5098, 0xDFA1, 0x5099, 0xDDE1, 0x50AC, 0xF5CA, 0x50AD, 0xE9B6, 0x50B2, 0xE7EC, 0x50B3, 0xEEEE, 0x50B5, 0xF3F0, + 0x50B7, 0xDFBF, 0x50BE, 0xCCCB, 0x50C5, 0xD0C1, 0x50C9, 0xF4D2, 0x50CA, 0xE0BA, 0x50CF, 0xDFC0, 0x50D1, 0xCEE0, 0x50D5, 0xDCD2, + 0x50D6, 0xFDEA, 0x50DA, 0xD6F6, 0x50DE, 0xEACA, 0x50E5, 0xE8E9, 0x50E7, 0xE3AC, 0x50ED, 0xF3D0, 0x50F9, 0xCAA4, 0x50FB, 0xDBF8, + 0x50FF, 0xDEC7, 0x5100, 0xEBF0, 0x5101, 0xF1D6, 0x5104, 0xE5E2, 0x5106, 0xCCCC, 0x5109, 0xCBFB, 0x5112, 0xEAE3, 0x511F, 0xDFC1, + 0x5121, 0xD6ED, 0x512A, 0xE9D0, 0x5132, 0xEEB9, 0x5137, 0xD5E3, 0x513A, 0xD1D3, 0x513C, 0xE5F0, 0x5140, 0xE8B4, 0x5141, 0xEBC3, + 0x5143, 0xEAAA, 0x5144, 0xFAFC, 0x5145, 0xF5F6, 0x5146, 0xF0BC, 0x5147, 0xFDD4, 0x5148, 0xE0BB, 0x5149, 0xCEC3, 0x514B, 0xD0BA, + 0x514C, 0xF7BA, 0x514D, 0xD8F3, 0x514E, 0xF7CD, 0x5152, 0xE4AE, 0x515C, 0xD4DF, 0x5162, 0xD0E7, 0x5165, 0xECFD, 0x5167, 0xD2AE, + 0x5168, 0xEEEF, 0x5169, 0xD5D7, 0x516A, 0xEAE4, 0x516B, 0xF8A2, 0x516C, 0xCDEB, 0x516D, 0xD7BF, 0x516E, 0xFBB1, 0x5171, 0xCDEC, + 0x5175, 0xDCB2, 0x5176, 0xD0EC, 0x5177, 0xCEFD, 0x5178, 0xEEF0, 0x517C, 0xCCC2, 0x5180, 0xD0ED, 0x5186, 0xE5F7, 0x518A, 0xF3FC, + 0x518D, 0xEEA2, 0x5192, 0xD9B3, 0x5195, 0xD8F4, 0x5197, 0xE9B7, 0x51A0, 0xCEAE, 0x51A5, 0xD9A2, 0x51AA, 0xD8F1, 0x51AC, 0xD4CF, + 0x51B6, 0xE5A7, 0x51B7, 0xD5D2, 0x51BD, 0xD6A9, 0x51C4, 0xF4A2, 0x51C6, 0xF1D7, 0x51C9, 0xD5D8, 0x51CB, 0xF0BD, 0x51CC, 0xD7D0, + 0x51CD, 0xD4D0, 0x51DC, 0xD7CF, 0x51DD, 0xEBEA, 0x51DE, 0xFDEB, 0x51E1, 0xDBED, 0x51F0, 0xFCC5, 0x51F1, 0xCBC2, 0x51F6, 0xFDD5, + 0x51F8, 0xF4C8, 0x51F9, 0xE8EA, 0x51FA, 0xF5F3, 0x51FD, 0xF9DE, 0x5200, 0xD3EF, 0x5203, 0xECD3, 0x5206, 0xDDC2, 0x5207, 0xEFB7, + 0x5208, 0xE7D4, 0x520A, 0xCACA, 0x520E, 0xD9FB, 0x5211, 0xFAFD, 0x5217, 0xD6AA, 0x521D, 0xF4F8, 0x5224, 0xF7F7, 0x5225, 0xDCAC, + 0x5229, 0xD7D7, 0x522A, 0xDFA2, 0x522E, 0xCEBE, 0x5230, 0xD3F0, 0x5236, 0xF0A4, 0x5237, 0xE1EC, 0x5238, 0xCFE7, 0x5239, 0xF3CB, + 0x523A, 0xEDA9, 0x523B, 0xCABE, 0x5243, 0xF4EF, 0x5247, 0xF6CE, 0x524A, 0xDEFB, 0x524B, 0xD0BB, 0x524C, 0xD5B7, 0x524D, 0xEEF1, + 0x5254, 0xF4A8, 0x5256, 0xDCF8, 0x525B, 0xCBA7, 0x525D, 0xDACE, 0x5261, 0xE0E6, 0x5269, 0xEDA5, 0x526A, 0xEEF2, 0x526F, 0xDCF9, + 0x5272, 0xF9DC, 0x5275, 0xF3DC, 0x527D, 0xF8F2, 0x527F, 0xF4F9, 0x5283, 0xFCF1, 0x5287, 0xD0BC, 0x5288, 0xDBF9, 0x5289, 0xD7B1, + 0x528D, 0xCBFC, 0x5291, 0xF0A5, 0x5292, 0xCBFD, 0x529B, 0xD5F4, 0x529F, 0xCDED, 0x52A0, 0xCAA5, 0x52A3, 0xD6AB, 0x52A4, 0xD0C2, + 0x52A9, 0xF0BE, 0x52AA, 0xD2BD, 0x52AB, 0xCCA4, 0x52BE, 0xFAB6, 0x52C1, 0xCCCD, 0x52C3, 0xDAFA, 0x52C5, 0xF6CF, 0x52C7, 0xE9B8, + 0x52C9, 0xD8F5, 0x52CD, 0xCCCE, 0x52D2, 0xD7CD, 0x52D5, 0xD4D1, 0x52D6, 0xE9ED, 0x52D8, 0xCAEB, 0x52D9, 0xD9E2, 0x52DB, 0xFDB2, + 0x52DD, 0xE3AD, 0x52DE, 0xD6CC, 0x52DF, 0xD9B4, 0x52E2, 0xE1A7, 0x52E3, 0xEED3, 0x52E4, 0xD0C3, 0x52F3, 0xFDB3, 0x52F5, 0xD5E4, + 0x52F8, 0xCFE8, 0x52FA, 0xEDC3, 0x52FB, 0xD0B2, 0x52FE, 0xCEFE, 0x52FF, 0xDAA8, 0x5305, 0xF8D0, 0x5308, 0xFDD6, 0x530D, 0xF8D1, + 0x530F, 0xF8D2, 0x5310, 0xDCD3, 0x5315, 0xDDE2, 0x5316, 0xFBF9, 0x5317, 0xDDC1, 0x5319, 0xE3B5, 0x5320, 0xEDDD, 0x5321, 0xCEC4, + 0x5323, 0xCBA1, 0x532A, 0xDDE3, 0x532F, 0xFCDD, 0x5339, 0xF9AF, 0x533F, 0xD2FB, 0x5340, 0xCFA1, 0x5341, 0xE4A8, 0x5343, 0xF4B6, + 0x5344, 0xECFE, 0x5347, 0xE3AE, 0x5348, 0xE7ED, 0x5349, 0xFDC1, 0x534A, 0xDAE2, 0x534D, 0xD8B3, 0x5351, 0xDDE4, 0x5352, 0xF0EF, + 0x5353, 0xF6F1, 0x5354, 0xFAF0, 0x5357, 0xD1F5, 0x535A, 0xDACF, 0x535C, 0xDCD4, 0x535E, 0xDCA6, 0x5360, 0xEFBF, 0x5366, 0xCECF, + 0x5368, 0xE0D9, 0x536F, 0xD9D6, 0x5370, 0xECD4, 0x5371, 0xEACB, 0x5374, 0xCABF, 0x5375, 0xD5B0, 0x5377, 0xCFE9, 0x537D, 0xF1ED, + 0x537F, 0xCCCF, 0x5384, 0xE4F8, 0x5393, 0xE4ED, 0x5398, 0xD7D8, 0x539A, 0xFDA7, 0x539F, 0xEAAB, 0x53A0, 0xF6B2, 0x53A5, 0xCFF0, + 0x53A6, 0xF9BD, 0x53AD, 0xE6F4, 0x53BB, 0xCBDB, 0x53C3, 0xF3D1, 0x53C8, 0xE9D1, 0x53C9, 0xF3A9, 0x53CA, 0xD0E0, 0x53CB, 0xE9D2, + 0x53CD, 0xDAE3, 0x53D4, 0xE2D2, 0x53D6, 0xF6A2, 0x53D7, 0xE1F4, 0x53DB, 0xDAE4, 0x53E1, 0xE7D5, 0x53E2, 0xF5BF, 0x53E3, 0xCFA2, + 0x53E4, 0xCDAF, 0x53E5, 0xCFA3, 0x53E9, 0xCDB0, 0x53EA, 0xF1FE, 0x53EB, 0xD0A3, 0x53EC, 0xE1AF, 0x53ED, 0xF8A3, 0x53EF, 0xCAA6, + 0x53F0, 0xF7BB, 0x53F1, 0xF2EA, 0x53F2, 0xDEC8, 0x53F3, 0xE9D3, 0x53F8, 0xDEC9, 0x5403, 0xFDDE, 0x5404, 0xCAC0, 0x5408, 0xF9EA, + 0x5409, 0xD1CE, 0x540A, 0xEED4, 0x540C, 0xD4D2, 0x540D, 0xD9A3, 0x540E, 0xFDA8, 0x540F, 0xD7D9, 0x5410, 0xF7CE, 0x5411, 0xFABE, + 0x541B, 0xCFD6, 0x541D, 0xD7F0, 0x541F, 0xEBE1, 0x5420, 0xF8C5, 0x5426, 0xDCFA, 0x5429, 0xDDC3, 0x542B, 0xF9DF, 0x5433, 0xE7EF, + 0x5438, 0xFDE5, 0x5439, 0xF6A3, 0x543B, 0xD9FC, 0x543C, 0xFDA9, 0x543E, 0xE7EE, 0x5442, 0xD5E5, 0x5448, 0xEFD0, 0x544A, 0xCDB1, + 0x5451, 0xF7A2, 0x5468, 0xF1B2, 0x546A, 0xF1B1, 0x5471, 0xCDB2, 0x5473, 0xDAAB, 0x5475, 0xCAA7, 0x547B, 0xE3E2, 0x547C, 0xFBBC, + 0x547D, 0xD9A4, 0x5480, 0xEEBA, 0x5486, 0xF8D3, 0x548C, 0xFBFA, 0x548E, 0xCFA4, 0x5490, 0xDCFB, 0x54A4, 0xF6E3, 0x54A8, 0xEDAA, + 0x54AB, 0xF2A1, 0x54AC, 0xCEE1, 0x54B3, 0xFAA6, 0x54B8, 0xF9E0, 0x54BD, 0xECD6, 0x54C0, 0xE4EE, 0x54C1, 0xF9A1, 0x54C4, 0xFBEF, + 0x54C8, 0xF9EB, 0x54C9, 0xEEA3, 0x54E1, 0xEAAC, 0x54E5, 0xCAA8, 0x54E8, 0xF4FA, 0x54ED, 0xCDD6, 0x54EE, 0xFCF6, 0x54F2, 0xF4C9, + 0x54FA, 0xF8D4, 0x5504, 0xF8A6, 0x5506, 0xDECA, 0x5507, 0xF2C6, 0x550E, 0xD7DA, 0x5510, 0xD3D0, 0x551C, 0xD8C5, 0x552F, 0xEAE6, + 0x5531, 0xF3DD, 0x5535, 0xE4DA, 0x553E, 0xF6E4, 0x5544, 0xF6F2, 0x5546, 0xDFC2, 0x554F, 0xD9FD, 0x5553, 0xCCF6, 0x5556, 0xD3BA, + 0x555E, 0xE4AF, 0x5563, 0xF9E1, 0x557C, 0xF0A6, 0x5580, 0xCBD3, 0x5584, 0xE0BC, 0x5586, 0xF4CA, 0x5587, 0xD4FA, 0x5589, 0xFDAA, + 0x558A, 0xF9E2, 0x5598, 0xF4B7, 0x5599, 0xFDC2, 0x559A, 0xFCB0, 0x559C, 0xFDEC, 0x559D, 0xCAE2, 0x55A7, 0xFDBD, 0x55A9, 0xEAE7, + 0x55AA, 0xDFC3, 0x55AB, 0xD1D2, 0x55AC, 0xCEE2, 0x55AE, 0xD3A4, 0x55C5, 0xFDAB, 0x55C7, 0xDFE0, 0x55D4, 0xF2C7, 0x55DA, 0xE7F0, + 0x55DC, 0xD0EE, 0x55DF, 0xF3AA, 0x55E3, 0xDECB, 0x55E4, 0xF6B8, 0x55FD, 0xE1F5, 0x55FE, 0xF1B3, 0x5606, 0xF7A3, 0x5609, 0xCAA9, + 0x5614, 0xCFA5, 0x5617, 0xDFC4, 0x562F, 0xE1B0, 0x5632, 0xF0BF, 0x5634, 0xF6A4, 0x5636, 0xE3B6, 0x5653, 0xFAC6, 0x5668, 0xD0EF, + 0x566B, 0xFDED, 0x5674, 0xDDC4, 0x5686, 0xFCF7, 0x56A5, 0xE6BF, 0x56AC, 0xDEAD, 0x56AE, 0xFABF, 0x56B4, 0xE5F1, 0x56BC, 0xEDC4, + 0x56CA, 0xD2A5, 0x56CD, 0xFDEE, 0x56D1, 0xF5B6, 0x56DA, 0xE1F6, 0x56DB, 0xDECC, 0x56DE, 0xFCDE, 0x56E0, 0xECD7, 0x56F0, 0xCDDD, + 0x56F9, 0xD6B7, 0x56FA, 0xCDB3, 0x5703, 0xF8D5, 0x5704, 0xE5D8, 0x5708, 0xCFEA, 0x570B, 0xCFD0, 0x570D, 0xEACC, 0x5712, 0xEAAE, + 0x5713, 0xEAAD, 0x5716, 0xD3F1, 0x5718, 0xD3A5, 0x571F, 0xF7CF, 0x5728, 0xEEA4, 0x572D, 0xD0A4, 0x5730, 0xF2A2, 0x573B, 0xD0F0, + 0x5740, 0xF2A3, 0x5742, 0xF7F8, 0x5747, 0xD0B3, 0x574A, 0xDBA9, 0x574D, 0xD3BB, 0x574E, 0xCAEC, 0x5750, 0xF1A6, 0x5751, 0xCBD5, + 0x5761, 0xF7E7, 0x5764, 0xCDDE, 0x5766, 0xF7A4, 0x576A, 0xF8C0, 0x576E, 0xD3DD, 0x5770, 0xCCD0, 0x5775, 0xCFA6, 0x577C, 0xF6F3, + 0x5782, 0xE1F7, 0x5788, 0xD3DC, 0x578B, 0xFAFE, 0x5793, 0xFAA7, 0x57A0, 0xEBD9, 0x57A2, 0xCFA7, 0x57A3, 0xEAAF, 0x57C3, 0xE4EF, + 0x57C7, 0xE9B9, 0x57C8, 0xF1D8, 0x57CB, 0xD8D8, 0x57CE, 0xE0F2, 0x57DF, 0xE6B4, 0x57E0, 0xDCFC, 0x57F0, 0xF3F1, 0x57F4, 0xE3D0, + 0x57F7, 0xF2FB, 0x57F9, 0xDBC6, 0x57FA, 0xD0F1, 0x57FC, 0xD0F2, 0x5800, 0xCFDC, 0x5802, 0xD3D1, 0x5805, 0xCCB1, 0x5806, 0xF7D8, + 0x5808, 0xCBA8, 0x5809, 0xEBBC, 0x580A, 0xE4BE, 0x581E, 0xF4DC, 0x5821, 0xDCC2, 0x5824, 0xF0A7, 0x5827, 0xE6C0, 0x582A, 0xCAED, + 0x582F, 0xE8EB, 0x5830, 0xE5E8, 0x5831, 0xDCC3, 0x5834, 0xEDDE, 0x5835, 0xD3F2, 0x583A, 0xCCF7, 0x584A, 0xCED4, 0x584B, 0xE7AB, + 0x584F, 0xCBC3, 0x5851, 0xE1B1, 0x5854, 0xF7B2, 0x5857, 0xD3F3, 0x5858, 0xD3D2, 0x585A, 0xF5C0, 0x585E, 0xDFDD, 0x5861, 0xEEF3, + 0x5862, 0xE7F1, 0x5864, 0xFDB4, 0x5875, 0xF2C8, 0x5879, 0xF3D2, 0x587C, 0xEEF4, 0x587E, 0xE2D3, 0x5883, 0xCCD1, 0x5885, 0xDFEA, + 0x5889, 0xE9BA, 0x5893, 0xD9D7, 0x589C, 0xF5CD, 0x589E, 0xF1F2, 0x589F, 0xFAC7, 0x58A8, 0xD9F8, 0x58A9, 0xD4C2, 0x58AE, 0xF6E5, + 0x58B3, 0xDDC5, 0x58BA, 0xE7F2, 0x58BB, 0xEDDF, 0x58BE, 0xCACB, 0x58C1, 0xDBFA, 0x58C5, 0xE8B5, 0x58C7, 0xD3A6, 0x58CE, 0xFDB5, + 0x58D1, 0xF9C9, 0x58D3, 0xE4E2, 0x58D5, 0xFBBD, 0x58D8, 0xD7A4, 0x58D9, 0xCEC5, 0x58DE, 0xCED5, 0x58DF, 0xD6E6, 0x58E4, 0xE5BD, + 0x58EB, 0xDECD, 0x58EC, 0xECF3, 0x58EF, 0xEDE0, 0x58F9, 0xECEC, 0x58FA, 0xFBBE, 0x58FB, 0xDFEB, 0x58FD, 0xE1F8, 0x590F, 0xF9BE, + 0x5914, 0xD0F3, 0x5915, 0xE0AA, 0x5916, 0xE8E2, 0x5919, 0xE2D4, 0x591A, 0xD2FD, 0x591C, 0xE5A8, 0x5922, 0xD9D3, 0x5927, 0xD3DE, + 0x5929, 0xF4B8, 0x592A, 0xF7BC, 0x592B, 0xDCFD, 0x592D, 0xE8EC, 0x592E, 0xE4E7, 0x5931, 0xE3F7, 0x5937, 0xECA8, 0x593E, 0xFAF1, + 0x5944, 0xE5F2, 0x5947, 0xD0F4, 0x5948, 0xD2AF, 0x5949, 0xDCE5, 0x594E, 0xD0A5, 0x594F, 0xF1B4, 0x5950, 0xFCB1, 0x5951, 0xCCF8, + 0x5954, 0xDDC6, 0x5955, 0xFAD1, 0x5957, 0xF7DF, 0x595A, 0xFAA8, 0x5960, 0xEEF5, 0x5962, 0xDECE, 0x5967, 0xE7F3, 0x596A, 0xF7AC, + 0x596B, 0xEBC4, 0x596C, 0xEDE1, 0x596D, 0xE0AB, 0x596E, 0xDDC7, 0x5973, 0xD2B3, 0x5974, 0xD2BF, 0x5978, 0xCACC, 0x597D, 0xFBBF, + 0x5982, 0xE5FD, 0x5983, 0xDDE5, 0x5984, 0xD8CD, 0x598A, 0xECF4, 0x5993, 0xD0F5, 0x5996, 0xE8ED, 0x5997, 0xD0D2, 0x5999, 0xD9D8, + 0x59A5, 0xF6E6, 0x59A8, 0xDBAA, 0x59AC, 0xF7E0, 0x59B9, 0xD8D9, 0x59BB, 0xF4A3, 0x59BE, 0xF4DD, 0x59C3, 0xEFD1, 0x59C6, 0xD9B5, + 0x59C9, 0xEDAB, 0x59CB, 0xE3B7, 0x59D0, 0xEEBB, 0x59D1, 0xCDB4, 0x59D3, 0xE0F3, 0x59D4, 0xEACD, 0x59D9, 0xECF5, 0x59DA, 0xE8EE, + 0x59DC, 0xCBA9, 0x59DD, 0xF1AF, 0x59E6, 0xCACD, 0x59E8, 0xECA9, 0x59EA, 0xF2EB, 0x59EC, 0xFDEF, 0x59EE, 0xF9F3, 0x59F8, 0xE6C1, + 0x59FB, 0xECD8, 0x59FF, 0xEDAC, 0x5A01, 0xEACE, 0x5A03, 0xE8DF, 0x5A11, 0xDECF, 0x5A18, 0xD2A6, 0x5A1B, 0xE7F4, 0x5A1C, 0xD1D6, + 0x5A1F, 0xE6C2, 0x5A20, 0xE3E3, 0x5A25, 0xE4B0, 0x5A29, 0xD8B4, 0x5A36, 0xF6A5, 0x5A3C, 0xF3DE, 0x5A41, 0xD7A5, 0x5A46, 0xF7E8, + 0x5A49, 0xE8C6, 0x5A5A, 0xFBE6, 0x5A62, 0xDDE6, 0x5A66, 0xDCFE, 0x5A92, 0xD8DA, 0x5A9A, 0xDAAC, 0x5A9B, 0xEAB0, 0x5AA4, 0xE3B8, + 0x5AC1, 0xCAAA, 0x5AC2, 0xE1F9, 0x5AC4, 0xEAB1, 0x5AC9, 0xF2EC, 0x5ACC, 0xFAEE, 0x5AE1, 0xEED5, 0x5AE6, 0xF9F4, 0x5AE9, 0xD2EC, + 0x5B05, 0xFBFB, 0x5B09, 0xFDF0, 0x5B0B, 0xE0BD, 0x5B0C, 0xCEE3, 0x5B16, 0xF8C6, 0x5B2A, 0xDEAE, 0x5B40, 0xDFC5, 0x5B43, 0xE5BE, + 0x5B50, 0xEDAD, 0x5B51, 0xFAEA, 0x5B54, 0xCDEE, 0x5B55, 0xEDA6, 0x5B57, 0xEDAE, 0x5B58, 0xF0ED, 0x5B5A, 0xDDA1, 0x5B5C, 0xEDAF, + 0x5B5D, 0xFCF8, 0x5B5F, 0xD8EB, 0x5B63, 0xCCF9, 0x5B64, 0xCDB5, 0x5B69, 0xFAA9, 0x5B6B, 0xE1DD, 0x5B70, 0xE2D5, 0x5B71, 0xEDCF, + 0x5B75, 0xDDA2, 0x5B78, 0xF9CA, 0x5B7A, 0xEAE8, 0x5B7C, 0xE5ED, 0x5B85, 0xD3EB, 0x5B87, 0xE9D4, 0x5B88, 0xE1FA, 0x5B89, 0xE4CC, + 0x5B8B, 0xE1E4, 0x5B8C, 0xE8C7, 0x5B8F, 0xCEDB, 0x5B93, 0xDCD5, 0x5B95, 0xF7B5, 0x5B96, 0xFCF3, 0x5B97, 0xF0F3, 0x5B98, 0xCEAF, + 0x5B99, 0xF1B5, 0x5B9A, 0xEFD2, 0x5B9B, 0xE8C8, 0x5B9C, 0xEBF1, 0x5BA2, 0xCBD4, 0x5BA3, 0xE0BE, 0x5BA4, 0xE3F8, 0x5BA5, 0xEAE9, + 0x5BA6, 0xFCB2, 0x5BAC, 0xE0F4, 0x5BAE, 0xCFE0, 0x5BB0, 0xEEA5, 0x5BB3, 0xFAAA, 0x5BB4, 0xE6C3, 0x5BB5, 0xE1B2, 0x5BB6, 0xCAAB, + 0x5BB8, 0xE3E4, 0x5BB9, 0xE9BB, 0x5BBF, 0xE2D6, 0x5BC0, 0xF3F2, 0x5BC2, 0xEED6, 0x5BC3, 0xEAB2, 0x5BC4, 0xD0F6, 0x5BC5, 0xECD9, + 0x5BC6, 0xDACB, 0x5BC7, 0xCFA8, 0x5BCC, 0xDDA3, 0x5BD0, 0xD8DB, 0x5BD2, 0xF9CE, 0x5BD3, 0xE9D5, 0x5BD4, 0xE3D1, 0x5BD7, 0xD2BC, + 0x5BDE, 0xD8AC, 0x5BDF, 0xF3CC, 0x5BE1, 0xCDFB, 0x5BE2, 0xF6D6, 0x5BE4, 0xE7F5, 0x5BE5, 0xE8EF, 0x5BE6, 0xE3F9, 0x5BE7, 0xD2BB, + 0x5BE8, 0xF3F3, 0x5BE9, 0xE3FB, 0x5BEB, 0xDED0, 0x5BEC, 0xCEB0, 0x5BEE, 0xD6F7, 0x5BEF, 0xF1D9, 0x5BF5, 0xF5C1, 0x5BF6, 0xDCC4, + 0x5BF8, 0xF5BB, 0x5BFA, 0xDED1, 0x5C01, 0xDCE6, 0x5C04, 0xDED2, 0x5C07, 0xEDE2, 0x5C08, 0xEEF6, 0x5C09, 0xEACF, 0x5C0A, 0xF0EE, + 0x5C0B, 0xE3FC, 0x5C0D, 0xD3DF, 0x5C0E, 0xD3F4, 0x5C0F, 0xE1B3, 0x5C11, 0xE1B4, 0x5C16, 0xF4D3, 0x5C19, 0xDFC6, 0x5C24, 0xE9D6, + 0x5C28, 0xDBAB, 0x5C31, 0xF6A6, 0x5C38, 0xE3B9, 0x5C39, 0xEBC5, 0x5C3A, 0xF4A9, 0x5C3B, 0xCDB6, 0x5C3C, 0xD2F9, 0x5C3E, 0xDAAD, + 0x5C3F, 0xD2E3, 0x5C40, 0xCFD1, 0x5C45, 0xCBDC, 0x5C46, 0xCCFA, 0x5C48, 0xCFDD, 0x5C4B, 0xE8A9, 0x5C4D, 0xE3BB, 0x5C4E, 0xE3BA, + 0x5C51, 0xE0DA, 0x5C55, 0xEEF7, 0x5C5B, 0xDCB3, 0x5C60, 0xD3F5, 0x5C62, 0xD7A6, 0x5C64, 0xF6B5, 0x5C65, 0xD7DB, 0x5C6C, 0xE1D5, + 0x5C6F, 0xD4EA, 0x5C71, 0xDFA3, 0x5C79, 0xFDDF, 0x5C90, 0xD0F7, 0x5C91, 0xEDD4, 0x5CA1, 0xCBAA, 0x5CA9, 0xE4DB, 0x5CAB, 0xE1FB, + 0x5CAC, 0xCBA2, 0x5CB1, 0xD3E0, 0x5CB3, 0xE4BF, 0x5CB5, 0xFBC0, 0x5CB7, 0xDABE, 0x5CB8, 0xE4CD, 0x5CBA, 0xD6B9, 0x5CBE, 0xEFC0, + 0x5CC0, 0xE1FC, 0x5CD9, 0xF6B9, 0x5CE0, 0xDFC7, 0x5CE8, 0xE4B1, 0x5CEF, 0xDCE7, 0x5CF0, 0xDCE8, 0x5CF4, 0xFAD6, 0x5CF6, 0xD3F6, + 0x5CFB, 0xF1DA, 0x5CFD, 0xFAF2, 0x5D07, 0xE2FD, 0x5D0D, 0xD5CF, 0x5D0E, 0xD0F8, 0x5D11, 0xCDDF, 0x5D14, 0xF5CB, 0x5D16, 0xE4F0, + 0x5D17, 0xCBAB, 0x5D19, 0xD7C4, 0x5D27, 0xE2FE, 0x5D29, 0xDDDA, 0x5D4B, 0xDAAE, 0x5D4C, 0xCAEE, 0x5D50, 0xD5B9, 0x5D69, 0xE3A1, + 0x5D6C, 0xE8E3, 0x5D6F, 0xF3AB, 0x5D87, 0xCFA9, 0x5D8B, 0xD3F7, 0x5D9D, 0xD4F1, 0x5DA0, 0xCEE4, 0x5DA2, 0xE8F2, 0x5DAA, 0xE5F5, + 0x5DB8, 0xE7AE, 0x5DBA, 0xD6BA, 0x5DBC, 0xDFEC, 0x5DBD, 0xE4C0, 0x5DCD, 0xE8E4, 0x5DD2, 0xD8B5, 0x5DD6, 0xE4DC, 0x5DDD, 0xF4B9, + 0x5DDE, 0xF1B6, 0x5DE1, 0xE2DE, 0x5DE2, 0xE1B5, 0x5DE5, 0xCDEF, 0x5DE6, 0xF1A7, 0x5DE7, 0xCEE5, 0x5DE8, 0xCBDD, 0x5DEB, 0xD9E3, + 0x5DEE, 0xF3AC, 0x5DF1, 0xD0F9, 0x5DF2, 0xECAB, 0x5DF3, 0xDED3, 0x5DF4, 0xF7E9, 0x5DF7, 0xF9F5, 0x5DFD, 0xE1DE, 0x5DFE, 0xCBEE, + 0x5E02, 0xE3BC, 0x5E03, 0xF8D6, 0x5E06, 0xDBEE, 0x5E0C, 0xFDF1, 0x5E11, 0xF7B6, 0x5E16, 0xF4DE, 0x5E19, 0xF2ED, 0x5E1B, 0xDBD9, + 0x5E1D, 0xF0A8, 0x5E25, 0xE1FD, 0x5E2B, 0xDED4, 0x5E2D, 0xE0AC, 0x5E33, 0xEDE3, 0x5E36, 0xD3E1, 0x5E38, 0xDFC8, 0x5E3D, 0xD9B6, + 0x5E3F, 0xFDAC, 0x5E40, 0xEFD3, 0x5E44, 0xE4C1, 0x5E45, 0xF8EB, 0x5E47, 0xDBAC, 0x5E4C, 0xFCC6, 0x5E55, 0xD8AD, 0x5E5F, 0xF6BA, + 0x5E61, 0xDBDF, 0x5E62, 0xD3D3, 0x5E63, 0xF8C7, 0x5E72, 0xCACE, 0x5E73, 0xF8C1, 0x5E74, 0xD2B4, 0x5E77, 0xDCB4, 0x5E78, 0xFAB9, + 0x5E79, 0xCACF, 0x5E7B, 0xFCB3, 0x5E7C, 0xEAEA, 0x5E7D, 0xEAEB, 0x5E7E, 0xD0FA, 0x5E84, 0xEDE4, 0x5E87, 0xDDE7, 0x5E8A, 0xDFC9, + 0x5E8F, 0xDFED, 0x5E95, 0xEEBC, 0x5E97, 0xEFC1, 0x5E9A, 0xCCD2, 0x5E9C, 0xDDA4, 0x5EA0, 0xDFCA, 0x5EA6, 0xD3F8, 0x5EA7, 0xF1A8, + 0x5EAB, 0xCDB7, 0x5EAD, 0xEFD4, 0x5EB5, 0xE4DD, 0x5EB6, 0xDFEE, 0x5EB7, 0xCBAC, 0x5EB8, 0xE9BC, 0x5EBE, 0xEAEC, 0x5EC2, 0xDFCB, + 0x5EC8, 0xF9BF, 0x5EC9, 0xD6AF, 0x5ECA, 0xD5C6, 0x5ED0, 0xCFAA, 0x5ED3, 0xCEA9, 0x5ED6, 0xD6F8, 0x5EDA, 0xF1B7, 0x5EDB, 0xEEF8, + 0x5EDF, 0xD9D9, 0x5EE0, 0xF3DF, 0x5EE2, 0xF8C8, 0x5EE3, 0xCEC6, 0x5EEC, 0xD5E6, 0x5EF3, 0xF4E6, 0x5EF6, 0xE6C5, 0x5EF7, 0xEFD5, + 0x5EFA, 0xCBEF, 0x5EFB, 0xFCDF, 0x5F01, 0xDCA7, 0x5F04, 0xD6E7, 0x5F0A, 0xF8C9, 0x5F0F, 0xE3D2, 0x5F11, 0xE3BD, 0x5F13, 0xCFE1, + 0x5F14, 0xF0C0, 0x5F15, 0xECDA, 0x5F17, 0xDDD7, 0x5F18, 0xFBF0, 0x5F1B, 0xECAC, 0x5F1F, 0xF0A9, 0x5F26, 0xFAD7, 0x5F27, 0xFBC1, + 0x5F29, 0xD2C0, 0x5F31, 0xE5B0, 0x5F35, 0xEDE5, 0x5F3A, 0xCBAD, 0x5F3C, 0xF9B0, 0x5F48, 0xF7A5, 0x5F4A, 0xCBAE, 0x5F4C, 0xDAAF, + 0x5F4E, 0xD8B6, 0x5F56, 0xD3A7, 0x5F57, 0xFBB2, 0x5F59, 0xFDC4, 0x5F5B, 0xECAD, 0x5F62, 0xFBA1, 0x5F66, 0xE5E9, 0x5F67, 0xE9EE, + 0x5F69, 0xF3F4, 0x5F6A, 0xF8F3, 0x5F6B, 0xF0C1, 0x5F6C, 0xDEAF, 0x5F6D, 0xF8B0, 0x5F70, 0xF3E0, 0x5F71, 0xE7AF, 0x5F77, 0xDBAD, + 0x5F79, 0xE6B5, 0x5F7C, 0xF9A8, 0x5F7F, 0xDDD8, 0x5F80, 0xE8D9, 0x5F81, 0xEFD6, 0x5F85, 0xD3E2, 0x5F87, 0xE2DF, 0x5F8A, 0xFCE0, + 0x5F8B, 0xD7C8, 0x5F8C, 0xFDAD, 0x5F90, 0xDFEF, 0x5F91, 0xCCD3, 0x5F92, 0xD3F9, 0x5F97, 0xD4F0, 0x5F98, 0xDBC7, 0x5F99, 0xDED5, + 0x5F9E, 0xF0F4, 0x5FA0, 0xD5D0, 0x5FA1, 0xE5D9, 0x5FA8, 0xFCC7, 0x5FA9, 0xDCD6, 0x5FAA, 0xE2E0, 0x5FAE, 0xDAB0, 0x5FB5, 0xF3A3, + 0x5FB7, 0xD3EC, 0x5FB9, 0xF4CB, 0x5FBD, 0xFDC5, 0x5FC3, 0xE3FD, 0x5FC5, 0xF9B1, 0x5FCC, 0xD0FB, 0x5FCD, 0xECDB, 0x5FD6, 0xF5BC, + 0x5FD7, 0xF2A4, 0x5FD8, 0xD8CE, 0x5FD9, 0xD8CF, 0x5FE0, 0xF5F7, 0x5FEB, 0xF6E1, 0x5FF5, 0xD2B7, 0x5FFD, 0xFBEC, 0x5FFF, 0xDDC8, + 0x600F, 0xE4E8, 0x6012, 0xD2C1, 0x6016, 0xF8D7, 0x601C, 0xD6BB, 0x601D, 0xDED6, 0x6020, 0xF7BD, 0x6021, 0xECAE, 0x6025, 0xD0E1, + 0x6027, 0xE0F5, 0x6028, 0xEAB3, 0x602A, 0xCED6, 0x602F, 0xCCA5, 0x6041, 0xECF6, 0x6042, 0xE2E1, 0x6043, 0xE3BE, 0x604D, 0xFCC8, + 0x6050, 0xCDF0, 0x6052, 0xF9F6, 0x6055, 0xDFF0, 0x6059, 0xE5BF, 0x605D, 0xCEBF, 0x6062, 0xFCE1, 0x6063, 0xEDB0, 0x6064, 0xFDD1, + 0x6065, 0xF6BB, 0x6068, 0xF9CF, 0x6069, 0xEBDA, 0x606A, 0xCAC1, 0x606C, 0xD2B8, 0x606D, 0xCDF1, 0x606F, 0xE3D3, 0x6070, 0xFDE6, + 0x6085, 0xE6ED, 0x6089, 0xE3FA, 0x608C, 0xF0AA, 0x608D, 0xF9D0, 0x6094, 0xFCE2, 0x6096, 0xF8A7, 0x609A, 0xE1E5, 0x609B, 0xEEF9, + 0x609F, 0xE7F6, 0x60A0, 0xEAED, 0x60A3, 0xFCB4, 0x60A4, 0xF5C2, 0x60A7, 0xD7DC, 0x60B0, 0xF0F5, 0x60B2, 0xDDE8, 0x60B3, 0xD3ED, + 0x60B4, 0xF5FC, 0x60B6, 0xDABF, 0x60B8, 0xCCFB, 0x60BC, 0xD3FA, 0x60BD, 0xF4A4, 0x60C5, 0xEFD7, 0x60C7, 0xD4C3, 0x60D1, 0xFBE3, + 0x60DA, 0xFBED, 0x60DC, 0xE0AD, 0x60DF, 0xEAEE, 0x60E0, 0xFBB3, 0x60E1, 0xE4C2, 0x60F0, 0xF6E7, 0x60F1, 0xD2DD, 0x60F3, 0xDFCC, + 0x60F6, 0xFCC9, 0x60F9, 0xE5A9, 0x60FA, 0xE0F6, 0x60FB, 0xF6B3, 0x6101, 0xE1FE, 0x6106, 0xCBF0, 0x6108, 0xEAEF, 0x6109, 0xEAF0, + 0x610D, 0xDAC0, 0x610E, 0xF8B4, 0x610F, 0xEBF2, 0x6115, 0xE4C3, 0x611A, 0xE9D7, 0x611B, 0xE4F1, 0x611F, 0xCAEF, 0x6127, 0xCED7, + 0x6130, 0xFCCA, 0x6134, 0xF3E1, 0x6137, 0xCBC4, 0x613C, 0xE3E5, 0x613E, 0xCBC5, 0x613F, 0xEAB4, 0x6142, 0xE9BD, 0x6144, 0xD7C9, + 0x6147, 0xEBDB, 0x6148, 0xEDB1, 0x614A, 0xCCC3, 0x614B, 0xF7BE, 0x614C, 0xFCCB, 0x6153, 0xF8F4, 0x6155, 0xD9B7, 0x6158, 0xF3D3, + 0x6159, 0xF3D4, 0x615D, 0xF7E4, 0x615F, 0xF7D1, 0x6162, 0xD8B7, 0x6163, 0xCEB1, 0x6164, 0xCAC2, 0x6167, 0xFBB4, 0x6168, 0xCBC6, + 0x616B, 0xF0F6, 0x616E, 0xD5E7, 0x6170, 0xEAD0, 0x6176, 0xCCD4, 0x6177, 0xCBAF, 0x617D, 0xF4AA, 0x617E, 0xE9AF, 0x6181, 0xF5C3, + 0x6182, 0xE9D8, 0x618A, 0xDDE9, 0x618E, 0xF1F3, 0x6190, 0xD5FB, 0x6191, 0xDEBB, 0x6194, 0xF4FB, 0x6198, 0xFDF3, 0x6199, 0xFDF2, + 0x619A, 0xF7A6, 0x61A4, 0xDDC9, 0x61A7, 0xD4D3, 0x61A9, 0xCCA8, 0x61AB, 0xDAC1, 0x61AC, 0xCCD5, 0x61AE, 0xD9E4, 0x61B2, 0xFACA, + 0x61B6, 0xE5E3, 0x61BA, 0xD3BC, 0x61BE, 0xCAF0, 0x61C3, 0xD0C4, 0x61C7, 0xCAD0, 0x61C8, 0xFAAB, 0x61C9, 0xEBEB, 0x61CA, 0xE7F8, + 0x61CB, 0xD9E5, 0x61E6, 0xD1D7, 0x61F2, 0xF3A4, 0x61F6, 0xD4FB, 0x61F7, 0xFCE3, 0x61F8, 0xFAD8, 0x61FA, 0xF3D5, 0x61FC, 0xCFAB, + 0x61FF, 0xEBF3, 0x6200, 0xD5FC, 0x6207, 0xD3D4, 0x6208, 0xCDFC, 0x620A, 0xD9E6, 0x620C, 0xE2F9, 0x620D, 0xE2A1, 0x620E, 0xEBD4, + 0x6210, 0xE0F7, 0x6211, 0xE4B2, 0x6212, 0xCCFC, 0x6216, 0xFBE4, 0x621A, 0xF4AB, 0x621F, 0xD0BD, 0x6221, 0xCAF1, 0x622A, 0xEFB8, + 0x622E, 0xD7C0, 0x6230, 0xEEFA, 0x6231, 0xFDF4, 0x6234, 0xD3E3, 0x6236, 0xFBC2, 0x623E, 0xD5E8, 0x623F, 0xDBAE, 0x6240, 0xE1B6, + 0x6241, 0xF8B7, 0x6247, 0xE0BF, 0x6248, 0xFBC3, 0x6249, 0xDDEA, 0x624B, 0xE2A2, 0x624D, 0xEEA6, 0x6253, 0xF6E8, 0x6258, 0xF6F5, + 0x626E, 0xDDCA, 0x6271, 0xD0E2, 0x6276, 0xDDA6, 0x6279, 0xDDEB, 0x627C, 0xE4F9, 0x627F, 0xE3AF, 0x6280, 0xD0FC, 0x6284, 0xF4FC, + 0x6289, 0xCCBC, 0x628A, 0xF7EA, 0x6291, 0xE5E4, 0x6292, 0xDFF1, 0x6295, 0xF7E1, 0x6297, 0xF9F7, 0x6298, 0xEFB9, 0x629B, 0xF8D8, + 0x62AB, 0xF9A9, 0x62B1, 0xF8D9, 0x62B5, 0xEEBD, 0x62B9, 0xD8C6, 0x62BC, 0xE4E3, 0x62BD, 0xF5CE, 0x62C2, 0xDDD9, 0x62C7, 0xD9E7, + 0x62C8, 0xD2B9, 0x62C9, 0xD5C3, 0x62CC, 0xDAE5, 0x62CD, 0xDAD0, 0x62CF, 0xD1D9, 0x62D0, 0xCED8, 0x62D2, 0xCBDE, 0x62D3, 0xF4AC, + 0x62D4, 0xDAFB, 0x62D6, 0xF6E9, 0x62D7, 0xE8F3, 0x62D8, 0xCFAC, 0x62D9, 0xF0F0, 0x62DB, 0xF4FD, 0x62DC, 0xDBC8, 0x62EC, 0xCEC0, + 0x62ED, 0xE3D4, 0x62EE, 0xD1CF, 0x62EF, 0xF1F5, 0x62F1, 0xCDF2, 0x62F3, 0xCFEB, 0x62F7, 0xCDB8, 0x62FE, 0xE3A6, 0x62FF, 0xD1DA, + 0x6301, 0xF2A5, 0x6307, 0xF2A6, 0x6309, 0xE4CE, 0x6311, 0xD3FB, 0x632B, 0xF1A9, 0x632F, 0xF2C9, 0x633A, 0xEFD8, 0x633B, 0xE6C9, + 0x633D, 0xD8B8, 0x633E, 0xFAF3, 0x6349, 0xF3B5, 0x634C, 0xF8A4, 0x634F, 0xD1F3, 0x6350, 0xE6C8, 0x6355, 0xF8DA, 0x6367, 0xDCE9, + 0x6368, 0xDED7, 0x636E, 0xCBDF, 0x6372, 0xCFEC, 0x6377, 0xF4DF, 0x637A, 0xD1F4, 0x637B, 0xD2BA, 0x637F, 0xDFF2, 0x6383, 0xE1B7, + 0x6388, 0xE2A3, 0x6389, 0xD3FC, 0x638C, 0xEDE6, 0x6392, 0xDBC9, 0x6396, 0xE4FA, 0x6398, 0xCFDE, 0x639B, 0xCED0, 0x63A0, 0xD5D3, + 0x63A1, 0xF3F5, 0x63A2, 0xF7AE, 0x63A5, 0xEFC8, 0x63A7, 0xCDF3, 0x63A8, 0xF5CF, 0x63A9, 0xE5F3, 0x63AA, 0xF0C2, 0x63C0, 0xCAD1, + 0x63C4, 0xEAF1, 0x63C6, 0xD0A6, 0x63CF, 0xD9DA, 0x63D0, 0xF0AB, 0x63D6, 0xEBE7, 0x63DA, 0xE5C0, 0x63DB, 0xFCB5, 0x63E1, 0xE4C4, + 0x63ED, 0xCCA9, 0x63EE, 0xFDC6, 0x63F4, 0xEAB5, 0x63F6, 0xE5AA, 0x63F7, 0xDFBA, 0x640D, 0xE1DF, 0x640F, 0xDAD1, 0x6414, 0xE1B8, + 0x6416, 0xE8F4, 0x6417, 0xD3FD, 0x641C, 0xE2A4, 0x6422, 0xF2CA, 0x642C, 0xDAE6, 0x642D, 0xF7B3, 0x643A, 0xFDCD, 0x643E, 0xF3B6, + 0x6458, 0xEED7, 0x6460, 0xF5C4, 0x6469, 0xD8A4, 0x646F, 0xF2A7, 0x6478, 0xD9B8, 0x6479, 0xD9B9, 0x647A, 0xEFC9, 0x6488, 0xD6CE, + 0x6491, 0xF7CB, 0x6492, 0xDFAE, 0x6493, 0xE8F5, 0x649A, 0xD2B5, 0x649E, 0xD3D5, 0x64A4, 0xF4CC, 0x64A5, 0xDAFC, 0x64AB, 0xD9E8, + 0x64AD, 0xF7EB, 0x64AE, 0xF5C9, 0x64B0, 0xF3BC, 0x64B2, 0xDAD2, 0x64BB, 0xD3B5, 0x64C1, 0xE8B6, 0x64C4, 0xD6CF, 0x64C5, 0xF4BA, + 0x64C7, 0xF7C9, 0x64CA, 0xCCAA, 0x64CD, 0xF0C3, 0x64CE, 0xCCD6, 0x64D2, 0xD0D3, 0x64D4, 0xD3BD, 0x64D8, 0xDBFB, 0x64DA, 0xCBE0, + 0x64E1, 0xD3E4, 0x64E2, 0xF6F7, 0x64E5, 0xD5BA, 0x64E6, 0xF3CD, 0x64E7, 0xCBE1, 0x64EC, 0xEBF4, 0x64F2, 0xF4AD, 0x64F4, 0xFCAA, + 0x64FA, 0xF7EC, 0x64FE, 0xE8F6, 0x6500, 0xDAE7, 0x6504, 0xF7CC, 0x6518, 0xE5C1, 0x651D, 0xE0EE, 0x6523, 0xD5FD, 0x652A, 0xCEE6, + 0x652B, 0xFCAB, 0x652C, 0xD5BB, 0x652F, 0xF2A8, 0x6536, 0xE2A5, 0x6537, 0xCDB9, 0x6538, 0xEAF2, 0x6539, 0xCBC7, 0x653B, 0xCDF4, + 0x653E, 0xDBAF, 0x653F, 0xEFD9, 0x6545, 0xCDBA, 0x6548, 0xFCF9, 0x654D, 0xDFF3, 0x654E, 0xCEE7, 0x654F, 0xDAC2, 0x6551, 0xCFAD, + 0x6556, 0xE7F9, 0x6557, 0xF8A8, 0x655E, 0xF3E2, 0x6562, 0xCAF2, 0x6563, 0xDFA4, 0x6566, 0xD4C4, 0x656C, 0xCCD7, 0x656D, 0xE5C2, + 0x6572, 0xCDBB, 0x6574, 0xEFDA, 0x6575, 0xEED8, 0x6577, 0xDDA7, 0x6578, 0xE2A6, 0x657E, 0xE0C0, 0x6582, 0xD6B0, 0x6583, 0xF8CA, + 0x6585, 0xFCFA, 0x6587, 0xD9FE, 0x658C, 0xDEB0, 0x6590, 0xDDEC, 0x6591, 0xDAE8, 0x6597, 0xD4E0, 0x6599, 0xD6F9, 0x659B, 0xCDD7, + 0x659C, 0xDED8, 0x659F, 0xF2F8, 0x65A1, 0xE4D6, 0x65A4, 0xD0C5, 0x65A5, 0xF4AE, 0x65A7, 0xDDA8, 0x65AB, 0xEDC5, 0x65AC, 0xF3D6, + 0x65AF, 0xDED9, 0x65B0, 0xE3E6, 0x65B7, 0xD3A8, 0x65B9, 0xDBB0, 0x65BC, 0xE5DA, 0x65BD, 0xE3BF, 0x65C1, 0xDBB1, 0x65C5, 0xD5E9, + 0x65CB, 0xE0C1, 0x65CC, 0xEFDB, 0x65CF, 0xF0E9, 0x65D2, 0xD7B2, 0x65D7, 0xD0FD, 0x65E0, 0xD9E9, 0x65E3, 0xD0FE, 0x65E5, 0xECED, + 0x65E6, 0xD3A9, 0x65E8, 0xF2A9, 0x65E9, 0xF0C4, 0x65EC, 0xE2E2, 0x65ED, 0xE9EF, 0x65F1, 0xF9D1, 0x65F4, 0xE9D9, 0x65FA, 0xE8DA, + 0x65FB, 0xDAC3, 0x65FC, 0xDAC4, 0x65FD, 0xD4C5, 0x65FF, 0xE7FA, 0x6606, 0xCDE0, 0x6607, 0xE3B0, 0x6609, 0xDBB2, 0x660A, 0xFBC4, + 0x660C, 0xF3E3, 0x660E, 0xD9A5, 0x660F, 0xFBE7, 0x6610, 0xDDCB, 0x6611, 0xD0D4, 0x6613, 0xE6B6, 0x6614, 0xE0AE, 0x6615, 0xFDDA, + 0x661E, 0xDCB5, 0x661F, 0xE0F8, 0x6620, 0xE7B1, 0x6625, 0xF5F0, 0x6627, 0xD8DC, 0x6628, 0xEDC6, 0x662D, 0xE1B9, 0x662F, 0xE3C0, + 0x6630, 0xF9C0, 0x6631, 0xE9F0, 0x6634, 0xD9DB, 0x6636, 0xF3E4, 0x663A, 0xDCB6, 0x663B, 0xE4E9, 0x6641, 0xF0C5, 0x6642, 0xE3C1, + 0x6643, 0xFCCC, 0x6644, 0xFCCD, 0x6649, 0xF2CB, 0x664B, 0xF2CC, 0x664F, 0xE4CF, 0x6659, 0xF1DB, 0x665B, 0xFAD9, 0x665D, 0xF1B8, + 0x665E, 0xFDF5, 0x665F, 0xE0F9, 0x6664, 0xE7FB, 0x6665, 0xFCB7, 0x6666, 0xFCE4, 0x6667, 0xFBC5, 0x6668, 0xE3E7, 0x6669, 0xD8B9, + 0x666B, 0xF6F8, 0x666E, 0xDCC5, 0x666F, 0xCCD8, 0x6673, 0xE0AF, 0x6674, 0xF4E7, 0x6676, 0xEFDC, 0x6677, 0xCFFC, 0x6678, 0xEFDD, + 0x667A, 0xF2AA, 0x6684, 0xFDBE, 0x6687, 0xCAAC, 0x6688, 0xFDBB, 0x6689, 0xFDC7, 0x668E, 0xE7B2, 0x6690, 0xEAD1, 0x6691, 0xDFF4, + 0x6696, 0xD1EC, 0x6697, 0xE4DE, 0x6698, 0xE5C3, 0x669D, 0xD9A6, 0x66A0, 0xCDBC, 0x66A2, 0xF3E5, 0x66AB, 0xEDD5, 0x66AE, 0xD9BA, + 0x66B2, 0xEDE7, 0x66B3, 0xFBB5, 0x66B4, 0xF8EC, 0x66B9, 0xE0E7, 0x66BB, 0xCCD9, 0x66BE, 0xD4C6, 0x66C4, 0xE7A5, 0x66C6, 0xD5F5, + 0x66C7, 0xD3BE, 0x66C9, 0xFCFB, 0x66D6, 0xE4F2, 0x66D9, 0xDFF5, 0x66DC, 0xE8F8, 0x66DD, 0xF8ED, 0x66E0, 0xCEC7, 0x66E6, 0xFDF6, + 0x66F0, 0xE8D8, 0x66F2, 0xCDD8, 0x66F3, 0xE7D6, 0x66F4, 0xCCDA, 0x66F7, 0xCAE3, 0x66F8, 0xDFF6, 0x66F9, 0xF0C7, 0x66FA, 0xF0C6, + 0x66FC, 0xD8BA, 0x66FE, 0xF1F4, 0x66FF, 0xF4F0, 0x6700, 0xF5CC, 0x6703, 0xFCE5, 0x6708, 0xEAC5, 0x6709, 0xEAF3, 0x670B, 0xDDDB, + 0x670D, 0xDCD7, 0x6714, 0xDEFD, 0x6715, 0xF2F9, 0x6717, 0xD5C7, 0x671B, 0xD8D0, 0x671D, 0xF0C8, 0x671E, 0xD1A1, 0x671F, 0xD1A2, + 0x6726, 0xD9D4, 0x6727, 0xD6E8, 0x6728, 0xD9CA, 0x672A, 0xDAB1, 0x672B, 0xD8C7, 0x672C, 0xDCE2, 0x672D, 0xF3CE, 0x672E, 0xF5F4, + 0x6731, 0xF1B9, 0x6734, 0xDAD3, 0x6736, 0xF6EA, 0x673A, 0xCFF5, 0x673D, 0xFDAE, 0x6746, 0xCAD2, 0x6749, 0xDFB4, 0x674E, 0xD7DD, + 0x674F, 0xFABA, 0x6750, 0xEEA7, 0x6751, 0xF5BD, 0x6753, 0xF8F5, 0x6756, 0xEDE8, 0x675C, 0xD4E1, 0x675E, 0xD1A3, 0x675F, 0xE1D6, + 0x676D, 0xF9F8, 0x676F, 0xDBCA, 0x6770, 0xCBF9, 0x6771, 0xD4D4, 0x6773, 0xD9DC, 0x6775, 0xEEBE, 0x6777, 0xF7ED, 0x677B, 0xD2EE, + 0x677E, 0xE1E6, 0x677F, 0xF7F9, 0x6787, 0xDDED, 0x6789, 0xE8DB, 0x678B, 0xDBB3, 0x678F, 0xD1F7, 0x6790, 0xE0B0, 0x6793, 0xD4E2, + 0x6795, 0xF6D7, 0x6797, 0xD7F9, 0x679A, 0xD8DD, 0x679C, 0xCDFD, 0x679D, 0xF2AB, 0x67AF, 0xCDBD, 0x67B0, 0xF8C2, 0x67B3, 0xF2AC, + 0x67B6, 0xCAAD, 0x67B7, 0xCAAE, 0x67B8, 0xCFAE, 0x67BE, 0xE3C2, 0x67C4, 0xDCB7, 0x67CF, 0xDBDA, 0x67D0, 0xD9BB, 0x67D1, 0xCAF3, + 0x67D2, 0xF6D3, 0x67D3, 0xE6F8, 0x67D4, 0xEAF5, 0x67DA, 0xEAF6, 0x67DD, 0xF6F9, 0x67E9, 0xCFAF, 0x67EC, 0xCAD3, 0x67EF, 0xCAAF, + 0x67F0, 0xD2B0, 0x67F1, 0xF1BA, 0x67F3, 0xD7B3, 0x67F4, 0xE3C3, 0x67F5, 0xF3FD, 0x67F6, 0xDEDA, 0x67FB, 0xDEDB, 0x67FE, 0xEFDE, + 0x6812, 0xE2E3, 0x6813, 0xEEFB, 0x6816, 0xDFF7, 0x6817, 0xD7CA, 0x6821, 0xCEE8, 0x6822, 0xDBDB, 0x682A, 0xF1BB, 0x682F, 0xE9F1, + 0x6838, 0xFAB7, 0x6839, 0xD0C6, 0x683C, 0xCCAB, 0x683D, 0xEEA8, 0x6840, 0xCBFA, 0x6841, 0xF9F9, 0x6842, 0xCCFD, 0x6843, 0xD3FE, + 0x6848, 0xE4D0, 0x684E, 0xF2EE, 0x6850, 0xD4D5, 0x6851, 0xDFCD, 0x6853, 0xFCB8, 0x6854, 0xD1D0, 0x686D, 0xF2CD, 0x6876, 0xF7D2, + 0x687F, 0xCAD4, 0x6881, 0xD5D9, 0x6885, 0xD8DE, 0x688F, 0xCDD9, 0x6893, 0xEEA9, 0x6894, 0xF6BC, 0x6897, 0xCCDB, 0x689D, 0xF0C9, + 0x689F, 0xFCFC, 0x68A1, 0xE8C9, 0x68A2, 0xF4FE, 0x68A7, 0xE7FC, 0x68A8, 0xD7DE, 0x68AD, 0xDEDC, 0x68AF, 0xF0AC, 0x68B0, 0xCCFE, + 0x68B1, 0xCDE1, 0x68B3, 0xE1BA, 0x68B5, 0xDBEF, 0x68B6, 0xDAB2, 0x68C4, 0xD1A5, 0x68C5, 0xDCB8, 0x68C9, 0xD8F6, 0x68CB, 0xD1A4, + 0x68CD, 0xCDE2, 0x68D2, 0xDCEA, 0x68D5, 0xF0F7, 0x68D7, 0xF0CA, 0x68D8, 0xD0BE, 0x68DA, 0xDDDC, 0x68DF, 0xD4D6, 0x68E0, 0xD3D6, + 0x68E7, 0xEDD0, 0x68E8, 0xCDA1, 0x68EE, 0xDFB5, 0x68F2, 0xDFF8, 0x68F9, 0xD4A1, 0x68FA, 0xCEB2, 0x6900, 0xE8CA, 0x6905, 0xEBF5, + 0x690D, 0xE3D5, 0x690E, 0xF5D0, 0x6912, 0xF5A1, 0x6927, 0xD9A7, 0x6930, 0xE5AB, 0x693D, 0xE6CB, 0x693F, 0xF5F1, 0x694A, 0xE5C5, + 0x6953, 0xF9A3, 0x6954, 0xE0DB, 0x6955, 0xF6EB, 0x6957, 0xCBF1, 0x6959, 0xD9EA, 0x695A, 0xF5A2, 0x695E, 0xD7D1, 0x6960, 0xD1F8, + 0x6961, 0xEAF8, 0x6962, 0xEAF9, 0x6963, 0xDAB3, 0x6968, 0xEFDF, 0x696B, 0xF1EF, 0x696D, 0xE5F6, 0x696E, 0xEEBF, 0x696F, 0xE2E4, + 0x6975, 0xD0BF, 0x6977, 0xFAAC, 0x6978, 0xF5D1, 0x6979, 0xE7B3, 0x6995, 0xE9BE, 0x699B, 0xF2CE, 0x699C, 0xDBB4, 0x69A5, 0xFCCE, + 0x69A7, 0xDDEE, 0x69AE, 0xE7B4, 0x69B4, 0xD7B4, 0x69BB, 0xF7B4, 0x69C1, 0xCDBE, 0x69C3, 0xDAE9, 0x69CB, 0xCFB0, 0x69CC, 0xF7D9, + 0x69CD, 0xF3E6, 0x69D0, 0xCED9, 0x69E8, 0xCEAA, 0x69EA, 0xCBC8, 0x69FB, 0xD0A7, 0x69FD, 0xF0CB, 0x69FF, 0xD0C7, 0x6A02, 0xE4C5, + 0x6A0A, 0xDBE0, 0x6A11, 0xD5DA, 0x6A13, 0xD7A7, 0x6A17, 0xEEC0, 0x6A19, 0xF8F6, 0x6A1E, 0xF5D2, 0x6A1F, 0xEDE9, 0x6A21, 0xD9BC, + 0x6A23, 0xE5C6, 0x6A35, 0xF5A3, 0x6A38, 0xDAD4, 0x6A39, 0xE2A7, 0x6A3A, 0xFBFC, 0x6A3D, 0xF1DC, 0x6A44, 0xCAF4, 0x6A48, 0xE8FA, + 0x6A4B, 0xCEE9, 0x6A52, 0xE9F8, 0x6A53, 0xE2E5, 0x6A58, 0xD0B9, 0x6A59, 0xD4F2, 0x6A5F, 0xD1A6, 0x6A61, 0xDFCE, 0x6A6B, 0xFCF4, + 0x6A80, 0xD3AA, 0x6A84, 0xCCAC, 0x6A89, 0xEFE0, 0x6A8D, 0xE5E5, 0x6A8E, 0xD0D5, 0x6A97, 0xDBFC, 0x6A9C, 0xFCE6, 0x6AA2, 0xCBFE, + 0x6AA3, 0xEDEA, 0x6AB3, 0xDEB1, 0x6ABB, 0xF9E3, 0x6AC2, 0xD4A2, 0x6AC3, 0xCFF6, 0x6AD3, 0xD6D0, 0x6ADA, 0xD5EA, 0x6ADB, 0xF1EE, + 0x6AF6, 0xFACB, 0x6AFB, 0xE5A1, 0x6B04, 0xD5B1, 0x6B0A, 0xCFED, 0x6B0C, 0xEDEB, 0x6B12, 0xD5B2, 0x6B16, 0xD5BC, 0x6B20, 0xFDE2, + 0x6B21, 0xF3AD, 0x6B23, 0xFDDB, 0x6B32, 0xE9B0, 0x6B3A, 0xD1A7, 0x6B3D, 0xFDE3, 0x6B3E, 0xCEB3, 0x6B46, 0xFDE4, 0x6B47, 0xFACE, + 0x6B4C, 0xCAB0, 0x6B4E, 0xF7A7, 0x6B50, 0xCFB1, 0x6B5F, 0xE6A2, 0x6B61, 0xFCB6, 0x6B62, 0xF2AD, 0x6B63, 0xEFE1, 0x6B64, 0xF3AE, + 0x6B65, 0xDCC6, 0x6B66, 0xD9EB, 0x6B6A, 0xE8E0, 0x6B72, 0xE1A8, 0x6B77, 0xD5F6, 0x6B78, 0xCFFD, 0x6B7B, 0xDEDD, 0x6B7F, 0xD9D1, + 0x6B83, 0xE4EA, 0x6B84, 0xF2CF, 0x6B86, 0xF7BF, 0x6B89, 0xE2E6, 0x6B8A, 0xE2A8, 0x6B96, 0xE3D6, 0x6B98, 0xEDD1, 0x6B9E, 0xE9F9, + 0x6BAE, 0xD6B1, 0x6BAF, 0xDEB2, 0x6BB2, 0xE0E8, 0x6BB5, 0xD3AB, 0x6BB7, 0xEBDC, 0x6BBA, 0xDFAF, 0x6BBC, 0xCAC3, 0x6BBF, 0xEEFC, + 0x6BC1, 0xFDC3, 0x6BC5, 0xEBF6, 0x6BC6, 0xCFB2, 0x6BCB, 0xD9EC, 0x6BCD, 0xD9BD, 0x6BCF, 0xD8DF, 0x6BD2, 0xD4B8, 0x6BD3, 0xEBBE, + 0x6BD4, 0xDDEF, 0x6BD6, 0xDDF0, 0x6BD7, 0xDDF1, 0x6BD8, 0xDDF2, 0x6BDB, 0xD9BE, 0x6BEB, 0xFBC6, 0x6BEC, 0xCFB3, 0x6C08, 0xEEFD, + 0x6C0F, 0xE4AB, 0x6C11, 0xDAC5, 0x6C13, 0xD8EC, 0x6C23, 0xD1A8, 0x6C34, 0xE2A9, 0x6C37, 0xDEBC, 0x6C38, 0xE7B5, 0x6C3E, 0xDBF0, + 0x6C40, 0xEFE2, 0x6C41, 0xF1F0, 0x6C42, 0xCFB4, 0x6C4E, 0xDBF1, 0x6C50, 0xE0B1, 0x6C55, 0xDFA5, 0x6C57, 0xF9D2, 0x6C5A, 0xE7FD, + 0x6C5D, 0xE6A3, 0x6C5E, 0xFBF1, 0x6C5F, 0xCBB0, 0x6C60, 0xF2AE, 0x6C68, 0xCDE7, 0x6C6A, 0xE8DC, 0x6C6D, 0xE7D7, 0x6C70, 0xF7C0, + 0x6C72, 0xD0E3, 0x6C76, 0xDAA1, 0x6C7A, 0xCCBD, 0x6C7D, 0xD1A9, 0x6C7E, 0xDDCC, 0x6C81, 0xE3FE, 0x6C82, 0xD1AA, 0x6C83, 0xE8AA, + 0x6C85, 0xEAB6, 0x6C86, 0xF9FA, 0x6C87, 0xE6CC, 0x6C88, 0xF6D8, 0x6C8C, 0xD4C7, 0x6C90, 0xD9CB, 0x6C92, 0xD9D2, 0x6C93, 0xD3CB, + 0x6C94, 0xD8F7, 0x6C95, 0xDAA9, 0x6C96, 0xF5F8, 0x6C99, 0xDEDE, 0x6C9A, 0xF2AF, 0x6C9B, 0xF8A9, 0x6CAB, 0xD8C8, 0x6CAE, 0xEEC1, + 0x6CB3, 0xF9C1, 0x6CB8, 0xDDF3, 0x6CB9, 0xEAFA, 0x6CBB, 0xF6BD, 0x6CBC, 0xE1BB, 0x6CBD, 0xCDBF, 0x6CBE, 0xF4D4, 0x6CBF, 0xE6CD, + 0x6CC1, 0xFCCF, 0x6CC2, 0xFBA2, 0x6CC4, 0xE0DC, 0x6CC9, 0xF4BB, 0x6CCA, 0xDAD5, 0x6CCC, 0xF9B2, 0x6CD3, 0xFBF2, 0x6CD5, 0xDBF6, + 0x6CD7, 0xDEDF, 0x6CDB, 0xDBF2, 0x6CE1, 0xF8DC, 0x6CE2, 0xF7EE, 0x6CE3, 0xEBE8, 0x6CE5, 0xD2FA, 0x6CE8, 0xF1BC, 0x6CEB, 0xFADA, + 0x6CEE, 0xDAEA, 0x6CEF, 0xDAC6, 0x6CF0, 0xF7C1, 0x6CF3, 0xE7B6, 0x6D0B, 0xE5C7, 0x6D0C, 0xD6AC, 0x6D11, 0xDCC7, 0x6D17, 0xE1A9, + 0x6D19, 0xE2AA, 0x6D1B, 0xD5A6, 0x6D1E, 0xD4D7, 0x6D25, 0xF2D0, 0x6D27, 0xEAFB, 0x6D29, 0xE0DD, 0x6D2A, 0xFBF3, 0x6D32, 0xF1BD, + 0x6D35, 0xE2E7, 0x6D36, 0xFDD7, 0x6D38, 0xCEC8, 0x6D39, 0xEAB7, 0x6D3B, 0xFCC0, 0x6D3D, 0xFDE7, 0x6D3E, 0xF7EF, 0x6D41, 0xD7B5, + 0x6D59, 0xEFBA, 0x6D5A, 0xF1DD, 0x6D5C, 0xDEB3, 0x6D63, 0xE8CB, 0x6D66, 0xF8DD, 0x6D69, 0xFBC7, 0x6D6A, 0xD5C8, 0x6D6C, 0xD7DF, + 0x6D6E, 0xDDA9, 0x6D74, 0xE9B1, 0x6D77, 0xFAAD, 0x6D78, 0xF6D9, 0x6D79, 0xFAF4, 0x6D7F, 0xF8AA, 0x6D85, 0xE6EE, 0x6D87, 0xCCDC, + 0x6D88, 0xE1BC, 0x6D89, 0xE0EF, 0x6D8C, 0xE9BF, 0x6D8D, 0xFCFD, 0x6D8E, 0xE6CE, 0x6D91, 0xE1D7, 0x6D93, 0xE6CF, 0x6D95, 0xF4F1, + 0x6DAF, 0xE4F3, 0x6DB2, 0xE4FB, 0x6DB5, 0xF9E4, 0x6DC0, 0xEFE3, 0x6DC3, 0xCFEE, 0x6DC4, 0xF6BE, 0x6DC5, 0xE0B2, 0x6DC6, 0xFCFE, + 0x6DC7, 0xD1AB, 0x6DCB, 0xD7FA, 0x6DCF, 0xFBC8, 0x6DD1, 0xE2D7, 0x6DD8, 0xD4A3, 0x6DD9, 0xF0F8, 0x6DDA, 0xD7A8, 0x6DDE, 0xE1E7, + 0x6DE1, 0xD3BF, 0x6DE8, 0xEFE4, 0x6DEA, 0xD7C5, 0x6DEB, 0xEBE2, 0x6DEE, 0xFCE7, 0x6DF1, 0xE4A2, 0x6DF3, 0xE2E8, 0x6DF5, 0xE6D0, + 0x6DF7, 0xFBE8, 0x6DF8, 0xF4E8, 0x6DF9, 0xE5F4, 0x6DFA, 0xF4BC, 0x6DFB, 0xF4D5, 0x6E17, 0xDFB6, 0x6E19, 0xFCB9, 0x6E1A, 0xEEC2, + 0x6E1B, 0xCAF5, 0x6E1F, 0xEFE5, 0x6E20, 0xCBE2, 0x6E21, 0xD4A4, 0x6E23, 0xDEE0, 0x6E24, 0xDAFD, 0x6E25, 0xE4C6, 0x6E26, 0xE8BE, + 0x6E2B, 0xE0DE, 0x6E2C, 0xF6B4, 0x6E2D, 0xEAD2, 0x6E2F, 0xF9FB, 0x6E32, 0xE0C2, 0x6E34, 0xCAE4, 0x6E36, 0xE7B7, 0x6E38, 0xEAFD, + 0x6E3A, 0xD9DD, 0x6E3C, 0xDAB4, 0x6E3D, 0xEEAA, 0x6E3E, 0xFBE9, 0x6E43, 0xDBCB, 0x6E44, 0xDAB5, 0x6E4A, 0xF1BE, 0x6E4D, 0xD3AC, + 0x6E56, 0xFBC9, 0x6E58, 0xDFCF, 0x6E5B, 0xD3C0, 0x6E5C, 0xE3D7, 0x6E5E, 0xEFE6, 0x6E5F, 0xFCD0, 0x6E67, 0xE9C0, 0x6E6B, 0xF5D3, + 0x6E6E, 0xECDC, 0x6E6F, 0xF7B7, 0x6E72, 0xEAB8, 0x6E73, 0xD1F9, 0x6E7A, 0xDCC8, 0x6E90, 0xEAB9, 0x6E96, 0xF1DE, 0x6E9C, 0xD7B6, + 0x6E9D, 0xCFB5, 0x6E9F, 0xD9A8, 0x6EA2, 0xECEE, 0x6EA5, 0xDDAA, 0x6EAA, 0xCDA2, 0x6EAB, 0xE8AE, 0x6EAF, 0xE1BD, 0x6EB1, 0xF2D1, + 0x6EB6, 0xE9C1, 0x6EBA, 0xD2FC, 0x6EC2, 0xDBB5, 0x6EC4, 0xF3E7, 0x6EC5, 0xD8FE, 0x6EC9, 0xFCD1, 0x6ECB, 0xEDB2, 0x6ECC, 0xF4AF, + 0x6ECE, 0xFBA3, 0x6ED1, 0xFCC1, 0x6ED3, 0xEEAB, 0x6ED4, 0xD4A5, 0x6EEF, 0xF4F2, 0x6EF4, 0xEED9, 0x6EF8, 0xFBCA, 0x6EFE, 0xCDE3, + 0x6EFF, 0xD8BB, 0x6F01, 0xE5DB, 0x6F02, 0xF8F7, 0x6F06, 0xF6D4, 0x6F0F, 0xD7A9, 0x6F11, 0xCBC9, 0x6F14, 0xE6D1, 0x6F15, 0xF0CC, + 0x6F20, 0xD8AE, 0x6F22, 0xF9D3, 0x6F23, 0xD5FE, 0x6F2B, 0xD8BC, 0x6F2C, 0xF2B0, 0x6F31, 0xE2AB, 0x6F32, 0xF3E8, 0x6F38, 0xEFC2, + 0x6F3F, 0xEDEC, 0x6F41, 0xE7B8, 0x6F51, 0xDAFE, 0x6F54, 0xCCBE, 0x6F57, 0xF2FC, 0x6F58, 0xDAEB, 0x6F5A, 0xE2D8, 0x6F5B, 0xEDD6, + 0x6F5E, 0xD6D1, 0x6F5F, 0xE0B3, 0x6F62, 0xFCD2, 0x6F64, 0xEBC8, 0x6F6D, 0xD3C1, 0x6F6E, 0xF0CD, 0x6F70, 0xCFF7, 0x6F7A, 0xEDD2, + 0x6F7C, 0xD4D8, 0x6F7D, 0xDCC9, 0x6F7E, 0xD7F1, 0x6F81, 0xDFBB, 0x6F84, 0xF3A5, 0x6F88, 0xF4CD, 0x6F8D, 0xF1BF, 0x6F8E, 0xF8B1, + 0x6F90, 0xE9FA, 0x6F94, 0xFBCB, 0x6F97, 0xCAD5, 0x6FA3, 0xF9D4, 0x6FA4, 0xF7CA, 0x6FA7, 0xD6C8, 0x6FAE, 0xFCE8, 0x6FAF, 0xF3BD, + 0x6FB1, 0xEEFE, 0x6FB3, 0xE7FE, 0x6FB9, 0xD3C2, 0x6FBE, 0xD3B6, 0x6FC0, 0xCCAD, 0x6FC1, 0xF6FA, 0x6FC2, 0xD6B2, 0x6FC3, 0xD2D8, + 0x6FCA, 0xE7D8, 0x6FD5, 0xE3A5, 0x6FDA, 0xE7B9, 0x6FDF, 0xF0AD, 0x6FE0, 0xFBCC, 0x6FE1, 0xEBA1, 0x6FE4, 0xD4A6, 0x6FE9, 0xFBCD, + 0x6FEB, 0xD5BD, 0x6FEC, 0xF1DF, 0x6FEF, 0xF6FB, 0x6FF1, 0xDEB4, 0x6FFE, 0xD5EB, 0x7001, 0xE5C8, 0x7005, 0xFBA4, 0x7006, 0xD4B9, + 0x7009, 0xDEE1, 0x700B, 0xE4A3, 0x700F, 0xD7B7, 0x7011, 0xF8EE, 0x7015, 0xDEB5, 0x7018, 0xD6D2, 0x701A, 0xF9D5, 0x701B, 0xE7BA, + 0x701C, 0xEBD5, 0x701D, 0xD5F7, 0x701E, 0xEFE7, 0x701F, 0xE1BE, 0x7023, 0xFAAE, 0x7027, 0xD6E9, 0x7028, 0xD6EE, 0x702F, 0xE7BB, + 0x7037, 0xECCB, 0x703E, 0xD5B3, 0x704C, 0xCEB4, 0x7050, 0xFBA5, 0x7051, 0xE1EE, 0x7058, 0xF7A8, 0x705D, 0xFBCE, 0x7063, 0xD8BD, + 0x706B, 0xFBFD, 0x7070, 0xFCE9, 0x7078, 0xCFB6, 0x707C, 0xEDC7, 0x707D, 0xEEAC, 0x7085, 0xCCDD, 0x708A, 0xF6A7, 0x708E, 0xE6FA, + 0x7092, 0xF5A4, 0x7098, 0xFDDC, 0x7099, 0xEDB3, 0x709A, 0xCEC9, 0x70A1, 0xEFE8, 0x70A4, 0xE1BF, 0x70AB, 0xFADB, 0x70AC, 0xCBE3, + 0x70AD, 0xF7A9, 0x70AF, 0xFBA6, 0x70B3, 0xDCB9, 0x70B7, 0xF1C0, 0x70B8, 0xEDC8, 0x70B9, 0xEFC3, 0x70C8, 0xD6AD, 0x70CB, 0xFDCE, + 0x70CF, 0xE8A1, 0x70D8, 0xFBF4, 0x70D9, 0xD5A7, 0x70DD, 0xF1F6, 0x70DF, 0xE6D3, 0x70F1, 0xCCDE, 0x70F9, 0xF8B2, 0x70FD, 0xDCEB, + 0x7104, 0xFDB6, 0x7109, 0xE5EA, 0x710C, 0xF1E0, 0x7119, 0xDBCC, 0x711A, 0xDDCD, 0x711E, 0xD4C8, 0x7121, 0xD9ED, 0x7126, 0xF5A5, + 0x7130, 0xE6FB, 0x7136, 0xE6D4, 0x7147, 0xFDC8, 0x7149, 0xD6A1, 0x714A, 0xFDBF, 0x714C, 0xFCD3, 0x714E, 0xEFA1, 0x7150, 0xE7BC, + 0x7156, 0xD1EE, 0x7159, 0xE6D5, 0x715C, 0xE9F2, 0x715E, 0xDFB0, 0x7164, 0xD8E0, 0x7165, 0xFCBA, 0x7166, 0xFDAF, 0x7167, 0xF0CE, + 0x7169, 0xDBE1, 0x716C, 0xE5C9, 0x716E, 0xEDB4, 0x717D, 0xE0C3, 0x7184, 0xE3D8, 0x7189, 0xE9FB, 0x718A, 0xEAA8, 0x718F, 0xFDB7, + 0x7192, 0xFBA7, 0x7194, 0xE9C2, 0x7199, 0xFDF7, 0x719F, 0xE2D9, 0x71A2, 0xDCEC, 0x71AC, 0xE8A2, 0x71B1, 0xE6F0, 0x71B9, 0xFDF8, + 0x71BA, 0xFDF9, 0x71BE, 0xF6BF, 0x71C1, 0xE7A7, 0x71C3, 0xE6D7, 0x71C8, 0xD4F3, 0x71C9, 0xD4C9, 0x71CE, 0xD6FA, 0x71D0, 0xD7F2, + 0x71D2, 0xE1C0, 0x71D4, 0xDBE2, 0x71D5, 0xE6D8, 0x71DF, 0xE7BD, 0x71E5, 0xF0CF, 0x71E6, 0xF3BE, 0x71E7, 0xE2AC, 0x71ED, 0xF5B7, + 0x71EE, 0xE0F0, 0x71FB, 0xFDB8, 0x71FC, 0xE3E8, 0x71FE, 0xD4A7, 0x71FF, 0xE8FC, 0x7200, 0xFAD2, 0x7206, 0xF8EF, 0x7210, 0xD6D3, + 0x721B, 0xD5B4, 0x722A, 0xF0D0, 0x722C, 0xF7F0, 0x722D, 0xEEB3, 0x7230, 0xEABA, 0x7232, 0xEAD3, 0x7235, 0xEDC9, 0x7236, 0xDDAB, + 0x723A, 0xE5AC, 0x723B, 0xFDA1, 0x723D, 0xDFD0, 0x723E, 0xECB3, 0x7240, 0xDFD1, 0x7246, 0xEDED, 0x7247, 0xF8B8, 0x7248, 0xF7FA, + 0x724C, 0xF8AB, 0x7252, 0xF4E0, 0x7258, 0xD4BA, 0x7259, 0xE4B3, 0x725B, 0xE9DA, 0x725D, 0xDEB6, 0x725F, 0xD9BF, 0x7261, 0xD9C0, + 0x7262, 0xD6EF, 0x7267, 0xD9CC, 0x7269, 0xDAAA, 0x7272, 0xDFE5, 0x7279, 0xF7E5, 0x727D, 0xCCB2, 0x7280, 0xDFF9, 0x7281, 0xD7E0, + 0x72A2, 0xD4BB, 0x72A7, 0xFDFA, 0x72AC, 0xCCB3, 0x72AF, 0xDBF3, 0x72C0, 0xDFD2, 0x72C2, 0xCECA, 0x72C4, 0xEEDA, 0x72CE, 0xE4E4, + 0x72D0, 0xFBCF, 0x72D7, 0xCFB7, 0x72D9, 0xEEC3, 0x72E1, 0xCEEA, 0x72E9, 0xE2AD, 0x72F8, 0xD7E1, 0x72F9, 0xFAF5, 0x72FC, 0xD5C9, + 0x72FD, 0xF8AC, 0x730A, 0xE7D9, 0x7316, 0xF3E9, 0x731B, 0xD8ED, 0x731C, 0xE3C4, 0x731D, 0xF0F1, 0x7325, 0xE8E5, 0x7329, 0xE0FA, + 0x732A, 0xEEC4, 0x732B, 0xD9DE, 0x7336, 0xEBA2, 0x7337, 0xEBA3, 0x733E, 0xFCC2, 0x733F, 0xEABB, 0x7344, 0xE8AB, 0x7345, 0xDEE2, + 0x7350, 0xEDEF, 0x7352, 0xE8A3, 0x7357, 0xCFF1, 0x7368, 0xD4BC, 0x736A, 0xFCEA, 0x7370, 0xE7BE, 0x7372, 0xFCF2, 0x7375, 0xD6B4, + 0x7378, 0xE2AE, 0x737A, 0xD3B7, 0x737B, 0xFACC, 0x7384, 0xFADC, 0x7386, 0xEDB5, 0x7387, 0xE1E3, 0x7389, 0xE8AC, 0x738B, 0xE8DD, + 0x738E, 0xEFE9, 0x7394, 0xF4BD, 0x7396, 0xCFB8, 0x7397, 0xE9DB, 0x7398, 0xD1AC, 0x739F, 0xDAC7, 0x73A7, 0xEBC9, 0x73A9, 0xE8CC, + 0x73AD, 0xDEB7, 0x73B2, 0xD6BC, 0x73B3, 0xD3E5, 0x73B9, 0xFADD, 0x73C0, 0xDAD6, 0x73C2, 0xCAB1, 0x73C9, 0xDAC8, 0x73CA, 0xDFA6, + 0x73CC, 0xF9B3, 0x73CD, 0xF2D2, 0x73CF, 0xCAC4, 0x73D6, 0xCECB, 0x73D9, 0xCDF5, 0x73DD, 0xFDB0, 0x73DE, 0xD5A8, 0x73E0, 0xF1C1, + 0x73E3, 0xE2E9, 0x73E4, 0xDCCA, 0x73E5, 0xECB4, 0x73E6, 0xFAC0, 0x73E9, 0xFBA8, 0x73EA, 0xD0A8, 0x73ED, 0xDAEC, 0x73F7, 0xD9EE, + 0x73F9, 0xE0FB, 0x73FD, 0xEFEA, 0x73FE, 0xFADE, 0x7401, 0xE0C4, 0x7403, 0xCFB9, 0x7405, 0xD5CA, 0x7406, 0xD7E2, 0x7407, 0xE2AF, + 0x7409, 0xD7B8, 0x7413, 0xE8CD, 0x741B, 0xF6DA, 0x7420, 0xEFA2, 0x7421, 0xE2DA, 0x7422, 0xF6FC, 0x7425, 0xFBD0, 0x7426, 0xD1AD, + 0x7428, 0xCDE4, 0x742A, 0xD1AE, 0x742B, 0xDCED, 0x742C, 0xE8CE, 0x742E, 0xF0F9, 0x742F, 0xCEB5, 0x7430, 0xE6FC, 0x7433, 0xD7FB, + 0x7434, 0xD0D6, 0x7435, 0xDDF5, 0x7436, 0xF7F1, 0x7438, 0xF6FD, 0x743A, 0xDBF7, 0x743F, 0xFBEA, 0x7440, 0xE9DC, 0x7441, 0xD9C1, + 0x7443, 0xF5F2, 0x7444, 0xE0C5, 0x744B, 0xEAD4, 0x7455, 0xF9C2, 0x7457, 0xEABC, 0x7459, 0xD2C5, 0x745A, 0xFBD1, 0x745B, 0xE7C0, + 0x745C, 0xEBA5, 0x745E, 0xDFFA, 0x745F, 0xE3A2, 0x7460, 0xD7B9, 0x7462, 0xE9C3, 0x7464, 0xE8FD, 0x7465, 0xE8AF, 0x7468, 0xF2D3, + 0x7469, 0xFBA9, 0x746A, 0xD8A5, 0x746F, 0xD5CB, 0x747E, 0xD0C8, 0x7482, 0xD1AF, 0x7483, 0xD7E3, 0x7487, 0xE0C6, 0x7489, 0xD6A2, + 0x748B, 0xEDF0, 0x7498, 0xD7F3, 0x749C, 0xFCD4, 0x749E, 0xDAD7, 0x749F, 0xCCDF, 0x74A1, 0xF2D4, 0x74A3, 0xD1B0, 0x74A5, 0xCCE0, + 0x74A7, 0xDBFD, 0x74A8, 0xF3BF, 0x74AA, 0xF0D1, 0x74B0, 0xFCBB, 0x74B2, 0xE2B0, 0x74B5, 0xE6A5, 0x74B9, 0xE2DB, 0x74BD, 0xDFDE, + 0x74BF, 0xE0C7, 0x74C6, 0xF2EF, 0x74CA, 0xCCE1, 0x74CF, 0xD6EA, 0x74D4, 0xE7C2, 0x74D8, 0xCEB6, 0x74DA, 0xF3C0, 0x74DC, 0xCDFE, + 0x74E0, 0xFBD2, 0x74E2, 0xF8F8, 0x74E3, 0xF7FB, 0x74E6, 0xE8BF, 0x74EE, 0xE8B7, 0x74F7, 0xEDB6, 0x7501, 0xDCBA, 0x7504, 0xCCB4, + 0x7511, 0xF1F7, 0x7515, 0xE8B8, 0x7518, 0xCAF6, 0x751A, 0xE4A4, 0x751B, 0xF4D6, 0x751F, 0xDFE6, 0x7523, 0xDFA7, 0x7525, 0xDFE7, + 0x7526, 0xE1C1, 0x7528, 0xE9C4, 0x752B, 0xDCCB, 0x752C, 0xE9C5, 0x7530, 0xEFA3, 0x7531, 0xEBA6, 0x7532, 0xCBA3, 0x7533, 0xE3E9, + 0x7537, 0xD1FB, 0x7538, 0xEFA4, 0x753A, 0xEFEB, 0x7547, 0xD0B4, 0x754C, 0xCDA3, 0x754F, 0xE8E6, 0x7551, 0xEFA5, 0x7553, 0xD3CC, + 0x7554, 0xDAED, 0x7559, 0xD7BA, 0x755B, 0xF2D5, 0x755C, 0xF5E5, 0x755D, 0xD9EF, 0x7562, 0xF9B4, 0x7565, 0xD5D4, 0x7566, 0xFDCF, + 0x756A, 0xDBE3, 0x756F, 0xF1E1, 0x7570, 0xECB6, 0x7575, 0xFBFE, 0x7576, 0xD3D7, 0x7578, 0xD1B1, 0x757A, 0xCBB1, 0x757F, 0xD1B2, + 0x7586, 0xCBB2, 0x7587, 0xF1C2, 0x758A, 0xF4E1, 0x758B, 0xF9B5, 0x758E, 0xE1C3, 0x758F, 0xE1C2, 0x7591, 0xEBF7, 0x759D, 0xDFA8, + 0x75A5, 0xCBCA, 0x75AB, 0xE6B9, 0x75B1, 0xF8DE, 0x75B2, 0xF9AA, 0x75B3, 0xCAF7, 0x75B5, 0xEDB7, 0x75B8, 0xD3B8, 0x75B9, 0xF2D6, + 0x75BC, 0xD4D9, 0x75BD, 0xEEC5, 0x75BE, 0xF2F0, 0x75C2, 0xCAB2, 0x75C5, 0xDCBB, 0x75C7, 0xF1F8, 0x75CD, 0xECB7, 0x75D2, 0xE5CA, + 0x75D4, 0xF6C0, 0x75D5, 0xFDDD, 0x75D8, 0xD4E3, 0x75D9, 0xCCE2, 0x75DB, 0xF7D4, 0x75E2, 0xD7E5, 0x75F0, 0xD3C3, 0x75F2, 0xD8A6, + 0x75F4, 0xF6C1, 0x75FA, 0xDDF6, 0x75FC, 0xCDC0, 0x7600, 0xE5DC, 0x760D, 0xE5CB, 0x7619, 0xE1C4, 0x761F, 0xE8B0, 0x7620, 0xF4B0, + 0x7621, 0xF3EA, 0x7622, 0xDAEE, 0x7624, 0xD7BB, 0x7626, 0xE2B1, 0x763B, 0xD7AA, 0x7642, 0xD6FB, 0x764C, 0xE4DF, 0x764E, 0xCAD6, + 0x7652, 0xEBA8, 0x7656, 0xDBFE, 0x7661, 0xF6C2, 0x7664, 0xEFBB, 0x7669, 0xD4FD, 0x766C, 0xE0C8, 0x7670, 0xE8B9, 0x7672, 0xEFA6, + 0x7678, 0xCDA4, 0x767B, 0xD4F4, 0x767C, 0xDBA1, 0x767D, 0xDBDC, 0x767E, 0xDBDD, 0x7684, 0xEEDC, 0x7686, 0xCBCB, 0x7687, 0xFCD5, + 0x768E, 0xCEEB, 0x7690, 0xCDC1, 0x7693, 0xFBD3, 0x76AE, 0xF9AB, 0x76BA, 0xF5D4, 0x76BF, 0xD9A9, 0x76C2, 0xE9DD, 0x76C3, 0xDBCD, + 0x76C6, 0xDDCE, 0x76C8, 0xE7C3, 0x76CA, 0xECCC, 0x76D2, 0xF9EC, 0x76D6, 0xCBCC, 0x76DB, 0xE0FC, 0x76DC, 0xD4A8, 0x76DE, 0xEDD3, + 0x76DF, 0xD8EF, 0x76E1, 0xF2D7, 0x76E3, 0xCAF8, 0x76E4, 0xDAEF, 0x76E7, 0xD6D4, 0x76EE, 0xD9CD, 0x76F2, 0xD8EE, 0x76F4, 0xF2C1, + 0x76F8, 0xDFD3, 0x76FC, 0xDAF0, 0x76FE, 0xE2EA, 0x7701, 0xE0FD, 0x7704, 0xD8F8, 0x7708, 0xF7AF, 0x7709, 0xDAB6, 0x770B, 0xCAD7, + 0x771E, 0xF2D8, 0x7720, 0xD8F9, 0x7729, 0xFADF, 0x7737, 0xCFEF, 0x7738, 0xD9C2, 0x773A, 0xF0D2, 0x773C, 0xE4D1, 0x7740, 0xF3B7, + 0x774D, 0xFAE0, 0x775B, 0xEFEC, 0x7761, 0xE2B2, 0x7763, 0xD4BD, 0x7766, 0xD9CE, 0x776B, 0xF4E2, 0x7779, 0xD4A9, 0x777E, 0xCDC2, + 0x777F, 0xE7DA, 0x778B, 0xF2D9, 0x7791, 0xD9AA, 0x779E, 0xD8BE, 0x77A5, 0xDCAD, 0x77AC, 0xE2EB, 0x77AD, 0xD6FC, 0x77B0, 0xCAF9, + 0x77B3, 0xD4DA, 0x77BB, 0xF4D7, 0x77BC, 0xCCA1, 0x77BF, 0xCFBA, 0x77D7, 0xF5B8, 0x77DB, 0xD9C3, 0x77DC, 0xD0E8, 0x77E2, 0xE3C5, + 0x77E3, 0xEBF8, 0x77E5, 0xF2B1, 0x77E9, 0xCFBB, 0x77ED, 0xD3AD, 0x77EE, 0xE8E1, 0x77EF, 0xCEEC, 0x77F3, 0xE0B4, 0x7802, 0xDEE3, + 0x7812, 0xDDF7, 0x7825, 0xF2B2, 0x7826, 0xF3F6, 0x7827, 0xF6DB, 0x782C, 0xD7FE, 0x7832, 0xF8DF, 0x7834, 0xF7F2, 0x7845, 0xD0A9, + 0x784F, 0xE6DA, 0x785D, 0xF5A6, 0x786B, 0xD7BC, 0x786C, 0xCCE3, 0x786F, 0xE6DB, 0x787C, 0xDDDD, 0x7881, 0xD1B3, 0x7887, 0xEFED, + 0x788C, 0xD6DE, 0x788D, 0xE4F4, 0x788E, 0xE1EF, 0x7891, 0xDDF8, 0x7897, 0xE8CF, 0x78A3, 0xCAE5, 0x78A7, 0xDCA1, 0x78A9, 0xE0B5, + 0x78BA, 0xFCAC, 0x78BB, 0xFCAD, 0x78BC, 0xD8A7, 0x78C1, 0xEDB8, 0x78C5, 0xDBB6, 0x78CA, 0xD6F0, 0x78CB, 0xF3AF, 0x78CE, 0xCDA5, + 0x78D0, 0xDAF1, 0x78E8, 0xD8A8, 0x78EC, 0xCCE4, 0x78EF, 0xD1B4, 0x78F5, 0xCAD8, 0x78FB, 0xDAF2, 0x7901, 0xF5A7, 0x790E, 0xF5A8, + 0x7916, 0xE6A6, 0x792A, 0xD5EC, 0x792B, 0xD5F8, 0x792C, 0xDAF3, 0x793A, 0xE3C6, 0x793E, 0xDEE4, 0x7940, 0xDEE5, 0x7941, 0xD1B5, + 0x7947, 0xD1B6, 0x7948, 0xD1B7, 0x7949, 0xF2B3, 0x7950, 0xE9DE, 0x7956, 0xF0D3, 0x7957, 0xF2B4, 0x795A, 0xF0D4, 0x795B, 0xCBE4, + 0x795C, 0xFBD4, 0x795D, 0xF5E6, 0x795E, 0xE3EA, 0x7960, 0xDEE6, 0x7965, 0xDFD4, 0x7968, 0xF8F9, 0x796D, 0xF0AE, 0x797A, 0xD1B8, + 0x797F, 0xD6DF, 0x7981, 0xD0D7, 0x798D, 0xFCA1, 0x798E, 0xEFEE, 0x798F, 0xDCD8, 0x7991, 0xE9DF, 0x79A6, 0xE5DD, 0x79A7, 0xFDFB, + 0x79AA, 0xE0C9, 0x79AE, 0xD6C9, 0x79B1, 0xD4AA, 0x79B3, 0xE5CC, 0x79B9, 0xE9E0, 0x79BD, 0xD0D8, 0x79BE, 0xFCA2, 0x79BF, 0xD4BE, + 0x79C0, 0xE2B3, 0x79C1, 0xDEE7, 0x79C9, 0xDCBC, 0x79CA, 0xD2B6, 0x79CB, 0xF5D5, 0x79D1, 0xCEA1, 0x79D2, 0xF5A9, 0x79D5, 0xDDF9, + 0x79D8, 0xDDFA, 0x79DF, 0xF0D5, 0x79E4, 0xF6DF, 0x79E6, 0xF2DA, 0x79E7, 0xE4EB, 0x79E9, 0xF2F1, 0x79FB, 0xECB9, 0x7A00, 0xFDFC, + 0x7A05, 0xE1AA, 0x7A08, 0xCAD9, 0x7A0B, 0xEFEF, 0x7A0D, 0xF5AA, 0x7A14, 0xECF9, 0x7A17, 0xF8AD, 0x7A19, 0xF2C2, 0x7A1A, 0xF6C3, + 0x7A1C, 0xD7D2, 0x7A1F, 0xF9A2, 0x7A20, 0xF0D6, 0x7A2E, 0xF0FA, 0x7A31, 0xF6E0, 0x7A36, 0xE9F3, 0x7A37, 0xF2C3, 0x7A3B, 0xD4AB, + 0x7A3C, 0xCAB3, 0x7A3D, 0xCDA6, 0x7A3F, 0xCDC3, 0x7A40, 0xCDDA, 0x7A46, 0xD9CF, 0x7A49, 0xF6C4, 0x7A4D, 0xEEDD, 0x7A4E, 0xE7C4, + 0x7A57, 0xE2B4, 0x7A61, 0xDFE2, 0x7A62, 0xE7DB, 0x7A69, 0xE8B1, 0x7A6B, 0xFCAE, 0x7A70, 0xE5CD, 0x7A74, 0xFAEB, 0x7A76, 0xCFBC, + 0x7A79, 0xCFE2, 0x7A7A, 0xCDF6, 0x7A7D, 0xEFF0, 0x7A7F, 0xF4BE, 0x7A81, 0xD4CD, 0x7A84, 0xF3B8, 0x7A88, 0xE9A1, 0x7A92, 0xF2F2, + 0x7A93, 0xF3EB, 0x7A95, 0xF0D7, 0x7A98, 0xCFD7, 0x7A9F, 0xCFDF, 0x7AA9, 0xE8C0, 0x7AAA, 0xE8C1, 0x7AAE, 0xCFE3, 0x7AAF, 0xE9A2, + 0x7ABA, 0xD0AA, 0x7AC4, 0xF3C1, 0x7AC5, 0xD0AB, 0x7AC7, 0xD4E4, 0x7ACA, 0xEFBC, 0x7ACB, 0xD8A1, 0x7AD7, 0xD9DF, 0x7AD9, 0xF3D7, + 0x7ADD, 0xDCBD, 0x7ADF, 0xCCE5, 0x7AE0, 0xEDF1, 0x7AE3, 0xF1E2, 0x7AE5, 0xD4DB, 0x7AEA, 0xE2B5, 0x7AED, 0xCAE6, 0x7AEF, 0xD3AE, + 0x7AF6, 0xCCE6, 0x7AF9, 0xF1D3, 0x7AFA, 0xF5E7, 0x7AFF, 0xCADA, 0x7B0F, 0xFBEE, 0x7B11, 0xE1C5, 0x7B19, 0xDFE9, 0x7B1B, 0xEEDE, + 0x7B1E, 0xF7C2, 0x7B20, 0xD8A2, 0x7B26, 0xDDAC, 0x7B2C, 0xF0AF, 0x7B2D, 0xD6BD, 0x7B39, 0xE1AB, 0x7B46, 0xF9B6, 0x7B49, 0xD4F5, + 0x7B4B, 0xD0C9, 0x7B4C, 0xEFA7, 0x7B4D, 0xE2EC, 0x7B4F, 0xDBEA, 0x7B50, 0xCECC, 0x7B51, 0xF5E8, 0x7B52, 0xF7D5, 0x7B54, 0xD3CD, + 0x7B56, 0xF3FE, 0x7B60, 0xD0B5, 0x7B6C, 0xE0FE, 0x7B6E, 0xDFFB, 0x7B75, 0xE6DD, 0x7B7D, 0xE8A4, 0x7B87, 0xCBCD, 0x7B8B, 0xEFA8, + 0x7B8F, 0xEEB4, 0x7B94, 0xDAD8, 0x7B95, 0xD1B9, 0x7B97, 0xDFA9, 0x7B9A, 0xF3B0, 0x7B9D, 0xCCC4, 0x7BA1, 0xCEB7, 0x7BAD, 0xEFA9, + 0x7BB1, 0xDFD5, 0x7BB4, 0xEDD7, 0x7BB8, 0xEEC6, 0x7BC0, 0xEFBD, 0x7BC1, 0xFCD6, 0x7BC4, 0xDBF4, 0x7BC6, 0xEFAA, 0x7BC7, 0xF8B9, + 0x7BC9, 0xF5E9, 0x7BD2, 0xE3D9, 0x7BE0, 0xE1C6, 0x7BE4, 0xD4BF, 0x7BE9, 0xDEE8, 0x7C07, 0xF0EA, 0x7C12, 0xF3C2, 0x7C1E, 0xD3AF, + 0x7C21, 0xCADB, 0x7C27, 0xFCD7, 0x7C2A, 0xEDD8, 0x7C2B, 0xE1C7, 0x7C3D, 0xF4D8, 0x7C3E, 0xD6B3, 0x7C3F, 0xDDAD, 0x7C43, 0xD5BE, + 0x7C4C, 0xF1C3, 0x7C4D, 0xEEDF, 0x7C60, 0xD6EB, 0x7C64, 0xF4D9, 0x7C6C, 0xD7E6, 0x7C73, 0xDAB7, 0x7C83, 0xDDFB, 0x7C89, 0xDDCF, + 0x7C92, 0xD8A3, 0x7C95, 0xDAD9, 0x7C97, 0xF0D8, 0x7C98, 0xEFC4, 0x7C9F, 0xE1D8, 0x7CA5, 0xF1D4, 0x7CA7, 0xEDF2, 0x7CAE, 0xD5DB, + 0x7CB1, 0xD5DC, 0x7CB2, 0xF3C4, 0x7CB3, 0xCBD7, 0x7CB9, 0xE2B6, 0x7CBE, 0xEFF1, 0x7CCA, 0xFBD5, 0x7CD6, 0xD3D8, 0x7CDE, 0xDDD0, + 0x7CDF, 0xF0D9, 0x7CE0, 0xCBB3, 0x7CE7, 0xD5DD, 0x7CFB, 0xCDA7, 0x7CFE, 0xD0AC, 0x7D00, 0xD1BA, 0x7D02, 0xF1C4, 0x7D04, 0xE5B3, + 0x7D05, 0xFBF5, 0x7D06, 0xE9E1, 0x7D07, 0xFDE0, 0x7D08, 0xFCBC, 0x7D0A, 0xDAA2, 0x7D0B, 0xDAA3, 0x7D0D, 0xD2A1, 0x7D10, 0xD2EF, + 0x7D14, 0xE2ED, 0x7D17, 0xDEE9, 0x7D18, 0xCEDC, 0x7D19, 0xF2B5, 0x7D1A, 0xD0E4, 0x7D1B, 0xDDD1, 0x7D20, 0xE1C8, 0x7D21, 0xDBB7, + 0x7D22, 0xDFE3, 0x7D2B, 0xEDB9, 0x7D2C, 0xF1C5, 0x7D2E, 0xF3CF, 0x7D2F, 0xD7AB, 0x7D30, 0xE1AC, 0x7D33, 0xE3EB, 0x7D35, 0xEEC7, + 0x7D39, 0xE1C9, 0x7D3A, 0xCAFA, 0x7D42, 0xF0FB, 0x7D43, 0xFAE1, 0x7D44, 0xF0DA, 0x7D45, 0xCCE7, 0x7D46, 0xDAF4, 0x7D50, 0xCCBF, + 0x7D5E, 0xCEED, 0x7D61, 0xD5A9, 0x7D62, 0xFAE2, 0x7D66, 0xD0E5, 0x7D68, 0xEBD6, 0x7D6A, 0xECDF, 0x7D6E, 0xDFFC, 0x7D71, 0xF7D6, + 0x7D72, 0xDEEA, 0x7D73, 0xCBB4, 0x7D76, 0xEFBE, 0x7D79, 0xCCB5, 0x7D7F, 0xCFBD, 0x7D8E, 0xEFF2, 0x7D8F, 0xE2B7, 0x7D93, 0xCCE8, + 0x7D9C, 0xF0FC, 0x7DA0, 0xD6E0, 0x7DA2, 0xF1C6, 0x7DAC, 0xE2B8, 0x7DAD, 0xEBAB, 0x7DB1, 0xCBB5, 0x7DB2, 0xD8D1, 0x7DB4, 0xF4CE, + 0x7DB5, 0xF3F7, 0x7DB8, 0xD7C6, 0x7DBA, 0xD1BB, 0x7DBB, 0xF7AA, 0x7DBD, 0xEDCA, 0x7DBE, 0xD7D3, 0x7DBF, 0xD8FA, 0x7DC7, 0xF6C5, + 0x7DCA, 0xD1CC, 0x7DCB, 0xDDFC, 0x7DD6, 0xDFFD, 0x7DD8, 0xF9E5, 0x7DDA, 0xE0CA, 0x7DDD, 0xF2FD, 0x7DDE, 0xD3B0, 0x7DE0, 0xF4F3, + 0x7DE1, 0xDAC9, 0x7DE3, 0xE6DE, 0x7DE8, 0xF8BA, 0x7DE9, 0xE8D0, 0x7DEC, 0xD8FB, 0x7DEF, 0xEAD5, 0x7DF4, 0xD6A3, 0x7DFB, 0xF6C6, + 0x7E09, 0xF2DB, 0x7E0A, 0xE4FC, 0x7E15, 0xE8B2, 0x7E1B, 0xDADA, 0x7E1D, 0xF2DC, 0x7E1E, 0xFBD6, 0x7E1F, 0xE9B2, 0x7E21, 0xEEAD, + 0x7E23, 0xFAE3, 0x7E2B, 0xDCEE, 0x7E2E, 0xF5EA, 0x7E2F, 0xE6E0, 0x7E31, 0xF0FD, 0x7E37, 0xD7AC, 0x7E3D, 0xF5C5, 0x7E3E, 0xEEE0, + 0x7E41, 0xDBE5, 0x7E43, 0xDDDE, 0x7E46, 0xD9F0, 0x7E47, 0xE9A3, 0x7E52, 0xF1F9, 0x7E54, 0xF2C4, 0x7E55, 0xE0CB, 0x7E5E, 0xE9A4, + 0x7E61, 0xE2B9, 0x7E69, 0xE3B1, 0x7E6A, 0xFCEB, 0x7E6B, 0xCDA8, 0x7E6D, 0xCCB6, 0x7E70, 0xF0DB, 0x7E79, 0xE6BA, 0x7E7C, 0xCDA9, + 0x7E82, 0xF3C3, 0x7E8C, 0xE1D9, 0x7E8F, 0xEFAB, 0x7E93, 0xE7C5, 0x7E96, 0xE0E9, 0x7E98, 0xF3C5, 0x7E9B, 0xD4C0, 0x7E9C, 0xD5BF, + 0x7F36, 0xDDAE, 0x7F38, 0xF9FC, 0x7F3A, 0xCCC0, 0x7F4C, 0xE5A2, 0x7F50, 0xCEB8, 0x7F54, 0xD8D2, 0x7F55, 0xF9D6, 0x7F6A, 0xF1AA, + 0x7F6B, 0xCED1, 0x7F6E, 0xF6C7, 0x7F70, 0xDBEB, 0x7F72, 0xDFFE, 0x7F75, 0xD8E1, 0x7F77, 0xF7F3, 0x7F79, 0xD7E7, 0x7F85, 0xD4FE, + 0x7F88, 0xD1BC, 0x7F8A, 0xE5CF, 0x7F8C, 0xCBB6, 0x7F8E, 0xDAB8, 0x7F94, 0xCDC4, 0x7F9A, 0xD6BE, 0x7F9E, 0xE2BA, 0x7FA4, 0xCFD8, + 0x7FA8, 0xE0CC, 0x7FA9, 0xEBF9, 0x7FB2, 0xFDFD, 0x7FB8, 0xD7E8, 0x7FB9, 0xCBD8, 0x7FBD, 0xE9E2, 0x7FC1, 0xE8BA, 0x7FC5, 0xE3C7, + 0x7FCA, 0xECCD, 0x7FCC, 0xECCE, 0x7FCE, 0xD6BF, 0x7FD2, 0xE3A7, 0x7FD4, 0xDFD6, 0x7FD5, 0xFDE8, 0x7FDF, 0xEEE1, 0x7FE0, 0xF6A8, + 0x7FE1, 0xDDFD, 0x7FE9, 0xF8BB, 0x7FEB, 0xE8D1, 0x7FF0, 0xF9D7, 0x7FF9, 0xCEEE, 0x7FFC, 0xECCF, 0x8000, 0xE9A5, 0x8001, 0xD6D5, + 0x8003, 0xCDC5, 0x8005, 0xEDBA, 0x8006, 0xD1BD, 0x8009, 0xCFBE, 0x800C, 0xECBB, 0x8010, 0xD2B1, 0x8015, 0xCCE9, 0x8017, 0xD9C4, + 0x8018, 0xE9FC, 0x802D, 0xD1BE, 0x8033, 0xECBC, 0x8036, 0xE5AD, 0x803D, 0xF7B0, 0x803F, 0xCCEA, 0x8043, 0xD3C4, 0x8046, 0xD6C0, + 0x804A, 0xD6FD, 0x8056, 0xE1A1, 0x8058, 0xDEBD, 0x805A, 0xF6A9, 0x805E, 0xDAA4, 0x806F, 0xD6A4, 0x8070, 0xF5C6, 0x8072, 0xE1A2, + 0x8073, 0xE9C6, 0x8077, 0xF2C5, 0x807D, 0xF4E9, 0x807E, 0xD6EC, 0x807F, 0xEBD3, 0x8084, 0xECBD, 0x8085, 0xE2DC, 0x8086, 0xDEEB, + 0x8087, 0xF0DC, 0x8089, 0xEBBF, 0x808B, 0xD7CE, 0x808C, 0xD1BF, 0x8096, 0xF5AB, 0x809B, 0xF9FD, 0x809D, 0xCADC, 0x80A1, 0xCDC6, + 0x80A2, 0xF2B6, 0x80A5, 0xDDFE, 0x80A9, 0xCCB7, 0x80AA, 0xDBB8, 0x80AF, 0xD0E9, 0x80B1, 0xCEDD, 0x80B2, 0xEBC0, 0x80B4, 0xFDA2, + 0x80BA, 0xF8CB, 0x80C3, 0xEAD6, 0x80C4, 0xF1B0, 0x80CC, 0xDBCE, 0x80CE, 0xF7C3, 0x80DA, 0xDBCF, 0x80DB, 0xCBA4, 0x80DE, 0xF8E0, + 0x80E1, 0xFBD7, 0x80E4, 0xEBCA, 0x80E5, 0xE0A1, 0x80F1, 0xCECD, 0x80F4, 0xD4DC, 0x80F8, 0xFDD8, 0x80FD, 0xD2F6, 0x8102, 0xF2B7, + 0x8105, 0xFAF6, 0x8106, 0xF6AA, 0x8107, 0xFAF7, 0x8108, 0xD8E6, 0x810A, 0xF4B1, 0x8118, 0xE8D2, 0x811A, 0xCAC5, 0x811B, 0xCCEB, + 0x8123, 0xE2EE, 0x8129, 0xE2BB, 0x812B, 0xF7AD, 0x812F, 0xF8E1, 0x8139, 0xF3EC, 0x813E, 0xDEA1, 0x814B, 0xE4FD, 0x814E, 0xE3EC, + 0x8150, 0xDDAF, 0x8151, 0xDDB0, 0x8154, 0xCBB7, 0x8155, 0xE8D3, 0x8165, 0xE1A3, 0x8166, 0xD2E0, 0x816B, 0xF0FE, 0x8170, 0xE9A6, + 0x8171, 0xCBF2, 0x8178, 0xEDF3, 0x8179, 0xDCD9, 0x817A, 0xE0CD, 0x817F, 0xF7DA, 0x8180, 0xDBB9, 0x8188, 0xCCAE, 0x818A, 0xDADB, + 0x818F, 0xCDC7, 0x819A, 0xDDB1, 0x819C, 0xD8AF, 0x819D, 0xE3A3, 0x81A0, 0xCEEF, 0x81A3, 0xF2F3, 0x81A8, 0xF8B3, 0x81B3, 0xE0CE, + 0x81B5, 0xF5FD, 0x81BA, 0xEBEC, 0x81BD, 0xD3C5, 0x81BE, 0xFCEC, 0x81BF, 0xD2DB, 0x81C0, 0xD4EB, 0x81C2, 0xDEA2, 0x81C6, 0xE5E6, + 0x81CD, 0xF0B0, 0x81D8, 0xD5C4, 0x81DF, 0xEDF4, 0x81E3, 0xE3ED, 0x81E5, 0xE8C2, 0x81E7, 0xEDF5, 0x81E8, 0xD7FC, 0x81EA, 0xEDBB, + 0x81ED, 0xF6AB, 0x81F3, 0xF2B8, 0x81F4, 0xF6C8, 0x81FA, 0xD3E6, 0x81FB, 0xF2DD, 0x81FC, 0xCFBF, 0x81FE, 0xEBAC, 0x8205, 0xCFC0, + 0x8207, 0xE6A8, 0x8208, 0xFDE9, 0x820A, 0xCFC1, 0x820C, 0xE0DF, 0x820D, 0xDEEC, 0x8212, 0xE0A2, 0x821B, 0xF4BF, 0x821C, 0xE2EF, + 0x821E, 0xD9F1, 0x821F, 0xF1C7, 0x8221, 0xCBB8, 0x822A, 0xF9FE, 0x822B, 0xDBBA, 0x822C, 0xDAF5, 0x8235, 0xF6EC, 0x8236, 0xDADC, + 0x8237, 0xFAE4, 0x8239, 0xE0CF, 0x8240, 0xDDB2, 0x8245, 0xE6A9, 0x8247, 0xEFF3, 0x8259, 0xF3ED, 0x8264, 0xEBFA, 0x8266, 0xF9E6, + 0x826E, 0xCADD, 0x826F, 0xD5DE, 0x8271, 0xCADE, 0x8272, 0xDFE4, 0x8276, 0xE6FD, 0x8278, 0xF5AC, 0x827E, 0xE4F5, 0x828B, 0xE9E3, + 0x828D, 0xEDCB, 0x828E, 0xCFE4, 0x8292, 0xD8D3, 0x8299, 0xDDB3, 0x829A, 0xD4EC, 0x829D, 0xF2B9, 0x829F, 0xDFB7, 0x82A5, 0xCBCE, + 0x82A6, 0xFBD8, 0x82A9, 0xD0D9, 0x82AC, 0xDDD2, 0x82AD, 0xF7F4, 0x82AE, 0xE7DC, 0x82AF, 0xE4A5, 0x82B1, 0xFCA3, 0x82B3, 0xDBBB, + 0x82B7, 0xF2BA, 0x82B8, 0xE9FD, 0x82B9, 0xD0CA, 0x82BB, 0xF5D6, 0x82BC, 0xD9C5, 0x82BD, 0xE4B4, 0x82BF, 0xEDA7, 0x82D1, 0xEABD, + 0x82D2, 0xE6FE, 0x82D4, 0xF7C4, 0x82D5, 0xF5AD, 0x82D7, 0xD9E0, 0x82DB, 0xCAB4, 0x82DE, 0xF8E2, 0x82DF, 0xCFC2, 0x82E1, 0xECBE, + 0x82E5, 0xE5B4, 0x82E6, 0xCDC8, 0x82E7, 0xEEC8, 0x82F1, 0xE7C8, 0x82FD, 0xCDC9, 0x82FE, 0xF9B7, 0x8301, 0xF1E8, 0x8302, 0xD9F2, + 0x8303, 0xDBF5, 0x8304, 0xCAB5, 0x8305, 0xD9C6, 0x8309, 0xD8C9, 0x8317, 0xD9AB, 0x8328, 0xEDBC, 0x832B, 0xD8D4, 0x832F, 0xDCDA, + 0x8331, 0xE2BC, 0x8334, 0xFCED, 0x8335, 0xECE0, 0x8336, 0xD2FE, 0x8338, 0xE9C7, 0x8339, 0xE6AA, 0x8340, 0xE2F0, 0x8347, 0xFABB, + 0x8349, 0xF5AE, 0x834A, 0xFBAA, 0x834F, 0xECFB, 0x8351, 0xECBF, 0x8352, 0xFCD8, 0x8373, 0xD4E5, 0x8377, 0xF9C3, 0x837B, 0xEEE2, + 0x8389, 0xD7E9, 0x838A, 0xEDF6, 0x838E, 0xDEED, 0x8396, 0xCCEC, 0x8398, 0xE3EE, 0x839E, 0xE8D4, 0x83A2, 0xFAF8, 0x83A9, 0xDDB4, + 0x83AA, 0xE4B5, 0x83AB, 0xD8B0, 0x83BD, 0xD8D5, 0x83C1, 0xF4EA, 0x83C5, 0xCEB9, 0x83C9, 0xD6E1, 0x83CA, 0xCFD2, 0x83CC, 0xD0B6, + 0x83D3, 0xCEA2, 0x83D6, 0xF3EE, 0x83DC, 0xF3F8, 0x83E9, 0xDCCC, 0x83EB, 0xD0CB, 0x83EF, 0xFCA4, 0x83F0, 0xCDCA, 0x83F1, 0xD7D4, + 0x83F2, 0xDEA3, 0x83F4, 0xE4E0, 0x83F9, 0xEEC9, 0x83FD, 0xE2DD, 0x8403, 0xF5FE, 0x8404, 0xD4AC, 0x840A, 0xD5D1, 0x840C, 0xD8F0, + 0x840D, 0xF8C3, 0x840E, 0xEAD7, 0x8429, 0xF5D7, 0x842C, 0xD8BF, 0x8431, 0xFDC0, 0x8438, 0xEBAD, 0x843D, 0xD5AA, 0x8449, 0xE7A8, + 0x8457, 0xEECA, 0x845B, 0xCAE7, 0x8461, 0xF8E3, 0x8463, 0xD4DD, 0x8466, 0xEAD8, 0x846B, 0xFBD9, 0x846C, 0xEDF7, 0x846F, 0xE5B5, + 0x8475, 0xD0AD, 0x847A, 0xF1F1, 0x8490, 0xE2BD, 0x8494, 0xE3C8, 0x8499, 0xD9D5, 0x849C, 0xDFAA, 0x84A1, 0xDBBC, 0x84B2, 0xF8E4, + 0x84B8, 0xF1FA, 0x84BB, 0xE5B6, 0x84BC, 0xF3EF, 0x84BF, 0xFBDA, 0x84C0, 0xE1E0, 0x84C2, 0xD9AC, 0x84C4, 0xF5EB, 0x84C6, 0xE0B6, + 0x84C9, 0xE9C8, 0x84CB, 0xCBCF, 0x84CD, 0xE3C9, 0x84D1, 0xDEEE, 0x84DA, 0xE2BE, 0x84EC, 0xDCEF, 0x84EE, 0xD6A5, 0x84F4, 0xE2F1, + 0x84FC, 0xD6FE, 0x8511, 0xD9A1, 0x8513, 0xD8C0, 0x8514, 0xDCDB, 0x8517, 0xEDBD, 0x8518, 0xDFB8, 0x851A, 0xEAA5, 0x851E, 0xD7AD, + 0x8521, 0xF3F9, 0x8523, 0xEDF8, 0x8525, 0xF5C7, 0x852C, 0xE1CA, 0x852D, 0xEBE3, 0x852F, 0xF2DE, 0x853D, 0xF8CC, 0x853F, 0xEAD9, + 0x8541, 0xD3C6, 0x8543, 0xDBE6, 0x8549, 0xF5AF, 0x854E, 0xCEF0, 0x8553, 0xE9FE, 0x8559, 0xFBB6, 0x8563, 0xE2F2, 0x8568, 0xCFF2, + 0x8569, 0xF7B9, 0x856A, 0xD9F3, 0x856D, 0xE1CB, 0x8584, 0xDADD, 0x8587, 0xDAB9, 0x858F, 0xEBFB, 0x8591, 0xCBB9, 0x8594, 0xEDF9, + 0x859B, 0xE0E0, 0x85A6, 0xF4C0, 0x85A8, 0xFDBC, 0x85A9, 0xDFB1, 0x85AA, 0xE3EF, 0x85AF, 0xE0A3, 0x85B0, 0xFDB9, 0x85BA, 0xF0B1, + 0x85C1, 0xCDCB, 0x85C9, 0xEDBE, 0x85CD, 0xD5C0, 0x85CE, 0xE3F0, 0x85CF, 0xEDFA, 0x85D5, 0xE9E4, 0x85DC, 0xD5ED, 0x85DD, 0xE7DD, + 0x85E4, 0xD4F6, 0x85E5, 0xE5B7, 0x85E9, 0xDBE7, 0x85EA, 0xE2BF, 0x85F7, 0xEECB, 0x85FA, 0xD7F4, 0x85FB, 0xF0DD, 0x85FF, 0xCEAB, + 0x8602, 0xE7DE, 0x8606, 0xD6D6, 0x8607, 0xE1CC, 0x860A, 0xE8B3, 0x8616, 0xE5EE, 0x8617, 0xDCA2, 0x861A, 0xE0D0, 0x862D, 0xD5B5, + 0x863F, 0xD5A1, 0x864E, 0xFBDB, 0x8650, 0xF9CB, 0x8654, 0xCBF3, 0x8655, 0xF4A5, 0x865B, 0xFAC8, 0x865C, 0xD6D7, 0x865E, 0xE9E5, + 0x865F, 0xFBDC, 0x8667, 0xFDD0, 0x8679, 0xFBF6, 0x868A, 0xDAA5, 0x868C, 0xDBBD, 0x8693, 0xECE2, 0x86A3, 0xCDF7, 0x86A4, 0xF0DE, + 0x86A9, 0xF6C9, 0x86C7, 0xDEEF, 0x86CB, 0xD3B1, 0x86D4, 0xFCEE, 0x86D9, 0xE8C3, 0x86DB, 0xF1C8, 0x86DF, 0xCEF1, 0x86E4, 0xF9ED, + 0x86ED, 0xF2F4, 0x86FE, 0xE4B6, 0x8700, 0xF5B9, 0x8702, 0xDCF0, 0x8703, 0xE3F1, 0x8708, 0xE8A5, 0x8718, 0xF2BB, 0x871A, 0xDEA4, + 0x871C, 0xDACC, 0x874E, 0xCAE9, 0x8755, 0xE3DA, 0x8757, 0xFCD9, 0x875F, 0xEADA, 0x8766, 0xF9C4, 0x8768, 0xE3A4, 0x8774, 0xFBDD, + 0x8776, 0xEFCA, 0x8778, 0xE8C4, 0x8782, 0xD5CC, 0x878D, 0xEBD7, 0x879F, 0xD9AD, 0x87A2, 0xFBAB, 0x87B3, 0xD3D9, 0x87BA, 0xD5A2, + 0x87C4, 0xF6DE, 0x87E0, 0xDAF6, 0x87EC, 0xE0D1, 0x87EF, 0xE9A8, 0x87F2, 0xF5F9, 0x87F9, 0xFAAF, 0x87FB, 0xEBFC, 0x87FE, 0xE0EA, + 0x8805, 0xE3B2, 0x881F, 0xD5C5, 0x8822, 0xF1E3, 0x8823, 0xD5EE, 0x8831, 0xCDCC, 0x8836, 0xEDD9, 0x883B, 0xD8C1, 0x8840, 0xFAEC, + 0x8846, 0xF1EB, 0x884C, 0xFABC, 0x884D, 0xE6E2, 0x8852, 0xFAE5, 0x8853, 0xE2FA, 0x8857, 0xCAB6, 0x8859, 0xE4B7, 0x885B, 0xEADB, + 0x885D, 0xF5FA, 0x8861, 0xFBAC, 0x8862, 0xCFC3, 0x8863, 0xEBFD, 0x8868, 0xF8FA, 0x886B, 0xDFB9, 0x8870, 0xE1F1, 0x8872, 0xD2A4, + 0x8877, 0xF5FB, 0x887E, 0xD0DA, 0x887F, 0xD0DB, 0x8881, 0xEABE, 0x8882, 0xD9B1, 0x8888, 0xCAB7, 0x888B, 0xD3E7, 0x888D, 0xF8E5, + 0x8892, 0xD3B2, 0x8896, 0xE2C0, 0x8897, 0xF2DF, 0x889E, 0xCDE5, 0x88AB, 0xF9AC, 0x88B4, 0xCDCD, 0x88C1, 0xEEAE, 0x88C2, 0xD6AE, + 0x88CF, 0xD7EA, 0x88D4, 0xE7E0, 0x88D5, 0xEBAE, 0x88D9, 0xCFD9, 0x88DC, 0xDCCD, 0x88DD, 0xEDFB, 0x88DF, 0xDEF0, 0x88E1, 0xD7EB, + 0x88E8, 0xDEA5, 0x88F3, 0xDFD7, 0x88F4, 0xDBD0, 0x88F5, 0xDBD1, 0x88F8, 0xD5A3, 0x88FD, 0xF0B2, 0x8907, 0xDCDC, 0x8910, 0xCAE8, + 0x8912, 0xF8E6, 0x8913, 0xDCCE, 0x8918, 0xEADC, 0x8919, 0xDBD2, 0x8925, 0xE9B3, 0x892A, 0xF7DB, 0x8936, 0xE3A8, 0x8938, 0xD7AE, + 0x893B, 0xE0E1, 0x8941, 0xCBBA, 0x8944, 0xE5D1, 0x895F, 0xD0DC, 0x8964, 0xD5C1, 0x896A, 0xD8CA, 0x8972, 0xE3A9, 0x897F, 0xE0A4, + 0x8981, 0xE9A9, 0x8983, 0xD3C7, 0x8986, 0xDCDD, 0x8987, 0xF8AE, 0x898B, 0xCCB8, 0x898F, 0xD0AE, 0x8993, 0xD8F2, 0x8996, 0xE3CA, + 0x89A1, 0xCCAF, 0x89A9, 0xD4AD, 0x89AA, 0xF6D1, 0x89B2, 0xD0CC, 0x89BA, 0xCAC6, 0x89BD, 0xD5C2, 0x89C0, 0xCEBA, 0x89D2, 0xCAC7, + 0x89E3, 0xFAB0, 0x89F4, 0xDFD8, 0x89F8, 0xF5BA, 0x8A00, 0xE5EB, 0x8A02, 0xEFF4, 0x8A03, 0xDDB5, 0x8A08, 0xCDAA, 0x8A0A, 0xE3F2, + 0x8A0C, 0xFBF7, 0x8A0E, 0xF7D0, 0x8A13, 0xFDBA, 0x8A16, 0xFDE1, 0x8A17, 0xF6FE, 0x8A18, 0xD1C0, 0x8A1B, 0xE8C5, 0x8A1D, 0xE4B8, + 0x8A1F, 0xE1E8, 0x8A23, 0xCCC1, 0x8A25, 0xD2ED, 0x8A2A, 0xDBBE, 0x8A2D, 0xE0E2, 0x8A31, 0xFAC9, 0x8A34, 0xE1CD, 0x8A36, 0xCAB8, + 0x8A3A, 0xF2E0, 0x8A3B, 0xF1C9, 0x8A50, 0xDEF1, 0x8A54, 0xF0DF, 0x8A55, 0xF8C4, 0x8A5B, 0xEECC, 0x8A5E, 0xDEF2, 0x8A60, 0xE7C9, + 0x8A62, 0xE2F3, 0x8A63, 0xE7E1, 0x8A66, 0xE3CB, 0x8A69, 0xE3CC, 0x8A6D, 0xCFF8, 0x8A6E, 0xEFAC, 0x8A70, 0xFDFE, 0x8A71, 0xFCA5, + 0x8A72, 0xFAB1, 0x8A73, 0xDFD9, 0x8A75, 0xE0D2, 0x8A79, 0xF4DA, 0x8A85, 0xF1CA, 0x8A87, 0xCEA3, 0x8A8C, 0xF2BC, 0x8A8D, 0xECE3, + 0x8A93, 0xE0A5, 0x8A95, 0xF7AB, 0x8A98, 0xEBAF, 0x8A9E, 0xE5DE, 0x8AA0, 0xE1A4, 0x8AA1, 0xCDAB, 0x8AA3, 0xD9F4, 0x8AA4, 0xE8A6, + 0x8AA5, 0xCDCE, 0x8AA6, 0xE1E9, 0x8AA8, 0xFCEF, 0x8AAA, 0xE0E3, 0x8AB0, 0xE2C1, 0x8AB2, 0xCEA4, 0x8AB9, 0xDEA6, 0x8ABC, 0xEBFE, + 0x8ABE, 0xEBDD, 0x8ABF, 0xF0E0, 0x8AC2, 0xF4DB, 0x8AC4, 0xE2F4, 0x8AC7, 0xD3C8, 0x8ACB, 0xF4EB, 0x8ACD, 0xEEB5, 0x8ACF, 0xF5D8, + 0x8AD2, 0xD5DF, 0x8AD6, 0xD6E5, 0x8ADB, 0xEBB0, 0x8ADC, 0xF4E3, 0x8AE1, 0xE3CD, 0x8AE6, 0xF4F4, 0x8AE7, 0xFAB2, 0x8AEA, 0xEFF5, + 0x8AEB, 0xCADF, 0x8AED, 0xEBB1, 0x8AEE, 0xEDBF, 0x8AF1, 0xFDC9, 0x8AF6, 0xE4A6, 0x8AF7, 0xF9A4, 0x8AF8, 0xF0B3, 0x8AFA, 0xE5EC, + 0x8AFE, 0xD1E7, 0x8B00, 0xD9C7, 0x8B01, 0xE4D7, 0x8B02, 0xEADD, 0x8B04, 0xD4F7, 0x8B0E, 0xDABA, 0x8B10, 0xDACD, 0x8B14, 0xF9CC, + 0x8B16, 0xE1DA, 0x8B17, 0xDBBF, 0x8B19, 0xCCC5, 0x8B1A, 0xECD0, 0x8B1B, 0xCBBB, 0x8B1D, 0xDEF3, 0x8B20, 0xE9AA, 0x8B28, 0xD9C8, + 0x8B2B, 0xEEE3, 0x8B2C, 0xD7BD, 0x8B33, 0xCFC4, 0x8B39, 0xD0CD, 0x8B41, 0xFCA6, 0x8B49, 0xF1FB, 0x8B4E, 0xFDD2, 0x8B4F, 0xD1C1, + 0x8B58, 0xE3DB, 0x8B5A, 0xD3C9, 0x8B5C, 0xDCCF, 0x8B66, 0xCCED, 0x8B6C, 0xDEA7, 0x8B6F, 0xE6BB, 0x8B70, 0xECA1, 0x8B74, 0xCCB9, + 0x8B77, 0xFBDE, 0x8B7D, 0xE7E2, 0x8B80, 0xD4C1, 0x8B8A, 0xDCA8, 0x8B90, 0xE2C2, 0x8B92, 0xF3D8, 0x8B93, 0xE5D3, 0x8B96, 0xF3D9, + 0x8B9A, 0xF3C6, 0x8C37, 0xCDDB, 0x8C3F, 0xCDAC, 0x8C41, 0xFCC3, 0x8C46, 0xD4E7, 0x8C48, 0xD1C2, 0x8C4A, 0xF9A5, 0x8C4C, 0xE8D5, + 0x8C55, 0xE3CE, 0x8C5A, 0xD4CA, 0x8C61, 0xDFDA, 0x8C6A, 0xFBDF, 0x8C6B, 0xE7E3, 0x8C79, 0xF8FB, 0x8C7A, 0xE3CF, 0x8C82, 0xF5B0, + 0x8C8A, 0xD8E7, 0x8C8C, 0xD9C9, 0x8C9D, 0xF8AF, 0x8C9E, 0xEFF6, 0x8CA0, 0xDDB6, 0x8CA1, 0xEEAF, 0x8CA2, 0xCDF8, 0x8CA7, 0xDEB8, + 0x8CA8, 0xFCA7, 0x8CA9, 0xF7FC, 0x8CAA, 0xF7B1, 0x8CAB, 0xCEBB, 0x8CAC, 0xF4A1, 0x8CAF, 0xEECD, 0x8CB0, 0xE1AE, 0x8CB3, 0xECC3, + 0x8CB4, 0xCFFE, 0x8CB6, 0xF8BF, 0x8CB7, 0xD8E2, 0x8CB8, 0xD3E8, 0x8CBB, 0xDEA8, 0x8CBC, 0xF4E4, 0x8CBD, 0xECC2, 0x8CBF, 0xD9F5, + 0x8CC0, 0xF9C5, 0x8CC1, 0xDDD3, 0x8CC2, 0xD6F1, 0x8CC3, 0xECFC, 0x8CC4, 0xFCF0, 0x8CC7, 0xEDC0, 0x8CC8, 0xCAB9, 0x8CCA, 0xEEE4, + 0x8CD1, 0xF2E1, 0x8CD3, 0xDEB9, 0x8CDA, 0xD6F2, 0x8CDC, 0xDEF4, 0x8CDE, 0xDFDB, 0x8CE0, 0xDBD3, 0x8CE2, 0xFAE7, 0x8CE3, 0xD8E3, + 0x8CE4, 0xF4C1, 0x8CE6, 0xDDB7, 0x8CEA, 0xF2F5, 0x8CED, 0xD4AE, 0x8CF4, 0xD6F3, 0x8CFB, 0xDDB8, 0x8CFC, 0xCFC5, 0x8CFD, 0xDFDF, + 0x8D04, 0xF2BE, 0x8D05, 0xF6A1, 0x8D07, 0xEBCB, 0x8D08, 0xF1FC, 0x8D0A, 0xF3C7, 0x8D0D, 0xE0EB, 0x8D13, 0xEDFC, 0x8D16, 0xE1DB, + 0x8D64, 0xEEE5, 0x8D66, 0xDEF5, 0x8D6B, 0xFAD3, 0x8D70, 0xF1CB, 0x8D73, 0xD0AF, 0x8D74, 0xDDB9, 0x8D77, 0xD1C3, 0x8D85, 0xF5B1, + 0x8D8A, 0xEAC6, 0x8D99, 0xF0E1, 0x8DA3, 0xF6AC, 0x8DA8, 0xF5D9, 0x8DB3, 0xF0EB, 0x8DBA, 0xDDBA, 0x8DBE, 0xF2BF, 0x8DC6, 0xF7C5, + 0x8DCB, 0xDBA2, 0x8DCC, 0xF2F6, 0x8DCF, 0xCABA, 0x8DDB, 0xF7F5, 0x8DDD, 0xCBE5, 0x8DE1, 0xEEE6, 0x8DE3, 0xE0D3, 0x8DE8, 0xCEA5, + 0x8DEF, 0xD6D8, 0x8DF3, 0xD4AF, 0x8E0A, 0xE9C9, 0x8E0F, 0xD3CE, 0x8E10, 0xF4C2, 0x8E1E, 0xCBE6, 0x8E2A, 0xF1A1, 0x8E30, 0xEBB2, + 0x8E35, 0xF1A2, 0x8E42, 0xEBB3, 0x8E44, 0xF0B4, 0x8E47, 0xCBF4, 0x8E48, 0xD4B0, 0x8E49, 0xF3B2, 0x8E4A, 0xFBB7, 0x8E59, 0xF5EC, + 0x8E5F, 0xEEE7, 0x8E60, 0xF4B2, 0x8E74, 0xF5ED, 0x8E76, 0xCFF3, 0x8E81, 0xF0E2, 0x8E87, 0xEECE, 0x8E8A, 0xF1CC, 0x8E8D, 0xE5B8, + 0x8EAA, 0xD7F5, 0x8EAB, 0xE3F3, 0x8EAC, 0xCFE5, 0x8EC0, 0xCFC6, 0x8ECA, 0xF3B3, 0x8ECB, 0xE4D8, 0x8ECC, 0xCFF9, 0x8ECD, 0xCFDA, + 0x8ED2, 0xFACD, 0x8EDF, 0xE6E3, 0x8EEB, 0xF2E2, 0x8EF8, 0xF5EE, 0x8EFB, 0xCABB, 0x8EFE, 0xE3DC, 0x8F03, 0xCEF2, 0x8F05, 0xD6D9, + 0x8F09, 0xEEB0, 0x8F12, 0xF4E5, 0x8F13, 0xD8C2, 0x8F14, 0xDCD0, 0x8F15, 0xCCEE, 0x8F1B, 0xD5E0, 0x8F1C, 0xF6CA, 0x8F1D, 0xFDCA, + 0x8F1E, 0xD8D6, 0x8F1F, 0xF4CF, 0x8F26, 0xD6A6, 0x8F27, 0xDCBE, 0x8F29, 0xDBD4, 0x8F2A, 0xD7C7, 0x8F2F, 0xF2FE, 0x8F33, 0xF1CD, + 0x8F38, 0xE2C3, 0x8F39, 0xDCDE, 0x8F3B, 0xDCDF, 0x8F3E, 0xEFAD, 0x8F3F, 0xE6AB, 0x8F44, 0xF9DD, 0x8F45, 0xEABF, 0x8F49, 0xEFAE, + 0x8F4D, 0xF4D0, 0x8F4E, 0xCEF3, 0x8F5D, 0xE6AC, 0x8F5F, 0xCEDE, 0x8F62, 0xD5F9, 0x8F9B, 0xE3F4, 0x8F9C, 0xCDD0, 0x8FA3, 0xD5B8, + 0x8FA6, 0xF7FD, 0x8FA8, 0xDCA9, 0x8FAD, 0xDEF6, 0x8FAF, 0xDCAA, 0x8FB0, 0xF2E3, 0x8FB1, 0xE9B4, 0x8FB2, 0xD2DC, 0x8FC2, 0xE9E6, + 0x8FC5, 0xE3F6, 0x8FCE, 0xE7CA, 0x8FD1, 0xD0CE, 0x8FD4, 0xDAF7, 0x8FE6, 0xCABC, 0x8FEA, 0xEEE8, 0x8FEB, 0xDADE, 0x8FED, 0xF2F7, + 0x8FF0, 0xE2FB, 0x8FF2, 0xCCA6, 0x8FF7, 0xDABB, 0x8FF9, 0xEEE9, 0x8FFD, 0xF5DA, 0x9000, 0xF7DC, 0x9001, 0xE1EA, 0x9002, 0xCEC1, + 0x9003, 0xD4B1, 0x9005, 0xFDB1, 0x9006, 0xE6BD, 0x9008, 0xFBAD, 0x900B, 0xF8E7, 0x900D, 0xE1CE, 0x900F, 0xF7E2, 0x9010, 0xF5EF, + 0x9011, 0xCFC7, 0x9014, 0xD4B2, 0x9015, 0xCCEF, 0x9017, 0xD4E8, 0x9019, 0xEECF, 0x901A, 0xF7D7, 0x901D, 0xE0A6, 0x901E, 0xD6C1, + 0x901F, 0xE1DC, 0x9020, 0xF0E3, 0x9021, 0xF1E4, 0x9022, 0xDCF1, 0x9023, 0xD6A7, 0x902E, 0xF4F5, 0x9031, 0xF1CE, 0x9032, 0xF2E4, + 0x9035, 0xD0B0, 0x9038, 0xECEF, 0x903C, 0xF9BA, 0x903E, 0xEBB5, 0x9041, 0xD4ED, 0x9042, 0xE2C4, 0x9047, 0xE9E7, 0x904A, 0xEBB4, + 0x904B, 0xEAA1, 0x904D, 0xF8BC, 0x904E, 0xCEA6, 0x9050, 0xF9C6, 0x9051, 0xFCDA, 0x9053, 0xD4B3, 0x9054, 0xD3B9, 0x9055, 0xEADE, + 0x9059, 0xE9AB, 0x905C, 0xE1E1, 0x905D, 0xD3CF, 0x905E, 0xF4F6, 0x9060, 0xEAC0, 0x9061, 0xE1CF, 0x9063, 0xCCBA, 0x9069, 0xEEEA, + 0x906D, 0xF0E4, 0x906E, 0xF3B4, 0x906F, 0xD4EE, 0x9072, 0xF2C0, 0x9075, 0xF1E5, 0x9077, 0xF4C3, 0x9078, 0xE0D4, 0x907A, 0xEBB6, + 0x907C, 0xD7A1, 0x907D, 0xCBE8, 0x907F, 0xF9AD, 0x9080, 0xE9AD, 0x9081, 0xD8E4, 0x9082, 0xFAB3, 0x9083, 0xE2C5, 0x9084, 0xFCBD, + 0x9087, 0xECC4, 0x9088, 0xD8B1, 0x908A, 0xDCAB, 0x908F, 0xD5A4, 0x9091, 0xEBE9, 0x9095, 0xE8BB, 0x9099, 0xD8D7, 0x90A2, 0xFBAE, + 0x90A3, 0xD1E1, 0x90A6, 0xDBC0, 0x90A8, 0xF5BE, 0x90AA, 0xDEF7, 0x90AF, 0xCAFB, 0x90B0, 0xF7C6, 0x90B1, 0xCFC8, 0x90B5, 0xE1D0, + 0x90B8, 0xEED0, 0x90C1, 0xE9F4, 0x90CA, 0xCEF4, 0x90DE, 0xD5CD, 0x90E1, 0xCFDB, 0x90E8, 0xDDBB, 0x90ED, 0xCEAC, 0x90F5, 0xE9E8, + 0x90FD, 0xD4B4, 0x9102, 0xE4C7, 0x9112, 0xF5DB, 0x9115, 0xFAC1, 0x9119, 0xDEA9, 0x9127, 0xD4F8, 0x912D, 0xEFF7, 0x9132, 0xD3B3, + 0x9149, 0xEBB7, 0x914A, 0xEFF8, 0x914B, 0xF5DC, 0x914C, 0xEDCC, 0x914D, 0xDBD5, 0x914E, 0xF1CF, 0x9152, 0xF1D0, 0x9162, 0xF5B2, + 0x9169, 0xD9AE, 0x916A, 0xD5AC, 0x916C, 0xE2C6, 0x9175, 0xFDA3, 0x9177, 0xFBE5, 0x9178, 0xDFAB, 0x9187, 0xE2F5, 0x9189, 0xF6AD, + 0x918B, 0xF5B3, 0x918D, 0xF0B5, 0x9192, 0xE1A5, 0x919C, 0xF5DD, 0x91AB, 0xECA2, 0x91AC, 0xEDFD, 0x91AE, 0xF5B4, 0x91AF, 0xFBB8, + 0x91B1, 0xDBA3, 0x91B4, 0xD6CA, 0x91B5, 0xCBD9, 0x91C0, 0xE5D4, 0x91C7, 0xF3FA, 0x91C9, 0xEBB8, 0x91CB, 0xE0B7, 0x91CC, 0xD7EC, + 0x91CD, 0xF1EC, 0x91CE, 0xE5AF, 0x91CF, 0xD5E1, 0x91D0, 0xD7ED, 0x91D1, 0xD1D1, 0x91D7, 0xE1F2, 0x91D8, 0xEFF9, 0x91DC, 0xDDBC, + 0x91DD, 0xF6DC, 0x91E3, 0xF0E5, 0x91E7, 0xF4C4, 0x91EA, 0xE9E9, 0x91F5, 0xF3FB, 0x920D, 0xD4EF, 0x9210, 0xCCA2, 0x9211, 0xF7FE, + 0x9212, 0xDFBC, 0x9217, 0xEBCD, 0x921E, 0xD0B7, 0x9234, 0xD6C2, 0x923A, 0xE8AD, 0x923F, 0xEFAF, 0x9240, 0xCBA5, 0x9245, 0xCBE9, + 0x9249, 0xFAE8, 0x9257, 0xCCC6, 0x925B, 0xE6E7, 0x925E, 0xEAC7, 0x9262, 0xDBA4, 0x9264, 0xCFC9, 0x9265, 0xE2FC, 0x9266, 0xEFFA, + 0x9280, 0xEBDE, 0x9283, 0xF5C8, 0x9285, 0xD4DE, 0x9291, 0xE0D5, 0x9293, 0xEFB0, 0x9296, 0xE2C7, 0x9298, 0xD9AF, 0x929C, 0xF9E7, + 0x92B3, 0xE7E5, 0x92B6, 0xCFCA, 0x92B7, 0xE1D1, 0x92B9, 0xE2C8, 0x92CC, 0xEFFB, 0x92CF, 0xFAF9, 0x92D2, 0xDCF2, 0x92E4, 0xE0A7, + 0x92EA, 0xF8E8, 0x92F8, 0xCBEA, 0x92FC, 0xCBBC, 0x9304, 0xD6E2, 0x9310, 0xF5DE, 0x9318, 0xF5DF, 0x931A, 0xEEB6, 0x931E, 0xE2F6, + 0x931F, 0xD3CA, 0x9320, 0xEFFC, 0x9321, 0xD1C4, 0x9322, 0xEFB1, 0x9324, 0xD1C5, 0x9326, 0xD0DE, 0x9328, 0xD9E1, 0x932B, 0xE0B8, + 0x932E, 0xCDD1, 0x932F, 0xF3B9, 0x9348, 0xE7CC, 0x934A, 0xD6A8, 0x934B, 0xCEA7, 0x934D, 0xD4B5, 0x9354, 0xE4C8, 0x935B, 0xD3B4, + 0x936E, 0xEBB9, 0x9375, 0xCBF5, 0x937C, 0xF6DD, 0x937E, 0xF1A3, 0x938C, 0xCCC7, 0x9394, 0xE9CA, 0x9396, 0xE1F0, 0x939A, 0xF5E0, + 0x93A3, 0xFBAF, 0x93A7, 0xCBD1, 0x93AC, 0xFBE0, 0x93AD, 0xF2E5, 0x93B0, 0xECF0, 0x93C3, 0xF0EC, 0x93D1, 0xEEEB, 0x93DE, 0xE9CB, + 0x93E1, 0xCCF0, 0x93E4, 0xD7AF, 0x93F6, 0xF3A1, 0x9404, 0xFCF5, 0x9418, 0xF1A4, 0x9425, 0xE0D6, 0x942B, 0xEFB2, 0x9435, 0xF4D1, + 0x9438, 0xF7A1, 0x9444, 0xF1D1, 0x9451, 0xCAFC, 0x9452, 0xCAFD, 0x945B, 0xCECE, 0x947D, 0xF3C8, 0x947F, 0xF3BA, 0x9577, 0xEDFE, + 0x9580, 0xDAA6, 0x9583, 0xE0EC, 0x9589, 0xF8CD, 0x958B, 0xCBD2, 0x958F, 0xEBCE, 0x9591, 0xF9D8, 0x9592, 0xF9D9, 0x9593, 0xCAE0, + 0x9594, 0xDACA, 0x9598, 0xCBA6, 0x95A3, 0xCAC8, 0x95A4, 0xF9EE, 0x95A5, 0xDBEC, 0x95A8, 0xD0B1, 0x95AD, 0xD5EF, 0x95B1, 0xE6F3, + 0x95BB, 0xE7A2, 0x95BC, 0xE4D9, 0x95C7, 0xE4E1, 0x95CA, 0xFCC4, 0x95D4, 0xF9EF, 0x95D5, 0xCFF4, 0x95D6, 0xF7E6, 0x95DC, 0xCEBC, + 0x95E1, 0xF4C5, 0x95E2, 0xDCA3, 0x961C, 0xDDBD, 0x9621, 0xF4C6, 0x962A, 0xF8A1, 0x962E, 0xE8D6, 0x9632, 0xDBC1, 0x963B, 0xF0E6, + 0x963F, 0xE4B9, 0x9640, 0xF6ED, 0x9642, 0xF9AE, 0x9644, 0xDDBE, 0x964B, 0xD7B0, 0x964C, 0xD8E8, 0x964D, 0xCBBD, 0x9650, 0xF9DA, + 0x965B, 0xF8CE, 0x965C, 0xF9F0, 0x965D, 0xE0ED, 0x965E, 0xE3B3, 0x965F, 0xF4B3, 0x9662, 0xEAC2, 0x9663, 0xF2E6, 0x9664, 0xF0B6, + 0x966A, 0xDBD6, 0x9670, 0xEBE4, 0x9673, 0xF2E7, 0x9675, 0xD7D5, 0x9676, 0xD4B6, 0x9677, 0xF9E8, 0x9678, 0xD7C1, 0x967D, 0xE5D5, + 0x9685, 0xE9EA, 0x9686, 0xD7CC, 0x968A, 0xD3E9, 0x968B, 0xE2C9, 0x968D, 0xFCDB, 0x968E, 0xCDAD, 0x9694, 0xCCB0, 0x9695, 0xEAA2, + 0x9698, 0xE4F6, 0x9699, 0xD0C0, 0x969B, 0xF0B7, 0x969C, 0xEEA1, 0x96A3, 0xD7F6, 0x96A7, 0xE2CA, 0x96A8, 0xE2CB, 0x96AA, 0xFACF, + 0x96B1, 0xEBDF, 0x96B7, 0xD6CB, 0x96BB, 0xF4B4, 0x96C0, 0xEDCD, 0x96C1, 0xE4D2, 0x96C4, 0xEAA9, 0x96C5, 0xE4BA, 0x96C6, 0xF3A2, + 0x96C7, 0xCDD2, 0x96C9, 0xF6CB, 0x96CB, 0xF1E6, 0x96CC, 0xEDC1, 0x96CD, 0xE8BC, 0x96CE, 0xEED1, 0x96D5, 0xF0E7, 0x96D6, 0xE2CC, + 0x96D9, 0xE4AA, 0x96DB, 0xF5E1, 0x96DC, 0xEDDA, 0x96E2, 0xD7EE, 0x96E3, 0xD1F1, 0x96E8, 0xE9EB, 0x96E9, 0xE9EC, 0x96EA, 0xE0E4, + 0x96EF, 0xDAA7, 0x96F0, 0xDDD4, 0x96F2, 0xEAA3, 0x96F6, 0xD6C3, 0x96F7, 0xD6F4, 0x96F9, 0xDADF, 0x96FB, 0xEFB3, 0x9700, 0xE2CD, + 0x9706, 0xEFFD, 0x9707, 0xF2E8, 0x9711, 0xEFC5, 0x9713, 0xE7E7, 0x9716, 0xD7FD, 0x9719, 0xE7CE, 0x971C, 0xDFDC, 0x971E, 0xF9C7, + 0x9727, 0xD9F6, 0x9730, 0xDFAC, 0x9732, 0xD6DA, 0x9739, 0xDCA4, 0x973D, 0xF0B8, 0x9742, 0xD5FA, 0x9744, 0xE4F7, 0x9748, 0xD6C4, + 0x9751, 0xF4EC, 0x9756, 0xEFFE, 0x975C, 0xF0A1, 0x975E, 0xDEAA, 0x9761, 0xDABC, 0x9762, 0xD8FC, 0x9769, 0xFAD4, 0x976D, 0xECE5, + 0x9774, 0xFCA8, 0x9777, 0xECE6, 0x977A, 0xD8CB, 0x978B, 0xFBB9, 0x978D, 0xE4D3, 0x978F, 0xCDF9, 0x97A0, 0xCFD3, 0x97A8, 0xCAEA, + 0x97AB, 0xCFD4, 0x97AD, 0xF8BD, 0x97C6, 0xF4C7, 0x97CB, 0xEADF, 0x97D3, 0xF9DB, 0x97DC, 0xD4B7, 0x97F3, 0xEBE5, 0x97F6, 0xE1D2, + 0x97FB, 0xEAA4, 0x97FF, 0xFAC2, 0x9800, 0xFBE1, 0x9801, 0xFAED, 0x9802, 0xF0A2, 0x9803, 0xCCF1, 0x9805, 0xFAA3, 0x9806, 0xE2F7, + 0x9808, 0xE2CE, 0x980A, 0xE9F5, 0x980C, 0xE1EB, 0x9810, 0xE7E8, 0x9811, 0xE8D7, 0x9812, 0xDAF8, 0x9813, 0xD4CB, 0x9817, 0xF7F6, + 0x9818, 0xD6C5, 0x982D, 0xD4E9, 0x9830, 0xFAFA, 0x9838, 0xCCF2, 0x9839, 0xF7DD, 0x983B, 0xDEBA, 0x9846, 0xCEA8, 0x984C, 0xF0B9, + 0x984D, 0xE4FE, 0x984E, 0xE4C9, 0x9854, 0xE4D4, 0x9858, 0xEAC3, 0x985A, 0xEFB4, 0x985E, 0xD7BE, 0x9865, 0xFBE2, 0x9867, 0xCDD3, + 0x986B, 0xEFB5, 0x986F, 0xFAE9, 0x98A8, 0xF9A6, 0x98AF, 0xDFBD, 0x98B1, 0xF7C7, 0x98C4, 0xF8FD, 0x98C7, 0xF8FC, 0x98DB, 0xDEAB, + 0x98DC, 0xDBE8, 0x98DF, 0xE3DD, 0x98E1, 0xE1E2, 0x98E2, 0xD1C6, 0x98ED, 0xF6D0, 0x98EE, 0xEBE6, 0x98EF, 0xDAF9, 0x98F4, 0xECC7, + 0x98FC, 0xDEF8, 0x98FD, 0xF8E9, 0x98FE, 0xE3DE, 0x9903, 0xCEF5, 0x9909, 0xFAC3, 0x990A, 0xE5D7, 0x990C, 0xECC8, 0x9910, 0xF3C9, + 0x9913, 0xE4BB, 0x9918, 0xE6AE, 0x991E, 0xEFB6, 0x9920, 0xDCBF, 0x9928, 0xCEBD, 0x9945, 0xD8C3, 0x9949, 0xD0CF, 0x994B, 0xCFFA, + 0x994C, 0xF3CA, 0x994D, 0xE0D7, 0x9951, 0xD1C7, 0x9952, 0xE9AE, 0x9954, 0xE8BD, 0x9957, 0xFAC4, 0x9996, 0xE2CF, 0x9999, 0xFAC5, + 0x999D, 0xF9B8, 0x99A5, 0xDCE0, 0x99A8, 0xFBB0, 0x99AC, 0xD8A9, 0x99AD, 0xE5DF, 0x99AE, 0xF9A7, 0x99B1, 0xF6EE, 0x99B3, 0xF6CC, + 0x99B4, 0xE2F8, 0x99B9, 0xECF1, 0x99C1, 0xDAE0, 0x99D0, 0xF1D2, 0x99D1, 0xD2CC, 0x99D2, 0xCFCB, 0x99D5, 0xCABD, 0x99D9, 0xDDBF, + 0x99DD, 0xF6EF, 0x99DF, 0xDEF9, 0x99ED, 0xFAB4, 0x99F1, 0xD5AD, 0x99FF, 0xF1E7, 0x9A01, 0xDEBE, 0x9A08, 0xDCC0, 0x9A0E, 0xD1C8, + 0x9A0F, 0xD1C9, 0x9A19, 0xF8BE, 0x9A2B, 0xCBF6, 0x9A30, 0xD4F9, 0x9A36, 0xF5E2, 0x9A37, 0xE1D3, 0x9A40, 0xD8E9, 0x9A43, 0xF8FE, + 0x9A45, 0xCFCC, 0x9A4D, 0xFDA4, 0x9A55, 0xCEF6, 0x9A57, 0xFAD0, 0x9A5A, 0xCCF3, 0x9A5B, 0xE6BE, 0x9A5F, 0xF6AE, 0x9A62, 0xD5F0, + 0x9A65, 0xD1CA, 0x9A69, 0xFCBE, 0x9A6A, 0xD5F1, 0x9AA8, 0xCDE9, 0x9AB8, 0xFAB5, 0x9AD3, 0xE2D0, 0x9AD4, 0xF4F7, 0x9AD8, 0xCDD4, + 0x9AE5, 0xE7A3, 0x9AEE, 0xDBA5, 0x9B1A, 0xE2D1, 0x9B27, 0xD7A2, 0x9B2A, 0xF7E3, 0x9B31, 0xEAA6, 0x9B3C, 0xD0A1, 0x9B41, 0xCEDA, + 0x9B42, 0xFBEB, 0x9B43, 0xDBA6, 0x9B44, 0xDBDE, 0x9B45, 0xD8E5, 0x9B4F, 0xEAE0, 0x9B54, 0xD8AA, 0x9B5A, 0xE5E0, 0x9B6F, 0xD6DB, + 0x9B8E, 0xEFC6, 0x9B91, 0xF8EA, 0x9B9F, 0xE4D5, 0x9BAB, 0xCEF7, 0x9BAE, 0xE0D8, 0x9BC9, 0xD7EF, 0x9BD6, 0xF4ED, 0x9BE4, 0xCDE6, + 0x9BE8, 0xCCF4, 0x9C0D, 0xF5E3, 0x9C10, 0xE4CA, 0x9C12, 0xDCE1, 0x9C15, 0xF9C8, 0x9C25, 0xFCBF, 0x9C32, 0xE8A7, 0x9C3B, 0xD8C4, + 0x9C47, 0xCBBE, 0x9C49, 0xDCAE, 0x9C57, 0xD7F7, 0x9CE5, 0xF0E8, 0x9CE7, 0xDDC0, 0x9CE9, 0xCFCD, 0x9CF3, 0xDCF3, 0x9CF4, 0xD9B0, + 0x9CF6, 0xE6E9, 0x9D09, 0xE4BC, 0x9D1B, 0xEAC4, 0x9D26, 0xE4EC, 0x9D28, 0xE4E5, 0x9D3B, 0xFBF8, 0x9D51, 0xCCBB, 0x9D5D, 0xE4BD, + 0x9D60, 0xCDDC, 0x9D61, 0xD9F7, 0x9D6C, 0xDDDF, 0x9D72, 0xEDCE, 0x9DA9, 0xD9D0, 0x9DAF, 0xE5A3, 0x9DB4, 0xF9CD, 0x9DC4, 0xCDAE, + 0x9DD7, 0xCFCE, 0x9DF2, 0xF6AF, 0x9DF8, 0xFDD3, 0x9DF9, 0xEBED, 0x9DFA, 0xD6DC, 0x9E1A, 0xE5A4, 0x9E1E, 0xD5B6, 0x9E75, 0xD6DD, + 0x9E79, 0xF9E9, 0x9E7D, 0xE7A4, 0x9E7F, 0xD6E3, 0x9E92, 0xD1CB, 0x9E93, 0xD6E4, 0x9E97, 0xD5F2, 0x9E9D, 0xDEFA, 0x9E9F, 0xD7F8, + 0x9EA5, 0xD8EA, 0x9EB4, 0xCFD5, 0x9EB5, 0xD8FD, 0x9EBB, 0xD8AB, 0x9EBE, 0xFDCB, 0x9EC3, 0xFCDC, 0x9ECD, 0xE0A8, 0x9ECE, 0xD5F3, + 0x9ED1, 0xFDD9, 0x9ED4, 0xCCA3, 0x9ED8, 0xD9F9, 0x9EDB, 0xD3EA, 0x9EDC, 0xF5F5, 0x9EDE, 0xEFC7, 0x9EE8, 0xD3DA, 0x9EF4, 0xDABD, + 0x9F07, 0xE8A8, 0x9F08, 0xDCAF, 0x9F0E, 0xF0A3, 0x9F13, 0xCDD5, 0x9F20, 0xE0A9, 0x9F3B, 0xDEAC, 0x9F4A, 0xF0BA, 0x9F4B, 0xEEB1, + 0x9F4E, 0xEEB2, 0x9F52, 0xF6CD, 0x9F5F, 0xEED2, 0x9F61, 0xD6C6, 0x9F67, 0xE0E5, 0x9F6A, 0xF3BB, 0x9F6C, 0xE5E1, 0x9F77, 0xE4CB, + 0x9F8D, 0xD7A3, 0x9F90, 0xDBC2, 0x9F95, 0xCAFE, 0x9F9C, 0xCFCF, 0xAC00, 0xB0A1, 0xAC01, 0xB0A2, 0xAC02, 0x8141, 0xAC03, 0x8142, + 0xAC04, 0xB0A3, 0xAC05, 0x8143, 0xAC06, 0x8144, 0xAC07, 0xB0A4, 0xAC08, 0xB0A5, 0xAC09, 0xB0A6, 0xAC0A, 0xB0A7, 0xAC0B, 0x8145, + 0xAC0C, 0x8146, 0xAC0D, 0x8147, 0xAC0E, 0x8148, 0xAC0F, 0x8149, 0xAC10, 0xB0A8, 0xAC11, 0xB0A9, 0xAC12, 0xB0AA, 0xAC13, 0xB0AB, + 0xAC14, 0xB0AC, 0xAC15, 0xB0AD, 0xAC16, 0xB0AE, 0xAC17, 0xB0AF, 0xAC18, 0x814A, 0xAC19, 0xB0B0, 0xAC1A, 0xB0B1, 0xAC1B, 0xB0B2, + 0xAC1C, 0xB0B3, 0xAC1D, 0xB0B4, 0xAC1E, 0x814B, 0xAC1F, 0x814C, 0xAC20, 0xB0B5, 0xAC21, 0x814D, 0xAC22, 0x814E, 0xAC23, 0x814F, + 0xAC24, 0xB0B6, 0xAC25, 0x8150, 0xAC26, 0x8151, 0xAC27, 0x8152, 0xAC28, 0x8153, 0xAC29, 0x8154, 0xAC2A, 0x8155, 0xAC2B, 0x8156, + 0xAC2C, 0xB0B7, 0xAC2D, 0xB0B8, 0xAC2E, 0x8157, 0xAC2F, 0xB0B9, 0xAC30, 0xB0BA, 0xAC31, 0xB0BB, 0xAC32, 0x8158, 0xAC33, 0x8159, + 0xAC34, 0x815A, 0xAC35, 0x8161, 0xAC36, 0x8162, 0xAC37, 0x8163, 0xAC38, 0xB0BC, 0xAC39, 0xB0BD, 0xAC3A, 0x8164, 0xAC3B, 0x8165, + 0xAC3C, 0xB0BE, 0xAC3D, 0x8166, 0xAC3E, 0x8167, 0xAC3F, 0x8168, 0xAC40, 0xB0BF, 0xAC41, 0x8169, 0xAC42, 0x816A, 0xAC43, 0x816B, + 0xAC44, 0x816C, 0xAC45, 0x816D, 0xAC46, 0x816E, 0xAC47, 0x816F, 0xAC48, 0x8170, 0xAC49, 0x8171, 0xAC4A, 0x8172, 0xAC4B, 0xB0C0, + 0xAC4C, 0x8173, 0xAC4D, 0xB0C1, 0xAC4E, 0x8174, 0xAC4F, 0x8175, 0xAC50, 0x8176, 0xAC51, 0x8177, 0xAC52, 0x8178, 0xAC53, 0x8179, + 0xAC54, 0xB0C2, 0xAC55, 0x817A, 0xAC56, 0x8181, 0xAC57, 0x8182, 0xAC58, 0xB0C3, 0xAC59, 0x8183, 0xAC5A, 0x8184, 0xAC5B, 0x8185, + 0xAC5C, 0xB0C4, 0xAC5D, 0x8186, 0xAC5E, 0x8187, 0xAC5F, 0x8188, 0xAC60, 0x8189, 0xAC61, 0x818A, 0xAC62, 0x818B, 0xAC63, 0x818C, + 0xAC64, 0x818D, 0xAC65, 0x818E, 0xAC66, 0x818F, 0xAC67, 0x8190, 0xAC68, 0x8191, 0xAC69, 0x8192, 0xAC6A, 0x8193, 0xAC6B, 0x8194, + 0xAC6C, 0x8195, 0xAC6D, 0x8196, 0xAC6E, 0x8197, 0xAC6F, 0x8198, 0xAC70, 0xB0C5, 0xAC71, 0xB0C6, 0xAC72, 0x8199, 0xAC73, 0x819A, + 0xAC74, 0xB0C7, 0xAC75, 0x819B, 0xAC76, 0x819C, 0xAC77, 0xB0C8, 0xAC78, 0xB0C9, 0xAC79, 0x819D, 0xAC7A, 0xB0CA, 0xAC7B, 0x819E, + 0xAC7C, 0x819F, 0xAC7D, 0x81A0, 0xAC7E, 0x81A1, 0xAC7F, 0x81A2, 0xAC80, 0xB0CB, 0xAC81, 0xB0CC, 0xAC82, 0x81A3, 0xAC83, 0xB0CD, + 0xAC84, 0xB0CE, 0xAC85, 0xB0CF, 0xAC86, 0xB0D0, 0xAC87, 0x81A4, 0xAC88, 0x81A5, 0xAC89, 0xB0D1, 0xAC8A, 0xB0D2, 0xAC8B, 0xB0D3, + 0xAC8C, 0xB0D4, 0xAC8D, 0x81A6, 0xAC8E, 0x81A7, 0xAC8F, 0x81A8, 0xAC90, 0xB0D5, 0xAC91, 0x81A9, 0xAC92, 0x81AA, 0xAC93, 0x81AB, + 0xAC94, 0xB0D6, 0xAC95, 0x81AC, 0xAC96, 0x81AD, 0xAC97, 0x81AE, 0xAC98, 0x81AF, 0xAC99, 0x81B0, 0xAC9A, 0x81B1, 0xAC9B, 0x81B2, + 0xAC9C, 0xB0D7, 0xAC9D, 0xB0D8, 0xAC9E, 0x81B3, 0xAC9F, 0xB0D9, 0xACA0, 0xB0DA, 0xACA1, 0xB0DB, 0xACA2, 0x81B4, 0xACA3, 0x81B5, + 0xACA4, 0x81B6, 0xACA5, 0x81B7, 0xACA6, 0x81B8, 0xACA7, 0x81B9, 0xACA8, 0xB0DC, 0xACA9, 0xB0DD, 0xACAA, 0xB0DE, 0xACAB, 0x81BA, + 0xACAC, 0xB0DF, 0xACAD, 0x81BB, 0xACAE, 0x81BC, 0xACAF, 0xB0E0, 0xACB0, 0xB0E1, 0xACB1, 0x81BD, 0xACB2, 0x81BE, 0xACB3, 0x81BF, + 0xACB4, 0x81C0, 0xACB5, 0x81C1, 0xACB6, 0x81C2, 0xACB7, 0x81C3, 0xACB8, 0xB0E2, 0xACB9, 0xB0E3, 0xACBA, 0x81C4, 0xACBB, 0xB0E4, + 0xACBC, 0xB0E5, 0xACBD, 0xB0E6, 0xACBE, 0x81C5, 0xACBF, 0x81C6, 0xACC0, 0x81C7, 0xACC1, 0xB0E7, 0xACC2, 0x81C8, 0xACC3, 0x81C9, + 0xACC4, 0xB0E8, 0xACC5, 0x81CA, 0xACC6, 0x81CB, 0xACC7, 0x81CC, 0xACC8, 0xB0E9, 0xACC9, 0x81CD, 0xACCA, 0x81CE, 0xACCB, 0x81CF, + 0xACCC, 0xB0EA, 0xACCD, 0x81D0, 0xACCE, 0x81D1, 0xACCF, 0x81D2, 0xACD0, 0x81D3, 0xACD1, 0x81D4, 0xACD2, 0x81D5, 0xACD3, 0x81D6, + 0xACD4, 0x81D7, 0xACD5, 0xB0EB, 0xACD6, 0x81D8, 0xACD7, 0xB0EC, 0xACD8, 0x81D9, 0xACD9, 0x81DA, 0xACDA, 0x81DB, 0xACDB, 0x81DC, + 0xACDC, 0x81DD, 0xACDD, 0x81DE, 0xACDE, 0x81DF, 0xACDF, 0x81E0, 0xACE0, 0xB0ED, 0xACE1, 0xB0EE, 0xACE2, 0x81E1, 0xACE3, 0x81E2, + 0xACE4, 0xB0EF, 0xACE5, 0x81E3, 0xACE6, 0x81E4, 0xACE7, 0xB0F0, 0xACE8, 0xB0F1, 0xACE9, 0x81E5, 0xACEA, 0xB0F2, 0xACEB, 0x81E6, + 0xACEC, 0xB0F3, 0xACED, 0x81E7, 0xACEE, 0x81E8, 0xACEF, 0xB0F4, 0xACF0, 0xB0F5, 0xACF1, 0xB0F6, 0xACF2, 0x81E9, 0xACF3, 0xB0F7, + 0xACF4, 0x81EA, 0xACF5, 0xB0F8, 0xACF6, 0xB0F9, 0xACF7, 0x81EB, 0xACF8, 0x81EC, 0xACF9, 0x81ED, 0xACFA, 0x81EE, 0xACFB, 0x81EF, + 0xACFC, 0xB0FA, 0xACFD, 0xB0FB, 0xACFE, 0x81F0, 0xACFF, 0x81F1, 0xAD00, 0xB0FC, 0xAD01, 0x81F2, 0xAD02, 0x81F3, 0xAD03, 0x81F4, + 0xAD04, 0xB0FD, 0xAD05, 0x81F5, 0xAD06, 0xB0FE, 0xAD07, 0x81F6, 0xAD08, 0x81F7, 0xAD09, 0x81F8, 0xAD0A, 0x81F9, 0xAD0B, 0x81FA, + 0xAD0C, 0xB1A1, 0xAD0D, 0xB1A2, 0xAD0E, 0x81FB, 0xAD0F, 0xB1A3, 0xAD10, 0x81FC, 0xAD11, 0xB1A4, 0xAD12, 0x81FD, 0xAD13, 0x81FE, + 0xAD14, 0x8241, 0xAD15, 0x8242, 0xAD16, 0x8243, 0xAD17, 0x8244, 0xAD18, 0xB1A5, 0xAD19, 0x8245, 0xAD1A, 0x8246, 0xAD1B, 0x8247, + 0xAD1C, 0xB1A6, 0xAD1D, 0x8248, 0xAD1E, 0x8249, 0xAD1F, 0x824A, 0xAD20, 0xB1A7, 0xAD21, 0x824B, 0xAD22, 0x824C, 0xAD23, 0x824D, + 0xAD24, 0x824E, 0xAD25, 0x824F, 0xAD26, 0x8250, 0xAD27, 0x8251, 0xAD28, 0x8252, 0xAD29, 0xB1A8, 0xAD2A, 0x8253, 0xAD2B, 0x8254, + 0xAD2C, 0xB1A9, 0xAD2D, 0xB1AA, 0xAD2E, 0x8255, 0xAD2F, 0x8256, 0xAD30, 0x8257, 0xAD31, 0x8258, 0xAD32, 0x8259, 0xAD33, 0x825A, + 0xAD34, 0xB1AB, 0xAD35, 0xB1AC, 0xAD36, 0x8261, 0xAD37, 0x8262, 0xAD38, 0xB1AD, 0xAD39, 0x8263, 0xAD3A, 0x8264, 0xAD3B, 0x8265, + 0xAD3C, 0xB1AE, 0xAD3D, 0x8266, 0xAD3E, 0x8267, 0xAD3F, 0x8268, 0xAD40, 0x8269, 0xAD41, 0x826A, 0xAD42, 0x826B, 0xAD43, 0x826C, + 0xAD44, 0xB1AF, 0xAD45, 0xB1B0, 0xAD46, 0x826D, 0xAD47, 0xB1B1, 0xAD48, 0x826E, 0xAD49, 0xB1B2, 0xAD4A, 0x826F, 0xAD4B, 0x8270, + 0xAD4C, 0x8271, 0xAD4D, 0x8272, 0xAD4E, 0x8273, 0xAD4F, 0x8274, 0xAD50, 0xB1B3, 0xAD51, 0x8275, 0xAD52, 0x8276, 0xAD53, 0x8277, + 0xAD54, 0xB1B4, 0xAD55, 0x8278, 0xAD56, 0x8279, 0xAD57, 0x827A, 0xAD58, 0xB1B5, 0xAD59, 0x8281, 0xAD5A, 0x8282, 0xAD5B, 0x8283, + 0xAD5C, 0x8284, 0xAD5D, 0x8285, 0xAD5E, 0x8286, 0xAD5F, 0x8287, 0xAD60, 0x8288, 0xAD61, 0xB1B6, 0xAD62, 0x8289, 0xAD63, 0xB1B7, + 0xAD64, 0x828A, 0xAD65, 0x828B, 0xAD66, 0x828C, 0xAD67, 0x828D, 0xAD68, 0x828E, 0xAD69, 0x828F, 0xAD6A, 0x8290, 0xAD6B, 0x8291, + 0xAD6C, 0xB1B8, 0xAD6D, 0xB1B9, 0xAD6E, 0x8292, 0xAD6F, 0x8293, 0xAD70, 0xB1BA, 0xAD71, 0x8294, 0xAD72, 0x8295, 0xAD73, 0xB1BB, + 0xAD74, 0xB1BC, 0xAD75, 0xB1BD, 0xAD76, 0xB1BE, 0xAD77, 0x8296, 0xAD78, 0x8297, 0xAD79, 0x8298, 0xAD7A, 0x8299, 0xAD7B, 0xB1BF, + 0xAD7C, 0xB1C0, 0xAD7D, 0xB1C1, 0xAD7E, 0x829A, 0xAD7F, 0xB1C2, 0xAD80, 0x829B, 0xAD81, 0xB1C3, 0xAD82, 0xB1C4, 0xAD83, 0x829C, + 0xAD84, 0x829D, 0xAD85, 0x829E, 0xAD86, 0x829F, 0xAD87, 0x82A0, 0xAD88, 0xB1C5, 0xAD89, 0xB1C6, 0xAD8A, 0x82A1, 0xAD8B, 0x82A2, + 0xAD8C, 0xB1C7, 0xAD8D, 0x82A3, 0xAD8E, 0x82A4, 0xAD8F, 0x82A5, 0xAD90, 0xB1C8, 0xAD91, 0x82A6, 0xAD92, 0x82A7, 0xAD93, 0x82A8, + 0xAD94, 0x82A9, 0xAD95, 0x82AA, 0xAD96, 0x82AB, 0xAD97, 0x82AC, 0xAD98, 0x82AD, 0xAD99, 0x82AE, 0xAD9A, 0x82AF, 0xAD9B, 0x82B0, + 0xAD9C, 0xB1C9, 0xAD9D, 0xB1CA, 0xAD9E, 0x82B1, 0xAD9F, 0x82B2, 0xADA0, 0x82B3, 0xADA1, 0x82B4, 0xADA2, 0x82B5, 0xADA3, 0x82B6, + 0xADA4, 0xB1CB, 0xADA5, 0x82B7, 0xADA6, 0x82B8, 0xADA7, 0x82B9, 0xADA8, 0x82BA, 0xADA9, 0x82BB, 0xADAA, 0x82BC, 0xADAB, 0x82BD, + 0xADAC, 0x82BE, 0xADAD, 0x82BF, 0xADAE, 0x82C0, 0xADAF, 0x82C1, 0xADB0, 0x82C2, 0xADB1, 0x82C3, 0xADB2, 0x82C4, 0xADB3, 0x82C5, + 0xADB4, 0x82C6, 0xADB5, 0x82C7, 0xADB6, 0x82C8, 0xADB7, 0xB1CC, 0xADB8, 0x82C9, 0xADB9, 0x82CA, 0xADBA, 0x82CB, 0xADBB, 0x82CC, + 0xADBC, 0x82CD, 0xADBD, 0x82CE, 0xADBE, 0x82CF, 0xADBF, 0x82D0, 0xADC0, 0xB1CD, 0xADC1, 0xB1CE, 0xADC2, 0x82D1, 0xADC3, 0x82D2, + 0xADC4, 0xB1CF, 0xADC5, 0x82D3, 0xADC6, 0x82D4, 0xADC7, 0x82D5, 0xADC8, 0xB1D0, 0xADC9, 0x82D6, 0xADCA, 0x82D7, 0xADCB, 0x82D8, + 0xADCC, 0x82D9, 0xADCD, 0x82DA, 0xADCE, 0x82DB, 0xADCF, 0x82DC, 0xADD0, 0xB1D1, 0xADD1, 0xB1D2, 0xADD2, 0x82DD, 0xADD3, 0xB1D3, + 0xADD4, 0x82DE, 0xADD5, 0x82DF, 0xADD6, 0x82E0, 0xADD7, 0x82E1, 0xADD8, 0x82E2, 0xADD9, 0x82E3, 0xADDA, 0x82E4, 0xADDB, 0x82E5, + 0xADDC, 0xB1D4, 0xADDD, 0x82E6, 0xADDE, 0x82E7, 0xADDF, 0x82E8, 0xADE0, 0xB1D5, 0xADE1, 0x82E9, 0xADE2, 0x82EA, 0xADE3, 0x82EB, + 0xADE4, 0xB1D6, 0xADE5, 0x82EC, 0xADE6, 0x82ED, 0xADE7, 0x82EE, 0xADE8, 0x82EF, 0xADE9, 0x82F0, 0xADEA, 0x82F1, 0xADEB, 0x82F2, + 0xADEC, 0x82F3, 0xADED, 0x82F4, 0xADEE, 0x82F5, 0xADEF, 0x82F6, 0xADF0, 0x82F7, 0xADF1, 0x82F8, 0xADF2, 0x82F9, 0xADF3, 0x82FA, + 0xADF4, 0x82FB, 0xADF5, 0x82FC, 0xADF6, 0x82FD, 0xADF7, 0x82FE, 0xADF8, 0xB1D7, 0xADF9, 0xB1D8, 0xADFA, 0x8341, 0xADFB, 0x8342, + 0xADFC, 0xB1D9, 0xADFD, 0x8343, 0xADFE, 0x8344, 0xADFF, 0xB1DA, 0xAE00, 0xB1DB, 0xAE01, 0xB1DC, 0xAE02, 0x8345, 0xAE03, 0x8346, + 0xAE04, 0x8347, 0xAE05, 0x8348, 0xAE06, 0x8349, 0xAE07, 0x834A, 0xAE08, 0xB1DD, 0xAE09, 0xB1DE, 0xAE0A, 0x834B, 0xAE0B, 0xB1DF, + 0xAE0C, 0x834C, 0xAE0D, 0xB1E0, 0xAE0E, 0x834D, 0xAE0F, 0x834E, 0xAE10, 0x834F, 0xAE11, 0x8350, 0xAE12, 0x8351, 0xAE13, 0x8352, + 0xAE14, 0xB1E1, 0xAE15, 0x8353, 0xAE16, 0x8354, 0xAE17, 0x8355, 0xAE18, 0x8356, 0xAE19, 0x8357, 0xAE1A, 0x8358, 0xAE1B, 0x8359, + 0xAE1C, 0x835A, 0xAE1D, 0x8361, 0xAE1E, 0x8362, 0xAE1F, 0x8363, 0xAE20, 0x8364, 0xAE21, 0x8365, 0xAE22, 0x8366, 0xAE23, 0x8367, + 0xAE24, 0x8368, 0xAE25, 0x8369, 0xAE26, 0x836A, 0xAE27, 0x836B, 0xAE28, 0x836C, 0xAE29, 0x836D, 0xAE2A, 0x836E, 0xAE2B, 0x836F, + 0xAE2C, 0x8370, 0xAE2D, 0x8371, 0xAE2E, 0x8372, 0xAE2F, 0x8373, 0xAE30, 0xB1E2, 0xAE31, 0xB1E3, 0xAE32, 0x8374, 0xAE33, 0x8375, + 0xAE34, 0xB1E4, 0xAE35, 0x8376, 0xAE36, 0x8377, 0xAE37, 0xB1E5, 0xAE38, 0xB1E6, 0xAE39, 0x8378, 0xAE3A, 0xB1E7, 0xAE3B, 0x8379, + 0xAE3C, 0x837A, 0xAE3D, 0x8381, 0xAE3E, 0x8382, 0xAE3F, 0x8383, 0xAE40, 0xB1E8, 0xAE41, 0xB1E9, 0xAE42, 0x8384, 0xAE43, 0xB1EA, + 0xAE44, 0x8385, 0xAE45, 0xB1EB, 0xAE46, 0xB1EC, 0xAE47, 0x8386, 0xAE48, 0x8387, 0xAE49, 0x8388, 0xAE4A, 0xB1ED, 0xAE4B, 0x8389, + 0xAE4C, 0xB1EE, 0xAE4D, 0xB1EF, 0xAE4E, 0xB1F0, 0xAE4F, 0x838A, 0xAE50, 0xB1F1, 0xAE51, 0x838B, 0xAE52, 0x838C, 0xAE53, 0x838D, + 0xAE54, 0xB1F2, 0xAE55, 0x838E, 0xAE56, 0xB1F3, 0xAE57, 0x838F, 0xAE58, 0x8390, 0xAE59, 0x8391, 0xAE5A, 0x8392, 0xAE5B, 0x8393, + 0xAE5C, 0xB1F4, 0xAE5D, 0xB1F5, 0xAE5E, 0x8394, 0xAE5F, 0xB1F6, 0xAE60, 0xB1F7, 0xAE61, 0xB1F8, 0xAE62, 0x8395, 0xAE63, 0x8396, + 0xAE64, 0x8397, 0xAE65, 0xB1F9, 0xAE66, 0x8398, 0xAE67, 0x8399, 0xAE68, 0xB1FA, 0xAE69, 0xB1FB, 0xAE6A, 0x839A, 0xAE6B, 0x839B, + 0xAE6C, 0xB1FC, 0xAE6D, 0x839C, 0xAE6E, 0x839D, 0xAE6F, 0x839E, 0xAE70, 0xB1FD, 0xAE71, 0x839F, 0xAE72, 0x83A0, 0xAE73, 0x83A1, + 0xAE74, 0x83A2, 0xAE75, 0x83A3, 0xAE76, 0x83A4, 0xAE77, 0x83A5, 0xAE78, 0xB1FE, 0xAE79, 0xB2A1, 0xAE7A, 0x83A6, 0xAE7B, 0xB2A2, + 0xAE7C, 0xB2A3, 0xAE7D, 0xB2A4, 0xAE7E, 0x83A7, 0xAE7F, 0x83A8, 0xAE80, 0x83A9, 0xAE81, 0x83AA, 0xAE82, 0x83AB, 0xAE83, 0x83AC, + 0xAE84, 0xB2A5, 0xAE85, 0xB2A6, 0xAE86, 0x83AD, 0xAE87, 0x83AE, 0xAE88, 0x83AF, 0xAE89, 0x83B0, 0xAE8A, 0x83B1, 0xAE8B, 0x83B2, + 0xAE8C, 0xB2A7, 0xAE8D, 0x83B3, 0xAE8E, 0x83B4, 0xAE8F, 0x83B5, 0xAE90, 0x83B6, 0xAE91, 0x83B7, 0xAE92, 0x83B8, 0xAE93, 0x83B9, + 0xAE94, 0x83BA, 0xAE95, 0x83BB, 0xAE96, 0x83BC, 0xAE97, 0x83BD, 0xAE98, 0x83BE, 0xAE99, 0x83BF, 0xAE9A, 0x83C0, 0xAE9B, 0x83C1, + 0xAE9C, 0x83C2, 0xAE9D, 0x83C3, 0xAE9E, 0x83C4, 0xAE9F, 0x83C5, 0xAEA0, 0x83C6, 0xAEA1, 0x83C7, 0xAEA2, 0x83C8, 0xAEA3, 0x83C9, + 0xAEA4, 0x83CA, 0xAEA5, 0x83CB, 0xAEA6, 0x83CC, 0xAEA7, 0x83CD, 0xAEA8, 0x83CE, 0xAEA9, 0x83CF, 0xAEAA, 0x83D0, 0xAEAB, 0x83D1, + 0xAEAC, 0x83D2, 0xAEAD, 0x83D3, 0xAEAE, 0x83D4, 0xAEAF, 0x83D5, 0xAEB0, 0x83D6, 0xAEB1, 0x83D7, 0xAEB2, 0x83D8, 0xAEB3, 0x83D9, + 0xAEB4, 0x83DA, 0xAEB5, 0x83DB, 0xAEB6, 0x83DC, 0xAEB7, 0x83DD, 0xAEB8, 0x83DE, 0xAEB9, 0x83DF, 0xAEBA, 0x83E0, 0xAEBB, 0x83E1, + 0xAEBC, 0xB2A8, 0xAEBD, 0xB2A9, 0xAEBE, 0xB2AA, 0xAEBF, 0x83E2, 0xAEC0, 0xB2AB, 0xAEC1, 0x83E3, 0xAEC2, 0x83E4, 0xAEC3, 0x83E5, + 0xAEC4, 0xB2AC, 0xAEC5, 0x83E6, 0xAEC6, 0x83E7, 0xAEC7, 0x83E8, 0xAEC8, 0x83E9, 0xAEC9, 0x83EA, 0xAECA, 0x83EB, 0xAECB, 0x83EC, + 0xAECC, 0xB2AD, 0xAECD, 0xB2AE, 0xAECE, 0x83ED, 0xAECF, 0xB2AF, 0xAED0, 0xB2B0, 0xAED1, 0xB2B1, 0xAED2, 0x83EE, 0xAED3, 0x83EF, + 0xAED4, 0x83F0, 0xAED5, 0x83F1, 0xAED6, 0x83F2, 0xAED7, 0x83F3, 0xAED8, 0xB2B2, 0xAED9, 0xB2B3, 0xAEDA, 0x83F4, 0xAEDB, 0x83F5, + 0xAEDC, 0xB2B4, 0xAEDD, 0x83F6, 0xAEDE, 0x83F7, 0xAEDF, 0x83F8, 0xAEE0, 0x83F9, 0xAEE1, 0x83FA, 0xAEE2, 0x83FB, 0xAEE3, 0x83FC, + 0xAEE4, 0x83FD, 0xAEE5, 0x83FE, 0xAEE6, 0x8441, 0xAEE7, 0x8442, 0xAEE8, 0xB2B5, 0xAEE9, 0x8443, 0xAEEA, 0x8444, 0xAEEB, 0xB2B6, + 0xAEEC, 0x8445, 0xAEED, 0xB2B7, 0xAEEE, 0x8446, 0xAEEF, 0x8447, 0xAEF0, 0x8448, 0xAEF1, 0x8449, 0xAEF2, 0x844A, 0xAEF3, 0x844B, + 0xAEF4, 0xB2B8, 0xAEF5, 0x844C, 0xAEF6, 0x844D, 0xAEF7, 0x844E, 0xAEF8, 0xB2B9, 0xAEF9, 0x844F, 0xAEFA, 0x8450, 0xAEFB, 0x8451, + 0xAEFC, 0xB2BA, 0xAEFD, 0x8452, 0xAEFE, 0x8453, 0xAEFF, 0x8454, 0xAF00, 0x8455, 0xAF01, 0x8456, 0xAF02, 0x8457, 0xAF03, 0x8458, + 0xAF04, 0x8459, 0xAF05, 0x845A, 0xAF06, 0x8461, 0xAF07, 0xB2BB, 0xAF08, 0xB2BC, 0xAF09, 0x8462, 0xAF0A, 0x8463, 0xAF0B, 0x8464, + 0xAF0C, 0x8465, 0xAF0D, 0xB2BD, 0xAF0E, 0x8466, 0xAF0F, 0x8467, 0xAF10, 0xB2BE, 0xAF11, 0x8468, 0xAF12, 0x8469, 0xAF13, 0x846A, + 0xAF14, 0x846B, 0xAF15, 0x846C, 0xAF16, 0x846D, 0xAF17, 0x846E, 0xAF18, 0x846F, 0xAF19, 0x8470, 0xAF1A, 0x8471, 0xAF1B, 0x8472, + 0xAF1C, 0x8473, 0xAF1D, 0x8474, 0xAF1E, 0x8475, 0xAF1F, 0x8476, 0xAF20, 0x8477, 0xAF21, 0x8478, 0xAF22, 0x8479, 0xAF23, 0x847A, + 0xAF24, 0x8481, 0xAF25, 0x8482, 0xAF26, 0x8483, 0xAF27, 0x8484, 0xAF28, 0x8485, 0xAF29, 0x8486, 0xAF2A, 0x8487, 0xAF2B, 0x8488, + 0xAF2C, 0xB2BF, 0xAF2D, 0xB2C0, 0xAF2E, 0x8489, 0xAF2F, 0x848A, 0xAF30, 0xB2C1, 0xAF31, 0x848B, 0xAF32, 0xB2C2, 0xAF33, 0x848C, + 0xAF34, 0xB2C3, 0xAF35, 0x848D, 0xAF36, 0x848E, 0xAF37, 0x848F, 0xAF38, 0x8490, 0xAF39, 0x8491, 0xAF3A, 0x8492, 0xAF3B, 0x8493, + 0xAF3C, 0xB2C4, 0xAF3D, 0xB2C5, 0xAF3E, 0x8494, 0xAF3F, 0xB2C6, 0xAF40, 0x8495, 0xAF41, 0xB2C7, 0xAF42, 0xB2C8, 0xAF43, 0xB2C9, + 0xAF44, 0x8496, 0xAF45, 0x8497, 0xAF46, 0x8498, 0xAF47, 0x8499, 0xAF48, 0xB2CA, 0xAF49, 0xB2CB, 0xAF4A, 0x849A, 0xAF4B, 0x849B, + 0xAF4C, 0x849C, 0xAF4D, 0x849D, 0xAF4E, 0x849E, 0xAF4F, 0x849F, 0xAF50, 0xB2CC, 0xAF51, 0x84A0, 0xAF52, 0x84A1, 0xAF53, 0x84A2, + 0xAF54, 0x84A3, 0xAF55, 0x84A4, 0xAF56, 0x84A5, 0xAF57, 0x84A6, 0xAF58, 0x84A7, 0xAF59, 0x84A8, 0xAF5A, 0x84A9, 0xAF5B, 0x84AA, + 0xAF5C, 0xB2CD, 0xAF5D, 0xB2CE, 0xAF5E, 0x84AB, 0xAF5F, 0x84AC, 0xAF60, 0x84AD, 0xAF61, 0x84AE, 0xAF62, 0x84AF, 0xAF63, 0x84B0, + 0xAF64, 0xB2CF, 0xAF65, 0xB2D0, 0xAF66, 0x84B1, 0xAF67, 0x84B2, 0xAF68, 0x84B3, 0xAF69, 0x84B4, 0xAF6A, 0x84B5, 0xAF6B, 0x84B6, + 0xAF6C, 0x84B7, 0xAF6D, 0x84B8, 0xAF6E, 0x84B9, 0xAF6F, 0x84BA, 0xAF70, 0x84BB, 0xAF71, 0x84BC, 0xAF72, 0x84BD, 0xAF73, 0x84BE, + 0xAF74, 0x84BF, 0xAF75, 0x84C0, 0xAF76, 0x84C1, 0xAF77, 0x84C2, 0xAF78, 0x84C3, 0xAF79, 0xB2D1, 0xAF7A, 0x84C4, 0xAF7B, 0x84C5, + 0xAF7C, 0x84C6, 0xAF7D, 0x84C7, 0xAF7E, 0x84C8, 0xAF7F, 0x84C9, 0xAF80, 0xB2D2, 0xAF81, 0x84CA, 0xAF82, 0x84CB, 0xAF83, 0x84CC, + 0xAF84, 0xB2D3, 0xAF85, 0x84CD, 0xAF86, 0x84CE, 0xAF87, 0x84CF, 0xAF88, 0xB2D4, 0xAF89, 0x84D0, 0xAF8A, 0x84D1, 0xAF8B, 0x84D2, + 0xAF8C, 0x84D3, 0xAF8D, 0x84D4, 0xAF8E, 0x84D5, 0xAF8F, 0x84D6, 0xAF90, 0xB2D5, 0xAF91, 0xB2D6, 0xAF92, 0x84D7, 0xAF93, 0x84D8, + 0xAF94, 0x84D9, 0xAF95, 0xB2D7, 0xAF96, 0x84DA, 0xAF97, 0x84DB, 0xAF98, 0x84DC, 0xAF99, 0x84DD, 0xAF9A, 0x84DE, 0xAF9B, 0x84DF, + 0xAF9C, 0xB2D8, 0xAF9D, 0x84E0, 0xAF9E, 0x84E1, 0xAF9F, 0x84E2, 0xAFA0, 0x84E3, 0xAFA1, 0x84E4, 0xAFA2, 0x84E5, 0xAFA3, 0x84E6, + 0xAFA4, 0x84E7, 0xAFA5, 0x84E8, 0xAFA6, 0x84E9, 0xAFA7, 0x84EA, 0xAFA8, 0x84EB, 0xAFA9, 0x84EC, 0xAFAA, 0x84ED, 0xAFAB, 0x84EE, + 0xAFAC, 0x84EF, 0xAFAD, 0x84F0, 0xAFAE, 0x84F1, 0xAFAF, 0x84F2, 0xAFB0, 0x84F3, 0xAFB1, 0x84F4, 0xAFB2, 0x84F5, 0xAFB3, 0x84F6, + 0xAFB4, 0x84F7, 0xAFB5, 0x84F8, 0xAFB6, 0x84F9, 0xAFB7, 0x84FA, 0xAFB8, 0xB2D9, 0xAFB9, 0xB2DA, 0xAFBA, 0x84FB, 0xAFBB, 0x84FC, + 0xAFBC, 0xB2DB, 0xAFBD, 0x84FD, 0xAFBE, 0x84FE, 0xAFBF, 0x8541, 0xAFC0, 0xB2DC, 0xAFC1, 0x8542, 0xAFC2, 0x8543, 0xAFC3, 0x8544, + 0xAFC4, 0x8545, 0xAFC5, 0x8546, 0xAFC6, 0x8547, 0xAFC7, 0xB2DD, 0xAFC8, 0xB2DE, 0xAFC9, 0xB2DF, 0xAFCA, 0x8548, 0xAFCB, 0xB2E0, + 0xAFCC, 0x8549, 0xAFCD, 0xB2E1, 0xAFCE, 0xB2E2, 0xAFCF, 0x854A, 0xAFD0, 0x854B, 0xAFD1, 0x854C, 0xAFD2, 0x854D, 0xAFD3, 0x854E, + 0xAFD4, 0xB2E3, 0xAFD5, 0x854F, 0xAFD6, 0x8550, 0xAFD7, 0x8551, 0xAFD8, 0x8552, 0xAFD9, 0x8553, 0xAFDA, 0x8554, 0xAFDB, 0x8555, + 0xAFDC, 0xB2E4, 0xAFDD, 0x8556, 0xAFDE, 0x8557, 0xAFDF, 0x8558, 0xAFE0, 0x8559, 0xAFE1, 0x855A, 0xAFE2, 0x8561, 0xAFE3, 0x8562, + 0xAFE4, 0x8563, 0xAFE5, 0x8564, 0xAFE6, 0x8565, 0xAFE7, 0x8566, 0xAFE8, 0xB2E5, 0xAFE9, 0xB2E6, 0xAFEA, 0x8567, 0xAFEB, 0x8568, + 0xAFEC, 0x8569, 0xAFED, 0x856A, 0xAFEE, 0x856B, 0xAFEF, 0x856C, 0xAFF0, 0xB2E7, 0xAFF1, 0xB2E8, 0xAFF2, 0x856D, 0xAFF3, 0x856E, + 0xAFF4, 0xB2E9, 0xAFF5, 0x856F, 0xAFF6, 0x8570, 0xAFF7, 0x8571, 0xAFF8, 0xB2EA, 0xAFF9, 0x8572, 0xAFFA, 0x8573, 0xAFFB, 0x8574, + 0xAFFC, 0x8575, 0xAFFD, 0x8576, 0xAFFE, 0x8577, 0xAFFF, 0x8578, 0xB000, 0xB2EB, 0xB001, 0xB2EC, 0xB002, 0x8579, 0xB003, 0x857A, + 0xB004, 0xB2ED, 0xB005, 0x8581, 0xB006, 0x8582, 0xB007, 0x8583, 0xB008, 0x8584, 0xB009, 0x8585, 0xB00A, 0x8586, 0xB00B, 0x8587, + 0xB00C, 0xB2EE, 0xB00D, 0x8588, 0xB00E, 0x8589, 0xB00F, 0x858A, 0xB010, 0xB2EF, 0xB011, 0x858B, 0xB012, 0x858C, 0xB013, 0x858D, + 0xB014, 0xB2F0, 0xB015, 0x858E, 0xB016, 0x858F, 0xB017, 0x8590, 0xB018, 0x8591, 0xB019, 0x8592, 0xB01A, 0x8593, 0xB01B, 0x8594, + 0xB01C, 0xB2F1, 0xB01D, 0xB2F2, 0xB01E, 0x8595, 0xB01F, 0x8596, 0xB020, 0x8597, 0xB021, 0x8598, 0xB022, 0x8599, 0xB023, 0x859A, + 0xB024, 0x859B, 0xB025, 0x859C, 0xB026, 0x859D, 0xB027, 0x859E, 0xB028, 0xB2F3, 0xB029, 0x859F, 0xB02A, 0x85A0, 0xB02B, 0x85A1, + 0xB02C, 0x85A2, 0xB02D, 0x85A3, 0xB02E, 0x85A4, 0xB02F, 0x85A5, 0xB030, 0x85A6, 0xB031, 0x85A7, 0xB032, 0x85A8, 0xB033, 0x85A9, + 0xB034, 0x85AA, 0xB035, 0x85AB, 0xB036, 0x85AC, 0xB037, 0x85AD, 0xB038, 0x85AE, 0xB039, 0x85AF, 0xB03A, 0x85B0, 0xB03B, 0x85B1, + 0xB03C, 0x85B2, 0xB03D, 0x85B3, 0xB03E, 0x85B4, 0xB03F, 0x85B5, 0xB040, 0x85B6, 0xB041, 0x85B7, 0xB042, 0x85B8, 0xB043, 0x85B9, + 0xB044, 0xB2F4, 0xB045, 0xB2F5, 0xB046, 0x85BA, 0xB047, 0x85BB, 0xB048, 0xB2F6, 0xB049, 0x85BC, 0xB04A, 0xB2F7, 0xB04B, 0x85BD, + 0xB04C, 0xB2F8, 0xB04D, 0x85BE, 0xB04E, 0xB2F9, 0xB04F, 0x85BF, 0xB050, 0x85C0, 0xB051, 0x85C1, 0xB052, 0x85C2, 0xB053, 0xB2FA, + 0xB054, 0xB2FB, 0xB055, 0xB2FC, 0xB056, 0x85C3, 0xB057, 0xB2FD, 0xB058, 0x85C4, 0xB059, 0xB2FE, 0xB05A, 0x85C5, 0xB05B, 0x85C6, + 0xB05C, 0x85C7, 0xB05D, 0xB3A1, 0xB05E, 0x85C8, 0xB05F, 0x85C9, 0xB060, 0x85CA, 0xB061, 0x85CB, 0xB062, 0x85CC, 0xB063, 0x85CD, + 0xB064, 0x85CE, 0xB065, 0x85CF, 0xB066, 0x85D0, 0xB067, 0x85D1, 0xB068, 0x85D2, 0xB069, 0x85D3, 0xB06A, 0x85D4, 0xB06B, 0x85D5, + 0xB06C, 0x85D6, 0xB06D, 0x85D7, 0xB06E, 0x85D8, 0xB06F, 0x85D9, 0xB070, 0x85DA, 0xB071, 0x85DB, 0xB072, 0x85DC, 0xB073, 0x85DD, + 0xB074, 0x85DE, 0xB075, 0x85DF, 0xB076, 0x85E0, 0xB077, 0x85E1, 0xB078, 0x85E2, 0xB079, 0x85E3, 0xB07A, 0x85E4, 0xB07B, 0x85E5, + 0xB07C, 0xB3A2, 0xB07D, 0xB3A3, 0xB07E, 0x85E6, 0xB07F, 0x85E7, 0xB080, 0xB3A4, 0xB081, 0x85E8, 0xB082, 0x85E9, 0xB083, 0x85EA, + 0xB084, 0xB3A5, 0xB085, 0x85EB, 0xB086, 0x85EC, 0xB087, 0x85ED, 0xB088, 0x85EE, 0xB089, 0x85EF, 0xB08A, 0x85F0, 0xB08B, 0x85F1, + 0xB08C, 0xB3A6, 0xB08D, 0xB3A7, 0xB08E, 0x85F2, 0xB08F, 0xB3A8, 0xB090, 0x85F3, 0xB091, 0xB3A9, 0xB092, 0x85F4, 0xB093, 0x85F5, + 0xB094, 0x85F6, 0xB095, 0x85F7, 0xB096, 0x85F8, 0xB097, 0x85F9, 0xB098, 0xB3AA, 0xB099, 0xB3AB, 0xB09A, 0xB3AC, 0xB09B, 0x85FA, + 0xB09C, 0xB3AD, 0xB09D, 0x85FB, 0xB09E, 0x85FC, 0xB09F, 0xB3AE, 0xB0A0, 0xB3AF, 0xB0A1, 0xB3B0, 0xB0A2, 0xB3B1, 0xB0A3, 0x85FD, + 0xB0A4, 0x85FE, 0xB0A5, 0x8641, 0xB0A6, 0x8642, 0xB0A7, 0x8643, 0xB0A8, 0xB3B2, 0xB0A9, 0xB3B3, 0xB0AA, 0x8644, 0xB0AB, 0xB3B4, + 0xB0AC, 0xB3B5, 0xB0AD, 0xB3B6, 0xB0AE, 0xB3B7, 0xB0AF, 0xB3B8, 0xB0B0, 0x8645, 0xB0B1, 0xB3B9, 0xB0B2, 0x8646, 0xB0B3, 0xB3BA, + 0xB0B4, 0xB3BB, 0xB0B5, 0xB3BC, 0xB0B6, 0x8647, 0xB0B7, 0x8648, 0xB0B8, 0xB3BD, 0xB0B9, 0x8649, 0xB0BA, 0x864A, 0xB0BB, 0x864B, + 0xB0BC, 0xB3BE, 0xB0BD, 0x864C, 0xB0BE, 0x864D, 0xB0BF, 0x864E, 0xB0C0, 0x864F, 0xB0C1, 0x8650, 0xB0C2, 0x8651, 0xB0C3, 0x8652, + 0xB0C4, 0xB3BF, 0xB0C5, 0xB3C0, 0xB0C6, 0x8653, 0xB0C7, 0xB3C1, 0xB0C8, 0xB3C2, 0xB0C9, 0xB3C3, 0xB0CA, 0x8654, 0xB0CB, 0x8655, + 0xB0CC, 0x8656, 0xB0CD, 0x8657, 0xB0CE, 0x8658, 0xB0CF, 0x8659, 0xB0D0, 0xB3C4, 0xB0D1, 0xB3C5, 0xB0D2, 0x865A, 0xB0D3, 0x8661, + 0xB0D4, 0xB3C6, 0xB0D5, 0x8662, 0xB0D6, 0x8663, 0xB0D7, 0x8664, 0xB0D8, 0xB3C7, 0xB0D9, 0x8665, 0xB0DA, 0x8666, 0xB0DB, 0x8667, + 0xB0DC, 0x8668, 0xB0DD, 0x8669, 0xB0DE, 0x866A, 0xB0DF, 0x866B, 0xB0E0, 0xB3C8, 0xB0E1, 0x866C, 0xB0E2, 0x866D, 0xB0E3, 0x866E, + 0xB0E4, 0x866F, 0xB0E5, 0xB3C9, 0xB0E6, 0x8670, 0xB0E7, 0x8671, 0xB0E8, 0x8672, 0xB0E9, 0x8673, 0xB0EA, 0x8674, 0xB0EB, 0x8675, + 0xB0EC, 0x8676, 0xB0ED, 0x8677, 0xB0EE, 0x8678, 0xB0EF, 0x8679, 0xB0F0, 0x867A, 0xB0F1, 0x8681, 0xB0F2, 0x8682, 0xB0F3, 0x8683, + 0xB0F4, 0x8684, 0xB0F5, 0x8685, 0xB0F6, 0x8686, 0xB0F7, 0x8687, 0xB0F8, 0x8688, 0xB0F9, 0x8689, 0xB0FA, 0x868A, 0xB0FB, 0x868B, + 0xB0FC, 0x868C, 0xB0FD, 0x868D, 0xB0FE, 0x868E, 0xB0FF, 0x868F, 0xB100, 0x8690, 0xB101, 0x8691, 0xB102, 0x8692, 0xB103, 0x8693, + 0xB104, 0x8694, 0xB105, 0x8695, 0xB106, 0x8696, 0xB107, 0x8697, 0xB108, 0xB3CA, 0xB109, 0xB3CB, 0xB10A, 0x8698, 0xB10B, 0xB3CC, + 0xB10C, 0xB3CD, 0xB10D, 0x8699, 0xB10E, 0x869A, 0xB10F, 0x869B, 0xB110, 0xB3CE, 0xB111, 0x869C, 0xB112, 0xB3CF, 0xB113, 0xB3D0, + 0xB114, 0x869D, 0xB115, 0x869E, 0xB116, 0x869F, 0xB117, 0x86A0, 0xB118, 0xB3D1, 0xB119, 0xB3D2, 0xB11A, 0x86A1, 0xB11B, 0xB3D3, + 0xB11C, 0xB3D4, 0xB11D, 0xB3D5, 0xB11E, 0x86A2, 0xB11F, 0x86A3, 0xB120, 0x86A4, 0xB121, 0x86A5, 0xB122, 0x86A6, 0xB123, 0xB3D6, + 0xB124, 0xB3D7, 0xB125, 0xB3D8, 0xB126, 0x86A7, 0xB127, 0x86A8, 0xB128, 0xB3D9, 0xB129, 0x86A9, 0xB12A, 0x86AA, 0xB12B, 0x86AB, + 0xB12C, 0xB3DA, 0xB12D, 0x86AC, 0xB12E, 0x86AD, 0xB12F, 0x86AE, 0xB130, 0x86AF, 0xB131, 0x86B0, 0xB132, 0x86B1, 0xB133, 0x86B2, + 0xB134, 0xB3DB, 0xB135, 0xB3DC, 0xB136, 0x86B3, 0xB137, 0xB3DD, 0xB138, 0xB3DE, 0xB139, 0xB3DF, 0xB13A, 0x86B4, 0xB13B, 0x86B5, + 0xB13C, 0x86B6, 0xB13D, 0x86B7, 0xB13E, 0x86B8, 0xB13F, 0x86B9, 0xB140, 0xB3E0, 0xB141, 0xB3E1, 0xB142, 0x86BA, 0xB143, 0x86BB, + 0xB144, 0xB3E2, 0xB145, 0x86BC, 0xB146, 0x86BD, 0xB147, 0x86BE, 0xB148, 0xB3E3, 0xB149, 0x86BF, 0xB14A, 0x86C0, 0xB14B, 0x86C1, + 0xB14C, 0x86C2, 0xB14D, 0x86C3, 0xB14E, 0x86C4, 0xB14F, 0x86C5, 0xB150, 0xB3E4, 0xB151, 0xB3E5, 0xB152, 0x86C6, 0xB153, 0x86C7, + 0xB154, 0xB3E6, 0xB155, 0xB3E7, 0xB156, 0x86C8, 0xB157, 0x86C9, 0xB158, 0xB3E8, 0xB159, 0x86CA, 0xB15A, 0x86CB, 0xB15B, 0x86CC, + 0xB15C, 0xB3E9, 0xB15D, 0x86CD, 0xB15E, 0x86CE, 0xB15F, 0x86CF, 0xB160, 0xB3EA, 0xB161, 0x86D0, 0xB162, 0x86D1, 0xB163, 0x86D2, + 0xB164, 0x86D3, 0xB165, 0x86D4, 0xB166, 0x86D5, 0xB167, 0x86D6, 0xB168, 0x86D7, 0xB169, 0x86D8, 0xB16A, 0x86D9, 0xB16B, 0x86DA, + 0xB16C, 0x86DB, 0xB16D, 0x86DC, 0xB16E, 0x86DD, 0xB16F, 0x86DE, 0xB170, 0x86DF, 0xB171, 0x86E0, 0xB172, 0x86E1, 0xB173, 0x86E2, + 0xB174, 0x86E3, 0xB175, 0x86E4, 0xB176, 0x86E5, 0xB177, 0x86E6, 0xB178, 0xB3EB, 0xB179, 0xB3EC, 0xB17A, 0x86E7, 0xB17B, 0x86E8, + 0xB17C, 0xB3ED, 0xB17D, 0x86E9, 0xB17E, 0x86EA, 0xB17F, 0x86EB, 0xB180, 0xB3EE, 0xB181, 0x86EC, 0xB182, 0xB3EF, 0xB183, 0x86ED, + 0xB184, 0x86EE, 0xB185, 0x86EF, 0xB186, 0x86F0, 0xB187, 0x86F1, 0xB188, 0xB3F0, 0xB189, 0xB3F1, 0xB18A, 0x86F2, 0xB18B, 0xB3F2, + 0xB18C, 0x86F3, 0xB18D, 0xB3F3, 0xB18E, 0x86F4, 0xB18F, 0x86F5, 0xB190, 0x86F6, 0xB191, 0x86F7, 0xB192, 0xB3F4, 0xB193, 0xB3F5, + 0xB194, 0xB3F6, 0xB195, 0x86F8, 0xB196, 0x86F9, 0xB197, 0x86FA, 0xB198, 0xB3F7, 0xB199, 0x86FB, 0xB19A, 0x86FC, 0xB19B, 0x86FD, + 0xB19C, 0xB3F8, 0xB19D, 0x86FE, 0xB19E, 0x8741, 0xB19F, 0x8742, 0xB1A0, 0x8743, 0xB1A1, 0x8744, 0xB1A2, 0x8745, 0xB1A3, 0x8746, + 0xB1A4, 0x8747, 0xB1A5, 0x8748, 0xB1A6, 0x8749, 0xB1A7, 0x874A, 0xB1A8, 0xB3F9, 0xB1A9, 0x874B, 0xB1AA, 0x874C, 0xB1AB, 0x874D, + 0xB1AC, 0x874E, 0xB1AD, 0x874F, 0xB1AE, 0x8750, 0xB1AF, 0x8751, 0xB1B0, 0x8752, 0xB1B1, 0x8753, 0xB1B2, 0x8754, 0xB1B3, 0x8755, + 0xB1B4, 0x8756, 0xB1B5, 0x8757, 0xB1B6, 0x8758, 0xB1B7, 0x8759, 0xB1B8, 0x875A, 0xB1B9, 0x8761, 0xB1BA, 0x8762, 0xB1BB, 0x8763, + 0xB1BC, 0x8764, 0xB1BD, 0x8765, 0xB1BE, 0x8766, 0xB1BF, 0x8767, 0xB1C0, 0x8768, 0xB1C1, 0x8769, 0xB1C2, 0x876A, 0xB1C3, 0x876B, + 0xB1C4, 0x876C, 0xB1C5, 0x876D, 0xB1C6, 0x876E, 0xB1C7, 0x876F, 0xB1C8, 0x8770, 0xB1C9, 0x8771, 0xB1CA, 0x8772, 0xB1CB, 0x8773, + 0xB1CC, 0xB3FA, 0xB1CD, 0x8774, 0xB1CE, 0x8775, 0xB1CF, 0x8776, 0xB1D0, 0xB3FB, 0xB1D1, 0x8777, 0xB1D2, 0x8778, 0xB1D3, 0x8779, + 0xB1D4, 0xB3FC, 0xB1D5, 0x877A, 0xB1D6, 0x8781, 0xB1D7, 0x8782, 0xB1D8, 0x8783, 0xB1D9, 0x8784, 0xB1DA, 0x8785, 0xB1DB, 0x8786, + 0xB1DC, 0xB3FD, 0xB1DD, 0xB3FE, 0xB1DE, 0x8787, 0xB1DF, 0xB4A1, 0xB1E0, 0x8788, 0xB1E1, 0x8789, 0xB1E2, 0x878A, 0xB1E3, 0x878B, + 0xB1E4, 0x878C, 0xB1E5, 0x878D, 0xB1E6, 0x878E, 0xB1E7, 0x878F, 0xB1E8, 0xB4A2, 0xB1E9, 0xB4A3, 0xB1EA, 0x8790, 0xB1EB, 0x8791, + 0xB1EC, 0xB4A4, 0xB1ED, 0x8792, 0xB1EE, 0x8793, 0xB1EF, 0x8794, 0xB1F0, 0xB4A5, 0xB1F1, 0x8795, 0xB1F2, 0x8796, 0xB1F3, 0x8797, + 0xB1F4, 0x8798, 0xB1F5, 0x8799, 0xB1F6, 0x879A, 0xB1F7, 0x879B, 0xB1F8, 0x879C, 0xB1F9, 0xB4A6, 0xB1FA, 0x879D, 0xB1FB, 0xB4A7, + 0xB1FC, 0x879E, 0xB1FD, 0xB4A8, 0xB1FE, 0x879F, 0xB1FF, 0x87A0, 0xB200, 0x87A1, 0xB201, 0x87A2, 0xB202, 0x87A3, 0xB203, 0x87A4, + 0xB204, 0xB4A9, 0xB205, 0xB4AA, 0xB206, 0x87A5, 0xB207, 0x87A6, 0xB208, 0xB4AB, 0xB209, 0x87A7, 0xB20A, 0x87A8, 0xB20B, 0xB4AC, + 0xB20C, 0xB4AD, 0xB20D, 0x87A9, 0xB20E, 0x87AA, 0xB20F, 0x87AB, 0xB210, 0x87AC, 0xB211, 0x87AD, 0xB212, 0x87AE, 0xB213, 0x87AF, + 0xB214, 0xB4AE, 0xB215, 0xB4AF, 0xB216, 0x87B0, 0xB217, 0xB4B0, 0xB218, 0x87B1, 0xB219, 0xB4B1, 0xB21A, 0x87B2, 0xB21B, 0x87B3, + 0xB21C, 0x87B4, 0xB21D, 0x87B5, 0xB21E, 0x87B6, 0xB21F, 0x87B7, 0xB220, 0xB4B2, 0xB221, 0x87B8, 0xB222, 0x87B9, 0xB223, 0x87BA, + 0xB224, 0x87BB, 0xB225, 0x87BC, 0xB226, 0x87BD, 0xB227, 0x87BE, 0xB228, 0x87BF, 0xB229, 0x87C0, 0xB22A, 0x87C1, 0xB22B, 0x87C2, + 0xB22C, 0x87C3, 0xB22D, 0x87C4, 0xB22E, 0x87C5, 0xB22F, 0x87C6, 0xB230, 0x87C7, 0xB231, 0x87C8, 0xB232, 0x87C9, 0xB233, 0x87CA, + 0xB234, 0xB4B3, 0xB235, 0x87CB, 0xB236, 0x87CC, 0xB237, 0x87CD, 0xB238, 0x87CE, 0xB239, 0x87CF, 0xB23A, 0x87D0, 0xB23B, 0x87D1, + 0xB23C, 0xB4B4, 0xB23D, 0x87D2, 0xB23E, 0x87D3, 0xB23F, 0x87D4, 0xB240, 0x87D5, 0xB241, 0x87D6, 0xB242, 0x87D7, 0xB243, 0x87D8, + 0xB244, 0x87D9, 0xB245, 0x87DA, 0xB246, 0x87DB, 0xB247, 0x87DC, 0xB248, 0x87DD, 0xB249, 0x87DE, 0xB24A, 0x87DF, 0xB24B, 0x87E0, + 0xB24C, 0x87E1, 0xB24D, 0x87E2, 0xB24E, 0x87E3, 0xB24F, 0x87E4, 0xB250, 0x87E5, 0xB251, 0x87E6, 0xB252, 0x87E7, 0xB253, 0x87E8, + 0xB254, 0x87E9, 0xB255, 0x87EA, 0xB256, 0x87EB, 0xB257, 0x87EC, 0xB258, 0xB4B5, 0xB259, 0x87ED, 0xB25A, 0x87EE, 0xB25B, 0x87EF, + 0xB25C, 0xB4B6, 0xB25D, 0x87F0, 0xB25E, 0x87F1, 0xB25F, 0x87F2, 0xB260, 0xB4B7, 0xB261, 0x87F3, 0xB262, 0x87F4, 0xB263, 0x87F5, + 0xB264, 0x87F6, 0xB265, 0x87F7, 0xB266, 0x87F8, 0xB267, 0x87F9, 0xB268, 0xB4B8, 0xB269, 0xB4B9, 0xB26A, 0x87FA, 0xB26B, 0x87FB, + 0xB26C, 0x87FC, 0xB26D, 0x87FD, 0xB26E, 0x87FE, 0xB26F, 0x8841, 0xB270, 0x8842, 0xB271, 0x8843, 0xB272, 0x8844, 0xB273, 0x8845, + 0xB274, 0xB4BA, 0xB275, 0xB4BB, 0xB276, 0x8846, 0xB277, 0x8847, 0xB278, 0x8848, 0xB279, 0x8849, 0xB27A, 0x884A, 0xB27B, 0x884B, + 0xB27C, 0xB4BC, 0xB27D, 0x884C, 0xB27E, 0x884D, 0xB27F, 0x884E, 0xB280, 0x884F, 0xB281, 0x8850, 0xB282, 0x8851, 0xB283, 0x8852, + 0xB284, 0xB4BD, 0xB285, 0xB4BE, 0xB286, 0x8853, 0xB287, 0x8854, 0xB288, 0x8855, 0xB289, 0xB4BF, 0xB28A, 0x8856, 0xB28B, 0x8857, + 0xB28C, 0x8858, 0xB28D, 0x8859, 0xB28E, 0x885A, 0xB28F, 0x8861, 0xB290, 0xB4C0, 0xB291, 0xB4C1, 0xB292, 0x8862, 0xB293, 0x8863, + 0xB294, 0xB4C2, 0xB295, 0x8864, 0xB296, 0x8865, 0xB297, 0x8866, 0xB298, 0xB4C3, 0xB299, 0xB4C4, 0xB29A, 0xB4C5, 0xB29B, 0x8867, + 0xB29C, 0x8868, 0xB29D, 0x8869, 0xB29E, 0x886A, 0xB29F, 0x886B, 0xB2A0, 0xB4C6, 0xB2A1, 0xB4C7, 0xB2A2, 0x886C, 0xB2A3, 0xB4C8, + 0xB2A4, 0x886D, 0xB2A5, 0xB4C9, 0xB2A6, 0xB4CA, 0xB2A7, 0x886E, 0xB2A8, 0x886F, 0xB2A9, 0x8870, 0xB2AA, 0xB4CB, 0xB2AB, 0x8871, + 0xB2AC, 0xB4CC, 0xB2AD, 0x8872, 0xB2AE, 0x8873, 0xB2AF, 0x8874, 0xB2B0, 0xB4CD, 0xB2B1, 0x8875, 0xB2B2, 0x8876, 0xB2B3, 0x8877, + 0xB2B4, 0xB4CE, 0xB2B5, 0x8878, 0xB2B6, 0x8879, 0xB2B7, 0x887A, 0xB2B8, 0x8881, 0xB2B9, 0x8882, 0xB2BA, 0x8883, 0xB2BB, 0x8884, + 0xB2BC, 0x8885, 0xB2BD, 0x8886, 0xB2BE, 0x8887, 0xB2BF, 0x8888, 0xB2C0, 0x8889, 0xB2C1, 0x888A, 0xB2C2, 0x888B, 0xB2C3, 0x888C, + 0xB2C4, 0x888D, 0xB2C5, 0x888E, 0xB2C6, 0x888F, 0xB2C7, 0x8890, 0xB2C8, 0xB4CF, 0xB2C9, 0xB4D0, 0xB2CA, 0x8891, 0xB2CB, 0x8892, + 0xB2CC, 0xB4D1, 0xB2CD, 0x8893, 0xB2CE, 0x8894, 0xB2CF, 0x8895, 0xB2D0, 0xB4D2, 0xB2D1, 0x8896, 0xB2D2, 0xB4D3, 0xB2D3, 0x8897, + 0xB2D4, 0x8898, 0xB2D5, 0x8899, 0xB2D6, 0x889A, 0xB2D7, 0x889B, 0xB2D8, 0xB4D4, 0xB2D9, 0xB4D5, 0xB2DA, 0x889C, 0xB2DB, 0xB4D6, + 0xB2DC, 0x889D, 0xB2DD, 0xB4D7, 0xB2DE, 0x889E, 0xB2DF, 0x889F, 0xB2E0, 0x88A0, 0xB2E1, 0x88A1, 0xB2E2, 0xB4D8, 0xB2E3, 0x88A2, + 0xB2E4, 0xB4D9, 0xB2E5, 0xB4DA, 0xB2E6, 0xB4DB, 0xB2E7, 0x88A3, 0xB2E8, 0xB4DC, 0xB2E9, 0x88A4, 0xB2EA, 0x88A5, 0xB2EB, 0xB4DD, + 0xB2EC, 0xB4DE, 0xB2ED, 0xB4DF, 0xB2EE, 0xB4E0, 0xB2EF, 0xB4E1, 0xB2F0, 0x88A6, 0xB2F1, 0x88A7, 0xB2F2, 0x88A8, 0xB2F3, 0xB4E2, + 0xB2F4, 0xB4E3, 0xB2F5, 0xB4E4, 0xB2F6, 0x88A9, 0xB2F7, 0xB4E5, 0xB2F8, 0xB4E6, 0xB2F9, 0xB4E7, 0xB2FA, 0xB4E8, 0xB2FB, 0xB4E9, + 0xB2FC, 0x88AA, 0xB2FD, 0x88AB, 0xB2FE, 0x88AC, 0xB2FF, 0xB4EA, 0xB300, 0xB4EB, 0xB301, 0xB4EC, 0xB302, 0x88AD, 0xB303, 0x88AE, + 0xB304, 0xB4ED, 0xB305, 0x88AF, 0xB306, 0x88B0, 0xB307, 0x88B1, 0xB308, 0xB4EE, 0xB309, 0x88B2, 0xB30A, 0x88B3, 0xB30B, 0x88B4, + 0xB30C, 0x88B5, 0xB30D, 0x88B6, 0xB30E, 0x88B7, 0xB30F, 0x88B8, 0xB310, 0xB4EF, 0xB311, 0xB4F0, 0xB312, 0x88B9, 0xB313, 0xB4F1, + 0xB314, 0xB4F2, 0xB315, 0xB4F3, 0xB316, 0x88BA, 0xB317, 0x88BB, 0xB318, 0x88BC, 0xB319, 0x88BD, 0xB31A, 0x88BE, 0xB31B, 0x88BF, + 0xB31C, 0xB4F4, 0xB31D, 0x88C0, 0xB31E, 0x88C1, 0xB31F, 0x88C2, 0xB320, 0x88C3, 0xB321, 0x88C4, 0xB322, 0x88C5, 0xB323, 0x88C6, + 0xB324, 0x88C7, 0xB325, 0x88C8, 0xB326, 0x88C9, 0xB327, 0x88CA, 0xB328, 0x88CB, 0xB329, 0x88CC, 0xB32A, 0x88CD, 0xB32B, 0x88CE, + 0xB32C, 0x88CF, 0xB32D, 0x88D0, 0xB32E, 0x88D1, 0xB32F, 0x88D2, 0xB330, 0x88D3, 0xB331, 0x88D4, 0xB332, 0x88D5, 0xB333, 0x88D6, + 0xB334, 0x88D7, 0xB335, 0x88D8, 0xB336, 0x88D9, 0xB337, 0x88DA, 0xB338, 0x88DB, 0xB339, 0x88DC, 0xB33A, 0x88DD, 0xB33B, 0x88DE, + 0xB33C, 0x88DF, 0xB33D, 0x88E0, 0xB33E, 0x88E1, 0xB33F, 0x88E2, 0xB340, 0x88E3, 0xB341, 0x88E4, 0xB342, 0x88E5, 0xB343, 0x88E6, + 0xB344, 0x88E7, 0xB345, 0x88E8, 0xB346, 0x88E9, 0xB347, 0x88EA, 0xB348, 0x88EB, 0xB349, 0x88EC, 0xB34A, 0x88ED, 0xB34B, 0x88EE, + 0xB34C, 0x88EF, 0xB34D, 0x88F0, 0xB34E, 0x88F1, 0xB34F, 0x88F2, 0xB350, 0x88F3, 0xB351, 0x88F4, 0xB352, 0x88F5, 0xB353, 0x88F6, + 0xB354, 0xB4F5, 0xB355, 0xB4F6, 0xB356, 0xB4F7, 0xB357, 0x88F7, 0xB358, 0xB4F8, 0xB359, 0x88F8, 0xB35A, 0x88F9, 0xB35B, 0xB4F9, + 0xB35C, 0xB4FA, 0xB35D, 0x88FA, 0xB35E, 0xB4FB, 0xB35F, 0xB4FC, 0xB360, 0x88FB, 0xB361, 0x88FC, 0xB362, 0x88FD, 0xB363, 0x88FE, + 0xB364, 0xB4FD, 0xB365, 0xB4FE, 0xB366, 0x8941, 0xB367, 0xB5A1, 0xB368, 0x8942, 0xB369, 0xB5A2, 0xB36A, 0x8943, 0xB36B, 0xB5A3, + 0xB36C, 0x8944, 0xB36D, 0x8945, 0xB36E, 0xB5A4, 0xB36F, 0x8946, 0xB370, 0xB5A5, 0xB371, 0xB5A6, 0xB372, 0x8947, 0xB373, 0x8948, + 0xB374, 0xB5A7, 0xB375, 0x8949, 0xB376, 0x894A, 0xB377, 0x894B, 0xB378, 0xB5A8, 0xB379, 0x894C, 0xB37A, 0x894D, 0xB37B, 0x894E, + 0xB37C, 0x894F, 0xB37D, 0x8950, 0xB37E, 0x8951, 0xB37F, 0x8952, 0xB380, 0xB5A9, 0xB381, 0xB5AA, 0xB382, 0x8953, 0xB383, 0xB5AB, + 0xB384, 0xB5AC, 0xB385, 0xB5AD, 0xB386, 0x8954, 0xB387, 0x8955, 0xB388, 0x8956, 0xB389, 0x8957, 0xB38A, 0x8958, 0xB38B, 0x8959, + 0xB38C, 0xB5AE, 0xB38D, 0x895A, 0xB38E, 0x8961, 0xB38F, 0x8962, 0xB390, 0xB5AF, 0xB391, 0x8963, 0xB392, 0x8964, 0xB393, 0x8965, + 0xB394, 0xB5B0, 0xB395, 0x8966, 0xB396, 0x8967, 0xB397, 0x8968, 0xB398, 0x8969, 0xB399, 0x896A, 0xB39A, 0x896B, 0xB39B, 0x896C, + 0xB39C, 0x896D, 0xB39D, 0x896E, 0xB39E, 0x896F, 0xB39F, 0x8970, 0xB3A0, 0xB5B1, 0xB3A1, 0xB5B2, 0xB3A2, 0x8971, 0xB3A3, 0x8972, + 0xB3A4, 0x8973, 0xB3A5, 0x8974, 0xB3A6, 0x8975, 0xB3A7, 0x8976, 0xB3A8, 0xB5B3, 0xB3A9, 0x8977, 0xB3AA, 0x8978, 0xB3AB, 0x8979, + 0xB3AC, 0xB5B4, 0xB3AD, 0x897A, 0xB3AE, 0x8981, 0xB3AF, 0x8982, 0xB3B0, 0x8983, 0xB3B1, 0x8984, 0xB3B2, 0x8985, 0xB3B3, 0x8986, + 0xB3B4, 0x8987, 0xB3B5, 0x8988, 0xB3B6, 0x8989, 0xB3B7, 0x898A, 0xB3B8, 0x898B, 0xB3B9, 0x898C, 0xB3BA, 0x898D, 0xB3BB, 0x898E, + 0xB3BC, 0x898F, 0xB3BD, 0x8990, 0xB3BE, 0x8991, 0xB3BF, 0x8992, 0xB3C0, 0x8993, 0xB3C1, 0x8994, 0xB3C2, 0x8995, 0xB3C3, 0x8996, + 0xB3C4, 0xB5B5, 0xB3C5, 0xB5B6, 0xB3C6, 0x8997, 0xB3C7, 0x8998, 0xB3C8, 0xB5B7, 0xB3C9, 0x8999, 0xB3CA, 0x899A, 0xB3CB, 0xB5B8, + 0xB3CC, 0xB5B9, 0xB3CD, 0x899B, 0xB3CE, 0xB5BA, 0xB3CF, 0x899C, 0xB3D0, 0xB5BB, 0xB3D1, 0x899D, 0xB3D2, 0x899E, 0xB3D3, 0x899F, + 0xB3D4, 0xB5BC, 0xB3D5, 0xB5BD, 0xB3D6, 0x89A0, 0xB3D7, 0xB5BE, 0xB3D8, 0x89A1, 0xB3D9, 0xB5BF, 0xB3DA, 0x89A2, 0xB3DB, 0xB5C0, + 0xB3DC, 0x89A3, 0xB3DD, 0xB5C1, 0xB3DE, 0x89A4, 0xB3DF, 0x89A5, 0xB3E0, 0xB5C2, 0xB3E1, 0x89A6, 0xB3E2, 0x89A7, 0xB3E3, 0x89A8, + 0xB3E4, 0xB5C3, 0xB3E5, 0x89A9, 0xB3E6, 0x89AA, 0xB3E7, 0x89AB, 0xB3E8, 0xB5C4, 0xB3E9, 0x89AC, 0xB3EA, 0x89AD, 0xB3EB, 0x89AE, + 0xB3EC, 0x89AF, 0xB3ED, 0x89B0, 0xB3EE, 0x89B1, 0xB3EF, 0x89B2, 0xB3F0, 0x89B3, 0xB3F1, 0x89B4, 0xB3F2, 0x89B5, 0xB3F3, 0x89B6, + 0xB3F4, 0x89B7, 0xB3F5, 0x89B8, 0xB3F6, 0x89B9, 0xB3F7, 0x89BA, 0xB3F8, 0x89BB, 0xB3F9, 0x89BC, 0xB3FA, 0x89BD, 0xB3FB, 0x89BE, + 0xB3FC, 0xB5C5, 0xB3FD, 0x89BF, 0xB3FE, 0x89C0, 0xB3FF, 0x89C1, 0xB400, 0x89C2, 0xB401, 0x89C3, 0xB402, 0x89C4, 0xB403, 0x89C5, + 0xB404, 0x89C6, 0xB405, 0x89C7, 0xB406, 0x89C8, 0xB407, 0x89C9, 0xB408, 0x89CA, 0xB409, 0x89CB, 0xB40A, 0x89CC, 0xB40B, 0x89CD, + 0xB40C, 0x89CE, 0xB40D, 0x89CF, 0xB40E, 0x89D0, 0xB40F, 0x89D1, 0xB410, 0xB5C6, 0xB411, 0x89D2, 0xB412, 0x89D3, 0xB413, 0x89D4, + 0xB414, 0x89D5, 0xB415, 0x89D6, 0xB416, 0x89D7, 0xB417, 0x89D8, 0xB418, 0xB5C7, 0xB419, 0x89D9, 0xB41A, 0x89DA, 0xB41B, 0x89DB, + 0xB41C, 0xB5C8, 0xB41D, 0x89DC, 0xB41E, 0x89DD, 0xB41F, 0x89DE, 0xB420, 0xB5C9, 0xB421, 0x89DF, 0xB422, 0x89E0, 0xB423, 0x89E1, + 0xB424, 0x89E2, 0xB425, 0x89E3, 0xB426, 0x89E4, 0xB427, 0x89E5, 0xB428, 0xB5CA, 0xB429, 0xB5CB, 0xB42A, 0x89E6, 0xB42B, 0xB5CC, + 0xB42C, 0x89E7, 0xB42D, 0x89E8, 0xB42E, 0x89E9, 0xB42F, 0x89EA, 0xB430, 0x89EB, 0xB431, 0x89EC, 0xB432, 0x89ED, 0xB433, 0x89EE, + 0xB434, 0xB5CD, 0xB435, 0x89EF, 0xB436, 0x89F0, 0xB437, 0x89F1, 0xB438, 0x89F2, 0xB439, 0x89F3, 0xB43A, 0x89F4, 0xB43B, 0x89F5, + 0xB43C, 0x89F6, 0xB43D, 0x89F7, 0xB43E, 0x89F8, 0xB43F, 0x89F9, 0xB440, 0x89FA, 0xB441, 0x89FB, 0xB442, 0x89FC, 0xB443, 0x89FD, + 0xB444, 0x89FE, 0xB445, 0x8A41, 0xB446, 0x8A42, 0xB447, 0x8A43, 0xB448, 0x8A44, 0xB449, 0x8A45, 0xB44A, 0x8A46, 0xB44B, 0x8A47, + 0xB44C, 0x8A48, 0xB44D, 0x8A49, 0xB44E, 0x8A4A, 0xB44F, 0x8A4B, 0xB450, 0xB5CE, 0xB451, 0xB5CF, 0xB452, 0x8A4C, 0xB453, 0x8A4D, + 0xB454, 0xB5D0, 0xB455, 0x8A4E, 0xB456, 0x8A4F, 0xB457, 0x8A50, 0xB458, 0xB5D1, 0xB459, 0x8A51, 0xB45A, 0x8A52, 0xB45B, 0x8A53, + 0xB45C, 0x8A54, 0xB45D, 0x8A55, 0xB45E, 0x8A56, 0xB45F, 0x8A57, 0xB460, 0xB5D2, 0xB461, 0xB5D3, 0xB462, 0x8A58, 0xB463, 0xB5D4, + 0xB464, 0x8A59, 0xB465, 0xB5D5, 0xB466, 0x8A5A, 0xB467, 0x8A61, 0xB468, 0x8A62, 0xB469, 0x8A63, 0xB46A, 0x8A64, 0xB46B, 0x8A65, + 0xB46C, 0xB5D6, 0xB46D, 0x8A66, 0xB46E, 0x8A67, 0xB46F, 0x8A68, 0xB470, 0x8A69, 0xB471, 0x8A6A, 0xB472, 0x8A6B, 0xB473, 0x8A6C, + 0xB474, 0x8A6D, 0xB475, 0x8A6E, 0xB476, 0x8A6F, 0xB477, 0x8A70, 0xB478, 0x8A71, 0xB479, 0x8A72, 0xB47A, 0x8A73, 0xB47B, 0x8A74, + 0xB47C, 0x8A75, 0xB47D, 0x8A76, 0xB47E, 0x8A77, 0xB47F, 0x8A78, 0xB480, 0xB5D7, 0xB481, 0x8A79, 0xB482, 0x8A7A, 0xB483, 0x8A81, + 0xB484, 0x8A82, 0xB485, 0x8A83, 0xB486, 0x8A84, 0xB487, 0x8A85, 0xB488, 0xB5D8, 0xB489, 0x8A86, 0xB48A, 0x8A87, 0xB48B, 0x8A88, + 0xB48C, 0x8A89, 0xB48D, 0x8A8A, 0xB48E, 0x8A8B, 0xB48F, 0x8A8C, 0xB490, 0x8A8D, 0xB491, 0x8A8E, 0xB492, 0x8A8F, 0xB493, 0x8A90, + 0xB494, 0x8A91, 0xB495, 0x8A92, 0xB496, 0x8A93, 0xB497, 0x8A94, 0xB498, 0x8A95, 0xB499, 0x8A96, 0xB49A, 0x8A97, 0xB49B, 0x8A98, + 0xB49C, 0x8A99, 0xB49D, 0xB5D9, 0xB49E, 0x8A9A, 0xB49F, 0x8A9B, 0xB4A0, 0x8A9C, 0xB4A1, 0x8A9D, 0xB4A2, 0x8A9E, 0xB4A3, 0x8A9F, + 0xB4A4, 0xB5DA, 0xB4A5, 0x8AA0, 0xB4A6, 0x8AA1, 0xB4A7, 0x8AA2, 0xB4A8, 0xB5DB, 0xB4A9, 0x8AA3, 0xB4AA, 0x8AA4, 0xB4AB, 0x8AA5, + 0xB4AC, 0xB5DC, 0xB4AD, 0x8AA6, 0xB4AE, 0x8AA7, 0xB4AF, 0x8AA8, 0xB4B0, 0x8AA9, 0xB4B1, 0x8AAA, 0xB4B2, 0x8AAB, 0xB4B3, 0x8AAC, + 0xB4B4, 0x8AAD, 0xB4B5, 0xB5DD, 0xB4B6, 0x8AAE, 0xB4B7, 0xB5DE, 0xB4B8, 0x8AAF, 0xB4B9, 0xB5DF, 0xB4BA, 0x8AB0, 0xB4BB, 0x8AB1, + 0xB4BC, 0x8AB2, 0xB4BD, 0x8AB3, 0xB4BE, 0x8AB4, 0xB4BF, 0x8AB5, 0xB4C0, 0xB5E0, 0xB4C1, 0x8AB6, 0xB4C2, 0x8AB7, 0xB4C3, 0x8AB8, + 0xB4C4, 0xB5E1, 0xB4C5, 0x8AB9, 0xB4C6, 0x8ABA, 0xB4C7, 0x8ABB, 0xB4C8, 0xB5E2, 0xB4C9, 0x8ABC, 0xB4CA, 0x8ABD, 0xB4CB, 0x8ABE, + 0xB4CC, 0x8ABF, 0xB4CD, 0x8AC0, 0xB4CE, 0x8AC1, 0xB4CF, 0x8AC2, 0xB4D0, 0xB5E3, 0xB4D1, 0x8AC3, 0xB4D2, 0x8AC4, 0xB4D3, 0x8AC5, + 0xB4D4, 0x8AC6, 0xB4D5, 0xB5E4, 0xB4D6, 0x8AC7, 0xB4D7, 0x8AC8, 0xB4D8, 0x8AC9, 0xB4D9, 0x8ACA, 0xB4DA, 0x8ACB, 0xB4DB, 0x8ACC, + 0xB4DC, 0xB5E5, 0xB4DD, 0xB5E6, 0xB4DE, 0x8ACD, 0xB4DF, 0x8ACE, 0xB4E0, 0xB5E7, 0xB4E1, 0x8ACF, 0xB4E2, 0x8AD0, 0xB4E3, 0xB5E8, + 0xB4E4, 0xB5E9, 0xB4E5, 0x8AD1, 0xB4E6, 0xB5EA, 0xB4E7, 0x8AD2, 0xB4E8, 0x8AD3, 0xB4E9, 0x8AD4, 0xB4EA, 0x8AD5, 0xB4EB, 0x8AD6, + 0xB4EC, 0xB5EB, 0xB4ED, 0xB5EC, 0xB4EE, 0x8AD7, 0xB4EF, 0xB5ED, 0xB4F0, 0x8AD8, 0xB4F1, 0xB5EE, 0xB4F2, 0x8AD9, 0xB4F3, 0x8ADA, + 0xB4F4, 0x8ADB, 0xB4F5, 0x8ADC, 0xB4F6, 0x8ADD, 0xB4F7, 0x8ADE, 0xB4F8, 0xB5EF, 0xB4F9, 0x8ADF, 0xB4FA, 0x8AE0, 0xB4FB, 0x8AE1, + 0xB4FC, 0x8AE2, 0xB4FD, 0x8AE3, 0xB4FE, 0x8AE4, 0xB4FF, 0x8AE5, 0xB500, 0x8AE6, 0xB501, 0x8AE7, 0xB502, 0x8AE8, 0xB503, 0x8AE9, + 0xB504, 0x8AEA, 0xB505, 0x8AEB, 0xB506, 0x8AEC, 0xB507, 0x8AED, 0xB508, 0x8AEE, 0xB509, 0x8AEF, 0xB50A, 0x8AF0, 0xB50B, 0x8AF1, + 0xB50C, 0x8AF2, 0xB50D, 0x8AF3, 0xB50E, 0x8AF4, 0xB50F, 0x8AF5, 0xB510, 0x8AF6, 0xB511, 0x8AF7, 0xB512, 0x8AF8, 0xB513, 0x8AF9, + 0xB514, 0xB5F0, 0xB515, 0xB5F1, 0xB516, 0x8AFA, 0xB517, 0x8AFB, 0xB518, 0xB5F2, 0xB519, 0x8AFC, 0xB51A, 0x8AFD, 0xB51B, 0xB5F3, + 0xB51C, 0xB5F4, 0xB51D, 0x8AFE, 0xB51E, 0x8B41, 0xB51F, 0x8B42, 0xB520, 0x8B43, 0xB521, 0x8B44, 0xB522, 0x8B45, 0xB523, 0x8B46, + 0xB524, 0xB5F5, 0xB525, 0xB5F6, 0xB526, 0x8B47, 0xB527, 0xB5F7, 0xB528, 0xB5F8, 0xB529, 0xB5F9, 0xB52A, 0xB5FA, 0xB52B, 0x8B48, + 0xB52C, 0x8B49, 0xB52D, 0x8B4A, 0xB52E, 0x8B4B, 0xB52F, 0x8B4C, 0xB530, 0xB5FB, 0xB531, 0xB5FC, 0xB532, 0x8B4D, 0xB533, 0x8B4E, + 0xB534, 0xB5FD, 0xB535, 0x8B4F, 0xB536, 0x8B50, 0xB537, 0x8B51, 0xB538, 0xB5FE, 0xB539, 0x8B52, 0xB53A, 0x8B53, 0xB53B, 0x8B54, + 0xB53C, 0x8B55, 0xB53D, 0x8B56, 0xB53E, 0x8B57, 0xB53F, 0x8B58, 0xB540, 0xB6A1, 0xB541, 0xB6A2, 0xB542, 0x8B59, 0xB543, 0xB6A3, + 0xB544, 0xB6A4, 0xB545, 0xB6A5, 0xB546, 0x8B5A, 0xB547, 0x8B61, 0xB548, 0x8B62, 0xB549, 0x8B63, 0xB54A, 0x8B64, 0xB54B, 0xB6A6, + 0xB54C, 0xB6A7, 0xB54D, 0xB6A8, 0xB54E, 0x8B65, 0xB54F, 0x8B66, 0xB550, 0xB6A9, 0xB551, 0x8B67, 0xB552, 0x8B68, 0xB553, 0x8B69, + 0xB554, 0xB6AA, 0xB555, 0x8B6A, 0xB556, 0x8B6B, 0xB557, 0x8B6C, 0xB558, 0x8B6D, 0xB559, 0x8B6E, 0xB55A, 0x8B6F, 0xB55B, 0x8B70, + 0xB55C, 0xB6AB, 0xB55D, 0xB6AC, 0xB55E, 0x8B71, 0xB55F, 0xB6AD, 0xB560, 0xB6AE, 0xB561, 0xB6AF, 0xB562, 0x8B72, 0xB563, 0x8B73, + 0xB564, 0x8B74, 0xB565, 0x8B75, 0xB566, 0x8B76, 0xB567, 0x8B77, 0xB568, 0x8B78, 0xB569, 0x8B79, 0xB56A, 0x8B7A, 0xB56B, 0x8B81, + 0xB56C, 0x8B82, 0xB56D, 0x8B83, 0xB56E, 0x8B84, 0xB56F, 0x8B85, 0xB570, 0x8B86, 0xB571, 0x8B87, 0xB572, 0x8B88, 0xB573, 0x8B89, + 0xB574, 0x8B8A, 0xB575, 0x8B8B, 0xB576, 0x8B8C, 0xB577, 0x8B8D, 0xB578, 0x8B8E, 0xB579, 0x8B8F, 0xB57A, 0x8B90, 0xB57B, 0x8B91, + 0xB57C, 0x8B92, 0xB57D, 0x8B93, 0xB57E, 0x8B94, 0xB57F, 0x8B95, 0xB580, 0x8B96, 0xB581, 0x8B97, 0xB582, 0x8B98, 0xB583, 0x8B99, + 0xB584, 0x8B9A, 0xB585, 0x8B9B, 0xB586, 0x8B9C, 0xB587, 0x8B9D, 0xB588, 0x8B9E, 0xB589, 0x8B9F, 0xB58A, 0x8BA0, 0xB58B, 0x8BA1, + 0xB58C, 0x8BA2, 0xB58D, 0x8BA3, 0xB58E, 0x8BA4, 0xB58F, 0x8BA5, 0xB590, 0x8BA6, 0xB591, 0x8BA7, 0xB592, 0x8BA8, 0xB593, 0x8BA9, + 0xB594, 0x8BAA, 0xB595, 0x8BAB, 0xB596, 0x8BAC, 0xB597, 0x8BAD, 0xB598, 0x8BAE, 0xB599, 0x8BAF, 0xB59A, 0x8BB0, 0xB59B, 0x8BB1, + 0xB59C, 0x8BB2, 0xB59D, 0x8BB3, 0xB59E, 0x8BB4, 0xB59F, 0x8BB5, 0xB5A0, 0xB6B0, 0xB5A1, 0xB6B1, 0xB5A2, 0x8BB6, 0xB5A3, 0x8BB7, + 0xB5A4, 0xB6B2, 0xB5A5, 0x8BB8, 0xB5A6, 0x8BB9, 0xB5A7, 0x8BBA, 0xB5A8, 0xB6B3, 0xB5A9, 0x8BBB, 0xB5AA, 0xB6B4, 0xB5AB, 0xB6B5, + 0xB5AC, 0x8BBC, 0xB5AD, 0x8BBD, 0xB5AE, 0x8BBE, 0xB5AF, 0x8BBF, 0xB5B0, 0xB6B6, 0xB5B1, 0xB6B7, 0xB5B2, 0x8BC0, 0xB5B3, 0xB6B8, + 0xB5B4, 0xB6B9, 0xB5B5, 0xB6BA, 0xB5B6, 0x8BC1, 0xB5B7, 0x8BC2, 0xB5B8, 0x8BC3, 0xB5B9, 0x8BC4, 0xB5BA, 0x8BC5, 0xB5BB, 0xB6BB, + 0xB5BC, 0xB6BC, 0xB5BD, 0xB6BD, 0xB5BE, 0x8BC6, 0xB5BF, 0x8BC7, 0xB5C0, 0xB6BE, 0xB5C1, 0x8BC8, 0xB5C2, 0x8BC9, 0xB5C3, 0x8BCA, + 0xB5C4, 0xB6BF, 0xB5C5, 0x8BCB, 0xB5C6, 0x8BCC, 0xB5C7, 0x8BCD, 0xB5C8, 0x8BCE, 0xB5C9, 0x8BCF, 0xB5CA, 0x8BD0, 0xB5CB, 0x8BD1, + 0xB5CC, 0xB6C0, 0xB5CD, 0xB6C1, 0xB5CE, 0x8BD2, 0xB5CF, 0xB6C2, 0xB5D0, 0xB6C3, 0xB5D1, 0xB6C4, 0xB5D2, 0x8BD3, 0xB5D3, 0x8BD4, + 0xB5D4, 0x8BD5, 0xB5D5, 0x8BD6, 0xB5D6, 0x8BD7, 0xB5D7, 0x8BD8, 0xB5D8, 0xB6C5, 0xB5D9, 0x8BD9, 0xB5DA, 0x8BDA, 0xB5DB, 0x8BDB, + 0xB5DC, 0x8BDC, 0xB5DD, 0x8BDD, 0xB5DE, 0x8BDE, 0xB5DF, 0x8BDF, 0xB5E0, 0x8BE0, 0xB5E1, 0x8BE1, 0xB5E2, 0x8BE2, 0xB5E3, 0x8BE3, + 0xB5E4, 0x8BE4, 0xB5E5, 0x8BE5, 0xB5E6, 0x8BE6, 0xB5E7, 0x8BE7, 0xB5E8, 0x8BE8, 0xB5E9, 0x8BE9, 0xB5EA, 0x8BEA, 0xB5EB, 0x8BEB, + 0xB5EC, 0xB6C6, 0xB5ED, 0x8BEC, 0xB5EE, 0x8BED, 0xB5EF, 0x8BEE, 0xB5F0, 0x8BEF, 0xB5F1, 0x8BF0, 0xB5F2, 0x8BF1, 0xB5F3, 0x8BF2, + 0xB5F4, 0x8BF3, 0xB5F5, 0x8BF4, 0xB5F6, 0x8BF5, 0xB5F7, 0x8BF6, 0xB5F8, 0x8BF7, 0xB5F9, 0x8BF8, 0xB5FA, 0x8BF9, 0xB5FB, 0x8BFA, + 0xB5FC, 0x8BFB, 0xB5FD, 0x8BFC, 0xB5FE, 0x8BFD, 0xB5FF, 0x8BFE, 0xB600, 0x8C41, 0xB601, 0x8C42, 0xB602, 0x8C43, 0xB603, 0x8C44, + 0xB604, 0x8C45, 0xB605, 0x8C46, 0xB606, 0x8C47, 0xB607, 0x8C48, 0xB608, 0x8C49, 0xB609, 0x8C4A, 0xB60A, 0x8C4B, 0xB60B, 0x8C4C, + 0xB60C, 0x8C4D, 0xB60D, 0x8C4E, 0xB60E, 0x8C4F, 0xB60F, 0x8C50, 0xB610, 0xB6C7, 0xB611, 0xB6C8, 0xB612, 0x8C51, 0xB613, 0x8C52, + 0xB614, 0xB6C9, 0xB615, 0x8C53, 0xB616, 0x8C54, 0xB617, 0x8C55, 0xB618, 0xB6CA, 0xB619, 0x8C56, 0xB61A, 0x8C57, 0xB61B, 0x8C58, + 0xB61C, 0x8C59, 0xB61D, 0x8C5A, 0xB61E, 0x8C61, 0xB61F, 0x8C62, 0xB620, 0x8C63, 0xB621, 0x8C64, 0xB622, 0x8C65, 0xB623, 0x8C66, + 0xB624, 0x8C67, 0xB625, 0xB6CB, 0xB626, 0x8C68, 0xB627, 0x8C69, 0xB628, 0x8C6A, 0xB629, 0x8C6B, 0xB62A, 0x8C6C, 0xB62B, 0x8C6D, + 0xB62C, 0xB6CC, 0xB62D, 0x8C6E, 0xB62E, 0x8C6F, 0xB62F, 0x8C70, 0xB630, 0x8C71, 0xB631, 0x8C72, 0xB632, 0x8C73, 0xB633, 0x8C74, + 0xB634, 0xB6CD, 0xB635, 0x8C75, 0xB636, 0x8C76, 0xB637, 0x8C77, 0xB638, 0x8C78, 0xB639, 0x8C79, 0xB63A, 0x8C7A, 0xB63B, 0x8C81, + 0xB63C, 0x8C82, 0xB63D, 0x8C83, 0xB63E, 0x8C84, 0xB63F, 0x8C85, 0xB640, 0x8C86, 0xB641, 0x8C87, 0xB642, 0x8C88, 0xB643, 0x8C89, + 0xB644, 0x8C8A, 0xB645, 0x8C8B, 0xB646, 0x8C8C, 0xB647, 0x8C8D, 0xB648, 0xB6CE, 0xB649, 0x8C8E, 0xB64A, 0x8C8F, 0xB64B, 0x8C90, + 0xB64C, 0x8C91, 0xB64D, 0x8C92, 0xB64E, 0x8C93, 0xB64F, 0x8C94, 0xB650, 0x8C95, 0xB651, 0x8C96, 0xB652, 0x8C97, 0xB653, 0x8C98, + 0xB654, 0x8C99, 0xB655, 0x8C9A, 0xB656, 0x8C9B, 0xB657, 0x8C9C, 0xB658, 0x8C9D, 0xB659, 0x8C9E, 0xB65A, 0x8C9F, 0xB65B, 0x8CA0, + 0xB65C, 0x8CA1, 0xB65D, 0x8CA2, 0xB65E, 0x8CA3, 0xB65F, 0x8CA4, 0xB660, 0x8CA5, 0xB661, 0x8CA6, 0xB662, 0x8CA7, 0xB663, 0x8CA8, + 0xB664, 0xB6CF, 0xB665, 0x8CA9, 0xB666, 0x8CAA, 0xB667, 0x8CAB, 0xB668, 0xB6D0, 0xB669, 0x8CAC, 0xB66A, 0x8CAD, 0xB66B, 0x8CAE, + 0xB66C, 0x8CAF, 0xB66D, 0x8CB0, 0xB66E, 0x8CB1, 0xB66F, 0x8CB2, 0xB670, 0x8CB3, 0xB671, 0x8CB4, 0xB672, 0x8CB5, 0xB673, 0x8CB6, + 0xB674, 0x8CB7, 0xB675, 0x8CB8, 0xB676, 0x8CB9, 0xB677, 0x8CBA, 0xB678, 0x8CBB, 0xB679, 0x8CBC, 0xB67A, 0x8CBD, 0xB67B, 0x8CBE, + 0xB67C, 0x8CBF, 0xB67D, 0x8CC0, 0xB67E, 0x8CC1, 0xB67F, 0x8CC2, 0xB680, 0x8CC3, 0xB681, 0x8CC4, 0xB682, 0x8CC5, 0xB683, 0x8CC6, + 0xB684, 0x8CC7, 0xB685, 0x8CC8, 0xB686, 0x8CC9, 0xB687, 0x8CCA, 0xB688, 0x8CCB, 0xB689, 0x8CCC, 0xB68A, 0x8CCD, 0xB68B, 0x8CCE, + 0xB68C, 0x8CCF, 0xB68D, 0x8CD0, 0xB68E, 0x8CD1, 0xB68F, 0x8CD2, 0xB690, 0x8CD3, 0xB691, 0x8CD4, 0xB692, 0x8CD5, 0xB693, 0x8CD6, + 0xB694, 0x8CD7, 0xB695, 0x8CD8, 0xB696, 0x8CD9, 0xB697, 0x8CDA, 0xB698, 0x8CDB, 0xB699, 0x8CDC, 0xB69A, 0x8CDD, 0xB69B, 0x8CDE, + 0xB69C, 0xB6D1, 0xB69D, 0xB6D2, 0xB69E, 0x8CDF, 0xB69F, 0x8CE0, 0xB6A0, 0xB6D3, 0xB6A1, 0x8CE1, 0xB6A2, 0x8CE2, 0xB6A3, 0x8CE3, + 0xB6A4, 0xB6D4, 0xB6A5, 0x8CE4, 0xB6A6, 0x8CE5, 0xB6A7, 0x8CE6, 0xB6A8, 0x8CE7, 0xB6A9, 0x8CE8, 0xB6AA, 0x8CE9, 0xB6AB, 0xB6D5, + 0xB6AC, 0xB6D6, 0xB6AD, 0x8CEA, 0xB6AE, 0x8CEB, 0xB6AF, 0x8CEC, 0xB6B0, 0x8CED, 0xB6B1, 0xB6D7, 0xB6B2, 0x8CEE, 0xB6B3, 0x8CEF, + 0xB6B4, 0x8CF0, 0xB6B5, 0x8CF1, 0xB6B6, 0x8CF2, 0xB6B7, 0x8CF3, 0xB6B8, 0x8CF4, 0xB6B9, 0x8CF5, 0xB6BA, 0x8CF6, 0xB6BB, 0x8CF7, + 0xB6BC, 0x8CF8, 0xB6BD, 0x8CF9, 0xB6BE, 0x8CFA, 0xB6BF, 0x8CFB, 0xB6C0, 0x8CFC, 0xB6C1, 0x8CFD, 0xB6C2, 0x8CFE, 0xB6C3, 0x8D41, + 0xB6C4, 0x8D42, 0xB6C5, 0x8D43, 0xB6C6, 0x8D44, 0xB6C7, 0x8D45, 0xB6C8, 0x8D46, 0xB6C9, 0x8D47, 0xB6CA, 0x8D48, 0xB6CB, 0x8D49, + 0xB6CC, 0x8D4A, 0xB6CD, 0x8D4B, 0xB6CE, 0x8D4C, 0xB6CF, 0x8D4D, 0xB6D0, 0x8D4E, 0xB6D1, 0x8D4F, 0xB6D2, 0x8D50, 0xB6D3, 0x8D51, + 0xB6D4, 0xB6D8, 0xB6D5, 0x8D52, 0xB6D6, 0x8D53, 0xB6D7, 0x8D54, 0xB6D8, 0x8D55, 0xB6D9, 0x8D56, 0xB6DA, 0x8D57, 0xB6DB, 0x8D58, + 0xB6DC, 0x8D59, 0xB6DD, 0x8D5A, 0xB6DE, 0x8D61, 0xB6DF, 0x8D62, 0xB6E0, 0x8D63, 0xB6E1, 0x8D64, 0xB6E2, 0x8D65, 0xB6E3, 0x8D66, + 0xB6E4, 0x8D67, 0xB6E5, 0x8D68, 0xB6E6, 0x8D69, 0xB6E7, 0x8D6A, 0xB6E8, 0x8D6B, 0xB6E9, 0x8D6C, 0xB6EA, 0x8D6D, 0xB6EB, 0x8D6E, + 0xB6EC, 0x8D6F, 0xB6ED, 0x8D70, 0xB6EE, 0x8D71, 0xB6EF, 0x8D72, 0xB6F0, 0xB6D9, 0xB6F1, 0x8D73, 0xB6F2, 0x8D74, 0xB6F3, 0x8D75, + 0xB6F4, 0xB6DA, 0xB6F5, 0x8D76, 0xB6F6, 0x8D77, 0xB6F7, 0x8D78, 0xB6F8, 0xB6DB, 0xB6F9, 0x8D79, 0xB6FA, 0x8D7A, 0xB6FB, 0x8D81, + 0xB6FC, 0x8D82, 0xB6FD, 0x8D83, 0xB6FE, 0x8D84, 0xB6FF, 0x8D85, 0xB700, 0xB6DC, 0xB701, 0xB6DD, 0xB702, 0x8D86, 0xB703, 0x8D87, + 0xB704, 0x8D88, 0xB705, 0xB6DE, 0xB706, 0x8D89, 0xB707, 0x8D8A, 0xB708, 0x8D8B, 0xB709, 0x8D8C, 0xB70A, 0x8D8D, 0xB70B, 0x8D8E, + 0xB70C, 0x8D8F, 0xB70D, 0x8D90, 0xB70E, 0x8D91, 0xB70F, 0x8D92, 0xB710, 0x8D93, 0xB711, 0x8D94, 0xB712, 0x8D95, 0xB713, 0x8D96, + 0xB714, 0x8D97, 0xB715, 0x8D98, 0xB716, 0x8D99, 0xB717, 0x8D9A, 0xB718, 0x8D9B, 0xB719, 0x8D9C, 0xB71A, 0x8D9D, 0xB71B, 0x8D9E, + 0xB71C, 0x8D9F, 0xB71D, 0x8DA0, 0xB71E, 0x8DA1, 0xB71F, 0x8DA2, 0xB720, 0x8DA3, 0xB721, 0x8DA4, 0xB722, 0x8DA5, 0xB723, 0x8DA6, + 0xB724, 0x8DA7, 0xB725, 0x8DA8, 0xB726, 0x8DA9, 0xB727, 0x8DAA, 0xB728, 0xB6DF, 0xB729, 0xB6E0, 0xB72A, 0x8DAB, 0xB72B, 0x8DAC, + 0xB72C, 0xB6E1, 0xB72D, 0x8DAD, 0xB72E, 0x8DAE, 0xB72F, 0xB6E2, 0xB730, 0xB6E3, 0xB731, 0x8DAF, 0xB732, 0x8DB0, 0xB733, 0x8DB1, + 0xB734, 0x8DB2, 0xB735, 0x8DB3, 0xB736, 0x8DB4, 0xB737, 0x8DB5, 0xB738, 0xB6E4, 0xB739, 0xB6E5, 0xB73A, 0x8DB6, 0xB73B, 0xB6E6, + 0xB73C, 0x8DB7, 0xB73D, 0x8DB8, 0xB73E, 0x8DB9, 0xB73F, 0x8DBA, 0xB740, 0x8DBB, 0xB741, 0x8DBC, 0xB742, 0x8DBD, 0xB743, 0x8DBE, + 0xB744, 0xB6E7, 0xB745, 0x8DBF, 0xB746, 0x8DC0, 0xB747, 0x8DC1, 0xB748, 0xB6E8, 0xB749, 0x8DC2, 0xB74A, 0x8DC3, 0xB74B, 0x8DC4, + 0xB74C, 0xB6E9, 0xB74D, 0x8DC5, 0xB74E, 0x8DC6, 0xB74F, 0x8DC7, 0xB750, 0x8DC8, 0xB751, 0x8DC9, 0xB752, 0x8DCA, 0xB753, 0x8DCB, + 0xB754, 0xB6EA, 0xB755, 0xB6EB, 0xB756, 0x8DCC, 0xB757, 0x8DCD, 0xB758, 0x8DCE, 0xB759, 0x8DCF, 0xB75A, 0x8DD0, 0xB75B, 0x8DD1, + 0xB75C, 0x8DD2, 0xB75D, 0x8DD3, 0xB75E, 0x8DD4, 0xB75F, 0x8DD5, 0xB760, 0xB6EC, 0xB761, 0x8DD6, 0xB762, 0x8DD7, 0xB763, 0x8DD8, + 0xB764, 0xB6ED, 0xB765, 0x8DD9, 0xB766, 0x8DDA, 0xB767, 0x8DDB, 0xB768, 0xB6EE, 0xB769, 0x8DDC, 0xB76A, 0x8DDD, 0xB76B, 0x8DDE, + 0xB76C, 0x8DDF, 0xB76D, 0x8DE0, 0xB76E, 0x8DE1, 0xB76F, 0x8DE2, 0xB770, 0xB6EF, 0xB771, 0xB6F0, 0xB772, 0x8DE3, 0xB773, 0xB6F1, + 0xB774, 0x8DE4, 0xB775, 0xB6F2, 0xB776, 0x8DE5, 0xB777, 0x8DE6, 0xB778, 0x8DE7, 0xB779, 0x8DE8, 0xB77A, 0x8DE9, 0xB77B, 0x8DEA, + 0xB77C, 0xB6F3, 0xB77D, 0xB6F4, 0xB77E, 0x8DEB, 0xB77F, 0x8DEC, 0xB780, 0xB6F5, 0xB781, 0x8DED, 0xB782, 0x8DEE, 0xB783, 0x8DEF, + 0xB784, 0xB6F6, 0xB785, 0x8DF0, 0xB786, 0x8DF1, 0xB787, 0x8DF2, 0xB788, 0x8DF3, 0xB789, 0x8DF4, 0xB78A, 0x8DF5, 0xB78B, 0x8DF6, + 0xB78C, 0xB6F7, 0xB78D, 0xB6F8, 0xB78E, 0x8DF7, 0xB78F, 0xB6F9, 0xB790, 0xB6FA, 0xB791, 0xB6FB, 0xB792, 0xB6FC, 0xB793, 0x8DF8, + 0xB794, 0x8DF9, 0xB795, 0x8DFA, 0xB796, 0xB6FD, 0xB797, 0xB6FE, 0xB798, 0xB7A1, 0xB799, 0xB7A2, 0xB79A, 0x8DFB, 0xB79B, 0x8DFC, + 0xB79C, 0xB7A3, 0xB79D, 0x8DFD, 0xB79E, 0x8DFE, 0xB79F, 0x8E41, 0xB7A0, 0xB7A4, 0xB7A1, 0x8E42, 0xB7A2, 0x8E43, 0xB7A3, 0x8E44, + 0xB7A4, 0x8E45, 0xB7A5, 0x8E46, 0xB7A6, 0x8E47, 0xB7A7, 0x8E48, 0xB7A8, 0xB7A5, 0xB7A9, 0xB7A6, 0xB7AA, 0x8E49, 0xB7AB, 0xB7A7, + 0xB7AC, 0xB7A8, 0xB7AD, 0xB7A9, 0xB7AE, 0x8E4A, 0xB7AF, 0x8E4B, 0xB7B0, 0x8E4C, 0xB7B1, 0x8E4D, 0xB7B2, 0x8E4E, 0xB7B3, 0x8E4F, + 0xB7B4, 0xB7AA, 0xB7B5, 0xB7AB, 0xB7B6, 0x8E50, 0xB7B7, 0x8E51, 0xB7B8, 0xB7AC, 0xB7B9, 0x8E52, 0xB7BA, 0x8E53, 0xB7BB, 0x8E54, + 0xB7BC, 0x8E55, 0xB7BD, 0x8E56, 0xB7BE, 0x8E57, 0xB7BF, 0x8E58, 0xB7C0, 0x8E59, 0xB7C1, 0x8E5A, 0xB7C2, 0x8E61, 0xB7C3, 0x8E62, + 0xB7C4, 0x8E63, 0xB7C5, 0x8E64, 0xB7C6, 0x8E65, 0xB7C7, 0xB7AD, 0xB7C8, 0x8E66, 0xB7C9, 0xB7AE, 0xB7CA, 0x8E67, 0xB7CB, 0x8E68, + 0xB7CC, 0x8E69, 0xB7CD, 0x8E6A, 0xB7CE, 0x8E6B, 0xB7CF, 0x8E6C, 0xB7D0, 0x8E6D, 0xB7D1, 0x8E6E, 0xB7D2, 0x8E6F, 0xB7D3, 0x8E70, + 0xB7D4, 0x8E71, 0xB7D5, 0x8E72, 0xB7D6, 0x8E73, 0xB7D7, 0x8E74, 0xB7D8, 0x8E75, 0xB7D9, 0x8E76, 0xB7DA, 0x8E77, 0xB7DB, 0x8E78, + 0xB7DC, 0x8E79, 0xB7DD, 0x8E7A, 0xB7DE, 0x8E81, 0xB7DF, 0x8E82, 0xB7E0, 0x8E83, 0xB7E1, 0x8E84, 0xB7E2, 0x8E85, 0xB7E3, 0x8E86, + 0xB7E4, 0x8E87, 0xB7E5, 0x8E88, 0xB7E6, 0x8E89, 0xB7E7, 0x8E8A, 0xB7E8, 0x8E8B, 0xB7E9, 0x8E8C, 0xB7EA, 0x8E8D, 0xB7EB, 0x8E8E, + 0xB7EC, 0xB7AF, 0xB7ED, 0xB7B0, 0xB7EE, 0x8E8F, 0xB7EF, 0x8E90, 0xB7F0, 0xB7B1, 0xB7F1, 0x8E91, 0xB7F2, 0x8E92, 0xB7F3, 0x8E93, + 0xB7F4, 0xB7B2, 0xB7F5, 0x8E94, 0xB7F6, 0x8E95, 0xB7F7, 0x8E96, 0xB7F8, 0x8E97, 0xB7F9, 0x8E98, 0xB7FA, 0x8E99, 0xB7FB, 0x8E9A, + 0xB7FC, 0xB7B3, 0xB7FD, 0xB7B4, 0xB7FE, 0x8E9B, 0xB7FF, 0xB7B5, 0xB800, 0xB7B6, 0xB801, 0xB7B7, 0xB802, 0x8E9C, 0xB803, 0x8E9D, + 0xB804, 0x8E9E, 0xB805, 0x8E9F, 0xB806, 0x8EA0, 0xB807, 0xB7B8, 0xB808, 0xB7B9, 0xB809, 0xB7BA, 0xB80A, 0x8EA1, 0xB80B, 0x8EA2, + 0xB80C, 0xB7BB, 0xB80D, 0x8EA3, 0xB80E, 0x8EA4, 0xB80F, 0x8EA5, 0xB810, 0xB7BC, 0xB811, 0x8EA6, 0xB812, 0x8EA7, 0xB813, 0x8EA8, + 0xB814, 0x8EA9, 0xB815, 0x8EAA, 0xB816, 0x8EAB, 0xB817, 0x8EAC, 0xB818, 0xB7BD, 0xB819, 0xB7BE, 0xB81A, 0x8EAD, 0xB81B, 0xB7BF, + 0xB81C, 0x8EAE, 0xB81D, 0xB7C0, 0xB81E, 0x8EAF, 0xB81F, 0x8EB0, 0xB820, 0x8EB1, 0xB821, 0x8EB2, 0xB822, 0x8EB3, 0xB823, 0x8EB4, + 0xB824, 0xB7C1, 0xB825, 0xB7C2, 0xB826, 0x8EB5, 0xB827, 0x8EB6, 0xB828, 0xB7C3, 0xB829, 0x8EB7, 0xB82A, 0x8EB8, 0xB82B, 0x8EB9, + 0xB82C, 0xB7C4, 0xB82D, 0x8EBA, 0xB82E, 0x8EBB, 0xB82F, 0x8EBC, 0xB830, 0x8EBD, 0xB831, 0x8EBE, 0xB832, 0x8EBF, 0xB833, 0x8EC0, + 0xB834, 0xB7C5, 0xB835, 0xB7C6, 0xB836, 0x8EC1, 0xB837, 0xB7C7, 0xB838, 0xB7C8, 0xB839, 0xB7C9, 0xB83A, 0x8EC2, 0xB83B, 0x8EC3, + 0xB83C, 0x8EC4, 0xB83D, 0x8EC5, 0xB83E, 0x8EC6, 0xB83F, 0x8EC7, 0xB840, 0xB7CA, 0xB841, 0x8EC8, 0xB842, 0x8EC9, 0xB843, 0x8ECA, + 0xB844, 0xB7CB, 0xB845, 0x8ECB, 0xB846, 0x8ECC, 0xB847, 0x8ECD, 0xB848, 0x8ECE, 0xB849, 0x8ECF, 0xB84A, 0x8ED0, 0xB84B, 0x8ED1, + 0xB84C, 0x8ED2, 0xB84D, 0x8ED3, 0xB84E, 0x8ED4, 0xB84F, 0x8ED5, 0xB850, 0x8ED6, 0xB851, 0xB7CC, 0xB852, 0x8ED7, 0xB853, 0xB7CD, + 0xB854, 0x8ED8, 0xB855, 0x8ED9, 0xB856, 0x8EDA, 0xB857, 0x8EDB, 0xB858, 0x8EDC, 0xB859, 0x8EDD, 0xB85A, 0x8EDE, 0xB85B, 0x8EDF, + 0xB85C, 0xB7CE, 0xB85D, 0xB7CF, 0xB85E, 0x8EE0, 0xB85F, 0x8EE1, 0xB860, 0xB7D0, 0xB861, 0x8EE2, 0xB862, 0x8EE3, 0xB863, 0x8EE4, + 0xB864, 0xB7D1, 0xB865, 0x8EE5, 0xB866, 0x8EE6, 0xB867, 0x8EE7, 0xB868, 0x8EE8, 0xB869, 0x8EE9, 0xB86A, 0x8EEA, 0xB86B, 0x8EEB, + 0xB86C, 0xB7D2, 0xB86D, 0xB7D3, 0xB86E, 0x8EEC, 0xB86F, 0xB7D4, 0xB870, 0x8EED, 0xB871, 0xB7D5, 0xB872, 0x8EEE, 0xB873, 0x8EEF, + 0xB874, 0x8EF0, 0xB875, 0x8EF1, 0xB876, 0x8EF2, 0xB877, 0x8EF3, 0xB878, 0xB7D6, 0xB879, 0x8EF4, 0xB87A, 0x8EF5, 0xB87B, 0x8EF6, + 0xB87C, 0xB7D7, 0xB87D, 0x8EF7, 0xB87E, 0x8EF8, 0xB87F, 0x8EF9, 0xB880, 0x8EFA, 0xB881, 0x8EFB, 0xB882, 0x8EFC, 0xB883, 0x8EFD, + 0xB884, 0x8EFE, 0xB885, 0x8F41, 0xB886, 0x8F42, 0xB887, 0x8F43, 0xB888, 0x8F44, 0xB889, 0x8F45, 0xB88A, 0x8F46, 0xB88B, 0x8F47, + 0xB88C, 0x8F48, 0xB88D, 0xB7D8, 0xB88E, 0x8F49, 0xB88F, 0x8F4A, 0xB890, 0x8F4B, 0xB891, 0x8F4C, 0xB892, 0x8F4D, 0xB893, 0x8F4E, + 0xB894, 0x8F4F, 0xB895, 0x8F50, 0xB896, 0x8F51, 0xB897, 0x8F52, 0xB898, 0x8F53, 0xB899, 0x8F54, 0xB89A, 0x8F55, 0xB89B, 0x8F56, + 0xB89C, 0x8F57, 0xB89D, 0x8F58, 0xB89E, 0x8F59, 0xB89F, 0x8F5A, 0xB8A0, 0x8F61, 0xB8A1, 0x8F62, 0xB8A2, 0x8F63, 0xB8A3, 0x8F64, + 0xB8A4, 0x8F65, 0xB8A5, 0x8F66, 0xB8A6, 0x8F67, 0xB8A7, 0x8F68, 0xB8A8, 0xB7D9, 0xB8A9, 0x8F69, 0xB8AA, 0x8F6A, 0xB8AB, 0x8F6B, + 0xB8AC, 0x8F6C, 0xB8AD, 0x8F6D, 0xB8AE, 0x8F6E, 0xB8AF, 0x8F6F, 0xB8B0, 0xB7DA, 0xB8B1, 0x8F70, 0xB8B2, 0x8F71, 0xB8B3, 0x8F72, + 0xB8B4, 0xB7DB, 0xB8B5, 0x8F73, 0xB8B6, 0x8F74, 0xB8B7, 0x8F75, 0xB8B8, 0xB7DC, 0xB8B9, 0x8F76, 0xB8BA, 0x8F77, 0xB8BB, 0x8F78, + 0xB8BC, 0x8F79, 0xB8BD, 0x8F7A, 0xB8BE, 0x8F81, 0xB8BF, 0x8F82, 0xB8C0, 0xB7DD, 0xB8C1, 0xB7DE, 0xB8C2, 0x8F83, 0xB8C3, 0xB7DF, + 0xB8C4, 0x8F84, 0xB8C5, 0xB7E0, 0xB8C6, 0x8F85, 0xB8C7, 0x8F86, 0xB8C8, 0x8F87, 0xB8C9, 0x8F88, 0xB8CA, 0x8F89, 0xB8CB, 0x8F8A, + 0xB8CC, 0xB7E1, 0xB8CD, 0x8F8B, 0xB8CE, 0x8F8C, 0xB8CF, 0x8F8D, 0xB8D0, 0xB7E2, 0xB8D1, 0x8F8E, 0xB8D2, 0x8F8F, 0xB8D3, 0x8F90, + 0xB8D4, 0xB7E3, 0xB8D5, 0x8F91, 0xB8D6, 0x8F92, 0xB8D7, 0x8F93, 0xB8D8, 0x8F94, 0xB8D9, 0x8F95, 0xB8DA, 0x8F96, 0xB8DB, 0x8F97, + 0xB8DC, 0x8F98, 0xB8DD, 0xB7E4, 0xB8DE, 0x8F99, 0xB8DF, 0xB7E5, 0xB8E0, 0x8F9A, 0xB8E1, 0xB7E6, 0xB8E2, 0x8F9B, 0xB8E3, 0x8F9C, + 0xB8E4, 0x8F9D, 0xB8E5, 0x8F9E, 0xB8E6, 0x8F9F, 0xB8E7, 0x8FA0, 0xB8E8, 0xB7E7, 0xB8E9, 0xB7E8, 0xB8EA, 0x8FA1, 0xB8EB, 0x8FA2, + 0xB8EC, 0xB7E9, 0xB8ED, 0x8FA3, 0xB8EE, 0x8FA4, 0xB8EF, 0x8FA5, 0xB8F0, 0xB7EA, 0xB8F1, 0x8FA6, 0xB8F2, 0x8FA7, 0xB8F3, 0x8FA8, + 0xB8F4, 0x8FA9, 0xB8F5, 0x8FAA, 0xB8F6, 0x8FAB, 0xB8F7, 0x8FAC, 0xB8F8, 0xB7EB, 0xB8F9, 0xB7EC, 0xB8FA, 0x8FAD, 0xB8FB, 0xB7ED, + 0xB8FC, 0x8FAE, 0xB8FD, 0xB7EE, 0xB8FE, 0x8FAF, 0xB8FF, 0x8FB0, 0xB900, 0x8FB1, 0xB901, 0x8FB2, 0xB902, 0x8FB3, 0xB903, 0x8FB4, + 0xB904, 0xB7EF, 0xB905, 0x8FB5, 0xB906, 0x8FB6, 0xB907, 0x8FB7, 0xB908, 0x8FB8, 0xB909, 0x8FB9, 0xB90A, 0x8FBA, 0xB90B, 0x8FBB, + 0xB90C, 0x8FBC, 0xB90D, 0x8FBD, 0xB90E, 0x8FBE, 0xB90F, 0x8FBF, 0xB910, 0x8FC0, 0xB911, 0x8FC1, 0xB912, 0x8FC2, 0xB913, 0x8FC3, + 0xB914, 0x8FC4, 0xB915, 0x8FC5, 0xB916, 0x8FC6, 0xB917, 0x8FC7, 0xB918, 0xB7F0, 0xB919, 0x8FC8, 0xB91A, 0x8FC9, 0xB91B, 0x8FCA, + 0xB91C, 0x8FCB, 0xB91D, 0x8FCC, 0xB91E, 0x8FCD, 0xB91F, 0x8FCE, 0xB920, 0xB7F1, 0xB921, 0x8FCF, 0xB922, 0x8FD0, 0xB923, 0x8FD1, + 0xB924, 0x8FD2, 0xB925, 0x8FD3, 0xB926, 0x8FD4, 0xB927, 0x8FD5, 0xB928, 0x8FD6, 0xB929, 0x8FD7, 0xB92A, 0x8FD8, 0xB92B, 0x8FD9, + 0xB92C, 0x8FDA, 0xB92D, 0x8FDB, 0xB92E, 0x8FDC, 0xB92F, 0x8FDD, 0xB930, 0x8FDE, 0xB931, 0x8FDF, 0xB932, 0x8FE0, 0xB933, 0x8FE1, + 0xB934, 0x8FE2, 0xB935, 0x8FE3, 0xB936, 0x8FE4, 0xB937, 0x8FE5, 0xB938, 0x8FE6, 0xB939, 0x8FE7, 0xB93A, 0x8FE8, 0xB93B, 0x8FE9, + 0xB93C, 0xB7F2, 0xB93D, 0xB7F3, 0xB93E, 0x8FEA, 0xB93F, 0x8FEB, 0xB940, 0xB7F4, 0xB941, 0x8FEC, 0xB942, 0x8FED, 0xB943, 0x8FEE, + 0xB944, 0xB7F5, 0xB945, 0x8FEF, 0xB946, 0x8FF0, 0xB947, 0x8FF1, 0xB948, 0x8FF2, 0xB949, 0x8FF3, 0xB94A, 0x8FF4, 0xB94B, 0x8FF5, + 0xB94C, 0xB7F6, 0xB94D, 0x8FF6, 0xB94E, 0x8FF7, 0xB94F, 0xB7F7, 0xB950, 0x8FF8, 0xB951, 0xB7F8, 0xB952, 0x8FF9, 0xB953, 0x8FFA, + 0xB954, 0x8FFB, 0xB955, 0x8FFC, 0xB956, 0x8FFD, 0xB957, 0x8FFE, 0xB958, 0xB7F9, 0xB959, 0xB7FA, 0xB95A, 0x9041, 0xB95B, 0x9042, + 0xB95C, 0xB7FB, 0xB95D, 0x9043, 0xB95E, 0x9044, 0xB95F, 0x9045, 0xB960, 0xB7FC, 0xB961, 0x9046, 0xB962, 0x9047, 0xB963, 0x9048, + 0xB964, 0x9049, 0xB965, 0x904A, 0xB966, 0x904B, 0xB967, 0x904C, 0xB968, 0xB7FD, 0xB969, 0xB7FE, 0xB96A, 0x904D, 0xB96B, 0xB8A1, + 0xB96C, 0x904E, 0xB96D, 0xB8A2, 0xB96E, 0x904F, 0xB96F, 0x9050, 0xB970, 0x9051, 0xB971, 0x9052, 0xB972, 0x9053, 0xB973, 0x9054, + 0xB974, 0xB8A3, 0xB975, 0xB8A4, 0xB976, 0x9055, 0xB977, 0x9056, 0xB978, 0xB8A5, 0xB979, 0x9057, 0xB97A, 0x9058, 0xB97B, 0x9059, + 0xB97C, 0xB8A6, 0xB97D, 0x905A, 0xB97E, 0x9061, 0xB97F, 0x9062, 0xB980, 0x9063, 0xB981, 0x9064, 0xB982, 0x9065, 0xB983, 0x9066, + 0xB984, 0xB8A7, 0xB985, 0xB8A8, 0xB986, 0x9067, 0xB987, 0xB8A9, 0xB988, 0x9068, 0xB989, 0xB8AA, 0xB98A, 0xB8AB, 0xB98B, 0x9069, + 0xB98C, 0x906A, 0xB98D, 0xB8AC, 0xB98E, 0xB8AD, 0xB98F, 0x906B, 0xB990, 0x906C, 0xB991, 0x906D, 0xB992, 0x906E, 0xB993, 0x906F, + 0xB994, 0x9070, 0xB995, 0x9071, 0xB996, 0x9072, 0xB997, 0x9073, 0xB998, 0x9074, 0xB999, 0x9075, 0xB99A, 0x9076, 0xB99B, 0x9077, + 0xB99C, 0x9078, 0xB99D, 0x9079, 0xB99E, 0x907A, 0xB99F, 0x9081, 0xB9A0, 0x9082, 0xB9A1, 0x9083, 0xB9A2, 0x9084, 0xB9A3, 0x9085, + 0xB9A4, 0x9086, 0xB9A5, 0x9087, 0xB9A6, 0x9088, 0xB9A7, 0x9089, 0xB9A8, 0x908A, 0xB9A9, 0x908B, 0xB9AA, 0x908C, 0xB9AB, 0x908D, + 0xB9AC, 0xB8AE, 0xB9AD, 0xB8AF, 0xB9AE, 0x908E, 0xB9AF, 0x908F, 0xB9B0, 0xB8B0, 0xB9B1, 0x9090, 0xB9B2, 0x9091, 0xB9B3, 0x9092, + 0xB9B4, 0xB8B1, 0xB9B5, 0x9093, 0xB9B6, 0x9094, 0xB9B7, 0x9095, 0xB9B8, 0x9096, 0xB9B9, 0x9097, 0xB9BA, 0x9098, 0xB9BB, 0x9099, + 0xB9BC, 0xB8B2, 0xB9BD, 0xB8B3, 0xB9BE, 0x909A, 0xB9BF, 0xB8B4, 0xB9C0, 0x909B, 0xB9C1, 0xB8B5, 0xB9C2, 0x909C, 0xB9C3, 0x909D, + 0xB9C4, 0x909E, 0xB9C5, 0x909F, 0xB9C6, 0x90A0, 0xB9C7, 0x90A1, 0xB9C8, 0xB8B6, 0xB9C9, 0xB8B7, 0xB9CA, 0x90A2, 0xB9CB, 0x90A3, + 0xB9CC, 0xB8B8, 0xB9CD, 0x90A4, 0xB9CE, 0xB8B9, 0xB9CF, 0xB8BA, 0xB9D0, 0xB8BB, 0xB9D1, 0xB8BC, 0xB9D2, 0xB8BD, 0xB9D3, 0x90A5, + 0xB9D4, 0x90A6, 0xB9D5, 0x90A7, 0xB9D6, 0x90A8, 0xB9D7, 0x90A9, 0xB9D8, 0xB8BE, 0xB9D9, 0xB8BF, 0xB9DA, 0x90AA, 0xB9DB, 0xB8C0, + 0xB9DC, 0x90AB, 0xB9DD, 0xB8C1, 0xB9DE, 0xB8C2, 0xB9DF, 0x90AC, 0xB9E0, 0x90AD, 0xB9E1, 0xB8C3, 0xB9E2, 0x90AE, 0xB9E3, 0xB8C4, + 0xB9E4, 0xB8C5, 0xB9E5, 0xB8C6, 0xB9E6, 0x90AF, 0xB9E7, 0x90B0, 0xB9E8, 0xB8C7, 0xB9E9, 0x90B1, 0xB9EA, 0x90B2, 0xB9EB, 0x90B3, + 0xB9EC, 0xB8C8, 0xB9ED, 0x90B4, 0xB9EE, 0x90B5, 0xB9EF, 0x90B6, 0xB9F0, 0x90B7, 0xB9F1, 0x90B8, 0xB9F2, 0x90B9, 0xB9F3, 0x90BA, + 0xB9F4, 0xB8C9, 0xB9F5, 0xB8CA, 0xB9F6, 0x90BB, 0xB9F7, 0xB8CB, 0xB9F8, 0xB8CC, 0xB9F9, 0xB8CD, 0xB9FA, 0xB8CE, 0xB9FB, 0x90BC, + 0xB9FC, 0x90BD, 0xB9FD, 0x90BE, 0xB9FE, 0x90BF, 0xB9FF, 0x90C0, 0xBA00, 0xB8CF, 0xBA01, 0xB8D0, 0xBA02, 0x90C1, 0xBA03, 0x90C2, + 0xBA04, 0x90C3, 0xBA05, 0x90C4, 0xBA06, 0x90C5, 0xBA07, 0x90C6, 0xBA08, 0xB8D1, 0xBA09, 0x90C7, 0xBA0A, 0x90C8, 0xBA0B, 0x90C9, + 0xBA0C, 0x90CA, 0xBA0D, 0x90CB, 0xBA0E, 0x90CC, 0xBA0F, 0x90CD, 0xBA10, 0x90CE, 0xBA11, 0x90CF, 0xBA12, 0x90D0, 0xBA13, 0x90D1, + 0xBA14, 0x90D2, 0xBA15, 0xB8D2, 0xBA16, 0x90D3, 0xBA17, 0x90D4, 0xBA18, 0x90D5, 0xBA19, 0x90D6, 0xBA1A, 0x90D7, 0xBA1B, 0x90D8, + 0xBA1C, 0x90D9, 0xBA1D, 0x90DA, 0xBA1E, 0x90DB, 0xBA1F, 0x90DC, 0xBA20, 0x90DD, 0xBA21, 0x90DE, 0xBA22, 0x90DF, 0xBA23, 0x90E0, + 0xBA24, 0x90E1, 0xBA25, 0x90E2, 0xBA26, 0x90E3, 0xBA27, 0x90E4, 0xBA28, 0x90E5, 0xBA29, 0x90E6, 0xBA2A, 0x90E7, 0xBA2B, 0x90E8, + 0xBA2C, 0x90E9, 0xBA2D, 0x90EA, 0xBA2E, 0x90EB, 0xBA2F, 0x90EC, 0xBA30, 0x90ED, 0xBA31, 0x90EE, 0xBA32, 0x90EF, 0xBA33, 0x90F0, + 0xBA34, 0x90F1, 0xBA35, 0x90F2, 0xBA36, 0x90F3, 0xBA37, 0x90F4, 0xBA38, 0xB8D3, 0xBA39, 0xB8D4, 0xBA3A, 0x90F5, 0xBA3B, 0x90F6, + 0xBA3C, 0xB8D5, 0xBA3D, 0x90F7, 0xBA3E, 0x90F8, 0xBA3F, 0x90F9, 0xBA40, 0xB8D6, 0xBA41, 0x90FA, 0xBA42, 0xB8D7, 0xBA43, 0x90FB, + 0xBA44, 0x90FC, 0xBA45, 0x90FD, 0xBA46, 0x90FE, 0xBA47, 0x9141, 0xBA48, 0xB8D8, 0xBA49, 0xB8D9, 0xBA4A, 0x9142, 0xBA4B, 0xB8DA, + 0xBA4C, 0x9143, 0xBA4D, 0xB8DB, 0xBA4E, 0xB8DC, 0xBA4F, 0x9144, 0xBA50, 0x9145, 0xBA51, 0x9146, 0xBA52, 0x9147, 0xBA53, 0xB8DD, + 0xBA54, 0xB8DE, 0xBA55, 0xB8DF, 0xBA56, 0x9148, 0xBA57, 0x9149, 0xBA58, 0xB8E0, 0xBA59, 0x914A, 0xBA5A, 0x914B, 0xBA5B, 0x914C, + 0xBA5C, 0xB8E1, 0xBA5D, 0x914D, 0xBA5E, 0x914E, 0xBA5F, 0x914F, 0xBA60, 0x9150, 0xBA61, 0x9151, 0xBA62, 0x9152, 0xBA63, 0x9153, + 0xBA64, 0xB8E2, 0xBA65, 0xB8E3, 0xBA66, 0x9154, 0xBA67, 0xB8E4, 0xBA68, 0xB8E5, 0xBA69, 0xB8E6, 0xBA6A, 0x9155, 0xBA6B, 0x9156, + 0xBA6C, 0x9157, 0xBA6D, 0x9158, 0xBA6E, 0x9159, 0xBA6F, 0x915A, 0xBA70, 0xB8E7, 0xBA71, 0xB8E8, 0xBA72, 0x9161, 0xBA73, 0x9162, + 0xBA74, 0xB8E9, 0xBA75, 0x9163, 0xBA76, 0x9164, 0xBA77, 0x9165, 0xBA78, 0xB8EA, 0xBA79, 0x9166, 0xBA7A, 0x9167, 0xBA7B, 0x9168, + 0xBA7C, 0x9169, 0xBA7D, 0x916A, 0xBA7E, 0x916B, 0xBA7F, 0x916C, 0xBA80, 0x916D, 0xBA81, 0x916E, 0xBA82, 0x916F, 0xBA83, 0xB8EB, + 0xBA84, 0xB8EC, 0xBA85, 0xB8ED, 0xBA86, 0x9170, 0xBA87, 0xB8EE, 0xBA88, 0x9171, 0xBA89, 0x9172, 0xBA8A, 0x9173, 0xBA8B, 0x9174, + 0xBA8C, 0xB8EF, 0xBA8D, 0x9175, 0xBA8E, 0x9176, 0xBA8F, 0x9177, 0xBA90, 0x9178, 0xBA91, 0x9179, 0xBA92, 0x917A, 0xBA93, 0x9181, + 0xBA94, 0x9182, 0xBA95, 0x9183, 0xBA96, 0x9184, 0xBA97, 0x9185, 0xBA98, 0x9186, 0xBA99, 0x9187, 0xBA9A, 0x9188, 0xBA9B, 0x9189, + 0xBA9C, 0x918A, 0xBA9D, 0x918B, 0xBA9E, 0x918C, 0xBA9F, 0x918D, 0xBAA0, 0x918E, 0xBAA1, 0x918F, 0xBAA2, 0x9190, 0xBAA3, 0x9191, + 0xBAA4, 0x9192, 0xBAA5, 0x9193, 0xBAA6, 0x9194, 0xBAA7, 0x9195, 0xBAA8, 0xB8F0, 0xBAA9, 0xB8F1, 0xBAAA, 0x9196, 0xBAAB, 0xB8F2, + 0xBAAC, 0xB8F3, 0xBAAD, 0x9197, 0xBAAE, 0x9198, 0xBAAF, 0x9199, 0xBAB0, 0xB8F4, 0xBAB1, 0x919A, 0xBAB2, 0xB8F5, 0xBAB3, 0x919B, + 0xBAB4, 0x919C, 0xBAB5, 0x919D, 0xBAB6, 0x919E, 0xBAB7, 0x919F, 0xBAB8, 0xB8F6, 0xBAB9, 0xB8F7, 0xBABA, 0x91A0, 0xBABB, 0xB8F8, + 0xBABC, 0x91A1, 0xBABD, 0xB8F9, 0xBABE, 0x91A2, 0xBABF, 0x91A3, 0xBAC0, 0x91A4, 0xBAC1, 0x91A5, 0xBAC2, 0x91A6, 0xBAC3, 0x91A7, + 0xBAC4, 0xB8FA, 0xBAC5, 0x91A8, 0xBAC6, 0x91A9, 0xBAC7, 0x91AA, 0xBAC8, 0xB8FB, 0xBAC9, 0x91AB, 0xBACA, 0x91AC, 0xBACB, 0x91AD, + 0xBACC, 0x91AE, 0xBACD, 0x91AF, 0xBACE, 0x91B0, 0xBACF, 0x91B1, 0xBAD0, 0x91B2, 0xBAD1, 0x91B3, 0xBAD2, 0x91B4, 0xBAD3, 0x91B5, + 0xBAD4, 0x91B6, 0xBAD5, 0x91B7, 0xBAD6, 0x91B8, 0xBAD7, 0x91B9, 0xBAD8, 0xB8FC, 0xBAD9, 0xB8FD, 0xBADA, 0x91BA, 0xBADB, 0x91BB, + 0xBADC, 0x91BC, 0xBADD, 0x91BD, 0xBADE, 0x91BE, 0xBADF, 0x91BF, 0xBAE0, 0x91C0, 0xBAE1, 0x91C1, 0xBAE2, 0x91C2, 0xBAE3, 0x91C3, + 0xBAE4, 0x91C4, 0xBAE5, 0x91C5, 0xBAE6, 0x91C6, 0xBAE7, 0x91C7, 0xBAE8, 0x91C8, 0xBAE9, 0x91C9, 0xBAEA, 0x91CA, 0xBAEB, 0x91CB, + 0xBAEC, 0x91CC, 0xBAED, 0x91CD, 0xBAEE, 0x91CE, 0xBAEF, 0x91CF, 0xBAF0, 0x91D0, 0xBAF1, 0x91D1, 0xBAF2, 0x91D2, 0xBAF3, 0x91D3, + 0xBAF4, 0x91D4, 0xBAF5, 0x91D5, 0xBAF6, 0x91D6, 0xBAF7, 0x91D7, 0xBAF8, 0x91D8, 0xBAF9, 0x91D9, 0xBAFA, 0x91DA, 0xBAFB, 0x91DB, + 0xBAFC, 0xB8FE, 0xBAFD, 0x91DC, 0xBAFE, 0x91DD, 0xBAFF, 0x91DE, 0xBB00, 0xB9A1, 0xBB01, 0x91DF, 0xBB02, 0x91E0, 0xBB03, 0x91E1, + 0xBB04, 0xB9A2, 0xBB05, 0x91E2, 0xBB06, 0x91E3, 0xBB07, 0x91E4, 0xBB08, 0x91E5, 0xBB09, 0x91E6, 0xBB0A, 0x91E7, 0xBB0B, 0x91E8, + 0xBB0C, 0x91E9, 0xBB0D, 0xB9A3, 0xBB0E, 0x91EA, 0xBB0F, 0xB9A4, 0xBB10, 0x91EB, 0xBB11, 0xB9A5, 0xBB12, 0x91EC, 0xBB13, 0x91ED, + 0xBB14, 0x91EE, 0xBB15, 0x91EF, 0xBB16, 0x91F0, 0xBB17, 0x91F1, 0xBB18, 0xB9A6, 0xBB19, 0x91F2, 0xBB1A, 0x91F3, 0xBB1B, 0x91F4, + 0xBB1C, 0xB9A7, 0xBB1D, 0x91F5, 0xBB1E, 0x91F6, 0xBB1F, 0x91F7, 0xBB20, 0xB9A8, 0xBB21, 0x91F8, 0xBB22, 0x91F9, 0xBB23, 0x91FA, + 0xBB24, 0x91FB, 0xBB25, 0x91FC, 0xBB26, 0x91FD, 0xBB27, 0x91FE, 0xBB28, 0x9241, 0xBB29, 0xB9A9, 0xBB2A, 0x9242, 0xBB2B, 0xB9AA, + 0xBB2C, 0x9243, 0xBB2D, 0x9244, 0xBB2E, 0x9245, 0xBB2F, 0x9246, 0xBB30, 0x9247, 0xBB31, 0x9248, 0xBB32, 0x9249, 0xBB33, 0x924A, + 0xBB34, 0xB9AB, 0xBB35, 0xB9AC, 0xBB36, 0xB9AD, 0xBB37, 0x924B, 0xBB38, 0xB9AE, 0xBB39, 0x924C, 0xBB3A, 0x924D, 0xBB3B, 0xB9AF, + 0xBB3C, 0xB9B0, 0xBB3D, 0xB9B1, 0xBB3E, 0xB9B2, 0xBB3F, 0x924E, 0xBB40, 0x924F, 0xBB41, 0x9250, 0xBB42, 0x9251, 0xBB43, 0x9252, + 0xBB44, 0xB9B3, 0xBB45, 0xB9B4, 0xBB46, 0x9253, 0xBB47, 0xB9B5, 0xBB48, 0x9254, 0xBB49, 0xB9B6, 0xBB4A, 0x9255, 0xBB4B, 0x9256, + 0xBB4C, 0x9257, 0xBB4D, 0xB9B7, 0xBB4E, 0x9258, 0xBB4F, 0xB9B8, 0xBB50, 0xB9B9, 0xBB51, 0x9259, 0xBB52, 0x925A, 0xBB53, 0x9261, + 0xBB54, 0xB9BA, 0xBB55, 0x9262, 0xBB56, 0x9263, 0xBB57, 0x9264, 0xBB58, 0xB9BB, 0xBB59, 0x9265, 0xBB5A, 0x9266, 0xBB5B, 0x9267, + 0xBB5C, 0x9268, 0xBB5D, 0x9269, 0xBB5E, 0x926A, 0xBB5F, 0x926B, 0xBB60, 0x926C, 0xBB61, 0xB9BC, 0xBB62, 0x926D, 0xBB63, 0xB9BD, + 0xBB64, 0x926E, 0xBB65, 0x926F, 0xBB66, 0x9270, 0xBB67, 0x9271, 0xBB68, 0x9272, 0xBB69, 0x9273, 0xBB6A, 0x9274, 0xBB6B, 0x9275, + 0xBB6C, 0xB9BE, 0xBB6D, 0x9276, 0xBB6E, 0x9277, 0xBB6F, 0x9278, 0xBB70, 0x9279, 0xBB71, 0x927A, 0xBB72, 0x9281, 0xBB73, 0x9282, + 0xBB74, 0x9283, 0xBB75, 0x9284, 0xBB76, 0x9285, 0xBB77, 0x9286, 0xBB78, 0x9287, 0xBB79, 0x9288, 0xBB7A, 0x9289, 0xBB7B, 0x928A, + 0xBB7C, 0x928B, 0xBB7D, 0x928C, 0xBB7E, 0x928D, 0xBB7F, 0x928E, 0xBB80, 0x928F, 0xBB81, 0x9290, 0xBB82, 0x9291, 0xBB83, 0x9292, + 0xBB84, 0x9293, 0xBB85, 0x9294, 0xBB86, 0x9295, 0xBB87, 0x9296, 0xBB88, 0xB9BF, 0xBB89, 0x9297, 0xBB8A, 0x9298, 0xBB8B, 0x9299, + 0xBB8C, 0xB9C0, 0xBB8D, 0x929A, 0xBB8E, 0x929B, 0xBB8F, 0x929C, 0xBB90, 0xB9C1, 0xBB91, 0x929D, 0xBB92, 0x929E, 0xBB93, 0x929F, + 0xBB94, 0x92A0, 0xBB95, 0x92A1, 0xBB96, 0x92A2, 0xBB97, 0x92A3, 0xBB98, 0x92A4, 0xBB99, 0x92A5, 0xBB9A, 0x92A6, 0xBB9B, 0x92A7, + 0xBB9C, 0x92A8, 0xBB9D, 0x92A9, 0xBB9E, 0x92AA, 0xBB9F, 0x92AB, 0xBBA0, 0x92AC, 0xBBA1, 0x92AD, 0xBBA2, 0x92AE, 0xBBA3, 0x92AF, + 0xBBA4, 0xB9C2, 0xBBA5, 0x92B0, 0xBBA6, 0x92B1, 0xBBA7, 0x92B2, 0xBBA8, 0xB9C3, 0xBBA9, 0x92B3, 0xBBAA, 0x92B4, 0xBBAB, 0x92B5, + 0xBBAC, 0xB9C4, 0xBBAD, 0x92B6, 0xBBAE, 0x92B7, 0xBBAF, 0x92B8, 0xBBB0, 0x92B9, 0xBBB1, 0x92BA, 0xBBB2, 0x92BB, 0xBBB3, 0x92BC, + 0xBBB4, 0xB9C5, 0xBBB5, 0x92BD, 0xBBB6, 0x92BE, 0xBBB7, 0xB9C6, 0xBBB8, 0x92BF, 0xBBB9, 0x92C0, 0xBBBA, 0x92C1, 0xBBBB, 0x92C2, + 0xBBBC, 0x92C3, 0xBBBD, 0x92C4, 0xBBBE, 0x92C5, 0xBBBF, 0x92C6, 0xBBC0, 0xB9C7, 0xBBC1, 0x92C7, 0xBBC2, 0x92C8, 0xBBC3, 0x92C9, + 0xBBC4, 0xB9C8, 0xBBC5, 0x92CA, 0xBBC6, 0x92CB, 0xBBC7, 0x92CC, 0xBBC8, 0xB9C9, 0xBBC9, 0x92CD, 0xBBCA, 0x92CE, 0xBBCB, 0x92CF, + 0xBBCC, 0x92D0, 0xBBCD, 0x92D1, 0xBBCE, 0x92D2, 0xBBCF, 0x92D3, 0xBBD0, 0xB9CA, 0xBBD1, 0x92D4, 0xBBD2, 0x92D5, 0xBBD3, 0xB9CB, + 0xBBD4, 0x92D6, 0xBBD5, 0x92D7, 0xBBD6, 0x92D8, 0xBBD7, 0x92D9, 0xBBD8, 0x92DA, 0xBBD9, 0x92DB, 0xBBDA, 0x92DC, 0xBBDB, 0x92DD, + 0xBBDC, 0x92DE, 0xBBDD, 0x92DF, 0xBBDE, 0x92E0, 0xBBDF, 0x92E1, 0xBBE0, 0x92E2, 0xBBE1, 0x92E3, 0xBBE2, 0x92E4, 0xBBE3, 0x92E5, + 0xBBE4, 0x92E6, 0xBBE5, 0x92E7, 0xBBE6, 0x92E8, 0xBBE7, 0x92E9, 0xBBE8, 0x92EA, 0xBBE9, 0x92EB, 0xBBEA, 0x92EC, 0xBBEB, 0x92ED, + 0xBBEC, 0x92EE, 0xBBED, 0x92EF, 0xBBEE, 0x92F0, 0xBBEF, 0x92F1, 0xBBF0, 0x92F2, 0xBBF1, 0x92F3, 0xBBF2, 0x92F4, 0xBBF3, 0x92F5, + 0xBBF4, 0x92F6, 0xBBF5, 0x92F7, 0xBBF6, 0x92F8, 0xBBF7, 0x92F9, 0xBBF8, 0xB9CC, 0xBBF9, 0xB9CD, 0xBBFA, 0x92FA, 0xBBFB, 0x92FB, + 0xBBFC, 0xB9CE, 0xBBFD, 0x92FC, 0xBBFE, 0x92FD, 0xBBFF, 0xB9CF, 0xBC00, 0xB9D0, 0xBC01, 0x92FE, 0xBC02, 0xB9D1, 0xBC03, 0x9341, + 0xBC04, 0x9342, 0xBC05, 0x9343, 0xBC06, 0x9344, 0xBC07, 0x9345, 0xBC08, 0xB9D2, 0xBC09, 0xB9D3, 0xBC0A, 0x9346, 0xBC0B, 0xB9D4, + 0xBC0C, 0xB9D5, 0xBC0D, 0xB9D6, 0xBC0E, 0x9347, 0xBC0F, 0xB9D7, 0xBC10, 0x9348, 0xBC11, 0xB9D8, 0xBC12, 0x9349, 0xBC13, 0x934A, + 0xBC14, 0xB9D9, 0xBC15, 0xB9DA, 0xBC16, 0xB9DB, 0xBC17, 0xB9DC, 0xBC18, 0xB9DD, 0xBC19, 0x934B, 0xBC1A, 0x934C, 0xBC1B, 0xB9DE, + 0xBC1C, 0xB9DF, 0xBC1D, 0xB9E0, 0xBC1E, 0xB9E1, 0xBC1F, 0xB9E2, 0xBC20, 0x934D, 0xBC21, 0x934E, 0xBC22, 0x934F, 0xBC23, 0x9350, + 0xBC24, 0xB9E3, 0xBC25, 0xB9E4, 0xBC26, 0x9351, 0xBC27, 0xB9E5, 0xBC28, 0x9352, 0xBC29, 0xB9E6, 0xBC2A, 0x9353, 0xBC2B, 0x9354, + 0xBC2C, 0x9355, 0xBC2D, 0xB9E7, 0xBC2E, 0x9356, 0xBC2F, 0x9357, 0xBC30, 0xB9E8, 0xBC31, 0xB9E9, 0xBC32, 0x9358, 0xBC33, 0x9359, + 0xBC34, 0xB9EA, 0xBC35, 0x935A, 0xBC36, 0x9361, 0xBC37, 0x9362, 0xBC38, 0xB9EB, 0xBC39, 0x9363, 0xBC3A, 0x9364, 0xBC3B, 0x9365, + 0xBC3C, 0x9366, 0xBC3D, 0x9367, 0xBC3E, 0x9368, 0xBC3F, 0x9369, 0xBC40, 0xB9EC, 0xBC41, 0xB9ED, 0xBC42, 0x936A, 0xBC43, 0xB9EE, + 0xBC44, 0xB9EF, 0xBC45, 0xB9F0, 0xBC46, 0x936B, 0xBC47, 0x936C, 0xBC48, 0x936D, 0xBC49, 0xB9F1, 0xBC4A, 0x936E, 0xBC4B, 0x936F, + 0xBC4C, 0xB9F2, 0xBC4D, 0xB9F3, 0xBC4E, 0x9370, 0xBC4F, 0x9371, 0xBC50, 0xB9F4, 0xBC51, 0x9372, 0xBC52, 0x9373, 0xBC53, 0x9374, + 0xBC54, 0x9375, 0xBC55, 0x9376, 0xBC56, 0x9377, 0xBC57, 0x9378, 0xBC58, 0x9379, 0xBC59, 0x937A, 0xBC5A, 0x9381, 0xBC5B, 0x9382, + 0xBC5C, 0x9383, 0xBC5D, 0xB9F5, 0xBC5E, 0x9384, 0xBC5F, 0x9385, 0xBC60, 0x9386, 0xBC61, 0x9387, 0xBC62, 0x9388, 0xBC63, 0x9389, + 0xBC64, 0x938A, 0xBC65, 0x938B, 0xBC66, 0x938C, 0xBC67, 0x938D, 0xBC68, 0x938E, 0xBC69, 0x938F, 0xBC6A, 0x9390, 0xBC6B, 0x9391, + 0xBC6C, 0x9392, 0xBC6D, 0x9393, 0xBC6E, 0x9394, 0xBC6F, 0x9395, 0xBC70, 0x9396, 0xBC71, 0x9397, 0xBC72, 0x9398, 0xBC73, 0x9399, + 0xBC74, 0x939A, 0xBC75, 0x939B, 0xBC76, 0x939C, 0xBC77, 0x939D, 0xBC78, 0x939E, 0xBC79, 0x939F, 0xBC7A, 0x93A0, 0xBC7B, 0x93A1, + 0xBC7C, 0x93A2, 0xBC7D, 0x93A3, 0xBC7E, 0x93A4, 0xBC7F, 0x93A5, 0xBC80, 0x93A6, 0xBC81, 0x93A7, 0xBC82, 0x93A8, 0xBC83, 0x93A9, + 0xBC84, 0xB9F6, 0xBC85, 0xB9F7, 0xBC86, 0x93AA, 0xBC87, 0x93AB, 0xBC88, 0xB9F8, 0xBC89, 0x93AC, 0xBC8A, 0x93AD, 0xBC8B, 0xB9F9, + 0xBC8C, 0xB9FA, 0xBC8D, 0x93AE, 0xBC8E, 0xB9FB, 0xBC8F, 0x93AF, 0xBC90, 0x93B0, 0xBC91, 0x93B1, 0xBC92, 0x93B2, 0xBC93, 0x93B3, + 0xBC94, 0xB9FC, 0xBC95, 0xB9FD, 0xBC96, 0x93B4, 0xBC97, 0xB9FE, 0xBC98, 0x93B5, 0xBC99, 0xBAA1, 0xBC9A, 0xBAA2, 0xBC9B, 0x93B6, + 0xBC9C, 0x93B7, 0xBC9D, 0x93B8, 0xBC9E, 0x93B9, 0xBC9F, 0x93BA, 0xBCA0, 0xBAA3, 0xBCA1, 0xBAA4, 0xBCA2, 0x93BB, 0xBCA3, 0x93BC, + 0xBCA4, 0xBAA5, 0xBCA5, 0x93BD, 0xBCA6, 0x93BE, 0xBCA7, 0xBAA6, 0xBCA8, 0xBAA7, 0xBCA9, 0x93BF, 0xBCAA, 0x93C0, 0xBCAB, 0x93C1, + 0xBCAC, 0x93C2, 0xBCAD, 0x93C3, 0xBCAE, 0x93C4, 0xBCAF, 0x93C5, 0xBCB0, 0xBAA8, 0xBCB1, 0xBAA9, 0xBCB2, 0x93C6, 0xBCB3, 0xBAAA, + 0xBCB4, 0xBAAB, 0xBCB5, 0xBAAC, 0xBCB6, 0x93C7, 0xBCB7, 0x93C8, 0xBCB8, 0x93C9, 0xBCB9, 0x93CA, 0xBCBA, 0x93CB, 0xBCBB, 0x93CC, + 0xBCBC, 0xBAAD, 0xBCBD, 0xBAAE, 0xBCBE, 0x93CD, 0xBCBF, 0x93CE, 0xBCC0, 0xBAAF, 0xBCC1, 0x93CF, 0xBCC2, 0x93D0, 0xBCC3, 0x93D1, + 0xBCC4, 0xBAB0, 0xBCC5, 0x93D2, 0xBCC6, 0x93D3, 0xBCC7, 0x93D4, 0xBCC8, 0x93D5, 0xBCC9, 0x93D6, 0xBCCA, 0x93D7, 0xBCCB, 0x93D8, + 0xBCCC, 0x93D9, 0xBCCD, 0xBAB1, 0xBCCE, 0x93DA, 0xBCCF, 0xBAB2, 0xBCD0, 0xBAB3, 0xBCD1, 0xBAB4, 0xBCD2, 0x93DB, 0xBCD3, 0x93DC, + 0xBCD4, 0x93DD, 0xBCD5, 0xBAB5, 0xBCD6, 0x93DE, 0xBCD7, 0x93DF, 0xBCD8, 0xBAB6, 0xBCD9, 0x93E0, 0xBCDA, 0x93E1, 0xBCDB, 0x93E2, + 0xBCDC, 0xBAB7, 0xBCDD, 0x93E3, 0xBCDE, 0x93E4, 0xBCDF, 0x93E5, 0xBCE0, 0x93E6, 0xBCE1, 0x93E7, 0xBCE2, 0x93E8, 0xBCE3, 0x93E9, + 0xBCE4, 0x93EA, 0xBCE5, 0x93EB, 0xBCE6, 0x93EC, 0xBCE7, 0x93ED, 0xBCE8, 0x93EE, 0xBCE9, 0x93EF, 0xBCEA, 0x93F0, 0xBCEB, 0x93F1, + 0xBCEC, 0x93F2, 0xBCED, 0x93F3, 0xBCEE, 0x93F4, 0xBCEF, 0x93F5, 0xBCF0, 0x93F6, 0xBCF1, 0x93F7, 0xBCF2, 0x93F8, 0xBCF3, 0x93F9, + 0xBCF4, 0xBAB8, 0xBCF5, 0xBAB9, 0xBCF6, 0xBABA, 0xBCF7, 0x93FA, 0xBCF8, 0xBABB, 0xBCF9, 0x93FB, 0xBCFA, 0x93FC, 0xBCFB, 0x93FD, + 0xBCFC, 0xBABC, 0xBCFD, 0x93FE, 0xBCFE, 0x9441, 0xBCFF, 0x9442, 0xBD00, 0x9443, 0xBD01, 0x9444, 0xBD02, 0x9445, 0xBD03, 0x9446, + 0xBD04, 0xBABD, 0xBD05, 0xBABE, 0xBD06, 0x9447, 0xBD07, 0xBABF, 0xBD08, 0x9448, 0xBD09, 0xBAC0, 0xBD0A, 0x9449, 0xBD0B, 0x944A, + 0xBD0C, 0x944B, 0xBD0D, 0x944C, 0xBD0E, 0x944D, 0xBD0F, 0x944E, 0xBD10, 0xBAC1, 0xBD11, 0x944F, 0xBD12, 0x9450, 0xBD13, 0x9451, + 0xBD14, 0xBAC2, 0xBD15, 0x9452, 0xBD16, 0x9453, 0xBD17, 0x9454, 0xBD18, 0x9455, 0xBD19, 0x9456, 0xBD1A, 0x9457, 0xBD1B, 0x9458, + 0xBD1C, 0x9459, 0xBD1D, 0x945A, 0xBD1E, 0x9461, 0xBD1F, 0x9462, 0xBD20, 0x9463, 0xBD21, 0x9464, 0xBD22, 0x9465, 0xBD23, 0x9466, + 0xBD24, 0xBAC3, 0xBD25, 0x9467, 0xBD26, 0x9468, 0xBD27, 0x9469, 0xBD28, 0x946A, 0xBD29, 0x946B, 0xBD2A, 0x946C, 0xBD2B, 0x946D, + 0xBD2C, 0xBAC4, 0xBD2D, 0x946E, 0xBD2E, 0x946F, 0xBD2F, 0x9470, 0xBD30, 0x9471, 0xBD31, 0x9472, 0xBD32, 0x9473, 0xBD33, 0x9474, + 0xBD34, 0x9475, 0xBD35, 0x9476, 0xBD36, 0x9477, 0xBD37, 0x9478, 0xBD38, 0x9479, 0xBD39, 0x947A, 0xBD3A, 0x9481, 0xBD3B, 0x9482, + 0xBD3C, 0x9483, 0xBD3D, 0x9484, 0xBD3E, 0x9485, 0xBD3F, 0x9486, 0xBD40, 0xBAC5, 0xBD41, 0x9487, 0xBD42, 0x9488, 0xBD43, 0x9489, + 0xBD44, 0x948A, 0xBD45, 0x948B, 0xBD46, 0x948C, 0xBD47, 0x948D, 0xBD48, 0xBAC6, 0xBD49, 0xBAC7, 0xBD4A, 0x948E, 0xBD4B, 0x948F, + 0xBD4C, 0xBAC8, 0xBD4D, 0x9490, 0xBD4E, 0x9491, 0xBD4F, 0x9492, 0xBD50, 0xBAC9, 0xBD51, 0x9493, 0xBD52, 0x9494, 0xBD53, 0x9495, + 0xBD54, 0x9496, 0xBD55, 0x9497, 0xBD56, 0x9498, 0xBD57, 0x9499, 0xBD58, 0xBACA, 0xBD59, 0xBACB, 0xBD5A, 0x949A, 0xBD5B, 0x949B, + 0xBD5C, 0x949C, 0xBD5D, 0x949D, 0xBD5E, 0x949E, 0xBD5F, 0x949F, 0xBD60, 0x94A0, 0xBD61, 0x94A1, 0xBD62, 0x94A2, 0xBD63, 0x94A3, + 0xBD64, 0xBACC, 0xBD65, 0x94A4, 0xBD66, 0x94A5, 0xBD67, 0x94A6, 0xBD68, 0xBACD, 0xBD69, 0x94A7, 0xBD6A, 0x94A8, 0xBD6B, 0x94A9, + 0xBD6C, 0x94AA, 0xBD6D, 0x94AB, 0xBD6E, 0x94AC, 0xBD6F, 0x94AD, 0xBD70, 0x94AE, 0xBD71, 0x94AF, 0xBD72, 0x94B0, 0xBD73, 0x94B1, + 0xBD74, 0x94B2, 0xBD75, 0x94B3, 0xBD76, 0x94B4, 0xBD77, 0x94B5, 0xBD78, 0x94B6, 0xBD79, 0x94B7, 0xBD7A, 0x94B8, 0xBD7B, 0x94B9, + 0xBD7C, 0x94BA, 0xBD7D, 0x94BB, 0xBD7E, 0x94BC, 0xBD7F, 0x94BD, 0xBD80, 0xBACE, 0xBD81, 0xBACF, 0xBD82, 0x94BE, 0xBD83, 0x94BF, + 0xBD84, 0xBAD0, 0xBD85, 0x94C0, 0xBD86, 0x94C1, 0xBD87, 0xBAD1, 0xBD88, 0xBAD2, 0xBD89, 0xBAD3, 0xBD8A, 0xBAD4, 0xBD8B, 0x94C2, + 0xBD8C, 0x94C3, 0xBD8D, 0x94C4, 0xBD8E, 0x94C5, 0xBD8F, 0x94C6, 0xBD90, 0xBAD5, 0xBD91, 0xBAD6, 0xBD92, 0x94C7, 0xBD93, 0xBAD7, + 0xBD94, 0x94C8, 0xBD95, 0xBAD8, 0xBD96, 0x94C9, 0xBD97, 0x94CA, 0xBD98, 0x94CB, 0xBD99, 0xBAD9, 0xBD9A, 0xBADA, 0xBD9B, 0x94CC, + 0xBD9C, 0xBADB, 0xBD9D, 0x94CD, 0xBD9E, 0x94CE, 0xBD9F, 0x94CF, 0xBDA0, 0x94D0, 0xBDA1, 0x94D1, 0xBDA2, 0x94D2, 0xBDA3, 0x94D3, + 0xBDA4, 0xBADC, 0xBDA5, 0x94D4, 0xBDA6, 0x94D5, 0xBDA7, 0x94D6, 0xBDA8, 0x94D7, 0xBDA9, 0x94D8, 0xBDAA, 0x94D9, 0xBDAB, 0x94DA, + 0xBDAC, 0x94DB, 0xBDAD, 0x94DC, 0xBDAE, 0x94DD, 0xBDAF, 0x94DE, 0xBDB0, 0xBADD, 0xBDB1, 0x94DF, 0xBDB2, 0x94E0, 0xBDB3, 0x94E1, + 0xBDB4, 0x94E2, 0xBDB5, 0x94E3, 0xBDB6, 0x94E4, 0xBDB7, 0x94E5, 0xBDB8, 0xBADE, 0xBDB9, 0x94E6, 0xBDBA, 0x94E7, 0xBDBB, 0x94E8, + 0xBDBC, 0x94E9, 0xBDBD, 0x94EA, 0xBDBE, 0x94EB, 0xBDBF, 0x94EC, 0xBDC0, 0x94ED, 0xBDC1, 0x94EE, 0xBDC2, 0x94EF, 0xBDC3, 0x94F0, + 0xBDC4, 0x94F1, 0xBDC5, 0x94F2, 0xBDC6, 0x94F3, 0xBDC7, 0x94F4, 0xBDC8, 0x94F5, 0xBDC9, 0x94F6, 0xBDCA, 0x94F7, 0xBDCB, 0x94F8, + 0xBDCC, 0x94F9, 0xBDCD, 0x94FA, 0xBDCE, 0x94FB, 0xBDCF, 0x94FC, 0xBDD0, 0x94FD, 0xBDD1, 0x94FE, 0xBDD2, 0x9541, 0xBDD3, 0x9542, + 0xBDD4, 0xBADF, 0xBDD5, 0xBAE0, 0xBDD6, 0x9543, 0xBDD7, 0x9544, 0xBDD8, 0xBAE1, 0xBDD9, 0x9545, 0xBDDA, 0x9546, 0xBDDB, 0x9547, + 0xBDDC, 0xBAE2, 0xBDDD, 0x9548, 0xBDDE, 0x9549, 0xBDDF, 0x954A, 0xBDE0, 0x954B, 0xBDE1, 0x954C, 0xBDE2, 0x954D, 0xBDE3, 0x954E, + 0xBDE4, 0x954F, 0xBDE5, 0x9550, 0xBDE6, 0x9551, 0xBDE7, 0x9552, 0xBDE8, 0x9553, 0xBDE9, 0xBAE3, 0xBDEA, 0x9554, 0xBDEB, 0x9555, + 0xBDEC, 0x9556, 0xBDED, 0x9557, 0xBDEE, 0x9558, 0xBDEF, 0x9559, 0xBDF0, 0xBAE4, 0xBDF1, 0x955A, 0xBDF2, 0x9561, 0xBDF3, 0x9562, + 0xBDF4, 0xBAE5, 0xBDF5, 0x9563, 0xBDF6, 0x9564, 0xBDF7, 0x9565, 0xBDF8, 0xBAE6, 0xBDF9, 0x9566, 0xBDFA, 0x9567, 0xBDFB, 0x9568, + 0xBDFC, 0x9569, 0xBDFD, 0x956A, 0xBDFE, 0x956B, 0xBDFF, 0x956C, 0xBE00, 0xBAE7, 0xBE01, 0x956D, 0xBE02, 0x956E, 0xBE03, 0xBAE8, + 0xBE04, 0x956F, 0xBE05, 0xBAE9, 0xBE06, 0x9570, 0xBE07, 0x9571, 0xBE08, 0x9572, 0xBE09, 0x9573, 0xBE0A, 0x9574, 0xBE0B, 0x9575, + 0xBE0C, 0xBAEA, 0xBE0D, 0xBAEB, 0xBE0E, 0x9576, 0xBE0F, 0x9577, 0xBE10, 0xBAEC, 0xBE11, 0x9578, 0xBE12, 0x9579, 0xBE13, 0x957A, + 0xBE14, 0xBAED, 0xBE15, 0x9581, 0xBE16, 0x9582, 0xBE17, 0x9583, 0xBE18, 0x9584, 0xBE19, 0x9585, 0xBE1A, 0x9586, 0xBE1B, 0x9587, + 0xBE1C, 0xBAEE, 0xBE1D, 0xBAEF, 0xBE1E, 0x9588, 0xBE1F, 0xBAF0, 0xBE20, 0x9589, 0xBE21, 0x958A, 0xBE22, 0x958B, 0xBE23, 0x958C, + 0xBE24, 0x958D, 0xBE25, 0x958E, 0xBE26, 0x958F, 0xBE27, 0x9590, 0xBE28, 0x9591, 0xBE29, 0x9592, 0xBE2A, 0x9593, 0xBE2B, 0x9594, + 0xBE2C, 0x9595, 0xBE2D, 0x9596, 0xBE2E, 0x9597, 0xBE2F, 0x9598, 0xBE30, 0x9599, 0xBE31, 0x959A, 0xBE32, 0x959B, 0xBE33, 0x959C, + 0xBE34, 0x959D, 0xBE35, 0x959E, 0xBE36, 0x959F, 0xBE37, 0x95A0, 0xBE38, 0x95A1, 0xBE39, 0x95A2, 0xBE3A, 0x95A3, 0xBE3B, 0x95A4, + 0xBE3C, 0x95A5, 0xBE3D, 0x95A6, 0xBE3E, 0x95A7, 0xBE3F, 0x95A8, 0xBE40, 0x95A9, 0xBE41, 0x95AA, 0xBE42, 0x95AB, 0xBE43, 0x95AC, + 0xBE44, 0xBAF1, 0xBE45, 0xBAF2, 0xBE46, 0x95AD, 0xBE47, 0x95AE, 0xBE48, 0xBAF3, 0xBE49, 0x95AF, 0xBE4A, 0x95B0, 0xBE4B, 0x95B1, + 0xBE4C, 0xBAF4, 0xBE4D, 0x95B2, 0xBE4E, 0xBAF5, 0xBE4F, 0x95B3, 0xBE50, 0x95B4, 0xBE51, 0x95B5, 0xBE52, 0x95B6, 0xBE53, 0x95B7, + 0xBE54, 0xBAF6, 0xBE55, 0xBAF7, 0xBE56, 0x95B8, 0xBE57, 0xBAF8, 0xBE58, 0x95B9, 0xBE59, 0xBAF9, 0xBE5A, 0xBAFA, 0xBE5B, 0xBAFB, + 0xBE5C, 0x95BA, 0xBE5D, 0x95BB, 0xBE5E, 0x95BC, 0xBE5F, 0x95BD, 0xBE60, 0xBAFC, 0xBE61, 0xBAFD, 0xBE62, 0x95BE, 0xBE63, 0x95BF, + 0xBE64, 0xBAFE, 0xBE65, 0x95C0, 0xBE66, 0x95C1, 0xBE67, 0x95C2, 0xBE68, 0xBBA1, 0xBE69, 0x95C3, 0xBE6A, 0xBBA2, 0xBE6B, 0x95C4, + 0xBE6C, 0x95C5, 0xBE6D, 0x95C6, 0xBE6E, 0x95C7, 0xBE6F, 0x95C8, 0xBE70, 0xBBA3, 0xBE71, 0xBBA4, 0xBE72, 0x95C9, 0xBE73, 0xBBA5, + 0xBE74, 0xBBA6, 0xBE75, 0xBBA7, 0xBE76, 0x95CA, 0xBE77, 0x95CB, 0xBE78, 0x95CC, 0xBE79, 0x95CD, 0xBE7A, 0x95CE, 0xBE7B, 0xBBA8, + 0xBE7C, 0xBBA9, 0xBE7D, 0xBBAA, 0xBE7E, 0x95CF, 0xBE7F, 0x95D0, 0xBE80, 0xBBAB, 0xBE81, 0x95D1, 0xBE82, 0x95D2, 0xBE83, 0x95D3, + 0xBE84, 0xBBAC, 0xBE85, 0x95D4, 0xBE86, 0x95D5, 0xBE87, 0x95D6, 0xBE88, 0x95D7, 0xBE89, 0x95D8, 0xBE8A, 0x95D9, 0xBE8B, 0x95DA, + 0xBE8C, 0xBBAD, 0xBE8D, 0xBBAE, 0xBE8E, 0x95DB, 0xBE8F, 0xBBAF, 0xBE90, 0xBBB0, 0xBE91, 0xBBB1, 0xBE92, 0x95DC, 0xBE93, 0x95DD, + 0xBE94, 0x95DE, 0xBE95, 0x95DF, 0xBE96, 0x95E0, 0xBE97, 0x95E1, 0xBE98, 0xBBB2, 0xBE99, 0xBBB3, 0xBE9A, 0x95E2, 0xBE9B, 0x95E3, + 0xBE9C, 0x95E4, 0xBE9D, 0x95E5, 0xBE9E, 0x95E6, 0xBE9F, 0x95E7, 0xBEA0, 0x95E8, 0xBEA1, 0x95E9, 0xBEA2, 0x95EA, 0xBEA3, 0x95EB, + 0xBEA4, 0x95EC, 0xBEA5, 0x95ED, 0xBEA6, 0x95EE, 0xBEA7, 0x95EF, 0xBEA8, 0xBBB4, 0xBEA9, 0x95F0, 0xBEAA, 0x95F1, 0xBEAB, 0x95F2, + 0xBEAC, 0x95F3, 0xBEAD, 0x95F4, 0xBEAE, 0x95F5, 0xBEAF, 0x95F6, 0xBEB0, 0x95F7, 0xBEB1, 0x95F8, 0xBEB2, 0x95F9, 0xBEB3, 0x95FA, + 0xBEB4, 0x95FB, 0xBEB5, 0x95FC, 0xBEB6, 0x95FD, 0xBEB7, 0x95FE, 0xBEB8, 0x9641, 0xBEB9, 0x9642, 0xBEBA, 0x9643, 0xBEBB, 0x9644, + 0xBEBC, 0x9645, 0xBEBD, 0x9646, 0xBEBE, 0x9647, 0xBEBF, 0x9648, 0xBEC0, 0x9649, 0xBEC1, 0x964A, 0xBEC2, 0x964B, 0xBEC3, 0x964C, + 0xBEC4, 0x964D, 0xBEC5, 0x964E, 0xBEC6, 0x964F, 0xBEC7, 0x9650, 0xBEC8, 0x9651, 0xBEC9, 0x9652, 0xBECA, 0x9653, 0xBECB, 0x9654, + 0xBECC, 0x9655, 0xBECD, 0x9656, 0xBECE, 0x9657, 0xBECF, 0x9658, 0xBED0, 0xBBB5, 0xBED1, 0xBBB6, 0xBED2, 0x9659, 0xBED3, 0x965A, + 0xBED4, 0xBBB7, 0xBED5, 0x9661, 0xBED6, 0x9662, 0xBED7, 0xBBB8, 0xBED8, 0xBBB9, 0xBED9, 0x9663, 0xBEDA, 0x9664, 0xBEDB, 0x9665, + 0xBEDC, 0x9666, 0xBEDD, 0x9667, 0xBEDE, 0x9668, 0xBEDF, 0x9669, 0xBEE0, 0xBBBA, 0xBEE1, 0x966A, 0xBEE2, 0x966B, 0xBEE3, 0xBBBB, + 0xBEE4, 0xBBBC, 0xBEE5, 0xBBBD, 0xBEE6, 0x966C, 0xBEE7, 0x966D, 0xBEE8, 0x966E, 0xBEE9, 0x966F, 0xBEEA, 0x9670, 0xBEEB, 0x9671, + 0xBEEC, 0xBBBE, 0xBEED, 0x9672, 0xBEEE, 0x9673, 0xBEEF, 0x9674, 0xBEF0, 0x9675, 0xBEF1, 0x9676, 0xBEF2, 0x9677, 0xBEF3, 0x9678, + 0xBEF4, 0x9679, 0xBEF5, 0x967A, 0xBEF6, 0x9681, 0xBEF7, 0x9682, 0xBEF8, 0x9683, 0xBEF9, 0x9684, 0xBEFA, 0x9685, 0xBEFB, 0x9686, + 0xBEFC, 0x9687, 0xBEFD, 0x9688, 0xBEFE, 0x9689, 0xBEFF, 0x968A, 0xBF00, 0x968B, 0xBF01, 0xBBBF, 0xBF02, 0x968C, 0xBF03, 0x968D, + 0xBF04, 0x968E, 0xBF05, 0x968F, 0xBF06, 0x9690, 0xBF07, 0x9691, 0xBF08, 0xBBC0, 0xBF09, 0xBBC1, 0xBF0A, 0x9692, 0xBF0B, 0x9693, + 0xBF0C, 0x9694, 0xBF0D, 0x9695, 0xBF0E, 0x9696, 0xBF0F, 0x9697, 0xBF10, 0x9698, 0xBF11, 0x9699, 0xBF12, 0x969A, 0xBF13, 0x969B, + 0xBF14, 0x969C, 0xBF15, 0x969D, 0xBF16, 0x969E, 0xBF17, 0x969F, 0xBF18, 0xBBC2, 0xBF19, 0xBBC3, 0xBF1A, 0x96A0, 0xBF1B, 0xBBC4, + 0xBF1C, 0xBBC5, 0xBF1D, 0xBBC6, 0xBF1E, 0x96A1, 0xBF1F, 0x96A2, 0xBF20, 0x96A3, 0xBF21, 0x96A4, 0xBF22, 0x96A5, 0xBF23, 0x96A6, + 0xBF24, 0x96A7, 0xBF25, 0x96A8, 0xBF26, 0x96A9, 0xBF27, 0x96AA, 0xBF28, 0x96AB, 0xBF29, 0x96AC, 0xBF2A, 0x96AD, 0xBF2B, 0x96AE, + 0xBF2C, 0x96AF, 0xBF2D, 0x96B0, 0xBF2E, 0x96B1, 0xBF2F, 0x96B2, 0xBF30, 0x96B3, 0xBF31, 0x96B4, 0xBF32, 0x96B5, 0xBF33, 0x96B6, + 0xBF34, 0x96B7, 0xBF35, 0x96B8, 0xBF36, 0x96B9, 0xBF37, 0x96BA, 0xBF38, 0x96BB, 0xBF39, 0x96BC, 0xBF3A, 0x96BD, 0xBF3B, 0x96BE, + 0xBF3C, 0x96BF, 0xBF3D, 0x96C0, 0xBF3E, 0x96C1, 0xBF3F, 0x96C2, 0xBF40, 0xBBC7, 0xBF41, 0xBBC8, 0xBF42, 0x96C3, 0xBF43, 0x96C4, + 0xBF44, 0xBBC9, 0xBF45, 0x96C5, 0xBF46, 0x96C6, 0xBF47, 0x96C7, 0xBF48, 0xBBCA, 0xBF49, 0x96C8, 0xBF4A, 0x96C9, 0xBF4B, 0x96CA, + 0xBF4C, 0x96CB, 0xBF4D, 0x96CC, 0xBF4E, 0x96CD, 0xBF4F, 0x96CE, 0xBF50, 0xBBCB, 0xBF51, 0xBBCC, 0xBF52, 0x96CF, 0xBF53, 0x96D0, + 0xBF54, 0x96D1, 0xBF55, 0xBBCD, 0xBF56, 0x96D2, 0xBF57, 0x96D3, 0xBF58, 0x96D4, 0xBF59, 0x96D5, 0xBF5A, 0x96D6, 0xBF5B, 0x96D7, + 0xBF5C, 0x96D8, 0xBF5D, 0x96D9, 0xBF5E, 0x96DA, 0xBF5F, 0x96DB, 0xBF60, 0x96DC, 0xBF61, 0x96DD, 0xBF62, 0x96DE, 0xBF63, 0x96DF, + 0xBF64, 0x96E0, 0xBF65, 0x96E1, 0xBF66, 0x96E2, 0xBF67, 0x96E3, 0xBF68, 0x96E4, 0xBF69, 0x96E5, 0xBF6A, 0x96E6, 0xBF6B, 0x96E7, + 0xBF6C, 0x96E8, 0xBF6D, 0x96E9, 0xBF6E, 0x96EA, 0xBF6F, 0x96EB, 0xBF70, 0x96EC, 0xBF71, 0x96ED, 0xBF72, 0x96EE, 0xBF73, 0x96EF, + 0xBF74, 0x96F0, 0xBF75, 0x96F1, 0xBF76, 0x96F2, 0xBF77, 0x96F3, 0xBF78, 0x96F4, 0xBF79, 0x96F5, 0xBF7A, 0x96F6, 0xBF7B, 0x96F7, + 0xBF7C, 0x96F8, 0xBF7D, 0x96F9, 0xBF7E, 0x96FA, 0xBF7F, 0x96FB, 0xBF80, 0x96FC, 0xBF81, 0x96FD, 0xBF82, 0x96FE, 0xBF83, 0x9741, + 0xBF84, 0x9742, 0xBF85, 0x9743, 0xBF86, 0x9744, 0xBF87, 0x9745, 0xBF88, 0x9746, 0xBF89, 0x9747, 0xBF8A, 0x9748, 0xBF8B, 0x9749, + 0xBF8C, 0x974A, 0xBF8D, 0x974B, 0xBF8E, 0x974C, 0xBF8F, 0x974D, 0xBF90, 0x974E, 0xBF91, 0x974F, 0xBF92, 0x9750, 0xBF93, 0x9751, + 0xBF94, 0xBBCE, 0xBF95, 0x9752, 0xBF96, 0x9753, 0xBF97, 0x9754, 0xBF98, 0x9755, 0xBF99, 0x9756, 0xBF9A, 0x9757, 0xBF9B, 0x9758, + 0xBF9C, 0x9759, 0xBF9D, 0x975A, 0xBF9E, 0x9761, 0xBF9F, 0x9762, 0xBFA0, 0x9763, 0xBFA1, 0x9764, 0xBFA2, 0x9765, 0xBFA3, 0x9766, + 0xBFA4, 0x9767, 0xBFA5, 0x9768, 0xBFA6, 0x9769, 0xBFA7, 0x976A, 0xBFA8, 0x976B, 0xBFA9, 0x976C, 0xBFAA, 0x976D, 0xBFAB, 0x976E, + 0xBFAC, 0x976F, 0xBFAD, 0x9770, 0xBFAE, 0x9771, 0xBFAF, 0x9772, 0xBFB0, 0xBBCF, 0xBFB1, 0x9773, 0xBFB2, 0x9774, 0xBFB3, 0x9775, + 0xBFB4, 0x9776, 0xBFB5, 0x9777, 0xBFB6, 0x9778, 0xBFB7, 0x9779, 0xBFB8, 0x977A, 0xBFB9, 0x9781, 0xBFBA, 0x9782, 0xBFBB, 0x9783, + 0xBFBC, 0x9784, 0xBFBD, 0x9785, 0xBFBE, 0x9786, 0xBFBF, 0x9787, 0xBFC0, 0x9788, 0xBFC1, 0x9789, 0xBFC2, 0x978A, 0xBFC3, 0x978B, + 0xBFC4, 0x978C, 0xBFC5, 0xBBD0, 0xBFC6, 0x978D, 0xBFC7, 0x978E, 0xBFC8, 0x978F, 0xBFC9, 0x9790, 0xBFCA, 0x9791, 0xBFCB, 0x9792, + 0xBFCC, 0xBBD1, 0xBFCD, 0xBBD2, 0xBFCE, 0x9793, 0xBFCF, 0x9794, 0xBFD0, 0xBBD3, 0xBFD1, 0x9795, 0xBFD2, 0x9796, 0xBFD3, 0x9797, + 0xBFD4, 0xBBD4, 0xBFD5, 0x9798, 0xBFD6, 0x9799, 0xBFD7, 0x979A, 0xBFD8, 0x979B, 0xBFD9, 0x979C, 0xBFDA, 0x979D, 0xBFDB, 0x979E, + 0xBFDC, 0xBBD5, 0xBFDD, 0x979F, 0xBFDE, 0x97A0, 0xBFDF, 0xBBD6, 0xBFE0, 0x97A1, 0xBFE1, 0xBBD7, 0xBFE2, 0x97A2, 0xBFE3, 0x97A3, + 0xBFE4, 0x97A4, 0xBFE5, 0x97A5, 0xBFE6, 0x97A6, 0xBFE7, 0x97A7, 0xBFE8, 0x97A8, 0xBFE9, 0x97A9, 0xBFEA, 0x97AA, 0xBFEB, 0x97AB, + 0xBFEC, 0x97AC, 0xBFED, 0x97AD, 0xBFEE, 0x97AE, 0xBFEF, 0x97AF, 0xBFF0, 0x97B0, 0xBFF1, 0x97B1, 0xBFF2, 0x97B2, 0xBFF3, 0x97B3, + 0xBFF4, 0x97B4, 0xBFF5, 0x97B5, 0xBFF6, 0x97B6, 0xBFF7, 0x97B7, 0xBFF8, 0x97B8, 0xBFF9, 0x97B9, 0xBFFA, 0x97BA, 0xBFFB, 0x97BB, + 0xBFFC, 0x97BC, 0xBFFD, 0x97BD, 0xBFFE, 0x97BE, 0xBFFF, 0x97BF, 0xC000, 0x97C0, 0xC001, 0x97C1, 0xC002, 0x97C2, 0xC003, 0x97C3, + 0xC004, 0x97C4, 0xC005, 0x97C5, 0xC006, 0x97C6, 0xC007, 0x97C7, 0xC008, 0x97C8, 0xC009, 0x97C9, 0xC00A, 0x97CA, 0xC00B, 0x97CB, + 0xC00C, 0x97CC, 0xC00D, 0x97CD, 0xC00E, 0x97CE, 0xC00F, 0x97CF, 0xC010, 0x97D0, 0xC011, 0x97D1, 0xC012, 0x97D2, 0xC013, 0x97D3, + 0xC014, 0x97D4, 0xC015, 0x97D5, 0xC016, 0x97D6, 0xC017, 0x97D7, 0xC018, 0x97D8, 0xC019, 0x97D9, 0xC01A, 0x97DA, 0xC01B, 0x97DB, + 0xC01C, 0x97DC, 0xC01D, 0x97DD, 0xC01E, 0x97DE, 0xC01F, 0x97DF, 0xC020, 0x97E0, 0xC021, 0x97E1, 0xC022, 0x97E2, 0xC023, 0x97E3, + 0xC024, 0x97E4, 0xC025, 0x97E5, 0xC026, 0x97E6, 0xC027, 0x97E7, 0xC028, 0x97E8, 0xC029, 0x97E9, 0xC02A, 0x97EA, 0xC02B, 0x97EB, + 0xC02C, 0x97EC, 0xC02D, 0x97ED, 0xC02E, 0x97EE, 0xC02F, 0x97EF, 0xC030, 0x97F0, 0xC031, 0x97F1, 0xC032, 0x97F2, 0xC033, 0x97F3, + 0xC034, 0x97F4, 0xC035, 0x97F5, 0xC036, 0x97F6, 0xC037, 0x97F7, 0xC038, 0x97F8, 0xC039, 0x97F9, 0xC03A, 0x97FA, 0xC03B, 0x97FB, + 0xC03C, 0xBBD8, 0xC03D, 0x97FC, 0xC03E, 0x97FD, 0xC03F, 0x97FE, 0xC040, 0x9841, 0xC041, 0x9842, 0xC042, 0x9843, 0xC043, 0x9844, + 0xC044, 0x9845, 0xC045, 0x9846, 0xC046, 0x9847, 0xC047, 0x9848, 0xC048, 0x9849, 0xC049, 0x984A, 0xC04A, 0x984B, 0xC04B, 0x984C, + 0xC04C, 0x984D, 0xC04D, 0x984E, 0xC04E, 0x984F, 0xC04F, 0x9850, 0xC050, 0x9851, 0xC051, 0xBBD9, 0xC052, 0x9852, 0xC053, 0x9853, + 0xC054, 0x9854, 0xC055, 0x9855, 0xC056, 0x9856, 0xC057, 0x9857, 0xC058, 0xBBDA, 0xC059, 0x9858, 0xC05A, 0x9859, 0xC05B, 0x985A, + 0xC05C, 0xBBDB, 0xC05D, 0x9861, 0xC05E, 0x9862, 0xC05F, 0x9863, 0xC060, 0xBBDC, 0xC061, 0x9864, 0xC062, 0x9865, 0xC063, 0x9866, + 0xC064, 0x9867, 0xC065, 0x9868, 0xC066, 0x9869, 0xC067, 0x986A, 0xC068, 0xBBDD, 0xC069, 0xBBDE, 0xC06A, 0x986B, 0xC06B, 0x986C, + 0xC06C, 0x986D, 0xC06D, 0x986E, 0xC06E, 0x986F, 0xC06F, 0x9870, 0xC070, 0x9871, 0xC071, 0x9872, 0xC072, 0x9873, 0xC073, 0x9874, + 0xC074, 0x9875, 0xC075, 0x9876, 0xC076, 0x9877, 0xC077, 0x9878, 0xC078, 0x9879, 0xC079, 0x987A, 0xC07A, 0x9881, 0xC07B, 0x9882, + 0xC07C, 0x9883, 0xC07D, 0x9884, 0xC07E, 0x9885, 0xC07F, 0x9886, 0xC080, 0x9887, 0xC081, 0x9888, 0xC082, 0x9889, 0xC083, 0x988A, + 0xC084, 0x988B, 0xC085, 0x988C, 0xC086, 0x988D, 0xC087, 0x988E, 0xC088, 0x988F, 0xC089, 0x9890, 0xC08A, 0x9891, 0xC08B, 0x9892, + 0xC08C, 0x9893, 0xC08D, 0x9894, 0xC08E, 0x9895, 0xC08F, 0x9896, 0xC090, 0xBBDF, 0xC091, 0xBBE0, 0xC092, 0x9897, 0xC093, 0x9898, + 0xC094, 0xBBE1, 0xC095, 0x9899, 0xC096, 0x989A, 0xC097, 0x989B, 0xC098, 0xBBE2, 0xC099, 0x989C, 0xC09A, 0x989D, 0xC09B, 0x989E, + 0xC09C, 0x989F, 0xC09D, 0x98A0, 0xC09E, 0x98A1, 0xC09F, 0x98A2, 0xC0A0, 0xBBE3, 0xC0A1, 0xBBE4, 0xC0A2, 0x98A3, 0xC0A3, 0xBBE5, + 0xC0A4, 0x98A4, 0xC0A5, 0xBBE6, 0xC0A6, 0x98A5, 0xC0A7, 0x98A6, 0xC0A8, 0x98A7, 0xC0A9, 0x98A8, 0xC0AA, 0x98A9, 0xC0AB, 0x98AA, + 0xC0AC, 0xBBE7, 0xC0AD, 0xBBE8, 0xC0AE, 0x98AB, 0xC0AF, 0xBBE9, 0xC0B0, 0xBBEA, 0xC0B1, 0x98AC, 0xC0B2, 0x98AD, 0xC0B3, 0xBBEB, + 0xC0B4, 0xBBEC, 0xC0B5, 0xBBED, 0xC0B6, 0xBBEE, 0xC0B7, 0x98AE, 0xC0B8, 0x98AF, 0xC0B9, 0x98B0, 0xC0BA, 0x98B1, 0xC0BB, 0x98B2, + 0xC0BC, 0xBBEF, 0xC0BD, 0xBBF0, 0xC0BE, 0x98B3, 0xC0BF, 0xBBF1, 0xC0C0, 0xBBF2, 0xC0C1, 0xBBF3, 0xC0C2, 0x98B4, 0xC0C3, 0x98B5, + 0xC0C4, 0x98B6, 0xC0C5, 0xBBF4, 0xC0C6, 0x98B7, 0xC0C7, 0x98B8, 0xC0C8, 0xBBF5, 0xC0C9, 0xBBF6, 0xC0CA, 0x98B9, 0xC0CB, 0x98BA, + 0xC0CC, 0xBBF7, 0xC0CD, 0x98BB, 0xC0CE, 0x98BC, 0xC0CF, 0x98BD, 0xC0D0, 0xBBF8, 0xC0D1, 0x98BE, 0xC0D2, 0x98BF, 0xC0D3, 0x98C0, + 0xC0D4, 0x98C1, 0xC0D5, 0x98C2, 0xC0D6, 0x98C3, 0xC0D7, 0x98C4, 0xC0D8, 0xBBF9, 0xC0D9, 0xBBFA, 0xC0DA, 0x98C5, 0xC0DB, 0xBBFB, + 0xC0DC, 0xBBFC, 0xC0DD, 0xBBFD, 0xC0DE, 0x98C6, 0xC0DF, 0x98C7, 0xC0E0, 0x98C8, 0xC0E1, 0x98C9, 0xC0E2, 0x98CA, 0xC0E3, 0x98CB, + 0xC0E4, 0xBBFE, 0xC0E5, 0xBCA1, 0xC0E6, 0x98CC, 0xC0E7, 0x98CD, 0xC0E8, 0xBCA2, 0xC0E9, 0x98CE, 0xC0EA, 0x98CF, 0xC0EB, 0x98D0, + 0xC0EC, 0xBCA3, 0xC0ED, 0x98D1, 0xC0EE, 0x98D2, 0xC0EF, 0x98D3, 0xC0F0, 0x98D4, 0xC0F1, 0x98D5, 0xC0F2, 0x98D6, 0xC0F3, 0x98D7, + 0xC0F4, 0xBCA4, 0xC0F5, 0xBCA5, 0xC0F6, 0x98D8, 0xC0F7, 0xBCA6, 0xC0F8, 0x98D9, 0xC0F9, 0xBCA7, 0xC0FA, 0x98DA, 0xC0FB, 0x98DB, + 0xC0FC, 0x98DC, 0xC0FD, 0x98DD, 0xC0FE, 0x98DE, 0xC0FF, 0x98DF, 0xC100, 0xBCA8, 0xC101, 0x98E0, 0xC102, 0x98E1, 0xC103, 0x98E2, + 0xC104, 0xBCA9, 0xC105, 0x98E3, 0xC106, 0x98E4, 0xC107, 0x98E5, 0xC108, 0xBCAA, 0xC109, 0x98E6, 0xC10A, 0x98E7, 0xC10B, 0x98E8, + 0xC10C, 0x98E9, 0xC10D, 0x98EA, 0xC10E, 0x98EB, 0xC10F, 0x98EC, 0xC110, 0xBCAB, 0xC111, 0x98ED, 0xC112, 0x98EE, 0xC113, 0x98EF, + 0xC114, 0x98F0, 0xC115, 0xBCAC, 0xC116, 0x98F1, 0xC117, 0x98F2, 0xC118, 0x98F3, 0xC119, 0x98F4, 0xC11A, 0x98F5, 0xC11B, 0x98F6, + 0xC11C, 0xBCAD, 0xC11D, 0xBCAE, 0xC11E, 0xBCAF, 0xC11F, 0xBCB0, 0xC120, 0xBCB1, 0xC121, 0x98F7, 0xC122, 0x98F8, 0xC123, 0xBCB2, + 0xC124, 0xBCB3, 0xC125, 0x98F9, 0xC126, 0xBCB4, 0xC127, 0xBCB5, 0xC128, 0x98FA, 0xC129, 0x98FB, 0xC12A, 0x98FC, 0xC12B, 0x98FD, + 0xC12C, 0xBCB6, 0xC12D, 0xBCB7, 0xC12E, 0x98FE, 0xC12F, 0xBCB8, 0xC130, 0xBCB9, 0xC131, 0xBCBA, 0xC132, 0x9941, 0xC133, 0x9942, + 0xC134, 0x9943, 0xC135, 0x9944, 0xC136, 0xBCBB, 0xC137, 0x9945, 0xC138, 0xBCBC, 0xC139, 0xBCBD, 0xC13A, 0x9946, 0xC13B, 0x9947, + 0xC13C, 0xBCBE, 0xC13D, 0x9948, 0xC13E, 0x9949, 0xC13F, 0x994A, 0xC140, 0xBCBF, 0xC141, 0x994B, 0xC142, 0x994C, 0xC143, 0x994D, + 0xC144, 0x994E, 0xC145, 0x994F, 0xC146, 0x9950, 0xC147, 0x9951, 0xC148, 0xBCC0, 0xC149, 0xBCC1, 0xC14A, 0x9952, 0xC14B, 0xBCC2, + 0xC14C, 0xBCC3, 0xC14D, 0xBCC4, 0xC14E, 0x9953, 0xC14F, 0x9954, 0xC150, 0x9955, 0xC151, 0x9956, 0xC152, 0x9957, 0xC153, 0x9958, + 0xC154, 0xBCC5, 0xC155, 0xBCC6, 0xC156, 0x9959, 0xC157, 0x995A, 0xC158, 0xBCC7, 0xC159, 0x9961, 0xC15A, 0x9962, 0xC15B, 0x9963, + 0xC15C, 0xBCC8, 0xC15D, 0x9964, 0xC15E, 0x9965, 0xC15F, 0x9966, 0xC160, 0x9967, 0xC161, 0x9968, 0xC162, 0x9969, 0xC163, 0x996A, + 0xC164, 0xBCC9, 0xC165, 0xBCCA, 0xC166, 0x996B, 0xC167, 0xBCCB, 0xC168, 0xBCCC, 0xC169, 0xBCCD, 0xC16A, 0x996C, 0xC16B, 0x996D, + 0xC16C, 0x996E, 0xC16D, 0x996F, 0xC16E, 0x9970, 0xC16F, 0x9971, 0xC170, 0xBCCE, 0xC171, 0x9972, 0xC172, 0x9973, 0xC173, 0x9974, + 0xC174, 0xBCCF, 0xC175, 0x9975, 0xC176, 0x9976, 0xC177, 0x9977, 0xC178, 0xBCD0, 0xC179, 0x9978, 0xC17A, 0x9979, 0xC17B, 0x997A, + 0xC17C, 0x9981, 0xC17D, 0x9982, 0xC17E, 0x9983, 0xC17F, 0x9984, 0xC180, 0x9985, 0xC181, 0x9986, 0xC182, 0x9987, 0xC183, 0x9988, + 0xC184, 0x9989, 0xC185, 0xBCD1, 0xC186, 0x998A, 0xC187, 0x998B, 0xC188, 0x998C, 0xC189, 0x998D, 0xC18A, 0x998E, 0xC18B, 0x998F, + 0xC18C, 0xBCD2, 0xC18D, 0xBCD3, 0xC18E, 0xBCD4, 0xC18F, 0x9990, 0xC190, 0xBCD5, 0xC191, 0x9991, 0xC192, 0x9992, 0xC193, 0x9993, + 0xC194, 0xBCD6, 0xC195, 0x9994, 0xC196, 0xBCD7, 0xC197, 0x9995, 0xC198, 0x9996, 0xC199, 0x9997, 0xC19A, 0x9998, 0xC19B, 0x9999, + 0xC19C, 0xBCD8, 0xC19D, 0xBCD9, 0xC19E, 0x999A, 0xC19F, 0xBCDA, 0xC1A0, 0x999B, 0xC1A1, 0xBCDB, 0xC1A2, 0x999C, 0xC1A3, 0x999D, + 0xC1A4, 0x999E, 0xC1A5, 0xBCDC, 0xC1A6, 0x999F, 0xC1A7, 0x99A0, 0xC1A8, 0xBCDD, 0xC1A9, 0xBCDE, 0xC1AA, 0x99A1, 0xC1AB, 0x99A2, + 0xC1AC, 0xBCDF, 0xC1AD, 0x99A3, 0xC1AE, 0x99A4, 0xC1AF, 0x99A5, 0xC1B0, 0xBCE0, 0xC1B1, 0x99A6, 0xC1B2, 0x99A7, 0xC1B3, 0x99A8, + 0xC1B4, 0x99A9, 0xC1B5, 0x99AA, 0xC1B6, 0x99AB, 0xC1B7, 0x99AC, 0xC1B8, 0x99AD, 0xC1B9, 0x99AE, 0xC1BA, 0x99AF, 0xC1BB, 0x99B0, + 0xC1BC, 0x99B1, 0xC1BD, 0xBCE1, 0xC1BE, 0x99B2, 0xC1BF, 0x99B3, 0xC1C0, 0x99B4, 0xC1C1, 0x99B5, 0xC1C2, 0x99B6, 0xC1C3, 0x99B7, + 0xC1C4, 0xBCE2, 0xC1C5, 0x99B8, 0xC1C6, 0x99B9, 0xC1C7, 0x99BA, 0xC1C8, 0xBCE3, 0xC1C9, 0x99BB, 0xC1CA, 0x99BC, 0xC1CB, 0x99BD, + 0xC1CC, 0xBCE4, 0xC1CD, 0x99BE, 0xC1CE, 0x99BF, 0xC1CF, 0x99C0, 0xC1D0, 0x99C1, 0xC1D1, 0x99C2, 0xC1D2, 0x99C3, 0xC1D3, 0x99C4, + 0xC1D4, 0xBCE5, 0xC1D5, 0x99C5, 0xC1D6, 0x99C6, 0xC1D7, 0xBCE6, 0xC1D8, 0xBCE7, 0xC1D9, 0x99C7, 0xC1DA, 0x99C8, 0xC1DB, 0x99C9, + 0xC1DC, 0x99CA, 0xC1DD, 0x99CB, 0xC1DE, 0x99CC, 0xC1DF, 0x99CD, 0xC1E0, 0xBCE8, 0xC1E1, 0x99CE, 0xC1E2, 0x99CF, 0xC1E3, 0x99D0, + 0xC1E4, 0xBCE9, 0xC1E5, 0x99D1, 0xC1E6, 0x99D2, 0xC1E7, 0x99D3, 0xC1E8, 0xBCEA, 0xC1E9, 0x99D4, 0xC1EA, 0x99D5, 0xC1EB, 0x99D6, + 0xC1EC, 0x99D7, 0xC1ED, 0x99D8, 0xC1EE, 0x99D9, 0xC1EF, 0x99DA, 0xC1F0, 0xBCEB, 0xC1F1, 0xBCEC, 0xC1F2, 0x99DB, 0xC1F3, 0xBCED, + 0xC1F4, 0x99DC, 0xC1F5, 0x99DD, 0xC1F6, 0x99DE, 0xC1F7, 0x99DF, 0xC1F8, 0x99E0, 0xC1F9, 0x99E1, 0xC1FA, 0x99E2, 0xC1FB, 0x99E3, + 0xC1FC, 0xBCEE, 0xC1FD, 0xBCEF, 0xC1FE, 0x99E4, 0xC1FF, 0x99E5, 0xC200, 0xBCF0, 0xC201, 0x99E6, 0xC202, 0x99E7, 0xC203, 0x99E8, + 0xC204, 0xBCF1, 0xC205, 0x99E9, 0xC206, 0x99EA, 0xC207, 0x99EB, 0xC208, 0x99EC, 0xC209, 0x99ED, 0xC20A, 0x99EE, 0xC20B, 0x99EF, + 0xC20C, 0xBCF2, 0xC20D, 0xBCF3, 0xC20E, 0x99F0, 0xC20F, 0xBCF4, 0xC210, 0x99F1, 0xC211, 0xBCF5, 0xC212, 0x99F2, 0xC213, 0x99F3, + 0xC214, 0x99F4, 0xC215, 0x99F5, 0xC216, 0x99F6, 0xC217, 0x99F7, 0xC218, 0xBCF6, 0xC219, 0xBCF7, 0xC21A, 0x99F8, 0xC21B, 0x99F9, + 0xC21C, 0xBCF8, 0xC21D, 0x99FA, 0xC21E, 0x99FB, 0xC21F, 0xBCF9, 0xC220, 0xBCFA, 0xC221, 0x99FC, 0xC222, 0x99FD, 0xC223, 0x99FE, + 0xC224, 0x9A41, 0xC225, 0x9A42, 0xC226, 0x9A43, 0xC227, 0x9A44, 0xC228, 0xBCFB, 0xC229, 0xBCFC, 0xC22A, 0x9A45, 0xC22B, 0xBCFD, + 0xC22C, 0x9A46, 0xC22D, 0xBCFE, 0xC22E, 0x9A47, 0xC22F, 0xBDA1, 0xC230, 0x9A48, 0xC231, 0xBDA2, 0xC232, 0xBDA3, 0xC233, 0x9A49, + 0xC234, 0xBDA4, 0xC235, 0x9A4A, 0xC236, 0x9A4B, 0xC237, 0x9A4C, 0xC238, 0x9A4D, 0xC239, 0x9A4E, 0xC23A, 0x9A4F, 0xC23B, 0x9A50, + 0xC23C, 0x9A51, 0xC23D, 0x9A52, 0xC23E, 0x9A53, 0xC23F, 0x9A54, 0xC240, 0x9A55, 0xC241, 0x9A56, 0xC242, 0x9A57, 0xC243, 0x9A58, + 0xC244, 0x9A59, 0xC245, 0x9A5A, 0xC246, 0x9A61, 0xC247, 0x9A62, 0xC248, 0xBDA5, 0xC249, 0x9A63, 0xC24A, 0x9A64, 0xC24B, 0x9A65, + 0xC24C, 0x9A66, 0xC24D, 0x9A67, 0xC24E, 0x9A68, 0xC24F, 0x9A69, 0xC250, 0xBDA6, 0xC251, 0xBDA7, 0xC252, 0x9A6A, 0xC253, 0x9A6B, + 0xC254, 0xBDA8, 0xC255, 0x9A6C, 0xC256, 0x9A6D, 0xC257, 0x9A6E, 0xC258, 0xBDA9, 0xC259, 0x9A6F, 0xC25A, 0x9A70, 0xC25B, 0x9A71, + 0xC25C, 0x9A72, 0xC25D, 0x9A73, 0xC25E, 0x9A74, 0xC25F, 0x9A75, 0xC260, 0xBDAA, 0xC261, 0x9A76, 0xC262, 0x9A77, 0xC263, 0x9A78, + 0xC264, 0x9A79, 0xC265, 0xBDAB, 0xC266, 0x9A7A, 0xC267, 0x9A81, 0xC268, 0x9A82, 0xC269, 0x9A83, 0xC26A, 0x9A84, 0xC26B, 0x9A85, + 0xC26C, 0xBDAC, 0xC26D, 0xBDAD, 0xC26E, 0x9A86, 0xC26F, 0x9A87, 0xC270, 0xBDAE, 0xC271, 0x9A88, 0xC272, 0x9A89, 0xC273, 0x9A8A, + 0xC274, 0xBDAF, 0xC275, 0x9A8B, 0xC276, 0x9A8C, 0xC277, 0x9A8D, 0xC278, 0x9A8E, 0xC279, 0x9A8F, 0xC27A, 0x9A90, 0xC27B, 0x9A91, + 0xC27C, 0xBDB0, 0xC27D, 0xBDB1, 0xC27E, 0x9A92, 0xC27F, 0xBDB2, 0xC280, 0x9A93, 0xC281, 0xBDB3, 0xC282, 0x9A94, 0xC283, 0x9A95, + 0xC284, 0x9A96, 0xC285, 0x9A97, 0xC286, 0x9A98, 0xC287, 0x9A99, 0xC288, 0xBDB4, 0xC289, 0xBDB5, 0xC28A, 0x9A9A, 0xC28B, 0x9A9B, + 0xC28C, 0x9A9C, 0xC28D, 0x9A9D, 0xC28E, 0x9A9E, 0xC28F, 0x9A9F, 0xC290, 0xBDB6, 0xC291, 0x9AA0, 0xC292, 0x9AA1, 0xC293, 0x9AA2, + 0xC294, 0x9AA3, 0xC295, 0x9AA4, 0xC296, 0x9AA5, 0xC297, 0x9AA6, 0xC298, 0xBDB7, 0xC299, 0x9AA7, 0xC29A, 0x9AA8, 0xC29B, 0xBDB8, + 0xC29C, 0x9AA9, 0xC29D, 0xBDB9, 0xC29E, 0x9AAA, 0xC29F, 0x9AAB, 0xC2A0, 0x9AAC, 0xC2A1, 0x9AAD, 0xC2A2, 0x9AAE, 0xC2A3, 0x9AAF, + 0xC2A4, 0xBDBA, 0xC2A5, 0xBDBB, 0xC2A6, 0x9AB0, 0xC2A7, 0x9AB1, 0xC2A8, 0xBDBC, 0xC2A9, 0x9AB2, 0xC2AA, 0x9AB3, 0xC2AB, 0x9AB4, + 0xC2AC, 0xBDBD, 0xC2AD, 0xBDBE, 0xC2AE, 0x9AB5, 0xC2AF, 0x9AB6, 0xC2B0, 0x9AB7, 0xC2B1, 0x9AB8, 0xC2B2, 0x9AB9, 0xC2B3, 0x9ABA, + 0xC2B4, 0xBDBF, 0xC2B5, 0xBDC0, 0xC2B6, 0x9ABB, 0xC2B7, 0xBDC1, 0xC2B8, 0x9ABC, 0xC2B9, 0xBDC2, 0xC2BA, 0x9ABD, 0xC2BB, 0x9ABE, + 0xC2BC, 0x9ABF, 0xC2BD, 0x9AC0, 0xC2BE, 0x9AC1, 0xC2BF, 0x9AC2, 0xC2C0, 0x9AC3, 0xC2C1, 0x9AC4, 0xC2C2, 0x9AC5, 0xC2C3, 0x9AC6, + 0xC2C4, 0x9AC7, 0xC2C5, 0x9AC8, 0xC2C6, 0x9AC9, 0xC2C7, 0x9ACA, 0xC2C8, 0x9ACB, 0xC2C9, 0x9ACC, 0xC2CA, 0x9ACD, 0xC2CB, 0x9ACE, + 0xC2CC, 0x9ACF, 0xC2CD, 0x9AD0, 0xC2CE, 0x9AD1, 0xC2CF, 0x9AD2, 0xC2D0, 0x9AD3, 0xC2D1, 0x9AD4, 0xC2D2, 0x9AD5, 0xC2D3, 0x9AD6, + 0xC2D4, 0x9AD7, 0xC2D5, 0x9AD8, 0xC2D6, 0x9AD9, 0xC2D7, 0x9ADA, 0xC2D8, 0x9ADB, 0xC2D9, 0x9ADC, 0xC2DA, 0x9ADD, 0xC2DB, 0x9ADE, + 0xC2DC, 0xBDC3, 0xC2DD, 0xBDC4, 0xC2DE, 0x9ADF, 0xC2DF, 0x9AE0, 0xC2E0, 0xBDC5, 0xC2E1, 0x9AE1, 0xC2E2, 0x9AE2, 0xC2E3, 0xBDC6, + 0xC2E4, 0xBDC7, 0xC2E5, 0x9AE3, 0xC2E6, 0x9AE4, 0xC2E7, 0x9AE5, 0xC2E8, 0x9AE6, 0xC2E9, 0x9AE7, 0xC2EA, 0x9AE8, 0xC2EB, 0xBDC8, + 0xC2EC, 0xBDC9, 0xC2ED, 0xBDCA, 0xC2EE, 0x9AE9, 0xC2EF, 0xBDCB, 0xC2F0, 0x9AEA, 0xC2F1, 0xBDCC, 0xC2F2, 0x9AEB, 0xC2F3, 0x9AEC, + 0xC2F4, 0x9AED, 0xC2F5, 0x9AEE, 0xC2F6, 0xBDCD, 0xC2F7, 0x9AEF, 0xC2F8, 0xBDCE, 0xC2F9, 0xBDCF, 0xC2FA, 0x9AF0, 0xC2FB, 0xBDD0, + 0xC2FC, 0xBDD1, 0xC2FD, 0x9AF1, 0xC2FE, 0x9AF2, 0xC2FF, 0x9AF3, 0xC300, 0xBDD2, 0xC301, 0x9AF4, 0xC302, 0x9AF5, 0xC303, 0x9AF6, + 0xC304, 0x9AF7, 0xC305, 0x9AF8, 0xC306, 0x9AF9, 0xC307, 0x9AFA, 0xC308, 0xBDD3, 0xC309, 0xBDD4, 0xC30A, 0x9AFB, 0xC30B, 0x9AFC, + 0xC30C, 0xBDD5, 0xC30D, 0xBDD6, 0xC30E, 0x9AFD, 0xC30F, 0x9AFE, 0xC310, 0x9B41, 0xC311, 0x9B42, 0xC312, 0x9B43, 0xC313, 0xBDD7, + 0xC314, 0xBDD8, 0xC315, 0xBDD9, 0xC316, 0x9B44, 0xC317, 0x9B45, 0xC318, 0xBDDA, 0xC319, 0x9B46, 0xC31A, 0x9B47, 0xC31B, 0x9B48, + 0xC31C, 0xBDDB, 0xC31D, 0x9B49, 0xC31E, 0x9B4A, 0xC31F, 0x9B4B, 0xC320, 0x9B4C, 0xC321, 0x9B4D, 0xC322, 0x9B4E, 0xC323, 0x9B4F, + 0xC324, 0xBDDC, 0xC325, 0xBDDD, 0xC326, 0x9B50, 0xC327, 0x9B51, 0xC328, 0xBDDE, 0xC329, 0xBDDF, 0xC32A, 0x9B52, 0xC32B, 0x9B53, + 0xC32C, 0x9B54, 0xC32D, 0x9B55, 0xC32E, 0x9B56, 0xC32F, 0x9B57, 0xC330, 0x9B58, 0xC331, 0x9B59, 0xC332, 0x9B5A, 0xC333, 0x9B61, + 0xC334, 0x9B62, 0xC335, 0x9B63, 0xC336, 0x9B64, 0xC337, 0x9B65, 0xC338, 0x9B66, 0xC339, 0x9B67, 0xC33A, 0x9B68, 0xC33B, 0x9B69, + 0xC33C, 0x9B6A, 0xC33D, 0x9B6B, 0xC33E, 0x9B6C, 0xC33F, 0x9B6D, 0xC340, 0x9B6E, 0xC341, 0x9B6F, 0xC342, 0x9B70, 0xC343, 0x9B71, + 0xC344, 0x9B72, 0xC345, 0xBDE0, 0xC346, 0x9B73, 0xC347, 0x9B74, 0xC348, 0x9B75, 0xC349, 0x9B76, 0xC34A, 0x9B77, 0xC34B, 0x9B78, + 0xC34C, 0x9B79, 0xC34D, 0x9B7A, 0xC34E, 0x9B81, 0xC34F, 0x9B82, 0xC350, 0x9B83, 0xC351, 0x9B84, 0xC352, 0x9B85, 0xC353, 0x9B86, + 0xC354, 0x9B87, 0xC355, 0x9B88, 0xC356, 0x9B89, 0xC357, 0x9B8A, 0xC358, 0x9B8B, 0xC359, 0x9B8C, 0xC35A, 0x9B8D, 0xC35B, 0x9B8E, + 0xC35C, 0x9B8F, 0xC35D, 0x9B90, 0xC35E, 0x9B91, 0xC35F, 0x9B92, 0xC360, 0x9B93, 0xC361, 0x9B94, 0xC362, 0x9B95, 0xC363, 0x9B96, + 0xC364, 0x9B97, 0xC365, 0x9B98, 0xC366, 0x9B99, 0xC367, 0x9B9A, 0xC368, 0xBDE1, 0xC369, 0xBDE2, 0xC36A, 0x9B9B, 0xC36B, 0x9B9C, + 0xC36C, 0xBDE3, 0xC36D, 0x9B9D, 0xC36E, 0x9B9E, 0xC36F, 0x9B9F, 0xC370, 0xBDE4, 0xC371, 0x9BA0, 0xC372, 0xBDE5, 0xC373, 0x9BA1, + 0xC374, 0x9BA2, 0xC375, 0x9BA3, 0xC376, 0x9BA4, 0xC377, 0x9BA5, 0xC378, 0xBDE6, 0xC379, 0xBDE7, 0xC37A, 0x9BA6, 0xC37B, 0x9BA7, + 0xC37C, 0xBDE8, 0xC37D, 0xBDE9, 0xC37E, 0x9BA8, 0xC37F, 0x9BA9, 0xC380, 0x9BAA, 0xC381, 0x9BAB, 0xC382, 0x9BAC, 0xC383, 0x9BAD, + 0xC384, 0xBDEA, 0xC385, 0x9BAE, 0xC386, 0x9BAF, 0xC387, 0x9BB0, 0xC388, 0xBDEB, 0xC389, 0x9BB1, 0xC38A, 0x9BB2, 0xC38B, 0x9BB3, + 0xC38C, 0xBDEC, 0xC38D, 0x9BB4, 0xC38E, 0x9BB5, 0xC38F, 0x9BB6, 0xC390, 0x9BB7, 0xC391, 0x9BB8, 0xC392, 0x9BB9, 0xC393, 0x9BBA, + 0xC394, 0x9BBB, 0xC395, 0x9BBC, 0xC396, 0x9BBD, 0xC397, 0x9BBE, 0xC398, 0x9BBF, 0xC399, 0x9BC0, 0xC39A, 0x9BC1, 0xC39B, 0x9BC2, + 0xC39C, 0x9BC3, 0xC39D, 0x9BC4, 0xC39E, 0x9BC5, 0xC39F, 0x9BC6, 0xC3A0, 0x9BC7, 0xC3A1, 0x9BC8, 0xC3A2, 0x9BC9, 0xC3A3, 0x9BCA, + 0xC3A4, 0x9BCB, 0xC3A5, 0x9BCC, 0xC3A6, 0x9BCD, 0xC3A7, 0x9BCE, 0xC3A8, 0x9BCF, 0xC3A9, 0x9BD0, 0xC3AA, 0x9BD1, 0xC3AB, 0x9BD2, + 0xC3AC, 0x9BD3, 0xC3AD, 0x9BD4, 0xC3AE, 0x9BD5, 0xC3AF, 0x9BD6, 0xC3B0, 0x9BD7, 0xC3B1, 0x9BD8, 0xC3B2, 0x9BD9, 0xC3B3, 0x9BDA, + 0xC3B4, 0x9BDB, 0xC3B5, 0x9BDC, 0xC3B6, 0x9BDD, 0xC3B7, 0x9BDE, 0xC3B8, 0x9BDF, 0xC3B9, 0x9BE0, 0xC3BA, 0x9BE1, 0xC3BB, 0x9BE2, + 0xC3BC, 0x9BE3, 0xC3BD, 0x9BE4, 0xC3BE, 0x9BE5, 0xC3BF, 0x9BE6, 0xC3C0, 0xBDED, 0xC3C1, 0x9BE7, 0xC3C2, 0x9BE8, 0xC3C3, 0x9BE9, + 0xC3C4, 0x9BEA, 0xC3C5, 0x9BEB, 0xC3C6, 0x9BEC, 0xC3C7, 0x9BED, 0xC3C8, 0x9BEE, 0xC3C9, 0x9BEF, 0xC3CA, 0x9BF0, 0xC3CB, 0x9BF1, + 0xC3CC, 0x9BF2, 0xC3CD, 0x9BF3, 0xC3CE, 0x9BF4, 0xC3CF, 0x9BF5, 0xC3D0, 0x9BF6, 0xC3D1, 0x9BF7, 0xC3D2, 0x9BF8, 0xC3D3, 0x9BF9, + 0xC3D4, 0x9BFA, 0xC3D5, 0x9BFB, 0xC3D6, 0x9BFC, 0xC3D7, 0x9BFD, 0xC3D8, 0xBDEE, 0xC3D9, 0xBDEF, 0xC3DA, 0x9BFE, 0xC3DB, 0x9C41, + 0xC3DC, 0xBDF0, 0xC3DD, 0x9C42, 0xC3DE, 0x9C43, 0xC3DF, 0xBDF1, 0xC3E0, 0xBDF2, 0xC3E1, 0x9C44, 0xC3E2, 0xBDF3, 0xC3E3, 0x9C45, + 0xC3E4, 0x9C46, 0xC3E5, 0x9C47, 0xC3E6, 0x9C48, 0xC3E7, 0x9C49, 0xC3E8, 0xBDF4, 0xC3E9, 0xBDF5, 0xC3EA, 0x9C4A, 0xC3EB, 0x9C4B, + 0xC3EC, 0x9C4C, 0xC3ED, 0xBDF6, 0xC3EE, 0x9C4D, 0xC3EF, 0x9C4E, 0xC3F0, 0x9C4F, 0xC3F1, 0x9C50, 0xC3F2, 0x9C51, 0xC3F3, 0x9C52, + 0xC3F4, 0xBDF7, 0xC3F5, 0xBDF8, 0xC3F6, 0x9C53, 0xC3F7, 0x9C54, 0xC3F8, 0xBDF9, 0xC3F9, 0x9C55, 0xC3FA, 0x9C56, 0xC3FB, 0x9C57, + 0xC3FC, 0x9C58, 0xC3FD, 0x9C59, 0xC3FE, 0x9C5A, 0xC3FF, 0x9C61, 0xC400, 0x9C62, 0xC401, 0x9C63, 0xC402, 0x9C64, 0xC403, 0x9C65, + 0xC404, 0x9C66, 0xC405, 0x9C67, 0xC406, 0x9C68, 0xC407, 0x9C69, 0xC408, 0xBDFA, 0xC409, 0x9C6A, 0xC40A, 0x9C6B, 0xC40B, 0x9C6C, + 0xC40C, 0x9C6D, 0xC40D, 0x9C6E, 0xC40E, 0x9C6F, 0xC40F, 0x9C70, 0xC410, 0xBDFB, 0xC411, 0x9C71, 0xC412, 0x9C72, 0xC413, 0x9C73, + 0xC414, 0x9C74, 0xC415, 0x9C75, 0xC416, 0x9C76, 0xC417, 0x9C77, 0xC418, 0x9C78, 0xC419, 0x9C79, 0xC41A, 0x9C7A, 0xC41B, 0x9C81, + 0xC41C, 0x9C82, 0xC41D, 0x9C83, 0xC41E, 0x9C84, 0xC41F, 0x9C85, 0xC420, 0x9C86, 0xC421, 0x9C87, 0xC422, 0x9C88, 0xC423, 0x9C89, + 0xC424, 0xBDFC, 0xC425, 0x9C8A, 0xC426, 0x9C8B, 0xC427, 0x9C8C, 0xC428, 0x9C8D, 0xC429, 0x9C8E, 0xC42A, 0x9C8F, 0xC42B, 0x9C90, + 0xC42C, 0xBDFD, 0xC42D, 0x9C91, 0xC42E, 0x9C92, 0xC42F, 0x9C93, 0xC430, 0xBDFE, 0xC431, 0x9C94, 0xC432, 0x9C95, 0xC433, 0x9C96, + 0xC434, 0xBEA1, 0xC435, 0x9C97, 0xC436, 0x9C98, 0xC437, 0x9C99, 0xC438, 0x9C9A, 0xC439, 0x9C9B, 0xC43A, 0x9C9C, 0xC43B, 0x9C9D, + 0xC43C, 0xBEA2, 0xC43D, 0xBEA3, 0xC43E, 0x9C9E, 0xC43F, 0x9C9F, 0xC440, 0x9CA0, 0xC441, 0x9CA1, 0xC442, 0x9CA2, 0xC443, 0x9CA3, + 0xC444, 0x9CA4, 0xC445, 0x9CA5, 0xC446, 0x9CA6, 0xC447, 0x9CA7, 0xC448, 0xBEA4, 0xC449, 0x9CA8, 0xC44A, 0x9CA9, 0xC44B, 0x9CAA, + 0xC44C, 0x9CAB, 0xC44D, 0x9CAC, 0xC44E, 0x9CAD, 0xC44F, 0x9CAE, 0xC450, 0x9CAF, 0xC451, 0x9CB0, 0xC452, 0x9CB1, 0xC453, 0x9CB2, + 0xC454, 0x9CB3, 0xC455, 0x9CB4, 0xC456, 0x9CB5, 0xC457, 0x9CB6, 0xC458, 0x9CB7, 0xC459, 0x9CB8, 0xC45A, 0x9CB9, 0xC45B, 0x9CBA, + 0xC45C, 0x9CBB, 0xC45D, 0x9CBC, 0xC45E, 0x9CBD, 0xC45F, 0x9CBE, 0xC460, 0x9CBF, 0xC461, 0x9CC0, 0xC462, 0x9CC1, 0xC463, 0x9CC2, + 0xC464, 0xBEA5, 0xC465, 0xBEA6, 0xC466, 0x9CC3, 0xC467, 0x9CC4, 0xC468, 0xBEA7, 0xC469, 0x9CC5, 0xC46A, 0x9CC6, 0xC46B, 0x9CC7, + 0xC46C, 0xBEA8, 0xC46D, 0x9CC8, 0xC46E, 0x9CC9, 0xC46F, 0x9CCA, 0xC470, 0x9CCB, 0xC471, 0x9CCC, 0xC472, 0x9CCD, 0xC473, 0x9CCE, + 0xC474, 0xBEA9, 0xC475, 0xBEAA, 0xC476, 0x9CCF, 0xC477, 0x9CD0, 0xC478, 0x9CD1, 0xC479, 0xBEAB, 0xC47A, 0x9CD2, 0xC47B, 0x9CD3, + 0xC47C, 0x9CD4, 0xC47D, 0x9CD5, 0xC47E, 0x9CD6, 0xC47F, 0x9CD7, 0xC480, 0xBEAC, 0xC481, 0x9CD8, 0xC482, 0x9CD9, 0xC483, 0x9CDA, + 0xC484, 0x9CDB, 0xC485, 0x9CDC, 0xC486, 0x9CDD, 0xC487, 0x9CDE, 0xC488, 0x9CDF, 0xC489, 0x9CE0, 0xC48A, 0x9CE1, 0xC48B, 0x9CE2, + 0xC48C, 0x9CE3, 0xC48D, 0x9CE4, 0xC48E, 0x9CE5, 0xC48F, 0x9CE6, 0xC490, 0x9CE7, 0xC491, 0x9CE8, 0xC492, 0x9CE9, 0xC493, 0x9CEA, + 0xC494, 0xBEAD, 0xC495, 0x9CEB, 0xC496, 0x9CEC, 0xC497, 0x9CED, 0xC498, 0x9CEE, 0xC499, 0x9CEF, 0xC49A, 0x9CF0, 0xC49B, 0x9CF1, + 0xC49C, 0xBEAE, 0xC49D, 0x9CF2, 0xC49E, 0x9CF3, 0xC49F, 0x9CF4, 0xC4A0, 0x9CF5, 0xC4A1, 0x9CF6, 0xC4A2, 0x9CF7, 0xC4A3, 0x9CF8, + 0xC4A4, 0x9CF9, 0xC4A5, 0x9CFA, 0xC4A6, 0x9CFB, 0xC4A7, 0x9CFC, 0xC4A8, 0x9CFD, 0xC4A9, 0x9CFE, 0xC4AA, 0x9D41, 0xC4AB, 0x9D42, + 0xC4AC, 0x9D43, 0xC4AD, 0x9D44, 0xC4AE, 0x9D45, 0xC4AF, 0x9D46, 0xC4B0, 0x9D47, 0xC4B1, 0x9D48, 0xC4B2, 0x9D49, 0xC4B3, 0x9D4A, + 0xC4B4, 0x9D4B, 0xC4B5, 0x9D4C, 0xC4B6, 0x9D4D, 0xC4B7, 0x9D4E, 0xC4B8, 0xBEAF, 0xC4B9, 0x9D4F, 0xC4BA, 0x9D50, 0xC4BB, 0x9D51, + 0xC4BC, 0xBEB0, 0xC4BD, 0x9D52, 0xC4BE, 0x9D53, 0xC4BF, 0x9D54, 0xC4C0, 0x9D55, 0xC4C1, 0x9D56, 0xC4C2, 0x9D57, 0xC4C3, 0x9D58, + 0xC4C4, 0x9D59, 0xC4C5, 0x9D5A, 0xC4C6, 0x9D61, 0xC4C7, 0x9D62, 0xC4C8, 0x9D63, 0xC4C9, 0x9D64, 0xC4CA, 0x9D65, 0xC4CB, 0x9D66, + 0xC4CC, 0x9D67, 0xC4CD, 0x9D68, 0xC4CE, 0x9D69, 0xC4CF, 0x9D6A, 0xC4D0, 0x9D6B, 0xC4D1, 0x9D6C, 0xC4D2, 0x9D6D, 0xC4D3, 0x9D6E, + 0xC4D4, 0x9D6F, 0xC4D5, 0x9D70, 0xC4D6, 0x9D71, 0xC4D7, 0x9D72, 0xC4D8, 0x9D73, 0xC4D9, 0x9D74, 0xC4DA, 0x9D75, 0xC4DB, 0x9D76, + 0xC4DC, 0x9D77, 0xC4DD, 0x9D78, 0xC4DE, 0x9D79, 0xC4DF, 0x9D7A, 0xC4E0, 0x9D81, 0xC4E1, 0x9D82, 0xC4E2, 0x9D83, 0xC4E3, 0x9D84, + 0xC4E4, 0x9D85, 0xC4E5, 0x9D86, 0xC4E6, 0x9D87, 0xC4E7, 0x9D88, 0xC4E8, 0x9D89, 0xC4E9, 0xBEB1, 0xC4EA, 0x9D8A, 0xC4EB, 0x9D8B, + 0xC4EC, 0x9D8C, 0xC4ED, 0x9D8D, 0xC4EE, 0x9D8E, 0xC4EF, 0x9D8F, 0xC4F0, 0xBEB2, 0xC4F1, 0xBEB3, 0xC4F2, 0x9D90, 0xC4F3, 0x9D91, + 0xC4F4, 0xBEB4, 0xC4F5, 0x9D92, 0xC4F6, 0x9D93, 0xC4F7, 0x9D94, 0xC4F8, 0xBEB5, 0xC4F9, 0x9D95, 0xC4FA, 0xBEB6, 0xC4FB, 0x9D96, + 0xC4FC, 0x9D97, 0xC4FD, 0x9D98, 0xC4FE, 0x9D99, 0xC4FF, 0xBEB7, 0xC500, 0xBEB8, 0xC501, 0xBEB9, 0xC502, 0x9D9A, 0xC503, 0x9D9B, + 0xC504, 0x9D9C, 0xC505, 0x9D9D, 0xC506, 0x9D9E, 0xC507, 0x9D9F, 0xC508, 0x9DA0, 0xC509, 0x9DA1, 0xC50A, 0x9DA2, 0xC50B, 0x9DA3, + 0xC50C, 0xBEBA, 0xC50D, 0x9DA4, 0xC50E, 0x9DA5, 0xC50F, 0x9DA6, 0xC510, 0xBEBB, 0xC511, 0x9DA7, 0xC512, 0x9DA8, 0xC513, 0x9DA9, + 0xC514, 0xBEBC, 0xC515, 0x9DAA, 0xC516, 0x9DAB, 0xC517, 0x9DAC, 0xC518, 0x9DAD, 0xC519, 0x9DAE, 0xC51A, 0x9DAF, 0xC51B, 0x9DB0, + 0xC51C, 0xBEBD, 0xC51D, 0x9DB1, 0xC51E, 0x9DB2, 0xC51F, 0x9DB3, 0xC520, 0x9DB4, 0xC521, 0x9DB5, 0xC522, 0x9DB6, 0xC523, 0x9DB7, + 0xC524, 0x9DB8, 0xC525, 0x9DB9, 0xC526, 0x9DBA, 0xC527, 0x9DBB, 0xC528, 0xBEBE, 0xC529, 0xBEBF, 0xC52A, 0x9DBC, 0xC52B, 0x9DBD, + 0xC52C, 0xBEC0, 0xC52D, 0x9DBE, 0xC52E, 0x9DBF, 0xC52F, 0x9DC0, 0xC530, 0xBEC1, 0xC531, 0x9DC1, 0xC532, 0x9DC2, 0xC533, 0x9DC3, + 0xC534, 0x9DC4, 0xC535, 0x9DC5, 0xC536, 0x9DC6, 0xC537, 0x9DC7, 0xC538, 0xBEC2, 0xC539, 0xBEC3, 0xC53A, 0x9DC8, 0xC53B, 0xBEC4, + 0xC53C, 0x9DC9, 0xC53D, 0xBEC5, 0xC53E, 0x9DCA, 0xC53F, 0x9DCB, 0xC540, 0x9DCC, 0xC541, 0x9DCD, 0xC542, 0x9DCE, 0xC543, 0x9DCF, + 0xC544, 0xBEC6, 0xC545, 0xBEC7, 0xC546, 0x9DD0, 0xC547, 0x9DD1, 0xC548, 0xBEC8, 0xC549, 0xBEC9, 0xC54A, 0xBECA, 0xC54B, 0x9DD2, + 0xC54C, 0xBECB, 0xC54D, 0xBECC, 0xC54E, 0xBECD, 0xC54F, 0x9DD3, 0xC550, 0x9DD4, 0xC551, 0x9DD5, 0xC552, 0x9DD6, 0xC553, 0xBECE, + 0xC554, 0xBECF, 0xC555, 0xBED0, 0xC556, 0x9DD7, 0xC557, 0xBED1, 0xC558, 0xBED2, 0xC559, 0xBED3, 0xC55A, 0x9DD8, 0xC55B, 0x9DD9, + 0xC55C, 0x9DDA, 0xC55D, 0xBED4, 0xC55E, 0xBED5, 0xC55F, 0x9DDB, 0xC560, 0xBED6, 0xC561, 0xBED7, 0xC562, 0x9DDC, 0xC563, 0x9DDD, + 0xC564, 0xBED8, 0xC565, 0x9DDE, 0xC566, 0x9DDF, 0xC567, 0x9DE0, 0xC568, 0xBED9, 0xC569, 0x9DE1, 0xC56A, 0x9DE2, 0xC56B, 0x9DE3, + 0xC56C, 0x9DE4, 0xC56D, 0x9DE5, 0xC56E, 0x9DE6, 0xC56F, 0x9DE7, 0xC570, 0xBEDA, 0xC571, 0xBEDB, 0xC572, 0x9DE8, 0xC573, 0xBEDC, + 0xC574, 0xBEDD, 0xC575, 0xBEDE, 0xC576, 0x9DE9, 0xC577, 0x9DEA, 0xC578, 0x9DEB, 0xC579, 0x9DEC, 0xC57A, 0x9DED, 0xC57B, 0x9DEE, + 0xC57C, 0xBEDF, 0xC57D, 0xBEE0, 0xC57E, 0x9DEF, 0xC57F, 0x9DF0, 0xC580, 0xBEE1, 0xC581, 0x9DF1, 0xC582, 0x9DF2, 0xC583, 0x9DF3, + 0xC584, 0xBEE2, 0xC585, 0x9DF4, 0xC586, 0x9DF5, 0xC587, 0xBEE3, 0xC588, 0x9DF6, 0xC589, 0x9DF7, 0xC58A, 0x9DF8, 0xC58B, 0x9DF9, + 0xC58C, 0xBEE4, 0xC58D, 0xBEE5, 0xC58E, 0x9DFA, 0xC58F, 0xBEE6, 0xC590, 0x9DFB, 0xC591, 0xBEE7, 0xC592, 0x9DFC, 0xC593, 0x9DFD, + 0xC594, 0x9DFE, 0xC595, 0xBEE8, 0xC596, 0x9E41, 0xC597, 0xBEE9, 0xC598, 0xBEEA, 0xC599, 0x9E42, 0xC59A, 0x9E43, 0xC59B, 0x9E44, + 0xC59C, 0xBEEB, 0xC59D, 0x9E45, 0xC59E, 0x9E46, 0xC59F, 0x9E47, 0xC5A0, 0xBEEC, 0xC5A1, 0x9E48, 0xC5A2, 0x9E49, 0xC5A3, 0x9E4A, + 0xC5A4, 0x9E4B, 0xC5A5, 0x9E4C, 0xC5A6, 0x9E4D, 0xC5A7, 0x9E4E, 0xC5A8, 0x9E4F, 0xC5A9, 0xBEED, 0xC5AA, 0x9E50, 0xC5AB, 0x9E51, + 0xC5AC, 0x9E52, 0xC5AD, 0x9E53, 0xC5AE, 0x9E54, 0xC5AF, 0x9E55, 0xC5B0, 0x9E56, 0xC5B1, 0x9E57, 0xC5B2, 0x9E58, 0xC5B3, 0x9E59, + 0xC5B4, 0xBEEE, 0xC5B5, 0xBEEF, 0xC5B6, 0x9E5A, 0xC5B7, 0x9E61, 0xC5B8, 0xBEF0, 0xC5B9, 0xBEF1, 0xC5BA, 0x9E62, 0xC5BB, 0xBEF2, + 0xC5BC, 0xBEF3, 0xC5BD, 0xBEF4, 0xC5BE, 0xBEF5, 0xC5BF, 0x9E63, 0xC5C0, 0x9E64, 0xC5C1, 0x9E65, 0xC5C2, 0x9E66, 0xC5C3, 0x9E67, + 0xC5C4, 0xBEF6, 0xC5C5, 0xBEF7, 0xC5C6, 0xBEF8, 0xC5C7, 0xBEF9, 0xC5C8, 0xBEFA, 0xC5C9, 0xBEFB, 0xC5CA, 0xBEFC, 0xC5CB, 0x9E68, + 0xC5CC, 0xBEFD, 0xC5CD, 0x9E69, 0xC5CE, 0xBEFE, 0xC5CF, 0x9E6A, 0xC5D0, 0xBFA1, 0xC5D1, 0xBFA2, 0xC5D2, 0x9E6B, 0xC5D3, 0x9E6C, + 0xC5D4, 0xBFA3, 0xC5D5, 0x9E6D, 0xC5D6, 0x9E6E, 0xC5D7, 0x9E6F, 0xC5D8, 0xBFA4, 0xC5D9, 0x9E70, 0xC5DA, 0x9E71, 0xC5DB, 0x9E72, + 0xC5DC, 0x9E73, 0xC5DD, 0x9E74, 0xC5DE, 0x9E75, 0xC5DF, 0x9E76, 0xC5E0, 0xBFA5, 0xC5E1, 0xBFA6, 0xC5E2, 0x9E77, 0xC5E3, 0xBFA7, + 0xC5E4, 0x9E78, 0xC5E5, 0xBFA8, 0xC5E6, 0x9E79, 0xC5E7, 0x9E7A, 0xC5E8, 0x9E81, 0xC5E9, 0x9E82, 0xC5EA, 0x9E83, 0xC5EB, 0x9E84, + 0xC5EC, 0xBFA9, 0xC5ED, 0xBFAA, 0xC5EE, 0xBFAB, 0xC5EF, 0x9E85, 0xC5F0, 0xBFAC, 0xC5F1, 0x9E86, 0xC5F2, 0x9E87, 0xC5F3, 0x9E88, + 0xC5F4, 0xBFAD, 0xC5F5, 0x9E89, 0xC5F6, 0xBFAE, 0xC5F7, 0xBFAF, 0xC5F8, 0x9E8A, 0xC5F9, 0x9E8B, 0xC5FA, 0x9E8C, 0xC5FB, 0x9E8D, + 0xC5FC, 0xBFB0, 0xC5FD, 0xBFB1, 0xC5FE, 0xBFB2, 0xC5FF, 0xBFB3, 0xC600, 0xBFB4, 0xC601, 0xBFB5, 0xC602, 0x9E8E, 0xC603, 0x9E8F, + 0xC604, 0x9E90, 0xC605, 0xBFB6, 0xC606, 0xBFB7, 0xC607, 0xBFB8, 0xC608, 0xBFB9, 0xC609, 0x9E91, 0xC60A, 0x9E92, 0xC60B, 0x9E93, + 0xC60C, 0xBFBA, 0xC60D, 0x9E94, 0xC60E, 0x9E95, 0xC60F, 0x9E96, 0xC610, 0xBFBB, 0xC611, 0x9E97, 0xC612, 0x9E98, 0xC613, 0x9E99, + 0xC614, 0x9E9A, 0xC615, 0x9E9B, 0xC616, 0x9E9C, 0xC617, 0x9E9D, 0xC618, 0xBFBC, 0xC619, 0xBFBD, 0xC61A, 0x9E9E, 0xC61B, 0xBFBE, + 0xC61C, 0xBFBF, 0xC61D, 0x9E9F, 0xC61E, 0x9EA0, 0xC61F, 0x9EA1, 0xC620, 0x9EA2, 0xC621, 0x9EA3, 0xC622, 0x9EA4, 0xC623, 0x9EA5, + 0xC624, 0xBFC0, 0xC625, 0xBFC1, 0xC626, 0x9EA6, 0xC627, 0x9EA7, 0xC628, 0xBFC2, 0xC629, 0x9EA8, 0xC62A, 0x9EA9, 0xC62B, 0x9EAA, + 0xC62C, 0xBFC3, 0xC62D, 0xBFC4, 0xC62E, 0xBFC5, 0xC62F, 0x9EAB, 0xC630, 0xBFC6, 0xC631, 0x9EAC, 0xC632, 0x9EAD, 0xC633, 0xBFC7, + 0xC634, 0xBFC8, 0xC635, 0xBFC9, 0xC636, 0x9EAE, 0xC637, 0xBFCA, 0xC638, 0x9EAF, 0xC639, 0xBFCB, 0xC63A, 0x9EB0, 0xC63B, 0xBFCC, + 0xC63C, 0x9EB1, 0xC63D, 0x9EB2, 0xC63E, 0x9EB3, 0xC63F, 0x9EB4, 0xC640, 0xBFCD, 0xC641, 0xBFCE, 0xC642, 0x9EB5, 0xC643, 0x9EB6, + 0xC644, 0xBFCF, 0xC645, 0x9EB7, 0xC646, 0x9EB8, 0xC647, 0x9EB9, 0xC648, 0xBFD0, 0xC649, 0x9EBA, 0xC64A, 0x9EBB, 0xC64B, 0x9EBC, + 0xC64C, 0x9EBD, 0xC64D, 0x9EBE, 0xC64E, 0x9EBF, 0xC64F, 0x9EC0, 0xC650, 0xBFD1, 0xC651, 0xBFD2, 0xC652, 0x9EC1, 0xC653, 0xBFD3, + 0xC654, 0xBFD4, 0xC655, 0xBFD5, 0xC656, 0x9EC2, 0xC657, 0x9EC3, 0xC658, 0x9EC4, 0xC659, 0x9EC5, 0xC65A, 0x9EC6, 0xC65B, 0x9EC7, + 0xC65C, 0xBFD6, 0xC65D, 0xBFD7, 0xC65E, 0x9EC8, 0xC65F, 0x9EC9, 0xC660, 0xBFD8, 0xC661, 0x9ECA, 0xC662, 0x9ECB, 0xC663, 0x9ECC, + 0xC664, 0x9ECD, 0xC665, 0x9ECE, 0xC666, 0x9ECF, 0xC667, 0x9ED0, 0xC668, 0x9ED1, 0xC669, 0x9ED2, 0xC66A, 0x9ED3, 0xC66B, 0x9ED4, + 0xC66C, 0xBFD9, 0xC66D, 0x9ED5, 0xC66E, 0x9ED6, 0xC66F, 0xBFDA, 0xC670, 0x9ED7, 0xC671, 0xBFDB, 0xC672, 0x9ED8, 0xC673, 0x9ED9, + 0xC674, 0x9EDA, 0xC675, 0x9EDB, 0xC676, 0x9EDC, 0xC677, 0x9EDD, 0xC678, 0xBFDC, 0xC679, 0xBFDD, 0xC67A, 0x9EDE, 0xC67B, 0x9EDF, + 0xC67C, 0xBFDE, 0xC67D, 0x9EE0, 0xC67E, 0x9EE1, 0xC67F, 0x9EE2, 0xC680, 0xBFDF, 0xC681, 0x9EE3, 0xC682, 0x9EE4, 0xC683, 0x9EE5, + 0xC684, 0x9EE6, 0xC685, 0x9EE7, 0xC686, 0x9EE8, 0xC687, 0x9EE9, 0xC688, 0xBFE0, 0xC689, 0xBFE1, 0xC68A, 0x9EEA, 0xC68B, 0xBFE2, + 0xC68C, 0x9EEB, 0xC68D, 0xBFE3, 0xC68E, 0x9EEC, 0xC68F, 0x9EED, 0xC690, 0x9EEE, 0xC691, 0x9EEF, 0xC692, 0x9EF0, 0xC693, 0x9EF1, + 0xC694, 0xBFE4, 0xC695, 0xBFE5, 0xC696, 0x9EF2, 0xC697, 0x9EF3, 0xC698, 0xBFE6, 0xC699, 0x9EF4, 0xC69A, 0x9EF5, 0xC69B, 0x9EF6, + 0xC69C, 0xBFE7, 0xC69D, 0x9EF7, 0xC69E, 0x9EF8, 0xC69F, 0x9EF9, 0xC6A0, 0x9EFA, 0xC6A1, 0x9EFB, 0xC6A2, 0x9EFC, 0xC6A3, 0x9EFD, + 0xC6A4, 0xBFE8, 0xC6A5, 0xBFE9, 0xC6A6, 0x9EFE, 0xC6A7, 0xBFEA, 0xC6A8, 0x9F41, 0xC6A9, 0xBFEB, 0xC6AA, 0x9F42, 0xC6AB, 0x9F43, + 0xC6AC, 0x9F44, 0xC6AD, 0x9F45, 0xC6AE, 0x9F46, 0xC6AF, 0x9F47, 0xC6B0, 0xBFEC, 0xC6B1, 0xBFED, 0xC6B2, 0x9F48, 0xC6B3, 0x9F49, + 0xC6B4, 0xBFEE, 0xC6B5, 0x9F4A, 0xC6B6, 0x9F4B, 0xC6B7, 0x9F4C, 0xC6B8, 0xBFEF, 0xC6B9, 0xBFF0, 0xC6BA, 0xBFF1, 0xC6BB, 0x9F4D, + 0xC6BC, 0x9F4E, 0xC6BD, 0x9F4F, 0xC6BE, 0x9F50, 0xC6BF, 0x9F51, 0xC6C0, 0xBFF2, 0xC6C1, 0xBFF3, 0xC6C2, 0x9F52, 0xC6C3, 0xBFF4, + 0xC6C4, 0x9F53, 0xC6C5, 0xBFF5, 0xC6C6, 0x9F54, 0xC6C7, 0x9F55, 0xC6C8, 0x9F56, 0xC6C9, 0x9F57, 0xC6CA, 0x9F58, 0xC6CB, 0x9F59, + 0xC6CC, 0xBFF6, 0xC6CD, 0xBFF7, 0xC6CE, 0x9F5A, 0xC6CF, 0x9F61, 0xC6D0, 0xBFF8, 0xC6D1, 0x9F62, 0xC6D2, 0x9F63, 0xC6D3, 0x9F64, + 0xC6D4, 0xBFF9, 0xC6D5, 0x9F65, 0xC6D6, 0x9F66, 0xC6D7, 0x9F67, 0xC6D8, 0x9F68, 0xC6D9, 0x9F69, 0xC6DA, 0x9F6A, 0xC6DB, 0x9F6B, + 0xC6DC, 0xBFFA, 0xC6DD, 0xBFFB, 0xC6DE, 0x9F6C, 0xC6DF, 0x9F6D, 0xC6E0, 0xBFFC, 0xC6E1, 0xBFFD, 0xC6E2, 0x9F6E, 0xC6E3, 0x9F6F, + 0xC6E4, 0x9F70, 0xC6E5, 0x9F71, 0xC6E6, 0x9F72, 0xC6E7, 0x9F73, 0xC6E8, 0xBFFE, 0xC6E9, 0xC0A1, 0xC6EA, 0x9F74, 0xC6EB, 0x9F75, + 0xC6EC, 0xC0A2, 0xC6ED, 0x9F76, 0xC6EE, 0x9F77, 0xC6EF, 0x9F78, 0xC6F0, 0xC0A3, 0xC6F1, 0x9F79, 0xC6F2, 0x9F7A, 0xC6F3, 0x9F81, + 0xC6F4, 0x9F82, 0xC6F5, 0x9F83, 0xC6F6, 0x9F84, 0xC6F7, 0x9F85, 0xC6F8, 0xC0A4, 0xC6F9, 0xC0A5, 0xC6FA, 0x9F86, 0xC6FB, 0x9F87, + 0xC6FC, 0x9F88, 0xC6FD, 0xC0A6, 0xC6FE, 0x9F89, 0xC6FF, 0x9F8A, 0xC700, 0x9F8B, 0xC701, 0x9F8C, 0xC702, 0x9F8D, 0xC703, 0x9F8E, + 0xC704, 0xC0A7, 0xC705, 0xC0A8, 0xC706, 0x9F8F, 0xC707, 0x9F90, 0xC708, 0xC0A9, 0xC709, 0x9F91, 0xC70A, 0x9F92, 0xC70B, 0x9F93, + 0xC70C, 0xC0AA, 0xC70D, 0x9F94, 0xC70E, 0x9F95, 0xC70F, 0x9F96, 0xC710, 0x9F97, 0xC711, 0x9F98, 0xC712, 0x9F99, 0xC713, 0x9F9A, + 0xC714, 0xC0AB, 0xC715, 0xC0AC, 0xC716, 0x9F9B, 0xC717, 0xC0AD, 0xC718, 0x9F9C, 0xC719, 0xC0AE, 0xC71A, 0x9F9D, 0xC71B, 0x9F9E, + 0xC71C, 0x9F9F, 0xC71D, 0x9FA0, 0xC71E, 0x9FA1, 0xC71F, 0x9FA2, 0xC720, 0xC0AF, 0xC721, 0xC0B0, 0xC722, 0x9FA3, 0xC723, 0x9FA4, + 0xC724, 0xC0B1, 0xC725, 0x9FA5, 0xC726, 0x9FA6, 0xC727, 0x9FA7, 0xC728, 0xC0B2, 0xC729, 0x9FA8, 0xC72A, 0x9FA9, 0xC72B, 0x9FAA, + 0xC72C, 0x9FAB, 0xC72D, 0x9FAC, 0xC72E, 0x9FAD, 0xC72F, 0x9FAE, 0xC730, 0xC0B3, 0xC731, 0xC0B4, 0xC732, 0x9FAF, 0xC733, 0xC0B5, + 0xC734, 0x9FB0, 0xC735, 0xC0B6, 0xC736, 0x9FB1, 0xC737, 0xC0B7, 0xC738, 0x9FB2, 0xC739, 0x9FB3, 0xC73A, 0x9FB4, 0xC73B, 0x9FB5, + 0xC73C, 0xC0B8, 0xC73D, 0xC0B9, 0xC73E, 0x9FB6, 0xC73F, 0x9FB7, 0xC740, 0xC0BA, 0xC741, 0x9FB8, 0xC742, 0x9FB9, 0xC743, 0x9FBA, + 0xC744, 0xC0BB, 0xC745, 0x9FBB, 0xC746, 0x9FBC, 0xC747, 0x9FBD, 0xC748, 0x9FBE, 0xC749, 0x9FBF, 0xC74A, 0xC0BC, 0xC74B, 0x9FC0, + 0xC74C, 0xC0BD, 0xC74D, 0xC0BE, 0xC74E, 0x9FC1, 0xC74F, 0xC0BF, 0xC750, 0x9FC2, 0xC751, 0xC0C0, 0xC752, 0xC0C1, 0xC753, 0xC0C2, + 0xC754, 0xC0C3, 0xC755, 0xC0C4, 0xC756, 0xC0C5, 0xC757, 0xC0C6, 0xC758, 0xC0C7, 0xC759, 0x9FC3, 0xC75A, 0x9FC4, 0xC75B, 0x9FC5, + 0xC75C, 0xC0C8, 0xC75D, 0x9FC6, 0xC75E, 0x9FC7, 0xC75F, 0x9FC8, 0xC760, 0xC0C9, 0xC761, 0x9FC9, 0xC762, 0x9FCA, 0xC763, 0x9FCB, + 0xC764, 0x9FCC, 0xC765, 0x9FCD, 0xC766, 0x9FCE, 0xC767, 0x9FCF, 0xC768, 0xC0CA, 0xC769, 0x9FD0, 0xC76A, 0x9FD1, 0xC76B, 0xC0CB, + 0xC76C, 0x9FD2, 0xC76D, 0x9FD3, 0xC76E, 0x9FD4, 0xC76F, 0x9FD5, 0xC770, 0x9FD6, 0xC771, 0x9FD7, 0xC772, 0x9FD8, 0xC773, 0x9FD9, + 0xC774, 0xC0CC, 0xC775, 0xC0CD, 0xC776, 0x9FDA, 0xC777, 0x9FDB, 0xC778, 0xC0CE, 0xC779, 0x9FDC, 0xC77A, 0x9FDD, 0xC77B, 0x9FDE, + 0xC77C, 0xC0CF, 0xC77D, 0xC0D0, 0xC77E, 0xC0D1, 0xC77F, 0x9FDF, 0xC780, 0x9FE0, 0xC781, 0x9FE1, 0xC782, 0x9FE2, 0xC783, 0xC0D2, + 0xC784, 0xC0D3, 0xC785, 0xC0D4, 0xC786, 0x9FE3, 0xC787, 0xC0D5, 0xC788, 0xC0D6, 0xC789, 0xC0D7, 0xC78A, 0xC0D8, 0xC78B, 0x9FE4, + 0xC78C, 0x9FE5, 0xC78D, 0x9FE6, 0xC78E, 0xC0D9, 0xC78F, 0x9FE7, 0xC790, 0xC0DA, 0xC791, 0xC0DB, 0xC792, 0x9FE8, 0xC793, 0x9FE9, + 0xC794, 0xC0DC, 0xC795, 0x9FEA, 0xC796, 0xC0DD, 0xC797, 0xC0DE, 0xC798, 0xC0DF, 0xC799, 0x9FEB, 0xC79A, 0xC0E0, 0xC79B, 0x9FEC, + 0xC79C, 0x9FED, 0xC79D, 0x9FEE, 0xC79E, 0x9FEF, 0xC79F, 0x9FF0, 0xC7A0, 0xC0E1, 0xC7A1, 0xC0E2, 0xC7A2, 0x9FF1, 0xC7A3, 0xC0E3, + 0xC7A4, 0xC0E4, 0xC7A5, 0xC0E5, 0xC7A6, 0xC0E6, 0xC7A7, 0x9FF2, 0xC7A8, 0x9FF3, 0xC7A9, 0x9FF4, 0xC7AA, 0x9FF5, 0xC7AB, 0x9FF6, + 0xC7AC, 0xC0E7, 0xC7AD, 0xC0E8, 0xC7AE, 0x9FF7, 0xC7AF, 0x9FF8, 0xC7B0, 0xC0E9, 0xC7B1, 0x9FF9, 0xC7B2, 0x9FFA, 0xC7B3, 0x9FFB, + 0xC7B4, 0xC0EA, 0xC7B5, 0x9FFC, 0xC7B6, 0x9FFD, 0xC7B7, 0x9FFE, 0xC7B8, 0xA041, 0xC7B9, 0xA042, 0xC7BA, 0xA043, 0xC7BB, 0xA044, + 0xC7BC, 0xC0EB, 0xC7BD, 0xC0EC, 0xC7BE, 0xA045, 0xC7BF, 0xC0ED, 0xC7C0, 0xC0EE, 0xC7C1, 0xC0EF, 0xC7C2, 0xA046, 0xC7C3, 0xA047, + 0xC7C4, 0xA048, 0xC7C5, 0xA049, 0xC7C6, 0xA04A, 0xC7C7, 0xA04B, 0xC7C8, 0xC0F0, 0xC7C9, 0xC0F1, 0xC7CA, 0xA04C, 0xC7CB, 0xA04D, + 0xC7CC, 0xC0F2, 0xC7CD, 0xA04E, 0xC7CE, 0xC0F3, 0xC7CF, 0xA04F, 0xC7D0, 0xC0F4, 0xC7D1, 0xA050, 0xC7D2, 0xA051, 0xC7D3, 0xA052, + 0xC7D4, 0xA053, 0xC7D5, 0xA054, 0xC7D6, 0xA055, 0xC7D7, 0xA056, 0xC7D8, 0xC0F5, 0xC7D9, 0xA057, 0xC7DA, 0xA058, 0xC7DB, 0xA059, + 0xC7DC, 0xA05A, 0xC7DD, 0xC0F6, 0xC7DE, 0xA061, 0xC7DF, 0xA062, 0xC7E0, 0xA063, 0xC7E1, 0xA064, 0xC7E2, 0xA065, 0xC7E3, 0xA066, + 0xC7E4, 0xC0F7, 0xC7E5, 0xA067, 0xC7E6, 0xA068, 0xC7E7, 0xA069, 0xC7E8, 0xC0F8, 0xC7E9, 0xA06A, 0xC7EA, 0xA06B, 0xC7EB, 0xA06C, + 0xC7EC, 0xC0F9, 0xC7ED, 0xA06D, 0xC7EE, 0xA06E, 0xC7EF, 0xA06F, 0xC7F0, 0xA070, 0xC7F1, 0xA071, 0xC7F2, 0xA072, 0xC7F3, 0xA073, + 0xC7F4, 0xA074, 0xC7F5, 0xA075, 0xC7F6, 0xA076, 0xC7F7, 0xA077, 0xC7F8, 0xA078, 0xC7F9, 0xA079, 0xC7FA, 0xA07A, 0xC7FB, 0xA081, + 0xC7FC, 0xA082, 0xC7FD, 0xA083, 0xC7FE, 0xA084, 0xC7FF, 0xA085, 0xC800, 0xC0FA, 0xC801, 0xC0FB, 0xC802, 0xA086, 0xC803, 0xA087, + 0xC804, 0xC0FC, 0xC805, 0xA088, 0xC806, 0xA089, 0xC807, 0xA08A, 0xC808, 0xC0FD, 0xC809, 0xA08B, 0xC80A, 0xC0FE, 0xC80B, 0xA08C, + 0xC80C, 0xA08D, 0xC80D, 0xA08E, 0xC80E, 0xA08F, 0xC80F, 0xA090, 0xC810, 0xC1A1, 0xC811, 0xC1A2, 0xC812, 0xA091, 0xC813, 0xC1A3, + 0xC814, 0xA092, 0xC815, 0xC1A4, 0xC816, 0xC1A5, 0xC817, 0xA093, 0xC818, 0xA094, 0xC819, 0xA095, 0xC81A, 0xA096, 0xC81B, 0xA097, + 0xC81C, 0xC1A6, 0xC81D, 0xC1A7, 0xC81E, 0xA098, 0xC81F, 0xA099, 0xC820, 0xC1A8, 0xC821, 0xA09A, 0xC822, 0xA09B, 0xC823, 0xA09C, + 0xC824, 0xC1A9, 0xC825, 0xA09D, 0xC826, 0xA09E, 0xC827, 0xA09F, 0xC828, 0xA0A0, 0xC829, 0xA0A1, 0xC82A, 0xA0A2, 0xC82B, 0xA0A3, + 0xC82C, 0xC1AA, 0xC82D, 0xC1AB, 0xC82E, 0xA0A4, 0xC82F, 0xC1AC, 0xC830, 0xA0A5, 0xC831, 0xC1AD, 0xC832, 0xA0A6, 0xC833, 0xA0A7, + 0xC834, 0xA0A8, 0xC835, 0xA0A9, 0xC836, 0xA0AA, 0xC837, 0xA0AB, 0xC838, 0xC1AE, 0xC839, 0xA0AC, 0xC83A, 0xA0AD, 0xC83B, 0xA0AE, + 0xC83C, 0xC1AF, 0xC83D, 0xA0AF, 0xC83E, 0xA0B0, 0xC83F, 0xA0B1, 0xC840, 0xC1B0, 0xC841, 0xA0B2, 0xC842, 0xA0B3, 0xC843, 0xA0B4, + 0xC844, 0xA0B5, 0xC845, 0xA0B6, 0xC846, 0xA0B7, 0xC847, 0xA0B8, 0xC848, 0xC1B1, 0xC849, 0xC1B2, 0xC84A, 0xA0B9, 0xC84B, 0xA0BA, + 0xC84C, 0xC1B3, 0xC84D, 0xC1B4, 0xC84E, 0xA0BB, 0xC84F, 0xA0BC, 0xC850, 0xA0BD, 0xC851, 0xA0BE, 0xC852, 0xA0BF, 0xC853, 0xA0C0, + 0xC854, 0xC1B5, 0xC855, 0xA0C1, 0xC856, 0xA0C2, 0xC857, 0xA0C3, 0xC858, 0xA0C4, 0xC859, 0xA0C5, 0xC85A, 0xA0C6, 0xC85B, 0xA0C7, + 0xC85C, 0xA0C8, 0xC85D, 0xA0C9, 0xC85E, 0xA0CA, 0xC85F, 0xA0CB, 0xC860, 0xA0CC, 0xC861, 0xA0CD, 0xC862, 0xA0CE, 0xC863, 0xA0CF, + 0xC864, 0xA0D0, 0xC865, 0xA0D1, 0xC866, 0xA0D2, 0xC867, 0xA0D3, 0xC868, 0xA0D4, 0xC869, 0xA0D5, 0xC86A, 0xA0D6, 0xC86B, 0xA0D7, + 0xC86C, 0xA0D8, 0xC86D, 0xA0D9, 0xC86E, 0xA0DA, 0xC86F, 0xA0DB, 0xC870, 0xC1B6, 0xC871, 0xC1B7, 0xC872, 0xA0DC, 0xC873, 0xA0DD, + 0xC874, 0xC1B8, 0xC875, 0xA0DE, 0xC876, 0xA0DF, 0xC877, 0xA0E0, 0xC878, 0xC1B9, 0xC879, 0xA0E1, 0xC87A, 0xC1BA, 0xC87B, 0xA0E2, + 0xC87C, 0xA0E3, 0xC87D, 0xA0E4, 0xC87E, 0xA0E5, 0xC87F, 0xA0E6, 0xC880, 0xC1BB, 0xC881, 0xC1BC, 0xC882, 0xA0E7, 0xC883, 0xC1BD, + 0xC884, 0xA0E8, 0xC885, 0xC1BE, 0xC886, 0xC1BF, 0xC887, 0xC1C0, 0xC888, 0xA0E9, 0xC889, 0xA0EA, 0xC88A, 0xA0EB, 0xC88B, 0xC1C1, + 0xC88C, 0xC1C2, 0xC88D, 0xC1C3, 0xC88E, 0xA0EC, 0xC88F, 0xA0ED, 0xC890, 0xA0EE, 0xC891, 0xA0EF, 0xC892, 0xA0F0, 0xC893, 0xA0F1, + 0xC894, 0xC1C4, 0xC895, 0xA0F2, 0xC896, 0xA0F3, 0xC897, 0xA0F4, 0xC898, 0xA0F5, 0xC899, 0xA0F6, 0xC89A, 0xA0F7, 0xC89B, 0xA0F8, + 0xC89C, 0xA0F9, 0xC89D, 0xC1C5, 0xC89E, 0xA0FA, 0xC89F, 0xC1C6, 0xC8A0, 0xA0FB, 0xC8A1, 0xC1C7, 0xC8A2, 0xA0FC, 0xC8A3, 0xA0FD, + 0xC8A4, 0xA0FE, 0xC8A5, 0xA141, 0xC8A6, 0xA142, 0xC8A7, 0xA143, 0xC8A8, 0xC1C8, 0xC8A9, 0xA144, 0xC8AA, 0xA145, 0xC8AB, 0xA146, + 0xC8AC, 0xA147, 0xC8AD, 0xA148, 0xC8AE, 0xA149, 0xC8AF, 0xA14A, 0xC8B0, 0xA14B, 0xC8B1, 0xA14C, 0xC8B2, 0xA14D, 0xC8B3, 0xA14E, + 0xC8B4, 0xA14F, 0xC8B5, 0xA150, 0xC8B6, 0xA151, 0xC8B7, 0xA152, 0xC8B8, 0xA153, 0xC8B9, 0xA154, 0xC8BA, 0xA155, 0xC8BB, 0xA156, + 0xC8BC, 0xC1C9, 0xC8BD, 0xC1CA, 0xC8BE, 0xA157, 0xC8BF, 0xA158, 0xC8C0, 0xA159, 0xC8C1, 0xA15A, 0xC8C2, 0xA161, 0xC8C3, 0xA162, + 0xC8C4, 0xC1CB, 0xC8C5, 0xA163, 0xC8C6, 0xA164, 0xC8C7, 0xA165, 0xC8C8, 0xC1CC, 0xC8C9, 0xA166, 0xC8CA, 0xA167, 0xC8CB, 0xA168, + 0xC8CC, 0xC1CD, 0xC8CD, 0xA169, 0xC8CE, 0xA16A, 0xC8CF, 0xA16B, 0xC8D0, 0xA16C, 0xC8D1, 0xA16D, 0xC8D2, 0xA16E, 0xC8D3, 0xA16F, + 0xC8D4, 0xC1CE, 0xC8D5, 0xC1CF, 0xC8D6, 0xA170, 0xC8D7, 0xC1D0, 0xC8D8, 0xA171, 0xC8D9, 0xC1D1, 0xC8DA, 0xA172, 0xC8DB, 0xA173, + 0xC8DC, 0xA174, 0xC8DD, 0xA175, 0xC8DE, 0xA176, 0xC8DF, 0xA177, 0xC8E0, 0xC1D2, 0xC8E1, 0xC1D3, 0xC8E2, 0xA178, 0xC8E3, 0xA179, + 0xC8E4, 0xC1D4, 0xC8E5, 0xA17A, 0xC8E6, 0xA181, 0xC8E7, 0xA182, 0xC8E8, 0xA183, 0xC8E9, 0xA184, 0xC8EA, 0xA185, 0xC8EB, 0xA186, + 0xC8EC, 0xA187, 0xC8ED, 0xA188, 0xC8EE, 0xA189, 0xC8EF, 0xA18A, 0xC8F0, 0xA18B, 0xC8F1, 0xA18C, 0xC8F2, 0xA18D, 0xC8F3, 0xA18E, + 0xC8F4, 0xA18F, 0xC8F5, 0xC1D5, 0xC8F6, 0xA190, 0xC8F7, 0xA191, 0xC8F8, 0xA192, 0xC8F9, 0xA193, 0xC8FA, 0xA194, 0xC8FB, 0xA195, + 0xC8FC, 0xC1D6, 0xC8FD, 0xC1D7, 0xC8FE, 0xA196, 0xC8FF, 0xA197, 0xC900, 0xC1D8, 0xC901, 0xA198, 0xC902, 0xA199, 0xC903, 0xA19A, + 0xC904, 0xC1D9, 0xC905, 0xC1DA, 0xC906, 0xC1DB, 0xC907, 0xA19B, 0xC908, 0xA19C, 0xC909, 0xA19D, 0xC90A, 0xA19E, 0xC90B, 0xA19F, + 0xC90C, 0xC1DC, 0xC90D, 0xC1DD, 0xC90E, 0xA1A0, 0xC90F, 0xC1DE, 0xC910, 0xA241, 0xC911, 0xC1DF, 0xC912, 0xA242, 0xC913, 0xA243, + 0xC914, 0xA244, 0xC915, 0xA245, 0xC916, 0xA246, 0xC917, 0xA247, 0xC918, 0xC1E0, 0xC919, 0xA248, 0xC91A, 0xA249, 0xC91B, 0xA24A, + 0xC91C, 0xA24B, 0xC91D, 0xA24C, 0xC91E, 0xA24D, 0xC91F, 0xA24E, 0xC920, 0xA24F, 0xC921, 0xA250, 0xC922, 0xA251, 0xC923, 0xA252, + 0xC924, 0xA253, 0xC925, 0xA254, 0xC926, 0xA255, 0xC927, 0xA256, 0xC928, 0xA257, 0xC929, 0xA258, 0xC92A, 0xA259, 0xC92B, 0xA25A, + 0xC92C, 0xC1E1, 0xC92D, 0xA261, 0xC92E, 0xA262, 0xC92F, 0xA263, 0xC930, 0xA264, 0xC931, 0xA265, 0xC932, 0xA266, 0xC933, 0xA267, + 0xC934, 0xC1E2, 0xC935, 0xA268, 0xC936, 0xA269, 0xC937, 0xA26A, 0xC938, 0xA26B, 0xC939, 0xA26C, 0xC93A, 0xA26D, 0xC93B, 0xA26E, + 0xC93C, 0xA26F, 0xC93D, 0xA270, 0xC93E, 0xA271, 0xC93F, 0xA272, 0xC940, 0xA273, 0xC941, 0xA274, 0xC942, 0xA275, 0xC943, 0xA276, + 0xC944, 0xA277, 0xC945, 0xA278, 0xC946, 0xA279, 0xC947, 0xA27A, 0xC948, 0xA281, 0xC949, 0xA282, 0xC94A, 0xA283, 0xC94B, 0xA284, + 0xC94C, 0xA285, 0xC94D, 0xA286, 0xC94E, 0xA287, 0xC94F, 0xA288, 0xC950, 0xC1E3, 0xC951, 0xC1E4, 0xC952, 0xA289, 0xC953, 0xA28A, + 0xC954, 0xC1E5, 0xC955, 0xA28B, 0xC956, 0xA28C, 0xC957, 0xA28D, 0xC958, 0xC1E6, 0xC959, 0xA28E, 0xC95A, 0xA28F, 0xC95B, 0xA290, + 0xC95C, 0xA291, 0xC95D, 0xA292, 0xC95E, 0xA293, 0xC95F, 0xA294, 0xC960, 0xC1E7, 0xC961, 0xC1E8, 0xC962, 0xA295, 0xC963, 0xC1E9, + 0xC964, 0xA296, 0xC965, 0xA297, 0xC966, 0xA298, 0xC967, 0xA299, 0xC968, 0xA29A, 0xC969, 0xA29B, 0xC96A, 0xA29C, 0xC96B, 0xA29D, + 0xC96C, 0xC1EA, 0xC96D, 0xA29E, 0xC96E, 0xA29F, 0xC96F, 0xA2A0, 0xC970, 0xC1EB, 0xC971, 0xA341, 0xC972, 0xA342, 0xC973, 0xA343, + 0xC974, 0xC1EC, 0xC975, 0xA344, 0xC976, 0xA345, 0xC977, 0xA346, 0xC978, 0xA347, 0xC979, 0xA348, 0xC97A, 0xA349, 0xC97B, 0xA34A, + 0xC97C, 0xC1ED, 0xC97D, 0xA34B, 0xC97E, 0xA34C, 0xC97F, 0xA34D, 0xC980, 0xA34E, 0xC981, 0xA34F, 0xC982, 0xA350, 0xC983, 0xA351, + 0xC984, 0xA352, 0xC985, 0xA353, 0xC986, 0xA354, 0xC987, 0xA355, 0xC988, 0xC1EE, 0xC989, 0xC1EF, 0xC98A, 0xA356, 0xC98B, 0xA357, + 0xC98C, 0xC1F0, 0xC98D, 0xA358, 0xC98E, 0xA359, 0xC98F, 0xA35A, 0xC990, 0xC1F1, 0xC991, 0xA361, 0xC992, 0xA362, 0xC993, 0xA363, + 0xC994, 0xA364, 0xC995, 0xA365, 0xC996, 0xA366, 0xC997, 0xA367, 0xC998, 0xC1F2, 0xC999, 0xC1F3, 0xC99A, 0xA368, 0xC99B, 0xC1F4, + 0xC99C, 0xA369, 0xC99D, 0xC1F5, 0xC99E, 0xA36A, 0xC99F, 0xA36B, 0xC9A0, 0xA36C, 0xC9A1, 0xA36D, 0xC9A2, 0xA36E, 0xC9A3, 0xA36F, + 0xC9A4, 0xA370, 0xC9A5, 0xA371, 0xC9A6, 0xA372, 0xC9A7, 0xA373, 0xC9A8, 0xA374, 0xC9A9, 0xA375, 0xC9AA, 0xA376, 0xC9AB, 0xA377, + 0xC9AC, 0xA378, 0xC9AD, 0xA379, 0xC9AE, 0xA37A, 0xC9AF, 0xA381, 0xC9B0, 0xA382, 0xC9B1, 0xA383, 0xC9B2, 0xA384, 0xC9B3, 0xA385, + 0xC9B4, 0xA386, 0xC9B5, 0xA387, 0xC9B6, 0xA388, 0xC9B7, 0xA389, 0xC9B8, 0xA38A, 0xC9B9, 0xA38B, 0xC9BA, 0xA38C, 0xC9BB, 0xA38D, + 0xC9BC, 0xA38E, 0xC9BD, 0xA38F, 0xC9BE, 0xA390, 0xC9BF, 0xA391, 0xC9C0, 0xC1F6, 0xC9C1, 0xC1F7, 0xC9C2, 0xA392, 0xC9C3, 0xA393, + 0xC9C4, 0xC1F8, 0xC9C5, 0xA394, 0xC9C6, 0xA395, 0xC9C7, 0xC1F9, 0xC9C8, 0xC1FA, 0xC9C9, 0xA396, 0xC9CA, 0xC1FB, 0xC9CB, 0xA397, + 0xC9CC, 0xA398, 0xC9CD, 0xA399, 0xC9CE, 0xA39A, 0xC9CF, 0xA39B, 0xC9D0, 0xC1FC, 0xC9D1, 0xC1FD, 0xC9D2, 0xA39C, 0xC9D3, 0xC1FE, + 0xC9D4, 0xA39D, 0xC9D5, 0xC2A1, 0xC9D6, 0xC2A2, 0xC9D7, 0xA39E, 0xC9D8, 0xA39F, 0xC9D9, 0xC2A3, 0xC9DA, 0xC2A4, 0xC9DB, 0xA3A0, + 0xC9DC, 0xC2A5, 0xC9DD, 0xC2A6, 0xC9DE, 0xA441, 0xC9DF, 0xA442, 0xC9E0, 0xC2A7, 0xC9E1, 0xA443, 0xC9E2, 0xC2A8, 0xC9E3, 0xA444, + 0xC9E4, 0xC2A9, 0xC9E5, 0xA445, 0xC9E6, 0xA446, 0xC9E7, 0xC2AA, 0xC9E8, 0xA447, 0xC9E9, 0xA448, 0xC9EA, 0xA449, 0xC9EB, 0xA44A, + 0xC9EC, 0xC2AB, 0xC9ED, 0xC2AC, 0xC9EE, 0xA44B, 0xC9EF, 0xC2AD, 0xC9F0, 0xC2AE, 0xC9F1, 0xC2AF, 0xC9F2, 0xA44C, 0xC9F3, 0xA44D, + 0xC9F4, 0xA44E, 0xC9F5, 0xA44F, 0xC9F6, 0xA450, 0xC9F7, 0xA451, 0xC9F8, 0xC2B0, 0xC9F9, 0xC2B1, 0xC9FA, 0xA452, 0xC9FB, 0xA453, + 0xC9FC, 0xC2B2, 0xC9FD, 0xA454, 0xC9FE, 0xA455, 0xC9FF, 0xA456, 0xCA00, 0xC2B3, 0xCA01, 0xA457, 0xCA02, 0xA458, 0xCA03, 0xA459, + 0xCA04, 0xA45A, 0xCA05, 0xA461, 0xCA06, 0xA462, 0xCA07, 0xA463, 0xCA08, 0xC2B4, 0xCA09, 0xC2B5, 0xCA0A, 0xA464, 0xCA0B, 0xC2B6, + 0xCA0C, 0xC2B7, 0xCA0D, 0xC2B8, 0xCA0E, 0xA465, 0xCA0F, 0xA466, 0xCA10, 0xA467, 0xCA11, 0xA468, 0xCA12, 0xA469, 0xCA13, 0xA46A, + 0xCA14, 0xC2B9, 0xCA15, 0xA46B, 0xCA16, 0xA46C, 0xCA17, 0xA46D, 0xCA18, 0xC2BA, 0xCA19, 0xA46E, 0xCA1A, 0xA46F, 0xCA1B, 0xA470, + 0xCA1C, 0xA471, 0xCA1D, 0xA472, 0xCA1E, 0xA473, 0xCA1F, 0xA474, 0xCA20, 0xA475, 0xCA21, 0xA476, 0xCA22, 0xA477, 0xCA23, 0xA478, + 0xCA24, 0xA479, 0xCA25, 0xA47A, 0xCA26, 0xA481, 0xCA27, 0xA482, 0xCA28, 0xA483, 0xCA29, 0xC2BB, 0xCA2A, 0xA484, 0xCA2B, 0xA485, + 0xCA2C, 0xA486, 0xCA2D, 0xA487, 0xCA2E, 0xA488, 0xCA2F, 0xA489, 0xCA30, 0xA48A, 0xCA31, 0xA48B, 0xCA32, 0xA48C, 0xCA33, 0xA48D, + 0xCA34, 0xA48E, 0xCA35, 0xA48F, 0xCA36, 0xA490, 0xCA37, 0xA491, 0xCA38, 0xA492, 0xCA39, 0xA493, 0xCA3A, 0xA494, 0xCA3B, 0xA495, + 0xCA3C, 0xA496, 0xCA3D, 0xA497, 0xCA3E, 0xA498, 0xCA3F, 0xA499, 0xCA40, 0xA49A, 0xCA41, 0xA49B, 0xCA42, 0xA49C, 0xCA43, 0xA49D, + 0xCA44, 0xA49E, 0xCA45, 0xA49F, 0xCA46, 0xA4A0, 0xCA47, 0xA541, 0xCA48, 0xA542, 0xCA49, 0xA543, 0xCA4A, 0xA544, 0xCA4B, 0xA545, + 0xCA4C, 0xC2BC, 0xCA4D, 0xC2BD, 0xCA4E, 0xA546, 0xCA4F, 0xA547, 0xCA50, 0xC2BE, 0xCA51, 0xA548, 0xCA52, 0xA549, 0xCA53, 0xA54A, + 0xCA54, 0xC2BF, 0xCA55, 0xA54B, 0xCA56, 0xA54C, 0xCA57, 0xA54D, 0xCA58, 0xA54E, 0xCA59, 0xA54F, 0xCA5A, 0xA550, 0xCA5B, 0xA551, + 0xCA5C, 0xC2C0, 0xCA5D, 0xC2C1, 0xCA5E, 0xA552, 0xCA5F, 0xC2C2, 0xCA60, 0xC2C3, 0xCA61, 0xC2C4, 0xCA62, 0xA553, 0xCA63, 0xA554, + 0xCA64, 0xA555, 0xCA65, 0xA556, 0xCA66, 0xA557, 0xCA67, 0xA558, 0xCA68, 0xC2C5, 0xCA69, 0xA559, 0xCA6A, 0xA55A, 0xCA6B, 0xA561, + 0xCA6C, 0xA562, 0xCA6D, 0xA563, 0xCA6E, 0xA564, 0xCA6F, 0xA565, 0xCA70, 0xA566, 0xCA71, 0xA567, 0xCA72, 0xA568, 0xCA73, 0xA569, + 0xCA74, 0xA56A, 0xCA75, 0xA56B, 0xCA76, 0xA56C, 0xCA77, 0xA56D, 0xCA78, 0xA56E, 0xCA79, 0xA56F, 0xCA7A, 0xA570, 0xCA7B, 0xA571, + 0xCA7C, 0xA572, 0xCA7D, 0xC2C6, 0xCA7E, 0xA573, 0xCA7F, 0xA574, 0xCA80, 0xA575, 0xCA81, 0xA576, 0xCA82, 0xA577, 0xCA83, 0xA578, + 0xCA84, 0xC2C7, 0xCA85, 0xA579, 0xCA86, 0xA57A, 0xCA87, 0xA581, 0xCA88, 0xA582, 0xCA89, 0xA583, 0xCA8A, 0xA584, 0xCA8B, 0xA585, + 0xCA8C, 0xA586, 0xCA8D, 0xA587, 0xCA8E, 0xA588, 0xCA8F, 0xA589, 0xCA90, 0xA58A, 0xCA91, 0xA58B, 0xCA92, 0xA58C, 0xCA93, 0xA58D, + 0xCA94, 0xA58E, 0xCA95, 0xA58F, 0xCA96, 0xA590, 0xCA97, 0xA591, 0xCA98, 0xC2C8, 0xCA99, 0xA592, 0xCA9A, 0xA593, 0xCA9B, 0xA594, + 0xCA9C, 0xA595, 0xCA9D, 0xA596, 0xCA9E, 0xA597, 0xCA9F, 0xA598, 0xCAA0, 0xA599, 0xCAA1, 0xA59A, 0xCAA2, 0xA59B, 0xCAA3, 0xA59C, + 0xCAA4, 0xA59D, 0xCAA5, 0xA59E, 0xCAA6, 0xA59F, 0xCAA7, 0xA5A0, 0xCAA8, 0xA641, 0xCAA9, 0xA642, 0xCAAA, 0xA643, 0xCAAB, 0xA644, + 0xCAAC, 0xA645, 0xCAAD, 0xA646, 0xCAAE, 0xA647, 0xCAAF, 0xA648, 0xCAB0, 0xA649, 0xCAB1, 0xA64A, 0xCAB2, 0xA64B, 0xCAB3, 0xA64C, + 0xCAB4, 0xA64D, 0xCAB5, 0xA64E, 0xCAB6, 0xA64F, 0xCAB7, 0xA650, 0xCAB8, 0xA651, 0xCAB9, 0xA652, 0xCABA, 0xA653, 0xCABB, 0xA654, + 0xCABC, 0xC2C9, 0xCABD, 0xC2CA, 0xCABE, 0xA655, 0xCABF, 0xA656, 0xCAC0, 0xC2CB, 0xCAC1, 0xA657, 0xCAC2, 0xA658, 0xCAC3, 0xA659, + 0xCAC4, 0xC2CC, 0xCAC5, 0xA65A, 0xCAC6, 0xA661, 0xCAC7, 0xA662, 0xCAC8, 0xA663, 0xCAC9, 0xA664, 0xCACA, 0xA665, 0xCACB, 0xA666, + 0xCACC, 0xC2CD, 0xCACD, 0xC2CE, 0xCACE, 0xA667, 0xCACF, 0xC2CF, 0xCAD0, 0xA668, 0xCAD1, 0xC2D0, 0xCAD2, 0xA669, 0xCAD3, 0xC2D1, + 0xCAD4, 0xA66A, 0xCAD5, 0xA66B, 0xCAD6, 0xA66C, 0xCAD7, 0xA66D, 0xCAD8, 0xC2D2, 0xCAD9, 0xC2D3, 0xCADA, 0xA66E, 0xCADB, 0xA66F, + 0xCADC, 0xA670, 0xCADD, 0xA671, 0xCADE, 0xA672, 0xCADF, 0xA673, 0xCAE0, 0xC2D4, 0xCAE1, 0xA674, 0xCAE2, 0xA675, 0xCAE3, 0xA676, + 0xCAE4, 0xA677, 0xCAE5, 0xA678, 0xCAE6, 0xA679, 0xCAE7, 0xA67A, 0xCAE8, 0xA681, 0xCAE9, 0xA682, 0xCAEA, 0xA683, 0xCAEB, 0xA684, + 0xCAEC, 0xC2D5, 0xCAED, 0xA685, 0xCAEE, 0xA686, 0xCAEF, 0xA687, 0xCAF0, 0xA688, 0xCAF1, 0xA689, 0xCAF2, 0xA68A, 0xCAF3, 0xA68B, + 0xCAF4, 0xC2D6, 0xCAF5, 0xA68C, 0xCAF6, 0xA68D, 0xCAF7, 0xA68E, 0xCAF8, 0xA68F, 0xCAF9, 0xA690, 0xCAFA, 0xA691, 0xCAFB, 0xA692, + 0xCAFC, 0xA693, 0xCAFD, 0xA694, 0xCAFE, 0xA695, 0xCAFF, 0xA696, 0xCB00, 0xA697, 0xCB01, 0xA698, 0xCB02, 0xA699, 0xCB03, 0xA69A, + 0xCB04, 0xA69B, 0xCB05, 0xA69C, 0xCB06, 0xA69D, 0xCB07, 0xA69E, 0xCB08, 0xC2D7, 0xCB09, 0xA69F, 0xCB0A, 0xA6A0, 0xCB0B, 0xA741, + 0xCB0C, 0xA742, 0xCB0D, 0xA743, 0xCB0E, 0xA744, 0xCB0F, 0xA745, 0xCB10, 0xC2D8, 0xCB11, 0xA746, 0xCB12, 0xA747, 0xCB13, 0xA748, + 0xCB14, 0xC2D9, 0xCB15, 0xA749, 0xCB16, 0xA74A, 0xCB17, 0xA74B, 0xCB18, 0xC2DA, 0xCB19, 0xA74C, 0xCB1A, 0xA74D, 0xCB1B, 0xA74E, + 0xCB1C, 0xA74F, 0xCB1D, 0xA750, 0xCB1E, 0xA751, 0xCB1F, 0xA752, 0xCB20, 0xC2DB, 0xCB21, 0xC2DC, 0xCB22, 0xA753, 0xCB23, 0xA754, + 0xCB24, 0xA755, 0xCB25, 0xA756, 0xCB26, 0xA757, 0xCB27, 0xA758, 0xCB28, 0xA759, 0xCB29, 0xA75A, 0xCB2A, 0xA761, 0xCB2B, 0xA762, + 0xCB2C, 0xA763, 0xCB2D, 0xA764, 0xCB2E, 0xA765, 0xCB2F, 0xA766, 0xCB30, 0xA767, 0xCB31, 0xA768, 0xCB32, 0xA769, 0xCB33, 0xA76A, + 0xCB34, 0xA76B, 0xCB35, 0xA76C, 0xCB36, 0xA76D, 0xCB37, 0xA76E, 0xCB38, 0xA76F, 0xCB39, 0xA770, 0xCB3A, 0xA771, 0xCB3B, 0xA772, + 0xCB3C, 0xA773, 0xCB3D, 0xA774, 0xCB3E, 0xA775, 0xCB3F, 0xA776, 0xCB40, 0xA777, 0xCB41, 0xC2DD, 0xCB42, 0xA778, 0xCB43, 0xA779, + 0xCB44, 0xA77A, 0xCB45, 0xA781, 0xCB46, 0xA782, 0xCB47, 0xA783, 0xCB48, 0xC2DE, 0xCB49, 0xC2DF, 0xCB4A, 0xA784, 0xCB4B, 0xA785, + 0xCB4C, 0xC2E0, 0xCB4D, 0xA786, 0xCB4E, 0xA787, 0xCB4F, 0xA788, 0xCB50, 0xC2E1, 0xCB51, 0xA789, 0xCB52, 0xA78A, 0xCB53, 0xA78B, + 0xCB54, 0xA78C, 0xCB55, 0xA78D, 0xCB56, 0xA78E, 0xCB57, 0xA78F, 0xCB58, 0xC2E2, 0xCB59, 0xC2E3, 0xCB5A, 0xA790, 0xCB5B, 0xA791, + 0xCB5C, 0xA792, 0xCB5D, 0xC2E4, 0xCB5E, 0xA793, 0xCB5F, 0xA794, 0xCB60, 0xA795, 0xCB61, 0xA796, 0xCB62, 0xA797, 0xCB63, 0xA798, + 0xCB64, 0xC2E5, 0xCB65, 0xA799, 0xCB66, 0xA79A, 0xCB67, 0xA79B, 0xCB68, 0xA79C, 0xCB69, 0xA79D, 0xCB6A, 0xA79E, 0xCB6B, 0xA79F, + 0xCB6C, 0xA7A0, 0xCB6D, 0xA841, 0xCB6E, 0xA842, 0xCB6F, 0xA843, 0xCB70, 0xA844, 0xCB71, 0xA845, 0xCB72, 0xA846, 0xCB73, 0xA847, + 0xCB74, 0xA848, 0xCB75, 0xA849, 0xCB76, 0xA84A, 0xCB77, 0xA84B, 0xCB78, 0xC2E6, 0xCB79, 0xC2E7, 0xCB7A, 0xA84C, 0xCB7B, 0xA84D, + 0xCB7C, 0xA84E, 0xCB7D, 0xA84F, 0xCB7E, 0xA850, 0xCB7F, 0xA851, 0xCB80, 0xA852, 0xCB81, 0xA853, 0xCB82, 0xA854, 0xCB83, 0xA855, + 0xCB84, 0xA856, 0xCB85, 0xA857, 0xCB86, 0xA858, 0xCB87, 0xA859, 0xCB88, 0xA85A, 0xCB89, 0xA861, 0xCB8A, 0xA862, 0xCB8B, 0xA863, + 0xCB8C, 0xA864, 0xCB8D, 0xA865, 0xCB8E, 0xA866, 0xCB8F, 0xA867, 0xCB90, 0xA868, 0xCB91, 0xA869, 0xCB92, 0xA86A, 0xCB93, 0xA86B, + 0xCB94, 0xA86C, 0xCB95, 0xA86D, 0xCB96, 0xA86E, 0xCB97, 0xA86F, 0xCB98, 0xA870, 0xCB99, 0xA871, 0xCB9A, 0xA872, 0xCB9B, 0xA873, + 0xCB9C, 0xC2E8, 0xCB9D, 0xA874, 0xCB9E, 0xA875, 0xCB9F, 0xA876, 0xCBA0, 0xA877, 0xCBA1, 0xA878, 0xCBA2, 0xA879, 0xCBA3, 0xA87A, + 0xCBA4, 0xA881, 0xCBA5, 0xA882, 0xCBA6, 0xA883, 0xCBA7, 0xA884, 0xCBA8, 0xA885, 0xCBA9, 0xA886, 0xCBAA, 0xA887, 0xCBAB, 0xA888, + 0xCBAC, 0xA889, 0xCBAD, 0xA88A, 0xCBAE, 0xA88B, 0xCBAF, 0xA88C, 0xCBB0, 0xA88D, 0xCBB1, 0xA88E, 0xCBB2, 0xA88F, 0xCBB3, 0xA890, + 0xCBB4, 0xA891, 0xCBB5, 0xA892, 0xCBB6, 0xA893, 0xCBB7, 0xA894, 0xCBB8, 0xC2E9, 0xCBB9, 0xA895, 0xCBBA, 0xA896, 0xCBBB, 0xA897, + 0xCBBC, 0xA898, 0xCBBD, 0xA899, 0xCBBE, 0xA89A, 0xCBBF, 0xA89B, 0xCBC0, 0xA89C, 0xCBC1, 0xA89D, 0xCBC2, 0xA89E, 0xCBC3, 0xA89F, + 0xCBC4, 0xA8A0, 0xCBC5, 0xA941, 0xCBC6, 0xA942, 0xCBC7, 0xA943, 0xCBC8, 0xA944, 0xCBC9, 0xA945, 0xCBCA, 0xA946, 0xCBCB, 0xA947, + 0xCBCC, 0xA948, 0xCBCD, 0xA949, 0xCBCE, 0xA94A, 0xCBCF, 0xA94B, 0xCBD0, 0xA94C, 0xCBD1, 0xA94D, 0xCBD2, 0xA94E, 0xCBD3, 0xA94F, + 0xCBD4, 0xC2EA, 0xCBD5, 0xA950, 0xCBD6, 0xA951, 0xCBD7, 0xA952, 0xCBD8, 0xA953, 0xCBD9, 0xA954, 0xCBDA, 0xA955, 0xCBDB, 0xA956, + 0xCBDC, 0xA957, 0xCBDD, 0xA958, 0xCBDE, 0xA959, 0xCBDF, 0xA95A, 0xCBE0, 0xA961, 0xCBE1, 0xA962, 0xCBE2, 0xA963, 0xCBE3, 0xA964, + 0xCBE4, 0xC2EB, 0xCBE5, 0xA965, 0xCBE6, 0xA966, 0xCBE7, 0xC2EC, 0xCBE8, 0xA967, 0xCBE9, 0xC2ED, 0xCBEA, 0xA968, 0xCBEB, 0xA969, + 0xCBEC, 0xA96A, 0xCBED, 0xA96B, 0xCBEE, 0xA96C, 0xCBEF, 0xA96D, 0xCBF0, 0xA96E, 0xCBF1, 0xA96F, 0xCBF2, 0xA970, 0xCBF3, 0xA971, + 0xCBF4, 0xA972, 0xCBF5, 0xA973, 0xCBF6, 0xA974, 0xCBF7, 0xA975, 0xCBF8, 0xA976, 0xCBF9, 0xA977, 0xCBFA, 0xA978, 0xCBFB, 0xA979, + 0xCBFC, 0xA97A, 0xCBFD, 0xA981, 0xCBFE, 0xA982, 0xCBFF, 0xA983, 0xCC00, 0xA984, 0xCC01, 0xA985, 0xCC02, 0xA986, 0xCC03, 0xA987, + 0xCC04, 0xA988, 0xCC05, 0xA989, 0xCC06, 0xA98A, 0xCC07, 0xA98B, 0xCC08, 0xA98C, 0xCC09, 0xA98D, 0xCC0A, 0xA98E, 0xCC0B, 0xA98F, + 0xCC0C, 0xC2EE, 0xCC0D, 0xC2EF, 0xCC0E, 0xA990, 0xCC0F, 0xA991, 0xCC10, 0xC2F0, 0xCC11, 0xA992, 0xCC12, 0xA993, 0xCC13, 0xA994, + 0xCC14, 0xC2F1, 0xCC15, 0xA995, 0xCC16, 0xA996, 0xCC17, 0xA997, 0xCC18, 0xA998, 0xCC19, 0xA999, 0xCC1A, 0xA99A, 0xCC1B, 0xA99B, + 0xCC1C, 0xC2F2, 0xCC1D, 0xC2F3, 0xCC1E, 0xA99C, 0xCC1F, 0xA99D, 0xCC20, 0xA99E, 0xCC21, 0xC2F4, 0xCC22, 0xC2F5, 0xCC23, 0xA99F, + 0xCC24, 0xA9A0, 0xCC25, 0xAA41, 0xCC26, 0xAA42, 0xCC27, 0xC2F6, 0xCC28, 0xC2F7, 0xCC29, 0xC2F8, 0xCC2A, 0xAA43, 0xCC2B, 0xAA44, + 0xCC2C, 0xC2F9, 0xCC2D, 0xAA45, 0xCC2E, 0xC2FA, 0xCC2F, 0xAA46, 0xCC30, 0xC2FB, 0xCC31, 0xAA47, 0xCC32, 0xAA48, 0xCC33, 0xAA49, + 0xCC34, 0xAA4A, 0xCC35, 0xAA4B, 0xCC36, 0xAA4C, 0xCC37, 0xAA4D, 0xCC38, 0xC2FC, 0xCC39, 0xC2FD, 0xCC3A, 0xAA4E, 0xCC3B, 0xC2FE, + 0xCC3C, 0xC3A1, 0xCC3D, 0xC3A2, 0xCC3E, 0xC3A3, 0xCC3F, 0xAA4F, 0xCC40, 0xAA50, 0xCC41, 0xAA51, 0xCC42, 0xAA52, 0xCC43, 0xAA53, + 0xCC44, 0xC3A4, 0xCC45, 0xC3A5, 0xCC46, 0xAA54, 0xCC47, 0xAA55, 0xCC48, 0xC3A6, 0xCC49, 0xAA56, 0xCC4A, 0xAA57, 0xCC4B, 0xAA58, + 0xCC4C, 0xC3A7, 0xCC4D, 0xAA59, 0xCC4E, 0xAA5A, 0xCC4F, 0xAA61, 0xCC50, 0xAA62, 0xCC51, 0xAA63, 0xCC52, 0xAA64, 0xCC53, 0xAA65, + 0xCC54, 0xC3A8, 0xCC55, 0xC3A9, 0xCC56, 0xAA66, 0xCC57, 0xC3AA, 0xCC58, 0xC3AB, 0xCC59, 0xC3AC, 0xCC5A, 0xAA67, 0xCC5B, 0xAA68, + 0xCC5C, 0xAA69, 0xCC5D, 0xAA6A, 0xCC5E, 0xAA6B, 0xCC5F, 0xAA6C, 0xCC60, 0xC3AD, 0xCC61, 0xAA6D, 0xCC62, 0xAA6E, 0xCC63, 0xAA6F, + 0xCC64, 0xC3AE, 0xCC65, 0xAA70, 0xCC66, 0xC3AF, 0xCC67, 0xAA71, 0xCC68, 0xC3B0, 0xCC69, 0xAA72, 0xCC6A, 0xAA73, 0xCC6B, 0xAA74, + 0xCC6C, 0xAA75, 0xCC6D, 0xAA76, 0xCC6E, 0xAA77, 0xCC6F, 0xAA78, 0xCC70, 0xC3B1, 0xCC71, 0xAA79, 0xCC72, 0xAA7A, 0xCC73, 0xAA81, + 0xCC74, 0xAA82, 0xCC75, 0xC3B2, 0xCC76, 0xAA83, 0xCC77, 0xAA84, 0xCC78, 0xAA85, 0xCC79, 0xAA86, 0xCC7A, 0xAA87, 0xCC7B, 0xAA88, + 0xCC7C, 0xAA89, 0xCC7D, 0xAA8A, 0xCC7E, 0xAA8B, 0xCC7F, 0xAA8C, 0xCC80, 0xAA8D, 0xCC81, 0xAA8E, 0xCC82, 0xAA8F, 0xCC83, 0xAA90, + 0xCC84, 0xAA91, 0xCC85, 0xAA92, 0xCC86, 0xAA93, 0xCC87, 0xAA94, 0xCC88, 0xAA95, 0xCC89, 0xAA96, 0xCC8A, 0xAA97, 0xCC8B, 0xAA98, + 0xCC8C, 0xAA99, 0xCC8D, 0xAA9A, 0xCC8E, 0xAA9B, 0xCC8F, 0xAA9C, 0xCC90, 0xAA9D, 0xCC91, 0xAA9E, 0xCC92, 0xAA9F, 0xCC93, 0xAAA0, + 0xCC94, 0xAB41, 0xCC95, 0xAB42, 0xCC96, 0xAB43, 0xCC97, 0xAB44, 0xCC98, 0xC3B3, 0xCC99, 0xC3B4, 0xCC9A, 0xAB45, 0xCC9B, 0xAB46, + 0xCC9C, 0xC3B5, 0xCC9D, 0xAB47, 0xCC9E, 0xAB48, 0xCC9F, 0xAB49, 0xCCA0, 0xC3B6, 0xCCA1, 0xAB4A, 0xCCA2, 0xAB4B, 0xCCA3, 0xAB4C, + 0xCCA4, 0xAB4D, 0xCCA5, 0xAB4E, 0xCCA6, 0xAB4F, 0xCCA7, 0xAB50, 0xCCA8, 0xC3B7, 0xCCA9, 0xC3B8, 0xCCAA, 0xAB51, 0xCCAB, 0xC3B9, + 0xCCAC, 0xC3BA, 0xCCAD, 0xC3BB, 0xCCAE, 0xAB52, 0xCCAF, 0xAB53, 0xCCB0, 0xAB54, 0xCCB1, 0xAB55, 0xCCB2, 0xAB56, 0xCCB3, 0xAB57, + 0xCCB4, 0xC3BC, 0xCCB5, 0xC3BD, 0xCCB6, 0xAB58, 0xCCB7, 0xAB59, 0xCCB8, 0xC3BE, 0xCCB9, 0xAB5A, 0xCCBA, 0xAB61, 0xCCBB, 0xAB62, + 0xCCBC, 0xC3BF, 0xCCBD, 0xAB63, 0xCCBE, 0xAB64, 0xCCBF, 0xAB65, 0xCCC0, 0xAB66, 0xCCC1, 0xAB67, 0xCCC2, 0xAB68, 0xCCC3, 0xAB69, + 0xCCC4, 0xC3C0, 0xCCC5, 0xC3C1, 0xCCC6, 0xAB6A, 0xCCC7, 0xC3C2, 0xCCC8, 0xAB6B, 0xCCC9, 0xC3C3, 0xCCCA, 0xAB6C, 0xCCCB, 0xAB6D, + 0xCCCC, 0xAB6E, 0xCCCD, 0xAB6F, 0xCCCE, 0xAB70, 0xCCCF, 0xAB71, 0xCCD0, 0xC3C4, 0xCCD1, 0xAB72, 0xCCD2, 0xAB73, 0xCCD3, 0xAB74, + 0xCCD4, 0xC3C5, 0xCCD5, 0xAB75, 0xCCD6, 0xAB76, 0xCCD7, 0xAB77, 0xCCD8, 0xAB78, 0xCCD9, 0xAB79, 0xCCDA, 0xAB7A, 0xCCDB, 0xAB81, + 0xCCDC, 0xAB82, 0xCCDD, 0xAB83, 0xCCDE, 0xAB84, 0xCCDF, 0xAB85, 0xCCE0, 0xAB86, 0xCCE1, 0xAB87, 0xCCE2, 0xAB88, 0xCCE3, 0xAB89, + 0xCCE4, 0xC3C6, 0xCCE5, 0xAB8A, 0xCCE6, 0xAB8B, 0xCCE7, 0xAB8C, 0xCCE8, 0xAB8D, 0xCCE9, 0xAB8E, 0xCCEA, 0xAB8F, 0xCCEB, 0xAB90, + 0xCCEC, 0xC3C7, 0xCCED, 0xAB91, 0xCCEE, 0xAB92, 0xCCEF, 0xAB93, 0xCCF0, 0xC3C8, 0xCCF1, 0xAB94, 0xCCF2, 0xAB95, 0xCCF3, 0xAB96, + 0xCCF4, 0xAB97, 0xCCF5, 0xAB98, 0xCCF6, 0xAB99, 0xCCF7, 0xAB9A, 0xCCF8, 0xAB9B, 0xCCF9, 0xAB9C, 0xCCFA, 0xAB9D, 0xCCFB, 0xAB9E, + 0xCCFC, 0xAB9F, 0xCCFD, 0xABA0, 0xCCFE, 0xAC41, 0xCCFF, 0xAC42, 0xCD00, 0xAC43, 0xCD01, 0xC3C9, 0xCD02, 0xAC44, 0xCD03, 0xAC45, + 0xCD04, 0xAC46, 0xCD05, 0xAC47, 0xCD06, 0xAC48, 0xCD07, 0xAC49, 0xCD08, 0xC3CA, 0xCD09, 0xC3CB, 0xCD0A, 0xAC4A, 0xCD0B, 0xAC4B, + 0xCD0C, 0xC3CC, 0xCD0D, 0xAC4C, 0xCD0E, 0xAC4D, 0xCD0F, 0xAC4E, 0xCD10, 0xC3CD, 0xCD11, 0xAC4F, 0xCD12, 0xAC50, 0xCD13, 0xAC51, + 0xCD14, 0xAC52, 0xCD15, 0xAC53, 0xCD16, 0xAC54, 0xCD17, 0xAC55, 0xCD18, 0xC3CE, 0xCD19, 0xC3CF, 0xCD1A, 0xAC56, 0xCD1B, 0xC3D0, + 0xCD1C, 0xAC57, 0xCD1D, 0xC3D1, 0xCD1E, 0xAC58, 0xCD1F, 0xAC59, 0xCD20, 0xAC5A, 0xCD21, 0xAC61, 0xCD22, 0xAC62, 0xCD23, 0xAC63, + 0xCD24, 0xC3D2, 0xCD25, 0xAC64, 0xCD26, 0xAC65, 0xCD27, 0xAC66, 0xCD28, 0xC3D3, 0xCD29, 0xAC67, 0xCD2A, 0xAC68, 0xCD2B, 0xAC69, + 0xCD2C, 0xC3D4, 0xCD2D, 0xAC6A, 0xCD2E, 0xAC6B, 0xCD2F, 0xAC6C, 0xCD30, 0xAC6D, 0xCD31, 0xAC6E, 0xCD32, 0xAC6F, 0xCD33, 0xAC70, + 0xCD34, 0xAC71, 0xCD35, 0xAC72, 0xCD36, 0xAC73, 0xCD37, 0xAC74, 0xCD38, 0xAC75, 0xCD39, 0xC3D5, 0xCD3A, 0xAC76, 0xCD3B, 0xAC77, + 0xCD3C, 0xAC78, 0xCD3D, 0xAC79, 0xCD3E, 0xAC7A, 0xCD3F, 0xAC81, 0xCD40, 0xAC82, 0xCD41, 0xAC83, 0xCD42, 0xAC84, 0xCD43, 0xAC85, + 0xCD44, 0xAC86, 0xCD45, 0xAC87, 0xCD46, 0xAC88, 0xCD47, 0xAC89, 0xCD48, 0xAC8A, 0xCD49, 0xAC8B, 0xCD4A, 0xAC8C, 0xCD4B, 0xAC8D, + 0xCD4C, 0xAC8E, 0xCD4D, 0xAC8F, 0xCD4E, 0xAC90, 0xCD4F, 0xAC91, 0xCD50, 0xAC92, 0xCD51, 0xAC93, 0xCD52, 0xAC94, 0xCD53, 0xAC95, + 0xCD54, 0xAC96, 0xCD55, 0xAC97, 0xCD56, 0xAC98, 0xCD57, 0xAC99, 0xCD58, 0xAC9A, 0xCD59, 0xAC9B, 0xCD5A, 0xAC9C, 0xCD5B, 0xAC9D, + 0xCD5C, 0xC3D6, 0xCD5D, 0xAC9E, 0xCD5E, 0xAC9F, 0xCD5F, 0xACA0, 0xCD60, 0xC3D7, 0xCD61, 0xAD41, 0xCD62, 0xAD42, 0xCD63, 0xAD43, + 0xCD64, 0xC3D8, 0xCD65, 0xAD44, 0xCD66, 0xAD45, 0xCD67, 0xAD46, 0xCD68, 0xAD47, 0xCD69, 0xAD48, 0xCD6A, 0xAD49, 0xCD6B, 0xAD4A, + 0xCD6C, 0xC3D9, 0xCD6D, 0xC3DA, 0xCD6E, 0xAD4B, 0xCD6F, 0xC3DB, 0xCD70, 0xAD4C, 0xCD71, 0xC3DC, 0xCD72, 0xAD4D, 0xCD73, 0xAD4E, + 0xCD74, 0xAD4F, 0xCD75, 0xAD50, 0xCD76, 0xAD51, 0xCD77, 0xAD52, 0xCD78, 0xC3DD, 0xCD79, 0xAD53, 0xCD7A, 0xAD54, 0xCD7B, 0xAD55, + 0xCD7C, 0xAD56, 0xCD7D, 0xAD57, 0xCD7E, 0xAD58, 0xCD7F, 0xAD59, 0xCD80, 0xAD5A, 0xCD81, 0xAD61, 0xCD82, 0xAD62, 0xCD83, 0xAD63, + 0xCD84, 0xAD64, 0xCD85, 0xAD65, 0xCD86, 0xAD66, 0xCD87, 0xAD67, 0xCD88, 0xC3DE, 0xCD89, 0xAD68, 0xCD8A, 0xAD69, 0xCD8B, 0xAD6A, + 0xCD8C, 0xAD6B, 0xCD8D, 0xAD6C, 0xCD8E, 0xAD6D, 0xCD8F, 0xAD6E, 0xCD90, 0xAD6F, 0xCD91, 0xAD70, 0xCD92, 0xAD71, 0xCD93, 0xAD72, + 0xCD94, 0xC3DF, 0xCD95, 0xC3E0, 0xCD96, 0xAD73, 0xCD97, 0xAD74, 0xCD98, 0xC3E1, 0xCD99, 0xAD75, 0xCD9A, 0xAD76, 0xCD9B, 0xAD77, + 0xCD9C, 0xC3E2, 0xCD9D, 0xAD78, 0xCD9E, 0xAD79, 0xCD9F, 0xAD7A, 0xCDA0, 0xAD81, 0xCDA1, 0xAD82, 0xCDA2, 0xAD83, 0xCDA3, 0xAD84, + 0xCDA4, 0xC3E3, 0xCDA5, 0xC3E4, 0xCDA6, 0xAD85, 0xCDA7, 0xC3E5, 0xCDA8, 0xAD86, 0xCDA9, 0xC3E6, 0xCDAA, 0xAD87, 0xCDAB, 0xAD88, + 0xCDAC, 0xAD89, 0xCDAD, 0xAD8A, 0xCDAE, 0xAD8B, 0xCDAF, 0xAD8C, 0xCDB0, 0xC3E7, 0xCDB1, 0xAD8D, 0xCDB2, 0xAD8E, 0xCDB3, 0xAD8F, + 0xCDB4, 0xAD90, 0xCDB5, 0xAD91, 0xCDB6, 0xAD92, 0xCDB7, 0xAD93, 0xCDB8, 0xAD94, 0xCDB9, 0xAD95, 0xCDBA, 0xAD96, 0xCDBB, 0xAD97, + 0xCDBC, 0xAD98, 0xCDBD, 0xAD99, 0xCDBE, 0xAD9A, 0xCDBF, 0xAD9B, 0xCDC0, 0xAD9C, 0xCDC1, 0xAD9D, 0xCDC2, 0xAD9E, 0xCDC3, 0xAD9F, + 0xCDC4, 0xC3E8, 0xCDC5, 0xADA0, 0xCDC6, 0xAE41, 0xCDC7, 0xAE42, 0xCDC8, 0xAE43, 0xCDC9, 0xAE44, 0xCDCA, 0xAE45, 0xCDCB, 0xAE46, + 0xCDCC, 0xC3E9, 0xCDCD, 0xAE47, 0xCDCE, 0xAE48, 0xCDCF, 0xAE49, 0xCDD0, 0xC3EA, 0xCDD1, 0xAE4A, 0xCDD2, 0xAE4B, 0xCDD3, 0xAE4C, + 0xCDD4, 0xAE4D, 0xCDD5, 0xAE4E, 0xCDD6, 0xAE4F, 0xCDD7, 0xAE50, 0xCDD8, 0xAE51, 0xCDD9, 0xAE52, 0xCDDA, 0xAE53, 0xCDDB, 0xAE54, + 0xCDDC, 0xAE55, 0xCDDD, 0xAE56, 0xCDDE, 0xAE57, 0xCDDF, 0xAE58, 0xCDE0, 0xAE59, 0xCDE1, 0xAE5A, 0xCDE2, 0xAE61, 0xCDE3, 0xAE62, + 0xCDE4, 0xAE63, 0xCDE5, 0xAE64, 0xCDE6, 0xAE65, 0xCDE7, 0xAE66, 0xCDE8, 0xC3EB, 0xCDE9, 0xAE67, 0xCDEA, 0xAE68, 0xCDEB, 0xAE69, + 0xCDEC, 0xC3EC, 0xCDED, 0xAE6A, 0xCDEE, 0xAE6B, 0xCDEF, 0xAE6C, 0xCDF0, 0xC3ED, 0xCDF1, 0xAE6D, 0xCDF2, 0xAE6E, 0xCDF3, 0xAE6F, + 0xCDF4, 0xAE70, 0xCDF5, 0xAE71, 0xCDF6, 0xAE72, 0xCDF7, 0xAE73, 0xCDF8, 0xC3EE, 0xCDF9, 0xC3EF, 0xCDFA, 0xAE74, 0xCDFB, 0xC3F0, + 0xCDFC, 0xAE75, 0xCDFD, 0xC3F1, 0xCDFE, 0xAE76, 0xCDFF, 0xAE77, 0xCE00, 0xAE78, 0xCE01, 0xAE79, 0xCE02, 0xAE7A, 0xCE03, 0xAE81, + 0xCE04, 0xC3F2, 0xCE05, 0xAE82, 0xCE06, 0xAE83, 0xCE07, 0xAE84, 0xCE08, 0xC3F3, 0xCE09, 0xAE85, 0xCE0A, 0xAE86, 0xCE0B, 0xAE87, + 0xCE0C, 0xC3F4, 0xCE0D, 0xAE88, 0xCE0E, 0xAE89, 0xCE0F, 0xAE8A, 0xCE10, 0xAE8B, 0xCE11, 0xAE8C, 0xCE12, 0xAE8D, 0xCE13, 0xAE8E, + 0xCE14, 0xC3F5, 0xCE15, 0xAE8F, 0xCE16, 0xAE90, 0xCE17, 0xAE91, 0xCE18, 0xAE92, 0xCE19, 0xC3F6, 0xCE1A, 0xAE93, 0xCE1B, 0xAE94, + 0xCE1C, 0xAE95, 0xCE1D, 0xAE96, 0xCE1E, 0xAE97, 0xCE1F, 0xAE98, 0xCE20, 0xC3F7, 0xCE21, 0xC3F8, 0xCE22, 0xAE99, 0xCE23, 0xAE9A, + 0xCE24, 0xC3F9, 0xCE25, 0xAE9B, 0xCE26, 0xAE9C, 0xCE27, 0xAE9D, 0xCE28, 0xC3FA, 0xCE29, 0xAE9E, 0xCE2A, 0xAE9F, 0xCE2B, 0xAEA0, + 0xCE2C, 0xAF41, 0xCE2D, 0xAF42, 0xCE2E, 0xAF43, 0xCE2F, 0xAF44, 0xCE30, 0xC3FB, 0xCE31, 0xC3FC, 0xCE32, 0xAF45, 0xCE33, 0xC3FD, + 0xCE34, 0xAF46, 0xCE35, 0xC3FE, 0xCE36, 0xAF47, 0xCE37, 0xAF48, 0xCE38, 0xAF49, 0xCE39, 0xAF4A, 0xCE3A, 0xAF4B, 0xCE3B, 0xAF4C, + 0xCE3C, 0xAF4D, 0xCE3D, 0xAF4E, 0xCE3E, 0xAF4F, 0xCE3F, 0xAF50, 0xCE40, 0xAF51, 0xCE41, 0xAF52, 0xCE42, 0xAF53, 0xCE43, 0xAF54, + 0xCE44, 0xAF55, 0xCE45, 0xAF56, 0xCE46, 0xAF57, 0xCE47, 0xAF58, 0xCE48, 0xAF59, 0xCE49, 0xAF5A, 0xCE4A, 0xAF61, 0xCE4B, 0xAF62, + 0xCE4C, 0xAF63, 0xCE4D, 0xAF64, 0xCE4E, 0xAF65, 0xCE4F, 0xAF66, 0xCE50, 0xAF67, 0xCE51, 0xAF68, 0xCE52, 0xAF69, 0xCE53, 0xAF6A, + 0xCE54, 0xAF6B, 0xCE55, 0xAF6C, 0xCE56, 0xAF6D, 0xCE57, 0xAF6E, 0xCE58, 0xC4A1, 0xCE59, 0xC4A2, 0xCE5A, 0xAF6F, 0xCE5B, 0xAF70, + 0xCE5C, 0xC4A3, 0xCE5D, 0xAF71, 0xCE5E, 0xAF72, 0xCE5F, 0xC4A4, 0xCE60, 0xC4A5, 0xCE61, 0xC4A6, 0xCE62, 0xAF73, 0xCE63, 0xAF74, + 0xCE64, 0xAF75, 0xCE65, 0xAF76, 0xCE66, 0xAF77, 0xCE67, 0xAF78, 0xCE68, 0xC4A7, 0xCE69, 0xC4A8, 0xCE6A, 0xAF79, 0xCE6B, 0xC4A9, + 0xCE6C, 0xAF7A, 0xCE6D, 0xC4AA, 0xCE6E, 0xAF81, 0xCE6F, 0xAF82, 0xCE70, 0xAF83, 0xCE71, 0xAF84, 0xCE72, 0xAF85, 0xCE73, 0xAF86, + 0xCE74, 0xC4AB, 0xCE75, 0xC4AC, 0xCE76, 0xAF87, 0xCE77, 0xAF88, 0xCE78, 0xC4AD, 0xCE79, 0xAF89, 0xCE7A, 0xAF8A, 0xCE7B, 0xAF8B, + 0xCE7C, 0xC4AE, 0xCE7D, 0xAF8C, 0xCE7E, 0xAF8D, 0xCE7F, 0xAF8E, 0xCE80, 0xAF8F, 0xCE81, 0xAF90, 0xCE82, 0xAF91, 0xCE83, 0xAF92, + 0xCE84, 0xC4AF, 0xCE85, 0xC4B0, 0xCE86, 0xAF93, 0xCE87, 0xC4B1, 0xCE88, 0xAF94, 0xCE89, 0xC4B2, 0xCE8A, 0xAF95, 0xCE8B, 0xAF96, + 0xCE8C, 0xAF97, 0xCE8D, 0xAF98, 0xCE8E, 0xAF99, 0xCE8F, 0xAF9A, 0xCE90, 0xC4B3, 0xCE91, 0xC4B4, 0xCE92, 0xAF9B, 0xCE93, 0xAF9C, + 0xCE94, 0xC4B5, 0xCE95, 0xAF9D, 0xCE96, 0xAF9E, 0xCE97, 0xAF9F, 0xCE98, 0xC4B6, 0xCE99, 0xAFA0, 0xCE9A, 0xB041, 0xCE9B, 0xB042, + 0xCE9C, 0xB043, 0xCE9D, 0xB044, 0xCE9E, 0xB045, 0xCE9F, 0xB046, 0xCEA0, 0xC4B7, 0xCEA1, 0xC4B8, 0xCEA2, 0xB047, 0xCEA3, 0xC4B9, + 0xCEA4, 0xC4BA, 0xCEA5, 0xC4BB, 0xCEA6, 0xB048, 0xCEA7, 0xB049, 0xCEA8, 0xB04A, 0xCEA9, 0xB04B, 0xCEAA, 0xB04C, 0xCEAB, 0xB04D, + 0xCEAC, 0xC4BC, 0xCEAD, 0xC4BD, 0xCEAE, 0xB04E, 0xCEAF, 0xB04F, 0xCEB0, 0xB050, 0xCEB1, 0xB051, 0xCEB2, 0xB052, 0xCEB3, 0xB053, + 0xCEB4, 0xB054, 0xCEB5, 0xB055, 0xCEB6, 0xB056, 0xCEB7, 0xB057, 0xCEB8, 0xB058, 0xCEB9, 0xB059, 0xCEBA, 0xB05A, 0xCEBB, 0xB061, + 0xCEBC, 0xB062, 0xCEBD, 0xB063, 0xCEBE, 0xB064, 0xCEBF, 0xB065, 0xCEC0, 0xB066, 0xCEC1, 0xC4BE, 0xCEC2, 0xB067, 0xCEC3, 0xB068, + 0xCEC4, 0xB069, 0xCEC5, 0xB06A, 0xCEC6, 0xB06B, 0xCEC7, 0xB06C, 0xCEC8, 0xB06D, 0xCEC9, 0xB06E, 0xCECA, 0xB06F, 0xCECB, 0xB070, + 0xCECC, 0xB071, 0xCECD, 0xB072, 0xCECE, 0xB073, 0xCECF, 0xB074, 0xCED0, 0xB075, 0xCED1, 0xB076, 0xCED2, 0xB077, 0xCED3, 0xB078, + 0xCED4, 0xB079, 0xCED5, 0xB07A, 0xCED6, 0xB081, 0xCED7, 0xB082, 0xCED8, 0xB083, 0xCED9, 0xB084, 0xCEDA, 0xB085, 0xCEDB, 0xB086, + 0xCEDC, 0xB087, 0xCEDD, 0xB088, 0xCEDE, 0xB089, 0xCEDF, 0xB08A, 0xCEE0, 0xB08B, 0xCEE1, 0xB08C, 0xCEE2, 0xB08D, 0xCEE3, 0xB08E, + 0xCEE4, 0xC4BF, 0xCEE5, 0xC4C0, 0xCEE6, 0xB08F, 0xCEE7, 0xB090, 0xCEE8, 0xC4C1, 0xCEE9, 0xB091, 0xCEEA, 0xB092, 0xCEEB, 0xC4C2, + 0xCEEC, 0xC4C3, 0xCEED, 0xB093, 0xCEEE, 0xB094, 0xCEEF, 0xB095, 0xCEF0, 0xB096, 0xCEF1, 0xB097, 0xCEF2, 0xB098, 0xCEF3, 0xB099, + 0xCEF4, 0xC4C4, 0xCEF5, 0xC4C5, 0xCEF6, 0xB09A, 0xCEF7, 0xC4C6, 0xCEF8, 0xC4C7, 0xCEF9, 0xC4C8, 0xCEFA, 0xB09B, 0xCEFB, 0xB09C, + 0xCEFC, 0xB09D, 0xCEFD, 0xB09E, 0xCEFE, 0xB09F, 0xCEFF, 0xB0A0, 0xCF00, 0xC4C9, 0xCF01, 0xC4CA, 0xCF02, 0xB141, 0xCF03, 0xB142, + 0xCF04, 0xC4CB, 0xCF05, 0xB143, 0xCF06, 0xB144, 0xCF07, 0xB145, 0xCF08, 0xC4CC, 0xCF09, 0xB146, 0xCF0A, 0xB147, 0xCF0B, 0xB148, + 0xCF0C, 0xB149, 0xCF0D, 0xB14A, 0xCF0E, 0xB14B, 0xCF0F, 0xB14C, 0xCF10, 0xC4CD, 0xCF11, 0xC4CE, 0xCF12, 0xB14D, 0xCF13, 0xC4CF, + 0xCF14, 0xB14E, 0xCF15, 0xC4D0, 0xCF16, 0xB14F, 0xCF17, 0xB150, 0xCF18, 0xB151, 0xCF19, 0xB152, 0xCF1A, 0xB153, 0xCF1B, 0xB154, + 0xCF1C, 0xC4D1, 0xCF1D, 0xB155, 0xCF1E, 0xB156, 0xCF1F, 0xB157, 0xCF20, 0xC4D2, 0xCF21, 0xB158, 0xCF22, 0xB159, 0xCF23, 0xB15A, + 0xCF24, 0xC4D3, 0xCF25, 0xB161, 0xCF26, 0xB162, 0xCF27, 0xB163, 0xCF28, 0xB164, 0xCF29, 0xB165, 0xCF2A, 0xB166, 0xCF2B, 0xB167, + 0xCF2C, 0xC4D4, 0xCF2D, 0xC4D5, 0xCF2E, 0xB168, 0xCF2F, 0xC4D6, 0xCF30, 0xC4D7, 0xCF31, 0xC4D8, 0xCF32, 0xB169, 0xCF33, 0xB16A, + 0xCF34, 0xB16B, 0xCF35, 0xB16C, 0xCF36, 0xB16D, 0xCF37, 0xB16E, 0xCF38, 0xC4D9, 0xCF39, 0xB16F, 0xCF3A, 0xB170, 0xCF3B, 0xB171, + 0xCF3C, 0xB172, 0xCF3D, 0xB173, 0xCF3E, 0xB174, 0xCF3F, 0xB175, 0xCF40, 0xB176, 0xCF41, 0xB177, 0xCF42, 0xB178, 0xCF43, 0xB179, + 0xCF44, 0xB17A, 0xCF45, 0xB181, 0xCF46, 0xB182, 0xCF47, 0xB183, 0xCF48, 0xB184, 0xCF49, 0xB185, 0xCF4A, 0xB186, 0xCF4B, 0xB187, + 0xCF4C, 0xB188, 0xCF4D, 0xB189, 0xCF4E, 0xB18A, 0xCF4F, 0xB18B, 0xCF50, 0xB18C, 0xCF51, 0xB18D, 0xCF52, 0xB18E, 0xCF53, 0xB18F, + 0xCF54, 0xC4DA, 0xCF55, 0xC4DB, 0xCF56, 0xB190, 0xCF57, 0xB191, 0xCF58, 0xC4DC, 0xCF59, 0xB192, 0xCF5A, 0xB193, 0xCF5B, 0xB194, + 0xCF5C, 0xC4DD, 0xCF5D, 0xB195, 0xCF5E, 0xB196, 0xCF5F, 0xB197, 0xCF60, 0xB198, 0xCF61, 0xB199, 0xCF62, 0xB19A, 0xCF63, 0xB19B, + 0xCF64, 0xC4DE, 0xCF65, 0xC4DF, 0xCF66, 0xB19C, 0xCF67, 0xC4E0, 0xCF68, 0xB19D, 0xCF69, 0xC4E1, 0xCF6A, 0xB19E, 0xCF6B, 0xB19F, + 0xCF6C, 0xB1A0, 0xCF6D, 0xB241, 0xCF6E, 0xB242, 0xCF6F, 0xB243, 0xCF70, 0xC4E2, 0xCF71, 0xC4E3, 0xCF72, 0xB244, 0xCF73, 0xB245, + 0xCF74, 0xC4E4, 0xCF75, 0xB246, 0xCF76, 0xB247, 0xCF77, 0xB248, 0xCF78, 0xC4E5, 0xCF79, 0xB249, 0xCF7A, 0xB24A, 0xCF7B, 0xB24B, + 0xCF7C, 0xB24C, 0xCF7D, 0xB24D, 0xCF7E, 0xB24E, 0xCF7F, 0xB24F, 0xCF80, 0xC4E6, 0xCF81, 0xB250, 0xCF82, 0xB251, 0xCF83, 0xB252, + 0xCF84, 0xB253, 0xCF85, 0xC4E7, 0xCF86, 0xB254, 0xCF87, 0xB255, 0xCF88, 0xB256, 0xCF89, 0xB257, 0xCF8A, 0xB258, 0xCF8B, 0xB259, + 0xCF8C, 0xC4E8, 0xCF8D, 0xB25A, 0xCF8E, 0xB261, 0xCF8F, 0xB262, 0xCF90, 0xB263, 0xCF91, 0xB264, 0xCF92, 0xB265, 0xCF93, 0xB266, + 0xCF94, 0xB267, 0xCF95, 0xB268, 0xCF96, 0xB269, 0xCF97, 0xB26A, 0xCF98, 0xB26B, 0xCF99, 0xB26C, 0xCF9A, 0xB26D, 0xCF9B, 0xB26E, + 0xCF9C, 0xB26F, 0xCF9D, 0xB270, 0xCF9E, 0xB271, 0xCF9F, 0xB272, 0xCFA0, 0xB273, 0xCFA1, 0xC4E9, 0xCFA2, 0xB274, 0xCFA3, 0xB275, + 0xCFA4, 0xB276, 0xCFA5, 0xB277, 0xCFA6, 0xB278, 0xCFA7, 0xB279, 0xCFA8, 0xC4EA, 0xCFA9, 0xB27A, 0xCFAA, 0xB281, 0xCFAB, 0xB282, + 0xCFAC, 0xB283, 0xCFAD, 0xB284, 0xCFAE, 0xB285, 0xCFAF, 0xB286, 0xCFB0, 0xC4EB, 0xCFB1, 0xB287, 0xCFB2, 0xB288, 0xCFB3, 0xB289, + 0xCFB4, 0xB28A, 0xCFB5, 0xB28B, 0xCFB6, 0xB28C, 0xCFB7, 0xB28D, 0xCFB8, 0xB28E, 0xCFB9, 0xB28F, 0xCFBA, 0xB290, 0xCFBB, 0xB291, + 0xCFBC, 0xB292, 0xCFBD, 0xB293, 0xCFBE, 0xB294, 0xCFBF, 0xB295, 0xCFC0, 0xB296, 0xCFC1, 0xB297, 0xCFC2, 0xB298, 0xCFC3, 0xB299, + 0xCFC4, 0xC4EC, 0xCFC5, 0xB29A, 0xCFC6, 0xB29B, 0xCFC7, 0xB29C, 0xCFC8, 0xB29D, 0xCFC9, 0xB29E, 0xCFCA, 0xB29F, 0xCFCB, 0xB2A0, + 0xCFCC, 0xB341, 0xCFCD, 0xB342, 0xCFCE, 0xB343, 0xCFCF, 0xB344, 0xCFD0, 0xB345, 0xCFD1, 0xB346, 0xCFD2, 0xB347, 0xCFD3, 0xB348, + 0xCFD4, 0xB349, 0xCFD5, 0xB34A, 0xCFD6, 0xB34B, 0xCFD7, 0xB34C, 0xCFD8, 0xB34D, 0xCFD9, 0xB34E, 0xCFDA, 0xB34F, 0xCFDB, 0xB350, + 0xCFDC, 0xB351, 0xCFDD, 0xB352, 0xCFDE, 0xB353, 0xCFDF, 0xB354, 0xCFE0, 0xC4ED, 0xCFE1, 0xC4EE, 0xCFE2, 0xB355, 0xCFE3, 0xB356, + 0xCFE4, 0xC4EF, 0xCFE5, 0xB357, 0xCFE6, 0xB358, 0xCFE7, 0xB359, 0xCFE8, 0xC4F0, 0xCFE9, 0xB35A, 0xCFEA, 0xB361, 0xCFEB, 0xB362, + 0xCFEC, 0xB363, 0xCFED, 0xB364, 0xCFEE, 0xB365, 0xCFEF, 0xB366, 0xCFF0, 0xC4F1, 0xCFF1, 0xC4F2, 0xCFF2, 0xB367, 0xCFF3, 0xC4F3, + 0xCFF4, 0xB368, 0xCFF5, 0xC4F4, 0xCFF6, 0xB369, 0xCFF7, 0xB36A, 0xCFF8, 0xB36B, 0xCFF9, 0xB36C, 0xCFFA, 0xB36D, 0xCFFB, 0xB36E, + 0xCFFC, 0xC4F5, 0xCFFD, 0xB36F, 0xCFFE, 0xB370, 0xCFFF, 0xB371, 0xD000, 0xC4F6, 0xD001, 0xB372, 0xD002, 0xB373, 0xD003, 0xB374, + 0xD004, 0xC4F7, 0xD005, 0xB375, 0xD006, 0xB376, 0xD007, 0xB377, 0xD008, 0xB378, 0xD009, 0xB379, 0xD00A, 0xB37A, 0xD00B, 0xB381, + 0xD00C, 0xB382, 0xD00D, 0xB383, 0xD00E, 0xB384, 0xD00F, 0xB385, 0xD010, 0xB386, 0xD011, 0xC4F8, 0xD012, 0xB387, 0xD013, 0xB388, + 0xD014, 0xB389, 0xD015, 0xB38A, 0xD016, 0xB38B, 0xD017, 0xB38C, 0xD018, 0xC4F9, 0xD019, 0xB38D, 0xD01A, 0xB38E, 0xD01B, 0xB38F, + 0xD01C, 0xB390, 0xD01D, 0xB391, 0xD01E, 0xB392, 0xD01F, 0xB393, 0xD020, 0xB394, 0xD021, 0xB395, 0xD022, 0xB396, 0xD023, 0xB397, + 0xD024, 0xB398, 0xD025, 0xB399, 0xD026, 0xB39A, 0xD027, 0xB39B, 0xD028, 0xB39C, 0xD029, 0xB39D, 0xD02A, 0xB39E, 0xD02B, 0xB39F, + 0xD02C, 0xB3A0, 0xD02D, 0xC4FA, 0xD02E, 0xB441, 0xD02F, 0xB442, 0xD030, 0xB443, 0xD031, 0xB444, 0xD032, 0xB445, 0xD033, 0xB446, + 0xD034, 0xC4FB, 0xD035, 0xC4FC, 0xD036, 0xB447, 0xD037, 0xB448, 0xD038, 0xC4FD, 0xD039, 0xB449, 0xD03A, 0xB44A, 0xD03B, 0xB44B, + 0xD03C, 0xC4FE, 0xD03D, 0xB44C, 0xD03E, 0xB44D, 0xD03F, 0xB44E, 0xD040, 0xB44F, 0xD041, 0xB450, 0xD042, 0xB451, 0xD043, 0xB452, + 0xD044, 0xC5A1, 0xD045, 0xC5A2, 0xD046, 0xB453, 0xD047, 0xC5A3, 0xD048, 0xB454, 0xD049, 0xC5A4, 0xD04A, 0xB455, 0xD04B, 0xB456, + 0xD04C, 0xB457, 0xD04D, 0xB458, 0xD04E, 0xB459, 0xD04F, 0xB45A, 0xD050, 0xC5A5, 0xD051, 0xB461, 0xD052, 0xB462, 0xD053, 0xB463, + 0xD054, 0xC5A6, 0xD055, 0xB464, 0xD056, 0xB465, 0xD057, 0xB466, 0xD058, 0xC5A7, 0xD059, 0xB467, 0xD05A, 0xB468, 0xD05B, 0xB469, + 0xD05C, 0xB46A, 0xD05D, 0xB46B, 0xD05E, 0xB46C, 0xD05F, 0xB46D, 0xD060, 0xC5A8, 0xD061, 0xB46E, 0xD062, 0xB46F, 0xD063, 0xB470, + 0xD064, 0xB471, 0xD065, 0xB472, 0xD066, 0xB473, 0xD067, 0xB474, 0xD068, 0xB475, 0xD069, 0xB476, 0xD06A, 0xB477, 0xD06B, 0xB478, + 0xD06C, 0xC5A9, 0xD06D, 0xC5AA, 0xD06E, 0xB479, 0xD06F, 0xB47A, 0xD070, 0xC5AB, 0xD071, 0xB481, 0xD072, 0xB482, 0xD073, 0xB483, + 0xD074, 0xC5AC, 0xD075, 0xB484, 0xD076, 0xB485, 0xD077, 0xB486, 0xD078, 0xB487, 0xD079, 0xB488, 0xD07A, 0xB489, 0xD07B, 0xB48A, + 0xD07C, 0xC5AD, 0xD07D, 0xC5AE, 0xD07E, 0xB48B, 0xD07F, 0xB48C, 0xD080, 0xB48D, 0xD081, 0xC5AF, 0xD082, 0xB48E, 0xD083, 0xB48F, + 0xD084, 0xB490, 0xD085, 0xB491, 0xD086, 0xB492, 0xD087, 0xB493, 0xD088, 0xB494, 0xD089, 0xB495, 0xD08A, 0xB496, 0xD08B, 0xB497, + 0xD08C, 0xB498, 0xD08D, 0xB499, 0xD08E, 0xB49A, 0xD08F, 0xB49B, 0xD090, 0xB49C, 0xD091, 0xB49D, 0xD092, 0xB49E, 0xD093, 0xB49F, + 0xD094, 0xB4A0, 0xD095, 0xB541, 0xD096, 0xB542, 0xD097, 0xB543, 0xD098, 0xB544, 0xD099, 0xB545, 0xD09A, 0xB546, 0xD09B, 0xB547, + 0xD09C, 0xB548, 0xD09D, 0xB549, 0xD09E, 0xB54A, 0xD09F, 0xB54B, 0xD0A0, 0xB54C, 0xD0A1, 0xB54D, 0xD0A2, 0xB54E, 0xD0A3, 0xB54F, + 0xD0A4, 0xC5B0, 0xD0A5, 0xC5B1, 0xD0A6, 0xB550, 0xD0A7, 0xB551, 0xD0A8, 0xC5B2, 0xD0A9, 0xB552, 0xD0AA, 0xB553, 0xD0AB, 0xB554, + 0xD0AC, 0xC5B3, 0xD0AD, 0xB555, 0xD0AE, 0xB556, 0xD0AF, 0xB557, 0xD0B0, 0xB558, 0xD0B1, 0xB559, 0xD0B2, 0xB55A, 0xD0B3, 0xB561, + 0xD0B4, 0xC5B4, 0xD0B5, 0xC5B5, 0xD0B6, 0xB562, 0xD0B7, 0xC5B6, 0xD0B8, 0xB563, 0xD0B9, 0xC5B7, 0xD0BA, 0xB564, 0xD0BB, 0xB565, + 0xD0BC, 0xB566, 0xD0BD, 0xB567, 0xD0BE, 0xB568, 0xD0BF, 0xB569, 0xD0C0, 0xC5B8, 0xD0C1, 0xC5B9, 0xD0C2, 0xB56A, 0xD0C3, 0xB56B, + 0xD0C4, 0xC5BA, 0xD0C5, 0xB56C, 0xD0C6, 0xB56D, 0xD0C7, 0xB56E, 0xD0C8, 0xC5BB, 0xD0C9, 0xC5BC, 0xD0CA, 0xB56F, 0xD0CB, 0xB570, + 0xD0CC, 0xB571, 0xD0CD, 0xB572, 0xD0CE, 0xB573, 0xD0CF, 0xB574, 0xD0D0, 0xC5BD, 0xD0D1, 0xC5BE, 0xD0D2, 0xB575, 0xD0D3, 0xC5BF, + 0xD0D4, 0xC5C0, 0xD0D5, 0xC5C1, 0xD0D6, 0xB576, 0xD0D7, 0xB577, 0xD0D8, 0xB578, 0xD0D9, 0xB579, 0xD0DA, 0xB57A, 0xD0DB, 0xB581, + 0xD0DC, 0xC5C2, 0xD0DD, 0xC5C3, 0xD0DE, 0xB582, 0xD0DF, 0xB583, 0xD0E0, 0xC5C4, 0xD0E1, 0xB584, 0xD0E2, 0xB585, 0xD0E3, 0xB586, + 0xD0E4, 0xC5C5, 0xD0E5, 0xB587, 0xD0E6, 0xB588, 0xD0E7, 0xB589, 0xD0E8, 0xB58A, 0xD0E9, 0xB58B, 0xD0EA, 0xB58C, 0xD0EB, 0xB58D, + 0xD0EC, 0xC5C6, 0xD0ED, 0xC5C7, 0xD0EE, 0xB58E, 0xD0EF, 0xC5C8, 0xD0F0, 0xC5C9, 0xD0F1, 0xC5CA, 0xD0F2, 0xB58F, 0xD0F3, 0xB590, + 0xD0F4, 0xB591, 0xD0F5, 0xB592, 0xD0F6, 0xB593, 0xD0F7, 0xB594, 0xD0F8, 0xC5CB, 0xD0F9, 0xB595, 0xD0FA, 0xB596, 0xD0FB, 0xB597, + 0xD0FC, 0xB598, 0xD0FD, 0xB599, 0xD0FE, 0xB59A, 0xD0FF, 0xB59B, 0xD100, 0xB59C, 0xD101, 0xB59D, 0xD102, 0xB59E, 0xD103, 0xB59F, + 0xD104, 0xB5A0, 0xD105, 0xB641, 0xD106, 0xB642, 0xD107, 0xB643, 0xD108, 0xB644, 0xD109, 0xB645, 0xD10A, 0xB646, 0xD10B, 0xB647, + 0xD10C, 0xB648, 0xD10D, 0xC5CC, 0xD10E, 0xB649, 0xD10F, 0xB64A, 0xD110, 0xB64B, 0xD111, 0xB64C, 0xD112, 0xB64D, 0xD113, 0xB64E, + 0xD114, 0xB64F, 0xD115, 0xB650, 0xD116, 0xB651, 0xD117, 0xB652, 0xD118, 0xB653, 0xD119, 0xB654, 0xD11A, 0xB655, 0xD11B, 0xB656, + 0xD11C, 0xB657, 0xD11D, 0xB658, 0xD11E, 0xB659, 0xD11F, 0xB65A, 0xD120, 0xB661, 0xD121, 0xB662, 0xD122, 0xB663, 0xD123, 0xB664, + 0xD124, 0xB665, 0xD125, 0xB666, 0xD126, 0xB667, 0xD127, 0xB668, 0xD128, 0xB669, 0xD129, 0xB66A, 0xD12A, 0xB66B, 0xD12B, 0xB66C, + 0xD12C, 0xB66D, 0xD12D, 0xB66E, 0xD12E, 0xB66F, 0xD12F, 0xB670, 0xD130, 0xC5CD, 0xD131, 0xC5CE, 0xD132, 0xB671, 0xD133, 0xB672, + 0xD134, 0xC5CF, 0xD135, 0xB673, 0xD136, 0xB674, 0xD137, 0xB675, 0xD138, 0xC5D0, 0xD139, 0xB676, 0xD13A, 0xC5D1, 0xD13B, 0xB677, + 0xD13C, 0xB678, 0xD13D, 0xB679, 0xD13E, 0xB67A, 0xD13F, 0xB681, 0xD140, 0xC5D2, 0xD141, 0xC5D3, 0xD142, 0xB682, 0xD143, 0xC5D4, + 0xD144, 0xC5D5, 0xD145, 0xC5D6, 0xD146, 0xB683, 0xD147, 0xB684, 0xD148, 0xB685, 0xD149, 0xB686, 0xD14A, 0xB687, 0xD14B, 0xB688, + 0xD14C, 0xC5D7, 0xD14D, 0xC5D8, 0xD14E, 0xB689, 0xD14F, 0xB68A, 0xD150, 0xC5D9, 0xD151, 0xB68B, 0xD152, 0xB68C, 0xD153, 0xB68D, + 0xD154, 0xC5DA, 0xD155, 0xB68E, 0xD156, 0xB68F, 0xD157, 0xB690, 0xD158, 0xB691, 0xD159, 0xB692, 0xD15A, 0xB693, 0xD15B, 0xB694, + 0xD15C, 0xC5DB, 0xD15D, 0xC5DC, 0xD15E, 0xB695, 0xD15F, 0xC5DD, 0xD160, 0xB696, 0xD161, 0xC5DE, 0xD162, 0xB697, 0xD163, 0xB698, + 0xD164, 0xB699, 0xD165, 0xB69A, 0xD166, 0xB69B, 0xD167, 0xB69C, 0xD168, 0xC5DF, 0xD169, 0xB69D, 0xD16A, 0xB69E, 0xD16B, 0xB69F, + 0xD16C, 0xC5E0, 0xD16D, 0xB6A0, 0xD16E, 0xB741, 0xD16F, 0xB742, 0xD170, 0xB743, 0xD171, 0xB744, 0xD172, 0xB745, 0xD173, 0xB746, + 0xD174, 0xB747, 0xD175, 0xB748, 0xD176, 0xB749, 0xD177, 0xB74A, 0xD178, 0xB74B, 0xD179, 0xB74C, 0xD17A, 0xB74D, 0xD17B, 0xB74E, + 0xD17C, 0xC5E1, 0xD17D, 0xB74F, 0xD17E, 0xB750, 0xD17F, 0xB751, 0xD180, 0xB752, 0xD181, 0xB753, 0xD182, 0xB754, 0xD183, 0xB755, + 0xD184, 0xC5E2, 0xD185, 0xB756, 0xD186, 0xB757, 0xD187, 0xB758, 0xD188, 0xC5E3, 0xD189, 0xB759, 0xD18A, 0xB75A, 0xD18B, 0xB761, + 0xD18C, 0xB762, 0xD18D, 0xB763, 0xD18E, 0xB764, 0xD18F, 0xB765, 0xD190, 0xB766, 0xD191, 0xB767, 0xD192, 0xB768, 0xD193, 0xB769, + 0xD194, 0xB76A, 0xD195, 0xB76B, 0xD196, 0xB76C, 0xD197, 0xB76D, 0xD198, 0xB76E, 0xD199, 0xB76F, 0xD19A, 0xB770, 0xD19B, 0xB771, + 0xD19C, 0xB772, 0xD19D, 0xB773, 0xD19E, 0xB774, 0xD19F, 0xB775, 0xD1A0, 0xC5E4, 0xD1A1, 0xC5E5, 0xD1A2, 0xB776, 0xD1A3, 0xB777, + 0xD1A4, 0xC5E6, 0xD1A5, 0xB778, 0xD1A6, 0xB779, 0xD1A7, 0xB77A, 0xD1A8, 0xC5E7, 0xD1A9, 0xB781, 0xD1AA, 0xB782, 0xD1AB, 0xB783, + 0xD1AC, 0xB784, 0xD1AD, 0xB785, 0xD1AE, 0xB786, 0xD1AF, 0xB787, 0xD1B0, 0xC5E8, 0xD1B1, 0xC5E9, 0xD1B2, 0xB788, 0xD1B3, 0xC5EA, + 0xD1B4, 0xB789, 0xD1B5, 0xC5EB, 0xD1B6, 0xB78A, 0xD1B7, 0xB78B, 0xD1B8, 0xB78C, 0xD1B9, 0xB78D, 0xD1BA, 0xC5EC, 0xD1BB, 0xB78E, + 0xD1BC, 0xC5ED, 0xD1BD, 0xB78F, 0xD1BE, 0xB790, 0xD1BF, 0xB791, 0xD1C0, 0xC5EE, 0xD1C1, 0xB792, 0xD1C2, 0xB793, 0xD1C3, 0xB794, + 0xD1C4, 0xB795, 0xD1C5, 0xB796, 0xD1C6, 0xB797, 0xD1C7, 0xB798, 0xD1C8, 0xB799, 0xD1C9, 0xB79A, 0xD1CA, 0xB79B, 0xD1CB, 0xB79C, + 0xD1CC, 0xB79D, 0xD1CD, 0xB79E, 0xD1CE, 0xB79F, 0xD1CF, 0xB7A0, 0xD1D0, 0xB841, 0xD1D1, 0xB842, 0xD1D2, 0xB843, 0xD1D3, 0xB844, + 0xD1D4, 0xB845, 0xD1D5, 0xB846, 0xD1D6, 0xB847, 0xD1D7, 0xB848, 0xD1D8, 0xC5EF, 0xD1D9, 0xB849, 0xD1DA, 0xB84A, 0xD1DB, 0xB84B, + 0xD1DC, 0xB84C, 0xD1DD, 0xB84D, 0xD1DE, 0xB84E, 0xD1DF, 0xB84F, 0xD1E0, 0xB850, 0xD1E1, 0xB851, 0xD1E2, 0xB852, 0xD1E3, 0xB853, + 0xD1E4, 0xB854, 0xD1E5, 0xB855, 0xD1E6, 0xB856, 0xD1E7, 0xB857, 0xD1E8, 0xB858, 0xD1E9, 0xB859, 0xD1EA, 0xB85A, 0xD1EB, 0xB861, + 0xD1EC, 0xB862, 0xD1ED, 0xB863, 0xD1EE, 0xB864, 0xD1EF, 0xB865, 0xD1F0, 0xB866, 0xD1F1, 0xB867, 0xD1F2, 0xB868, 0xD1F3, 0xB869, + 0xD1F4, 0xC5F0, 0xD1F5, 0xB86A, 0xD1F6, 0xB86B, 0xD1F7, 0xB86C, 0xD1F8, 0xC5F1, 0xD1F9, 0xB86D, 0xD1FA, 0xB86E, 0xD1FB, 0xB86F, + 0xD1FC, 0xB870, 0xD1FD, 0xB871, 0xD1FE, 0xB872, 0xD1FF, 0xB873, 0xD200, 0xB874, 0xD201, 0xB875, 0xD202, 0xB876, 0xD203, 0xB877, + 0xD204, 0xB878, 0xD205, 0xB879, 0xD206, 0xB87A, 0xD207, 0xC5F2, 0xD208, 0xB881, 0xD209, 0xC5F3, 0xD20A, 0xB882, 0xD20B, 0xB883, + 0xD20C, 0xB884, 0xD20D, 0xB885, 0xD20E, 0xB886, 0xD20F, 0xB887, 0xD210, 0xC5F4, 0xD211, 0xB888, 0xD212, 0xB889, 0xD213, 0xB88A, + 0xD214, 0xB88B, 0xD215, 0xB88C, 0xD216, 0xB88D, 0xD217, 0xB88E, 0xD218, 0xB88F, 0xD219, 0xB890, 0xD21A, 0xB891, 0xD21B, 0xB892, + 0xD21C, 0xB893, 0xD21D, 0xB894, 0xD21E, 0xB895, 0xD21F, 0xB896, 0xD220, 0xB897, 0xD221, 0xB898, 0xD222, 0xB899, 0xD223, 0xB89A, + 0xD224, 0xB89B, 0xD225, 0xB89C, 0xD226, 0xB89D, 0xD227, 0xB89E, 0xD228, 0xB89F, 0xD229, 0xB8A0, 0xD22A, 0xB941, 0xD22B, 0xB942, + 0xD22C, 0xC5F5, 0xD22D, 0xC5F6, 0xD22E, 0xB943, 0xD22F, 0xB944, 0xD230, 0xC5F7, 0xD231, 0xB945, 0xD232, 0xB946, 0xD233, 0xB947, + 0xD234, 0xC5F8, 0xD235, 0xB948, 0xD236, 0xB949, 0xD237, 0xB94A, 0xD238, 0xB94B, 0xD239, 0xB94C, 0xD23A, 0xB94D, 0xD23B, 0xB94E, + 0xD23C, 0xC5F9, 0xD23D, 0xC5FA, 0xD23E, 0xB94F, 0xD23F, 0xC5FB, 0xD240, 0xB950, 0xD241, 0xC5FC, 0xD242, 0xB951, 0xD243, 0xB952, + 0xD244, 0xB953, 0xD245, 0xB954, 0xD246, 0xB955, 0xD247, 0xB956, 0xD248, 0xC5FD, 0xD249, 0xB957, 0xD24A, 0xB958, 0xD24B, 0xB959, + 0xD24C, 0xB95A, 0xD24D, 0xB961, 0xD24E, 0xB962, 0xD24F, 0xB963, 0xD250, 0xB964, 0xD251, 0xB965, 0xD252, 0xB966, 0xD253, 0xB967, + 0xD254, 0xB968, 0xD255, 0xB969, 0xD256, 0xB96A, 0xD257, 0xB96B, 0xD258, 0xB96C, 0xD259, 0xB96D, 0xD25A, 0xB96E, 0xD25B, 0xB96F, + 0xD25C, 0xC5FE, 0xD25D, 0xB970, 0xD25E, 0xB971, 0xD25F, 0xB972, 0xD260, 0xB973, 0xD261, 0xB974, 0xD262, 0xB975, 0xD263, 0xB976, + 0xD264, 0xC6A1, 0xD265, 0xB977, 0xD266, 0xB978, 0xD267, 0xB979, 0xD268, 0xB97A, 0xD269, 0xB981, 0xD26A, 0xB982, 0xD26B, 0xB983, + 0xD26C, 0xB984, 0xD26D, 0xB985, 0xD26E, 0xB986, 0xD26F, 0xB987, 0xD270, 0xB988, 0xD271, 0xB989, 0xD272, 0xB98A, 0xD273, 0xB98B, + 0xD274, 0xB98C, 0xD275, 0xB98D, 0xD276, 0xB98E, 0xD277, 0xB98F, 0xD278, 0xB990, 0xD279, 0xB991, 0xD27A, 0xB992, 0xD27B, 0xB993, + 0xD27C, 0xB994, 0xD27D, 0xB995, 0xD27E, 0xB996, 0xD27F, 0xB997, 0xD280, 0xC6A2, 0xD281, 0xC6A3, 0xD282, 0xB998, 0xD283, 0xB999, + 0xD284, 0xC6A4, 0xD285, 0xB99A, 0xD286, 0xB99B, 0xD287, 0xB99C, 0xD288, 0xC6A5, 0xD289, 0xB99D, 0xD28A, 0xB99E, 0xD28B, 0xB99F, + 0xD28C, 0xB9A0, 0xD28D, 0xBA41, 0xD28E, 0xBA42, 0xD28F, 0xBA43, 0xD290, 0xC6A6, 0xD291, 0xC6A7, 0xD292, 0xBA44, 0xD293, 0xBA45, + 0xD294, 0xBA46, 0xD295, 0xC6A8, 0xD296, 0xBA47, 0xD297, 0xBA48, 0xD298, 0xBA49, 0xD299, 0xBA4A, 0xD29A, 0xBA4B, 0xD29B, 0xBA4C, + 0xD29C, 0xC6A9, 0xD29D, 0xBA4D, 0xD29E, 0xBA4E, 0xD29F, 0xBA4F, 0xD2A0, 0xC6AA, 0xD2A1, 0xBA50, 0xD2A2, 0xBA51, 0xD2A3, 0xBA52, + 0xD2A4, 0xC6AB, 0xD2A5, 0xBA53, 0xD2A6, 0xBA54, 0xD2A7, 0xBA55, 0xD2A8, 0xBA56, 0xD2A9, 0xBA57, 0xD2AA, 0xBA58, 0xD2AB, 0xBA59, + 0xD2AC, 0xC6AC, 0xD2AD, 0xBA5A, 0xD2AE, 0xBA61, 0xD2AF, 0xBA62, 0xD2B0, 0xBA63, 0xD2B1, 0xC6AD, 0xD2B2, 0xBA64, 0xD2B3, 0xBA65, + 0xD2B4, 0xBA66, 0xD2B5, 0xBA67, 0xD2B6, 0xBA68, 0xD2B7, 0xBA69, 0xD2B8, 0xC6AE, 0xD2B9, 0xC6AF, 0xD2BA, 0xBA6A, 0xD2BB, 0xBA6B, + 0xD2BC, 0xC6B0, 0xD2BD, 0xBA6C, 0xD2BE, 0xBA6D, 0xD2BF, 0xC6B1, 0xD2C0, 0xC6B2, 0xD2C1, 0xBA6E, 0xD2C2, 0xC6B3, 0xD2C3, 0xBA6F, + 0xD2C4, 0xBA70, 0xD2C5, 0xBA71, 0xD2C6, 0xBA72, 0xD2C7, 0xBA73, 0xD2C8, 0xC6B4, 0xD2C9, 0xC6B5, 0xD2CA, 0xBA74, 0xD2CB, 0xC6B6, + 0xD2CC, 0xBA75, 0xD2CD, 0xBA76, 0xD2CE, 0xBA77, 0xD2CF, 0xBA78, 0xD2D0, 0xBA79, 0xD2D1, 0xBA7A, 0xD2D2, 0xBA81, 0xD2D3, 0xBA82, + 0xD2D4, 0xC6B7, 0xD2D5, 0xBA83, 0xD2D6, 0xBA84, 0xD2D7, 0xBA85, 0xD2D8, 0xC6B8, 0xD2D9, 0xBA86, 0xD2DA, 0xBA87, 0xD2DB, 0xBA88, + 0xD2DC, 0xC6B9, 0xD2DD, 0xBA89, 0xD2DE, 0xBA8A, 0xD2DF, 0xBA8B, 0xD2E0, 0xBA8C, 0xD2E1, 0xBA8D, 0xD2E2, 0xBA8E, 0xD2E3, 0xBA8F, + 0xD2E4, 0xC6BA, 0xD2E5, 0xC6BB, 0xD2E6, 0xBA90, 0xD2E7, 0xBA91, 0xD2E8, 0xBA92, 0xD2E9, 0xBA93, 0xD2EA, 0xBA94, 0xD2EB, 0xBA95, + 0xD2EC, 0xBA96, 0xD2ED, 0xBA97, 0xD2EE, 0xBA98, 0xD2EF, 0xBA99, 0xD2F0, 0xC6BC, 0xD2F1, 0xC6BD, 0xD2F2, 0xBA9A, 0xD2F3, 0xBA9B, + 0xD2F4, 0xC6BE, 0xD2F5, 0xBA9C, 0xD2F6, 0xBA9D, 0xD2F7, 0xBA9E, 0xD2F8, 0xC6BF, 0xD2F9, 0xBA9F, 0xD2FA, 0xBAA0, 0xD2FB, 0xBB41, + 0xD2FC, 0xBB42, 0xD2FD, 0xBB43, 0xD2FE, 0xBB44, 0xD2FF, 0xBB45, 0xD300, 0xC6C0, 0xD301, 0xC6C1, 0xD302, 0xBB46, 0xD303, 0xC6C2, + 0xD304, 0xBB47, 0xD305, 0xC6C3, 0xD306, 0xBB48, 0xD307, 0xBB49, 0xD308, 0xBB4A, 0xD309, 0xBB4B, 0xD30A, 0xBB4C, 0xD30B, 0xBB4D, + 0xD30C, 0xC6C4, 0xD30D, 0xC6C5, 0xD30E, 0xC6C6, 0xD30F, 0xBB4E, 0xD310, 0xC6C7, 0xD311, 0xBB4F, 0xD312, 0xBB50, 0xD313, 0xBB51, + 0xD314, 0xC6C8, 0xD315, 0xBB52, 0xD316, 0xC6C9, 0xD317, 0xBB53, 0xD318, 0xBB54, 0xD319, 0xBB55, 0xD31A, 0xBB56, 0xD31B, 0xBB57, + 0xD31C, 0xC6CA, 0xD31D, 0xC6CB, 0xD31E, 0xBB58, 0xD31F, 0xC6CC, 0xD320, 0xC6CD, 0xD321, 0xC6CE, 0xD322, 0xBB59, 0xD323, 0xBB5A, + 0xD324, 0xBB61, 0xD325, 0xC6CF, 0xD326, 0xBB62, 0xD327, 0xBB63, 0xD328, 0xC6D0, 0xD329, 0xC6D1, 0xD32A, 0xBB64, 0xD32B, 0xBB65, + 0xD32C, 0xC6D2, 0xD32D, 0xBB66, 0xD32E, 0xBB67, 0xD32F, 0xBB68, 0xD330, 0xC6D3, 0xD331, 0xBB69, 0xD332, 0xBB6A, 0xD333, 0xBB6B, + 0xD334, 0xBB6C, 0xD335, 0xBB6D, 0xD336, 0xBB6E, 0xD337, 0xBB6F, 0xD338, 0xC6D4, 0xD339, 0xC6D5, 0xD33A, 0xBB70, 0xD33B, 0xC6D6, + 0xD33C, 0xC6D7, 0xD33D, 0xC6D8, 0xD33E, 0xBB71, 0xD33F, 0xBB72, 0xD340, 0xBB73, 0xD341, 0xBB74, 0xD342, 0xBB75, 0xD343, 0xBB76, + 0xD344, 0xC6D9, 0xD345, 0xC6DA, 0xD346, 0xBB77, 0xD347, 0xBB78, 0xD348, 0xBB79, 0xD349, 0xBB7A, 0xD34A, 0xBB81, 0xD34B, 0xBB82, + 0xD34C, 0xBB83, 0xD34D, 0xBB84, 0xD34E, 0xBB85, 0xD34F, 0xBB86, 0xD350, 0xBB87, 0xD351, 0xBB88, 0xD352, 0xBB89, 0xD353, 0xBB8A, + 0xD354, 0xBB8B, 0xD355, 0xBB8C, 0xD356, 0xBB8D, 0xD357, 0xBB8E, 0xD358, 0xBB8F, 0xD359, 0xBB90, 0xD35A, 0xBB91, 0xD35B, 0xBB92, + 0xD35C, 0xBB93, 0xD35D, 0xBB94, 0xD35E, 0xBB95, 0xD35F, 0xBB96, 0xD360, 0xBB97, 0xD361, 0xBB98, 0xD362, 0xBB99, 0xD363, 0xBB9A, + 0xD364, 0xBB9B, 0xD365, 0xBB9C, 0xD366, 0xBB9D, 0xD367, 0xBB9E, 0xD368, 0xBB9F, 0xD369, 0xBBA0, 0xD36A, 0xBC41, 0xD36B, 0xBC42, + 0xD36C, 0xBC43, 0xD36D, 0xBC44, 0xD36E, 0xBC45, 0xD36F, 0xBC46, 0xD370, 0xBC47, 0xD371, 0xBC48, 0xD372, 0xBC49, 0xD373, 0xBC4A, + 0xD374, 0xBC4B, 0xD375, 0xBC4C, 0xD376, 0xBC4D, 0xD377, 0xBC4E, 0xD378, 0xBC4F, 0xD379, 0xBC50, 0xD37A, 0xBC51, 0xD37B, 0xBC52, + 0xD37C, 0xC6DB, 0xD37D, 0xC6DC, 0xD37E, 0xBC53, 0xD37F, 0xBC54, 0xD380, 0xC6DD, 0xD381, 0xBC55, 0xD382, 0xBC56, 0xD383, 0xBC57, + 0xD384, 0xC6DE, 0xD385, 0xBC58, 0xD386, 0xBC59, 0xD387, 0xBC5A, 0xD388, 0xBC61, 0xD389, 0xBC62, 0xD38A, 0xBC63, 0xD38B, 0xBC64, + 0xD38C, 0xC6DF, 0xD38D, 0xC6E0, 0xD38E, 0xBC65, 0xD38F, 0xC6E1, 0xD390, 0xC6E2, 0xD391, 0xC6E3, 0xD392, 0xBC66, 0xD393, 0xBC67, + 0xD394, 0xBC68, 0xD395, 0xBC69, 0xD396, 0xBC6A, 0xD397, 0xBC6B, 0xD398, 0xC6E4, 0xD399, 0xC6E5, 0xD39A, 0xBC6C, 0xD39B, 0xBC6D, + 0xD39C, 0xC6E6, 0xD39D, 0xBC6E, 0xD39E, 0xBC6F, 0xD39F, 0xBC70, 0xD3A0, 0xC6E7, 0xD3A1, 0xBC71, 0xD3A2, 0xBC72, 0xD3A3, 0xBC73, + 0xD3A4, 0xBC74, 0xD3A5, 0xBC75, 0xD3A6, 0xBC76, 0xD3A7, 0xBC77, 0xD3A8, 0xC6E8, 0xD3A9, 0xC6E9, 0xD3AA, 0xBC78, 0xD3AB, 0xC6EA, + 0xD3AC, 0xBC79, 0xD3AD, 0xC6EB, 0xD3AE, 0xBC7A, 0xD3AF, 0xBC81, 0xD3B0, 0xBC82, 0xD3B1, 0xBC83, 0xD3B2, 0xBC84, 0xD3B3, 0xBC85, + 0xD3B4, 0xC6EC, 0xD3B5, 0xBC86, 0xD3B6, 0xBC87, 0xD3B7, 0xBC88, 0xD3B8, 0xC6ED, 0xD3B9, 0xBC89, 0xD3BA, 0xBC8A, 0xD3BB, 0xBC8B, + 0xD3BC, 0xC6EE, 0xD3BD, 0xBC8C, 0xD3BE, 0xBC8D, 0xD3BF, 0xBC8E, 0xD3C0, 0xBC8F, 0xD3C1, 0xBC90, 0xD3C2, 0xBC91, 0xD3C3, 0xBC92, + 0xD3C4, 0xC6EF, 0xD3C5, 0xC6F0, 0xD3C6, 0xBC93, 0xD3C7, 0xBC94, 0xD3C8, 0xC6F1, 0xD3C9, 0xC6F2, 0xD3CA, 0xBC95, 0xD3CB, 0xBC96, + 0xD3CC, 0xBC97, 0xD3CD, 0xBC98, 0xD3CE, 0xBC99, 0xD3CF, 0xBC9A, 0xD3D0, 0xC6F3, 0xD3D1, 0xBC9B, 0xD3D2, 0xBC9C, 0xD3D3, 0xBC9D, + 0xD3D4, 0xBC9E, 0xD3D5, 0xBC9F, 0xD3D6, 0xBCA0, 0xD3D7, 0xBD41, 0xD3D8, 0xC6F4, 0xD3D9, 0xBD42, 0xD3DA, 0xBD43, 0xD3DB, 0xBD44, + 0xD3DC, 0xBD45, 0xD3DD, 0xBD46, 0xD3DE, 0xBD47, 0xD3DF, 0xBD48, 0xD3E0, 0xBD49, 0xD3E1, 0xC6F5, 0xD3E2, 0xBD4A, 0xD3E3, 0xC6F6, + 0xD3E4, 0xBD4B, 0xD3E5, 0xBD4C, 0xD3E6, 0xBD4D, 0xD3E7, 0xBD4E, 0xD3E8, 0xBD4F, 0xD3E9, 0xBD50, 0xD3EA, 0xBD51, 0xD3EB, 0xBD52, + 0xD3EC, 0xC6F7, 0xD3ED, 0xC6F8, 0xD3EE, 0xBD53, 0xD3EF, 0xBD54, 0xD3F0, 0xC6F9, 0xD3F1, 0xBD55, 0xD3F2, 0xBD56, 0xD3F3, 0xBD57, + 0xD3F4, 0xC6FA, 0xD3F5, 0xBD58, 0xD3F6, 0xBD59, 0xD3F7, 0xBD5A, 0xD3F8, 0xBD61, 0xD3F9, 0xBD62, 0xD3FA, 0xBD63, 0xD3FB, 0xBD64, + 0xD3FC, 0xC6FB, 0xD3FD, 0xC6FC, 0xD3FE, 0xBD65, 0xD3FF, 0xC6FD, 0xD400, 0xBD66, 0xD401, 0xC6FE, 0xD402, 0xBD67, 0xD403, 0xBD68, + 0xD404, 0xBD69, 0xD405, 0xBD6A, 0xD406, 0xBD6B, 0xD407, 0xBD6C, 0xD408, 0xC7A1, 0xD409, 0xBD6D, 0xD40A, 0xBD6E, 0xD40B, 0xBD6F, + 0xD40C, 0xBD70, 0xD40D, 0xBD71, 0xD40E, 0xBD72, 0xD40F, 0xBD73, 0xD410, 0xBD74, 0xD411, 0xBD75, 0xD412, 0xBD76, 0xD413, 0xBD77, + 0xD414, 0xBD78, 0xD415, 0xBD79, 0xD416, 0xBD7A, 0xD417, 0xBD81, 0xD418, 0xBD82, 0xD419, 0xBD83, 0xD41A, 0xBD84, 0xD41B, 0xBD85, + 0xD41C, 0xBD86, 0xD41D, 0xC7A2, 0xD41E, 0xBD87, 0xD41F, 0xBD88, 0xD420, 0xBD89, 0xD421, 0xBD8A, 0xD422, 0xBD8B, 0xD423, 0xBD8C, + 0xD424, 0xBD8D, 0xD425, 0xBD8E, 0xD426, 0xBD8F, 0xD427, 0xBD90, 0xD428, 0xBD91, 0xD429, 0xBD92, 0xD42A, 0xBD93, 0xD42B, 0xBD94, + 0xD42C, 0xBD95, 0xD42D, 0xBD96, 0xD42E, 0xBD97, 0xD42F, 0xBD98, 0xD430, 0xBD99, 0xD431, 0xBD9A, 0xD432, 0xBD9B, 0xD433, 0xBD9C, + 0xD434, 0xBD9D, 0xD435, 0xBD9E, 0xD436, 0xBD9F, 0xD437, 0xBDA0, 0xD438, 0xBE41, 0xD439, 0xBE42, 0xD43A, 0xBE43, 0xD43B, 0xBE44, + 0xD43C, 0xBE45, 0xD43D, 0xBE46, 0xD43E, 0xBE47, 0xD43F, 0xBE48, 0xD440, 0xC7A3, 0xD441, 0xBE49, 0xD442, 0xBE4A, 0xD443, 0xBE4B, + 0xD444, 0xC7A4, 0xD445, 0xBE4C, 0xD446, 0xBE4D, 0xD447, 0xBE4E, 0xD448, 0xBE4F, 0xD449, 0xBE50, 0xD44A, 0xBE51, 0xD44B, 0xBE52, + 0xD44C, 0xBE53, 0xD44D, 0xBE54, 0xD44E, 0xBE55, 0xD44F, 0xBE56, 0xD450, 0xBE57, 0xD451, 0xBE58, 0xD452, 0xBE59, 0xD453, 0xBE5A, + 0xD454, 0xBE61, 0xD455, 0xBE62, 0xD456, 0xBE63, 0xD457, 0xBE64, 0xD458, 0xBE65, 0xD459, 0xBE66, 0xD45A, 0xBE67, 0xD45B, 0xBE68, + 0xD45C, 0xC7A5, 0xD45D, 0xBE69, 0xD45E, 0xBE6A, 0xD45F, 0xBE6B, 0xD460, 0xC7A6, 0xD461, 0xBE6C, 0xD462, 0xBE6D, 0xD463, 0xBE6E, + 0xD464, 0xC7A7, 0xD465, 0xBE6F, 0xD466, 0xBE70, 0xD467, 0xBE71, 0xD468, 0xBE72, 0xD469, 0xBE73, 0xD46A, 0xBE74, 0xD46B, 0xBE75, + 0xD46C, 0xBE76, 0xD46D, 0xC7A8, 0xD46E, 0xBE77, 0xD46F, 0xC7A9, 0xD470, 0xBE78, 0xD471, 0xBE79, 0xD472, 0xBE7A, 0xD473, 0xBE81, + 0xD474, 0xBE82, 0xD475, 0xBE83, 0xD476, 0xBE84, 0xD477, 0xBE85, 0xD478, 0xC7AA, 0xD479, 0xC7AB, 0xD47A, 0xBE86, 0xD47B, 0xBE87, + 0xD47C, 0xC7AC, 0xD47D, 0xBE88, 0xD47E, 0xBE89, 0xD47F, 0xC7AD, 0xD480, 0xC7AE, 0xD481, 0xBE8A, 0xD482, 0xC7AF, 0xD483, 0xBE8B, + 0xD484, 0xBE8C, 0xD485, 0xBE8D, 0xD486, 0xBE8E, 0xD487, 0xBE8F, 0xD488, 0xC7B0, 0xD489, 0xC7B1, 0xD48A, 0xBE90, 0xD48B, 0xC7B2, + 0xD48C, 0xBE91, 0xD48D, 0xC7B3, 0xD48E, 0xBE92, 0xD48F, 0xBE93, 0xD490, 0xBE94, 0xD491, 0xBE95, 0xD492, 0xBE96, 0xD493, 0xBE97, + 0xD494, 0xC7B4, 0xD495, 0xBE98, 0xD496, 0xBE99, 0xD497, 0xBE9A, 0xD498, 0xBE9B, 0xD499, 0xBE9C, 0xD49A, 0xBE9D, 0xD49B, 0xBE9E, + 0xD49C, 0xBE9F, 0xD49D, 0xBEA0, 0xD49E, 0xBF41, 0xD49F, 0xBF42, 0xD4A0, 0xBF43, 0xD4A1, 0xBF44, 0xD4A2, 0xBF45, 0xD4A3, 0xBF46, + 0xD4A4, 0xBF47, 0xD4A5, 0xBF48, 0xD4A6, 0xBF49, 0xD4A7, 0xBF4A, 0xD4A8, 0xBF4B, 0xD4A9, 0xC7B5, 0xD4AA, 0xBF4C, 0xD4AB, 0xBF4D, + 0xD4AC, 0xBF4E, 0xD4AD, 0xBF4F, 0xD4AE, 0xBF50, 0xD4AF, 0xBF51, 0xD4B0, 0xBF52, 0xD4B1, 0xBF53, 0xD4B2, 0xBF54, 0xD4B3, 0xBF55, + 0xD4B4, 0xBF56, 0xD4B5, 0xBF57, 0xD4B6, 0xBF58, 0xD4B7, 0xBF59, 0xD4B8, 0xBF5A, 0xD4B9, 0xBF61, 0xD4BA, 0xBF62, 0xD4BB, 0xBF63, + 0xD4BC, 0xBF64, 0xD4BD, 0xBF65, 0xD4BE, 0xBF66, 0xD4BF, 0xBF67, 0xD4C0, 0xBF68, 0xD4C1, 0xBF69, 0xD4C2, 0xBF6A, 0xD4C3, 0xBF6B, + 0xD4C4, 0xBF6C, 0xD4C5, 0xBF6D, 0xD4C6, 0xBF6E, 0xD4C7, 0xBF6F, 0xD4C8, 0xBF70, 0xD4C9, 0xBF71, 0xD4CA, 0xBF72, 0xD4CB, 0xBF73, + 0xD4CC, 0xC7B6, 0xD4CD, 0xBF74, 0xD4CE, 0xBF75, 0xD4CF, 0xBF76, 0xD4D0, 0xC7B7, 0xD4D1, 0xBF77, 0xD4D2, 0xBF78, 0xD4D3, 0xBF79, + 0xD4D4, 0xC7B8, 0xD4D5, 0xBF7A, 0xD4D6, 0xBF81, 0xD4D7, 0xBF82, 0xD4D8, 0xBF83, 0xD4D9, 0xBF84, 0xD4DA, 0xBF85, 0xD4DB, 0xBF86, + 0xD4DC, 0xC7B9, 0xD4DD, 0xBF87, 0xD4DE, 0xBF88, 0xD4DF, 0xC7BA, 0xD4E0, 0xBF89, 0xD4E1, 0xBF8A, 0xD4E2, 0xBF8B, 0xD4E3, 0xBF8C, + 0xD4E4, 0xBF8D, 0xD4E5, 0xBF8E, 0xD4E6, 0xBF8F, 0xD4E7, 0xBF90, 0xD4E8, 0xC7BB, 0xD4E9, 0xBF91, 0xD4EA, 0xBF92, 0xD4EB, 0xBF93, + 0xD4EC, 0xC7BC, 0xD4ED, 0xBF94, 0xD4EE, 0xBF95, 0xD4EF, 0xBF96, 0xD4F0, 0xC7BD, 0xD4F1, 0xBF97, 0xD4F2, 0xBF98, 0xD4F3, 0xBF99, + 0xD4F4, 0xBF9A, 0xD4F5, 0xBF9B, 0xD4F6, 0xBF9C, 0xD4F7, 0xBF9D, 0xD4F8, 0xC7BE, 0xD4F9, 0xBF9E, 0xD4FA, 0xBF9F, 0xD4FB, 0xC7BF, + 0xD4FC, 0xBFA0, 0xD4FD, 0xC7C0, 0xD4FE, 0xC041, 0xD4FF, 0xC042, 0xD500, 0xC043, 0xD501, 0xC044, 0xD502, 0xC045, 0xD503, 0xC046, + 0xD504, 0xC7C1, 0xD505, 0xC047, 0xD506, 0xC048, 0xD507, 0xC049, 0xD508, 0xC7C2, 0xD509, 0xC04A, 0xD50A, 0xC04B, 0xD50B, 0xC04C, + 0xD50C, 0xC7C3, 0xD50D, 0xC04D, 0xD50E, 0xC04E, 0xD50F, 0xC04F, 0xD510, 0xC050, 0xD511, 0xC051, 0xD512, 0xC052, 0xD513, 0xC053, + 0xD514, 0xC7C4, 0xD515, 0xC7C5, 0xD516, 0xC054, 0xD517, 0xC7C6, 0xD518, 0xC055, 0xD519, 0xC056, 0xD51A, 0xC057, 0xD51B, 0xC058, + 0xD51C, 0xC059, 0xD51D, 0xC05A, 0xD51E, 0xC061, 0xD51F, 0xC062, 0xD520, 0xC063, 0xD521, 0xC064, 0xD522, 0xC065, 0xD523, 0xC066, + 0xD524, 0xC067, 0xD525, 0xC068, 0xD526, 0xC069, 0xD527, 0xC06A, 0xD528, 0xC06B, 0xD529, 0xC06C, 0xD52A, 0xC06D, 0xD52B, 0xC06E, + 0xD52C, 0xC06F, 0xD52D, 0xC070, 0xD52E, 0xC071, 0xD52F, 0xC072, 0xD530, 0xC073, 0xD531, 0xC074, 0xD532, 0xC075, 0xD533, 0xC076, + 0xD534, 0xC077, 0xD535, 0xC078, 0xD536, 0xC079, 0xD537, 0xC07A, 0xD538, 0xC081, 0xD539, 0xC082, 0xD53A, 0xC083, 0xD53B, 0xC084, + 0xD53C, 0xC7C7, 0xD53D, 0xC7C8, 0xD53E, 0xC085, 0xD53F, 0xC086, 0xD540, 0xC7C9, 0xD541, 0xC087, 0xD542, 0xC088, 0xD543, 0xC089, + 0xD544, 0xC7CA, 0xD545, 0xC08A, 0xD546, 0xC08B, 0xD547, 0xC08C, 0xD548, 0xC08D, 0xD549, 0xC08E, 0xD54A, 0xC08F, 0xD54B, 0xC090, + 0xD54C, 0xC7CB, 0xD54D, 0xC7CC, 0xD54E, 0xC091, 0xD54F, 0xC7CD, 0xD550, 0xC092, 0xD551, 0xC7CE, 0xD552, 0xC093, 0xD553, 0xC094, + 0xD554, 0xC095, 0xD555, 0xC096, 0xD556, 0xC097, 0xD557, 0xC098, 0xD558, 0xC7CF, 0xD559, 0xC7D0, 0xD55A, 0xC099, 0xD55B, 0xC09A, + 0xD55C, 0xC7D1, 0xD55D, 0xC09B, 0xD55E, 0xC09C, 0xD55F, 0xC09D, 0xD560, 0xC7D2, 0xD561, 0xC09E, 0xD562, 0xC09F, 0xD563, 0xC0A0, + 0xD564, 0xC141, 0xD565, 0xC7D3, 0xD566, 0xC142, 0xD567, 0xC143, 0xD568, 0xC7D4, 0xD569, 0xC7D5, 0xD56A, 0xC144, 0xD56B, 0xC7D6, + 0xD56C, 0xC145, 0xD56D, 0xC7D7, 0xD56E, 0xC146, 0xD56F, 0xC147, 0xD570, 0xC148, 0xD571, 0xC149, 0xD572, 0xC14A, 0xD573, 0xC14B, + 0xD574, 0xC7D8, 0xD575, 0xC7D9, 0xD576, 0xC14C, 0xD577, 0xC14D, 0xD578, 0xC7DA, 0xD579, 0xC14E, 0xD57A, 0xC14F, 0xD57B, 0xC150, + 0xD57C, 0xC7DB, 0xD57D, 0xC151, 0xD57E, 0xC152, 0xD57F, 0xC153, 0xD580, 0xC154, 0xD581, 0xC155, 0xD582, 0xC156, 0xD583, 0xC157, + 0xD584, 0xC7DC, 0xD585, 0xC7DD, 0xD586, 0xC158, 0xD587, 0xC7DE, 0xD588, 0xC7DF, 0xD589, 0xC7E0, 0xD58A, 0xC159, 0xD58B, 0xC15A, + 0xD58C, 0xC161, 0xD58D, 0xC162, 0xD58E, 0xC163, 0xD58F, 0xC164, 0xD590, 0xC7E1, 0xD591, 0xC165, 0xD592, 0xC166, 0xD593, 0xC167, + 0xD594, 0xC168, 0xD595, 0xC169, 0xD596, 0xC16A, 0xD597, 0xC16B, 0xD598, 0xC16C, 0xD599, 0xC16D, 0xD59A, 0xC16E, 0xD59B, 0xC16F, + 0xD59C, 0xC170, 0xD59D, 0xC171, 0xD59E, 0xC172, 0xD59F, 0xC173, 0xD5A0, 0xC174, 0xD5A1, 0xC175, 0xD5A2, 0xC176, 0xD5A3, 0xC177, + 0xD5A4, 0xC178, 0xD5A5, 0xC7E2, 0xD5A6, 0xC179, 0xD5A7, 0xC17A, 0xD5A8, 0xC181, 0xD5A9, 0xC182, 0xD5AA, 0xC183, 0xD5AB, 0xC184, + 0xD5AC, 0xC185, 0xD5AD, 0xC186, 0xD5AE, 0xC187, 0xD5AF, 0xC188, 0xD5B0, 0xC189, 0xD5B1, 0xC18A, 0xD5B2, 0xC18B, 0xD5B3, 0xC18C, + 0xD5B4, 0xC18D, 0xD5B5, 0xC18E, 0xD5B6, 0xC18F, 0xD5B7, 0xC190, 0xD5B8, 0xC191, 0xD5B9, 0xC192, 0xD5BA, 0xC193, 0xD5BB, 0xC194, + 0xD5BC, 0xC195, 0xD5BD, 0xC196, 0xD5BE, 0xC197, 0xD5BF, 0xC198, 0xD5C0, 0xC199, 0xD5C1, 0xC19A, 0xD5C2, 0xC19B, 0xD5C3, 0xC19C, + 0xD5C4, 0xC19D, 0xD5C5, 0xC19E, 0xD5C6, 0xC19F, 0xD5C7, 0xC1A0, 0xD5C8, 0xC7E3, 0xD5C9, 0xC7E4, 0xD5CA, 0xC241, 0xD5CB, 0xC242, + 0xD5CC, 0xC7E5, 0xD5CD, 0xC243, 0xD5CE, 0xC244, 0xD5CF, 0xC245, 0xD5D0, 0xC7E6, 0xD5D1, 0xC246, 0xD5D2, 0xC7E7, 0xD5D3, 0xC247, + 0xD5D4, 0xC248, 0xD5D5, 0xC249, 0xD5D6, 0xC24A, 0xD5D7, 0xC24B, 0xD5D8, 0xC7E8, 0xD5D9, 0xC7E9, 0xD5DA, 0xC24C, 0xD5DB, 0xC7EA, + 0xD5DC, 0xC24D, 0xD5DD, 0xC7EB, 0xD5DE, 0xC24E, 0xD5DF, 0xC24F, 0xD5E0, 0xC250, 0xD5E1, 0xC251, 0xD5E2, 0xC252, 0xD5E3, 0xC253, + 0xD5E4, 0xC7EC, 0xD5E5, 0xC7ED, 0xD5E6, 0xC254, 0xD5E7, 0xC255, 0xD5E8, 0xC7EE, 0xD5E9, 0xC256, 0xD5EA, 0xC257, 0xD5EB, 0xC258, + 0xD5EC, 0xC7EF, 0xD5ED, 0xC259, 0xD5EE, 0xC25A, 0xD5EF, 0xC261, 0xD5F0, 0xC262, 0xD5F1, 0xC263, 0xD5F2, 0xC264, 0xD5F3, 0xC265, + 0xD5F4, 0xC7F0, 0xD5F5, 0xC7F1, 0xD5F6, 0xC266, 0xD5F7, 0xC7F2, 0xD5F8, 0xC267, 0xD5F9, 0xC7F3, 0xD5FA, 0xC268, 0xD5FB, 0xC269, + 0xD5FC, 0xC26A, 0xD5FD, 0xC26B, 0xD5FE, 0xC26C, 0xD5FF, 0xC26D, 0xD600, 0xC7F4, 0xD601, 0xC7F5, 0xD602, 0xC26E, 0xD603, 0xC26F, + 0xD604, 0xC7F6, 0xD605, 0xC270, 0xD606, 0xC271, 0xD607, 0xC272, 0xD608, 0xC7F7, 0xD609, 0xC273, 0xD60A, 0xC274, 0xD60B, 0xC275, + 0xD60C, 0xC276, 0xD60D, 0xC277, 0xD60E, 0xC278, 0xD60F, 0xC279, 0xD610, 0xC7F8, 0xD611, 0xC7F9, 0xD612, 0xC27A, 0xD613, 0xC7FA, + 0xD614, 0xC7FB, 0xD615, 0xC7FC, 0xD616, 0xC281, 0xD617, 0xC282, 0xD618, 0xC283, 0xD619, 0xC284, 0xD61A, 0xC285, 0xD61B, 0xC286, + 0xD61C, 0xC7FD, 0xD61D, 0xC287, 0xD61E, 0xC288, 0xD61F, 0xC289, 0xD620, 0xC7FE, 0xD621, 0xC28A, 0xD622, 0xC28B, 0xD623, 0xC28C, + 0xD624, 0xC8A1, 0xD625, 0xC28D, 0xD626, 0xC28E, 0xD627, 0xC28F, 0xD628, 0xC290, 0xD629, 0xC291, 0xD62A, 0xC292, 0xD62B, 0xC293, + 0xD62C, 0xC294, 0xD62D, 0xC8A2, 0xD62E, 0xC295, 0xD62F, 0xC296, 0xD630, 0xC297, 0xD631, 0xC298, 0xD632, 0xC299, 0xD633, 0xC29A, + 0xD634, 0xC29B, 0xD635, 0xC29C, 0xD636, 0xC29D, 0xD637, 0xC29E, 0xD638, 0xC8A3, 0xD639, 0xC8A4, 0xD63A, 0xC29F, 0xD63B, 0xC2A0, + 0xD63C, 0xC8A5, 0xD63D, 0xC341, 0xD63E, 0xC342, 0xD63F, 0xC343, 0xD640, 0xC8A6, 0xD641, 0xC344, 0xD642, 0xC345, 0xD643, 0xC346, + 0xD644, 0xC347, 0xD645, 0xC8A7, 0xD646, 0xC348, 0xD647, 0xC349, 0xD648, 0xC8A8, 0xD649, 0xC8A9, 0xD64A, 0xC34A, 0xD64B, 0xC8AA, + 0xD64C, 0xC34B, 0xD64D, 0xC8AB, 0xD64E, 0xC34C, 0xD64F, 0xC34D, 0xD650, 0xC34E, 0xD651, 0xC8AC, 0xD652, 0xC34F, 0xD653, 0xC350, + 0xD654, 0xC8AD, 0xD655, 0xC8AE, 0xD656, 0xC351, 0xD657, 0xC352, 0xD658, 0xC8AF, 0xD659, 0xC353, 0xD65A, 0xC354, 0xD65B, 0xC355, + 0xD65C, 0xC8B0, 0xD65D, 0xC356, 0xD65E, 0xC357, 0xD65F, 0xC358, 0xD660, 0xC359, 0xD661, 0xC35A, 0xD662, 0xC361, 0xD663, 0xC362, + 0xD664, 0xC363, 0xD665, 0xC364, 0xD666, 0xC365, 0xD667, 0xC8B1, 0xD668, 0xC366, 0xD669, 0xC8B2, 0xD66A, 0xC367, 0xD66B, 0xC368, + 0xD66C, 0xC369, 0xD66D, 0xC36A, 0xD66E, 0xC36B, 0xD66F, 0xC36C, 0xD670, 0xC8B3, 0xD671, 0xC8B4, 0xD672, 0xC36D, 0xD673, 0xC36E, + 0xD674, 0xC8B5, 0xD675, 0xC36F, 0xD676, 0xC370, 0xD677, 0xC371, 0xD678, 0xC372, 0xD679, 0xC373, 0xD67A, 0xC374, 0xD67B, 0xC375, + 0xD67C, 0xC376, 0xD67D, 0xC377, 0xD67E, 0xC378, 0xD67F, 0xC379, 0xD680, 0xC37A, 0xD681, 0xC381, 0xD682, 0xC382, 0xD683, 0xC8B6, + 0xD684, 0xC383, 0xD685, 0xC8B7, 0xD686, 0xC384, 0xD687, 0xC385, 0xD688, 0xC386, 0xD689, 0xC387, 0xD68A, 0xC388, 0xD68B, 0xC389, + 0xD68C, 0xC8B8, 0xD68D, 0xC8B9, 0xD68E, 0xC38A, 0xD68F, 0xC38B, 0xD690, 0xC8BA, 0xD691, 0xC38C, 0xD692, 0xC38D, 0xD693, 0xC38E, + 0xD694, 0xC8BB, 0xD695, 0xC38F, 0xD696, 0xC390, 0xD697, 0xC391, 0xD698, 0xC392, 0xD699, 0xC393, 0xD69A, 0xC394, 0xD69B, 0xC395, + 0xD69C, 0xC396, 0xD69D, 0xC8BC, 0xD69E, 0xC397, 0xD69F, 0xC8BD, 0xD6A0, 0xC398, 0xD6A1, 0xC8BE, 0xD6A2, 0xC399, 0xD6A3, 0xC39A, + 0xD6A4, 0xC39B, 0xD6A5, 0xC39C, 0xD6A6, 0xC39D, 0xD6A7, 0xC39E, 0xD6A8, 0xC8BF, 0xD6A9, 0xC39F, 0xD6AA, 0xC3A0, 0xD6AB, 0xC441, + 0xD6AC, 0xC8C0, 0xD6AD, 0xC442, 0xD6AE, 0xC443, 0xD6AF, 0xC444, 0xD6B0, 0xC8C1, 0xD6B1, 0xC445, 0xD6B2, 0xC446, 0xD6B3, 0xC447, + 0xD6B4, 0xC448, 0xD6B5, 0xC449, 0xD6B6, 0xC44A, 0xD6B7, 0xC44B, 0xD6B8, 0xC44C, 0xD6B9, 0xC8C2, 0xD6BA, 0xC44D, 0xD6BB, 0xC8C3, + 0xD6BC, 0xC44E, 0xD6BD, 0xC44F, 0xD6BE, 0xC450, 0xD6BF, 0xC451, 0xD6C0, 0xC452, 0xD6C1, 0xC453, 0xD6C2, 0xC454, 0xD6C3, 0xC455, + 0xD6C4, 0xC8C4, 0xD6C5, 0xC8C5, 0xD6C6, 0xC456, 0xD6C7, 0xC457, 0xD6C8, 0xC8C6, 0xD6C9, 0xC458, 0xD6CA, 0xC459, 0xD6CB, 0xC45A, + 0xD6CC, 0xC8C7, 0xD6CD, 0xC461, 0xD6CE, 0xC462, 0xD6CF, 0xC463, 0xD6D0, 0xC464, 0xD6D1, 0xC8C8, 0xD6D2, 0xC465, 0xD6D3, 0xC466, + 0xD6D4, 0xC8C9, 0xD6D5, 0xC467, 0xD6D6, 0xC468, 0xD6D7, 0xC8CA, 0xD6D8, 0xC469, 0xD6D9, 0xC8CB, 0xD6DA, 0xC46A, 0xD6DB, 0xC46B, + 0xD6DC, 0xC46C, 0xD6DD, 0xC46D, 0xD6DE, 0xC46E, 0xD6DF, 0xC46F, 0xD6E0, 0xC8CC, 0xD6E1, 0xC470, 0xD6E2, 0xC471, 0xD6E3, 0xC472, + 0xD6E4, 0xC8CD, 0xD6E5, 0xC473, 0xD6E6, 0xC474, 0xD6E7, 0xC475, 0xD6E8, 0xC8CE, 0xD6E9, 0xC476, 0xD6EA, 0xC477, 0xD6EB, 0xC478, + 0xD6EC, 0xC479, 0xD6ED, 0xC47A, 0xD6EE, 0xC481, 0xD6EF, 0xC482, 0xD6F0, 0xC8CF, 0xD6F1, 0xC483, 0xD6F2, 0xC484, 0xD6F3, 0xC485, + 0xD6F4, 0xC486, 0xD6F5, 0xC8D0, 0xD6F6, 0xC487, 0xD6F7, 0xC488, 0xD6F8, 0xC489, 0xD6F9, 0xC48A, 0xD6FA, 0xC48B, 0xD6FB, 0xC48C, + 0xD6FC, 0xC8D1, 0xD6FD, 0xC8D2, 0xD6FE, 0xC48D, 0xD6FF, 0xC48E, 0xD700, 0xC8D3, 0xD701, 0xC48F, 0xD702, 0xC490, 0xD703, 0xC491, + 0xD704, 0xC8D4, 0xD705, 0xC492, 0xD706, 0xC493, 0xD707, 0xC494, 0xD708, 0xC495, 0xD709, 0xC496, 0xD70A, 0xC497, 0xD70B, 0xC498, + 0xD70C, 0xC499, 0xD70D, 0xC49A, 0xD70E, 0xC49B, 0xD70F, 0xC49C, 0xD710, 0xC49D, 0xD711, 0xC8D5, 0xD712, 0xC49E, 0xD713, 0xC49F, + 0xD714, 0xC4A0, 0xD715, 0xC541, 0xD716, 0xC542, 0xD717, 0xC543, 0xD718, 0xC8D6, 0xD719, 0xC8D7, 0xD71A, 0xC544, 0xD71B, 0xC545, + 0xD71C, 0xC8D8, 0xD71D, 0xC546, 0xD71E, 0xC547, 0xD71F, 0xC548, 0xD720, 0xC8D9, 0xD721, 0xC549, 0xD722, 0xC54A, 0xD723, 0xC54B, + 0xD724, 0xC54C, 0xD725, 0xC54D, 0xD726, 0xC54E, 0xD727, 0xC54F, 0xD728, 0xC8DA, 0xD729, 0xC8DB, 0xD72A, 0xC550, 0xD72B, 0xC8DC, + 0xD72C, 0xC551, 0xD72D, 0xC8DD, 0xD72E, 0xC552, 0xD72F, 0xC553, 0xD730, 0xC554, 0xD731, 0xC555, 0xD732, 0xC556, 0xD733, 0xC557, + 0xD734, 0xC8DE, 0xD735, 0xC8DF, 0xD736, 0xC558, 0xD737, 0xC559, 0xD738, 0xC8E0, 0xD739, 0xC55A, 0xD73A, 0xC561, 0xD73B, 0xC562, + 0xD73C, 0xC8E1, 0xD73D, 0xC563, 0xD73E, 0xC564, 0xD73F, 0xC565, 0xD740, 0xC566, 0xD741, 0xC567, 0xD742, 0xC568, 0xD743, 0xC569, + 0xD744, 0xC8E2, 0xD745, 0xC56A, 0xD746, 0xC56B, 0xD747, 0xC8E3, 0xD748, 0xC56C, 0xD749, 0xC8E4, 0xD74A, 0xC56D, 0xD74B, 0xC56E, + 0xD74C, 0xC56F, 0xD74D, 0xC570, 0xD74E, 0xC571, 0xD74F, 0xC572, 0xD750, 0xC8E5, 0xD751, 0xC8E6, 0xD752, 0xC573, 0xD753, 0xC574, + 0xD754, 0xC8E7, 0xD755, 0xC575, 0xD756, 0xC8E8, 0xD757, 0xC8E9, 0xD758, 0xC8EA, 0xD759, 0xC8EB, 0xD75A, 0xC576, 0xD75B, 0xC577, + 0xD75C, 0xC578, 0xD75D, 0xC579, 0xD75E, 0xC57A, 0xD75F, 0xC581, 0xD760, 0xC8EC, 0xD761, 0xC8ED, 0xD762, 0xC582, 0xD763, 0xC8EE, + 0xD764, 0xC583, 0xD765, 0xC8EF, 0xD766, 0xC584, 0xD767, 0xC585, 0xD768, 0xC586, 0xD769, 0xC8F0, 0xD76A, 0xC587, 0xD76B, 0xC588, + 0xD76C, 0xC8F1, 0xD76D, 0xC589, 0xD76E, 0xC58A, 0xD76F, 0xC58B, 0xD770, 0xC8F2, 0xD771, 0xC58C, 0xD772, 0xC58D, 0xD773, 0xC58E, + 0xD774, 0xC8F3, 0xD775, 0xC58F, 0xD776, 0xC590, 0xD777, 0xC591, 0xD778, 0xC592, 0xD779, 0xC593, 0xD77A, 0xC594, 0xD77B, 0xC595, + 0xD77C, 0xC8F4, 0xD77D, 0xC8F5, 0xD77E, 0xC596, 0xD77F, 0xC597, 0xD780, 0xC598, 0xD781, 0xC8F6, 0xD782, 0xC599, 0xD783, 0xC59A, + 0xD784, 0xC59B, 0xD785, 0xC59C, 0xD786, 0xC59D, 0xD787, 0xC59E, 0xD788, 0xC8F7, 0xD789, 0xC8F8, 0xD78A, 0xC59F, 0xD78B, 0xC5A0, + 0xD78C, 0xC8F9, 0xD78D, 0xC641, 0xD78E, 0xC642, 0xD78F, 0xC643, 0xD790, 0xC8FA, 0xD791, 0xC644, 0xD792, 0xC645, 0xD793, 0xC646, + 0xD794, 0xC647, 0xD795, 0xC648, 0xD796, 0xC649, 0xD797, 0xC64A, 0xD798, 0xC8FB, 0xD799, 0xC8FC, 0xD79A, 0xC64B, 0xD79B, 0xC8FD, + 0xD79C, 0xC64C, 0xD79D, 0xC8FE, 0xD79E, 0xC64D, 0xD79F, 0xC64E, 0xD7A0, 0xC64F, 0xD7A1, 0xC650, 0xD7A2, 0xC651, 0xD7A3, 0xC652, + 0xF900, 0xCBD0, 0xF901, 0xCBD6, 0xF902, 0xCBE7, 0xF903, 0xCDCF, 0xF904, 0xCDE8, 0xF905, 0xCEAD, 0xF906, 0xCFFB, 0xF907, 0xD0A2, + 0xF908, 0xD0B8, 0xF909, 0xD0D0, 0xF90A, 0xD0DD, 0xF90B, 0xD1D4, 0xF90C, 0xD1D5, 0xF90D, 0xD1D8, 0xF90E, 0xD1DB, 0xF90F, 0xD1DC, + 0xF910, 0xD1DD, 0xF911, 0xD1DE, 0xF912, 0xD1DF, 0xF913, 0xD1E0, 0xF914, 0xD1E2, 0xF915, 0xD1E3, 0xF916, 0xD1E4, 0xF917, 0xD1E5, + 0xF918, 0xD1E6, 0xF919, 0xD1E8, 0xF91A, 0xD1E9, 0xF91B, 0xD1EA, 0xF91C, 0xD1EB, 0xF91D, 0xD1ED, 0xF91E, 0xD1EF, 0xF91F, 0xD1F0, + 0xF920, 0xD1F2, 0xF921, 0xD1F6, 0xF922, 0xD1FA, 0xF923, 0xD1FC, 0xF924, 0xD1FD, 0xF925, 0xD1FE, 0xF926, 0xD2A2, 0xF927, 0xD2A3, + 0xF928, 0xD2A7, 0xF929, 0xD2A8, 0xF92A, 0xD2A9, 0xF92B, 0xD2AA, 0xF92C, 0xD2AB, 0xF92D, 0xD2AD, 0xF92E, 0xD2B2, 0xF92F, 0xD2BE, + 0xF930, 0xD2C2, 0xF931, 0xD2C3, 0xF932, 0xD2C4, 0xF933, 0xD2C6, 0xF934, 0xD2C7, 0xF935, 0xD2C8, 0xF936, 0xD2C9, 0xF937, 0xD2CA, + 0xF938, 0xD2CB, 0xF939, 0xD2CD, 0xF93A, 0xD2CE, 0xF93B, 0xD2CF, 0xF93C, 0xD2D0, 0xF93D, 0xD2D1, 0xF93E, 0xD2D2, 0xF93F, 0xD2D3, + 0xF940, 0xD2D4, 0xF941, 0xD2D5, 0xF942, 0xD2D6, 0xF943, 0xD2D7, 0xF944, 0xD2D9, 0xF945, 0xD2DA, 0xF946, 0xD2DE, 0xF947, 0xD2DF, + 0xF948, 0xD2E1, 0xF949, 0xD2E2, 0xF94A, 0xD2E4, 0xF94B, 0xD2E5, 0xF94C, 0xD2E6, 0xF94D, 0xD2E7, 0xF94E, 0xD2E8, 0xF94F, 0xD2E9, + 0xF950, 0xD2EA, 0xF951, 0xD2EB, 0xF952, 0xD2F0, 0xF953, 0xD2F1, 0xF954, 0xD2F2, 0xF955, 0xD2F3, 0xF956, 0xD2F4, 0xF957, 0xD2F5, + 0xF958, 0xD2F7, 0xF959, 0xD2F8, 0xF95A, 0xD4E6, 0xF95B, 0xD4FC, 0xF95C, 0xD5A5, 0xF95D, 0xD5AB, 0xF95E, 0xD5AE, 0xF95F, 0xD6B8, + 0xF960, 0xD6CD, 0xF961, 0xD7CB, 0xF962, 0xD7E4, 0xF963, 0xDBC5, 0xF964, 0xDBE4, 0xF965, 0xDCA5, 0xF966, 0xDDA5, 0xF967, 0xDDD5, + 0xF968, 0xDDF4, 0xF969, 0xDEFC, 0xF96A, 0xDEFE, 0xF96B, 0xDFB3, 0xF96C, 0xDFE1, 0xF96D, 0xDFE8, 0xF96E, 0xE0F1, 0xF96F, 0xE1AD, + 0xF970, 0xE1ED, 0xF971, 0xE3F5, 0xF972, 0xE4A1, 0xF973, 0xE4A9, 0xF974, 0xE5AE, 0xF975, 0xE5B1, 0xF976, 0xE5B2, 0xF977, 0xE5B9, + 0xF978, 0xE5BB, 0xF979, 0xE5BC, 0xF97A, 0xE5C4, 0xF97B, 0xE5CE, 0xF97C, 0xE5D0, 0xF97D, 0xE5D2, 0xF97E, 0xE5D6, 0xF97F, 0xE5FA, + 0xF980, 0xE5FB, 0xF981, 0xE5FC, 0xF982, 0xE5FE, 0xF983, 0xE6A1, 0xF984, 0xE6A4, 0xF985, 0xE6A7, 0xF986, 0xE6AD, 0xF987, 0xE6AF, + 0xF988, 0xE6B0, 0xF989, 0xE6B1, 0xF98A, 0xE6B3, 0xF98B, 0xE6B7, 0xF98C, 0xE6B8, 0xF98D, 0xE6BC, 0xF98E, 0xE6C4, 0xF98F, 0xE6C6, + 0xF990, 0xE6C7, 0xF991, 0xE6CA, 0xF992, 0xE6D2, 0xF993, 0xE6D6, 0xF994, 0xE6D9, 0xF995, 0xE6DC, 0xF996, 0xE6DF, 0xF997, 0xE6E1, + 0xF998, 0xE6E4, 0xF999, 0xE6E5, 0xF99A, 0xE6E6, 0xF99B, 0xE6E8, 0xF99C, 0xE6EA, 0xF99D, 0xE6EB, 0xF99E, 0xE6EC, 0xF99F, 0xE6EF, + 0xF9A0, 0xE6F1, 0xF9A1, 0xE6F2, 0xF9A2, 0xE6F5, 0xF9A3, 0xE6F6, 0xF9A4, 0xE6F7, 0xF9A5, 0xE6F9, 0xF9A6, 0xE7A1, 0xF9A7, 0xE7A6, + 0xF9A8, 0xE7A9, 0xF9A9, 0xE7AA, 0xF9AA, 0xE7AC, 0xF9AB, 0xE7AD, 0xF9AC, 0xE7B0, 0xF9AD, 0xE7BF, 0xF9AE, 0xE7C1, 0xF9AF, 0xE7C6, + 0xF9B0, 0xE7C7, 0xF9B1, 0xE7CB, 0xF9B2, 0xE7CD, 0xF9B3, 0xE7CF, 0xF9B4, 0xE7D0, 0xF9B5, 0xE7D3, 0xF9B6, 0xE7DF, 0xF9B7, 0xE7E4, + 0xF9B8, 0xE7E6, 0xF9B9, 0xE7F7, 0xF9BA, 0xE8E7, 0xF9BB, 0xE8E8, 0xF9BC, 0xE8F0, 0xF9BD, 0xE8F1, 0xF9BE, 0xE8F7, 0xF9BF, 0xE8F9, + 0xF9C0, 0xE8FB, 0xF9C1, 0xE8FE, 0xF9C2, 0xE9A7, 0xF9C3, 0xE9AC, 0xF9C4, 0xE9CC, 0xF9C5, 0xE9F7, 0xF9C6, 0xEAC1, 0xF9C7, 0xEAE5, + 0xF9C8, 0xEAF4, 0xF9C9, 0xEAF7, 0xF9CA, 0xEAFC, 0xF9CB, 0xEAFE, 0xF9CC, 0xEBA4, 0xF9CD, 0xEBA7, 0xF9CE, 0xEBA9, 0xF9CF, 0xEBAA, + 0xF9D0, 0xEBBA, 0xF9D1, 0xEBBB, 0xF9D2, 0xEBBD, 0xF9D3, 0xEBC1, 0xF9D4, 0xEBC2, 0xF9D5, 0xEBC6, 0xF9D6, 0xEBC7, 0xF9D7, 0xEBCC, + 0xF9D8, 0xEBCF, 0xF9D9, 0xEBD0, 0xF9DA, 0xEBD1, 0xF9DB, 0xEBD2, 0xF9DC, 0xEBD8, 0xF9DD, 0xECA6, 0xF9DE, 0xECA7, 0xF9DF, 0xECAA, + 0xF9E0, 0xECAF, 0xF9E1, 0xECB0, 0xF9E2, 0xECB1, 0xF9E3, 0xECB2, 0xF9E4, 0xECB5, 0xF9E5, 0xECB8, 0xF9E6, 0xECBA, 0xF9E7, 0xECC0, + 0xF9E8, 0xECC1, 0xF9E9, 0xECC5, 0xF9EA, 0xECC6, 0xF9EB, 0xECC9, 0xF9EC, 0xECCA, 0xF9ED, 0xECD5, 0xF9EE, 0xECDD, 0xF9EF, 0xECDE, + 0xF9F0, 0xECE1, 0xF9F1, 0xECE4, 0xF9F2, 0xECE7, 0xF9F3, 0xECE8, 0xF9F4, 0xECF7, 0xF9F5, 0xECF8, 0xF9F6, 0xECFA, 0xF9F7, 0xEDA1, + 0xF9F8, 0xEDA2, 0xF9F9, 0xEDA3, 0xF9FA, 0xEDEE, 0xF9FB, 0xEEDB, 0xF9FC, 0xF2BD, 0xF9FD, 0xF2FA, 0xF9FE, 0xF3B1, 0xF9FF, 0xF4A7, + 0xFA00, 0xF4EE, 0xFA01, 0xF6F4, 0xFA02, 0xF6F6, 0xFA03, 0xF7B8, 0xFA04, 0xF7C8, 0xFA05, 0xF7D3, 0xFA06, 0xF8DB, 0xFA07, 0xF8F0, + 0xFA08, 0xFAA1, 0xFA09, 0xFAA2, 0xFA0A, 0xFAE6, 0xFA0B, 0xFCA9, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA3A4, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA1AC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA2A6, 0xFFE0, 0xA1CB, 0xFFE1, 0xA1CC, 0xFFE2, 0xA1FE, 0xFFE3, 0xA3FE, 0xFFE5, 0xA1CD, 0xFFE6, 0xA3DC, + 0, 0 +}; + +static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ + 0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E, + 0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25, + 0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32, + 0x8159, 0xAC33, 0x815A, 0xAC34, 0x8161, 0xAC35, 0x8162, 0xAC36, 0x8163, 0xAC37, 0x8164, 0xAC3A, 0x8165, 0xAC3B, 0x8166, 0xAC3D, + 0x8167, 0xAC3E, 0x8168, 0xAC3F, 0x8169, 0xAC41, 0x816A, 0xAC42, 0x816B, 0xAC43, 0x816C, 0xAC44, 0x816D, 0xAC45, 0x816E, 0xAC46, + 0x816F, 0xAC47, 0x8170, 0xAC48, 0x8171, 0xAC49, 0x8172, 0xAC4A, 0x8173, 0xAC4C, 0x8174, 0xAC4E, 0x8175, 0xAC4F, 0x8176, 0xAC50, + 0x8177, 0xAC51, 0x8178, 0xAC52, 0x8179, 0xAC53, 0x817A, 0xAC55, 0x8181, 0xAC56, 0x8182, 0xAC57, 0x8183, 0xAC59, 0x8184, 0xAC5A, + 0x8185, 0xAC5B, 0x8186, 0xAC5D, 0x8187, 0xAC5E, 0x8188, 0xAC5F, 0x8189, 0xAC60, 0x818A, 0xAC61, 0x818B, 0xAC62, 0x818C, 0xAC63, + 0x818D, 0xAC64, 0x818E, 0xAC65, 0x818F, 0xAC66, 0x8190, 0xAC67, 0x8191, 0xAC68, 0x8192, 0xAC69, 0x8193, 0xAC6A, 0x8194, 0xAC6B, + 0x8195, 0xAC6C, 0x8196, 0xAC6D, 0x8197, 0xAC6E, 0x8198, 0xAC6F, 0x8199, 0xAC72, 0x819A, 0xAC73, 0x819B, 0xAC75, 0x819C, 0xAC76, + 0x819D, 0xAC79, 0x819E, 0xAC7B, 0x819F, 0xAC7C, 0x81A0, 0xAC7D, 0x81A1, 0xAC7E, 0x81A2, 0xAC7F, 0x81A3, 0xAC82, 0x81A4, 0xAC87, + 0x81A5, 0xAC88, 0x81A6, 0xAC8D, 0x81A7, 0xAC8E, 0x81A8, 0xAC8F, 0x81A9, 0xAC91, 0x81AA, 0xAC92, 0x81AB, 0xAC93, 0x81AC, 0xAC95, + 0x81AD, 0xAC96, 0x81AE, 0xAC97, 0x81AF, 0xAC98, 0x81B0, 0xAC99, 0x81B1, 0xAC9A, 0x81B2, 0xAC9B, 0x81B3, 0xAC9E, 0x81B4, 0xACA2, + 0x81B5, 0xACA3, 0x81B6, 0xACA4, 0x81B7, 0xACA5, 0x81B8, 0xACA6, 0x81B9, 0xACA7, 0x81BA, 0xACAB, 0x81BB, 0xACAD, 0x81BC, 0xACAE, + 0x81BD, 0xACB1, 0x81BE, 0xACB2, 0x81BF, 0xACB3, 0x81C0, 0xACB4, 0x81C1, 0xACB5, 0x81C2, 0xACB6, 0x81C3, 0xACB7, 0x81C4, 0xACBA, + 0x81C5, 0xACBE, 0x81C6, 0xACBF, 0x81C7, 0xACC0, 0x81C8, 0xACC2, 0x81C9, 0xACC3, 0x81CA, 0xACC5, 0x81CB, 0xACC6, 0x81CC, 0xACC7, + 0x81CD, 0xACC9, 0x81CE, 0xACCA, 0x81CF, 0xACCB, 0x81D0, 0xACCD, 0x81D1, 0xACCE, 0x81D2, 0xACCF, 0x81D3, 0xACD0, 0x81D4, 0xACD1, + 0x81D5, 0xACD2, 0x81D6, 0xACD3, 0x81D7, 0xACD4, 0x81D8, 0xACD6, 0x81D9, 0xACD8, 0x81DA, 0xACD9, 0x81DB, 0xACDA, 0x81DC, 0xACDB, + 0x81DD, 0xACDC, 0x81DE, 0xACDD, 0x81DF, 0xACDE, 0x81E0, 0xACDF, 0x81E1, 0xACE2, 0x81E2, 0xACE3, 0x81E3, 0xACE5, 0x81E4, 0xACE6, + 0x81E5, 0xACE9, 0x81E6, 0xACEB, 0x81E7, 0xACED, 0x81E8, 0xACEE, 0x81E9, 0xACF2, 0x81EA, 0xACF4, 0x81EB, 0xACF7, 0x81EC, 0xACF8, + 0x81ED, 0xACF9, 0x81EE, 0xACFA, 0x81EF, 0xACFB, 0x81F0, 0xACFE, 0x81F1, 0xACFF, 0x81F2, 0xAD01, 0x81F3, 0xAD02, 0x81F4, 0xAD03, + 0x81F5, 0xAD05, 0x81F6, 0xAD07, 0x81F7, 0xAD08, 0x81F8, 0xAD09, 0x81F9, 0xAD0A, 0x81FA, 0xAD0B, 0x81FB, 0xAD0E, 0x81FC, 0xAD10, + 0x81FD, 0xAD12, 0x81FE, 0xAD13, 0x8241, 0xAD14, 0x8242, 0xAD15, 0x8243, 0xAD16, 0x8244, 0xAD17, 0x8245, 0xAD19, 0x8246, 0xAD1A, + 0x8247, 0xAD1B, 0x8248, 0xAD1D, 0x8249, 0xAD1E, 0x824A, 0xAD1F, 0x824B, 0xAD21, 0x824C, 0xAD22, 0x824D, 0xAD23, 0x824E, 0xAD24, + 0x824F, 0xAD25, 0x8250, 0xAD26, 0x8251, 0xAD27, 0x8252, 0xAD28, 0x8253, 0xAD2A, 0x8254, 0xAD2B, 0x8255, 0xAD2E, 0x8256, 0xAD2F, + 0x8257, 0xAD30, 0x8258, 0xAD31, 0x8259, 0xAD32, 0x825A, 0xAD33, 0x8261, 0xAD36, 0x8262, 0xAD37, 0x8263, 0xAD39, 0x8264, 0xAD3A, + 0x8265, 0xAD3B, 0x8266, 0xAD3D, 0x8267, 0xAD3E, 0x8268, 0xAD3F, 0x8269, 0xAD40, 0x826A, 0xAD41, 0x826B, 0xAD42, 0x826C, 0xAD43, + 0x826D, 0xAD46, 0x826E, 0xAD48, 0x826F, 0xAD4A, 0x8270, 0xAD4B, 0x8271, 0xAD4C, 0x8272, 0xAD4D, 0x8273, 0xAD4E, 0x8274, 0xAD4F, + 0x8275, 0xAD51, 0x8276, 0xAD52, 0x8277, 0xAD53, 0x8278, 0xAD55, 0x8279, 0xAD56, 0x827A, 0xAD57, 0x8281, 0xAD59, 0x8282, 0xAD5A, + 0x8283, 0xAD5B, 0x8284, 0xAD5C, 0x8285, 0xAD5D, 0x8286, 0xAD5E, 0x8287, 0xAD5F, 0x8288, 0xAD60, 0x8289, 0xAD62, 0x828A, 0xAD64, + 0x828B, 0xAD65, 0x828C, 0xAD66, 0x828D, 0xAD67, 0x828E, 0xAD68, 0x828F, 0xAD69, 0x8290, 0xAD6A, 0x8291, 0xAD6B, 0x8292, 0xAD6E, + 0x8293, 0xAD6F, 0x8294, 0xAD71, 0x8295, 0xAD72, 0x8296, 0xAD77, 0x8297, 0xAD78, 0x8298, 0xAD79, 0x8299, 0xAD7A, 0x829A, 0xAD7E, + 0x829B, 0xAD80, 0x829C, 0xAD83, 0x829D, 0xAD84, 0x829E, 0xAD85, 0x829F, 0xAD86, 0x82A0, 0xAD87, 0x82A1, 0xAD8A, 0x82A2, 0xAD8B, + 0x82A3, 0xAD8D, 0x82A4, 0xAD8E, 0x82A5, 0xAD8F, 0x82A6, 0xAD91, 0x82A7, 0xAD92, 0x82A8, 0xAD93, 0x82A9, 0xAD94, 0x82AA, 0xAD95, + 0x82AB, 0xAD96, 0x82AC, 0xAD97, 0x82AD, 0xAD98, 0x82AE, 0xAD99, 0x82AF, 0xAD9A, 0x82B0, 0xAD9B, 0x82B1, 0xAD9E, 0x82B2, 0xAD9F, + 0x82B3, 0xADA0, 0x82B4, 0xADA1, 0x82B5, 0xADA2, 0x82B6, 0xADA3, 0x82B7, 0xADA5, 0x82B8, 0xADA6, 0x82B9, 0xADA7, 0x82BA, 0xADA8, + 0x82BB, 0xADA9, 0x82BC, 0xADAA, 0x82BD, 0xADAB, 0x82BE, 0xADAC, 0x82BF, 0xADAD, 0x82C0, 0xADAE, 0x82C1, 0xADAF, 0x82C2, 0xADB0, + 0x82C3, 0xADB1, 0x82C4, 0xADB2, 0x82C5, 0xADB3, 0x82C6, 0xADB4, 0x82C7, 0xADB5, 0x82C8, 0xADB6, 0x82C9, 0xADB8, 0x82CA, 0xADB9, + 0x82CB, 0xADBA, 0x82CC, 0xADBB, 0x82CD, 0xADBC, 0x82CE, 0xADBD, 0x82CF, 0xADBE, 0x82D0, 0xADBF, 0x82D1, 0xADC2, 0x82D2, 0xADC3, + 0x82D3, 0xADC5, 0x82D4, 0xADC6, 0x82D5, 0xADC7, 0x82D6, 0xADC9, 0x82D7, 0xADCA, 0x82D8, 0xADCB, 0x82D9, 0xADCC, 0x82DA, 0xADCD, + 0x82DB, 0xADCE, 0x82DC, 0xADCF, 0x82DD, 0xADD2, 0x82DE, 0xADD4, 0x82DF, 0xADD5, 0x82E0, 0xADD6, 0x82E1, 0xADD7, 0x82E2, 0xADD8, + 0x82E3, 0xADD9, 0x82E4, 0xADDA, 0x82E5, 0xADDB, 0x82E6, 0xADDD, 0x82E7, 0xADDE, 0x82E8, 0xADDF, 0x82E9, 0xADE1, 0x82EA, 0xADE2, + 0x82EB, 0xADE3, 0x82EC, 0xADE5, 0x82ED, 0xADE6, 0x82EE, 0xADE7, 0x82EF, 0xADE8, 0x82F0, 0xADE9, 0x82F1, 0xADEA, 0x82F2, 0xADEB, + 0x82F3, 0xADEC, 0x82F4, 0xADED, 0x82F5, 0xADEE, 0x82F6, 0xADEF, 0x82F7, 0xADF0, 0x82F8, 0xADF1, 0x82F9, 0xADF2, 0x82FA, 0xADF3, + 0x82FB, 0xADF4, 0x82FC, 0xADF5, 0x82FD, 0xADF6, 0x82FE, 0xADF7, 0x8341, 0xADFA, 0x8342, 0xADFB, 0x8343, 0xADFD, 0x8344, 0xADFE, + 0x8345, 0xAE02, 0x8346, 0xAE03, 0x8347, 0xAE04, 0x8348, 0xAE05, 0x8349, 0xAE06, 0x834A, 0xAE07, 0x834B, 0xAE0A, 0x834C, 0xAE0C, + 0x834D, 0xAE0E, 0x834E, 0xAE0F, 0x834F, 0xAE10, 0x8350, 0xAE11, 0x8351, 0xAE12, 0x8352, 0xAE13, 0x8353, 0xAE15, 0x8354, 0xAE16, + 0x8355, 0xAE17, 0x8356, 0xAE18, 0x8357, 0xAE19, 0x8358, 0xAE1A, 0x8359, 0xAE1B, 0x835A, 0xAE1C, 0x8361, 0xAE1D, 0x8362, 0xAE1E, + 0x8363, 0xAE1F, 0x8364, 0xAE20, 0x8365, 0xAE21, 0x8366, 0xAE22, 0x8367, 0xAE23, 0x8368, 0xAE24, 0x8369, 0xAE25, 0x836A, 0xAE26, + 0x836B, 0xAE27, 0x836C, 0xAE28, 0x836D, 0xAE29, 0x836E, 0xAE2A, 0x836F, 0xAE2B, 0x8370, 0xAE2C, 0x8371, 0xAE2D, 0x8372, 0xAE2E, + 0x8373, 0xAE2F, 0x8374, 0xAE32, 0x8375, 0xAE33, 0x8376, 0xAE35, 0x8377, 0xAE36, 0x8378, 0xAE39, 0x8379, 0xAE3B, 0x837A, 0xAE3C, + 0x8381, 0xAE3D, 0x8382, 0xAE3E, 0x8383, 0xAE3F, 0x8384, 0xAE42, 0x8385, 0xAE44, 0x8386, 0xAE47, 0x8387, 0xAE48, 0x8388, 0xAE49, + 0x8389, 0xAE4B, 0x838A, 0xAE4F, 0x838B, 0xAE51, 0x838C, 0xAE52, 0x838D, 0xAE53, 0x838E, 0xAE55, 0x838F, 0xAE57, 0x8390, 0xAE58, + 0x8391, 0xAE59, 0x8392, 0xAE5A, 0x8393, 0xAE5B, 0x8394, 0xAE5E, 0x8395, 0xAE62, 0x8396, 0xAE63, 0x8397, 0xAE64, 0x8398, 0xAE66, + 0x8399, 0xAE67, 0x839A, 0xAE6A, 0x839B, 0xAE6B, 0x839C, 0xAE6D, 0x839D, 0xAE6E, 0x839E, 0xAE6F, 0x839F, 0xAE71, 0x83A0, 0xAE72, + 0x83A1, 0xAE73, 0x83A2, 0xAE74, 0x83A3, 0xAE75, 0x83A4, 0xAE76, 0x83A5, 0xAE77, 0x83A6, 0xAE7A, 0x83A7, 0xAE7E, 0x83A8, 0xAE7F, + 0x83A9, 0xAE80, 0x83AA, 0xAE81, 0x83AB, 0xAE82, 0x83AC, 0xAE83, 0x83AD, 0xAE86, 0x83AE, 0xAE87, 0x83AF, 0xAE88, 0x83B0, 0xAE89, + 0x83B1, 0xAE8A, 0x83B2, 0xAE8B, 0x83B3, 0xAE8D, 0x83B4, 0xAE8E, 0x83B5, 0xAE8F, 0x83B6, 0xAE90, 0x83B7, 0xAE91, 0x83B8, 0xAE92, + 0x83B9, 0xAE93, 0x83BA, 0xAE94, 0x83BB, 0xAE95, 0x83BC, 0xAE96, 0x83BD, 0xAE97, 0x83BE, 0xAE98, 0x83BF, 0xAE99, 0x83C0, 0xAE9A, + 0x83C1, 0xAE9B, 0x83C2, 0xAE9C, 0x83C3, 0xAE9D, 0x83C4, 0xAE9E, 0x83C5, 0xAE9F, 0x83C6, 0xAEA0, 0x83C7, 0xAEA1, 0x83C8, 0xAEA2, + 0x83C9, 0xAEA3, 0x83CA, 0xAEA4, 0x83CB, 0xAEA5, 0x83CC, 0xAEA6, 0x83CD, 0xAEA7, 0x83CE, 0xAEA8, 0x83CF, 0xAEA9, 0x83D0, 0xAEAA, + 0x83D1, 0xAEAB, 0x83D2, 0xAEAC, 0x83D3, 0xAEAD, 0x83D4, 0xAEAE, 0x83D5, 0xAEAF, 0x83D6, 0xAEB0, 0x83D7, 0xAEB1, 0x83D8, 0xAEB2, + 0x83D9, 0xAEB3, 0x83DA, 0xAEB4, 0x83DB, 0xAEB5, 0x83DC, 0xAEB6, 0x83DD, 0xAEB7, 0x83DE, 0xAEB8, 0x83DF, 0xAEB9, 0x83E0, 0xAEBA, + 0x83E1, 0xAEBB, 0x83E2, 0xAEBF, 0x83E3, 0xAEC1, 0x83E4, 0xAEC2, 0x83E5, 0xAEC3, 0x83E6, 0xAEC5, 0x83E7, 0xAEC6, 0x83E8, 0xAEC7, + 0x83E9, 0xAEC8, 0x83EA, 0xAEC9, 0x83EB, 0xAECA, 0x83EC, 0xAECB, 0x83ED, 0xAECE, 0x83EE, 0xAED2, 0x83EF, 0xAED3, 0x83F0, 0xAED4, + 0x83F1, 0xAED5, 0x83F2, 0xAED6, 0x83F3, 0xAED7, 0x83F4, 0xAEDA, 0x83F5, 0xAEDB, 0x83F6, 0xAEDD, 0x83F7, 0xAEDE, 0x83F8, 0xAEDF, + 0x83F9, 0xAEE0, 0x83FA, 0xAEE1, 0x83FB, 0xAEE2, 0x83FC, 0xAEE3, 0x83FD, 0xAEE4, 0x83FE, 0xAEE5, 0x8441, 0xAEE6, 0x8442, 0xAEE7, + 0x8443, 0xAEE9, 0x8444, 0xAEEA, 0x8445, 0xAEEC, 0x8446, 0xAEEE, 0x8447, 0xAEEF, 0x8448, 0xAEF0, 0x8449, 0xAEF1, 0x844A, 0xAEF2, + 0x844B, 0xAEF3, 0x844C, 0xAEF5, 0x844D, 0xAEF6, 0x844E, 0xAEF7, 0x844F, 0xAEF9, 0x8450, 0xAEFA, 0x8451, 0xAEFB, 0x8452, 0xAEFD, + 0x8453, 0xAEFE, 0x8454, 0xAEFF, 0x8455, 0xAF00, 0x8456, 0xAF01, 0x8457, 0xAF02, 0x8458, 0xAF03, 0x8459, 0xAF04, 0x845A, 0xAF05, + 0x8461, 0xAF06, 0x8462, 0xAF09, 0x8463, 0xAF0A, 0x8464, 0xAF0B, 0x8465, 0xAF0C, 0x8466, 0xAF0E, 0x8467, 0xAF0F, 0x8468, 0xAF11, + 0x8469, 0xAF12, 0x846A, 0xAF13, 0x846B, 0xAF14, 0x846C, 0xAF15, 0x846D, 0xAF16, 0x846E, 0xAF17, 0x846F, 0xAF18, 0x8470, 0xAF19, + 0x8471, 0xAF1A, 0x8472, 0xAF1B, 0x8473, 0xAF1C, 0x8474, 0xAF1D, 0x8475, 0xAF1E, 0x8476, 0xAF1F, 0x8477, 0xAF20, 0x8478, 0xAF21, + 0x8479, 0xAF22, 0x847A, 0xAF23, 0x8481, 0xAF24, 0x8482, 0xAF25, 0x8483, 0xAF26, 0x8484, 0xAF27, 0x8485, 0xAF28, 0x8486, 0xAF29, + 0x8487, 0xAF2A, 0x8488, 0xAF2B, 0x8489, 0xAF2E, 0x848A, 0xAF2F, 0x848B, 0xAF31, 0x848C, 0xAF33, 0x848D, 0xAF35, 0x848E, 0xAF36, + 0x848F, 0xAF37, 0x8490, 0xAF38, 0x8491, 0xAF39, 0x8492, 0xAF3A, 0x8493, 0xAF3B, 0x8494, 0xAF3E, 0x8495, 0xAF40, 0x8496, 0xAF44, + 0x8497, 0xAF45, 0x8498, 0xAF46, 0x8499, 0xAF47, 0x849A, 0xAF4A, 0x849B, 0xAF4B, 0x849C, 0xAF4C, 0x849D, 0xAF4D, 0x849E, 0xAF4E, + 0x849F, 0xAF4F, 0x84A0, 0xAF51, 0x84A1, 0xAF52, 0x84A2, 0xAF53, 0x84A3, 0xAF54, 0x84A4, 0xAF55, 0x84A5, 0xAF56, 0x84A6, 0xAF57, + 0x84A7, 0xAF58, 0x84A8, 0xAF59, 0x84A9, 0xAF5A, 0x84AA, 0xAF5B, 0x84AB, 0xAF5E, 0x84AC, 0xAF5F, 0x84AD, 0xAF60, 0x84AE, 0xAF61, + 0x84AF, 0xAF62, 0x84B0, 0xAF63, 0x84B1, 0xAF66, 0x84B2, 0xAF67, 0x84B3, 0xAF68, 0x84B4, 0xAF69, 0x84B5, 0xAF6A, 0x84B6, 0xAF6B, + 0x84B7, 0xAF6C, 0x84B8, 0xAF6D, 0x84B9, 0xAF6E, 0x84BA, 0xAF6F, 0x84BB, 0xAF70, 0x84BC, 0xAF71, 0x84BD, 0xAF72, 0x84BE, 0xAF73, + 0x84BF, 0xAF74, 0x84C0, 0xAF75, 0x84C1, 0xAF76, 0x84C2, 0xAF77, 0x84C3, 0xAF78, 0x84C4, 0xAF7A, 0x84C5, 0xAF7B, 0x84C6, 0xAF7C, + 0x84C7, 0xAF7D, 0x84C8, 0xAF7E, 0x84C9, 0xAF7F, 0x84CA, 0xAF81, 0x84CB, 0xAF82, 0x84CC, 0xAF83, 0x84CD, 0xAF85, 0x84CE, 0xAF86, + 0x84CF, 0xAF87, 0x84D0, 0xAF89, 0x84D1, 0xAF8A, 0x84D2, 0xAF8B, 0x84D3, 0xAF8C, 0x84D4, 0xAF8D, 0x84D5, 0xAF8E, 0x84D6, 0xAF8F, + 0x84D7, 0xAF92, 0x84D8, 0xAF93, 0x84D9, 0xAF94, 0x84DA, 0xAF96, 0x84DB, 0xAF97, 0x84DC, 0xAF98, 0x84DD, 0xAF99, 0x84DE, 0xAF9A, + 0x84DF, 0xAF9B, 0x84E0, 0xAF9D, 0x84E1, 0xAF9E, 0x84E2, 0xAF9F, 0x84E3, 0xAFA0, 0x84E4, 0xAFA1, 0x84E5, 0xAFA2, 0x84E6, 0xAFA3, + 0x84E7, 0xAFA4, 0x84E8, 0xAFA5, 0x84E9, 0xAFA6, 0x84EA, 0xAFA7, 0x84EB, 0xAFA8, 0x84EC, 0xAFA9, 0x84ED, 0xAFAA, 0x84EE, 0xAFAB, + 0x84EF, 0xAFAC, 0x84F0, 0xAFAD, 0x84F1, 0xAFAE, 0x84F2, 0xAFAF, 0x84F3, 0xAFB0, 0x84F4, 0xAFB1, 0x84F5, 0xAFB2, 0x84F6, 0xAFB3, + 0x84F7, 0xAFB4, 0x84F8, 0xAFB5, 0x84F9, 0xAFB6, 0x84FA, 0xAFB7, 0x84FB, 0xAFBA, 0x84FC, 0xAFBB, 0x84FD, 0xAFBD, 0x84FE, 0xAFBE, + 0x8541, 0xAFBF, 0x8542, 0xAFC1, 0x8543, 0xAFC2, 0x8544, 0xAFC3, 0x8545, 0xAFC4, 0x8546, 0xAFC5, 0x8547, 0xAFC6, 0x8548, 0xAFCA, + 0x8549, 0xAFCC, 0x854A, 0xAFCF, 0x854B, 0xAFD0, 0x854C, 0xAFD1, 0x854D, 0xAFD2, 0x854E, 0xAFD3, 0x854F, 0xAFD5, 0x8550, 0xAFD6, + 0x8551, 0xAFD7, 0x8552, 0xAFD8, 0x8553, 0xAFD9, 0x8554, 0xAFDA, 0x8555, 0xAFDB, 0x8556, 0xAFDD, 0x8557, 0xAFDE, 0x8558, 0xAFDF, + 0x8559, 0xAFE0, 0x855A, 0xAFE1, 0x8561, 0xAFE2, 0x8562, 0xAFE3, 0x8563, 0xAFE4, 0x8564, 0xAFE5, 0x8565, 0xAFE6, 0x8566, 0xAFE7, + 0x8567, 0xAFEA, 0x8568, 0xAFEB, 0x8569, 0xAFEC, 0x856A, 0xAFED, 0x856B, 0xAFEE, 0x856C, 0xAFEF, 0x856D, 0xAFF2, 0x856E, 0xAFF3, + 0x856F, 0xAFF5, 0x8570, 0xAFF6, 0x8571, 0xAFF7, 0x8572, 0xAFF9, 0x8573, 0xAFFA, 0x8574, 0xAFFB, 0x8575, 0xAFFC, 0x8576, 0xAFFD, + 0x8577, 0xAFFE, 0x8578, 0xAFFF, 0x8579, 0xB002, 0x857A, 0xB003, 0x8581, 0xB005, 0x8582, 0xB006, 0x8583, 0xB007, 0x8584, 0xB008, + 0x8585, 0xB009, 0x8586, 0xB00A, 0x8587, 0xB00B, 0x8588, 0xB00D, 0x8589, 0xB00E, 0x858A, 0xB00F, 0x858B, 0xB011, 0x858C, 0xB012, + 0x858D, 0xB013, 0x858E, 0xB015, 0x858F, 0xB016, 0x8590, 0xB017, 0x8591, 0xB018, 0x8592, 0xB019, 0x8593, 0xB01A, 0x8594, 0xB01B, + 0x8595, 0xB01E, 0x8596, 0xB01F, 0x8597, 0xB020, 0x8598, 0xB021, 0x8599, 0xB022, 0x859A, 0xB023, 0x859B, 0xB024, 0x859C, 0xB025, + 0x859D, 0xB026, 0x859E, 0xB027, 0x859F, 0xB029, 0x85A0, 0xB02A, 0x85A1, 0xB02B, 0x85A2, 0xB02C, 0x85A3, 0xB02D, 0x85A4, 0xB02E, + 0x85A5, 0xB02F, 0x85A6, 0xB030, 0x85A7, 0xB031, 0x85A8, 0xB032, 0x85A9, 0xB033, 0x85AA, 0xB034, 0x85AB, 0xB035, 0x85AC, 0xB036, + 0x85AD, 0xB037, 0x85AE, 0xB038, 0x85AF, 0xB039, 0x85B0, 0xB03A, 0x85B1, 0xB03B, 0x85B2, 0xB03C, 0x85B3, 0xB03D, 0x85B4, 0xB03E, + 0x85B5, 0xB03F, 0x85B6, 0xB040, 0x85B7, 0xB041, 0x85B8, 0xB042, 0x85B9, 0xB043, 0x85BA, 0xB046, 0x85BB, 0xB047, 0x85BC, 0xB049, + 0x85BD, 0xB04B, 0x85BE, 0xB04D, 0x85BF, 0xB04F, 0x85C0, 0xB050, 0x85C1, 0xB051, 0x85C2, 0xB052, 0x85C3, 0xB056, 0x85C4, 0xB058, + 0x85C5, 0xB05A, 0x85C6, 0xB05B, 0x85C7, 0xB05C, 0x85C8, 0xB05E, 0x85C9, 0xB05F, 0x85CA, 0xB060, 0x85CB, 0xB061, 0x85CC, 0xB062, + 0x85CD, 0xB063, 0x85CE, 0xB064, 0x85CF, 0xB065, 0x85D0, 0xB066, 0x85D1, 0xB067, 0x85D2, 0xB068, 0x85D3, 0xB069, 0x85D4, 0xB06A, + 0x85D5, 0xB06B, 0x85D6, 0xB06C, 0x85D7, 0xB06D, 0x85D8, 0xB06E, 0x85D9, 0xB06F, 0x85DA, 0xB070, 0x85DB, 0xB071, 0x85DC, 0xB072, + 0x85DD, 0xB073, 0x85DE, 0xB074, 0x85DF, 0xB075, 0x85E0, 0xB076, 0x85E1, 0xB077, 0x85E2, 0xB078, 0x85E3, 0xB079, 0x85E4, 0xB07A, + 0x85E5, 0xB07B, 0x85E6, 0xB07E, 0x85E7, 0xB07F, 0x85E8, 0xB081, 0x85E9, 0xB082, 0x85EA, 0xB083, 0x85EB, 0xB085, 0x85EC, 0xB086, + 0x85ED, 0xB087, 0x85EE, 0xB088, 0x85EF, 0xB089, 0x85F0, 0xB08A, 0x85F1, 0xB08B, 0x85F2, 0xB08E, 0x85F3, 0xB090, 0x85F4, 0xB092, + 0x85F5, 0xB093, 0x85F6, 0xB094, 0x85F7, 0xB095, 0x85F8, 0xB096, 0x85F9, 0xB097, 0x85FA, 0xB09B, 0x85FB, 0xB09D, 0x85FC, 0xB09E, + 0x85FD, 0xB0A3, 0x85FE, 0xB0A4, 0x8641, 0xB0A5, 0x8642, 0xB0A6, 0x8643, 0xB0A7, 0x8644, 0xB0AA, 0x8645, 0xB0B0, 0x8646, 0xB0B2, + 0x8647, 0xB0B6, 0x8648, 0xB0B7, 0x8649, 0xB0B9, 0x864A, 0xB0BA, 0x864B, 0xB0BB, 0x864C, 0xB0BD, 0x864D, 0xB0BE, 0x864E, 0xB0BF, + 0x864F, 0xB0C0, 0x8650, 0xB0C1, 0x8651, 0xB0C2, 0x8652, 0xB0C3, 0x8653, 0xB0C6, 0x8654, 0xB0CA, 0x8655, 0xB0CB, 0x8656, 0xB0CC, + 0x8657, 0xB0CD, 0x8658, 0xB0CE, 0x8659, 0xB0CF, 0x865A, 0xB0D2, 0x8661, 0xB0D3, 0x8662, 0xB0D5, 0x8663, 0xB0D6, 0x8664, 0xB0D7, + 0x8665, 0xB0D9, 0x8666, 0xB0DA, 0x8667, 0xB0DB, 0x8668, 0xB0DC, 0x8669, 0xB0DD, 0x866A, 0xB0DE, 0x866B, 0xB0DF, 0x866C, 0xB0E1, + 0x866D, 0xB0E2, 0x866E, 0xB0E3, 0x866F, 0xB0E4, 0x8670, 0xB0E6, 0x8671, 0xB0E7, 0x8672, 0xB0E8, 0x8673, 0xB0E9, 0x8674, 0xB0EA, + 0x8675, 0xB0EB, 0x8676, 0xB0EC, 0x8677, 0xB0ED, 0x8678, 0xB0EE, 0x8679, 0xB0EF, 0x867A, 0xB0F0, 0x8681, 0xB0F1, 0x8682, 0xB0F2, + 0x8683, 0xB0F3, 0x8684, 0xB0F4, 0x8685, 0xB0F5, 0x8686, 0xB0F6, 0x8687, 0xB0F7, 0x8688, 0xB0F8, 0x8689, 0xB0F9, 0x868A, 0xB0FA, + 0x868B, 0xB0FB, 0x868C, 0xB0FC, 0x868D, 0xB0FD, 0x868E, 0xB0FE, 0x868F, 0xB0FF, 0x8690, 0xB100, 0x8691, 0xB101, 0x8692, 0xB102, + 0x8693, 0xB103, 0x8694, 0xB104, 0x8695, 0xB105, 0x8696, 0xB106, 0x8697, 0xB107, 0x8698, 0xB10A, 0x8699, 0xB10D, 0x869A, 0xB10E, + 0x869B, 0xB10F, 0x869C, 0xB111, 0x869D, 0xB114, 0x869E, 0xB115, 0x869F, 0xB116, 0x86A0, 0xB117, 0x86A1, 0xB11A, 0x86A2, 0xB11E, + 0x86A3, 0xB11F, 0x86A4, 0xB120, 0x86A5, 0xB121, 0x86A6, 0xB122, 0x86A7, 0xB126, 0x86A8, 0xB127, 0x86A9, 0xB129, 0x86AA, 0xB12A, + 0x86AB, 0xB12B, 0x86AC, 0xB12D, 0x86AD, 0xB12E, 0x86AE, 0xB12F, 0x86AF, 0xB130, 0x86B0, 0xB131, 0x86B1, 0xB132, 0x86B2, 0xB133, + 0x86B3, 0xB136, 0x86B4, 0xB13A, 0x86B5, 0xB13B, 0x86B6, 0xB13C, 0x86B7, 0xB13D, 0x86B8, 0xB13E, 0x86B9, 0xB13F, 0x86BA, 0xB142, + 0x86BB, 0xB143, 0x86BC, 0xB145, 0x86BD, 0xB146, 0x86BE, 0xB147, 0x86BF, 0xB149, 0x86C0, 0xB14A, 0x86C1, 0xB14B, 0x86C2, 0xB14C, + 0x86C3, 0xB14D, 0x86C4, 0xB14E, 0x86C5, 0xB14F, 0x86C6, 0xB152, 0x86C7, 0xB153, 0x86C8, 0xB156, 0x86C9, 0xB157, 0x86CA, 0xB159, + 0x86CB, 0xB15A, 0x86CC, 0xB15B, 0x86CD, 0xB15D, 0x86CE, 0xB15E, 0x86CF, 0xB15F, 0x86D0, 0xB161, 0x86D1, 0xB162, 0x86D2, 0xB163, + 0x86D3, 0xB164, 0x86D4, 0xB165, 0x86D5, 0xB166, 0x86D6, 0xB167, 0x86D7, 0xB168, 0x86D8, 0xB169, 0x86D9, 0xB16A, 0x86DA, 0xB16B, + 0x86DB, 0xB16C, 0x86DC, 0xB16D, 0x86DD, 0xB16E, 0x86DE, 0xB16F, 0x86DF, 0xB170, 0x86E0, 0xB171, 0x86E1, 0xB172, 0x86E2, 0xB173, + 0x86E3, 0xB174, 0x86E4, 0xB175, 0x86E5, 0xB176, 0x86E6, 0xB177, 0x86E7, 0xB17A, 0x86E8, 0xB17B, 0x86E9, 0xB17D, 0x86EA, 0xB17E, + 0x86EB, 0xB17F, 0x86EC, 0xB181, 0x86ED, 0xB183, 0x86EE, 0xB184, 0x86EF, 0xB185, 0x86F0, 0xB186, 0x86F1, 0xB187, 0x86F2, 0xB18A, + 0x86F3, 0xB18C, 0x86F4, 0xB18E, 0x86F5, 0xB18F, 0x86F6, 0xB190, 0x86F7, 0xB191, 0x86F8, 0xB195, 0x86F9, 0xB196, 0x86FA, 0xB197, + 0x86FB, 0xB199, 0x86FC, 0xB19A, 0x86FD, 0xB19B, 0x86FE, 0xB19D, 0x8741, 0xB19E, 0x8742, 0xB19F, 0x8743, 0xB1A0, 0x8744, 0xB1A1, + 0x8745, 0xB1A2, 0x8746, 0xB1A3, 0x8747, 0xB1A4, 0x8748, 0xB1A5, 0x8749, 0xB1A6, 0x874A, 0xB1A7, 0x874B, 0xB1A9, 0x874C, 0xB1AA, + 0x874D, 0xB1AB, 0x874E, 0xB1AC, 0x874F, 0xB1AD, 0x8750, 0xB1AE, 0x8751, 0xB1AF, 0x8752, 0xB1B0, 0x8753, 0xB1B1, 0x8754, 0xB1B2, + 0x8755, 0xB1B3, 0x8756, 0xB1B4, 0x8757, 0xB1B5, 0x8758, 0xB1B6, 0x8759, 0xB1B7, 0x875A, 0xB1B8, 0x8761, 0xB1B9, 0x8762, 0xB1BA, + 0x8763, 0xB1BB, 0x8764, 0xB1BC, 0x8765, 0xB1BD, 0x8766, 0xB1BE, 0x8767, 0xB1BF, 0x8768, 0xB1C0, 0x8769, 0xB1C1, 0x876A, 0xB1C2, + 0x876B, 0xB1C3, 0x876C, 0xB1C4, 0x876D, 0xB1C5, 0x876E, 0xB1C6, 0x876F, 0xB1C7, 0x8770, 0xB1C8, 0x8771, 0xB1C9, 0x8772, 0xB1CA, + 0x8773, 0xB1CB, 0x8774, 0xB1CD, 0x8775, 0xB1CE, 0x8776, 0xB1CF, 0x8777, 0xB1D1, 0x8778, 0xB1D2, 0x8779, 0xB1D3, 0x877A, 0xB1D5, + 0x8781, 0xB1D6, 0x8782, 0xB1D7, 0x8783, 0xB1D8, 0x8784, 0xB1D9, 0x8785, 0xB1DA, 0x8786, 0xB1DB, 0x8787, 0xB1DE, 0x8788, 0xB1E0, + 0x8789, 0xB1E1, 0x878A, 0xB1E2, 0x878B, 0xB1E3, 0x878C, 0xB1E4, 0x878D, 0xB1E5, 0x878E, 0xB1E6, 0x878F, 0xB1E7, 0x8790, 0xB1EA, + 0x8791, 0xB1EB, 0x8792, 0xB1ED, 0x8793, 0xB1EE, 0x8794, 0xB1EF, 0x8795, 0xB1F1, 0x8796, 0xB1F2, 0x8797, 0xB1F3, 0x8798, 0xB1F4, + 0x8799, 0xB1F5, 0x879A, 0xB1F6, 0x879B, 0xB1F7, 0x879C, 0xB1F8, 0x879D, 0xB1FA, 0x879E, 0xB1FC, 0x879F, 0xB1FE, 0x87A0, 0xB1FF, + 0x87A1, 0xB200, 0x87A2, 0xB201, 0x87A3, 0xB202, 0x87A4, 0xB203, 0x87A5, 0xB206, 0x87A6, 0xB207, 0x87A7, 0xB209, 0x87A8, 0xB20A, + 0x87A9, 0xB20D, 0x87AA, 0xB20E, 0x87AB, 0xB20F, 0x87AC, 0xB210, 0x87AD, 0xB211, 0x87AE, 0xB212, 0x87AF, 0xB213, 0x87B0, 0xB216, + 0x87B1, 0xB218, 0x87B2, 0xB21A, 0x87B3, 0xB21B, 0x87B4, 0xB21C, 0x87B5, 0xB21D, 0x87B6, 0xB21E, 0x87B7, 0xB21F, 0x87B8, 0xB221, + 0x87B9, 0xB222, 0x87BA, 0xB223, 0x87BB, 0xB224, 0x87BC, 0xB225, 0x87BD, 0xB226, 0x87BE, 0xB227, 0x87BF, 0xB228, 0x87C0, 0xB229, + 0x87C1, 0xB22A, 0x87C2, 0xB22B, 0x87C3, 0xB22C, 0x87C4, 0xB22D, 0x87C5, 0xB22E, 0x87C6, 0xB22F, 0x87C7, 0xB230, 0x87C8, 0xB231, + 0x87C9, 0xB232, 0x87CA, 0xB233, 0x87CB, 0xB235, 0x87CC, 0xB236, 0x87CD, 0xB237, 0x87CE, 0xB238, 0x87CF, 0xB239, 0x87D0, 0xB23A, + 0x87D1, 0xB23B, 0x87D2, 0xB23D, 0x87D3, 0xB23E, 0x87D4, 0xB23F, 0x87D5, 0xB240, 0x87D6, 0xB241, 0x87D7, 0xB242, 0x87D8, 0xB243, + 0x87D9, 0xB244, 0x87DA, 0xB245, 0x87DB, 0xB246, 0x87DC, 0xB247, 0x87DD, 0xB248, 0x87DE, 0xB249, 0x87DF, 0xB24A, 0x87E0, 0xB24B, + 0x87E1, 0xB24C, 0x87E2, 0xB24D, 0x87E3, 0xB24E, 0x87E4, 0xB24F, 0x87E5, 0xB250, 0x87E6, 0xB251, 0x87E7, 0xB252, 0x87E8, 0xB253, + 0x87E9, 0xB254, 0x87EA, 0xB255, 0x87EB, 0xB256, 0x87EC, 0xB257, 0x87ED, 0xB259, 0x87EE, 0xB25A, 0x87EF, 0xB25B, 0x87F0, 0xB25D, + 0x87F1, 0xB25E, 0x87F2, 0xB25F, 0x87F3, 0xB261, 0x87F4, 0xB262, 0x87F5, 0xB263, 0x87F6, 0xB264, 0x87F7, 0xB265, 0x87F8, 0xB266, + 0x87F9, 0xB267, 0x87FA, 0xB26A, 0x87FB, 0xB26B, 0x87FC, 0xB26C, 0x87FD, 0xB26D, 0x87FE, 0xB26E, 0x8841, 0xB26F, 0x8842, 0xB270, + 0x8843, 0xB271, 0x8844, 0xB272, 0x8845, 0xB273, 0x8846, 0xB276, 0x8847, 0xB277, 0x8848, 0xB278, 0x8849, 0xB279, 0x884A, 0xB27A, + 0x884B, 0xB27B, 0x884C, 0xB27D, 0x884D, 0xB27E, 0x884E, 0xB27F, 0x884F, 0xB280, 0x8850, 0xB281, 0x8851, 0xB282, 0x8852, 0xB283, + 0x8853, 0xB286, 0x8854, 0xB287, 0x8855, 0xB288, 0x8856, 0xB28A, 0x8857, 0xB28B, 0x8858, 0xB28C, 0x8859, 0xB28D, 0x885A, 0xB28E, + 0x8861, 0xB28F, 0x8862, 0xB292, 0x8863, 0xB293, 0x8864, 0xB295, 0x8865, 0xB296, 0x8866, 0xB297, 0x8867, 0xB29B, 0x8868, 0xB29C, + 0x8869, 0xB29D, 0x886A, 0xB29E, 0x886B, 0xB29F, 0x886C, 0xB2A2, 0x886D, 0xB2A4, 0x886E, 0xB2A7, 0x886F, 0xB2A8, 0x8870, 0xB2A9, + 0x8871, 0xB2AB, 0x8872, 0xB2AD, 0x8873, 0xB2AE, 0x8874, 0xB2AF, 0x8875, 0xB2B1, 0x8876, 0xB2B2, 0x8877, 0xB2B3, 0x8878, 0xB2B5, + 0x8879, 0xB2B6, 0x887A, 0xB2B7, 0x8881, 0xB2B8, 0x8882, 0xB2B9, 0x8883, 0xB2BA, 0x8884, 0xB2BB, 0x8885, 0xB2BC, 0x8886, 0xB2BD, + 0x8887, 0xB2BE, 0x8888, 0xB2BF, 0x8889, 0xB2C0, 0x888A, 0xB2C1, 0x888B, 0xB2C2, 0x888C, 0xB2C3, 0x888D, 0xB2C4, 0x888E, 0xB2C5, + 0x888F, 0xB2C6, 0x8890, 0xB2C7, 0x8891, 0xB2CA, 0x8892, 0xB2CB, 0x8893, 0xB2CD, 0x8894, 0xB2CE, 0x8895, 0xB2CF, 0x8896, 0xB2D1, + 0x8897, 0xB2D3, 0x8898, 0xB2D4, 0x8899, 0xB2D5, 0x889A, 0xB2D6, 0x889B, 0xB2D7, 0x889C, 0xB2DA, 0x889D, 0xB2DC, 0x889E, 0xB2DE, + 0x889F, 0xB2DF, 0x88A0, 0xB2E0, 0x88A1, 0xB2E1, 0x88A2, 0xB2E3, 0x88A3, 0xB2E7, 0x88A4, 0xB2E9, 0x88A5, 0xB2EA, 0x88A6, 0xB2F0, + 0x88A7, 0xB2F1, 0x88A8, 0xB2F2, 0x88A9, 0xB2F6, 0x88AA, 0xB2FC, 0x88AB, 0xB2FD, 0x88AC, 0xB2FE, 0x88AD, 0xB302, 0x88AE, 0xB303, + 0x88AF, 0xB305, 0x88B0, 0xB306, 0x88B1, 0xB307, 0x88B2, 0xB309, 0x88B3, 0xB30A, 0x88B4, 0xB30B, 0x88B5, 0xB30C, 0x88B6, 0xB30D, + 0x88B7, 0xB30E, 0x88B8, 0xB30F, 0x88B9, 0xB312, 0x88BA, 0xB316, 0x88BB, 0xB317, 0x88BC, 0xB318, 0x88BD, 0xB319, 0x88BE, 0xB31A, + 0x88BF, 0xB31B, 0x88C0, 0xB31D, 0x88C1, 0xB31E, 0x88C2, 0xB31F, 0x88C3, 0xB320, 0x88C4, 0xB321, 0x88C5, 0xB322, 0x88C6, 0xB323, + 0x88C7, 0xB324, 0x88C8, 0xB325, 0x88C9, 0xB326, 0x88CA, 0xB327, 0x88CB, 0xB328, 0x88CC, 0xB329, 0x88CD, 0xB32A, 0x88CE, 0xB32B, + 0x88CF, 0xB32C, 0x88D0, 0xB32D, 0x88D1, 0xB32E, 0x88D2, 0xB32F, 0x88D3, 0xB330, 0x88D4, 0xB331, 0x88D5, 0xB332, 0x88D6, 0xB333, + 0x88D7, 0xB334, 0x88D8, 0xB335, 0x88D9, 0xB336, 0x88DA, 0xB337, 0x88DB, 0xB338, 0x88DC, 0xB339, 0x88DD, 0xB33A, 0x88DE, 0xB33B, + 0x88DF, 0xB33C, 0x88E0, 0xB33D, 0x88E1, 0xB33E, 0x88E2, 0xB33F, 0x88E3, 0xB340, 0x88E4, 0xB341, 0x88E5, 0xB342, 0x88E6, 0xB343, + 0x88E7, 0xB344, 0x88E8, 0xB345, 0x88E9, 0xB346, 0x88EA, 0xB347, 0x88EB, 0xB348, 0x88EC, 0xB349, 0x88ED, 0xB34A, 0x88EE, 0xB34B, + 0x88EF, 0xB34C, 0x88F0, 0xB34D, 0x88F1, 0xB34E, 0x88F2, 0xB34F, 0x88F3, 0xB350, 0x88F4, 0xB351, 0x88F5, 0xB352, 0x88F6, 0xB353, + 0x88F7, 0xB357, 0x88F8, 0xB359, 0x88F9, 0xB35A, 0x88FA, 0xB35D, 0x88FB, 0xB360, 0x88FC, 0xB361, 0x88FD, 0xB362, 0x88FE, 0xB363, + 0x8941, 0xB366, 0x8942, 0xB368, 0x8943, 0xB36A, 0x8944, 0xB36C, 0x8945, 0xB36D, 0x8946, 0xB36F, 0x8947, 0xB372, 0x8948, 0xB373, + 0x8949, 0xB375, 0x894A, 0xB376, 0x894B, 0xB377, 0x894C, 0xB379, 0x894D, 0xB37A, 0x894E, 0xB37B, 0x894F, 0xB37C, 0x8950, 0xB37D, + 0x8951, 0xB37E, 0x8952, 0xB37F, 0x8953, 0xB382, 0x8954, 0xB386, 0x8955, 0xB387, 0x8956, 0xB388, 0x8957, 0xB389, 0x8958, 0xB38A, + 0x8959, 0xB38B, 0x895A, 0xB38D, 0x8961, 0xB38E, 0x8962, 0xB38F, 0x8963, 0xB391, 0x8964, 0xB392, 0x8965, 0xB393, 0x8966, 0xB395, + 0x8967, 0xB396, 0x8968, 0xB397, 0x8969, 0xB398, 0x896A, 0xB399, 0x896B, 0xB39A, 0x896C, 0xB39B, 0x896D, 0xB39C, 0x896E, 0xB39D, + 0x896F, 0xB39E, 0x8970, 0xB39F, 0x8971, 0xB3A2, 0x8972, 0xB3A3, 0x8973, 0xB3A4, 0x8974, 0xB3A5, 0x8975, 0xB3A6, 0x8976, 0xB3A7, + 0x8977, 0xB3A9, 0x8978, 0xB3AA, 0x8979, 0xB3AB, 0x897A, 0xB3AD, 0x8981, 0xB3AE, 0x8982, 0xB3AF, 0x8983, 0xB3B0, 0x8984, 0xB3B1, + 0x8985, 0xB3B2, 0x8986, 0xB3B3, 0x8987, 0xB3B4, 0x8988, 0xB3B5, 0x8989, 0xB3B6, 0x898A, 0xB3B7, 0x898B, 0xB3B8, 0x898C, 0xB3B9, + 0x898D, 0xB3BA, 0x898E, 0xB3BB, 0x898F, 0xB3BC, 0x8990, 0xB3BD, 0x8991, 0xB3BE, 0x8992, 0xB3BF, 0x8993, 0xB3C0, 0x8994, 0xB3C1, + 0x8995, 0xB3C2, 0x8996, 0xB3C3, 0x8997, 0xB3C6, 0x8998, 0xB3C7, 0x8999, 0xB3C9, 0x899A, 0xB3CA, 0x899B, 0xB3CD, 0x899C, 0xB3CF, + 0x899D, 0xB3D1, 0x899E, 0xB3D2, 0x899F, 0xB3D3, 0x89A0, 0xB3D6, 0x89A1, 0xB3D8, 0x89A2, 0xB3DA, 0x89A3, 0xB3DC, 0x89A4, 0xB3DE, + 0x89A5, 0xB3DF, 0x89A6, 0xB3E1, 0x89A7, 0xB3E2, 0x89A8, 0xB3E3, 0x89A9, 0xB3E5, 0x89AA, 0xB3E6, 0x89AB, 0xB3E7, 0x89AC, 0xB3E9, + 0x89AD, 0xB3EA, 0x89AE, 0xB3EB, 0x89AF, 0xB3EC, 0x89B0, 0xB3ED, 0x89B1, 0xB3EE, 0x89B2, 0xB3EF, 0x89B3, 0xB3F0, 0x89B4, 0xB3F1, + 0x89B5, 0xB3F2, 0x89B6, 0xB3F3, 0x89B7, 0xB3F4, 0x89B8, 0xB3F5, 0x89B9, 0xB3F6, 0x89BA, 0xB3F7, 0x89BB, 0xB3F8, 0x89BC, 0xB3F9, + 0x89BD, 0xB3FA, 0x89BE, 0xB3FB, 0x89BF, 0xB3FD, 0x89C0, 0xB3FE, 0x89C1, 0xB3FF, 0x89C2, 0xB400, 0x89C3, 0xB401, 0x89C4, 0xB402, + 0x89C5, 0xB403, 0x89C6, 0xB404, 0x89C7, 0xB405, 0x89C8, 0xB406, 0x89C9, 0xB407, 0x89CA, 0xB408, 0x89CB, 0xB409, 0x89CC, 0xB40A, + 0x89CD, 0xB40B, 0x89CE, 0xB40C, 0x89CF, 0xB40D, 0x89D0, 0xB40E, 0x89D1, 0xB40F, 0x89D2, 0xB411, 0x89D3, 0xB412, 0x89D4, 0xB413, + 0x89D5, 0xB414, 0x89D6, 0xB415, 0x89D7, 0xB416, 0x89D8, 0xB417, 0x89D9, 0xB419, 0x89DA, 0xB41A, 0x89DB, 0xB41B, 0x89DC, 0xB41D, + 0x89DD, 0xB41E, 0x89DE, 0xB41F, 0x89DF, 0xB421, 0x89E0, 0xB422, 0x89E1, 0xB423, 0x89E2, 0xB424, 0x89E3, 0xB425, 0x89E4, 0xB426, + 0x89E5, 0xB427, 0x89E6, 0xB42A, 0x89E7, 0xB42C, 0x89E8, 0xB42D, 0x89E9, 0xB42E, 0x89EA, 0xB42F, 0x89EB, 0xB430, 0x89EC, 0xB431, + 0x89ED, 0xB432, 0x89EE, 0xB433, 0x89EF, 0xB435, 0x89F0, 0xB436, 0x89F1, 0xB437, 0x89F2, 0xB438, 0x89F3, 0xB439, 0x89F4, 0xB43A, + 0x89F5, 0xB43B, 0x89F6, 0xB43C, 0x89F7, 0xB43D, 0x89F8, 0xB43E, 0x89F9, 0xB43F, 0x89FA, 0xB440, 0x89FB, 0xB441, 0x89FC, 0xB442, + 0x89FD, 0xB443, 0x89FE, 0xB444, 0x8A41, 0xB445, 0x8A42, 0xB446, 0x8A43, 0xB447, 0x8A44, 0xB448, 0x8A45, 0xB449, 0x8A46, 0xB44A, + 0x8A47, 0xB44B, 0x8A48, 0xB44C, 0x8A49, 0xB44D, 0x8A4A, 0xB44E, 0x8A4B, 0xB44F, 0x8A4C, 0xB452, 0x8A4D, 0xB453, 0x8A4E, 0xB455, + 0x8A4F, 0xB456, 0x8A50, 0xB457, 0x8A51, 0xB459, 0x8A52, 0xB45A, 0x8A53, 0xB45B, 0x8A54, 0xB45C, 0x8A55, 0xB45D, 0x8A56, 0xB45E, + 0x8A57, 0xB45F, 0x8A58, 0xB462, 0x8A59, 0xB464, 0x8A5A, 0xB466, 0x8A61, 0xB467, 0x8A62, 0xB468, 0x8A63, 0xB469, 0x8A64, 0xB46A, + 0x8A65, 0xB46B, 0x8A66, 0xB46D, 0x8A67, 0xB46E, 0x8A68, 0xB46F, 0x8A69, 0xB470, 0x8A6A, 0xB471, 0x8A6B, 0xB472, 0x8A6C, 0xB473, + 0x8A6D, 0xB474, 0x8A6E, 0xB475, 0x8A6F, 0xB476, 0x8A70, 0xB477, 0x8A71, 0xB478, 0x8A72, 0xB479, 0x8A73, 0xB47A, 0x8A74, 0xB47B, + 0x8A75, 0xB47C, 0x8A76, 0xB47D, 0x8A77, 0xB47E, 0x8A78, 0xB47F, 0x8A79, 0xB481, 0x8A7A, 0xB482, 0x8A81, 0xB483, 0x8A82, 0xB484, + 0x8A83, 0xB485, 0x8A84, 0xB486, 0x8A85, 0xB487, 0x8A86, 0xB489, 0x8A87, 0xB48A, 0x8A88, 0xB48B, 0x8A89, 0xB48C, 0x8A8A, 0xB48D, + 0x8A8B, 0xB48E, 0x8A8C, 0xB48F, 0x8A8D, 0xB490, 0x8A8E, 0xB491, 0x8A8F, 0xB492, 0x8A90, 0xB493, 0x8A91, 0xB494, 0x8A92, 0xB495, + 0x8A93, 0xB496, 0x8A94, 0xB497, 0x8A95, 0xB498, 0x8A96, 0xB499, 0x8A97, 0xB49A, 0x8A98, 0xB49B, 0x8A99, 0xB49C, 0x8A9A, 0xB49E, + 0x8A9B, 0xB49F, 0x8A9C, 0xB4A0, 0x8A9D, 0xB4A1, 0x8A9E, 0xB4A2, 0x8A9F, 0xB4A3, 0x8AA0, 0xB4A5, 0x8AA1, 0xB4A6, 0x8AA2, 0xB4A7, + 0x8AA3, 0xB4A9, 0x8AA4, 0xB4AA, 0x8AA5, 0xB4AB, 0x8AA6, 0xB4AD, 0x8AA7, 0xB4AE, 0x8AA8, 0xB4AF, 0x8AA9, 0xB4B0, 0x8AAA, 0xB4B1, + 0x8AAB, 0xB4B2, 0x8AAC, 0xB4B3, 0x8AAD, 0xB4B4, 0x8AAE, 0xB4B6, 0x8AAF, 0xB4B8, 0x8AB0, 0xB4BA, 0x8AB1, 0xB4BB, 0x8AB2, 0xB4BC, + 0x8AB3, 0xB4BD, 0x8AB4, 0xB4BE, 0x8AB5, 0xB4BF, 0x8AB6, 0xB4C1, 0x8AB7, 0xB4C2, 0x8AB8, 0xB4C3, 0x8AB9, 0xB4C5, 0x8ABA, 0xB4C6, + 0x8ABB, 0xB4C7, 0x8ABC, 0xB4C9, 0x8ABD, 0xB4CA, 0x8ABE, 0xB4CB, 0x8ABF, 0xB4CC, 0x8AC0, 0xB4CD, 0x8AC1, 0xB4CE, 0x8AC2, 0xB4CF, + 0x8AC3, 0xB4D1, 0x8AC4, 0xB4D2, 0x8AC5, 0xB4D3, 0x8AC6, 0xB4D4, 0x8AC7, 0xB4D6, 0x8AC8, 0xB4D7, 0x8AC9, 0xB4D8, 0x8ACA, 0xB4D9, + 0x8ACB, 0xB4DA, 0x8ACC, 0xB4DB, 0x8ACD, 0xB4DE, 0x8ACE, 0xB4DF, 0x8ACF, 0xB4E1, 0x8AD0, 0xB4E2, 0x8AD1, 0xB4E5, 0x8AD2, 0xB4E7, + 0x8AD3, 0xB4E8, 0x8AD4, 0xB4E9, 0x8AD5, 0xB4EA, 0x8AD6, 0xB4EB, 0x8AD7, 0xB4EE, 0x8AD8, 0xB4F0, 0x8AD9, 0xB4F2, 0x8ADA, 0xB4F3, + 0x8ADB, 0xB4F4, 0x8ADC, 0xB4F5, 0x8ADD, 0xB4F6, 0x8ADE, 0xB4F7, 0x8ADF, 0xB4F9, 0x8AE0, 0xB4FA, 0x8AE1, 0xB4FB, 0x8AE2, 0xB4FC, + 0x8AE3, 0xB4FD, 0x8AE4, 0xB4FE, 0x8AE5, 0xB4FF, 0x8AE6, 0xB500, 0x8AE7, 0xB501, 0x8AE8, 0xB502, 0x8AE9, 0xB503, 0x8AEA, 0xB504, + 0x8AEB, 0xB505, 0x8AEC, 0xB506, 0x8AED, 0xB507, 0x8AEE, 0xB508, 0x8AEF, 0xB509, 0x8AF0, 0xB50A, 0x8AF1, 0xB50B, 0x8AF2, 0xB50C, + 0x8AF3, 0xB50D, 0x8AF4, 0xB50E, 0x8AF5, 0xB50F, 0x8AF6, 0xB510, 0x8AF7, 0xB511, 0x8AF8, 0xB512, 0x8AF9, 0xB513, 0x8AFA, 0xB516, + 0x8AFB, 0xB517, 0x8AFC, 0xB519, 0x8AFD, 0xB51A, 0x8AFE, 0xB51D, 0x8B41, 0xB51E, 0x8B42, 0xB51F, 0x8B43, 0xB520, 0x8B44, 0xB521, + 0x8B45, 0xB522, 0x8B46, 0xB523, 0x8B47, 0xB526, 0x8B48, 0xB52B, 0x8B49, 0xB52C, 0x8B4A, 0xB52D, 0x8B4B, 0xB52E, 0x8B4C, 0xB52F, + 0x8B4D, 0xB532, 0x8B4E, 0xB533, 0x8B4F, 0xB535, 0x8B50, 0xB536, 0x8B51, 0xB537, 0x8B52, 0xB539, 0x8B53, 0xB53A, 0x8B54, 0xB53B, + 0x8B55, 0xB53C, 0x8B56, 0xB53D, 0x8B57, 0xB53E, 0x8B58, 0xB53F, 0x8B59, 0xB542, 0x8B5A, 0xB546, 0x8B61, 0xB547, 0x8B62, 0xB548, + 0x8B63, 0xB549, 0x8B64, 0xB54A, 0x8B65, 0xB54E, 0x8B66, 0xB54F, 0x8B67, 0xB551, 0x8B68, 0xB552, 0x8B69, 0xB553, 0x8B6A, 0xB555, + 0x8B6B, 0xB556, 0x8B6C, 0xB557, 0x8B6D, 0xB558, 0x8B6E, 0xB559, 0x8B6F, 0xB55A, 0x8B70, 0xB55B, 0x8B71, 0xB55E, 0x8B72, 0xB562, + 0x8B73, 0xB563, 0x8B74, 0xB564, 0x8B75, 0xB565, 0x8B76, 0xB566, 0x8B77, 0xB567, 0x8B78, 0xB568, 0x8B79, 0xB569, 0x8B7A, 0xB56A, + 0x8B81, 0xB56B, 0x8B82, 0xB56C, 0x8B83, 0xB56D, 0x8B84, 0xB56E, 0x8B85, 0xB56F, 0x8B86, 0xB570, 0x8B87, 0xB571, 0x8B88, 0xB572, + 0x8B89, 0xB573, 0x8B8A, 0xB574, 0x8B8B, 0xB575, 0x8B8C, 0xB576, 0x8B8D, 0xB577, 0x8B8E, 0xB578, 0x8B8F, 0xB579, 0x8B90, 0xB57A, + 0x8B91, 0xB57B, 0x8B92, 0xB57C, 0x8B93, 0xB57D, 0x8B94, 0xB57E, 0x8B95, 0xB57F, 0x8B96, 0xB580, 0x8B97, 0xB581, 0x8B98, 0xB582, + 0x8B99, 0xB583, 0x8B9A, 0xB584, 0x8B9B, 0xB585, 0x8B9C, 0xB586, 0x8B9D, 0xB587, 0x8B9E, 0xB588, 0x8B9F, 0xB589, 0x8BA0, 0xB58A, + 0x8BA1, 0xB58B, 0x8BA2, 0xB58C, 0x8BA3, 0xB58D, 0x8BA4, 0xB58E, 0x8BA5, 0xB58F, 0x8BA6, 0xB590, 0x8BA7, 0xB591, 0x8BA8, 0xB592, + 0x8BA9, 0xB593, 0x8BAA, 0xB594, 0x8BAB, 0xB595, 0x8BAC, 0xB596, 0x8BAD, 0xB597, 0x8BAE, 0xB598, 0x8BAF, 0xB599, 0x8BB0, 0xB59A, + 0x8BB1, 0xB59B, 0x8BB2, 0xB59C, 0x8BB3, 0xB59D, 0x8BB4, 0xB59E, 0x8BB5, 0xB59F, 0x8BB6, 0xB5A2, 0x8BB7, 0xB5A3, 0x8BB8, 0xB5A5, + 0x8BB9, 0xB5A6, 0x8BBA, 0xB5A7, 0x8BBB, 0xB5A9, 0x8BBC, 0xB5AC, 0x8BBD, 0xB5AD, 0x8BBE, 0xB5AE, 0x8BBF, 0xB5AF, 0x8BC0, 0xB5B2, + 0x8BC1, 0xB5B6, 0x8BC2, 0xB5B7, 0x8BC3, 0xB5B8, 0x8BC4, 0xB5B9, 0x8BC5, 0xB5BA, 0x8BC6, 0xB5BE, 0x8BC7, 0xB5BF, 0x8BC8, 0xB5C1, + 0x8BC9, 0xB5C2, 0x8BCA, 0xB5C3, 0x8BCB, 0xB5C5, 0x8BCC, 0xB5C6, 0x8BCD, 0xB5C7, 0x8BCE, 0xB5C8, 0x8BCF, 0xB5C9, 0x8BD0, 0xB5CA, + 0x8BD1, 0xB5CB, 0x8BD2, 0xB5CE, 0x8BD3, 0xB5D2, 0x8BD4, 0xB5D3, 0x8BD5, 0xB5D4, 0x8BD6, 0xB5D5, 0x8BD7, 0xB5D6, 0x8BD8, 0xB5D7, + 0x8BD9, 0xB5D9, 0x8BDA, 0xB5DA, 0x8BDB, 0xB5DB, 0x8BDC, 0xB5DC, 0x8BDD, 0xB5DD, 0x8BDE, 0xB5DE, 0x8BDF, 0xB5DF, 0x8BE0, 0xB5E0, + 0x8BE1, 0xB5E1, 0x8BE2, 0xB5E2, 0x8BE3, 0xB5E3, 0x8BE4, 0xB5E4, 0x8BE5, 0xB5E5, 0x8BE6, 0xB5E6, 0x8BE7, 0xB5E7, 0x8BE8, 0xB5E8, + 0x8BE9, 0xB5E9, 0x8BEA, 0xB5EA, 0x8BEB, 0xB5EB, 0x8BEC, 0xB5ED, 0x8BED, 0xB5EE, 0x8BEE, 0xB5EF, 0x8BEF, 0xB5F0, 0x8BF0, 0xB5F1, + 0x8BF1, 0xB5F2, 0x8BF2, 0xB5F3, 0x8BF3, 0xB5F4, 0x8BF4, 0xB5F5, 0x8BF5, 0xB5F6, 0x8BF6, 0xB5F7, 0x8BF7, 0xB5F8, 0x8BF8, 0xB5F9, + 0x8BF9, 0xB5FA, 0x8BFA, 0xB5FB, 0x8BFB, 0xB5FC, 0x8BFC, 0xB5FD, 0x8BFD, 0xB5FE, 0x8BFE, 0xB5FF, 0x8C41, 0xB600, 0x8C42, 0xB601, + 0x8C43, 0xB602, 0x8C44, 0xB603, 0x8C45, 0xB604, 0x8C46, 0xB605, 0x8C47, 0xB606, 0x8C48, 0xB607, 0x8C49, 0xB608, 0x8C4A, 0xB609, + 0x8C4B, 0xB60A, 0x8C4C, 0xB60B, 0x8C4D, 0xB60C, 0x8C4E, 0xB60D, 0x8C4F, 0xB60E, 0x8C50, 0xB60F, 0x8C51, 0xB612, 0x8C52, 0xB613, + 0x8C53, 0xB615, 0x8C54, 0xB616, 0x8C55, 0xB617, 0x8C56, 0xB619, 0x8C57, 0xB61A, 0x8C58, 0xB61B, 0x8C59, 0xB61C, 0x8C5A, 0xB61D, + 0x8C61, 0xB61E, 0x8C62, 0xB61F, 0x8C63, 0xB620, 0x8C64, 0xB621, 0x8C65, 0xB622, 0x8C66, 0xB623, 0x8C67, 0xB624, 0x8C68, 0xB626, + 0x8C69, 0xB627, 0x8C6A, 0xB628, 0x8C6B, 0xB629, 0x8C6C, 0xB62A, 0x8C6D, 0xB62B, 0x8C6E, 0xB62D, 0x8C6F, 0xB62E, 0x8C70, 0xB62F, + 0x8C71, 0xB630, 0x8C72, 0xB631, 0x8C73, 0xB632, 0x8C74, 0xB633, 0x8C75, 0xB635, 0x8C76, 0xB636, 0x8C77, 0xB637, 0x8C78, 0xB638, + 0x8C79, 0xB639, 0x8C7A, 0xB63A, 0x8C81, 0xB63B, 0x8C82, 0xB63C, 0x8C83, 0xB63D, 0x8C84, 0xB63E, 0x8C85, 0xB63F, 0x8C86, 0xB640, + 0x8C87, 0xB641, 0x8C88, 0xB642, 0x8C89, 0xB643, 0x8C8A, 0xB644, 0x8C8B, 0xB645, 0x8C8C, 0xB646, 0x8C8D, 0xB647, 0x8C8E, 0xB649, + 0x8C8F, 0xB64A, 0x8C90, 0xB64B, 0x8C91, 0xB64C, 0x8C92, 0xB64D, 0x8C93, 0xB64E, 0x8C94, 0xB64F, 0x8C95, 0xB650, 0x8C96, 0xB651, + 0x8C97, 0xB652, 0x8C98, 0xB653, 0x8C99, 0xB654, 0x8C9A, 0xB655, 0x8C9B, 0xB656, 0x8C9C, 0xB657, 0x8C9D, 0xB658, 0x8C9E, 0xB659, + 0x8C9F, 0xB65A, 0x8CA0, 0xB65B, 0x8CA1, 0xB65C, 0x8CA2, 0xB65D, 0x8CA3, 0xB65E, 0x8CA4, 0xB65F, 0x8CA5, 0xB660, 0x8CA6, 0xB661, + 0x8CA7, 0xB662, 0x8CA8, 0xB663, 0x8CA9, 0xB665, 0x8CAA, 0xB666, 0x8CAB, 0xB667, 0x8CAC, 0xB669, 0x8CAD, 0xB66A, 0x8CAE, 0xB66B, + 0x8CAF, 0xB66C, 0x8CB0, 0xB66D, 0x8CB1, 0xB66E, 0x8CB2, 0xB66F, 0x8CB3, 0xB670, 0x8CB4, 0xB671, 0x8CB5, 0xB672, 0x8CB6, 0xB673, + 0x8CB7, 0xB674, 0x8CB8, 0xB675, 0x8CB9, 0xB676, 0x8CBA, 0xB677, 0x8CBB, 0xB678, 0x8CBC, 0xB679, 0x8CBD, 0xB67A, 0x8CBE, 0xB67B, + 0x8CBF, 0xB67C, 0x8CC0, 0xB67D, 0x8CC1, 0xB67E, 0x8CC2, 0xB67F, 0x8CC3, 0xB680, 0x8CC4, 0xB681, 0x8CC5, 0xB682, 0x8CC6, 0xB683, + 0x8CC7, 0xB684, 0x8CC8, 0xB685, 0x8CC9, 0xB686, 0x8CCA, 0xB687, 0x8CCB, 0xB688, 0x8CCC, 0xB689, 0x8CCD, 0xB68A, 0x8CCE, 0xB68B, + 0x8CCF, 0xB68C, 0x8CD0, 0xB68D, 0x8CD1, 0xB68E, 0x8CD2, 0xB68F, 0x8CD3, 0xB690, 0x8CD4, 0xB691, 0x8CD5, 0xB692, 0x8CD6, 0xB693, + 0x8CD7, 0xB694, 0x8CD8, 0xB695, 0x8CD9, 0xB696, 0x8CDA, 0xB697, 0x8CDB, 0xB698, 0x8CDC, 0xB699, 0x8CDD, 0xB69A, 0x8CDE, 0xB69B, + 0x8CDF, 0xB69E, 0x8CE0, 0xB69F, 0x8CE1, 0xB6A1, 0x8CE2, 0xB6A2, 0x8CE3, 0xB6A3, 0x8CE4, 0xB6A5, 0x8CE5, 0xB6A6, 0x8CE6, 0xB6A7, + 0x8CE7, 0xB6A8, 0x8CE8, 0xB6A9, 0x8CE9, 0xB6AA, 0x8CEA, 0xB6AD, 0x8CEB, 0xB6AE, 0x8CEC, 0xB6AF, 0x8CED, 0xB6B0, 0x8CEE, 0xB6B2, + 0x8CEF, 0xB6B3, 0x8CF0, 0xB6B4, 0x8CF1, 0xB6B5, 0x8CF2, 0xB6B6, 0x8CF3, 0xB6B7, 0x8CF4, 0xB6B8, 0x8CF5, 0xB6B9, 0x8CF6, 0xB6BA, + 0x8CF7, 0xB6BB, 0x8CF8, 0xB6BC, 0x8CF9, 0xB6BD, 0x8CFA, 0xB6BE, 0x8CFB, 0xB6BF, 0x8CFC, 0xB6C0, 0x8CFD, 0xB6C1, 0x8CFE, 0xB6C2, + 0x8D41, 0xB6C3, 0x8D42, 0xB6C4, 0x8D43, 0xB6C5, 0x8D44, 0xB6C6, 0x8D45, 0xB6C7, 0x8D46, 0xB6C8, 0x8D47, 0xB6C9, 0x8D48, 0xB6CA, + 0x8D49, 0xB6CB, 0x8D4A, 0xB6CC, 0x8D4B, 0xB6CD, 0x8D4C, 0xB6CE, 0x8D4D, 0xB6CF, 0x8D4E, 0xB6D0, 0x8D4F, 0xB6D1, 0x8D50, 0xB6D2, + 0x8D51, 0xB6D3, 0x8D52, 0xB6D5, 0x8D53, 0xB6D6, 0x8D54, 0xB6D7, 0x8D55, 0xB6D8, 0x8D56, 0xB6D9, 0x8D57, 0xB6DA, 0x8D58, 0xB6DB, + 0x8D59, 0xB6DC, 0x8D5A, 0xB6DD, 0x8D61, 0xB6DE, 0x8D62, 0xB6DF, 0x8D63, 0xB6E0, 0x8D64, 0xB6E1, 0x8D65, 0xB6E2, 0x8D66, 0xB6E3, + 0x8D67, 0xB6E4, 0x8D68, 0xB6E5, 0x8D69, 0xB6E6, 0x8D6A, 0xB6E7, 0x8D6B, 0xB6E8, 0x8D6C, 0xB6E9, 0x8D6D, 0xB6EA, 0x8D6E, 0xB6EB, + 0x8D6F, 0xB6EC, 0x8D70, 0xB6ED, 0x8D71, 0xB6EE, 0x8D72, 0xB6EF, 0x8D73, 0xB6F1, 0x8D74, 0xB6F2, 0x8D75, 0xB6F3, 0x8D76, 0xB6F5, + 0x8D77, 0xB6F6, 0x8D78, 0xB6F7, 0x8D79, 0xB6F9, 0x8D7A, 0xB6FA, 0x8D81, 0xB6FB, 0x8D82, 0xB6FC, 0x8D83, 0xB6FD, 0x8D84, 0xB6FE, + 0x8D85, 0xB6FF, 0x8D86, 0xB702, 0x8D87, 0xB703, 0x8D88, 0xB704, 0x8D89, 0xB706, 0x8D8A, 0xB707, 0x8D8B, 0xB708, 0x8D8C, 0xB709, + 0x8D8D, 0xB70A, 0x8D8E, 0xB70B, 0x8D8F, 0xB70C, 0x8D90, 0xB70D, 0x8D91, 0xB70E, 0x8D92, 0xB70F, 0x8D93, 0xB710, 0x8D94, 0xB711, + 0x8D95, 0xB712, 0x8D96, 0xB713, 0x8D97, 0xB714, 0x8D98, 0xB715, 0x8D99, 0xB716, 0x8D9A, 0xB717, 0x8D9B, 0xB718, 0x8D9C, 0xB719, + 0x8D9D, 0xB71A, 0x8D9E, 0xB71B, 0x8D9F, 0xB71C, 0x8DA0, 0xB71D, 0x8DA1, 0xB71E, 0x8DA2, 0xB71F, 0x8DA3, 0xB720, 0x8DA4, 0xB721, + 0x8DA5, 0xB722, 0x8DA6, 0xB723, 0x8DA7, 0xB724, 0x8DA8, 0xB725, 0x8DA9, 0xB726, 0x8DAA, 0xB727, 0x8DAB, 0xB72A, 0x8DAC, 0xB72B, + 0x8DAD, 0xB72D, 0x8DAE, 0xB72E, 0x8DAF, 0xB731, 0x8DB0, 0xB732, 0x8DB1, 0xB733, 0x8DB2, 0xB734, 0x8DB3, 0xB735, 0x8DB4, 0xB736, + 0x8DB5, 0xB737, 0x8DB6, 0xB73A, 0x8DB7, 0xB73C, 0x8DB8, 0xB73D, 0x8DB9, 0xB73E, 0x8DBA, 0xB73F, 0x8DBB, 0xB740, 0x8DBC, 0xB741, + 0x8DBD, 0xB742, 0x8DBE, 0xB743, 0x8DBF, 0xB745, 0x8DC0, 0xB746, 0x8DC1, 0xB747, 0x8DC2, 0xB749, 0x8DC3, 0xB74A, 0x8DC4, 0xB74B, + 0x8DC5, 0xB74D, 0x8DC6, 0xB74E, 0x8DC7, 0xB74F, 0x8DC8, 0xB750, 0x8DC9, 0xB751, 0x8DCA, 0xB752, 0x8DCB, 0xB753, 0x8DCC, 0xB756, + 0x8DCD, 0xB757, 0x8DCE, 0xB758, 0x8DCF, 0xB759, 0x8DD0, 0xB75A, 0x8DD1, 0xB75B, 0x8DD2, 0xB75C, 0x8DD3, 0xB75D, 0x8DD4, 0xB75E, + 0x8DD5, 0xB75F, 0x8DD6, 0xB761, 0x8DD7, 0xB762, 0x8DD8, 0xB763, 0x8DD9, 0xB765, 0x8DDA, 0xB766, 0x8DDB, 0xB767, 0x8DDC, 0xB769, + 0x8DDD, 0xB76A, 0x8DDE, 0xB76B, 0x8DDF, 0xB76C, 0x8DE0, 0xB76D, 0x8DE1, 0xB76E, 0x8DE2, 0xB76F, 0x8DE3, 0xB772, 0x8DE4, 0xB774, + 0x8DE5, 0xB776, 0x8DE6, 0xB777, 0x8DE7, 0xB778, 0x8DE8, 0xB779, 0x8DE9, 0xB77A, 0x8DEA, 0xB77B, 0x8DEB, 0xB77E, 0x8DEC, 0xB77F, + 0x8DED, 0xB781, 0x8DEE, 0xB782, 0x8DEF, 0xB783, 0x8DF0, 0xB785, 0x8DF1, 0xB786, 0x8DF2, 0xB787, 0x8DF3, 0xB788, 0x8DF4, 0xB789, + 0x8DF5, 0xB78A, 0x8DF6, 0xB78B, 0x8DF7, 0xB78E, 0x8DF8, 0xB793, 0x8DF9, 0xB794, 0x8DFA, 0xB795, 0x8DFB, 0xB79A, 0x8DFC, 0xB79B, + 0x8DFD, 0xB79D, 0x8DFE, 0xB79E, 0x8E41, 0xB79F, 0x8E42, 0xB7A1, 0x8E43, 0xB7A2, 0x8E44, 0xB7A3, 0x8E45, 0xB7A4, 0x8E46, 0xB7A5, + 0x8E47, 0xB7A6, 0x8E48, 0xB7A7, 0x8E49, 0xB7AA, 0x8E4A, 0xB7AE, 0x8E4B, 0xB7AF, 0x8E4C, 0xB7B0, 0x8E4D, 0xB7B1, 0x8E4E, 0xB7B2, + 0x8E4F, 0xB7B3, 0x8E50, 0xB7B6, 0x8E51, 0xB7B7, 0x8E52, 0xB7B9, 0x8E53, 0xB7BA, 0x8E54, 0xB7BB, 0x8E55, 0xB7BC, 0x8E56, 0xB7BD, + 0x8E57, 0xB7BE, 0x8E58, 0xB7BF, 0x8E59, 0xB7C0, 0x8E5A, 0xB7C1, 0x8E61, 0xB7C2, 0x8E62, 0xB7C3, 0x8E63, 0xB7C4, 0x8E64, 0xB7C5, + 0x8E65, 0xB7C6, 0x8E66, 0xB7C8, 0x8E67, 0xB7CA, 0x8E68, 0xB7CB, 0x8E69, 0xB7CC, 0x8E6A, 0xB7CD, 0x8E6B, 0xB7CE, 0x8E6C, 0xB7CF, + 0x8E6D, 0xB7D0, 0x8E6E, 0xB7D1, 0x8E6F, 0xB7D2, 0x8E70, 0xB7D3, 0x8E71, 0xB7D4, 0x8E72, 0xB7D5, 0x8E73, 0xB7D6, 0x8E74, 0xB7D7, + 0x8E75, 0xB7D8, 0x8E76, 0xB7D9, 0x8E77, 0xB7DA, 0x8E78, 0xB7DB, 0x8E79, 0xB7DC, 0x8E7A, 0xB7DD, 0x8E81, 0xB7DE, 0x8E82, 0xB7DF, + 0x8E83, 0xB7E0, 0x8E84, 0xB7E1, 0x8E85, 0xB7E2, 0x8E86, 0xB7E3, 0x8E87, 0xB7E4, 0x8E88, 0xB7E5, 0x8E89, 0xB7E6, 0x8E8A, 0xB7E7, + 0x8E8B, 0xB7E8, 0x8E8C, 0xB7E9, 0x8E8D, 0xB7EA, 0x8E8E, 0xB7EB, 0x8E8F, 0xB7EE, 0x8E90, 0xB7EF, 0x8E91, 0xB7F1, 0x8E92, 0xB7F2, + 0x8E93, 0xB7F3, 0x8E94, 0xB7F5, 0x8E95, 0xB7F6, 0x8E96, 0xB7F7, 0x8E97, 0xB7F8, 0x8E98, 0xB7F9, 0x8E99, 0xB7FA, 0x8E9A, 0xB7FB, + 0x8E9B, 0xB7FE, 0x8E9C, 0xB802, 0x8E9D, 0xB803, 0x8E9E, 0xB804, 0x8E9F, 0xB805, 0x8EA0, 0xB806, 0x8EA1, 0xB80A, 0x8EA2, 0xB80B, + 0x8EA3, 0xB80D, 0x8EA4, 0xB80E, 0x8EA5, 0xB80F, 0x8EA6, 0xB811, 0x8EA7, 0xB812, 0x8EA8, 0xB813, 0x8EA9, 0xB814, 0x8EAA, 0xB815, + 0x8EAB, 0xB816, 0x8EAC, 0xB817, 0x8EAD, 0xB81A, 0x8EAE, 0xB81C, 0x8EAF, 0xB81E, 0x8EB0, 0xB81F, 0x8EB1, 0xB820, 0x8EB2, 0xB821, + 0x8EB3, 0xB822, 0x8EB4, 0xB823, 0x8EB5, 0xB826, 0x8EB6, 0xB827, 0x8EB7, 0xB829, 0x8EB8, 0xB82A, 0x8EB9, 0xB82B, 0x8EBA, 0xB82D, + 0x8EBB, 0xB82E, 0x8EBC, 0xB82F, 0x8EBD, 0xB830, 0x8EBE, 0xB831, 0x8EBF, 0xB832, 0x8EC0, 0xB833, 0x8EC1, 0xB836, 0x8EC2, 0xB83A, + 0x8EC3, 0xB83B, 0x8EC4, 0xB83C, 0x8EC5, 0xB83D, 0x8EC6, 0xB83E, 0x8EC7, 0xB83F, 0x8EC8, 0xB841, 0x8EC9, 0xB842, 0x8ECA, 0xB843, + 0x8ECB, 0xB845, 0x8ECC, 0xB846, 0x8ECD, 0xB847, 0x8ECE, 0xB848, 0x8ECF, 0xB849, 0x8ED0, 0xB84A, 0x8ED1, 0xB84B, 0x8ED2, 0xB84C, + 0x8ED3, 0xB84D, 0x8ED4, 0xB84E, 0x8ED5, 0xB84F, 0x8ED6, 0xB850, 0x8ED7, 0xB852, 0x8ED8, 0xB854, 0x8ED9, 0xB855, 0x8EDA, 0xB856, + 0x8EDB, 0xB857, 0x8EDC, 0xB858, 0x8EDD, 0xB859, 0x8EDE, 0xB85A, 0x8EDF, 0xB85B, 0x8EE0, 0xB85E, 0x8EE1, 0xB85F, 0x8EE2, 0xB861, + 0x8EE3, 0xB862, 0x8EE4, 0xB863, 0x8EE5, 0xB865, 0x8EE6, 0xB866, 0x8EE7, 0xB867, 0x8EE8, 0xB868, 0x8EE9, 0xB869, 0x8EEA, 0xB86A, + 0x8EEB, 0xB86B, 0x8EEC, 0xB86E, 0x8EED, 0xB870, 0x8EEE, 0xB872, 0x8EEF, 0xB873, 0x8EF0, 0xB874, 0x8EF1, 0xB875, 0x8EF2, 0xB876, + 0x8EF3, 0xB877, 0x8EF4, 0xB879, 0x8EF5, 0xB87A, 0x8EF6, 0xB87B, 0x8EF7, 0xB87D, 0x8EF8, 0xB87E, 0x8EF9, 0xB87F, 0x8EFA, 0xB880, + 0x8EFB, 0xB881, 0x8EFC, 0xB882, 0x8EFD, 0xB883, 0x8EFE, 0xB884, 0x8F41, 0xB885, 0x8F42, 0xB886, 0x8F43, 0xB887, 0x8F44, 0xB888, + 0x8F45, 0xB889, 0x8F46, 0xB88A, 0x8F47, 0xB88B, 0x8F48, 0xB88C, 0x8F49, 0xB88E, 0x8F4A, 0xB88F, 0x8F4B, 0xB890, 0x8F4C, 0xB891, + 0x8F4D, 0xB892, 0x8F4E, 0xB893, 0x8F4F, 0xB894, 0x8F50, 0xB895, 0x8F51, 0xB896, 0x8F52, 0xB897, 0x8F53, 0xB898, 0x8F54, 0xB899, + 0x8F55, 0xB89A, 0x8F56, 0xB89B, 0x8F57, 0xB89C, 0x8F58, 0xB89D, 0x8F59, 0xB89E, 0x8F5A, 0xB89F, 0x8F61, 0xB8A0, 0x8F62, 0xB8A1, + 0x8F63, 0xB8A2, 0x8F64, 0xB8A3, 0x8F65, 0xB8A4, 0x8F66, 0xB8A5, 0x8F67, 0xB8A6, 0x8F68, 0xB8A7, 0x8F69, 0xB8A9, 0x8F6A, 0xB8AA, + 0x8F6B, 0xB8AB, 0x8F6C, 0xB8AC, 0x8F6D, 0xB8AD, 0x8F6E, 0xB8AE, 0x8F6F, 0xB8AF, 0x8F70, 0xB8B1, 0x8F71, 0xB8B2, 0x8F72, 0xB8B3, + 0x8F73, 0xB8B5, 0x8F74, 0xB8B6, 0x8F75, 0xB8B7, 0x8F76, 0xB8B9, 0x8F77, 0xB8BA, 0x8F78, 0xB8BB, 0x8F79, 0xB8BC, 0x8F7A, 0xB8BD, + 0x8F81, 0xB8BE, 0x8F82, 0xB8BF, 0x8F83, 0xB8C2, 0x8F84, 0xB8C4, 0x8F85, 0xB8C6, 0x8F86, 0xB8C7, 0x8F87, 0xB8C8, 0x8F88, 0xB8C9, + 0x8F89, 0xB8CA, 0x8F8A, 0xB8CB, 0x8F8B, 0xB8CD, 0x8F8C, 0xB8CE, 0x8F8D, 0xB8CF, 0x8F8E, 0xB8D1, 0x8F8F, 0xB8D2, 0x8F90, 0xB8D3, + 0x8F91, 0xB8D5, 0x8F92, 0xB8D6, 0x8F93, 0xB8D7, 0x8F94, 0xB8D8, 0x8F95, 0xB8D9, 0x8F96, 0xB8DA, 0x8F97, 0xB8DB, 0x8F98, 0xB8DC, + 0x8F99, 0xB8DE, 0x8F9A, 0xB8E0, 0x8F9B, 0xB8E2, 0x8F9C, 0xB8E3, 0x8F9D, 0xB8E4, 0x8F9E, 0xB8E5, 0x8F9F, 0xB8E6, 0x8FA0, 0xB8E7, + 0x8FA1, 0xB8EA, 0x8FA2, 0xB8EB, 0x8FA3, 0xB8ED, 0x8FA4, 0xB8EE, 0x8FA5, 0xB8EF, 0x8FA6, 0xB8F1, 0x8FA7, 0xB8F2, 0x8FA8, 0xB8F3, + 0x8FA9, 0xB8F4, 0x8FAA, 0xB8F5, 0x8FAB, 0xB8F6, 0x8FAC, 0xB8F7, 0x8FAD, 0xB8FA, 0x8FAE, 0xB8FC, 0x8FAF, 0xB8FE, 0x8FB0, 0xB8FF, + 0x8FB1, 0xB900, 0x8FB2, 0xB901, 0x8FB3, 0xB902, 0x8FB4, 0xB903, 0x8FB5, 0xB905, 0x8FB6, 0xB906, 0x8FB7, 0xB907, 0x8FB8, 0xB908, + 0x8FB9, 0xB909, 0x8FBA, 0xB90A, 0x8FBB, 0xB90B, 0x8FBC, 0xB90C, 0x8FBD, 0xB90D, 0x8FBE, 0xB90E, 0x8FBF, 0xB90F, 0x8FC0, 0xB910, + 0x8FC1, 0xB911, 0x8FC2, 0xB912, 0x8FC3, 0xB913, 0x8FC4, 0xB914, 0x8FC5, 0xB915, 0x8FC6, 0xB916, 0x8FC7, 0xB917, 0x8FC8, 0xB919, + 0x8FC9, 0xB91A, 0x8FCA, 0xB91B, 0x8FCB, 0xB91C, 0x8FCC, 0xB91D, 0x8FCD, 0xB91E, 0x8FCE, 0xB91F, 0x8FCF, 0xB921, 0x8FD0, 0xB922, + 0x8FD1, 0xB923, 0x8FD2, 0xB924, 0x8FD3, 0xB925, 0x8FD4, 0xB926, 0x8FD5, 0xB927, 0x8FD6, 0xB928, 0x8FD7, 0xB929, 0x8FD8, 0xB92A, + 0x8FD9, 0xB92B, 0x8FDA, 0xB92C, 0x8FDB, 0xB92D, 0x8FDC, 0xB92E, 0x8FDD, 0xB92F, 0x8FDE, 0xB930, 0x8FDF, 0xB931, 0x8FE0, 0xB932, + 0x8FE1, 0xB933, 0x8FE2, 0xB934, 0x8FE3, 0xB935, 0x8FE4, 0xB936, 0x8FE5, 0xB937, 0x8FE6, 0xB938, 0x8FE7, 0xB939, 0x8FE8, 0xB93A, + 0x8FE9, 0xB93B, 0x8FEA, 0xB93E, 0x8FEB, 0xB93F, 0x8FEC, 0xB941, 0x8FED, 0xB942, 0x8FEE, 0xB943, 0x8FEF, 0xB945, 0x8FF0, 0xB946, + 0x8FF1, 0xB947, 0x8FF2, 0xB948, 0x8FF3, 0xB949, 0x8FF4, 0xB94A, 0x8FF5, 0xB94B, 0x8FF6, 0xB94D, 0x8FF7, 0xB94E, 0x8FF8, 0xB950, + 0x8FF9, 0xB952, 0x8FFA, 0xB953, 0x8FFB, 0xB954, 0x8FFC, 0xB955, 0x8FFD, 0xB956, 0x8FFE, 0xB957, 0x9041, 0xB95A, 0x9042, 0xB95B, + 0x9043, 0xB95D, 0x9044, 0xB95E, 0x9045, 0xB95F, 0x9046, 0xB961, 0x9047, 0xB962, 0x9048, 0xB963, 0x9049, 0xB964, 0x904A, 0xB965, + 0x904B, 0xB966, 0x904C, 0xB967, 0x904D, 0xB96A, 0x904E, 0xB96C, 0x904F, 0xB96E, 0x9050, 0xB96F, 0x9051, 0xB970, 0x9052, 0xB971, + 0x9053, 0xB972, 0x9054, 0xB973, 0x9055, 0xB976, 0x9056, 0xB977, 0x9057, 0xB979, 0x9058, 0xB97A, 0x9059, 0xB97B, 0x905A, 0xB97D, + 0x9061, 0xB97E, 0x9062, 0xB97F, 0x9063, 0xB980, 0x9064, 0xB981, 0x9065, 0xB982, 0x9066, 0xB983, 0x9067, 0xB986, 0x9068, 0xB988, + 0x9069, 0xB98B, 0x906A, 0xB98C, 0x906B, 0xB98F, 0x906C, 0xB990, 0x906D, 0xB991, 0x906E, 0xB992, 0x906F, 0xB993, 0x9070, 0xB994, + 0x9071, 0xB995, 0x9072, 0xB996, 0x9073, 0xB997, 0x9074, 0xB998, 0x9075, 0xB999, 0x9076, 0xB99A, 0x9077, 0xB99B, 0x9078, 0xB99C, + 0x9079, 0xB99D, 0x907A, 0xB99E, 0x9081, 0xB99F, 0x9082, 0xB9A0, 0x9083, 0xB9A1, 0x9084, 0xB9A2, 0x9085, 0xB9A3, 0x9086, 0xB9A4, + 0x9087, 0xB9A5, 0x9088, 0xB9A6, 0x9089, 0xB9A7, 0x908A, 0xB9A8, 0x908B, 0xB9A9, 0x908C, 0xB9AA, 0x908D, 0xB9AB, 0x908E, 0xB9AE, + 0x908F, 0xB9AF, 0x9090, 0xB9B1, 0x9091, 0xB9B2, 0x9092, 0xB9B3, 0x9093, 0xB9B5, 0x9094, 0xB9B6, 0x9095, 0xB9B7, 0x9096, 0xB9B8, + 0x9097, 0xB9B9, 0x9098, 0xB9BA, 0x9099, 0xB9BB, 0x909A, 0xB9BE, 0x909B, 0xB9C0, 0x909C, 0xB9C2, 0x909D, 0xB9C3, 0x909E, 0xB9C4, + 0x909F, 0xB9C5, 0x90A0, 0xB9C6, 0x90A1, 0xB9C7, 0x90A2, 0xB9CA, 0x90A3, 0xB9CB, 0x90A4, 0xB9CD, 0x90A5, 0xB9D3, 0x90A6, 0xB9D4, + 0x90A7, 0xB9D5, 0x90A8, 0xB9D6, 0x90A9, 0xB9D7, 0x90AA, 0xB9DA, 0x90AB, 0xB9DC, 0x90AC, 0xB9DF, 0x90AD, 0xB9E0, 0x90AE, 0xB9E2, + 0x90AF, 0xB9E6, 0x90B0, 0xB9E7, 0x90B1, 0xB9E9, 0x90B2, 0xB9EA, 0x90B3, 0xB9EB, 0x90B4, 0xB9ED, 0x90B5, 0xB9EE, 0x90B6, 0xB9EF, + 0x90B7, 0xB9F0, 0x90B8, 0xB9F1, 0x90B9, 0xB9F2, 0x90BA, 0xB9F3, 0x90BB, 0xB9F6, 0x90BC, 0xB9FB, 0x90BD, 0xB9FC, 0x90BE, 0xB9FD, + 0x90BF, 0xB9FE, 0x90C0, 0xB9FF, 0x90C1, 0xBA02, 0x90C2, 0xBA03, 0x90C3, 0xBA04, 0x90C4, 0xBA05, 0x90C5, 0xBA06, 0x90C6, 0xBA07, + 0x90C7, 0xBA09, 0x90C8, 0xBA0A, 0x90C9, 0xBA0B, 0x90CA, 0xBA0C, 0x90CB, 0xBA0D, 0x90CC, 0xBA0E, 0x90CD, 0xBA0F, 0x90CE, 0xBA10, + 0x90CF, 0xBA11, 0x90D0, 0xBA12, 0x90D1, 0xBA13, 0x90D2, 0xBA14, 0x90D3, 0xBA16, 0x90D4, 0xBA17, 0x90D5, 0xBA18, 0x90D6, 0xBA19, + 0x90D7, 0xBA1A, 0x90D8, 0xBA1B, 0x90D9, 0xBA1C, 0x90DA, 0xBA1D, 0x90DB, 0xBA1E, 0x90DC, 0xBA1F, 0x90DD, 0xBA20, 0x90DE, 0xBA21, + 0x90DF, 0xBA22, 0x90E0, 0xBA23, 0x90E1, 0xBA24, 0x90E2, 0xBA25, 0x90E3, 0xBA26, 0x90E4, 0xBA27, 0x90E5, 0xBA28, 0x90E6, 0xBA29, + 0x90E7, 0xBA2A, 0x90E8, 0xBA2B, 0x90E9, 0xBA2C, 0x90EA, 0xBA2D, 0x90EB, 0xBA2E, 0x90EC, 0xBA2F, 0x90ED, 0xBA30, 0x90EE, 0xBA31, + 0x90EF, 0xBA32, 0x90F0, 0xBA33, 0x90F1, 0xBA34, 0x90F2, 0xBA35, 0x90F3, 0xBA36, 0x90F4, 0xBA37, 0x90F5, 0xBA3A, 0x90F6, 0xBA3B, + 0x90F7, 0xBA3D, 0x90F8, 0xBA3E, 0x90F9, 0xBA3F, 0x90FA, 0xBA41, 0x90FB, 0xBA43, 0x90FC, 0xBA44, 0x90FD, 0xBA45, 0x90FE, 0xBA46, + 0x9141, 0xBA47, 0x9142, 0xBA4A, 0x9143, 0xBA4C, 0x9144, 0xBA4F, 0x9145, 0xBA50, 0x9146, 0xBA51, 0x9147, 0xBA52, 0x9148, 0xBA56, + 0x9149, 0xBA57, 0x914A, 0xBA59, 0x914B, 0xBA5A, 0x914C, 0xBA5B, 0x914D, 0xBA5D, 0x914E, 0xBA5E, 0x914F, 0xBA5F, 0x9150, 0xBA60, + 0x9151, 0xBA61, 0x9152, 0xBA62, 0x9153, 0xBA63, 0x9154, 0xBA66, 0x9155, 0xBA6A, 0x9156, 0xBA6B, 0x9157, 0xBA6C, 0x9158, 0xBA6D, + 0x9159, 0xBA6E, 0x915A, 0xBA6F, 0x9161, 0xBA72, 0x9162, 0xBA73, 0x9163, 0xBA75, 0x9164, 0xBA76, 0x9165, 0xBA77, 0x9166, 0xBA79, + 0x9167, 0xBA7A, 0x9168, 0xBA7B, 0x9169, 0xBA7C, 0x916A, 0xBA7D, 0x916B, 0xBA7E, 0x916C, 0xBA7F, 0x916D, 0xBA80, 0x916E, 0xBA81, + 0x916F, 0xBA82, 0x9170, 0xBA86, 0x9171, 0xBA88, 0x9172, 0xBA89, 0x9173, 0xBA8A, 0x9174, 0xBA8B, 0x9175, 0xBA8D, 0x9176, 0xBA8E, + 0x9177, 0xBA8F, 0x9178, 0xBA90, 0x9179, 0xBA91, 0x917A, 0xBA92, 0x9181, 0xBA93, 0x9182, 0xBA94, 0x9183, 0xBA95, 0x9184, 0xBA96, + 0x9185, 0xBA97, 0x9186, 0xBA98, 0x9187, 0xBA99, 0x9188, 0xBA9A, 0x9189, 0xBA9B, 0x918A, 0xBA9C, 0x918B, 0xBA9D, 0x918C, 0xBA9E, + 0x918D, 0xBA9F, 0x918E, 0xBAA0, 0x918F, 0xBAA1, 0x9190, 0xBAA2, 0x9191, 0xBAA3, 0x9192, 0xBAA4, 0x9193, 0xBAA5, 0x9194, 0xBAA6, + 0x9195, 0xBAA7, 0x9196, 0xBAAA, 0x9197, 0xBAAD, 0x9198, 0xBAAE, 0x9199, 0xBAAF, 0x919A, 0xBAB1, 0x919B, 0xBAB3, 0x919C, 0xBAB4, + 0x919D, 0xBAB5, 0x919E, 0xBAB6, 0x919F, 0xBAB7, 0x91A0, 0xBABA, 0x91A1, 0xBABC, 0x91A2, 0xBABE, 0x91A3, 0xBABF, 0x91A4, 0xBAC0, + 0x91A5, 0xBAC1, 0x91A6, 0xBAC2, 0x91A7, 0xBAC3, 0x91A8, 0xBAC5, 0x91A9, 0xBAC6, 0x91AA, 0xBAC7, 0x91AB, 0xBAC9, 0x91AC, 0xBACA, + 0x91AD, 0xBACB, 0x91AE, 0xBACC, 0x91AF, 0xBACD, 0x91B0, 0xBACE, 0x91B1, 0xBACF, 0x91B2, 0xBAD0, 0x91B3, 0xBAD1, 0x91B4, 0xBAD2, + 0x91B5, 0xBAD3, 0x91B6, 0xBAD4, 0x91B7, 0xBAD5, 0x91B8, 0xBAD6, 0x91B9, 0xBAD7, 0x91BA, 0xBADA, 0x91BB, 0xBADB, 0x91BC, 0xBADC, + 0x91BD, 0xBADD, 0x91BE, 0xBADE, 0x91BF, 0xBADF, 0x91C0, 0xBAE0, 0x91C1, 0xBAE1, 0x91C2, 0xBAE2, 0x91C3, 0xBAE3, 0x91C4, 0xBAE4, + 0x91C5, 0xBAE5, 0x91C6, 0xBAE6, 0x91C7, 0xBAE7, 0x91C8, 0xBAE8, 0x91C9, 0xBAE9, 0x91CA, 0xBAEA, 0x91CB, 0xBAEB, 0x91CC, 0xBAEC, + 0x91CD, 0xBAED, 0x91CE, 0xBAEE, 0x91CF, 0xBAEF, 0x91D0, 0xBAF0, 0x91D1, 0xBAF1, 0x91D2, 0xBAF2, 0x91D3, 0xBAF3, 0x91D4, 0xBAF4, + 0x91D5, 0xBAF5, 0x91D6, 0xBAF6, 0x91D7, 0xBAF7, 0x91D8, 0xBAF8, 0x91D9, 0xBAF9, 0x91DA, 0xBAFA, 0x91DB, 0xBAFB, 0x91DC, 0xBAFD, + 0x91DD, 0xBAFE, 0x91DE, 0xBAFF, 0x91DF, 0xBB01, 0x91E0, 0xBB02, 0x91E1, 0xBB03, 0x91E2, 0xBB05, 0x91E3, 0xBB06, 0x91E4, 0xBB07, + 0x91E5, 0xBB08, 0x91E6, 0xBB09, 0x91E7, 0xBB0A, 0x91E8, 0xBB0B, 0x91E9, 0xBB0C, 0x91EA, 0xBB0E, 0x91EB, 0xBB10, 0x91EC, 0xBB12, + 0x91ED, 0xBB13, 0x91EE, 0xBB14, 0x91EF, 0xBB15, 0x91F0, 0xBB16, 0x91F1, 0xBB17, 0x91F2, 0xBB19, 0x91F3, 0xBB1A, 0x91F4, 0xBB1B, + 0x91F5, 0xBB1D, 0x91F6, 0xBB1E, 0x91F7, 0xBB1F, 0x91F8, 0xBB21, 0x91F9, 0xBB22, 0x91FA, 0xBB23, 0x91FB, 0xBB24, 0x91FC, 0xBB25, + 0x91FD, 0xBB26, 0x91FE, 0xBB27, 0x9241, 0xBB28, 0x9242, 0xBB2A, 0x9243, 0xBB2C, 0x9244, 0xBB2D, 0x9245, 0xBB2E, 0x9246, 0xBB2F, + 0x9247, 0xBB30, 0x9248, 0xBB31, 0x9249, 0xBB32, 0x924A, 0xBB33, 0x924B, 0xBB37, 0x924C, 0xBB39, 0x924D, 0xBB3A, 0x924E, 0xBB3F, + 0x924F, 0xBB40, 0x9250, 0xBB41, 0x9251, 0xBB42, 0x9252, 0xBB43, 0x9253, 0xBB46, 0x9254, 0xBB48, 0x9255, 0xBB4A, 0x9256, 0xBB4B, + 0x9257, 0xBB4C, 0x9258, 0xBB4E, 0x9259, 0xBB51, 0x925A, 0xBB52, 0x9261, 0xBB53, 0x9262, 0xBB55, 0x9263, 0xBB56, 0x9264, 0xBB57, + 0x9265, 0xBB59, 0x9266, 0xBB5A, 0x9267, 0xBB5B, 0x9268, 0xBB5C, 0x9269, 0xBB5D, 0x926A, 0xBB5E, 0x926B, 0xBB5F, 0x926C, 0xBB60, + 0x926D, 0xBB62, 0x926E, 0xBB64, 0x926F, 0xBB65, 0x9270, 0xBB66, 0x9271, 0xBB67, 0x9272, 0xBB68, 0x9273, 0xBB69, 0x9274, 0xBB6A, + 0x9275, 0xBB6B, 0x9276, 0xBB6D, 0x9277, 0xBB6E, 0x9278, 0xBB6F, 0x9279, 0xBB70, 0x927A, 0xBB71, 0x9281, 0xBB72, 0x9282, 0xBB73, + 0x9283, 0xBB74, 0x9284, 0xBB75, 0x9285, 0xBB76, 0x9286, 0xBB77, 0x9287, 0xBB78, 0x9288, 0xBB79, 0x9289, 0xBB7A, 0x928A, 0xBB7B, + 0x928B, 0xBB7C, 0x928C, 0xBB7D, 0x928D, 0xBB7E, 0x928E, 0xBB7F, 0x928F, 0xBB80, 0x9290, 0xBB81, 0x9291, 0xBB82, 0x9292, 0xBB83, + 0x9293, 0xBB84, 0x9294, 0xBB85, 0x9295, 0xBB86, 0x9296, 0xBB87, 0x9297, 0xBB89, 0x9298, 0xBB8A, 0x9299, 0xBB8B, 0x929A, 0xBB8D, + 0x929B, 0xBB8E, 0x929C, 0xBB8F, 0x929D, 0xBB91, 0x929E, 0xBB92, 0x929F, 0xBB93, 0x92A0, 0xBB94, 0x92A1, 0xBB95, 0x92A2, 0xBB96, + 0x92A3, 0xBB97, 0x92A4, 0xBB98, 0x92A5, 0xBB99, 0x92A6, 0xBB9A, 0x92A7, 0xBB9B, 0x92A8, 0xBB9C, 0x92A9, 0xBB9D, 0x92AA, 0xBB9E, + 0x92AB, 0xBB9F, 0x92AC, 0xBBA0, 0x92AD, 0xBBA1, 0x92AE, 0xBBA2, 0x92AF, 0xBBA3, 0x92B0, 0xBBA5, 0x92B1, 0xBBA6, 0x92B2, 0xBBA7, + 0x92B3, 0xBBA9, 0x92B4, 0xBBAA, 0x92B5, 0xBBAB, 0x92B6, 0xBBAD, 0x92B7, 0xBBAE, 0x92B8, 0xBBAF, 0x92B9, 0xBBB0, 0x92BA, 0xBBB1, + 0x92BB, 0xBBB2, 0x92BC, 0xBBB3, 0x92BD, 0xBBB5, 0x92BE, 0xBBB6, 0x92BF, 0xBBB8, 0x92C0, 0xBBB9, 0x92C1, 0xBBBA, 0x92C2, 0xBBBB, + 0x92C3, 0xBBBC, 0x92C4, 0xBBBD, 0x92C5, 0xBBBE, 0x92C6, 0xBBBF, 0x92C7, 0xBBC1, 0x92C8, 0xBBC2, 0x92C9, 0xBBC3, 0x92CA, 0xBBC5, + 0x92CB, 0xBBC6, 0x92CC, 0xBBC7, 0x92CD, 0xBBC9, 0x92CE, 0xBBCA, 0x92CF, 0xBBCB, 0x92D0, 0xBBCC, 0x92D1, 0xBBCD, 0x92D2, 0xBBCE, + 0x92D3, 0xBBCF, 0x92D4, 0xBBD1, 0x92D5, 0xBBD2, 0x92D6, 0xBBD4, 0x92D7, 0xBBD5, 0x92D8, 0xBBD6, 0x92D9, 0xBBD7, 0x92DA, 0xBBD8, + 0x92DB, 0xBBD9, 0x92DC, 0xBBDA, 0x92DD, 0xBBDB, 0x92DE, 0xBBDC, 0x92DF, 0xBBDD, 0x92E0, 0xBBDE, 0x92E1, 0xBBDF, 0x92E2, 0xBBE0, + 0x92E3, 0xBBE1, 0x92E4, 0xBBE2, 0x92E5, 0xBBE3, 0x92E6, 0xBBE4, 0x92E7, 0xBBE5, 0x92E8, 0xBBE6, 0x92E9, 0xBBE7, 0x92EA, 0xBBE8, + 0x92EB, 0xBBE9, 0x92EC, 0xBBEA, 0x92ED, 0xBBEB, 0x92EE, 0xBBEC, 0x92EF, 0xBBED, 0x92F0, 0xBBEE, 0x92F1, 0xBBEF, 0x92F2, 0xBBF0, + 0x92F3, 0xBBF1, 0x92F4, 0xBBF2, 0x92F5, 0xBBF3, 0x92F6, 0xBBF4, 0x92F7, 0xBBF5, 0x92F8, 0xBBF6, 0x92F9, 0xBBF7, 0x92FA, 0xBBFA, + 0x92FB, 0xBBFB, 0x92FC, 0xBBFD, 0x92FD, 0xBBFE, 0x92FE, 0xBC01, 0x9341, 0xBC03, 0x9342, 0xBC04, 0x9343, 0xBC05, 0x9344, 0xBC06, + 0x9345, 0xBC07, 0x9346, 0xBC0A, 0x9347, 0xBC0E, 0x9348, 0xBC10, 0x9349, 0xBC12, 0x934A, 0xBC13, 0x934B, 0xBC19, 0x934C, 0xBC1A, + 0x934D, 0xBC20, 0x934E, 0xBC21, 0x934F, 0xBC22, 0x9350, 0xBC23, 0x9351, 0xBC26, 0x9352, 0xBC28, 0x9353, 0xBC2A, 0x9354, 0xBC2B, + 0x9355, 0xBC2C, 0x9356, 0xBC2E, 0x9357, 0xBC2F, 0x9358, 0xBC32, 0x9359, 0xBC33, 0x935A, 0xBC35, 0x9361, 0xBC36, 0x9362, 0xBC37, + 0x9363, 0xBC39, 0x9364, 0xBC3A, 0x9365, 0xBC3B, 0x9366, 0xBC3C, 0x9367, 0xBC3D, 0x9368, 0xBC3E, 0x9369, 0xBC3F, 0x936A, 0xBC42, + 0x936B, 0xBC46, 0x936C, 0xBC47, 0x936D, 0xBC48, 0x936E, 0xBC4A, 0x936F, 0xBC4B, 0x9370, 0xBC4E, 0x9371, 0xBC4F, 0x9372, 0xBC51, + 0x9373, 0xBC52, 0x9374, 0xBC53, 0x9375, 0xBC54, 0x9376, 0xBC55, 0x9377, 0xBC56, 0x9378, 0xBC57, 0x9379, 0xBC58, 0x937A, 0xBC59, + 0x9381, 0xBC5A, 0x9382, 0xBC5B, 0x9383, 0xBC5C, 0x9384, 0xBC5E, 0x9385, 0xBC5F, 0x9386, 0xBC60, 0x9387, 0xBC61, 0x9388, 0xBC62, + 0x9389, 0xBC63, 0x938A, 0xBC64, 0x938B, 0xBC65, 0x938C, 0xBC66, 0x938D, 0xBC67, 0x938E, 0xBC68, 0x938F, 0xBC69, 0x9390, 0xBC6A, + 0x9391, 0xBC6B, 0x9392, 0xBC6C, 0x9393, 0xBC6D, 0x9394, 0xBC6E, 0x9395, 0xBC6F, 0x9396, 0xBC70, 0x9397, 0xBC71, 0x9398, 0xBC72, + 0x9399, 0xBC73, 0x939A, 0xBC74, 0x939B, 0xBC75, 0x939C, 0xBC76, 0x939D, 0xBC77, 0x939E, 0xBC78, 0x939F, 0xBC79, 0x93A0, 0xBC7A, + 0x93A1, 0xBC7B, 0x93A2, 0xBC7C, 0x93A3, 0xBC7D, 0x93A4, 0xBC7E, 0x93A5, 0xBC7F, 0x93A6, 0xBC80, 0x93A7, 0xBC81, 0x93A8, 0xBC82, + 0x93A9, 0xBC83, 0x93AA, 0xBC86, 0x93AB, 0xBC87, 0x93AC, 0xBC89, 0x93AD, 0xBC8A, 0x93AE, 0xBC8D, 0x93AF, 0xBC8F, 0x93B0, 0xBC90, + 0x93B1, 0xBC91, 0x93B2, 0xBC92, 0x93B3, 0xBC93, 0x93B4, 0xBC96, 0x93B5, 0xBC98, 0x93B6, 0xBC9B, 0x93B7, 0xBC9C, 0x93B8, 0xBC9D, + 0x93B9, 0xBC9E, 0x93BA, 0xBC9F, 0x93BB, 0xBCA2, 0x93BC, 0xBCA3, 0x93BD, 0xBCA5, 0x93BE, 0xBCA6, 0x93BF, 0xBCA9, 0x93C0, 0xBCAA, + 0x93C1, 0xBCAB, 0x93C2, 0xBCAC, 0x93C3, 0xBCAD, 0x93C4, 0xBCAE, 0x93C5, 0xBCAF, 0x93C6, 0xBCB2, 0x93C7, 0xBCB6, 0x93C8, 0xBCB7, + 0x93C9, 0xBCB8, 0x93CA, 0xBCB9, 0x93CB, 0xBCBA, 0x93CC, 0xBCBB, 0x93CD, 0xBCBE, 0x93CE, 0xBCBF, 0x93CF, 0xBCC1, 0x93D0, 0xBCC2, + 0x93D1, 0xBCC3, 0x93D2, 0xBCC5, 0x93D3, 0xBCC6, 0x93D4, 0xBCC7, 0x93D5, 0xBCC8, 0x93D6, 0xBCC9, 0x93D7, 0xBCCA, 0x93D8, 0xBCCB, + 0x93D9, 0xBCCC, 0x93DA, 0xBCCE, 0x93DB, 0xBCD2, 0x93DC, 0xBCD3, 0x93DD, 0xBCD4, 0x93DE, 0xBCD6, 0x93DF, 0xBCD7, 0x93E0, 0xBCD9, + 0x93E1, 0xBCDA, 0x93E2, 0xBCDB, 0x93E3, 0xBCDD, 0x93E4, 0xBCDE, 0x93E5, 0xBCDF, 0x93E6, 0xBCE0, 0x93E7, 0xBCE1, 0x93E8, 0xBCE2, + 0x93E9, 0xBCE3, 0x93EA, 0xBCE4, 0x93EB, 0xBCE5, 0x93EC, 0xBCE6, 0x93ED, 0xBCE7, 0x93EE, 0xBCE8, 0x93EF, 0xBCE9, 0x93F0, 0xBCEA, + 0x93F1, 0xBCEB, 0x93F2, 0xBCEC, 0x93F3, 0xBCED, 0x93F4, 0xBCEE, 0x93F5, 0xBCEF, 0x93F6, 0xBCF0, 0x93F7, 0xBCF1, 0x93F8, 0xBCF2, + 0x93F9, 0xBCF3, 0x93FA, 0xBCF7, 0x93FB, 0xBCF9, 0x93FC, 0xBCFA, 0x93FD, 0xBCFB, 0x93FE, 0xBCFD, 0x9441, 0xBCFE, 0x9442, 0xBCFF, + 0x9443, 0xBD00, 0x9444, 0xBD01, 0x9445, 0xBD02, 0x9446, 0xBD03, 0x9447, 0xBD06, 0x9448, 0xBD08, 0x9449, 0xBD0A, 0x944A, 0xBD0B, + 0x944B, 0xBD0C, 0x944C, 0xBD0D, 0x944D, 0xBD0E, 0x944E, 0xBD0F, 0x944F, 0xBD11, 0x9450, 0xBD12, 0x9451, 0xBD13, 0x9452, 0xBD15, + 0x9453, 0xBD16, 0x9454, 0xBD17, 0x9455, 0xBD18, 0x9456, 0xBD19, 0x9457, 0xBD1A, 0x9458, 0xBD1B, 0x9459, 0xBD1C, 0x945A, 0xBD1D, + 0x9461, 0xBD1E, 0x9462, 0xBD1F, 0x9463, 0xBD20, 0x9464, 0xBD21, 0x9465, 0xBD22, 0x9466, 0xBD23, 0x9467, 0xBD25, 0x9468, 0xBD26, + 0x9469, 0xBD27, 0x946A, 0xBD28, 0x946B, 0xBD29, 0x946C, 0xBD2A, 0x946D, 0xBD2B, 0x946E, 0xBD2D, 0x946F, 0xBD2E, 0x9470, 0xBD2F, + 0x9471, 0xBD30, 0x9472, 0xBD31, 0x9473, 0xBD32, 0x9474, 0xBD33, 0x9475, 0xBD34, 0x9476, 0xBD35, 0x9477, 0xBD36, 0x9478, 0xBD37, + 0x9479, 0xBD38, 0x947A, 0xBD39, 0x9481, 0xBD3A, 0x9482, 0xBD3B, 0x9483, 0xBD3C, 0x9484, 0xBD3D, 0x9485, 0xBD3E, 0x9486, 0xBD3F, + 0x9487, 0xBD41, 0x9488, 0xBD42, 0x9489, 0xBD43, 0x948A, 0xBD44, 0x948B, 0xBD45, 0x948C, 0xBD46, 0x948D, 0xBD47, 0x948E, 0xBD4A, + 0x948F, 0xBD4B, 0x9490, 0xBD4D, 0x9491, 0xBD4E, 0x9492, 0xBD4F, 0x9493, 0xBD51, 0x9494, 0xBD52, 0x9495, 0xBD53, 0x9496, 0xBD54, + 0x9497, 0xBD55, 0x9498, 0xBD56, 0x9499, 0xBD57, 0x949A, 0xBD5A, 0x949B, 0xBD5B, 0x949C, 0xBD5C, 0x949D, 0xBD5D, 0x949E, 0xBD5E, + 0x949F, 0xBD5F, 0x94A0, 0xBD60, 0x94A1, 0xBD61, 0x94A2, 0xBD62, 0x94A3, 0xBD63, 0x94A4, 0xBD65, 0x94A5, 0xBD66, 0x94A6, 0xBD67, + 0x94A7, 0xBD69, 0x94A8, 0xBD6A, 0x94A9, 0xBD6B, 0x94AA, 0xBD6C, 0x94AB, 0xBD6D, 0x94AC, 0xBD6E, 0x94AD, 0xBD6F, 0x94AE, 0xBD70, + 0x94AF, 0xBD71, 0x94B0, 0xBD72, 0x94B1, 0xBD73, 0x94B2, 0xBD74, 0x94B3, 0xBD75, 0x94B4, 0xBD76, 0x94B5, 0xBD77, 0x94B6, 0xBD78, + 0x94B7, 0xBD79, 0x94B8, 0xBD7A, 0x94B9, 0xBD7B, 0x94BA, 0xBD7C, 0x94BB, 0xBD7D, 0x94BC, 0xBD7E, 0x94BD, 0xBD7F, 0x94BE, 0xBD82, + 0x94BF, 0xBD83, 0x94C0, 0xBD85, 0x94C1, 0xBD86, 0x94C2, 0xBD8B, 0x94C3, 0xBD8C, 0x94C4, 0xBD8D, 0x94C5, 0xBD8E, 0x94C6, 0xBD8F, + 0x94C7, 0xBD92, 0x94C8, 0xBD94, 0x94C9, 0xBD96, 0x94CA, 0xBD97, 0x94CB, 0xBD98, 0x94CC, 0xBD9B, 0x94CD, 0xBD9D, 0x94CE, 0xBD9E, + 0x94CF, 0xBD9F, 0x94D0, 0xBDA0, 0x94D1, 0xBDA1, 0x94D2, 0xBDA2, 0x94D3, 0xBDA3, 0x94D4, 0xBDA5, 0x94D5, 0xBDA6, 0x94D6, 0xBDA7, + 0x94D7, 0xBDA8, 0x94D8, 0xBDA9, 0x94D9, 0xBDAA, 0x94DA, 0xBDAB, 0x94DB, 0xBDAC, 0x94DC, 0xBDAD, 0x94DD, 0xBDAE, 0x94DE, 0xBDAF, + 0x94DF, 0xBDB1, 0x94E0, 0xBDB2, 0x94E1, 0xBDB3, 0x94E2, 0xBDB4, 0x94E3, 0xBDB5, 0x94E4, 0xBDB6, 0x94E5, 0xBDB7, 0x94E6, 0xBDB9, + 0x94E7, 0xBDBA, 0x94E8, 0xBDBB, 0x94E9, 0xBDBC, 0x94EA, 0xBDBD, 0x94EB, 0xBDBE, 0x94EC, 0xBDBF, 0x94ED, 0xBDC0, 0x94EE, 0xBDC1, + 0x94EF, 0xBDC2, 0x94F0, 0xBDC3, 0x94F1, 0xBDC4, 0x94F2, 0xBDC5, 0x94F3, 0xBDC6, 0x94F4, 0xBDC7, 0x94F5, 0xBDC8, 0x94F6, 0xBDC9, + 0x94F7, 0xBDCA, 0x94F8, 0xBDCB, 0x94F9, 0xBDCC, 0x94FA, 0xBDCD, 0x94FB, 0xBDCE, 0x94FC, 0xBDCF, 0x94FD, 0xBDD0, 0x94FE, 0xBDD1, + 0x9541, 0xBDD2, 0x9542, 0xBDD3, 0x9543, 0xBDD6, 0x9544, 0xBDD7, 0x9545, 0xBDD9, 0x9546, 0xBDDA, 0x9547, 0xBDDB, 0x9548, 0xBDDD, + 0x9549, 0xBDDE, 0x954A, 0xBDDF, 0x954B, 0xBDE0, 0x954C, 0xBDE1, 0x954D, 0xBDE2, 0x954E, 0xBDE3, 0x954F, 0xBDE4, 0x9550, 0xBDE5, + 0x9551, 0xBDE6, 0x9552, 0xBDE7, 0x9553, 0xBDE8, 0x9554, 0xBDEA, 0x9555, 0xBDEB, 0x9556, 0xBDEC, 0x9557, 0xBDED, 0x9558, 0xBDEE, + 0x9559, 0xBDEF, 0x955A, 0xBDF1, 0x9561, 0xBDF2, 0x9562, 0xBDF3, 0x9563, 0xBDF5, 0x9564, 0xBDF6, 0x9565, 0xBDF7, 0x9566, 0xBDF9, + 0x9567, 0xBDFA, 0x9568, 0xBDFB, 0x9569, 0xBDFC, 0x956A, 0xBDFD, 0x956B, 0xBDFE, 0x956C, 0xBDFF, 0x956D, 0xBE01, 0x956E, 0xBE02, + 0x956F, 0xBE04, 0x9570, 0xBE06, 0x9571, 0xBE07, 0x9572, 0xBE08, 0x9573, 0xBE09, 0x9574, 0xBE0A, 0x9575, 0xBE0B, 0x9576, 0xBE0E, + 0x9577, 0xBE0F, 0x9578, 0xBE11, 0x9579, 0xBE12, 0x957A, 0xBE13, 0x9581, 0xBE15, 0x9582, 0xBE16, 0x9583, 0xBE17, 0x9584, 0xBE18, + 0x9585, 0xBE19, 0x9586, 0xBE1A, 0x9587, 0xBE1B, 0x9588, 0xBE1E, 0x9589, 0xBE20, 0x958A, 0xBE21, 0x958B, 0xBE22, 0x958C, 0xBE23, + 0x958D, 0xBE24, 0x958E, 0xBE25, 0x958F, 0xBE26, 0x9590, 0xBE27, 0x9591, 0xBE28, 0x9592, 0xBE29, 0x9593, 0xBE2A, 0x9594, 0xBE2B, + 0x9595, 0xBE2C, 0x9596, 0xBE2D, 0x9597, 0xBE2E, 0x9598, 0xBE2F, 0x9599, 0xBE30, 0x959A, 0xBE31, 0x959B, 0xBE32, 0x959C, 0xBE33, + 0x959D, 0xBE34, 0x959E, 0xBE35, 0x959F, 0xBE36, 0x95A0, 0xBE37, 0x95A1, 0xBE38, 0x95A2, 0xBE39, 0x95A3, 0xBE3A, 0x95A4, 0xBE3B, + 0x95A5, 0xBE3C, 0x95A6, 0xBE3D, 0x95A7, 0xBE3E, 0x95A8, 0xBE3F, 0x95A9, 0xBE40, 0x95AA, 0xBE41, 0x95AB, 0xBE42, 0x95AC, 0xBE43, + 0x95AD, 0xBE46, 0x95AE, 0xBE47, 0x95AF, 0xBE49, 0x95B0, 0xBE4A, 0x95B1, 0xBE4B, 0x95B2, 0xBE4D, 0x95B3, 0xBE4F, 0x95B4, 0xBE50, + 0x95B5, 0xBE51, 0x95B6, 0xBE52, 0x95B7, 0xBE53, 0x95B8, 0xBE56, 0x95B9, 0xBE58, 0x95BA, 0xBE5C, 0x95BB, 0xBE5D, 0x95BC, 0xBE5E, + 0x95BD, 0xBE5F, 0x95BE, 0xBE62, 0x95BF, 0xBE63, 0x95C0, 0xBE65, 0x95C1, 0xBE66, 0x95C2, 0xBE67, 0x95C3, 0xBE69, 0x95C4, 0xBE6B, + 0x95C5, 0xBE6C, 0x95C6, 0xBE6D, 0x95C7, 0xBE6E, 0x95C8, 0xBE6F, 0x95C9, 0xBE72, 0x95CA, 0xBE76, 0x95CB, 0xBE77, 0x95CC, 0xBE78, + 0x95CD, 0xBE79, 0x95CE, 0xBE7A, 0x95CF, 0xBE7E, 0x95D0, 0xBE7F, 0x95D1, 0xBE81, 0x95D2, 0xBE82, 0x95D3, 0xBE83, 0x95D4, 0xBE85, + 0x95D5, 0xBE86, 0x95D6, 0xBE87, 0x95D7, 0xBE88, 0x95D8, 0xBE89, 0x95D9, 0xBE8A, 0x95DA, 0xBE8B, 0x95DB, 0xBE8E, 0x95DC, 0xBE92, + 0x95DD, 0xBE93, 0x95DE, 0xBE94, 0x95DF, 0xBE95, 0x95E0, 0xBE96, 0x95E1, 0xBE97, 0x95E2, 0xBE9A, 0x95E3, 0xBE9B, 0x95E4, 0xBE9C, + 0x95E5, 0xBE9D, 0x95E6, 0xBE9E, 0x95E7, 0xBE9F, 0x95E8, 0xBEA0, 0x95E9, 0xBEA1, 0x95EA, 0xBEA2, 0x95EB, 0xBEA3, 0x95EC, 0xBEA4, + 0x95ED, 0xBEA5, 0x95EE, 0xBEA6, 0x95EF, 0xBEA7, 0x95F0, 0xBEA9, 0x95F1, 0xBEAA, 0x95F2, 0xBEAB, 0x95F3, 0xBEAC, 0x95F4, 0xBEAD, + 0x95F5, 0xBEAE, 0x95F6, 0xBEAF, 0x95F7, 0xBEB0, 0x95F8, 0xBEB1, 0x95F9, 0xBEB2, 0x95FA, 0xBEB3, 0x95FB, 0xBEB4, 0x95FC, 0xBEB5, + 0x95FD, 0xBEB6, 0x95FE, 0xBEB7, 0x9641, 0xBEB8, 0x9642, 0xBEB9, 0x9643, 0xBEBA, 0x9644, 0xBEBB, 0x9645, 0xBEBC, 0x9646, 0xBEBD, + 0x9647, 0xBEBE, 0x9648, 0xBEBF, 0x9649, 0xBEC0, 0x964A, 0xBEC1, 0x964B, 0xBEC2, 0x964C, 0xBEC3, 0x964D, 0xBEC4, 0x964E, 0xBEC5, + 0x964F, 0xBEC6, 0x9650, 0xBEC7, 0x9651, 0xBEC8, 0x9652, 0xBEC9, 0x9653, 0xBECA, 0x9654, 0xBECB, 0x9655, 0xBECC, 0x9656, 0xBECD, + 0x9657, 0xBECE, 0x9658, 0xBECF, 0x9659, 0xBED2, 0x965A, 0xBED3, 0x9661, 0xBED5, 0x9662, 0xBED6, 0x9663, 0xBED9, 0x9664, 0xBEDA, + 0x9665, 0xBEDB, 0x9666, 0xBEDC, 0x9667, 0xBEDD, 0x9668, 0xBEDE, 0x9669, 0xBEDF, 0x966A, 0xBEE1, 0x966B, 0xBEE2, 0x966C, 0xBEE6, + 0x966D, 0xBEE7, 0x966E, 0xBEE8, 0x966F, 0xBEE9, 0x9670, 0xBEEA, 0x9671, 0xBEEB, 0x9672, 0xBEED, 0x9673, 0xBEEE, 0x9674, 0xBEEF, + 0x9675, 0xBEF0, 0x9676, 0xBEF1, 0x9677, 0xBEF2, 0x9678, 0xBEF3, 0x9679, 0xBEF4, 0x967A, 0xBEF5, 0x9681, 0xBEF6, 0x9682, 0xBEF7, + 0x9683, 0xBEF8, 0x9684, 0xBEF9, 0x9685, 0xBEFA, 0x9686, 0xBEFB, 0x9687, 0xBEFC, 0x9688, 0xBEFD, 0x9689, 0xBEFE, 0x968A, 0xBEFF, + 0x968B, 0xBF00, 0x968C, 0xBF02, 0x968D, 0xBF03, 0x968E, 0xBF04, 0x968F, 0xBF05, 0x9690, 0xBF06, 0x9691, 0xBF07, 0x9692, 0xBF0A, + 0x9693, 0xBF0B, 0x9694, 0xBF0C, 0x9695, 0xBF0D, 0x9696, 0xBF0E, 0x9697, 0xBF0F, 0x9698, 0xBF10, 0x9699, 0xBF11, 0x969A, 0xBF12, + 0x969B, 0xBF13, 0x969C, 0xBF14, 0x969D, 0xBF15, 0x969E, 0xBF16, 0x969F, 0xBF17, 0x96A0, 0xBF1A, 0x96A1, 0xBF1E, 0x96A2, 0xBF1F, + 0x96A3, 0xBF20, 0x96A4, 0xBF21, 0x96A5, 0xBF22, 0x96A6, 0xBF23, 0x96A7, 0xBF24, 0x96A8, 0xBF25, 0x96A9, 0xBF26, 0x96AA, 0xBF27, + 0x96AB, 0xBF28, 0x96AC, 0xBF29, 0x96AD, 0xBF2A, 0x96AE, 0xBF2B, 0x96AF, 0xBF2C, 0x96B0, 0xBF2D, 0x96B1, 0xBF2E, 0x96B2, 0xBF2F, + 0x96B3, 0xBF30, 0x96B4, 0xBF31, 0x96B5, 0xBF32, 0x96B6, 0xBF33, 0x96B7, 0xBF34, 0x96B8, 0xBF35, 0x96B9, 0xBF36, 0x96BA, 0xBF37, + 0x96BB, 0xBF38, 0x96BC, 0xBF39, 0x96BD, 0xBF3A, 0x96BE, 0xBF3B, 0x96BF, 0xBF3C, 0x96C0, 0xBF3D, 0x96C1, 0xBF3E, 0x96C2, 0xBF3F, + 0x96C3, 0xBF42, 0x96C4, 0xBF43, 0x96C5, 0xBF45, 0x96C6, 0xBF46, 0x96C7, 0xBF47, 0x96C8, 0xBF49, 0x96C9, 0xBF4A, 0x96CA, 0xBF4B, + 0x96CB, 0xBF4C, 0x96CC, 0xBF4D, 0x96CD, 0xBF4E, 0x96CE, 0xBF4F, 0x96CF, 0xBF52, 0x96D0, 0xBF53, 0x96D1, 0xBF54, 0x96D2, 0xBF56, + 0x96D3, 0xBF57, 0x96D4, 0xBF58, 0x96D5, 0xBF59, 0x96D6, 0xBF5A, 0x96D7, 0xBF5B, 0x96D8, 0xBF5C, 0x96D9, 0xBF5D, 0x96DA, 0xBF5E, + 0x96DB, 0xBF5F, 0x96DC, 0xBF60, 0x96DD, 0xBF61, 0x96DE, 0xBF62, 0x96DF, 0xBF63, 0x96E0, 0xBF64, 0x96E1, 0xBF65, 0x96E2, 0xBF66, + 0x96E3, 0xBF67, 0x96E4, 0xBF68, 0x96E5, 0xBF69, 0x96E6, 0xBF6A, 0x96E7, 0xBF6B, 0x96E8, 0xBF6C, 0x96E9, 0xBF6D, 0x96EA, 0xBF6E, + 0x96EB, 0xBF6F, 0x96EC, 0xBF70, 0x96ED, 0xBF71, 0x96EE, 0xBF72, 0x96EF, 0xBF73, 0x96F0, 0xBF74, 0x96F1, 0xBF75, 0x96F2, 0xBF76, + 0x96F3, 0xBF77, 0x96F4, 0xBF78, 0x96F5, 0xBF79, 0x96F6, 0xBF7A, 0x96F7, 0xBF7B, 0x96F8, 0xBF7C, 0x96F9, 0xBF7D, 0x96FA, 0xBF7E, + 0x96FB, 0xBF7F, 0x96FC, 0xBF80, 0x96FD, 0xBF81, 0x96FE, 0xBF82, 0x9741, 0xBF83, 0x9742, 0xBF84, 0x9743, 0xBF85, 0x9744, 0xBF86, + 0x9745, 0xBF87, 0x9746, 0xBF88, 0x9747, 0xBF89, 0x9748, 0xBF8A, 0x9749, 0xBF8B, 0x974A, 0xBF8C, 0x974B, 0xBF8D, 0x974C, 0xBF8E, + 0x974D, 0xBF8F, 0x974E, 0xBF90, 0x974F, 0xBF91, 0x9750, 0xBF92, 0x9751, 0xBF93, 0x9752, 0xBF95, 0x9753, 0xBF96, 0x9754, 0xBF97, + 0x9755, 0xBF98, 0x9756, 0xBF99, 0x9757, 0xBF9A, 0x9758, 0xBF9B, 0x9759, 0xBF9C, 0x975A, 0xBF9D, 0x9761, 0xBF9E, 0x9762, 0xBF9F, + 0x9763, 0xBFA0, 0x9764, 0xBFA1, 0x9765, 0xBFA2, 0x9766, 0xBFA3, 0x9767, 0xBFA4, 0x9768, 0xBFA5, 0x9769, 0xBFA6, 0x976A, 0xBFA7, + 0x976B, 0xBFA8, 0x976C, 0xBFA9, 0x976D, 0xBFAA, 0x976E, 0xBFAB, 0x976F, 0xBFAC, 0x9770, 0xBFAD, 0x9771, 0xBFAE, 0x9772, 0xBFAF, + 0x9773, 0xBFB1, 0x9774, 0xBFB2, 0x9775, 0xBFB3, 0x9776, 0xBFB4, 0x9777, 0xBFB5, 0x9778, 0xBFB6, 0x9779, 0xBFB7, 0x977A, 0xBFB8, + 0x9781, 0xBFB9, 0x9782, 0xBFBA, 0x9783, 0xBFBB, 0x9784, 0xBFBC, 0x9785, 0xBFBD, 0x9786, 0xBFBE, 0x9787, 0xBFBF, 0x9788, 0xBFC0, + 0x9789, 0xBFC1, 0x978A, 0xBFC2, 0x978B, 0xBFC3, 0x978C, 0xBFC4, 0x978D, 0xBFC6, 0x978E, 0xBFC7, 0x978F, 0xBFC8, 0x9790, 0xBFC9, + 0x9791, 0xBFCA, 0x9792, 0xBFCB, 0x9793, 0xBFCE, 0x9794, 0xBFCF, 0x9795, 0xBFD1, 0x9796, 0xBFD2, 0x9797, 0xBFD3, 0x9798, 0xBFD5, + 0x9799, 0xBFD6, 0x979A, 0xBFD7, 0x979B, 0xBFD8, 0x979C, 0xBFD9, 0x979D, 0xBFDA, 0x979E, 0xBFDB, 0x979F, 0xBFDD, 0x97A0, 0xBFDE, + 0x97A1, 0xBFE0, 0x97A2, 0xBFE2, 0x97A3, 0xBFE3, 0x97A4, 0xBFE4, 0x97A5, 0xBFE5, 0x97A6, 0xBFE6, 0x97A7, 0xBFE7, 0x97A8, 0xBFE8, + 0x97A9, 0xBFE9, 0x97AA, 0xBFEA, 0x97AB, 0xBFEB, 0x97AC, 0xBFEC, 0x97AD, 0xBFED, 0x97AE, 0xBFEE, 0x97AF, 0xBFEF, 0x97B0, 0xBFF0, + 0x97B1, 0xBFF1, 0x97B2, 0xBFF2, 0x97B3, 0xBFF3, 0x97B4, 0xBFF4, 0x97B5, 0xBFF5, 0x97B6, 0xBFF6, 0x97B7, 0xBFF7, 0x97B8, 0xBFF8, + 0x97B9, 0xBFF9, 0x97BA, 0xBFFA, 0x97BB, 0xBFFB, 0x97BC, 0xBFFC, 0x97BD, 0xBFFD, 0x97BE, 0xBFFE, 0x97BF, 0xBFFF, 0x97C0, 0xC000, + 0x97C1, 0xC001, 0x97C2, 0xC002, 0x97C3, 0xC003, 0x97C4, 0xC004, 0x97C5, 0xC005, 0x97C6, 0xC006, 0x97C7, 0xC007, 0x97C8, 0xC008, + 0x97C9, 0xC009, 0x97CA, 0xC00A, 0x97CB, 0xC00B, 0x97CC, 0xC00C, 0x97CD, 0xC00D, 0x97CE, 0xC00E, 0x97CF, 0xC00F, 0x97D0, 0xC010, + 0x97D1, 0xC011, 0x97D2, 0xC012, 0x97D3, 0xC013, 0x97D4, 0xC014, 0x97D5, 0xC015, 0x97D6, 0xC016, 0x97D7, 0xC017, 0x97D8, 0xC018, + 0x97D9, 0xC019, 0x97DA, 0xC01A, 0x97DB, 0xC01B, 0x97DC, 0xC01C, 0x97DD, 0xC01D, 0x97DE, 0xC01E, 0x97DF, 0xC01F, 0x97E0, 0xC020, + 0x97E1, 0xC021, 0x97E2, 0xC022, 0x97E3, 0xC023, 0x97E4, 0xC024, 0x97E5, 0xC025, 0x97E6, 0xC026, 0x97E7, 0xC027, 0x97E8, 0xC028, + 0x97E9, 0xC029, 0x97EA, 0xC02A, 0x97EB, 0xC02B, 0x97EC, 0xC02C, 0x97ED, 0xC02D, 0x97EE, 0xC02E, 0x97EF, 0xC02F, 0x97F0, 0xC030, + 0x97F1, 0xC031, 0x97F2, 0xC032, 0x97F3, 0xC033, 0x97F4, 0xC034, 0x97F5, 0xC035, 0x97F6, 0xC036, 0x97F7, 0xC037, 0x97F8, 0xC038, + 0x97F9, 0xC039, 0x97FA, 0xC03A, 0x97FB, 0xC03B, 0x97FC, 0xC03D, 0x97FD, 0xC03E, 0x97FE, 0xC03F, 0x9841, 0xC040, 0x9842, 0xC041, + 0x9843, 0xC042, 0x9844, 0xC043, 0x9845, 0xC044, 0x9846, 0xC045, 0x9847, 0xC046, 0x9848, 0xC047, 0x9849, 0xC048, 0x984A, 0xC049, + 0x984B, 0xC04A, 0x984C, 0xC04B, 0x984D, 0xC04C, 0x984E, 0xC04D, 0x984F, 0xC04E, 0x9850, 0xC04F, 0x9851, 0xC050, 0x9852, 0xC052, + 0x9853, 0xC053, 0x9854, 0xC054, 0x9855, 0xC055, 0x9856, 0xC056, 0x9857, 0xC057, 0x9858, 0xC059, 0x9859, 0xC05A, 0x985A, 0xC05B, + 0x9861, 0xC05D, 0x9862, 0xC05E, 0x9863, 0xC05F, 0x9864, 0xC061, 0x9865, 0xC062, 0x9866, 0xC063, 0x9867, 0xC064, 0x9868, 0xC065, + 0x9869, 0xC066, 0x986A, 0xC067, 0x986B, 0xC06A, 0x986C, 0xC06B, 0x986D, 0xC06C, 0x986E, 0xC06D, 0x986F, 0xC06E, 0x9870, 0xC06F, + 0x9871, 0xC070, 0x9872, 0xC071, 0x9873, 0xC072, 0x9874, 0xC073, 0x9875, 0xC074, 0x9876, 0xC075, 0x9877, 0xC076, 0x9878, 0xC077, + 0x9879, 0xC078, 0x987A, 0xC079, 0x9881, 0xC07A, 0x9882, 0xC07B, 0x9883, 0xC07C, 0x9884, 0xC07D, 0x9885, 0xC07E, 0x9886, 0xC07F, + 0x9887, 0xC080, 0x9888, 0xC081, 0x9889, 0xC082, 0x988A, 0xC083, 0x988B, 0xC084, 0x988C, 0xC085, 0x988D, 0xC086, 0x988E, 0xC087, + 0x988F, 0xC088, 0x9890, 0xC089, 0x9891, 0xC08A, 0x9892, 0xC08B, 0x9893, 0xC08C, 0x9894, 0xC08D, 0x9895, 0xC08E, 0x9896, 0xC08F, + 0x9897, 0xC092, 0x9898, 0xC093, 0x9899, 0xC095, 0x989A, 0xC096, 0x989B, 0xC097, 0x989C, 0xC099, 0x989D, 0xC09A, 0x989E, 0xC09B, + 0x989F, 0xC09C, 0x98A0, 0xC09D, 0x98A1, 0xC09E, 0x98A2, 0xC09F, 0x98A3, 0xC0A2, 0x98A4, 0xC0A4, 0x98A5, 0xC0A6, 0x98A6, 0xC0A7, + 0x98A7, 0xC0A8, 0x98A8, 0xC0A9, 0x98A9, 0xC0AA, 0x98AA, 0xC0AB, 0x98AB, 0xC0AE, 0x98AC, 0xC0B1, 0x98AD, 0xC0B2, 0x98AE, 0xC0B7, + 0x98AF, 0xC0B8, 0x98B0, 0xC0B9, 0x98B1, 0xC0BA, 0x98B2, 0xC0BB, 0x98B3, 0xC0BE, 0x98B4, 0xC0C2, 0x98B5, 0xC0C3, 0x98B6, 0xC0C4, + 0x98B7, 0xC0C6, 0x98B8, 0xC0C7, 0x98B9, 0xC0CA, 0x98BA, 0xC0CB, 0x98BB, 0xC0CD, 0x98BC, 0xC0CE, 0x98BD, 0xC0CF, 0x98BE, 0xC0D1, + 0x98BF, 0xC0D2, 0x98C0, 0xC0D3, 0x98C1, 0xC0D4, 0x98C2, 0xC0D5, 0x98C3, 0xC0D6, 0x98C4, 0xC0D7, 0x98C5, 0xC0DA, 0x98C6, 0xC0DE, + 0x98C7, 0xC0DF, 0x98C8, 0xC0E0, 0x98C9, 0xC0E1, 0x98CA, 0xC0E2, 0x98CB, 0xC0E3, 0x98CC, 0xC0E6, 0x98CD, 0xC0E7, 0x98CE, 0xC0E9, + 0x98CF, 0xC0EA, 0x98D0, 0xC0EB, 0x98D1, 0xC0ED, 0x98D2, 0xC0EE, 0x98D3, 0xC0EF, 0x98D4, 0xC0F0, 0x98D5, 0xC0F1, 0x98D6, 0xC0F2, + 0x98D7, 0xC0F3, 0x98D8, 0xC0F6, 0x98D9, 0xC0F8, 0x98DA, 0xC0FA, 0x98DB, 0xC0FB, 0x98DC, 0xC0FC, 0x98DD, 0xC0FD, 0x98DE, 0xC0FE, + 0x98DF, 0xC0FF, 0x98E0, 0xC101, 0x98E1, 0xC102, 0x98E2, 0xC103, 0x98E3, 0xC105, 0x98E4, 0xC106, 0x98E5, 0xC107, 0x98E6, 0xC109, + 0x98E7, 0xC10A, 0x98E8, 0xC10B, 0x98E9, 0xC10C, 0x98EA, 0xC10D, 0x98EB, 0xC10E, 0x98EC, 0xC10F, 0x98ED, 0xC111, 0x98EE, 0xC112, + 0x98EF, 0xC113, 0x98F0, 0xC114, 0x98F1, 0xC116, 0x98F2, 0xC117, 0x98F3, 0xC118, 0x98F4, 0xC119, 0x98F5, 0xC11A, 0x98F6, 0xC11B, + 0x98F7, 0xC121, 0x98F8, 0xC122, 0x98F9, 0xC125, 0x98FA, 0xC128, 0x98FB, 0xC129, 0x98FC, 0xC12A, 0x98FD, 0xC12B, 0x98FE, 0xC12E, + 0x9941, 0xC132, 0x9942, 0xC133, 0x9943, 0xC134, 0x9944, 0xC135, 0x9945, 0xC137, 0x9946, 0xC13A, 0x9947, 0xC13B, 0x9948, 0xC13D, + 0x9949, 0xC13E, 0x994A, 0xC13F, 0x994B, 0xC141, 0x994C, 0xC142, 0x994D, 0xC143, 0x994E, 0xC144, 0x994F, 0xC145, 0x9950, 0xC146, + 0x9951, 0xC147, 0x9952, 0xC14A, 0x9953, 0xC14E, 0x9954, 0xC14F, 0x9955, 0xC150, 0x9956, 0xC151, 0x9957, 0xC152, 0x9958, 0xC153, + 0x9959, 0xC156, 0x995A, 0xC157, 0x9961, 0xC159, 0x9962, 0xC15A, 0x9963, 0xC15B, 0x9964, 0xC15D, 0x9965, 0xC15E, 0x9966, 0xC15F, + 0x9967, 0xC160, 0x9968, 0xC161, 0x9969, 0xC162, 0x996A, 0xC163, 0x996B, 0xC166, 0x996C, 0xC16A, 0x996D, 0xC16B, 0x996E, 0xC16C, + 0x996F, 0xC16D, 0x9970, 0xC16E, 0x9971, 0xC16F, 0x9972, 0xC171, 0x9973, 0xC172, 0x9974, 0xC173, 0x9975, 0xC175, 0x9976, 0xC176, + 0x9977, 0xC177, 0x9978, 0xC179, 0x9979, 0xC17A, 0x997A, 0xC17B, 0x9981, 0xC17C, 0x9982, 0xC17D, 0x9983, 0xC17E, 0x9984, 0xC17F, + 0x9985, 0xC180, 0x9986, 0xC181, 0x9987, 0xC182, 0x9988, 0xC183, 0x9989, 0xC184, 0x998A, 0xC186, 0x998B, 0xC187, 0x998C, 0xC188, + 0x998D, 0xC189, 0x998E, 0xC18A, 0x998F, 0xC18B, 0x9990, 0xC18F, 0x9991, 0xC191, 0x9992, 0xC192, 0x9993, 0xC193, 0x9994, 0xC195, + 0x9995, 0xC197, 0x9996, 0xC198, 0x9997, 0xC199, 0x9998, 0xC19A, 0x9999, 0xC19B, 0x999A, 0xC19E, 0x999B, 0xC1A0, 0x999C, 0xC1A2, + 0x999D, 0xC1A3, 0x999E, 0xC1A4, 0x999F, 0xC1A6, 0x99A0, 0xC1A7, 0x99A1, 0xC1AA, 0x99A2, 0xC1AB, 0x99A3, 0xC1AD, 0x99A4, 0xC1AE, + 0x99A5, 0xC1AF, 0x99A6, 0xC1B1, 0x99A7, 0xC1B2, 0x99A8, 0xC1B3, 0x99A9, 0xC1B4, 0x99AA, 0xC1B5, 0x99AB, 0xC1B6, 0x99AC, 0xC1B7, + 0x99AD, 0xC1B8, 0x99AE, 0xC1B9, 0x99AF, 0xC1BA, 0x99B0, 0xC1BB, 0x99B1, 0xC1BC, 0x99B2, 0xC1BE, 0x99B3, 0xC1BF, 0x99B4, 0xC1C0, + 0x99B5, 0xC1C1, 0x99B6, 0xC1C2, 0x99B7, 0xC1C3, 0x99B8, 0xC1C5, 0x99B9, 0xC1C6, 0x99BA, 0xC1C7, 0x99BB, 0xC1C9, 0x99BC, 0xC1CA, + 0x99BD, 0xC1CB, 0x99BE, 0xC1CD, 0x99BF, 0xC1CE, 0x99C0, 0xC1CF, 0x99C1, 0xC1D0, 0x99C2, 0xC1D1, 0x99C3, 0xC1D2, 0x99C4, 0xC1D3, + 0x99C5, 0xC1D5, 0x99C6, 0xC1D6, 0x99C7, 0xC1D9, 0x99C8, 0xC1DA, 0x99C9, 0xC1DB, 0x99CA, 0xC1DC, 0x99CB, 0xC1DD, 0x99CC, 0xC1DE, + 0x99CD, 0xC1DF, 0x99CE, 0xC1E1, 0x99CF, 0xC1E2, 0x99D0, 0xC1E3, 0x99D1, 0xC1E5, 0x99D2, 0xC1E6, 0x99D3, 0xC1E7, 0x99D4, 0xC1E9, + 0x99D5, 0xC1EA, 0x99D6, 0xC1EB, 0x99D7, 0xC1EC, 0x99D8, 0xC1ED, 0x99D9, 0xC1EE, 0x99DA, 0xC1EF, 0x99DB, 0xC1F2, 0x99DC, 0xC1F4, + 0x99DD, 0xC1F5, 0x99DE, 0xC1F6, 0x99DF, 0xC1F7, 0x99E0, 0xC1F8, 0x99E1, 0xC1F9, 0x99E2, 0xC1FA, 0x99E3, 0xC1FB, 0x99E4, 0xC1FE, + 0x99E5, 0xC1FF, 0x99E6, 0xC201, 0x99E7, 0xC202, 0x99E8, 0xC203, 0x99E9, 0xC205, 0x99EA, 0xC206, 0x99EB, 0xC207, 0x99EC, 0xC208, + 0x99ED, 0xC209, 0x99EE, 0xC20A, 0x99EF, 0xC20B, 0x99F0, 0xC20E, 0x99F1, 0xC210, 0x99F2, 0xC212, 0x99F3, 0xC213, 0x99F4, 0xC214, + 0x99F5, 0xC215, 0x99F6, 0xC216, 0x99F7, 0xC217, 0x99F8, 0xC21A, 0x99F9, 0xC21B, 0x99FA, 0xC21D, 0x99FB, 0xC21E, 0x99FC, 0xC221, + 0x99FD, 0xC222, 0x99FE, 0xC223, 0x9A41, 0xC224, 0x9A42, 0xC225, 0x9A43, 0xC226, 0x9A44, 0xC227, 0x9A45, 0xC22A, 0x9A46, 0xC22C, + 0x9A47, 0xC22E, 0x9A48, 0xC230, 0x9A49, 0xC233, 0x9A4A, 0xC235, 0x9A4B, 0xC236, 0x9A4C, 0xC237, 0x9A4D, 0xC238, 0x9A4E, 0xC239, + 0x9A4F, 0xC23A, 0x9A50, 0xC23B, 0x9A51, 0xC23C, 0x9A52, 0xC23D, 0x9A53, 0xC23E, 0x9A54, 0xC23F, 0x9A55, 0xC240, 0x9A56, 0xC241, + 0x9A57, 0xC242, 0x9A58, 0xC243, 0x9A59, 0xC244, 0x9A5A, 0xC245, 0x9A61, 0xC246, 0x9A62, 0xC247, 0x9A63, 0xC249, 0x9A64, 0xC24A, + 0x9A65, 0xC24B, 0x9A66, 0xC24C, 0x9A67, 0xC24D, 0x9A68, 0xC24E, 0x9A69, 0xC24F, 0x9A6A, 0xC252, 0x9A6B, 0xC253, 0x9A6C, 0xC255, + 0x9A6D, 0xC256, 0x9A6E, 0xC257, 0x9A6F, 0xC259, 0x9A70, 0xC25A, 0x9A71, 0xC25B, 0x9A72, 0xC25C, 0x9A73, 0xC25D, 0x9A74, 0xC25E, + 0x9A75, 0xC25F, 0x9A76, 0xC261, 0x9A77, 0xC262, 0x9A78, 0xC263, 0x9A79, 0xC264, 0x9A7A, 0xC266, 0x9A81, 0xC267, 0x9A82, 0xC268, + 0x9A83, 0xC269, 0x9A84, 0xC26A, 0x9A85, 0xC26B, 0x9A86, 0xC26E, 0x9A87, 0xC26F, 0x9A88, 0xC271, 0x9A89, 0xC272, 0x9A8A, 0xC273, + 0x9A8B, 0xC275, 0x9A8C, 0xC276, 0x9A8D, 0xC277, 0x9A8E, 0xC278, 0x9A8F, 0xC279, 0x9A90, 0xC27A, 0x9A91, 0xC27B, 0x9A92, 0xC27E, + 0x9A93, 0xC280, 0x9A94, 0xC282, 0x9A95, 0xC283, 0x9A96, 0xC284, 0x9A97, 0xC285, 0x9A98, 0xC286, 0x9A99, 0xC287, 0x9A9A, 0xC28A, + 0x9A9B, 0xC28B, 0x9A9C, 0xC28C, 0x9A9D, 0xC28D, 0x9A9E, 0xC28E, 0x9A9F, 0xC28F, 0x9AA0, 0xC291, 0x9AA1, 0xC292, 0x9AA2, 0xC293, + 0x9AA3, 0xC294, 0x9AA4, 0xC295, 0x9AA5, 0xC296, 0x9AA6, 0xC297, 0x9AA7, 0xC299, 0x9AA8, 0xC29A, 0x9AA9, 0xC29C, 0x9AAA, 0xC29E, + 0x9AAB, 0xC29F, 0x9AAC, 0xC2A0, 0x9AAD, 0xC2A1, 0x9AAE, 0xC2A2, 0x9AAF, 0xC2A3, 0x9AB0, 0xC2A6, 0x9AB1, 0xC2A7, 0x9AB2, 0xC2A9, + 0x9AB3, 0xC2AA, 0x9AB4, 0xC2AB, 0x9AB5, 0xC2AE, 0x9AB6, 0xC2AF, 0x9AB7, 0xC2B0, 0x9AB8, 0xC2B1, 0x9AB9, 0xC2B2, 0x9ABA, 0xC2B3, + 0x9ABB, 0xC2B6, 0x9ABC, 0xC2B8, 0x9ABD, 0xC2BA, 0x9ABE, 0xC2BB, 0x9ABF, 0xC2BC, 0x9AC0, 0xC2BD, 0x9AC1, 0xC2BE, 0x9AC2, 0xC2BF, + 0x9AC3, 0xC2C0, 0x9AC4, 0xC2C1, 0x9AC5, 0xC2C2, 0x9AC6, 0xC2C3, 0x9AC7, 0xC2C4, 0x9AC8, 0xC2C5, 0x9AC9, 0xC2C6, 0x9ACA, 0xC2C7, + 0x9ACB, 0xC2C8, 0x9ACC, 0xC2C9, 0x9ACD, 0xC2CA, 0x9ACE, 0xC2CB, 0x9ACF, 0xC2CC, 0x9AD0, 0xC2CD, 0x9AD1, 0xC2CE, 0x9AD2, 0xC2CF, + 0x9AD3, 0xC2D0, 0x9AD4, 0xC2D1, 0x9AD5, 0xC2D2, 0x9AD6, 0xC2D3, 0x9AD7, 0xC2D4, 0x9AD8, 0xC2D5, 0x9AD9, 0xC2D6, 0x9ADA, 0xC2D7, + 0x9ADB, 0xC2D8, 0x9ADC, 0xC2D9, 0x9ADD, 0xC2DA, 0x9ADE, 0xC2DB, 0x9ADF, 0xC2DE, 0x9AE0, 0xC2DF, 0x9AE1, 0xC2E1, 0x9AE2, 0xC2E2, + 0x9AE3, 0xC2E5, 0x9AE4, 0xC2E6, 0x9AE5, 0xC2E7, 0x9AE6, 0xC2E8, 0x9AE7, 0xC2E9, 0x9AE8, 0xC2EA, 0x9AE9, 0xC2EE, 0x9AEA, 0xC2F0, + 0x9AEB, 0xC2F2, 0x9AEC, 0xC2F3, 0x9AED, 0xC2F4, 0x9AEE, 0xC2F5, 0x9AEF, 0xC2F7, 0x9AF0, 0xC2FA, 0x9AF1, 0xC2FD, 0x9AF2, 0xC2FE, + 0x9AF3, 0xC2FF, 0x9AF4, 0xC301, 0x9AF5, 0xC302, 0x9AF6, 0xC303, 0x9AF7, 0xC304, 0x9AF8, 0xC305, 0x9AF9, 0xC306, 0x9AFA, 0xC307, + 0x9AFB, 0xC30A, 0x9AFC, 0xC30B, 0x9AFD, 0xC30E, 0x9AFE, 0xC30F, 0x9B41, 0xC310, 0x9B42, 0xC311, 0x9B43, 0xC312, 0x9B44, 0xC316, + 0x9B45, 0xC317, 0x9B46, 0xC319, 0x9B47, 0xC31A, 0x9B48, 0xC31B, 0x9B49, 0xC31D, 0x9B4A, 0xC31E, 0x9B4B, 0xC31F, 0x9B4C, 0xC320, + 0x9B4D, 0xC321, 0x9B4E, 0xC322, 0x9B4F, 0xC323, 0x9B50, 0xC326, 0x9B51, 0xC327, 0x9B52, 0xC32A, 0x9B53, 0xC32B, 0x9B54, 0xC32C, + 0x9B55, 0xC32D, 0x9B56, 0xC32E, 0x9B57, 0xC32F, 0x9B58, 0xC330, 0x9B59, 0xC331, 0x9B5A, 0xC332, 0x9B61, 0xC333, 0x9B62, 0xC334, + 0x9B63, 0xC335, 0x9B64, 0xC336, 0x9B65, 0xC337, 0x9B66, 0xC338, 0x9B67, 0xC339, 0x9B68, 0xC33A, 0x9B69, 0xC33B, 0x9B6A, 0xC33C, + 0x9B6B, 0xC33D, 0x9B6C, 0xC33E, 0x9B6D, 0xC33F, 0x9B6E, 0xC340, 0x9B6F, 0xC341, 0x9B70, 0xC342, 0x9B71, 0xC343, 0x9B72, 0xC344, + 0x9B73, 0xC346, 0x9B74, 0xC347, 0x9B75, 0xC348, 0x9B76, 0xC349, 0x9B77, 0xC34A, 0x9B78, 0xC34B, 0x9B79, 0xC34C, 0x9B7A, 0xC34D, + 0x9B81, 0xC34E, 0x9B82, 0xC34F, 0x9B83, 0xC350, 0x9B84, 0xC351, 0x9B85, 0xC352, 0x9B86, 0xC353, 0x9B87, 0xC354, 0x9B88, 0xC355, + 0x9B89, 0xC356, 0x9B8A, 0xC357, 0x9B8B, 0xC358, 0x9B8C, 0xC359, 0x9B8D, 0xC35A, 0x9B8E, 0xC35B, 0x9B8F, 0xC35C, 0x9B90, 0xC35D, + 0x9B91, 0xC35E, 0x9B92, 0xC35F, 0x9B93, 0xC360, 0x9B94, 0xC361, 0x9B95, 0xC362, 0x9B96, 0xC363, 0x9B97, 0xC364, 0x9B98, 0xC365, + 0x9B99, 0xC366, 0x9B9A, 0xC367, 0x9B9B, 0xC36A, 0x9B9C, 0xC36B, 0x9B9D, 0xC36D, 0x9B9E, 0xC36E, 0x9B9F, 0xC36F, 0x9BA0, 0xC371, + 0x9BA1, 0xC373, 0x9BA2, 0xC374, 0x9BA3, 0xC375, 0x9BA4, 0xC376, 0x9BA5, 0xC377, 0x9BA6, 0xC37A, 0x9BA7, 0xC37B, 0x9BA8, 0xC37E, + 0x9BA9, 0xC37F, 0x9BAA, 0xC380, 0x9BAB, 0xC381, 0x9BAC, 0xC382, 0x9BAD, 0xC383, 0x9BAE, 0xC385, 0x9BAF, 0xC386, 0x9BB0, 0xC387, + 0x9BB1, 0xC389, 0x9BB2, 0xC38A, 0x9BB3, 0xC38B, 0x9BB4, 0xC38D, 0x9BB5, 0xC38E, 0x9BB6, 0xC38F, 0x9BB7, 0xC390, 0x9BB8, 0xC391, + 0x9BB9, 0xC392, 0x9BBA, 0xC393, 0x9BBB, 0xC394, 0x9BBC, 0xC395, 0x9BBD, 0xC396, 0x9BBE, 0xC397, 0x9BBF, 0xC398, 0x9BC0, 0xC399, + 0x9BC1, 0xC39A, 0x9BC2, 0xC39B, 0x9BC3, 0xC39C, 0x9BC4, 0xC39D, 0x9BC5, 0xC39E, 0x9BC6, 0xC39F, 0x9BC7, 0xC3A0, 0x9BC8, 0xC3A1, + 0x9BC9, 0xC3A2, 0x9BCA, 0xC3A3, 0x9BCB, 0xC3A4, 0x9BCC, 0xC3A5, 0x9BCD, 0xC3A6, 0x9BCE, 0xC3A7, 0x9BCF, 0xC3A8, 0x9BD0, 0xC3A9, + 0x9BD1, 0xC3AA, 0x9BD2, 0xC3AB, 0x9BD3, 0xC3AC, 0x9BD4, 0xC3AD, 0x9BD5, 0xC3AE, 0x9BD6, 0xC3AF, 0x9BD7, 0xC3B0, 0x9BD8, 0xC3B1, + 0x9BD9, 0xC3B2, 0x9BDA, 0xC3B3, 0x9BDB, 0xC3B4, 0x9BDC, 0xC3B5, 0x9BDD, 0xC3B6, 0x9BDE, 0xC3B7, 0x9BDF, 0xC3B8, 0x9BE0, 0xC3B9, + 0x9BE1, 0xC3BA, 0x9BE2, 0xC3BB, 0x9BE3, 0xC3BC, 0x9BE4, 0xC3BD, 0x9BE5, 0xC3BE, 0x9BE6, 0xC3BF, 0x9BE7, 0xC3C1, 0x9BE8, 0xC3C2, + 0x9BE9, 0xC3C3, 0x9BEA, 0xC3C4, 0x9BEB, 0xC3C5, 0x9BEC, 0xC3C6, 0x9BED, 0xC3C7, 0x9BEE, 0xC3C8, 0x9BEF, 0xC3C9, 0x9BF0, 0xC3CA, + 0x9BF1, 0xC3CB, 0x9BF2, 0xC3CC, 0x9BF3, 0xC3CD, 0x9BF4, 0xC3CE, 0x9BF5, 0xC3CF, 0x9BF6, 0xC3D0, 0x9BF7, 0xC3D1, 0x9BF8, 0xC3D2, + 0x9BF9, 0xC3D3, 0x9BFA, 0xC3D4, 0x9BFB, 0xC3D5, 0x9BFC, 0xC3D6, 0x9BFD, 0xC3D7, 0x9BFE, 0xC3DA, 0x9C41, 0xC3DB, 0x9C42, 0xC3DD, + 0x9C43, 0xC3DE, 0x9C44, 0xC3E1, 0x9C45, 0xC3E3, 0x9C46, 0xC3E4, 0x9C47, 0xC3E5, 0x9C48, 0xC3E6, 0x9C49, 0xC3E7, 0x9C4A, 0xC3EA, + 0x9C4B, 0xC3EB, 0x9C4C, 0xC3EC, 0x9C4D, 0xC3EE, 0x9C4E, 0xC3EF, 0x9C4F, 0xC3F0, 0x9C50, 0xC3F1, 0x9C51, 0xC3F2, 0x9C52, 0xC3F3, + 0x9C53, 0xC3F6, 0x9C54, 0xC3F7, 0x9C55, 0xC3F9, 0x9C56, 0xC3FA, 0x9C57, 0xC3FB, 0x9C58, 0xC3FC, 0x9C59, 0xC3FD, 0x9C5A, 0xC3FE, + 0x9C61, 0xC3FF, 0x9C62, 0xC400, 0x9C63, 0xC401, 0x9C64, 0xC402, 0x9C65, 0xC403, 0x9C66, 0xC404, 0x9C67, 0xC405, 0x9C68, 0xC406, + 0x9C69, 0xC407, 0x9C6A, 0xC409, 0x9C6B, 0xC40A, 0x9C6C, 0xC40B, 0x9C6D, 0xC40C, 0x9C6E, 0xC40D, 0x9C6F, 0xC40E, 0x9C70, 0xC40F, + 0x9C71, 0xC411, 0x9C72, 0xC412, 0x9C73, 0xC413, 0x9C74, 0xC414, 0x9C75, 0xC415, 0x9C76, 0xC416, 0x9C77, 0xC417, 0x9C78, 0xC418, + 0x9C79, 0xC419, 0x9C7A, 0xC41A, 0x9C81, 0xC41B, 0x9C82, 0xC41C, 0x9C83, 0xC41D, 0x9C84, 0xC41E, 0x9C85, 0xC41F, 0x9C86, 0xC420, + 0x9C87, 0xC421, 0x9C88, 0xC422, 0x9C89, 0xC423, 0x9C8A, 0xC425, 0x9C8B, 0xC426, 0x9C8C, 0xC427, 0x9C8D, 0xC428, 0x9C8E, 0xC429, + 0x9C8F, 0xC42A, 0x9C90, 0xC42B, 0x9C91, 0xC42D, 0x9C92, 0xC42E, 0x9C93, 0xC42F, 0x9C94, 0xC431, 0x9C95, 0xC432, 0x9C96, 0xC433, + 0x9C97, 0xC435, 0x9C98, 0xC436, 0x9C99, 0xC437, 0x9C9A, 0xC438, 0x9C9B, 0xC439, 0x9C9C, 0xC43A, 0x9C9D, 0xC43B, 0x9C9E, 0xC43E, + 0x9C9F, 0xC43F, 0x9CA0, 0xC440, 0x9CA1, 0xC441, 0x9CA2, 0xC442, 0x9CA3, 0xC443, 0x9CA4, 0xC444, 0x9CA5, 0xC445, 0x9CA6, 0xC446, + 0x9CA7, 0xC447, 0x9CA8, 0xC449, 0x9CA9, 0xC44A, 0x9CAA, 0xC44B, 0x9CAB, 0xC44C, 0x9CAC, 0xC44D, 0x9CAD, 0xC44E, 0x9CAE, 0xC44F, + 0x9CAF, 0xC450, 0x9CB0, 0xC451, 0x9CB1, 0xC452, 0x9CB2, 0xC453, 0x9CB3, 0xC454, 0x9CB4, 0xC455, 0x9CB5, 0xC456, 0x9CB6, 0xC457, + 0x9CB7, 0xC458, 0x9CB8, 0xC459, 0x9CB9, 0xC45A, 0x9CBA, 0xC45B, 0x9CBB, 0xC45C, 0x9CBC, 0xC45D, 0x9CBD, 0xC45E, 0x9CBE, 0xC45F, + 0x9CBF, 0xC460, 0x9CC0, 0xC461, 0x9CC1, 0xC462, 0x9CC2, 0xC463, 0x9CC3, 0xC466, 0x9CC4, 0xC467, 0x9CC5, 0xC469, 0x9CC6, 0xC46A, + 0x9CC7, 0xC46B, 0x9CC8, 0xC46D, 0x9CC9, 0xC46E, 0x9CCA, 0xC46F, 0x9CCB, 0xC470, 0x9CCC, 0xC471, 0x9CCD, 0xC472, 0x9CCE, 0xC473, + 0x9CCF, 0xC476, 0x9CD0, 0xC477, 0x9CD1, 0xC478, 0x9CD2, 0xC47A, 0x9CD3, 0xC47B, 0x9CD4, 0xC47C, 0x9CD5, 0xC47D, 0x9CD6, 0xC47E, + 0x9CD7, 0xC47F, 0x9CD8, 0xC481, 0x9CD9, 0xC482, 0x9CDA, 0xC483, 0x9CDB, 0xC484, 0x9CDC, 0xC485, 0x9CDD, 0xC486, 0x9CDE, 0xC487, + 0x9CDF, 0xC488, 0x9CE0, 0xC489, 0x9CE1, 0xC48A, 0x9CE2, 0xC48B, 0x9CE3, 0xC48C, 0x9CE4, 0xC48D, 0x9CE5, 0xC48E, 0x9CE6, 0xC48F, + 0x9CE7, 0xC490, 0x9CE8, 0xC491, 0x9CE9, 0xC492, 0x9CEA, 0xC493, 0x9CEB, 0xC495, 0x9CEC, 0xC496, 0x9CED, 0xC497, 0x9CEE, 0xC498, + 0x9CEF, 0xC499, 0x9CF0, 0xC49A, 0x9CF1, 0xC49B, 0x9CF2, 0xC49D, 0x9CF3, 0xC49E, 0x9CF4, 0xC49F, 0x9CF5, 0xC4A0, 0x9CF6, 0xC4A1, + 0x9CF7, 0xC4A2, 0x9CF8, 0xC4A3, 0x9CF9, 0xC4A4, 0x9CFA, 0xC4A5, 0x9CFB, 0xC4A6, 0x9CFC, 0xC4A7, 0x9CFD, 0xC4A8, 0x9CFE, 0xC4A9, + 0x9D41, 0xC4AA, 0x9D42, 0xC4AB, 0x9D43, 0xC4AC, 0x9D44, 0xC4AD, 0x9D45, 0xC4AE, 0x9D46, 0xC4AF, 0x9D47, 0xC4B0, 0x9D48, 0xC4B1, + 0x9D49, 0xC4B2, 0x9D4A, 0xC4B3, 0x9D4B, 0xC4B4, 0x9D4C, 0xC4B5, 0x9D4D, 0xC4B6, 0x9D4E, 0xC4B7, 0x9D4F, 0xC4B9, 0x9D50, 0xC4BA, + 0x9D51, 0xC4BB, 0x9D52, 0xC4BD, 0x9D53, 0xC4BE, 0x9D54, 0xC4BF, 0x9D55, 0xC4C0, 0x9D56, 0xC4C1, 0x9D57, 0xC4C2, 0x9D58, 0xC4C3, + 0x9D59, 0xC4C4, 0x9D5A, 0xC4C5, 0x9D61, 0xC4C6, 0x9D62, 0xC4C7, 0x9D63, 0xC4C8, 0x9D64, 0xC4C9, 0x9D65, 0xC4CA, 0x9D66, 0xC4CB, + 0x9D67, 0xC4CC, 0x9D68, 0xC4CD, 0x9D69, 0xC4CE, 0x9D6A, 0xC4CF, 0x9D6B, 0xC4D0, 0x9D6C, 0xC4D1, 0x9D6D, 0xC4D2, 0x9D6E, 0xC4D3, + 0x9D6F, 0xC4D4, 0x9D70, 0xC4D5, 0x9D71, 0xC4D6, 0x9D72, 0xC4D7, 0x9D73, 0xC4D8, 0x9D74, 0xC4D9, 0x9D75, 0xC4DA, 0x9D76, 0xC4DB, + 0x9D77, 0xC4DC, 0x9D78, 0xC4DD, 0x9D79, 0xC4DE, 0x9D7A, 0xC4DF, 0x9D81, 0xC4E0, 0x9D82, 0xC4E1, 0x9D83, 0xC4E2, 0x9D84, 0xC4E3, + 0x9D85, 0xC4E4, 0x9D86, 0xC4E5, 0x9D87, 0xC4E6, 0x9D88, 0xC4E7, 0x9D89, 0xC4E8, 0x9D8A, 0xC4EA, 0x9D8B, 0xC4EB, 0x9D8C, 0xC4EC, + 0x9D8D, 0xC4ED, 0x9D8E, 0xC4EE, 0x9D8F, 0xC4EF, 0x9D90, 0xC4F2, 0x9D91, 0xC4F3, 0x9D92, 0xC4F5, 0x9D93, 0xC4F6, 0x9D94, 0xC4F7, + 0x9D95, 0xC4F9, 0x9D96, 0xC4FB, 0x9D97, 0xC4FC, 0x9D98, 0xC4FD, 0x9D99, 0xC4FE, 0x9D9A, 0xC502, 0x9D9B, 0xC503, 0x9D9C, 0xC504, + 0x9D9D, 0xC505, 0x9D9E, 0xC506, 0x9D9F, 0xC507, 0x9DA0, 0xC508, 0x9DA1, 0xC509, 0x9DA2, 0xC50A, 0x9DA3, 0xC50B, 0x9DA4, 0xC50D, + 0x9DA5, 0xC50E, 0x9DA6, 0xC50F, 0x9DA7, 0xC511, 0x9DA8, 0xC512, 0x9DA9, 0xC513, 0x9DAA, 0xC515, 0x9DAB, 0xC516, 0x9DAC, 0xC517, + 0x9DAD, 0xC518, 0x9DAE, 0xC519, 0x9DAF, 0xC51A, 0x9DB0, 0xC51B, 0x9DB1, 0xC51D, 0x9DB2, 0xC51E, 0x9DB3, 0xC51F, 0x9DB4, 0xC520, + 0x9DB5, 0xC521, 0x9DB6, 0xC522, 0x9DB7, 0xC523, 0x9DB8, 0xC524, 0x9DB9, 0xC525, 0x9DBA, 0xC526, 0x9DBB, 0xC527, 0x9DBC, 0xC52A, + 0x9DBD, 0xC52B, 0x9DBE, 0xC52D, 0x9DBF, 0xC52E, 0x9DC0, 0xC52F, 0x9DC1, 0xC531, 0x9DC2, 0xC532, 0x9DC3, 0xC533, 0x9DC4, 0xC534, + 0x9DC5, 0xC535, 0x9DC6, 0xC536, 0x9DC7, 0xC537, 0x9DC8, 0xC53A, 0x9DC9, 0xC53C, 0x9DCA, 0xC53E, 0x9DCB, 0xC53F, 0x9DCC, 0xC540, + 0x9DCD, 0xC541, 0x9DCE, 0xC542, 0x9DCF, 0xC543, 0x9DD0, 0xC546, 0x9DD1, 0xC547, 0x9DD2, 0xC54B, 0x9DD3, 0xC54F, 0x9DD4, 0xC550, + 0x9DD5, 0xC551, 0x9DD6, 0xC552, 0x9DD7, 0xC556, 0x9DD8, 0xC55A, 0x9DD9, 0xC55B, 0x9DDA, 0xC55C, 0x9DDB, 0xC55F, 0x9DDC, 0xC562, + 0x9DDD, 0xC563, 0x9DDE, 0xC565, 0x9DDF, 0xC566, 0x9DE0, 0xC567, 0x9DE1, 0xC569, 0x9DE2, 0xC56A, 0x9DE3, 0xC56B, 0x9DE4, 0xC56C, + 0x9DE5, 0xC56D, 0x9DE6, 0xC56E, 0x9DE7, 0xC56F, 0x9DE8, 0xC572, 0x9DE9, 0xC576, 0x9DEA, 0xC577, 0x9DEB, 0xC578, 0x9DEC, 0xC579, + 0x9DED, 0xC57A, 0x9DEE, 0xC57B, 0x9DEF, 0xC57E, 0x9DF0, 0xC57F, 0x9DF1, 0xC581, 0x9DF2, 0xC582, 0x9DF3, 0xC583, 0x9DF4, 0xC585, + 0x9DF5, 0xC586, 0x9DF6, 0xC588, 0x9DF7, 0xC589, 0x9DF8, 0xC58A, 0x9DF9, 0xC58B, 0x9DFA, 0xC58E, 0x9DFB, 0xC590, 0x9DFC, 0xC592, + 0x9DFD, 0xC593, 0x9DFE, 0xC594, 0x9E41, 0xC596, 0x9E42, 0xC599, 0x9E43, 0xC59A, 0x9E44, 0xC59B, 0x9E45, 0xC59D, 0x9E46, 0xC59E, + 0x9E47, 0xC59F, 0x9E48, 0xC5A1, 0x9E49, 0xC5A2, 0x9E4A, 0xC5A3, 0x9E4B, 0xC5A4, 0x9E4C, 0xC5A5, 0x9E4D, 0xC5A6, 0x9E4E, 0xC5A7, + 0x9E4F, 0xC5A8, 0x9E50, 0xC5AA, 0x9E51, 0xC5AB, 0x9E52, 0xC5AC, 0x9E53, 0xC5AD, 0x9E54, 0xC5AE, 0x9E55, 0xC5AF, 0x9E56, 0xC5B0, + 0x9E57, 0xC5B1, 0x9E58, 0xC5B2, 0x9E59, 0xC5B3, 0x9E5A, 0xC5B6, 0x9E61, 0xC5B7, 0x9E62, 0xC5BA, 0x9E63, 0xC5BF, 0x9E64, 0xC5C0, + 0x9E65, 0xC5C1, 0x9E66, 0xC5C2, 0x9E67, 0xC5C3, 0x9E68, 0xC5CB, 0x9E69, 0xC5CD, 0x9E6A, 0xC5CF, 0x9E6B, 0xC5D2, 0x9E6C, 0xC5D3, + 0x9E6D, 0xC5D5, 0x9E6E, 0xC5D6, 0x9E6F, 0xC5D7, 0x9E70, 0xC5D9, 0x9E71, 0xC5DA, 0x9E72, 0xC5DB, 0x9E73, 0xC5DC, 0x9E74, 0xC5DD, + 0x9E75, 0xC5DE, 0x9E76, 0xC5DF, 0x9E77, 0xC5E2, 0x9E78, 0xC5E4, 0x9E79, 0xC5E6, 0x9E7A, 0xC5E7, 0x9E81, 0xC5E8, 0x9E82, 0xC5E9, + 0x9E83, 0xC5EA, 0x9E84, 0xC5EB, 0x9E85, 0xC5EF, 0x9E86, 0xC5F1, 0x9E87, 0xC5F2, 0x9E88, 0xC5F3, 0x9E89, 0xC5F5, 0x9E8A, 0xC5F8, + 0x9E8B, 0xC5F9, 0x9E8C, 0xC5FA, 0x9E8D, 0xC5FB, 0x9E8E, 0xC602, 0x9E8F, 0xC603, 0x9E90, 0xC604, 0x9E91, 0xC609, 0x9E92, 0xC60A, + 0x9E93, 0xC60B, 0x9E94, 0xC60D, 0x9E95, 0xC60E, 0x9E96, 0xC60F, 0x9E97, 0xC611, 0x9E98, 0xC612, 0x9E99, 0xC613, 0x9E9A, 0xC614, + 0x9E9B, 0xC615, 0x9E9C, 0xC616, 0x9E9D, 0xC617, 0x9E9E, 0xC61A, 0x9E9F, 0xC61D, 0x9EA0, 0xC61E, 0x9EA1, 0xC61F, 0x9EA2, 0xC620, + 0x9EA3, 0xC621, 0x9EA4, 0xC622, 0x9EA5, 0xC623, 0x9EA6, 0xC626, 0x9EA7, 0xC627, 0x9EA8, 0xC629, 0x9EA9, 0xC62A, 0x9EAA, 0xC62B, + 0x9EAB, 0xC62F, 0x9EAC, 0xC631, 0x9EAD, 0xC632, 0x9EAE, 0xC636, 0x9EAF, 0xC638, 0x9EB0, 0xC63A, 0x9EB1, 0xC63C, 0x9EB2, 0xC63D, + 0x9EB3, 0xC63E, 0x9EB4, 0xC63F, 0x9EB5, 0xC642, 0x9EB6, 0xC643, 0x9EB7, 0xC645, 0x9EB8, 0xC646, 0x9EB9, 0xC647, 0x9EBA, 0xC649, + 0x9EBB, 0xC64A, 0x9EBC, 0xC64B, 0x9EBD, 0xC64C, 0x9EBE, 0xC64D, 0x9EBF, 0xC64E, 0x9EC0, 0xC64F, 0x9EC1, 0xC652, 0x9EC2, 0xC656, + 0x9EC3, 0xC657, 0x9EC4, 0xC658, 0x9EC5, 0xC659, 0x9EC6, 0xC65A, 0x9EC7, 0xC65B, 0x9EC8, 0xC65E, 0x9EC9, 0xC65F, 0x9ECA, 0xC661, + 0x9ECB, 0xC662, 0x9ECC, 0xC663, 0x9ECD, 0xC664, 0x9ECE, 0xC665, 0x9ECF, 0xC666, 0x9ED0, 0xC667, 0x9ED1, 0xC668, 0x9ED2, 0xC669, + 0x9ED3, 0xC66A, 0x9ED4, 0xC66B, 0x9ED5, 0xC66D, 0x9ED6, 0xC66E, 0x9ED7, 0xC670, 0x9ED8, 0xC672, 0x9ED9, 0xC673, 0x9EDA, 0xC674, + 0x9EDB, 0xC675, 0x9EDC, 0xC676, 0x9EDD, 0xC677, 0x9EDE, 0xC67A, 0x9EDF, 0xC67B, 0x9EE0, 0xC67D, 0x9EE1, 0xC67E, 0x9EE2, 0xC67F, + 0x9EE3, 0xC681, 0x9EE4, 0xC682, 0x9EE5, 0xC683, 0x9EE6, 0xC684, 0x9EE7, 0xC685, 0x9EE8, 0xC686, 0x9EE9, 0xC687, 0x9EEA, 0xC68A, + 0x9EEB, 0xC68C, 0x9EEC, 0xC68E, 0x9EED, 0xC68F, 0x9EEE, 0xC690, 0x9EEF, 0xC691, 0x9EF0, 0xC692, 0x9EF1, 0xC693, 0x9EF2, 0xC696, + 0x9EF3, 0xC697, 0x9EF4, 0xC699, 0x9EF5, 0xC69A, 0x9EF6, 0xC69B, 0x9EF7, 0xC69D, 0x9EF8, 0xC69E, 0x9EF9, 0xC69F, 0x9EFA, 0xC6A0, + 0x9EFB, 0xC6A1, 0x9EFC, 0xC6A2, 0x9EFD, 0xC6A3, 0x9EFE, 0xC6A6, 0x9F41, 0xC6A8, 0x9F42, 0xC6AA, 0x9F43, 0xC6AB, 0x9F44, 0xC6AC, + 0x9F45, 0xC6AD, 0x9F46, 0xC6AE, 0x9F47, 0xC6AF, 0x9F48, 0xC6B2, 0x9F49, 0xC6B3, 0x9F4A, 0xC6B5, 0x9F4B, 0xC6B6, 0x9F4C, 0xC6B7, + 0x9F4D, 0xC6BB, 0x9F4E, 0xC6BC, 0x9F4F, 0xC6BD, 0x9F50, 0xC6BE, 0x9F51, 0xC6BF, 0x9F52, 0xC6C2, 0x9F53, 0xC6C4, 0x9F54, 0xC6C6, + 0x9F55, 0xC6C7, 0x9F56, 0xC6C8, 0x9F57, 0xC6C9, 0x9F58, 0xC6CA, 0x9F59, 0xC6CB, 0x9F5A, 0xC6CE, 0x9F61, 0xC6CF, 0x9F62, 0xC6D1, + 0x9F63, 0xC6D2, 0x9F64, 0xC6D3, 0x9F65, 0xC6D5, 0x9F66, 0xC6D6, 0x9F67, 0xC6D7, 0x9F68, 0xC6D8, 0x9F69, 0xC6D9, 0x9F6A, 0xC6DA, + 0x9F6B, 0xC6DB, 0x9F6C, 0xC6DE, 0x9F6D, 0xC6DF, 0x9F6E, 0xC6E2, 0x9F6F, 0xC6E3, 0x9F70, 0xC6E4, 0x9F71, 0xC6E5, 0x9F72, 0xC6E6, + 0x9F73, 0xC6E7, 0x9F74, 0xC6EA, 0x9F75, 0xC6EB, 0x9F76, 0xC6ED, 0x9F77, 0xC6EE, 0x9F78, 0xC6EF, 0x9F79, 0xC6F1, 0x9F7A, 0xC6F2, + 0x9F81, 0xC6F3, 0x9F82, 0xC6F4, 0x9F83, 0xC6F5, 0x9F84, 0xC6F6, 0x9F85, 0xC6F7, 0x9F86, 0xC6FA, 0x9F87, 0xC6FB, 0x9F88, 0xC6FC, + 0x9F89, 0xC6FE, 0x9F8A, 0xC6FF, 0x9F8B, 0xC700, 0x9F8C, 0xC701, 0x9F8D, 0xC702, 0x9F8E, 0xC703, 0x9F8F, 0xC706, 0x9F90, 0xC707, + 0x9F91, 0xC709, 0x9F92, 0xC70A, 0x9F93, 0xC70B, 0x9F94, 0xC70D, 0x9F95, 0xC70E, 0x9F96, 0xC70F, 0x9F97, 0xC710, 0x9F98, 0xC711, + 0x9F99, 0xC712, 0x9F9A, 0xC713, 0x9F9B, 0xC716, 0x9F9C, 0xC718, 0x9F9D, 0xC71A, 0x9F9E, 0xC71B, 0x9F9F, 0xC71C, 0x9FA0, 0xC71D, + 0x9FA1, 0xC71E, 0x9FA2, 0xC71F, 0x9FA3, 0xC722, 0x9FA4, 0xC723, 0x9FA5, 0xC725, 0x9FA6, 0xC726, 0x9FA7, 0xC727, 0x9FA8, 0xC729, + 0x9FA9, 0xC72A, 0x9FAA, 0xC72B, 0x9FAB, 0xC72C, 0x9FAC, 0xC72D, 0x9FAD, 0xC72E, 0x9FAE, 0xC72F, 0x9FAF, 0xC732, 0x9FB0, 0xC734, + 0x9FB1, 0xC736, 0x9FB2, 0xC738, 0x9FB3, 0xC739, 0x9FB4, 0xC73A, 0x9FB5, 0xC73B, 0x9FB6, 0xC73E, 0x9FB7, 0xC73F, 0x9FB8, 0xC741, + 0x9FB9, 0xC742, 0x9FBA, 0xC743, 0x9FBB, 0xC745, 0x9FBC, 0xC746, 0x9FBD, 0xC747, 0x9FBE, 0xC748, 0x9FBF, 0xC749, 0x9FC0, 0xC74B, + 0x9FC1, 0xC74E, 0x9FC2, 0xC750, 0x9FC3, 0xC759, 0x9FC4, 0xC75A, 0x9FC5, 0xC75B, 0x9FC6, 0xC75D, 0x9FC7, 0xC75E, 0x9FC8, 0xC75F, + 0x9FC9, 0xC761, 0x9FCA, 0xC762, 0x9FCB, 0xC763, 0x9FCC, 0xC764, 0x9FCD, 0xC765, 0x9FCE, 0xC766, 0x9FCF, 0xC767, 0x9FD0, 0xC769, + 0x9FD1, 0xC76A, 0x9FD2, 0xC76C, 0x9FD3, 0xC76D, 0x9FD4, 0xC76E, 0x9FD5, 0xC76F, 0x9FD6, 0xC770, 0x9FD7, 0xC771, 0x9FD8, 0xC772, + 0x9FD9, 0xC773, 0x9FDA, 0xC776, 0x9FDB, 0xC777, 0x9FDC, 0xC779, 0x9FDD, 0xC77A, 0x9FDE, 0xC77B, 0x9FDF, 0xC77F, 0x9FE0, 0xC780, + 0x9FE1, 0xC781, 0x9FE2, 0xC782, 0x9FE3, 0xC786, 0x9FE4, 0xC78B, 0x9FE5, 0xC78C, 0x9FE6, 0xC78D, 0x9FE7, 0xC78F, 0x9FE8, 0xC792, + 0x9FE9, 0xC793, 0x9FEA, 0xC795, 0x9FEB, 0xC799, 0x9FEC, 0xC79B, 0x9FED, 0xC79C, 0x9FEE, 0xC79D, 0x9FEF, 0xC79E, 0x9FF0, 0xC79F, + 0x9FF1, 0xC7A2, 0x9FF2, 0xC7A7, 0x9FF3, 0xC7A8, 0x9FF4, 0xC7A9, 0x9FF5, 0xC7AA, 0x9FF6, 0xC7AB, 0x9FF7, 0xC7AE, 0x9FF8, 0xC7AF, + 0x9FF9, 0xC7B1, 0x9FFA, 0xC7B2, 0x9FFB, 0xC7B3, 0x9FFC, 0xC7B5, 0x9FFD, 0xC7B6, 0x9FFE, 0xC7B7, 0xA041, 0xC7B8, 0xA042, 0xC7B9, + 0xA043, 0xC7BA, 0xA044, 0xC7BB, 0xA045, 0xC7BE, 0xA046, 0xC7C2, 0xA047, 0xC7C3, 0xA048, 0xC7C4, 0xA049, 0xC7C5, 0xA04A, 0xC7C6, + 0xA04B, 0xC7C7, 0xA04C, 0xC7CA, 0xA04D, 0xC7CB, 0xA04E, 0xC7CD, 0xA04F, 0xC7CF, 0xA050, 0xC7D1, 0xA051, 0xC7D2, 0xA052, 0xC7D3, + 0xA053, 0xC7D4, 0xA054, 0xC7D5, 0xA055, 0xC7D6, 0xA056, 0xC7D7, 0xA057, 0xC7D9, 0xA058, 0xC7DA, 0xA059, 0xC7DB, 0xA05A, 0xC7DC, + 0xA061, 0xC7DE, 0xA062, 0xC7DF, 0xA063, 0xC7E0, 0xA064, 0xC7E1, 0xA065, 0xC7E2, 0xA066, 0xC7E3, 0xA067, 0xC7E5, 0xA068, 0xC7E6, + 0xA069, 0xC7E7, 0xA06A, 0xC7E9, 0xA06B, 0xC7EA, 0xA06C, 0xC7EB, 0xA06D, 0xC7ED, 0xA06E, 0xC7EE, 0xA06F, 0xC7EF, 0xA070, 0xC7F0, + 0xA071, 0xC7F1, 0xA072, 0xC7F2, 0xA073, 0xC7F3, 0xA074, 0xC7F4, 0xA075, 0xC7F5, 0xA076, 0xC7F6, 0xA077, 0xC7F7, 0xA078, 0xC7F8, + 0xA079, 0xC7F9, 0xA07A, 0xC7FA, 0xA081, 0xC7FB, 0xA082, 0xC7FC, 0xA083, 0xC7FD, 0xA084, 0xC7FE, 0xA085, 0xC7FF, 0xA086, 0xC802, + 0xA087, 0xC803, 0xA088, 0xC805, 0xA089, 0xC806, 0xA08A, 0xC807, 0xA08B, 0xC809, 0xA08C, 0xC80B, 0xA08D, 0xC80C, 0xA08E, 0xC80D, + 0xA08F, 0xC80E, 0xA090, 0xC80F, 0xA091, 0xC812, 0xA092, 0xC814, 0xA093, 0xC817, 0xA094, 0xC818, 0xA095, 0xC819, 0xA096, 0xC81A, + 0xA097, 0xC81B, 0xA098, 0xC81E, 0xA099, 0xC81F, 0xA09A, 0xC821, 0xA09B, 0xC822, 0xA09C, 0xC823, 0xA09D, 0xC825, 0xA09E, 0xC826, + 0xA09F, 0xC827, 0xA0A0, 0xC828, 0xA0A1, 0xC829, 0xA0A2, 0xC82A, 0xA0A3, 0xC82B, 0xA0A4, 0xC82E, 0xA0A5, 0xC830, 0xA0A6, 0xC832, + 0xA0A7, 0xC833, 0xA0A8, 0xC834, 0xA0A9, 0xC835, 0xA0AA, 0xC836, 0xA0AB, 0xC837, 0xA0AC, 0xC839, 0xA0AD, 0xC83A, 0xA0AE, 0xC83B, + 0xA0AF, 0xC83D, 0xA0B0, 0xC83E, 0xA0B1, 0xC83F, 0xA0B2, 0xC841, 0xA0B3, 0xC842, 0xA0B4, 0xC843, 0xA0B5, 0xC844, 0xA0B6, 0xC845, + 0xA0B7, 0xC846, 0xA0B8, 0xC847, 0xA0B9, 0xC84A, 0xA0BA, 0xC84B, 0xA0BB, 0xC84E, 0xA0BC, 0xC84F, 0xA0BD, 0xC850, 0xA0BE, 0xC851, + 0xA0BF, 0xC852, 0xA0C0, 0xC853, 0xA0C1, 0xC855, 0xA0C2, 0xC856, 0xA0C3, 0xC857, 0xA0C4, 0xC858, 0xA0C5, 0xC859, 0xA0C6, 0xC85A, + 0xA0C7, 0xC85B, 0xA0C8, 0xC85C, 0xA0C9, 0xC85D, 0xA0CA, 0xC85E, 0xA0CB, 0xC85F, 0xA0CC, 0xC860, 0xA0CD, 0xC861, 0xA0CE, 0xC862, + 0xA0CF, 0xC863, 0xA0D0, 0xC864, 0xA0D1, 0xC865, 0xA0D2, 0xC866, 0xA0D3, 0xC867, 0xA0D4, 0xC868, 0xA0D5, 0xC869, 0xA0D6, 0xC86A, + 0xA0D7, 0xC86B, 0xA0D8, 0xC86C, 0xA0D9, 0xC86D, 0xA0DA, 0xC86E, 0xA0DB, 0xC86F, 0xA0DC, 0xC872, 0xA0DD, 0xC873, 0xA0DE, 0xC875, + 0xA0DF, 0xC876, 0xA0E0, 0xC877, 0xA0E1, 0xC879, 0xA0E2, 0xC87B, 0xA0E3, 0xC87C, 0xA0E4, 0xC87D, 0xA0E5, 0xC87E, 0xA0E6, 0xC87F, + 0xA0E7, 0xC882, 0xA0E8, 0xC884, 0xA0E9, 0xC888, 0xA0EA, 0xC889, 0xA0EB, 0xC88A, 0xA0EC, 0xC88E, 0xA0ED, 0xC88F, 0xA0EE, 0xC890, + 0xA0EF, 0xC891, 0xA0F0, 0xC892, 0xA0F1, 0xC893, 0xA0F2, 0xC895, 0xA0F3, 0xC896, 0xA0F4, 0xC897, 0xA0F5, 0xC898, 0xA0F6, 0xC899, + 0xA0F7, 0xC89A, 0xA0F8, 0xC89B, 0xA0F9, 0xC89C, 0xA0FA, 0xC89E, 0xA0FB, 0xC8A0, 0xA0FC, 0xC8A2, 0xA0FD, 0xC8A3, 0xA0FE, 0xC8A4, + 0xA141, 0xC8A5, 0xA142, 0xC8A6, 0xA143, 0xC8A7, 0xA144, 0xC8A9, 0xA145, 0xC8AA, 0xA146, 0xC8AB, 0xA147, 0xC8AC, 0xA148, 0xC8AD, + 0xA149, 0xC8AE, 0xA14A, 0xC8AF, 0xA14B, 0xC8B0, 0xA14C, 0xC8B1, 0xA14D, 0xC8B2, 0xA14E, 0xC8B3, 0xA14F, 0xC8B4, 0xA150, 0xC8B5, + 0xA151, 0xC8B6, 0xA152, 0xC8B7, 0xA153, 0xC8B8, 0xA154, 0xC8B9, 0xA155, 0xC8BA, 0xA156, 0xC8BB, 0xA157, 0xC8BE, 0xA158, 0xC8BF, + 0xA159, 0xC8C0, 0xA15A, 0xC8C1, 0xA161, 0xC8C2, 0xA162, 0xC8C3, 0xA163, 0xC8C5, 0xA164, 0xC8C6, 0xA165, 0xC8C7, 0xA166, 0xC8C9, + 0xA167, 0xC8CA, 0xA168, 0xC8CB, 0xA169, 0xC8CD, 0xA16A, 0xC8CE, 0xA16B, 0xC8CF, 0xA16C, 0xC8D0, 0xA16D, 0xC8D1, 0xA16E, 0xC8D2, + 0xA16F, 0xC8D3, 0xA170, 0xC8D6, 0xA171, 0xC8D8, 0xA172, 0xC8DA, 0xA173, 0xC8DB, 0xA174, 0xC8DC, 0xA175, 0xC8DD, 0xA176, 0xC8DE, + 0xA177, 0xC8DF, 0xA178, 0xC8E2, 0xA179, 0xC8E3, 0xA17A, 0xC8E5, 0xA181, 0xC8E6, 0xA182, 0xC8E7, 0xA183, 0xC8E8, 0xA184, 0xC8E9, + 0xA185, 0xC8EA, 0xA186, 0xC8EB, 0xA187, 0xC8EC, 0xA188, 0xC8ED, 0xA189, 0xC8EE, 0xA18A, 0xC8EF, 0xA18B, 0xC8F0, 0xA18C, 0xC8F1, + 0xA18D, 0xC8F2, 0xA18E, 0xC8F3, 0xA18F, 0xC8F4, 0xA190, 0xC8F6, 0xA191, 0xC8F7, 0xA192, 0xC8F8, 0xA193, 0xC8F9, 0xA194, 0xC8FA, + 0xA195, 0xC8FB, 0xA196, 0xC8FE, 0xA197, 0xC8FF, 0xA198, 0xC901, 0xA199, 0xC902, 0xA19A, 0xC903, 0xA19B, 0xC907, 0xA19C, 0xC908, + 0xA19D, 0xC909, 0xA19E, 0xC90A, 0xA19F, 0xC90B, 0xA1A0, 0xC90E, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, + 0xA1A5, 0x2025, 0xA1A6, 0x2026, 0xA1A7, 0x00A8, 0xA1A8, 0x3003, 0xA1A9, 0x00AD, 0xA1AA, 0x2015, 0xA1AB, 0x2225, 0xA1AC, 0xFF3C, + 0xA1AD, 0x223C, 0xA1AE, 0x2018, 0xA1AF, 0x2019, 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, + 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3010, + 0xA1BD, 0x3011, 0xA1BE, 0x00B1, 0xA1BF, 0x00D7, 0xA1C0, 0x00F7, 0xA1C1, 0x2260, 0xA1C2, 0x2264, 0xA1C3, 0x2265, 0xA1C4, 0x221E, + 0xA1C5, 0x2234, 0xA1C6, 0x00B0, 0xA1C7, 0x2032, 0xA1C8, 0x2033, 0xA1C9, 0x2103, 0xA1CA, 0x212B, 0xA1CB, 0xFFE0, 0xA1CC, 0xFFE1, + 0xA1CD, 0xFFE5, 0xA1CE, 0x2642, 0xA1CF, 0x2640, 0xA1D0, 0x2220, 0xA1D1, 0x22A5, 0xA1D2, 0x2312, 0xA1D3, 0x2202, 0xA1D4, 0x2207, + 0xA1D5, 0x2261, 0xA1D6, 0x2252, 0xA1D7, 0x00A7, 0xA1D8, 0x203B, 0xA1D9, 0x2606, 0xA1DA, 0x2605, 0xA1DB, 0x25CB, 0xA1DC, 0x25CF, + 0xA1DD, 0x25CE, 0xA1DE, 0x25C7, 0xA1DF, 0x25C6, 0xA1E0, 0x25A1, 0xA1E1, 0x25A0, 0xA1E2, 0x25B3, 0xA1E3, 0x25B2, 0xA1E4, 0x25BD, + 0xA1E5, 0x25BC, 0xA1E6, 0x2192, 0xA1E7, 0x2190, 0xA1E8, 0x2191, 0xA1E9, 0x2193, 0xA1EA, 0x2194, 0xA1EB, 0x3013, 0xA1EC, 0x226A, + 0xA1ED, 0x226B, 0xA1EE, 0x221A, 0xA1EF, 0x223D, 0xA1F0, 0x221D, 0xA1F1, 0x2235, 0xA1F2, 0x222B, 0xA1F3, 0x222C, 0xA1F4, 0x2208, + 0xA1F5, 0x220B, 0xA1F6, 0x2286, 0xA1F7, 0x2287, 0xA1F8, 0x2282, 0xA1F9, 0x2283, 0xA1FA, 0x222A, 0xA1FB, 0x2229, 0xA1FC, 0x2227, + 0xA1FD, 0x2228, 0xA1FE, 0xFFE2, 0xA241, 0xC910, 0xA242, 0xC912, 0xA243, 0xC913, 0xA244, 0xC914, 0xA245, 0xC915, 0xA246, 0xC916, + 0xA247, 0xC917, 0xA248, 0xC919, 0xA249, 0xC91A, 0xA24A, 0xC91B, 0xA24B, 0xC91C, 0xA24C, 0xC91D, 0xA24D, 0xC91E, 0xA24E, 0xC91F, + 0xA24F, 0xC920, 0xA250, 0xC921, 0xA251, 0xC922, 0xA252, 0xC923, 0xA253, 0xC924, 0xA254, 0xC925, 0xA255, 0xC926, 0xA256, 0xC927, + 0xA257, 0xC928, 0xA258, 0xC929, 0xA259, 0xC92A, 0xA25A, 0xC92B, 0xA261, 0xC92D, 0xA262, 0xC92E, 0xA263, 0xC92F, 0xA264, 0xC930, + 0xA265, 0xC931, 0xA266, 0xC932, 0xA267, 0xC933, 0xA268, 0xC935, 0xA269, 0xC936, 0xA26A, 0xC937, 0xA26B, 0xC938, 0xA26C, 0xC939, + 0xA26D, 0xC93A, 0xA26E, 0xC93B, 0xA26F, 0xC93C, 0xA270, 0xC93D, 0xA271, 0xC93E, 0xA272, 0xC93F, 0xA273, 0xC940, 0xA274, 0xC941, + 0xA275, 0xC942, 0xA276, 0xC943, 0xA277, 0xC944, 0xA278, 0xC945, 0xA279, 0xC946, 0xA27A, 0xC947, 0xA281, 0xC948, 0xA282, 0xC949, + 0xA283, 0xC94A, 0xA284, 0xC94B, 0xA285, 0xC94C, 0xA286, 0xC94D, 0xA287, 0xC94E, 0xA288, 0xC94F, 0xA289, 0xC952, 0xA28A, 0xC953, + 0xA28B, 0xC955, 0xA28C, 0xC956, 0xA28D, 0xC957, 0xA28E, 0xC959, 0xA28F, 0xC95A, 0xA290, 0xC95B, 0xA291, 0xC95C, 0xA292, 0xC95D, + 0xA293, 0xC95E, 0xA294, 0xC95F, 0xA295, 0xC962, 0xA296, 0xC964, 0xA297, 0xC965, 0xA298, 0xC966, 0xA299, 0xC967, 0xA29A, 0xC968, + 0xA29B, 0xC969, 0xA29C, 0xC96A, 0xA29D, 0xC96B, 0xA29E, 0xC96D, 0xA29F, 0xC96E, 0xA2A0, 0xC96F, 0xA2A1, 0x21D2, 0xA2A2, 0x21D4, + 0xA2A3, 0x2200, 0xA2A4, 0x2203, 0xA2A5, 0x00B4, 0xA2A6, 0xFF5E, 0xA2A7, 0x02C7, 0xA2A8, 0x02D8, 0xA2A9, 0x02DD, 0xA2AA, 0x02DA, + 0xA2AB, 0x02D9, 0xA2AC, 0x00B8, 0xA2AD, 0x02DB, 0xA2AE, 0x00A1, 0xA2AF, 0x00BF, 0xA2B0, 0x02D0, 0xA2B1, 0x222E, 0xA2B2, 0x2211, + 0xA2B3, 0x220F, 0xA2B4, 0x00A4, 0xA2B5, 0x2109, 0xA2B6, 0x2030, 0xA2B7, 0x25C1, 0xA2B8, 0x25C0, 0xA2B9, 0x25B7, 0xA2BA, 0x25B6, + 0xA2BB, 0x2664, 0xA2BC, 0x2660, 0xA2BD, 0x2661, 0xA2BE, 0x2665, 0xA2BF, 0x2667, 0xA2C0, 0x2663, 0xA2C1, 0x2299, 0xA2C2, 0x25C8, + 0xA2C3, 0x25A3, 0xA2C4, 0x25D0, 0xA2C5, 0x25D1, 0xA2C6, 0x2592, 0xA2C7, 0x25A4, 0xA2C8, 0x25A5, 0xA2C9, 0x25A8, 0xA2CA, 0x25A7, + 0xA2CB, 0x25A6, 0xA2CC, 0x25A9, 0xA2CD, 0x2668, 0xA2CE, 0x260F, 0xA2CF, 0x260E, 0xA2D0, 0x261C, 0xA2D1, 0x261E, 0xA2D2, 0x00B6, + 0xA2D3, 0x2020, 0xA2D4, 0x2021, 0xA2D5, 0x2195, 0xA2D6, 0x2197, 0xA2D7, 0x2199, 0xA2D8, 0x2196, 0xA2D9, 0x2198, 0xA2DA, 0x266D, + 0xA2DB, 0x2669, 0xA2DC, 0x266A, 0xA2DD, 0x266C, 0xA2DE, 0x327F, 0xA2DF, 0x321C, 0xA2E0, 0x2116, 0xA2E1, 0x33C7, 0xA2E2, 0x2122, + 0xA2E3, 0x33C2, 0xA2E4, 0x33D8, 0xA2E5, 0x2121, 0xA2E6, 0x20AC, 0xA2E7, 0x00AE, 0xA341, 0xC971, 0xA342, 0xC972, 0xA343, 0xC973, + 0xA344, 0xC975, 0xA345, 0xC976, 0xA346, 0xC977, 0xA347, 0xC978, 0xA348, 0xC979, 0xA349, 0xC97A, 0xA34A, 0xC97B, 0xA34B, 0xC97D, + 0xA34C, 0xC97E, 0xA34D, 0xC97F, 0xA34E, 0xC980, 0xA34F, 0xC981, 0xA350, 0xC982, 0xA351, 0xC983, 0xA352, 0xC984, 0xA353, 0xC985, + 0xA354, 0xC986, 0xA355, 0xC987, 0xA356, 0xC98A, 0xA357, 0xC98B, 0xA358, 0xC98D, 0xA359, 0xC98E, 0xA35A, 0xC98F, 0xA361, 0xC991, + 0xA362, 0xC992, 0xA363, 0xC993, 0xA364, 0xC994, 0xA365, 0xC995, 0xA366, 0xC996, 0xA367, 0xC997, 0xA368, 0xC99A, 0xA369, 0xC99C, + 0xA36A, 0xC99E, 0xA36B, 0xC99F, 0xA36C, 0xC9A0, 0xA36D, 0xC9A1, 0xA36E, 0xC9A2, 0xA36F, 0xC9A3, 0xA370, 0xC9A4, 0xA371, 0xC9A5, + 0xA372, 0xC9A6, 0xA373, 0xC9A7, 0xA374, 0xC9A8, 0xA375, 0xC9A9, 0xA376, 0xC9AA, 0xA377, 0xC9AB, 0xA378, 0xC9AC, 0xA379, 0xC9AD, + 0xA37A, 0xC9AE, 0xA381, 0xC9AF, 0xA382, 0xC9B0, 0xA383, 0xC9B1, 0xA384, 0xC9B2, 0xA385, 0xC9B3, 0xA386, 0xC9B4, 0xA387, 0xC9B5, + 0xA388, 0xC9B6, 0xA389, 0xC9B7, 0xA38A, 0xC9B8, 0xA38B, 0xC9B9, 0xA38C, 0xC9BA, 0xA38D, 0xC9BB, 0xA38E, 0xC9BC, 0xA38F, 0xC9BD, + 0xA390, 0xC9BE, 0xA391, 0xC9BF, 0xA392, 0xC9C2, 0xA393, 0xC9C3, 0xA394, 0xC9C5, 0xA395, 0xC9C6, 0xA396, 0xC9C9, 0xA397, 0xC9CB, + 0xA398, 0xC9CC, 0xA399, 0xC9CD, 0xA39A, 0xC9CE, 0xA39B, 0xC9CF, 0xA39C, 0xC9D2, 0xA39D, 0xC9D4, 0xA39E, 0xC9D7, 0xA39F, 0xC9D8, + 0xA3A0, 0xC9DB, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFF04, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFFE6, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA441, 0xC9DE, + 0xA442, 0xC9DF, 0xA443, 0xC9E1, 0xA444, 0xC9E3, 0xA445, 0xC9E5, 0xA446, 0xC9E6, 0xA447, 0xC9E8, 0xA448, 0xC9E9, 0xA449, 0xC9EA, + 0xA44A, 0xC9EB, 0xA44B, 0xC9EE, 0xA44C, 0xC9F2, 0xA44D, 0xC9F3, 0xA44E, 0xC9F4, 0xA44F, 0xC9F5, 0xA450, 0xC9F6, 0xA451, 0xC9F7, + 0xA452, 0xC9FA, 0xA453, 0xC9FB, 0xA454, 0xC9FD, 0xA455, 0xC9FE, 0xA456, 0xC9FF, 0xA457, 0xCA01, 0xA458, 0xCA02, 0xA459, 0xCA03, + 0xA45A, 0xCA04, 0xA461, 0xCA05, 0xA462, 0xCA06, 0xA463, 0xCA07, 0xA464, 0xCA0A, 0xA465, 0xCA0E, 0xA466, 0xCA0F, 0xA467, 0xCA10, + 0xA468, 0xCA11, 0xA469, 0xCA12, 0xA46A, 0xCA13, 0xA46B, 0xCA15, 0xA46C, 0xCA16, 0xA46D, 0xCA17, 0xA46E, 0xCA19, 0xA46F, 0xCA1A, + 0xA470, 0xCA1B, 0xA471, 0xCA1C, 0xA472, 0xCA1D, 0xA473, 0xCA1E, 0xA474, 0xCA1F, 0xA475, 0xCA20, 0xA476, 0xCA21, 0xA477, 0xCA22, + 0xA478, 0xCA23, 0xA479, 0xCA24, 0xA47A, 0xCA25, 0xA481, 0xCA26, 0xA482, 0xCA27, 0xA483, 0xCA28, 0xA484, 0xCA2A, 0xA485, 0xCA2B, + 0xA486, 0xCA2C, 0xA487, 0xCA2D, 0xA488, 0xCA2E, 0xA489, 0xCA2F, 0xA48A, 0xCA30, 0xA48B, 0xCA31, 0xA48C, 0xCA32, 0xA48D, 0xCA33, + 0xA48E, 0xCA34, 0xA48F, 0xCA35, 0xA490, 0xCA36, 0xA491, 0xCA37, 0xA492, 0xCA38, 0xA493, 0xCA39, 0xA494, 0xCA3A, 0xA495, 0xCA3B, + 0xA496, 0xCA3C, 0xA497, 0xCA3D, 0xA498, 0xCA3E, 0xA499, 0xCA3F, 0xA49A, 0xCA40, 0xA49B, 0xCA41, 0xA49C, 0xCA42, 0xA49D, 0xCA43, + 0xA49E, 0xCA44, 0xA49F, 0xCA45, 0xA4A0, 0xCA46, 0xA4A1, 0x3131, 0xA4A2, 0x3132, 0xA4A3, 0x3133, 0xA4A4, 0x3134, 0xA4A5, 0x3135, + 0xA4A6, 0x3136, 0xA4A7, 0x3137, 0xA4A8, 0x3138, 0xA4A9, 0x3139, 0xA4AA, 0x313A, 0xA4AB, 0x313B, 0xA4AC, 0x313C, 0xA4AD, 0x313D, + 0xA4AE, 0x313E, 0xA4AF, 0x313F, 0xA4B0, 0x3140, 0xA4B1, 0x3141, 0xA4B2, 0x3142, 0xA4B3, 0x3143, 0xA4B4, 0x3144, 0xA4B5, 0x3145, + 0xA4B6, 0x3146, 0xA4B7, 0x3147, 0xA4B8, 0x3148, 0xA4B9, 0x3149, 0xA4BA, 0x314A, 0xA4BB, 0x314B, 0xA4BC, 0x314C, 0xA4BD, 0x314D, + 0xA4BE, 0x314E, 0xA4BF, 0x314F, 0xA4C0, 0x3150, 0xA4C1, 0x3151, 0xA4C2, 0x3152, 0xA4C3, 0x3153, 0xA4C4, 0x3154, 0xA4C5, 0x3155, + 0xA4C6, 0x3156, 0xA4C7, 0x3157, 0xA4C8, 0x3158, 0xA4C9, 0x3159, 0xA4CA, 0x315A, 0xA4CB, 0x315B, 0xA4CC, 0x315C, 0xA4CD, 0x315D, + 0xA4CE, 0x315E, 0xA4CF, 0x315F, 0xA4D0, 0x3160, 0xA4D1, 0x3161, 0xA4D2, 0x3162, 0xA4D3, 0x3163, 0xA4D4, 0x3164, 0xA4D5, 0x3165, + 0xA4D6, 0x3166, 0xA4D7, 0x3167, 0xA4D8, 0x3168, 0xA4D9, 0x3169, 0xA4DA, 0x316A, 0xA4DB, 0x316B, 0xA4DC, 0x316C, 0xA4DD, 0x316D, + 0xA4DE, 0x316E, 0xA4DF, 0x316F, 0xA4E0, 0x3170, 0xA4E1, 0x3171, 0xA4E2, 0x3172, 0xA4E3, 0x3173, 0xA4E4, 0x3174, 0xA4E5, 0x3175, + 0xA4E6, 0x3176, 0xA4E7, 0x3177, 0xA4E8, 0x3178, 0xA4E9, 0x3179, 0xA4EA, 0x317A, 0xA4EB, 0x317B, 0xA4EC, 0x317C, 0xA4ED, 0x317D, + 0xA4EE, 0x317E, 0xA4EF, 0x317F, 0xA4F0, 0x3180, 0xA4F1, 0x3181, 0xA4F2, 0x3182, 0xA4F3, 0x3183, 0xA4F4, 0x3184, 0xA4F5, 0x3185, + 0xA4F6, 0x3186, 0xA4F7, 0x3187, 0xA4F8, 0x3188, 0xA4F9, 0x3189, 0xA4FA, 0x318A, 0xA4FB, 0x318B, 0xA4FC, 0x318C, 0xA4FD, 0x318D, + 0xA4FE, 0x318E, 0xA541, 0xCA47, 0xA542, 0xCA48, 0xA543, 0xCA49, 0xA544, 0xCA4A, 0xA545, 0xCA4B, 0xA546, 0xCA4E, 0xA547, 0xCA4F, + 0xA548, 0xCA51, 0xA549, 0xCA52, 0xA54A, 0xCA53, 0xA54B, 0xCA55, 0xA54C, 0xCA56, 0xA54D, 0xCA57, 0xA54E, 0xCA58, 0xA54F, 0xCA59, + 0xA550, 0xCA5A, 0xA551, 0xCA5B, 0xA552, 0xCA5E, 0xA553, 0xCA62, 0xA554, 0xCA63, 0xA555, 0xCA64, 0xA556, 0xCA65, 0xA557, 0xCA66, + 0xA558, 0xCA67, 0xA559, 0xCA69, 0xA55A, 0xCA6A, 0xA561, 0xCA6B, 0xA562, 0xCA6C, 0xA563, 0xCA6D, 0xA564, 0xCA6E, 0xA565, 0xCA6F, + 0xA566, 0xCA70, 0xA567, 0xCA71, 0xA568, 0xCA72, 0xA569, 0xCA73, 0xA56A, 0xCA74, 0xA56B, 0xCA75, 0xA56C, 0xCA76, 0xA56D, 0xCA77, + 0xA56E, 0xCA78, 0xA56F, 0xCA79, 0xA570, 0xCA7A, 0xA571, 0xCA7B, 0xA572, 0xCA7C, 0xA573, 0xCA7E, 0xA574, 0xCA7F, 0xA575, 0xCA80, + 0xA576, 0xCA81, 0xA577, 0xCA82, 0xA578, 0xCA83, 0xA579, 0xCA85, 0xA57A, 0xCA86, 0xA581, 0xCA87, 0xA582, 0xCA88, 0xA583, 0xCA89, + 0xA584, 0xCA8A, 0xA585, 0xCA8B, 0xA586, 0xCA8C, 0xA587, 0xCA8D, 0xA588, 0xCA8E, 0xA589, 0xCA8F, 0xA58A, 0xCA90, 0xA58B, 0xCA91, + 0xA58C, 0xCA92, 0xA58D, 0xCA93, 0xA58E, 0xCA94, 0xA58F, 0xCA95, 0xA590, 0xCA96, 0xA591, 0xCA97, 0xA592, 0xCA99, 0xA593, 0xCA9A, + 0xA594, 0xCA9B, 0xA595, 0xCA9C, 0xA596, 0xCA9D, 0xA597, 0xCA9E, 0xA598, 0xCA9F, 0xA599, 0xCAA0, 0xA59A, 0xCAA1, 0xA59B, 0xCAA2, + 0xA59C, 0xCAA3, 0xA59D, 0xCAA4, 0xA59E, 0xCAA5, 0xA59F, 0xCAA6, 0xA5A0, 0xCAA7, 0xA5A1, 0x2170, 0xA5A2, 0x2171, 0xA5A3, 0x2172, + 0xA5A4, 0x2173, 0xA5A5, 0x2174, 0xA5A6, 0x2175, 0xA5A7, 0x2176, 0xA5A8, 0x2177, 0xA5A9, 0x2178, 0xA5AA, 0x2179, 0xA5B0, 0x2160, + 0xA5B1, 0x2161, 0xA5B2, 0x2162, 0xA5B3, 0x2163, 0xA5B4, 0x2164, 0xA5B5, 0x2165, 0xA5B6, 0x2166, 0xA5B7, 0x2167, 0xA5B8, 0x2168, + 0xA5B9, 0x2169, 0xA5C1, 0x0391, 0xA5C2, 0x0392, 0xA5C3, 0x0393, 0xA5C4, 0x0394, 0xA5C5, 0x0395, 0xA5C6, 0x0396, 0xA5C7, 0x0397, + 0xA5C8, 0x0398, 0xA5C9, 0x0399, 0xA5CA, 0x039A, 0xA5CB, 0x039B, 0xA5CC, 0x039C, 0xA5CD, 0x039D, 0xA5CE, 0x039E, 0xA5CF, 0x039F, + 0xA5D0, 0x03A0, 0xA5D1, 0x03A1, 0xA5D2, 0x03A3, 0xA5D3, 0x03A4, 0xA5D4, 0x03A5, 0xA5D5, 0x03A6, 0xA5D6, 0x03A7, 0xA5D7, 0x03A8, + 0xA5D8, 0x03A9, 0xA5E1, 0x03B1, 0xA5E2, 0x03B2, 0xA5E3, 0x03B3, 0xA5E4, 0x03B4, 0xA5E5, 0x03B5, 0xA5E6, 0x03B6, 0xA5E7, 0x03B7, + 0xA5E8, 0x03B8, 0xA5E9, 0x03B9, 0xA5EA, 0x03BA, 0xA5EB, 0x03BB, 0xA5EC, 0x03BC, 0xA5ED, 0x03BD, 0xA5EE, 0x03BE, 0xA5EF, 0x03BF, + 0xA5F0, 0x03C0, 0xA5F1, 0x03C1, 0xA5F2, 0x03C3, 0xA5F3, 0x03C4, 0xA5F4, 0x03C5, 0xA5F5, 0x03C6, 0xA5F6, 0x03C7, 0xA5F7, 0x03C8, + 0xA5F8, 0x03C9, 0xA641, 0xCAA8, 0xA642, 0xCAA9, 0xA643, 0xCAAA, 0xA644, 0xCAAB, 0xA645, 0xCAAC, 0xA646, 0xCAAD, 0xA647, 0xCAAE, + 0xA648, 0xCAAF, 0xA649, 0xCAB0, 0xA64A, 0xCAB1, 0xA64B, 0xCAB2, 0xA64C, 0xCAB3, 0xA64D, 0xCAB4, 0xA64E, 0xCAB5, 0xA64F, 0xCAB6, + 0xA650, 0xCAB7, 0xA651, 0xCAB8, 0xA652, 0xCAB9, 0xA653, 0xCABA, 0xA654, 0xCABB, 0xA655, 0xCABE, 0xA656, 0xCABF, 0xA657, 0xCAC1, + 0xA658, 0xCAC2, 0xA659, 0xCAC3, 0xA65A, 0xCAC5, 0xA661, 0xCAC6, 0xA662, 0xCAC7, 0xA663, 0xCAC8, 0xA664, 0xCAC9, 0xA665, 0xCACA, + 0xA666, 0xCACB, 0xA667, 0xCACE, 0xA668, 0xCAD0, 0xA669, 0xCAD2, 0xA66A, 0xCAD4, 0xA66B, 0xCAD5, 0xA66C, 0xCAD6, 0xA66D, 0xCAD7, + 0xA66E, 0xCADA, 0xA66F, 0xCADB, 0xA670, 0xCADC, 0xA671, 0xCADD, 0xA672, 0xCADE, 0xA673, 0xCADF, 0xA674, 0xCAE1, 0xA675, 0xCAE2, + 0xA676, 0xCAE3, 0xA677, 0xCAE4, 0xA678, 0xCAE5, 0xA679, 0xCAE6, 0xA67A, 0xCAE7, 0xA681, 0xCAE8, 0xA682, 0xCAE9, 0xA683, 0xCAEA, + 0xA684, 0xCAEB, 0xA685, 0xCAED, 0xA686, 0xCAEE, 0xA687, 0xCAEF, 0xA688, 0xCAF0, 0xA689, 0xCAF1, 0xA68A, 0xCAF2, 0xA68B, 0xCAF3, + 0xA68C, 0xCAF5, 0xA68D, 0xCAF6, 0xA68E, 0xCAF7, 0xA68F, 0xCAF8, 0xA690, 0xCAF9, 0xA691, 0xCAFA, 0xA692, 0xCAFB, 0xA693, 0xCAFC, + 0xA694, 0xCAFD, 0xA695, 0xCAFE, 0xA696, 0xCAFF, 0xA697, 0xCB00, 0xA698, 0xCB01, 0xA699, 0xCB02, 0xA69A, 0xCB03, 0xA69B, 0xCB04, + 0xA69C, 0xCB05, 0xA69D, 0xCB06, 0xA69E, 0xCB07, 0xA69F, 0xCB09, 0xA6A0, 0xCB0A, 0xA6A1, 0x2500, 0xA6A2, 0x2502, 0xA6A3, 0x250C, + 0xA6A4, 0x2510, 0xA6A5, 0x2518, 0xA6A6, 0x2514, 0xA6A7, 0x251C, 0xA6A8, 0x252C, 0xA6A9, 0x2524, 0xA6AA, 0x2534, 0xA6AB, 0x253C, + 0xA6AC, 0x2501, 0xA6AD, 0x2503, 0xA6AE, 0x250F, 0xA6AF, 0x2513, 0xA6B0, 0x251B, 0xA6B1, 0x2517, 0xA6B2, 0x2523, 0xA6B3, 0x2533, + 0xA6B4, 0x252B, 0xA6B5, 0x253B, 0xA6B6, 0x254B, 0xA6B7, 0x2520, 0xA6B8, 0x252F, 0xA6B9, 0x2528, 0xA6BA, 0x2537, 0xA6BB, 0x253F, + 0xA6BC, 0x251D, 0xA6BD, 0x2530, 0xA6BE, 0x2525, 0xA6BF, 0x2538, 0xA6C0, 0x2542, 0xA6C1, 0x2512, 0xA6C2, 0x2511, 0xA6C3, 0x251A, + 0xA6C4, 0x2519, 0xA6C5, 0x2516, 0xA6C6, 0x2515, 0xA6C7, 0x250E, 0xA6C8, 0x250D, 0xA6C9, 0x251E, 0xA6CA, 0x251F, 0xA6CB, 0x2521, + 0xA6CC, 0x2522, 0xA6CD, 0x2526, 0xA6CE, 0x2527, 0xA6CF, 0x2529, 0xA6D0, 0x252A, 0xA6D1, 0x252D, 0xA6D2, 0x252E, 0xA6D3, 0x2531, + 0xA6D4, 0x2532, 0xA6D5, 0x2535, 0xA6D6, 0x2536, 0xA6D7, 0x2539, 0xA6D8, 0x253A, 0xA6D9, 0x253D, 0xA6DA, 0x253E, 0xA6DB, 0x2540, + 0xA6DC, 0x2541, 0xA6DD, 0x2543, 0xA6DE, 0x2544, 0xA6DF, 0x2545, 0xA6E0, 0x2546, 0xA6E1, 0x2547, 0xA6E2, 0x2548, 0xA6E3, 0x2549, + 0xA6E4, 0x254A, 0xA741, 0xCB0B, 0xA742, 0xCB0C, 0xA743, 0xCB0D, 0xA744, 0xCB0E, 0xA745, 0xCB0F, 0xA746, 0xCB11, 0xA747, 0xCB12, + 0xA748, 0xCB13, 0xA749, 0xCB15, 0xA74A, 0xCB16, 0xA74B, 0xCB17, 0xA74C, 0xCB19, 0xA74D, 0xCB1A, 0xA74E, 0xCB1B, 0xA74F, 0xCB1C, + 0xA750, 0xCB1D, 0xA751, 0xCB1E, 0xA752, 0xCB1F, 0xA753, 0xCB22, 0xA754, 0xCB23, 0xA755, 0xCB24, 0xA756, 0xCB25, 0xA757, 0xCB26, + 0xA758, 0xCB27, 0xA759, 0xCB28, 0xA75A, 0xCB29, 0xA761, 0xCB2A, 0xA762, 0xCB2B, 0xA763, 0xCB2C, 0xA764, 0xCB2D, 0xA765, 0xCB2E, + 0xA766, 0xCB2F, 0xA767, 0xCB30, 0xA768, 0xCB31, 0xA769, 0xCB32, 0xA76A, 0xCB33, 0xA76B, 0xCB34, 0xA76C, 0xCB35, 0xA76D, 0xCB36, + 0xA76E, 0xCB37, 0xA76F, 0xCB38, 0xA770, 0xCB39, 0xA771, 0xCB3A, 0xA772, 0xCB3B, 0xA773, 0xCB3C, 0xA774, 0xCB3D, 0xA775, 0xCB3E, + 0xA776, 0xCB3F, 0xA777, 0xCB40, 0xA778, 0xCB42, 0xA779, 0xCB43, 0xA77A, 0xCB44, 0xA781, 0xCB45, 0xA782, 0xCB46, 0xA783, 0xCB47, + 0xA784, 0xCB4A, 0xA785, 0xCB4B, 0xA786, 0xCB4D, 0xA787, 0xCB4E, 0xA788, 0xCB4F, 0xA789, 0xCB51, 0xA78A, 0xCB52, 0xA78B, 0xCB53, + 0xA78C, 0xCB54, 0xA78D, 0xCB55, 0xA78E, 0xCB56, 0xA78F, 0xCB57, 0xA790, 0xCB5A, 0xA791, 0xCB5B, 0xA792, 0xCB5C, 0xA793, 0xCB5E, + 0xA794, 0xCB5F, 0xA795, 0xCB60, 0xA796, 0xCB61, 0xA797, 0xCB62, 0xA798, 0xCB63, 0xA799, 0xCB65, 0xA79A, 0xCB66, 0xA79B, 0xCB67, + 0xA79C, 0xCB68, 0xA79D, 0xCB69, 0xA79E, 0xCB6A, 0xA79F, 0xCB6B, 0xA7A0, 0xCB6C, 0xA7A1, 0x3395, 0xA7A2, 0x3396, 0xA7A3, 0x3397, + 0xA7A4, 0x2113, 0xA7A5, 0x3398, 0xA7A6, 0x33C4, 0xA7A7, 0x33A3, 0xA7A8, 0x33A4, 0xA7A9, 0x33A5, 0xA7AA, 0x33A6, 0xA7AB, 0x3399, + 0xA7AC, 0x339A, 0xA7AD, 0x339B, 0xA7AE, 0x339C, 0xA7AF, 0x339D, 0xA7B0, 0x339E, 0xA7B1, 0x339F, 0xA7B2, 0x33A0, 0xA7B3, 0x33A1, + 0xA7B4, 0x33A2, 0xA7B5, 0x33CA, 0xA7B6, 0x338D, 0xA7B7, 0x338E, 0xA7B8, 0x338F, 0xA7B9, 0x33CF, 0xA7BA, 0x3388, 0xA7BB, 0x3389, + 0xA7BC, 0x33C8, 0xA7BD, 0x33A7, 0xA7BE, 0x33A8, 0xA7BF, 0x33B0, 0xA7C0, 0x33B1, 0xA7C1, 0x33B2, 0xA7C2, 0x33B3, 0xA7C3, 0x33B4, + 0xA7C4, 0x33B5, 0xA7C5, 0x33B6, 0xA7C6, 0x33B7, 0xA7C7, 0x33B8, 0xA7C8, 0x33B9, 0xA7C9, 0x3380, 0xA7CA, 0x3381, 0xA7CB, 0x3382, + 0xA7CC, 0x3383, 0xA7CD, 0x3384, 0xA7CE, 0x33BA, 0xA7CF, 0x33BB, 0xA7D0, 0x33BC, 0xA7D1, 0x33BD, 0xA7D2, 0x33BE, 0xA7D3, 0x33BF, + 0xA7D4, 0x3390, 0xA7D5, 0x3391, 0xA7D6, 0x3392, 0xA7D7, 0x3393, 0xA7D8, 0x3394, 0xA7D9, 0x2126, 0xA7DA, 0x33C0, 0xA7DB, 0x33C1, + 0xA7DC, 0x338A, 0xA7DD, 0x338B, 0xA7DE, 0x338C, 0xA7DF, 0x33D6, 0xA7E0, 0x33C5, 0xA7E1, 0x33AD, 0xA7E2, 0x33AE, 0xA7E3, 0x33AF, + 0xA7E4, 0x33DB, 0xA7E5, 0x33A9, 0xA7E6, 0x33AA, 0xA7E7, 0x33AB, 0xA7E8, 0x33AC, 0xA7E9, 0x33DD, 0xA7EA, 0x33D0, 0xA7EB, 0x33D3, + 0xA7EC, 0x33C3, 0xA7ED, 0x33C9, 0xA7EE, 0x33DC, 0xA7EF, 0x33C6, 0xA841, 0xCB6D, 0xA842, 0xCB6E, 0xA843, 0xCB6F, 0xA844, 0xCB70, + 0xA845, 0xCB71, 0xA846, 0xCB72, 0xA847, 0xCB73, 0xA848, 0xCB74, 0xA849, 0xCB75, 0xA84A, 0xCB76, 0xA84B, 0xCB77, 0xA84C, 0xCB7A, + 0xA84D, 0xCB7B, 0xA84E, 0xCB7C, 0xA84F, 0xCB7D, 0xA850, 0xCB7E, 0xA851, 0xCB7F, 0xA852, 0xCB80, 0xA853, 0xCB81, 0xA854, 0xCB82, + 0xA855, 0xCB83, 0xA856, 0xCB84, 0xA857, 0xCB85, 0xA858, 0xCB86, 0xA859, 0xCB87, 0xA85A, 0xCB88, 0xA861, 0xCB89, 0xA862, 0xCB8A, + 0xA863, 0xCB8B, 0xA864, 0xCB8C, 0xA865, 0xCB8D, 0xA866, 0xCB8E, 0xA867, 0xCB8F, 0xA868, 0xCB90, 0xA869, 0xCB91, 0xA86A, 0xCB92, + 0xA86B, 0xCB93, 0xA86C, 0xCB94, 0xA86D, 0xCB95, 0xA86E, 0xCB96, 0xA86F, 0xCB97, 0xA870, 0xCB98, 0xA871, 0xCB99, 0xA872, 0xCB9A, + 0xA873, 0xCB9B, 0xA874, 0xCB9D, 0xA875, 0xCB9E, 0xA876, 0xCB9F, 0xA877, 0xCBA0, 0xA878, 0xCBA1, 0xA879, 0xCBA2, 0xA87A, 0xCBA3, + 0xA881, 0xCBA4, 0xA882, 0xCBA5, 0xA883, 0xCBA6, 0xA884, 0xCBA7, 0xA885, 0xCBA8, 0xA886, 0xCBA9, 0xA887, 0xCBAA, 0xA888, 0xCBAB, + 0xA889, 0xCBAC, 0xA88A, 0xCBAD, 0xA88B, 0xCBAE, 0xA88C, 0xCBAF, 0xA88D, 0xCBB0, 0xA88E, 0xCBB1, 0xA88F, 0xCBB2, 0xA890, 0xCBB3, + 0xA891, 0xCBB4, 0xA892, 0xCBB5, 0xA893, 0xCBB6, 0xA894, 0xCBB7, 0xA895, 0xCBB9, 0xA896, 0xCBBA, 0xA897, 0xCBBB, 0xA898, 0xCBBC, + 0xA899, 0xCBBD, 0xA89A, 0xCBBE, 0xA89B, 0xCBBF, 0xA89C, 0xCBC0, 0xA89D, 0xCBC1, 0xA89E, 0xCBC2, 0xA89F, 0xCBC3, 0xA8A0, 0xCBC4, + 0xA8A1, 0x00C6, 0xA8A2, 0x00D0, 0xA8A3, 0x00AA, 0xA8A4, 0x0126, 0xA8A6, 0x0132, 0xA8A8, 0x013F, 0xA8A9, 0x0141, 0xA8AA, 0x00D8, + 0xA8AB, 0x0152, 0xA8AC, 0x00BA, 0xA8AD, 0x00DE, 0xA8AE, 0x0166, 0xA8AF, 0x014A, 0xA8B1, 0x3260, 0xA8B2, 0x3261, 0xA8B3, 0x3262, + 0xA8B4, 0x3263, 0xA8B5, 0x3264, 0xA8B6, 0x3265, 0xA8B7, 0x3266, 0xA8B8, 0x3267, 0xA8B9, 0x3268, 0xA8BA, 0x3269, 0xA8BB, 0x326A, + 0xA8BC, 0x326B, 0xA8BD, 0x326C, 0xA8BE, 0x326D, 0xA8BF, 0x326E, 0xA8C0, 0x326F, 0xA8C1, 0x3270, 0xA8C2, 0x3271, 0xA8C3, 0x3272, + 0xA8C4, 0x3273, 0xA8C5, 0x3274, 0xA8C6, 0x3275, 0xA8C7, 0x3276, 0xA8C8, 0x3277, 0xA8C9, 0x3278, 0xA8CA, 0x3279, 0xA8CB, 0x327A, + 0xA8CC, 0x327B, 0xA8CD, 0x24D0, 0xA8CE, 0x24D1, 0xA8CF, 0x24D2, 0xA8D0, 0x24D3, 0xA8D1, 0x24D4, 0xA8D2, 0x24D5, 0xA8D3, 0x24D6, + 0xA8D4, 0x24D7, 0xA8D5, 0x24D8, 0xA8D6, 0x24D9, 0xA8D7, 0x24DA, 0xA8D8, 0x24DB, 0xA8D9, 0x24DC, 0xA8DA, 0x24DD, 0xA8DB, 0x24DE, + 0xA8DC, 0x24DF, 0xA8DD, 0x24E0, 0xA8DE, 0x24E1, 0xA8DF, 0x24E2, 0xA8E0, 0x24E3, 0xA8E1, 0x24E4, 0xA8E2, 0x24E5, 0xA8E3, 0x24E6, + 0xA8E4, 0x24E7, 0xA8E5, 0x24E8, 0xA8E6, 0x24E9, 0xA8E7, 0x2460, 0xA8E8, 0x2461, 0xA8E9, 0x2462, 0xA8EA, 0x2463, 0xA8EB, 0x2464, + 0xA8EC, 0x2465, 0xA8ED, 0x2466, 0xA8EE, 0x2467, 0xA8EF, 0x2468, 0xA8F0, 0x2469, 0xA8F1, 0x246A, 0xA8F2, 0x246B, 0xA8F3, 0x246C, + 0xA8F4, 0x246D, 0xA8F5, 0x246E, 0xA8F6, 0x00BD, 0xA8F7, 0x2153, 0xA8F8, 0x2154, 0xA8F9, 0x00BC, 0xA8FA, 0x00BE, 0xA8FB, 0x215B, + 0xA8FC, 0x215C, 0xA8FD, 0x215D, 0xA8FE, 0x215E, 0xA941, 0xCBC5, 0xA942, 0xCBC6, 0xA943, 0xCBC7, 0xA944, 0xCBC8, 0xA945, 0xCBC9, + 0xA946, 0xCBCA, 0xA947, 0xCBCB, 0xA948, 0xCBCC, 0xA949, 0xCBCD, 0xA94A, 0xCBCE, 0xA94B, 0xCBCF, 0xA94C, 0xCBD0, 0xA94D, 0xCBD1, + 0xA94E, 0xCBD2, 0xA94F, 0xCBD3, 0xA950, 0xCBD5, 0xA951, 0xCBD6, 0xA952, 0xCBD7, 0xA953, 0xCBD8, 0xA954, 0xCBD9, 0xA955, 0xCBDA, + 0xA956, 0xCBDB, 0xA957, 0xCBDC, 0xA958, 0xCBDD, 0xA959, 0xCBDE, 0xA95A, 0xCBDF, 0xA961, 0xCBE0, 0xA962, 0xCBE1, 0xA963, 0xCBE2, + 0xA964, 0xCBE3, 0xA965, 0xCBE5, 0xA966, 0xCBE6, 0xA967, 0xCBE8, 0xA968, 0xCBEA, 0xA969, 0xCBEB, 0xA96A, 0xCBEC, 0xA96B, 0xCBED, + 0xA96C, 0xCBEE, 0xA96D, 0xCBEF, 0xA96E, 0xCBF0, 0xA96F, 0xCBF1, 0xA970, 0xCBF2, 0xA971, 0xCBF3, 0xA972, 0xCBF4, 0xA973, 0xCBF5, + 0xA974, 0xCBF6, 0xA975, 0xCBF7, 0xA976, 0xCBF8, 0xA977, 0xCBF9, 0xA978, 0xCBFA, 0xA979, 0xCBFB, 0xA97A, 0xCBFC, 0xA981, 0xCBFD, + 0xA982, 0xCBFE, 0xA983, 0xCBFF, 0xA984, 0xCC00, 0xA985, 0xCC01, 0xA986, 0xCC02, 0xA987, 0xCC03, 0xA988, 0xCC04, 0xA989, 0xCC05, + 0xA98A, 0xCC06, 0xA98B, 0xCC07, 0xA98C, 0xCC08, 0xA98D, 0xCC09, 0xA98E, 0xCC0A, 0xA98F, 0xCC0B, 0xA990, 0xCC0E, 0xA991, 0xCC0F, + 0xA992, 0xCC11, 0xA993, 0xCC12, 0xA994, 0xCC13, 0xA995, 0xCC15, 0xA996, 0xCC16, 0xA997, 0xCC17, 0xA998, 0xCC18, 0xA999, 0xCC19, + 0xA99A, 0xCC1A, 0xA99B, 0xCC1B, 0xA99C, 0xCC1E, 0xA99D, 0xCC1F, 0xA99E, 0xCC20, 0xA99F, 0xCC23, 0xA9A0, 0xCC24, 0xA9A1, 0x00E6, + 0xA9A2, 0x0111, 0xA9A3, 0x00F0, 0xA9A4, 0x0127, 0xA9A5, 0x0131, 0xA9A6, 0x0133, 0xA9A7, 0x0138, 0xA9A8, 0x0140, 0xA9A9, 0x0142, + 0xA9AA, 0x00F8, 0xA9AB, 0x0153, 0xA9AC, 0x00DF, 0xA9AD, 0x00FE, 0xA9AE, 0x0167, 0xA9AF, 0x014B, 0xA9B0, 0x0149, 0xA9B1, 0x3200, + 0xA9B2, 0x3201, 0xA9B3, 0x3202, 0xA9B4, 0x3203, 0xA9B5, 0x3204, 0xA9B6, 0x3205, 0xA9B7, 0x3206, 0xA9B8, 0x3207, 0xA9B9, 0x3208, + 0xA9BA, 0x3209, 0xA9BB, 0x320A, 0xA9BC, 0x320B, 0xA9BD, 0x320C, 0xA9BE, 0x320D, 0xA9BF, 0x320E, 0xA9C0, 0x320F, 0xA9C1, 0x3210, + 0xA9C2, 0x3211, 0xA9C3, 0x3212, 0xA9C4, 0x3213, 0xA9C5, 0x3214, 0xA9C6, 0x3215, 0xA9C7, 0x3216, 0xA9C8, 0x3217, 0xA9C9, 0x3218, + 0xA9CA, 0x3219, 0xA9CB, 0x321A, 0xA9CC, 0x321B, 0xA9CD, 0x249C, 0xA9CE, 0x249D, 0xA9CF, 0x249E, 0xA9D0, 0x249F, 0xA9D1, 0x24A0, + 0xA9D2, 0x24A1, 0xA9D3, 0x24A2, 0xA9D4, 0x24A3, 0xA9D5, 0x24A4, 0xA9D6, 0x24A5, 0xA9D7, 0x24A6, 0xA9D8, 0x24A7, 0xA9D9, 0x24A8, + 0xA9DA, 0x24A9, 0xA9DB, 0x24AA, 0xA9DC, 0x24AB, 0xA9DD, 0x24AC, 0xA9DE, 0x24AD, 0xA9DF, 0x24AE, 0xA9E0, 0x24AF, 0xA9E1, 0x24B0, + 0xA9E2, 0x24B1, 0xA9E3, 0x24B2, 0xA9E4, 0x24B3, 0xA9E5, 0x24B4, 0xA9E6, 0x24B5, 0xA9E7, 0x2474, 0xA9E8, 0x2475, 0xA9E9, 0x2476, + 0xA9EA, 0x2477, 0xA9EB, 0x2478, 0xA9EC, 0x2479, 0xA9ED, 0x247A, 0xA9EE, 0x247B, 0xA9EF, 0x247C, 0xA9F0, 0x247D, 0xA9F1, 0x247E, + 0xA9F2, 0x247F, 0xA9F3, 0x2480, 0xA9F4, 0x2481, 0xA9F5, 0x2482, 0xA9F6, 0x00B9, 0xA9F7, 0x00B2, 0xA9F8, 0x00B3, 0xA9F9, 0x2074, + 0xA9FA, 0x207F, 0xA9FB, 0x2081, 0xA9FC, 0x2082, 0xA9FD, 0x2083, 0xA9FE, 0x2084, 0xAA41, 0xCC25, 0xAA42, 0xCC26, 0xAA43, 0xCC2A, + 0xAA44, 0xCC2B, 0xAA45, 0xCC2D, 0xAA46, 0xCC2F, 0xAA47, 0xCC31, 0xAA48, 0xCC32, 0xAA49, 0xCC33, 0xAA4A, 0xCC34, 0xAA4B, 0xCC35, + 0xAA4C, 0xCC36, 0xAA4D, 0xCC37, 0xAA4E, 0xCC3A, 0xAA4F, 0xCC3F, 0xAA50, 0xCC40, 0xAA51, 0xCC41, 0xAA52, 0xCC42, 0xAA53, 0xCC43, + 0xAA54, 0xCC46, 0xAA55, 0xCC47, 0xAA56, 0xCC49, 0xAA57, 0xCC4A, 0xAA58, 0xCC4B, 0xAA59, 0xCC4D, 0xAA5A, 0xCC4E, 0xAA61, 0xCC4F, + 0xAA62, 0xCC50, 0xAA63, 0xCC51, 0xAA64, 0xCC52, 0xAA65, 0xCC53, 0xAA66, 0xCC56, 0xAA67, 0xCC5A, 0xAA68, 0xCC5B, 0xAA69, 0xCC5C, + 0xAA6A, 0xCC5D, 0xAA6B, 0xCC5E, 0xAA6C, 0xCC5F, 0xAA6D, 0xCC61, 0xAA6E, 0xCC62, 0xAA6F, 0xCC63, 0xAA70, 0xCC65, 0xAA71, 0xCC67, + 0xAA72, 0xCC69, 0xAA73, 0xCC6A, 0xAA74, 0xCC6B, 0xAA75, 0xCC6C, 0xAA76, 0xCC6D, 0xAA77, 0xCC6E, 0xAA78, 0xCC6F, 0xAA79, 0xCC71, + 0xAA7A, 0xCC72, 0xAA81, 0xCC73, 0xAA82, 0xCC74, 0xAA83, 0xCC76, 0xAA84, 0xCC77, 0xAA85, 0xCC78, 0xAA86, 0xCC79, 0xAA87, 0xCC7A, + 0xAA88, 0xCC7B, 0xAA89, 0xCC7C, 0xAA8A, 0xCC7D, 0xAA8B, 0xCC7E, 0xAA8C, 0xCC7F, 0xAA8D, 0xCC80, 0xAA8E, 0xCC81, 0xAA8F, 0xCC82, + 0xAA90, 0xCC83, 0xAA91, 0xCC84, 0xAA92, 0xCC85, 0xAA93, 0xCC86, 0xAA94, 0xCC87, 0xAA95, 0xCC88, 0xAA96, 0xCC89, 0xAA97, 0xCC8A, + 0xAA98, 0xCC8B, 0xAA99, 0xCC8C, 0xAA9A, 0xCC8D, 0xAA9B, 0xCC8E, 0xAA9C, 0xCC8F, 0xAA9D, 0xCC90, 0xAA9E, 0xCC91, 0xAA9F, 0xCC92, + 0xAAA0, 0xCC93, 0xAAA1, 0x3041, 0xAAA2, 0x3042, 0xAAA3, 0x3043, 0xAAA4, 0x3044, 0xAAA5, 0x3045, 0xAAA6, 0x3046, 0xAAA7, 0x3047, + 0xAAA8, 0x3048, 0xAAA9, 0x3049, 0xAAAA, 0x304A, 0xAAAB, 0x304B, 0xAAAC, 0x304C, 0xAAAD, 0x304D, 0xAAAE, 0x304E, 0xAAAF, 0x304F, + 0xAAB0, 0x3050, 0xAAB1, 0x3051, 0xAAB2, 0x3052, 0xAAB3, 0x3053, 0xAAB4, 0x3054, 0xAAB5, 0x3055, 0xAAB6, 0x3056, 0xAAB7, 0x3057, + 0xAAB8, 0x3058, 0xAAB9, 0x3059, 0xAABA, 0x305A, 0xAABB, 0x305B, 0xAABC, 0x305C, 0xAABD, 0x305D, 0xAABE, 0x305E, 0xAABF, 0x305F, + 0xAAC0, 0x3060, 0xAAC1, 0x3061, 0xAAC2, 0x3062, 0xAAC3, 0x3063, 0xAAC4, 0x3064, 0xAAC5, 0x3065, 0xAAC6, 0x3066, 0xAAC7, 0x3067, + 0xAAC8, 0x3068, 0xAAC9, 0x3069, 0xAACA, 0x306A, 0xAACB, 0x306B, 0xAACC, 0x306C, 0xAACD, 0x306D, 0xAACE, 0x306E, 0xAACF, 0x306F, + 0xAAD0, 0x3070, 0xAAD1, 0x3071, 0xAAD2, 0x3072, 0xAAD3, 0x3073, 0xAAD4, 0x3074, 0xAAD5, 0x3075, 0xAAD6, 0x3076, 0xAAD7, 0x3077, + 0xAAD8, 0x3078, 0xAAD9, 0x3079, 0xAADA, 0x307A, 0xAADB, 0x307B, 0xAADC, 0x307C, 0xAADD, 0x307D, 0xAADE, 0x307E, 0xAADF, 0x307F, + 0xAAE0, 0x3080, 0xAAE1, 0x3081, 0xAAE2, 0x3082, 0xAAE3, 0x3083, 0xAAE4, 0x3084, 0xAAE5, 0x3085, 0xAAE6, 0x3086, 0xAAE7, 0x3087, + 0xAAE8, 0x3088, 0xAAE9, 0x3089, 0xAAEA, 0x308A, 0xAAEB, 0x308B, 0xAAEC, 0x308C, 0xAAED, 0x308D, 0xAAEE, 0x308E, 0xAAEF, 0x308F, + 0xAAF0, 0x3090, 0xAAF1, 0x3091, 0xAAF2, 0x3092, 0xAAF3, 0x3093, 0xAB41, 0xCC94, 0xAB42, 0xCC95, 0xAB43, 0xCC96, 0xAB44, 0xCC97, + 0xAB45, 0xCC9A, 0xAB46, 0xCC9B, 0xAB47, 0xCC9D, 0xAB48, 0xCC9E, 0xAB49, 0xCC9F, 0xAB4A, 0xCCA1, 0xAB4B, 0xCCA2, 0xAB4C, 0xCCA3, + 0xAB4D, 0xCCA4, 0xAB4E, 0xCCA5, 0xAB4F, 0xCCA6, 0xAB50, 0xCCA7, 0xAB51, 0xCCAA, 0xAB52, 0xCCAE, 0xAB53, 0xCCAF, 0xAB54, 0xCCB0, + 0xAB55, 0xCCB1, 0xAB56, 0xCCB2, 0xAB57, 0xCCB3, 0xAB58, 0xCCB6, 0xAB59, 0xCCB7, 0xAB5A, 0xCCB9, 0xAB61, 0xCCBA, 0xAB62, 0xCCBB, + 0xAB63, 0xCCBD, 0xAB64, 0xCCBE, 0xAB65, 0xCCBF, 0xAB66, 0xCCC0, 0xAB67, 0xCCC1, 0xAB68, 0xCCC2, 0xAB69, 0xCCC3, 0xAB6A, 0xCCC6, + 0xAB6B, 0xCCC8, 0xAB6C, 0xCCCA, 0xAB6D, 0xCCCB, 0xAB6E, 0xCCCC, 0xAB6F, 0xCCCD, 0xAB70, 0xCCCE, 0xAB71, 0xCCCF, 0xAB72, 0xCCD1, + 0xAB73, 0xCCD2, 0xAB74, 0xCCD3, 0xAB75, 0xCCD5, 0xAB76, 0xCCD6, 0xAB77, 0xCCD7, 0xAB78, 0xCCD8, 0xAB79, 0xCCD9, 0xAB7A, 0xCCDA, + 0xAB81, 0xCCDB, 0xAB82, 0xCCDC, 0xAB83, 0xCCDD, 0xAB84, 0xCCDE, 0xAB85, 0xCCDF, 0xAB86, 0xCCE0, 0xAB87, 0xCCE1, 0xAB88, 0xCCE2, + 0xAB89, 0xCCE3, 0xAB8A, 0xCCE5, 0xAB8B, 0xCCE6, 0xAB8C, 0xCCE7, 0xAB8D, 0xCCE8, 0xAB8E, 0xCCE9, 0xAB8F, 0xCCEA, 0xAB90, 0xCCEB, + 0xAB91, 0xCCED, 0xAB92, 0xCCEE, 0xAB93, 0xCCEF, 0xAB94, 0xCCF1, 0xAB95, 0xCCF2, 0xAB96, 0xCCF3, 0xAB97, 0xCCF4, 0xAB98, 0xCCF5, + 0xAB99, 0xCCF6, 0xAB9A, 0xCCF7, 0xAB9B, 0xCCF8, 0xAB9C, 0xCCF9, 0xAB9D, 0xCCFA, 0xAB9E, 0xCCFB, 0xAB9F, 0xCCFC, 0xABA0, 0xCCFD, + 0xABA1, 0x30A1, 0xABA2, 0x30A2, 0xABA3, 0x30A3, 0xABA4, 0x30A4, 0xABA5, 0x30A5, 0xABA6, 0x30A6, 0xABA7, 0x30A7, 0xABA8, 0x30A8, + 0xABA9, 0x30A9, 0xABAA, 0x30AA, 0xABAB, 0x30AB, 0xABAC, 0x30AC, 0xABAD, 0x30AD, 0xABAE, 0x30AE, 0xABAF, 0x30AF, 0xABB0, 0x30B0, + 0xABB1, 0x30B1, 0xABB2, 0x30B2, 0xABB3, 0x30B3, 0xABB4, 0x30B4, 0xABB5, 0x30B5, 0xABB6, 0x30B6, 0xABB7, 0x30B7, 0xABB8, 0x30B8, + 0xABB9, 0x30B9, 0xABBA, 0x30BA, 0xABBB, 0x30BB, 0xABBC, 0x30BC, 0xABBD, 0x30BD, 0xABBE, 0x30BE, 0xABBF, 0x30BF, 0xABC0, 0x30C0, + 0xABC1, 0x30C1, 0xABC2, 0x30C2, 0xABC3, 0x30C3, 0xABC4, 0x30C4, 0xABC5, 0x30C5, 0xABC6, 0x30C6, 0xABC7, 0x30C7, 0xABC8, 0x30C8, + 0xABC9, 0x30C9, 0xABCA, 0x30CA, 0xABCB, 0x30CB, 0xABCC, 0x30CC, 0xABCD, 0x30CD, 0xABCE, 0x30CE, 0xABCF, 0x30CF, 0xABD0, 0x30D0, + 0xABD1, 0x30D1, 0xABD2, 0x30D2, 0xABD3, 0x30D3, 0xABD4, 0x30D4, 0xABD5, 0x30D5, 0xABD6, 0x30D6, 0xABD7, 0x30D7, 0xABD8, 0x30D8, + 0xABD9, 0x30D9, 0xABDA, 0x30DA, 0xABDB, 0x30DB, 0xABDC, 0x30DC, 0xABDD, 0x30DD, 0xABDE, 0x30DE, 0xABDF, 0x30DF, 0xABE0, 0x30E0, + 0xABE1, 0x30E1, 0xABE2, 0x30E2, 0xABE3, 0x30E3, 0xABE4, 0x30E4, 0xABE5, 0x30E5, 0xABE6, 0x30E6, 0xABE7, 0x30E7, 0xABE8, 0x30E8, + 0xABE9, 0x30E9, 0xABEA, 0x30EA, 0xABEB, 0x30EB, 0xABEC, 0x30EC, 0xABED, 0x30ED, 0xABEE, 0x30EE, 0xABEF, 0x30EF, 0xABF0, 0x30F0, + 0xABF1, 0x30F1, 0xABF2, 0x30F2, 0xABF3, 0x30F3, 0xABF4, 0x30F4, 0xABF5, 0x30F5, 0xABF6, 0x30F6, 0xAC41, 0xCCFE, 0xAC42, 0xCCFF, + 0xAC43, 0xCD00, 0xAC44, 0xCD02, 0xAC45, 0xCD03, 0xAC46, 0xCD04, 0xAC47, 0xCD05, 0xAC48, 0xCD06, 0xAC49, 0xCD07, 0xAC4A, 0xCD0A, + 0xAC4B, 0xCD0B, 0xAC4C, 0xCD0D, 0xAC4D, 0xCD0E, 0xAC4E, 0xCD0F, 0xAC4F, 0xCD11, 0xAC50, 0xCD12, 0xAC51, 0xCD13, 0xAC52, 0xCD14, + 0xAC53, 0xCD15, 0xAC54, 0xCD16, 0xAC55, 0xCD17, 0xAC56, 0xCD1A, 0xAC57, 0xCD1C, 0xAC58, 0xCD1E, 0xAC59, 0xCD1F, 0xAC5A, 0xCD20, + 0xAC61, 0xCD21, 0xAC62, 0xCD22, 0xAC63, 0xCD23, 0xAC64, 0xCD25, 0xAC65, 0xCD26, 0xAC66, 0xCD27, 0xAC67, 0xCD29, 0xAC68, 0xCD2A, + 0xAC69, 0xCD2B, 0xAC6A, 0xCD2D, 0xAC6B, 0xCD2E, 0xAC6C, 0xCD2F, 0xAC6D, 0xCD30, 0xAC6E, 0xCD31, 0xAC6F, 0xCD32, 0xAC70, 0xCD33, + 0xAC71, 0xCD34, 0xAC72, 0xCD35, 0xAC73, 0xCD36, 0xAC74, 0xCD37, 0xAC75, 0xCD38, 0xAC76, 0xCD3A, 0xAC77, 0xCD3B, 0xAC78, 0xCD3C, + 0xAC79, 0xCD3D, 0xAC7A, 0xCD3E, 0xAC81, 0xCD3F, 0xAC82, 0xCD40, 0xAC83, 0xCD41, 0xAC84, 0xCD42, 0xAC85, 0xCD43, 0xAC86, 0xCD44, + 0xAC87, 0xCD45, 0xAC88, 0xCD46, 0xAC89, 0xCD47, 0xAC8A, 0xCD48, 0xAC8B, 0xCD49, 0xAC8C, 0xCD4A, 0xAC8D, 0xCD4B, 0xAC8E, 0xCD4C, + 0xAC8F, 0xCD4D, 0xAC90, 0xCD4E, 0xAC91, 0xCD4F, 0xAC92, 0xCD50, 0xAC93, 0xCD51, 0xAC94, 0xCD52, 0xAC95, 0xCD53, 0xAC96, 0xCD54, + 0xAC97, 0xCD55, 0xAC98, 0xCD56, 0xAC99, 0xCD57, 0xAC9A, 0xCD58, 0xAC9B, 0xCD59, 0xAC9C, 0xCD5A, 0xAC9D, 0xCD5B, 0xAC9E, 0xCD5D, + 0xAC9F, 0xCD5E, 0xACA0, 0xCD5F, 0xACA1, 0x0410, 0xACA2, 0x0411, 0xACA3, 0x0412, 0xACA4, 0x0413, 0xACA5, 0x0414, 0xACA6, 0x0415, + 0xACA7, 0x0401, 0xACA8, 0x0416, 0xACA9, 0x0417, 0xACAA, 0x0418, 0xACAB, 0x0419, 0xACAC, 0x041A, 0xACAD, 0x041B, 0xACAE, 0x041C, + 0xACAF, 0x041D, 0xACB0, 0x041E, 0xACB1, 0x041F, 0xACB2, 0x0420, 0xACB3, 0x0421, 0xACB4, 0x0422, 0xACB5, 0x0423, 0xACB6, 0x0424, + 0xACB7, 0x0425, 0xACB8, 0x0426, 0xACB9, 0x0427, 0xACBA, 0x0428, 0xACBB, 0x0429, 0xACBC, 0x042A, 0xACBD, 0x042B, 0xACBE, 0x042C, + 0xACBF, 0x042D, 0xACC0, 0x042E, 0xACC1, 0x042F, 0xACD1, 0x0430, 0xACD2, 0x0431, 0xACD3, 0x0432, 0xACD4, 0x0433, 0xACD5, 0x0434, + 0xACD6, 0x0435, 0xACD7, 0x0451, 0xACD8, 0x0436, 0xACD9, 0x0437, 0xACDA, 0x0438, 0xACDB, 0x0439, 0xACDC, 0x043A, 0xACDD, 0x043B, + 0xACDE, 0x043C, 0xACDF, 0x043D, 0xACE0, 0x043E, 0xACE1, 0x043F, 0xACE2, 0x0440, 0xACE3, 0x0441, 0xACE4, 0x0442, 0xACE5, 0x0443, + 0xACE6, 0x0444, 0xACE7, 0x0445, 0xACE8, 0x0446, 0xACE9, 0x0447, 0xACEA, 0x0448, 0xACEB, 0x0449, 0xACEC, 0x044A, 0xACED, 0x044B, + 0xACEE, 0x044C, 0xACEF, 0x044D, 0xACF0, 0x044E, 0xACF1, 0x044F, 0xAD41, 0xCD61, 0xAD42, 0xCD62, 0xAD43, 0xCD63, 0xAD44, 0xCD65, + 0xAD45, 0xCD66, 0xAD46, 0xCD67, 0xAD47, 0xCD68, 0xAD48, 0xCD69, 0xAD49, 0xCD6A, 0xAD4A, 0xCD6B, 0xAD4B, 0xCD6E, 0xAD4C, 0xCD70, + 0xAD4D, 0xCD72, 0xAD4E, 0xCD73, 0xAD4F, 0xCD74, 0xAD50, 0xCD75, 0xAD51, 0xCD76, 0xAD52, 0xCD77, 0xAD53, 0xCD79, 0xAD54, 0xCD7A, + 0xAD55, 0xCD7B, 0xAD56, 0xCD7C, 0xAD57, 0xCD7D, 0xAD58, 0xCD7E, 0xAD59, 0xCD7F, 0xAD5A, 0xCD80, 0xAD61, 0xCD81, 0xAD62, 0xCD82, + 0xAD63, 0xCD83, 0xAD64, 0xCD84, 0xAD65, 0xCD85, 0xAD66, 0xCD86, 0xAD67, 0xCD87, 0xAD68, 0xCD89, 0xAD69, 0xCD8A, 0xAD6A, 0xCD8B, + 0xAD6B, 0xCD8C, 0xAD6C, 0xCD8D, 0xAD6D, 0xCD8E, 0xAD6E, 0xCD8F, 0xAD6F, 0xCD90, 0xAD70, 0xCD91, 0xAD71, 0xCD92, 0xAD72, 0xCD93, + 0xAD73, 0xCD96, 0xAD74, 0xCD97, 0xAD75, 0xCD99, 0xAD76, 0xCD9A, 0xAD77, 0xCD9B, 0xAD78, 0xCD9D, 0xAD79, 0xCD9E, 0xAD7A, 0xCD9F, + 0xAD81, 0xCDA0, 0xAD82, 0xCDA1, 0xAD83, 0xCDA2, 0xAD84, 0xCDA3, 0xAD85, 0xCDA6, 0xAD86, 0xCDA8, 0xAD87, 0xCDAA, 0xAD88, 0xCDAB, + 0xAD89, 0xCDAC, 0xAD8A, 0xCDAD, 0xAD8B, 0xCDAE, 0xAD8C, 0xCDAF, 0xAD8D, 0xCDB1, 0xAD8E, 0xCDB2, 0xAD8F, 0xCDB3, 0xAD90, 0xCDB4, + 0xAD91, 0xCDB5, 0xAD92, 0xCDB6, 0xAD93, 0xCDB7, 0xAD94, 0xCDB8, 0xAD95, 0xCDB9, 0xAD96, 0xCDBA, 0xAD97, 0xCDBB, 0xAD98, 0xCDBC, + 0xAD99, 0xCDBD, 0xAD9A, 0xCDBE, 0xAD9B, 0xCDBF, 0xAD9C, 0xCDC0, 0xAD9D, 0xCDC1, 0xAD9E, 0xCDC2, 0xAD9F, 0xCDC3, 0xADA0, 0xCDC5, + 0xAE41, 0xCDC6, 0xAE42, 0xCDC7, 0xAE43, 0xCDC8, 0xAE44, 0xCDC9, 0xAE45, 0xCDCA, 0xAE46, 0xCDCB, 0xAE47, 0xCDCD, 0xAE48, 0xCDCE, + 0xAE49, 0xCDCF, 0xAE4A, 0xCDD1, 0xAE4B, 0xCDD2, 0xAE4C, 0xCDD3, 0xAE4D, 0xCDD4, 0xAE4E, 0xCDD5, 0xAE4F, 0xCDD6, 0xAE50, 0xCDD7, + 0xAE51, 0xCDD8, 0xAE52, 0xCDD9, 0xAE53, 0xCDDA, 0xAE54, 0xCDDB, 0xAE55, 0xCDDC, 0xAE56, 0xCDDD, 0xAE57, 0xCDDE, 0xAE58, 0xCDDF, + 0xAE59, 0xCDE0, 0xAE5A, 0xCDE1, 0xAE61, 0xCDE2, 0xAE62, 0xCDE3, 0xAE63, 0xCDE4, 0xAE64, 0xCDE5, 0xAE65, 0xCDE6, 0xAE66, 0xCDE7, + 0xAE67, 0xCDE9, 0xAE68, 0xCDEA, 0xAE69, 0xCDEB, 0xAE6A, 0xCDED, 0xAE6B, 0xCDEE, 0xAE6C, 0xCDEF, 0xAE6D, 0xCDF1, 0xAE6E, 0xCDF2, + 0xAE6F, 0xCDF3, 0xAE70, 0xCDF4, 0xAE71, 0xCDF5, 0xAE72, 0xCDF6, 0xAE73, 0xCDF7, 0xAE74, 0xCDFA, 0xAE75, 0xCDFC, 0xAE76, 0xCDFE, + 0xAE77, 0xCDFF, 0xAE78, 0xCE00, 0xAE79, 0xCE01, 0xAE7A, 0xCE02, 0xAE81, 0xCE03, 0xAE82, 0xCE05, 0xAE83, 0xCE06, 0xAE84, 0xCE07, + 0xAE85, 0xCE09, 0xAE86, 0xCE0A, 0xAE87, 0xCE0B, 0xAE88, 0xCE0D, 0xAE89, 0xCE0E, 0xAE8A, 0xCE0F, 0xAE8B, 0xCE10, 0xAE8C, 0xCE11, + 0xAE8D, 0xCE12, 0xAE8E, 0xCE13, 0xAE8F, 0xCE15, 0xAE90, 0xCE16, 0xAE91, 0xCE17, 0xAE92, 0xCE18, 0xAE93, 0xCE1A, 0xAE94, 0xCE1B, + 0xAE95, 0xCE1C, 0xAE96, 0xCE1D, 0xAE97, 0xCE1E, 0xAE98, 0xCE1F, 0xAE99, 0xCE22, 0xAE9A, 0xCE23, 0xAE9B, 0xCE25, 0xAE9C, 0xCE26, + 0xAE9D, 0xCE27, 0xAE9E, 0xCE29, 0xAE9F, 0xCE2A, 0xAEA0, 0xCE2B, 0xAF41, 0xCE2C, 0xAF42, 0xCE2D, 0xAF43, 0xCE2E, 0xAF44, 0xCE2F, + 0xAF45, 0xCE32, 0xAF46, 0xCE34, 0xAF47, 0xCE36, 0xAF48, 0xCE37, 0xAF49, 0xCE38, 0xAF4A, 0xCE39, 0xAF4B, 0xCE3A, 0xAF4C, 0xCE3B, + 0xAF4D, 0xCE3C, 0xAF4E, 0xCE3D, 0xAF4F, 0xCE3E, 0xAF50, 0xCE3F, 0xAF51, 0xCE40, 0xAF52, 0xCE41, 0xAF53, 0xCE42, 0xAF54, 0xCE43, + 0xAF55, 0xCE44, 0xAF56, 0xCE45, 0xAF57, 0xCE46, 0xAF58, 0xCE47, 0xAF59, 0xCE48, 0xAF5A, 0xCE49, 0xAF61, 0xCE4A, 0xAF62, 0xCE4B, + 0xAF63, 0xCE4C, 0xAF64, 0xCE4D, 0xAF65, 0xCE4E, 0xAF66, 0xCE4F, 0xAF67, 0xCE50, 0xAF68, 0xCE51, 0xAF69, 0xCE52, 0xAF6A, 0xCE53, + 0xAF6B, 0xCE54, 0xAF6C, 0xCE55, 0xAF6D, 0xCE56, 0xAF6E, 0xCE57, 0xAF6F, 0xCE5A, 0xAF70, 0xCE5B, 0xAF71, 0xCE5D, 0xAF72, 0xCE5E, + 0xAF73, 0xCE62, 0xAF74, 0xCE63, 0xAF75, 0xCE64, 0xAF76, 0xCE65, 0xAF77, 0xCE66, 0xAF78, 0xCE67, 0xAF79, 0xCE6A, 0xAF7A, 0xCE6C, + 0xAF81, 0xCE6E, 0xAF82, 0xCE6F, 0xAF83, 0xCE70, 0xAF84, 0xCE71, 0xAF85, 0xCE72, 0xAF86, 0xCE73, 0xAF87, 0xCE76, 0xAF88, 0xCE77, + 0xAF89, 0xCE79, 0xAF8A, 0xCE7A, 0xAF8B, 0xCE7B, 0xAF8C, 0xCE7D, 0xAF8D, 0xCE7E, 0xAF8E, 0xCE7F, 0xAF8F, 0xCE80, 0xAF90, 0xCE81, + 0xAF91, 0xCE82, 0xAF92, 0xCE83, 0xAF93, 0xCE86, 0xAF94, 0xCE88, 0xAF95, 0xCE8A, 0xAF96, 0xCE8B, 0xAF97, 0xCE8C, 0xAF98, 0xCE8D, + 0xAF99, 0xCE8E, 0xAF9A, 0xCE8F, 0xAF9B, 0xCE92, 0xAF9C, 0xCE93, 0xAF9D, 0xCE95, 0xAF9E, 0xCE96, 0xAF9F, 0xCE97, 0xAFA0, 0xCE99, + 0xB041, 0xCE9A, 0xB042, 0xCE9B, 0xB043, 0xCE9C, 0xB044, 0xCE9D, 0xB045, 0xCE9E, 0xB046, 0xCE9F, 0xB047, 0xCEA2, 0xB048, 0xCEA6, + 0xB049, 0xCEA7, 0xB04A, 0xCEA8, 0xB04B, 0xCEA9, 0xB04C, 0xCEAA, 0xB04D, 0xCEAB, 0xB04E, 0xCEAE, 0xB04F, 0xCEAF, 0xB050, 0xCEB0, + 0xB051, 0xCEB1, 0xB052, 0xCEB2, 0xB053, 0xCEB3, 0xB054, 0xCEB4, 0xB055, 0xCEB5, 0xB056, 0xCEB6, 0xB057, 0xCEB7, 0xB058, 0xCEB8, + 0xB059, 0xCEB9, 0xB05A, 0xCEBA, 0xB061, 0xCEBB, 0xB062, 0xCEBC, 0xB063, 0xCEBD, 0xB064, 0xCEBE, 0xB065, 0xCEBF, 0xB066, 0xCEC0, + 0xB067, 0xCEC2, 0xB068, 0xCEC3, 0xB069, 0xCEC4, 0xB06A, 0xCEC5, 0xB06B, 0xCEC6, 0xB06C, 0xCEC7, 0xB06D, 0xCEC8, 0xB06E, 0xCEC9, + 0xB06F, 0xCECA, 0xB070, 0xCECB, 0xB071, 0xCECC, 0xB072, 0xCECD, 0xB073, 0xCECE, 0xB074, 0xCECF, 0xB075, 0xCED0, 0xB076, 0xCED1, + 0xB077, 0xCED2, 0xB078, 0xCED3, 0xB079, 0xCED4, 0xB07A, 0xCED5, 0xB081, 0xCED6, 0xB082, 0xCED7, 0xB083, 0xCED8, 0xB084, 0xCED9, + 0xB085, 0xCEDA, 0xB086, 0xCEDB, 0xB087, 0xCEDC, 0xB088, 0xCEDD, 0xB089, 0xCEDE, 0xB08A, 0xCEDF, 0xB08B, 0xCEE0, 0xB08C, 0xCEE1, + 0xB08D, 0xCEE2, 0xB08E, 0xCEE3, 0xB08F, 0xCEE6, 0xB090, 0xCEE7, 0xB091, 0xCEE9, 0xB092, 0xCEEA, 0xB093, 0xCEED, 0xB094, 0xCEEE, + 0xB095, 0xCEEF, 0xB096, 0xCEF0, 0xB097, 0xCEF1, 0xB098, 0xCEF2, 0xB099, 0xCEF3, 0xB09A, 0xCEF6, 0xB09B, 0xCEFA, 0xB09C, 0xCEFB, + 0xB09D, 0xCEFC, 0xB09E, 0xCEFD, 0xB09F, 0xCEFE, 0xB0A0, 0xCEFF, 0xB0A1, 0xAC00, 0xB0A2, 0xAC01, 0xB0A3, 0xAC04, 0xB0A4, 0xAC07, + 0xB0A5, 0xAC08, 0xB0A6, 0xAC09, 0xB0A7, 0xAC0A, 0xB0A8, 0xAC10, 0xB0A9, 0xAC11, 0xB0AA, 0xAC12, 0xB0AB, 0xAC13, 0xB0AC, 0xAC14, + 0xB0AD, 0xAC15, 0xB0AE, 0xAC16, 0xB0AF, 0xAC17, 0xB0B0, 0xAC19, 0xB0B1, 0xAC1A, 0xB0B2, 0xAC1B, 0xB0B3, 0xAC1C, 0xB0B4, 0xAC1D, + 0xB0B5, 0xAC20, 0xB0B6, 0xAC24, 0xB0B7, 0xAC2C, 0xB0B8, 0xAC2D, 0xB0B9, 0xAC2F, 0xB0BA, 0xAC30, 0xB0BB, 0xAC31, 0xB0BC, 0xAC38, + 0xB0BD, 0xAC39, 0xB0BE, 0xAC3C, 0xB0BF, 0xAC40, 0xB0C0, 0xAC4B, 0xB0C1, 0xAC4D, 0xB0C2, 0xAC54, 0xB0C3, 0xAC58, 0xB0C4, 0xAC5C, + 0xB0C5, 0xAC70, 0xB0C6, 0xAC71, 0xB0C7, 0xAC74, 0xB0C8, 0xAC77, 0xB0C9, 0xAC78, 0xB0CA, 0xAC7A, 0xB0CB, 0xAC80, 0xB0CC, 0xAC81, + 0xB0CD, 0xAC83, 0xB0CE, 0xAC84, 0xB0CF, 0xAC85, 0xB0D0, 0xAC86, 0xB0D1, 0xAC89, 0xB0D2, 0xAC8A, 0xB0D3, 0xAC8B, 0xB0D4, 0xAC8C, + 0xB0D5, 0xAC90, 0xB0D6, 0xAC94, 0xB0D7, 0xAC9C, 0xB0D8, 0xAC9D, 0xB0D9, 0xAC9F, 0xB0DA, 0xACA0, 0xB0DB, 0xACA1, 0xB0DC, 0xACA8, + 0xB0DD, 0xACA9, 0xB0DE, 0xACAA, 0xB0DF, 0xACAC, 0xB0E0, 0xACAF, 0xB0E1, 0xACB0, 0xB0E2, 0xACB8, 0xB0E3, 0xACB9, 0xB0E4, 0xACBB, + 0xB0E5, 0xACBC, 0xB0E6, 0xACBD, 0xB0E7, 0xACC1, 0xB0E8, 0xACC4, 0xB0E9, 0xACC8, 0xB0EA, 0xACCC, 0xB0EB, 0xACD5, 0xB0EC, 0xACD7, + 0xB0ED, 0xACE0, 0xB0EE, 0xACE1, 0xB0EF, 0xACE4, 0xB0F0, 0xACE7, 0xB0F1, 0xACE8, 0xB0F2, 0xACEA, 0xB0F3, 0xACEC, 0xB0F4, 0xACEF, + 0xB0F5, 0xACF0, 0xB0F6, 0xACF1, 0xB0F7, 0xACF3, 0xB0F8, 0xACF5, 0xB0F9, 0xACF6, 0xB0FA, 0xACFC, 0xB0FB, 0xACFD, 0xB0FC, 0xAD00, + 0xB0FD, 0xAD04, 0xB0FE, 0xAD06, 0xB141, 0xCF02, 0xB142, 0xCF03, 0xB143, 0xCF05, 0xB144, 0xCF06, 0xB145, 0xCF07, 0xB146, 0xCF09, + 0xB147, 0xCF0A, 0xB148, 0xCF0B, 0xB149, 0xCF0C, 0xB14A, 0xCF0D, 0xB14B, 0xCF0E, 0xB14C, 0xCF0F, 0xB14D, 0xCF12, 0xB14E, 0xCF14, + 0xB14F, 0xCF16, 0xB150, 0xCF17, 0xB151, 0xCF18, 0xB152, 0xCF19, 0xB153, 0xCF1A, 0xB154, 0xCF1B, 0xB155, 0xCF1D, 0xB156, 0xCF1E, + 0xB157, 0xCF1F, 0xB158, 0xCF21, 0xB159, 0xCF22, 0xB15A, 0xCF23, 0xB161, 0xCF25, 0xB162, 0xCF26, 0xB163, 0xCF27, 0xB164, 0xCF28, + 0xB165, 0xCF29, 0xB166, 0xCF2A, 0xB167, 0xCF2B, 0xB168, 0xCF2E, 0xB169, 0xCF32, 0xB16A, 0xCF33, 0xB16B, 0xCF34, 0xB16C, 0xCF35, + 0xB16D, 0xCF36, 0xB16E, 0xCF37, 0xB16F, 0xCF39, 0xB170, 0xCF3A, 0xB171, 0xCF3B, 0xB172, 0xCF3C, 0xB173, 0xCF3D, 0xB174, 0xCF3E, + 0xB175, 0xCF3F, 0xB176, 0xCF40, 0xB177, 0xCF41, 0xB178, 0xCF42, 0xB179, 0xCF43, 0xB17A, 0xCF44, 0xB181, 0xCF45, 0xB182, 0xCF46, + 0xB183, 0xCF47, 0xB184, 0xCF48, 0xB185, 0xCF49, 0xB186, 0xCF4A, 0xB187, 0xCF4B, 0xB188, 0xCF4C, 0xB189, 0xCF4D, 0xB18A, 0xCF4E, + 0xB18B, 0xCF4F, 0xB18C, 0xCF50, 0xB18D, 0xCF51, 0xB18E, 0xCF52, 0xB18F, 0xCF53, 0xB190, 0xCF56, 0xB191, 0xCF57, 0xB192, 0xCF59, + 0xB193, 0xCF5A, 0xB194, 0xCF5B, 0xB195, 0xCF5D, 0xB196, 0xCF5E, 0xB197, 0xCF5F, 0xB198, 0xCF60, 0xB199, 0xCF61, 0xB19A, 0xCF62, + 0xB19B, 0xCF63, 0xB19C, 0xCF66, 0xB19D, 0xCF68, 0xB19E, 0xCF6A, 0xB19F, 0xCF6B, 0xB1A0, 0xCF6C, 0xB1A1, 0xAD0C, 0xB1A2, 0xAD0D, + 0xB1A3, 0xAD0F, 0xB1A4, 0xAD11, 0xB1A5, 0xAD18, 0xB1A6, 0xAD1C, 0xB1A7, 0xAD20, 0xB1A8, 0xAD29, 0xB1A9, 0xAD2C, 0xB1AA, 0xAD2D, + 0xB1AB, 0xAD34, 0xB1AC, 0xAD35, 0xB1AD, 0xAD38, 0xB1AE, 0xAD3C, 0xB1AF, 0xAD44, 0xB1B0, 0xAD45, 0xB1B1, 0xAD47, 0xB1B2, 0xAD49, + 0xB1B3, 0xAD50, 0xB1B4, 0xAD54, 0xB1B5, 0xAD58, 0xB1B6, 0xAD61, 0xB1B7, 0xAD63, 0xB1B8, 0xAD6C, 0xB1B9, 0xAD6D, 0xB1BA, 0xAD70, + 0xB1BB, 0xAD73, 0xB1BC, 0xAD74, 0xB1BD, 0xAD75, 0xB1BE, 0xAD76, 0xB1BF, 0xAD7B, 0xB1C0, 0xAD7C, 0xB1C1, 0xAD7D, 0xB1C2, 0xAD7F, + 0xB1C3, 0xAD81, 0xB1C4, 0xAD82, 0xB1C5, 0xAD88, 0xB1C6, 0xAD89, 0xB1C7, 0xAD8C, 0xB1C8, 0xAD90, 0xB1C9, 0xAD9C, 0xB1CA, 0xAD9D, + 0xB1CB, 0xADA4, 0xB1CC, 0xADB7, 0xB1CD, 0xADC0, 0xB1CE, 0xADC1, 0xB1CF, 0xADC4, 0xB1D0, 0xADC8, 0xB1D1, 0xADD0, 0xB1D2, 0xADD1, + 0xB1D3, 0xADD3, 0xB1D4, 0xADDC, 0xB1D5, 0xADE0, 0xB1D6, 0xADE4, 0xB1D7, 0xADF8, 0xB1D8, 0xADF9, 0xB1D9, 0xADFC, 0xB1DA, 0xADFF, + 0xB1DB, 0xAE00, 0xB1DC, 0xAE01, 0xB1DD, 0xAE08, 0xB1DE, 0xAE09, 0xB1DF, 0xAE0B, 0xB1E0, 0xAE0D, 0xB1E1, 0xAE14, 0xB1E2, 0xAE30, + 0xB1E3, 0xAE31, 0xB1E4, 0xAE34, 0xB1E5, 0xAE37, 0xB1E6, 0xAE38, 0xB1E7, 0xAE3A, 0xB1E8, 0xAE40, 0xB1E9, 0xAE41, 0xB1EA, 0xAE43, + 0xB1EB, 0xAE45, 0xB1EC, 0xAE46, 0xB1ED, 0xAE4A, 0xB1EE, 0xAE4C, 0xB1EF, 0xAE4D, 0xB1F0, 0xAE4E, 0xB1F1, 0xAE50, 0xB1F2, 0xAE54, + 0xB1F3, 0xAE56, 0xB1F4, 0xAE5C, 0xB1F5, 0xAE5D, 0xB1F6, 0xAE5F, 0xB1F7, 0xAE60, 0xB1F8, 0xAE61, 0xB1F9, 0xAE65, 0xB1FA, 0xAE68, + 0xB1FB, 0xAE69, 0xB1FC, 0xAE6C, 0xB1FD, 0xAE70, 0xB1FE, 0xAE78, 0xB241, 0xCF6D, 0xB242, 0xCF6E, 0xB243, 0xCF6F, 0xB244, 0xCF72, + 0xB245, 0xCF73, 0xB246, 0xCF75, 0xB247, 0xCF76, 0xB248, 0xCF77, 0xB249, 0xCF79, 0xB24A, 0xCF7A, 0xB24B, 0xCF7B, 0xB24C, 0xCF7C, + 0xB24D, 0xCF7D, 0xB24E, 0xCF7E, 0xB24F, 0xCF7F, 0xB250, 0xCF81, 0xB251, 0xCF82, 0xB252, 0xCF83, 0xB253, 0xCF84, 0xB254, 0xCF86, + 0xB255, 0xCF87, 0xB256, 0xCF88, 0xB257, 0xCF89, 0xB258, 0xCF8A, 0xB259, 0xCF8B, 0xB25A, 0xCF8D, 0xB261, 0xCF8E, 0xB262, 0xCF8F, + 0xB263, 0xCF90, 0xB264, 0xCF91, 0xB265, 0xCF92, 0xB266, 0xCF93, 0xB267, 0xCF94, 0xB268, 0xCF95, 0xB269, 0xCF96, 0xB26A, 0xCF97, + 0xB26B, 0xCF98, 0xB26C, 0xCF99, 0xB26D, 0xCF9A, 0xB26E, 0xCF9B, 0xB26F, 0xCF9C, 0xB270, 0xCF9D, 0xB271, 0xCF9E, 0xB272, 0xCF9F, + 0xB273, 0xCFA0, 0xB274, 0xCFA2, 0xB275, 0xCFA3, 0xB276, 0xCFA4, 0xB277, 0xCFA5, 0xB278, 0xCFA6, 0xB279, 0xCFA7, 0xB27A, 0xCFA9, + 0xB281, 0xCFAA, 0xB282, 0xCFAB, 0xB283, 0xCFAC, 0xB284, 0xCFAD, 0xB285, 0xCFAE, 0xB286, 0xCFAF, 0xB287, 0xCFB1, 0xB288, 0xCFB2, + 0xB289, 0xCFB3, 0xB28A, 0xCFB4, 0xB28B, 0xCFB5, 0xB28C, 0xCFB6, 0xB28D, 0xCFB7, 0xB28E, 0xCFB8, 0xB28F, 0xCFB9, 0xB290, 0xCFBA, + 0xB291, 0xCFBB, 0xB292, 0xCFBC, 0xB293, 0xCFBD, 0xB294, 0xCFBE, 0xB295, 0xCFBF, 0xB296, 0xCFC0, 0xB297, 0xCFC1, 0xB298, 0xCFC2, + 0xB299, 0xCFC3, 0xB29A, 0xCFC5, 0xB29B, 0xCFC6, 0xB29C, 0xCFC7, 0xB29D, 0xCFC8, 0xB29E, 0xCFC9, 0xB29F, 0xCFCA, 0xB2A0, 0xCFCB, + 0xB2A1, 0xAE79, 0xB2A2, 0xAE7B, 0xB2A3, 0xAE7C, 0xB2A4, 0xAE7D, 0xB2A5, 0xAE84, 0xB2A6, 0xAE85, 0xB2A7, 0xAE8C, 0xB2A8, 0xAEBC, + 0xB2A9, 0xAEBD, 0xB2AA, 0xAEBE, 0xB2AB, 0xAEC0, 0xB2AC, 0xAEC4, 0xB2AD, 0xAECC, 0xB2AE, 0xAECD, 0xB2AF, 0xAECF, 0xB2B0, 0xAED0, + 0xB2B1, 0xAED1, 0xB2B2, 0xAED8, 0xB2B3, 0xAED9, 0xB2B4, 0xAEDC, 0xB2B5, 0xAEE8, 0xB2B6, 0xAEEB, 0xB2B7, 0xAEED, 0xB2B8, 0xAEF4, + 0xB2B9, 0xAEF8, 0xB2BA, 0xAEFC, 0xB2BB, 0xAF07, 0xB2BC, 0xAF08, 0xB2BD, 0xAF0D, 0xB2BE, 0xAF10, 0xB2BF, 0xAF2C, 0xB2C0, 0xAF2D, + 0xB2C1, 0xAF30, 0xB2C2, 0xAF32, 0xB2C3, 0xAF34, 0xB2C4, 0xAF3C, 0xB2C5, 0xAF3D, 0xB2C6, 0xAF3F, 0xB2C7, 0xAF41, 0xB2C8, 0xAF42, + 0xB2C9, 0xAF43, 0xB2CA, 0xAF48, 0xB2CB, 0xAF49, 0xB2CC, 0xAF50, 0xB2CD, 0xAF5C, 0xB2CE, 0xAF5D, 0xB2CF, 0xAF64, 0xB2D0, 0xAF65, + 0xB2D1, 0xAF79, 0xB2D2, 0xAF80, 0xB2D3, 0xAF84, 0xB2D4, 0xAF88, 0xB2D5, 0xAF90, 0xB2D6, 0xAF91, 0xB2D7, 0xAF95, 0xB2D8, 0xAF9C, + 0xB2D9, 0xAFB8, 0xB2DA, 0xAFB9, 0xB2DB, 0xAFBC, 0xB2DC, 0xAFC0, 0xB2DD, 0xAFC7, 0xB2DE, 0xAFC8, 0xB2DF, 0xAFC9, 0xB2E0, 0xAFCB, + 0xB2E1, 0xAFCD, 0xB2E2, 0xAFCE, 0xB2E3, 0xAFD4, 0xB2E4, 0xAFDC, 0xB2E5, 0xAFE8, 0xB2E6, 0xAFE9, 0xB2E7, 0xAFF0, 0xB2E8, 0xAFF1, + 0xB2E9, 0xAFF4, 0xB2EA, 0xAFF8, 0xB2EB, 0xB000, 0xB2EC, 0xB001, 0xB2ED, 0xB004, 0xB2EE, 0xB00C, 0xB2EF, 0xB010, 0xB2F0, 0xB014, + 0xB2F1, 0xB01C, 0xB2F2, 0xB01D, 0xB2F3, 0xB028, 0xB2F4, 0xB044, 0xB2F5, 0xB045, 0xB2F6, 0xB048, 0xB2F7, 0xB04A, 0xB2F8, 0xB04C, + 0xB2F9, 0xB04E, 0xB2FA, 0xB053, 0xB2FB, 0xB054, 0xB2FC, 0xB055, 0xB2FD, 0xB057, 0xB2FE, 0xB059, 0xB341, 0xCFCC, 0xB342, 0xCFCD, + 0xB343, 0xCFCE, 0xB344, 0xCFCF, 0xB345, 0xCFD0, 0xB346, 0xCFD1, 0xB347, 0xCFD2, 0xB348, 0xCFD3, 0xB349, 0xCFD4, 0xB34A, 0xCFD5, + 0xB34B, 0xCFD6, 0xB34C, 0xCFD7, 0xB34D, 0xCFD8, 0xB34E, 0xCFD9, 0xB34F, 0xCFDA, 0xB350, 0xCFDB, 0xB351, 0xCFDC, 0xB352, 0xCFDD, + 0xB353, 0xCFDE, 0xB354, 0xCFDF, 0xB355, 0xCFE2, 0xB356, 0xCFE3, 0xB357, 0xCFE5, 0xB358, 0xCFE6, 0xB359, 0xCFE7, 0xB35A, 0xCFE9, + 0xB361, 0xCFEA, 0xB362, 0xCFEB, 0xB363, 0xCFEC, 0xB364, 0xCFED, 0xB365, 0xCFEE, 0xB366, 0xCFEF, 0xB367, 0xCFF2, 0xB368, 0xCFF4, + 0xB369, 0xCFF6, 0xB36A, 0xCFF7, 0xB36B, 0xCFF8, 0xB36C, 0xCFF9, 0xB36D, 0xCFFA, 0xB36E, 0xCFFB, 0xB36F, 0xCFFD, 0xB370, 0xCFFE, + 0xB371, 0xCFFF, 0xB372, 0xD001, 0xB373, 0xD002, 0xB374, 0xD003, 0xB375, 0xD005, 0xB376, 0xD006, 0xB377, 0xD007, 0xB378, 0xD008, + 0xB379, 0xD009, 0xB37A, 0xD00A, 0xB381, 0xD00B, 0xB382, 0xD00C, 0xB383, 0xD00D, 0xB384, 0xD00E, 0xB385, 0xD00F, 0xB386, 0xD010, + 0xB387, 0xD012, 0xB388, 0xD013, 0xB389, 0xD014, 0xB38A, 0xD015, 0xB38B, 0xD016, 0xB38C, 0xD017, 0xB38D, 0xD019, 0xB38E, 0xD01A, + 0xB38F, 0xD01B, 0xB390, 0xD01C, 0xB391, 0xD01D, 0xB392, 0xD01E, 0xB393, 0xD01F, 0xB394, 0xD020, 0xB395, 0xD021, 0xB396, 0xD022, + 0xB397, 0xD023, 0xB398, 0xD024, 0xB399, 0xD025, 0xB39A, 0xD026, 0xB39B, 0xD027, 0xB39C, 0xD028, 0xB39D, 0xD029, 0xB39E, 0xD02A, + 0xB39F, 0xD02B, 0xB3A0, 0xD02C, 0xB3A1, 0xB05D, 0xB3A2, 0xB07C, 0xB3A3, 0xB07D, 0xB3A4, 0xB080, 0xB3A5, 0xB084, 0xB3A6, 0xB08C, + 0xB3A7, 0xB08D, 0xB3A8, 0xB08F, 0xB3A9, 0xB091, 0xB3AA, 0xB098, 0xB3AB, 0xB099, 0xB3AC, 0xB09A, 0xB3AD, 0xB09C, 0xB3AE, 0xB09F, + 0xB3AF, 0xB0A0, 0xB3B0, 0xB0A1, 0xB3B1, 0xB0A2, 0xB3B2, 0xB0A8, 0xB3B3, 0xB0A9, 0xB3B4, 0xB0AB, 0xB3B5, 0xB0AC, 0xB3B6, 0xB0AD, + 0xB3B7, 0xB0AE, 0xB3B8, 0xB0AF, 0xB3B9, 0xB0B1, 0xB3BA, 0xB0B3, 0xB3BB, 0xB0B4, 0xB3BC, 0xB0B5, 0xB3BD, 0xB0B8, 0xB3BE, 0xB0BC, + 0xB3BF, 0xB0C4, 0xB3C0, 0xB0C5, 0xB3C1, 0xB0C7, 0xB3C2, 0xB0C8, 0xB3C3, 0xB0C9, 0xB3C4, 0xB0D0, 0xB3C5, 0xB0D1, 0xB3C6, 0xB0D4, + 0xB3C7, 0xB0D8, 0xB3C8, 0xB0E0, 0xB3C9, 0xB0E5, 0xB3CA, 0xB108, 0xB3CB, 0xB109, 0xB3CC, 0xB10B, 0xB3CD, 0xB10C, 0xB3CE, 0xB110, + 0xB3CF, 0xB112, 0xB3D0, 0xB113, 0xB3D1, 0xB118, 0xB3D2, 0xB119, 0xB3D3, 0xB11B, 0xB3D4, 0xB11C, 0xB3D5, 0xB11D, 0xB3D6, 0xB123, + 0xB3D7, 0xB124, 0xB3D8, 0xB125, 0xB3D9, 0xB128, 0xB3DA, 0xB12C, 0xB3DB, 0xB134, 0xB3DC, 0xB135, 0xB3DD, 0xB137, 0xB3DE, 0xB138, + 0xB3DF, 0xB139, 0xB3E0, 0xB140, 0xB3E1, 0xB141, 0xB3E2, 0xB144, 0xB3E3, 0xB148, 0xB3E4, 0xB150, 0xB3E5, 0xB151, 0xB3E6, 0xB154, + 0xB3E7, 0xB155, 0xB3E8, 0xB158, 0xB3E9, 0xB15C, 0xB3EA, 0xB160, 0xB3EB, 0xB178, 0xB3EC, 0xB179, 0xB3ED, 0xB17C, 0xB3EE, 0xB180, + 0xB3EF, 0xB182, 0xB3F0, 0xB188, 0xB3F1, 0xB189, 0xB3F2, 0xB18B, 0xB3F3, 0xB18D, 0xB3F4, 0xB192, 0xB3F5, 0xB193, 0xB3F6, 0xB194, + 0xB3F7, 0xB198, 0xB3F8, 0xB19C, 0xB3F9, 0xB1A8, 0xB3FA, 0xB1CC, 0xB3FB, 0xB1D0, 0xB3FC, 0xB1D4, 0xB3FD, 0xB1DC, 0xB3FE, 0xB1DD, + 0xB441, 0xD02E, 0xB442, 0xD02F, 0xB443, 0xD030, 0xB444, 0xD031, 0xB445, 0xD032, 0xB446, 0xD033, 0xB447, 0xD036, 0xB448, 0xD037, + 0xB449, 0xD039, 0xB44A, 0xD03A, 0xB44B, 0xD03B, 0xB44C, 0xD03D, 0xB44D, 0xD03E, 0xB44E, 0xD03F, 0xB44F, 0xD040, 0xB450, 0xD041, + 0xB451, 0xD042, 0xB452, 0xD043, 0xB453, 0xD046, 0xB454, 0xD048, 0xB455, 0xD04A, 0xB456, 0xD04B, 0xB457, 0xD04C, 0xB458, 0xD04D, + 0xB459, 0xD04E, 0xB45A, 0xD04F, 0xB461, 0xD051, 0xB462, 0xD052, 0xB463, 0xD053, 0xB464, 0xD055, 0xB465, 0xD056, 0xB466, 0xD057, + 0xB467, 0xD059, 0xB468, 0xD05A, 0xB469, 0xD05B, 0xB46A, 0xD05C, 0xB46B, 0xD05D, 0xB46C, 0xD05E, 0xB46D, 0xD05F, 0xB46E, 0xD061, + 0xB46F, 0xD062, 0xB470, 0xD063, 0xB471, 0xD064, 0xB472, 0xD065, 0xB473, 0xD066, 0xB474, 0xD067, 0xB475, 0xD068, 0xB476, 0xD069, + 0xB477, 0xD06A, 0xB478, 0xD06B, 0xB479, 0xD06E, 0xB47A, 0xD06F, 0xB481, 0xD071, 0xB482, 0xD072, 0xB483, 0xD073, 0xB484, 0xD075, + 0xB485, 0xD076, 0xB486, 0xD077, 0xB487, 0xD078, 0xB488, 0xD079, 0xB489, 0xD07A, 0xB48A, 0xD07B, 0xB48B, 0xD07E, 0xB48C, 0xD07F, + 0xB48D, 0xD080, 0xB48E, 0xD082, 0xB48F, 0xD083, 0xB490, 0xD084, 0xB491, 0xD085, 0xB492, 0xD086, 0xB493, 0xD087, 0xB494, 0xD088, + 0xB495, 0xD089, 0xB496, 0xD08A, 0xB497, 0xD08B, 0xB498, 0xD08C, 0xB499, 0xD08D, 0xB49A, 0xD08E, 0xB49B, 0xD08F, 0xB49C, 0xD090, + 0xB49D, 0xD091, 0xB49E, 0xD092, 0xB49F, 0xD093, 0xB4A0, 0xD094, 0xB4A1, 0xB1DF, 0xB4A2, 0xB1E8, 0xB4A3, 0xB1E9, 0xB4A4, 0xB1EC, + 0xB4A5, 0xB1F0, 0xB4A6, 0xB1F9, 0xB4A7, 0xB1FB, 0xB4A8, 0xB1FD, 0xB4A9, 0xB204, 0xB4AA, 0xB205, 0xB4AB, 0xB208, 0xB4AC, 0xB20B, + 0xB4AD, 0xB20C, 0xB4AE, 0xB214, 0xB4AF, 0xB215, 0xB4B0, 0xB217, 0xB4B1, 0xB219, 0xB4B2, 0xB220, 0xB4B3, 0xB234, 0xB4B4, 0xB23C, + 0xB4B5, 0xB258, 0xB4B6, 0xB25C, 0xB4B7, 0xB260, 0xB4B8, 0xB268, 0xB4B9, 0xB269, 0xB4BA, 0xB274, 0xB4BB, 0xB275, 0xB4BC, 0xB27C, + 0xB4BD, 0xB284, 0xB4BE, 0xB285, 0xB4BF, 0xB289, 0xB4C0, 0xB290, 0xB4C1, 0xB291, 0xB4C2, 0xB294, 0xB4C3, 0xB298, 0xB4C4, 0xB299, + 0xB4C5, 0xB29A, 0xB4C6, 0xB2A0, 0xB4C7, 0xB2A1, 0xB4C8, 0xB2A3, 0xB4C9, 0xB2A5, 0xB4CA, 0xB2A6, 0xB4CB, 0xB2AA, 0xB4CC, 0xB2AC, + 0xB4CD, 0xB2B0, 0xB4CE, 0xB2B4, 0xB4CF, 0xB2C8, 0xB4D0, 0xB2C9, 0xB4D1, 0xB2CC, 0xB4D2, 0xB2D0, 0xB4D3, 0xB2D2, 0xB4D4, 0xB2D8, + 0xB4D5, 0xB2D9, 0xB4D6, 0xB2DB, 0xB4D7, 0xB2DD, 0xB4D8, 0xB2E2, 0xB4D9, 0xB2E4, 0xB4DA, 0xB2E5, 0xB4DB, 0xB2E6, 0xB4DC, 0xB2E8, + 0xB4DD, 0xB2EB, 0xB4DE, 0xB2EC, 0xB4DF, 0xB2ED, 0xB4E0, 0xB2EE, 0xB4E1, 0xB2EF, 0xB4E2, 0xB2F3, 0xB4E3, 0xB2F4, 0xB4E4, 0xB2F5, + 0xB4E5, 0xB2F7, 0xB4E6, 0xB2F8, 0xB4E7, 0xB2F9, 0xB4E8, 0xB2FA, 0xB4E9, 0xB2FB, 0xB4EA, 0xB2FF, 0xB4EB, 0xB300, 0xB4EC, 0xB301, + 0xB4ED, 0xB304, 0xB4EE, 0xB308, 0xB4EF, 0xB310, 0xB4F0, 0xB311, 0xB4F1, 0xB313, 0xB4F2, 0xB314, 0xB4F3, 0xB315, 0xB4F4, 0xB31C, + 0xB4F5, 0xB354, 0xB4F6, 0xB355, 0xB4F7, 0xB356, 0xB4F8, 0xB358, 0xB4F9, 0xB35B, 0xB4FA, 0xB35C, 0xB4FB, 0xB35E, 0xB4FC, 0xB35F, + 0xB4FD, 0xB364, 0xB4FE, 0xB365, 0xB541, 0xD095, 0xB542, 0xD096, 0xB543, 0xD097, 0xB544, 0xD098, 0xB545, 0xD099, 0xB546, 0xD09A, + 0xB547, 0xD09B, 0xB548, 0xD09C, 0xB549, 0xD09D, 0xB54A, 0xD09E, 0xB54B, 0xD09F, 0xB54C, 0xD0A0, 0xB54D, 0xD0A1, 0xB54E, 0xD0A2, + 0xB54F, 0xD0A3, 0xB550, 0xD0A6, 0xB551, 0xD0A7, 0xB552, 0xD0A9, 0xB553, 0xD0AA, 0xB554, 0xD0AB, 0xB555, 0xD0AD, 0xB556, 0xD0AE, + 0xB557, 0xD0AF, 0xB558, 0xD0B0, 0xB559, 0xD0B1, 0xB55A, 0xD0B2, 0xB561, 0xD0B3, 0xB562, 0xD0B6, 0xB563, 0xD0B8, 0xB564, 0xD0BA, + 0xB565, 0xD0BB, 0xB566, 0xD0BC, 0xB567, 0xD0BD, 0xB568, 0xD0BE, 0xB569, 0xD0BF, 0xB56A, 0xD0C2, 0xB56B, 0xD0C3, 0xB56C, 0xD0C5, + 0xB56D, 0xD0C6, 0xB56E, 0xD0C7, 0xB56F, 0xD0CA, 0xB570, 0xD0CB, 0xB571, 0xD0CC, 0xB572, 0xD0CD, 0xB573, 0xD0CE, 0xB574, 0xD0CF, + 0xB575, 0xD0D2, 0xB576, 0xD0D6, 0xB577, 0xD0D7, 0xB578, 0xD0D8, 0xB579, 0xD0D9, 0xB57A, 0xD0DA, 0xB581, 0xD0DB, 0xB582, 0xD0DE, + 0xB583, 0xD0DF, 0xB584, 0xD0E1, 0xB585, 0xD0E2, 0xB586, 0xD0E3, 0xB587, 0xD0E5, 0xB588, 0xD0E6, 0xB589, 0xD0E7, 0xB58A, 0xD0E8, + 0xB58B, 0xD0E9, 0xB58C, 0xD0EA, 0xB58D, 0xD0EB, 0xB58E, 0xD0EE, 0xB58F, 0xD0F2, 0xB590, 0xD0F3, 0xB591, 0xD0F4, 0xB592, 0xD0F5, + 0xB593, 0xD0F6, 0xB594, 0xD0F7, 0xB595, 0xD0F9, 0xB596, 0xD0FA, 0xB597, 0xD0FB, 0xB598, 0xD0FC, 0xB599, 0xD0FD, 0xB59A, 0xD0FE, + 0xB59B, 0xD0FF, 0xB59C, 0xD100, 0xB59D, 0xD101, 0xB59E, 0xD102, 0xB59F, 0xD103, 0xB5A0, 0xD104, 0xB5A1, 0xB367, 0xB5A2, 0xB369, + 0xB5A3, 0xB36B, 0xB5A4, 0xB36E, 0xB5A5, 0xB370, 0xB5A6, 0xB371, 0xB5A7, 0xB374, 0xB5A8, 0xB378, 0xB5A9, 0xB380, 0xB5AA, 0xB381, + 0xB5AB, 0xB383, 0xB5AC, 0xB384, 0xB5AD, 0xB385, 0xB5AE, 0xB38C, 0xB5AF, 0xB390, 0xB5B0, 0xB394, 0xB5B1, 0xB3A0, 0xB5B2, 0xB3A1, + 0xB5B3, 0xB3A8, 0xB5B4, 0xB3AC, 0xB5B5, 0xB3C4, 0xB5B6, 0xB3C5, 0xB5B7, 0xB3C8, 0xB5B8, 0xB3CB, 0xB5B9, 0xB3CC, 0xB5BA, 0xB3CE, + 0xB5BB, 0xB3D0, 0xB5BC, 0xB3D4, 0xB5BD, 0xB3D5, 0xB5BE, 0xB3D7, 0xB5BF, 0xB3D9, 0xB5C0, 0xB3DB, 0xB5C1, 0xB3DD, 0xB5C2, 0xB3E0, + 0xB5C3, 0xB3E4, 0xB5C4, 0xB3E8, 0xB5C5, 0xB3FC, 0xB5C6, 0xB410, 0xB5C7, 0xB418, 0xB5C8, 0xB41C, 0xB5C9, 0xB420, 0xB5CA, 0xB428, + 0xB5CB, 0xB429, 0xB5CC, 0xB42B, 0xB5CD, 0xB434, 0xB5CE, 0xB450, 0xB5CF, 0xB451, 0xB5D0, 0xB454, 0xB5D1, 0xB458, 0xB5D2, 0xB460, + 0xB5D3, 0xB461, 0xB5D4, 0xB463, 0xB5D5, 0xB465, 0xB5D6, 0xB46C, 0xB5D7, 0xB480, 0xB5D8, 0xB488, 0xB5D9, 0xB49D, 0xB5DA, 0xB4A4, + 0xB5DB, 0xB4A8, 0xB5DC, 0xB4AC, 0xB5DD, 0xB4B5, 0xB5DE, 0xB4B7, 0xB5DF, 0xB4B9, 0xB5E0, 0xB4C0, 0xB5E1, 0xB4C4, 0xB5E2, 0xB4C8, + 0xB5E3, 0xB4D0, 0xB5E4, 0xB4D5, 0xB5E5, 0xB4DC, 0xB5E6, 0xB4DD, 0xB5E7, 0xB4E0, 0xB5E8, 0xB4E3, 0xB5E9, 0xB4E4, 0xB5EA, 0xB4E6, + 0xB5EB, 0xB4EC, 0xB5EC, 0xB4ED, 0xB5ED, 0xB4EF, 0xB5EE, 0xB4F1, 0xB5EF, 0xB4F8, 0xB5F0, 0xB514, 0xB5F1, 0xB515, 0xB5F2, 0xB518, + 0xB5F3, 0xB51B, 0xB5F4, 0xB51C, 0xB5F5, 0xB524, 0xB5F6, 0xB525, 0xB5F7, 0xB527, 0xB5F8, 0xB528, 0xB5F9, 0xB529, 0xB5FA, 0xB52A, + 0xB5FB, 0xB530, 0xB5FC, 0xB531, 0xB5FD, 0xB534, 0xB5FE, 0xB538, 0xB641, 0xD105, 0xB642, 0xD106, 0xB643, 0xD107, 0xB644, 0xD108, + 0xB645, 0xD109, 0xB646, 0xD10A, 0xB647, 0xD10B, 0xB648, 0xD10C, 0xB649, 0xD10E, 0xB64A, 0xD10F, 0xB64B, 0xD110, 0xB64C, 0xD111, + 0xB64D, 0xD112, 0xB64E, 0xD113, 0xB64F, 0xD114, 0xB650, 0xD115, 0xB651, 0xD116, 0xB652, 0xD117, 0xB653, 0xD118, 0xB654, 0xD119, + 0xB655, 0xD11A, 0xB656, 0xD11B, 0xB657, 0xD11C, 0xB658, 0xD11D, 0xB659, 0xD11E, 0xB65A, 0xD11F, 0xB661, 0xD120, 0xB662, 0xD121, + 0xB663, 0xD122, 0xB664, 0xD123, 0xB665, 0xD124, 0xB666, 0xD125, 0xB667, 0xD126, 0xB668, 0xD127, 0xB669, 0xD128, 0xB66A, 0xD129, + 0xB66B, 0xD12A, 0xB66C, 0xD12B, 0xB66D, 0xD12C, 0xB66E, 0xD12D, 0xB66F, 0xD12E, 0xB670, 0xD12F, 0xB671, 0xD132, 0xB672, 0xD133, + 0xB673, 0xD135, 0xB674, 0xD136, 0xB675, 0xD137, 0xB676, 0xD139, 0xB677, 0xD13B, 0xB678, 0xD13C, 0xB679, 0xD13D, 0xB67A, 0xD13E, + 0xB681, 0xD13F, 0xB682, 0xD142, 0xB683, 0xD146, 0xB684, 0xD147, 0xB685, 0xD148, 0xB686, 0xD149, 0xB687, 0xD14A, 0xB688, 0xD14B, + 0xB689, 0xD14E, 0xB68A, 0xD14F, 0xB68B, 0xD151, 0xB68C, 0xD152, 0xB68D, 0xD153, 0xB68E, 0xD155, 0xB68F, 0xD156, 0xB690, 0xD157, + 0xB691, 0xD158, 0xB692, 0xD159, 0xB693, 0xD15A, 0xB694, 0xD15B, 0xB695, 0xD15E, 0xB696, 0xD160, 0xB697, 0xD162, 0xB698, 0xD163, + 0xB699, 0xD164, 0xB69A, 0xD165, 0xB69B, 0xD166, 0xB69C, 0xD167, 0xB69D, 0xD169, 0xB69E, 0xD16A, 0xB69F, 0xD16B, 0xB6A0, 0xD16D, + 0xB6A1, 0xB540, 0xB6A2, 0xB541, 0xB6A3, 0xB543, 0xB6A4, 0xB544, 0xB6A5, 0xB545, 0xB6A6, 0xB54B, 0xB6A7, 0xB54C, 0xB6A8, 0xB54D, + 0xB6A9, 0xB550, 0xB6AA, 0xB554, 0xB6AB, 0xB55C, 0xB6AC, 0xB55D, 0xB6AD, 0xB55F, 0xB6AE, 0xB560, 0xB6AF, 0xB561, 0xB6B0, 0xB5A0, + 0xB6B1, 0xB5A1, 0xB6B2, 0xB5A4, 0xB6B3, 0xB5A8, 0xB6B4, 0xB5AA, 0xB6B5, 0xB5AB, 0xB6B6, 0xB5B0, 0xB6B7, 0xB5B1, 0xB6B8, 0xB5B3, + 0xB6B9, 0xB5B4, 0xB6BA, 0xB5B5, 0xB6BB, 0xB5BB, 0xB6BC, 0xB5BC, 0xB6BD, 0xB5BD, 0xB6BE, 0xB5C0, 0xB6BF, 0xB5C4, 0xB6C0, 0xB5CC, + 0xB6C1, 0xB5CD, 0xB6C2, 0xB5CF, 0xB6C3, 0xB5D0, 0xB6C4, 0xB5D1, 0xB6C5, 0xB5D8, 0xB6C6, 0xB5EC, 0xB6C7, 0xB610, 0xB6C8, 0xB611, + 0xB6C9, 0xB614, 0xB6CA, 0xB618, 0xB6CB, 0xB625, 0xB6CC, 0xB62C, 0xB6CD, 0xB634, 0xB6CE, 0xB648, 0xB6CF, 0xB664, 0xB6D0, 0xB668, + 0xB6D1, 0xB69C, 0xB6D2, 0xB69D, 0xB6D3, 0xB6A0, 0xB6D4, 0xB6A4, 0xB6D5, 0xB6AB, 0xB6D6, 0xB6AC, 0xB6D7, 0xB6B1, 0xB6D8, 0xB6D4, + 0xB6D9, 0xB6F0, 0xB6DA, 0xB6F4, 0xB6DB, 0xB6F8, 0xB6DC, 0xB700, 0xB6DD, 0xB701, 0xB6DE, 0xB705, 0xB6DF, 0xB728, 0xB6E0, 0xB729, + 0xB6E1, 0xB72C, 0xB6E2, 0xB72F, 0xB6E3, 0xB730, 0xB6E4, 0xB738, 0xB6E5, 0xB739, 0xB6E6, 0xB73B, 0xB6E7, 0xB744, 0xB6E8, 0xB748, + 0xB6E9, 0xB74C, 0xB6EA, 0xB754, 0xB6EB, 0xB755, 0xB6EC, 0xB760, 0xB6ED, 0xB764, 0xB6EE, 0xB768, 0xB6EF, 0xB770, 0xB6F0, 0xB771, + 0xB6F1, 0xB773, 0xB6F2, 0xB775, 0xB6F3, 0xB77C, 0xB6F4, 0xB77D, 0xB6F5, 0xB780, 0xB6F6, 0xB784, 0xB6F7, 0xB78C, 0xB6F8, 0xB78D, + 0xB6F9, 0xB78F, 0xB6FA, 0xB790, 0xB6FB, 0xB791, 0xB6FC, 0xB792, 0xB6FD, 0xB796, 0xB6FE, 0xB797, 0xB741, 0xD16E, 0xB742, 0xD16F, + 0xB743, 0xD170, 0xB744, 0xD171, 0xB745, 0xD172, 0xB746, 0xD173, 0xB747, 0xD174, 0xB748, 0xD175, 0xB749, 0xD176, 0xB74A, 0xD177, + 0xB74B, 0xD178, 0xB74C, 0xD179, 0xB74D, 0xD17A, 0xB74E, 0xD17B, 0xB74F, 0xD17D, 0xB750, 0xD17E, 0xB751, 0xD17F, 0xB752, 0xD180, + 0xB753, 0xD181, 0xB754, 0xD182, 0xB755, 0xD183, 0xB756, 0xD185, 0xB757, 0xD186, 0xB758, 0xD187, 0xB759, 0xD189, 0xB75A, 0xD18A, + 0xB761, 0xD18B, 0xB762, 0xD18C, 0xB763, 0xD18D, 0xB764, 0xD18E, 0xB765, 0xD18F, 0xB766, 0xD190, 0xB767, 0xD191, 0xB768, 0xD192, + 0xB769, 0xD193, 0xB76A, 0xD194, 0xB76B, 0xD195, 0xB76C, 0xD196, 0xB76D, 0xD197, 0xB76E, 0xD198, 0xB76F, 0xD199, 0xB770, 0xD19A, + 0xB771, 0xD19B, 0xB772, 0xD19C, 0xB773, 0xD19D, 0xB774, 0xD19E, 0xB775, 0xD19F, 0xB776, 0xD1A2, 0xB777, 0xD1A3, 0xB778, 0xD1A5, + 0xB779, 0xD1A6, 0xB77A, 0xD1A7, 0xB781, 0xD1A9, 0xB782, 0xD1AA, 0xB783, 0xD1AB, 0xB784, 0xD1AC, 0xB785, 0xD1AD, 0xB786, 0xD1AE, + 0xB787, 0xD1AF, 0xB788, 0xD1B2, 0xB789, 0xD1B4, 0xB78A, 0xD1B6, 0xB78B, 0xD1B7, 0xB78C, 0xD1B8, 0xB78D, 0xD1B9, 0xB78E, 0xD1BB, + 0xB78F, 0xD1BD, 0xB790, 0xD1BE, 0xB791, 0xD1BF, 0xB792, 0xD1C1, 0xB793, 0xD1C2, 0xB794, 0xD1C3, 0xB795, 0xD1C4, 0xB796, 0xD1C5, + 0xB797, 0xD1C6, 0xB798, 0xD1C7, 0xB799, 0xD1C8, 0xB79A, 0xD1C9, 0xB79B, 0xD1CA, 0xB79C, 0xD1CB, 0xB79D, 0xD1CC, 0xB79E, 0xD1CD, + 0xB79F, 0xD1CE, 0xB7A0, 0xD1CF, 0xB7A1, 0xB798, 0xB7A2, 0xB799, 0xB7A3, 0xB79C, 0xB7A4, 0xB7A0, 0xB7A5, 0xB7A8, 0xB7A6, 0xB7A9, + 0xB7A7, 0xB7AB, 0xB7A8, 0xB7AC, 0xB7A9, 0xB7AD, 0xB7AA, 0xB7B4, 0xB7AB, 0xB7B5, 0xB7AC, 0xB7B8, 0xB7AD, 0xB7C7, 0xB7AE, 0xB7C9, + 0xB7AF, 0xB7EC, 0xB7B0, 0xB7ED, 0xB7B1, 0xB7F0, 0xB7B2, 0xB7F4, 0xB7B3, 0xB7FC, 0xB7B4, 0xB7FD, 0xB7B5, 0xB7FF, 0xB7B6, 0xB800, + 0xB7B7, 0xB801, 0xB7B8, 0xB807, 0xB7B9, 0xB808, 0xB7BA, 0xB809, 0xB7BB, 0xB80C, 0xB7BC, 0xB810, 0xB7BD, 0xB818, 0xB7BE, 0xB819, + 0xB7BF, 0xB81B, 0xB7C0, 0xB81D, 0xB7C1, 0xB824, 0xB7C2, 0xB825, 0xB7C3, 0xB828, 0xB7C4, 0xB82C, 0xB7C5, 0xB834, 0xB7C6, 0xB835, + 0xB7C7, 0xB837, 0xB7C8, 0xB838, 0xB7C9, 0xB839, 0xB7CA, 0xB840, 0xB7CB, 0xB844, 0xB7CC, 0xB851, 0xB7CD, 0xB853, 0xB7CE, 0xB85C, + 0xB7CF, 0xB85D, 0xB7D0, 0xB860, 0xB7D1, 0xB864, 0xB7D2, 0xB86C, 0xB7D3, 0xB86D, 0xB7D4, 0xB86F, 0xB7D5, 0xB871, 0xB7D6, 0xB878, + 0xB7D7, 0xB87C, 0xB7D8, 0xB88D, 0xB7D9, 0xB8A8, 0xB7DA, 0xB8B0, 0xB7DB, 0xB8B4, 0xB7DC, 0xB8B8, 0xB7DD, 0xB8C0, 0xB7DE, 0xB8C1, + 0xB7DF, 0xB8C3, 0xB7E0, 0xB8C5, 0xB7E1, 0xB8CC, 0xB7E2, 0xB8D0, 0xB7E3, 0xB8D4, 0xB7E4, 0xB8DD, 0xB7E5, 0xB8DF, 0xB7E6, 0xB8E1, + 0xB7E7, 0xB8E8, 0xB7E8, 0xB8E9, 0xB7E9, 0xB8EC, 0xB7EA, 0xB8F0, 0xB7EB, 0xB8F8, 0xB7EC, 0xB8F9, 0xB7ED, 0xB8FB, 0xB7EE, 0xB8FD, + 0xB7EF, 0xB904, 0xB7F0, 0xB918, 0xB7F1, 0xB920, 0xB7F2, 0xB93C, 0xB7F3, 0xB93D, 0xB7F4, 0xB940, 0xB7F5, 0xB944, 0xB7F6, 0xB94C, + 0xB7F7, 0xB94F, 0xB7F8, 0xB951, 0xB7F9, 0xB958, 0xB7FA, 0xB959, 0xB7FB, 0xB95C, 0xB7FC, 0xB960, 0xB7FD, 0xB968, 0xB7FE, 0xB969, + 0xB841, 0xD1D0, 0xB842, 0xD1D1, 0xB843, 0xD1D2, 0xB844, 0xD1D3, 0xB845, 0xD1D4, 0xB846, 0xD1D5, 0xB847, 0xD1D6, 0xB848, 0xD1D7, + 0xB849, 0xD1D9, 0xB84A, 0xD1DA, 0xB84B, 0xD1DB, 0xB84C, 0xD1DC, 0xB84D, 0xD1DD, 0xB84E, 0xD1DE, 0xB84F, 0xD1DF, 0xB850, 0xD1E0, + 0xB851, 0xD1E1, 0xB852, 0xD1E2, 0xB853, 0xD1E3, 0xB854, 0xD1E4, 0xB855, 0xD1E5, 0xB856, 0xD1E6, 0xB857, 0xD1E7, 0xB858, 0xD1E8, + 0xB859, 0xD1E9, 0xB85A, 0xD1EA, 0xB861, 0xD1EB, 0xB862, 0xD1EC, 0xB863, 0xD1ED, 0xB864, 0xD1EE, 0xB865, 0xD1EF, 0xB866, 0xD1F0, + 0xB867, 0xD1F1, 0xB868, 0xD1F2, 0xB869, 0xD1F3, 0xB86A, 0xD1F5, 0xB86B, 0xD1F6, 0xB86C, 0xD1F7, 0xB86D, 0xD1F9, 0xB86E, 0xD1FA, + 0xB86F, 0xD1FB, 0xB870, 0xD1FC, 0xB871, 0xD1FD, 0xB872, 0xD1FE, 0xB873, 0xD1FF, 0xB874, 0xD200, 0xB875, 0xD201, 0xB876, 0xD202, + 0xB877, 0xD203, 0xB878, 0xD204, 0xB879, 0xD205, 0xB87A, 0xD206, 0xB881, 0xD208, 0xB882, 0xD20A, 0xB883, 0xD20B, 0xB884, 0xD20C, + 0xB885, 0xD20D, 0xB886, 0xD20E, 0xB887, 0xD20F, 0xB888, 0xD211, 0xB889, 0xD212, 0xB88A, 0xD213, 0xB88B, 0xD214, 0xB88C, 0xD215, + 0xB88D, 0xD216, 0xB88E, 0xD217, 0xB88F, 0xD218, 0xB890, 0xD219, 0xB891, 0xD21A, 0xB892, 0xD21B, 0xB893, 0xD21C, 0xB894, 0xD21D, + 0xB895, 0xD21E, 0xB896, 0xD21F, 0xB897, 0xD220, 0xB898, 0xD221, 0xB899, 0xD222, 0xB89A, 0xD223, 0xB89B, 0xD224, 0xB89C, 0xD225, + 0xB89D, 0xD226, 0xB89E, 0xD227, 0xB89F, 0xD228, 0xB8A0, 0xD229, 0xB8A1, 0xB96B, 0xB8A2, 0xB96D, 0xB8A3, 0xB974, 0xB8A4, 0xB975, + 0xB8A5, 0xB978, 0xB8A6, 0xB97C, 0xB8A7, 0xB984, 0xB8A8, 0xB985, 0xB8A9, 0xB987, 0xB8AA, 0xB989, 0xB8AB, 0xB98A, 0xB8AC, 0xB98D, + 0xB8AD, 0xB98E, 0xB8AE, 0xB9AC, 0xB8AF, 0xB9AD, 0xB8B0, 0xB9B0, 0xB8B1, 0xB9B4, 0xB8B2, 0xB9BC, 0xB8B3, 0xB9BD, 0xB8B4, 0xB9BF, + 0xB8B5, 0xB9C1, 0xB8B6, 0xB9C8, 0xB8B7, 0xB9C9, 0xB8B8, 0xB9CC, 0xB8B9, 0xB9CE, 0xB8BA, 0xB9CF, 0xB8BB, 0xB9D0, 0xB8BC, 0xB9D1, + 0xB8BD, 0xB9D2, 0xB8BE, 0xB9D8, 0xB8BF, 0xB9D9, 0xB8C0, 0xB9DB, 0xB8C1, 0xB9DD, 0xB8C2, 0xB9DE, 0xB8C3, 0xB9E1, 0xB8C4, 0xB9E3, + 0xB8C5, 0xB9E4, 0xB8C6, 0xB9E5, 0xB8C7, 0xB9E8, 0xB8C8, 0xB9EC, 0xB8C9, 0xB9F4, 0xB8CA, 0xB9F5, 0xB8CB, 0xB9F7, 0xB8CC, 0xB9F8, + 0xB8CD, 0xB9F9, 0xB8CE, 0xB9FA, 0xB8CF, 0xBA00, 0xB8D0, 0xBA01, 0xB8D1, 0xBA08, 0xB8D2, 0xBA15, 0xB8D3, 0xBA38, 0xB8D4, 0xBA39, + 0xB8D5, 0xBA3C, 0xB8D6, 0xBA40, 0xB8D7, 0xBA42, 0xB8D8, 0xBA48, 0xB8D9, 0xBA49, 0xB8DA, 0xBA4B, 0xB8DB, 0xBA4D, 0xB8DC, 0xBA4E, + 0xB8DD, 0xBA53, 0xB8DE, 0xBA54, 0xB8DF, 0xBA55, 0xB8E0, 0xBA58, 0xB8E1, 0xBA5C, 0xB8E2, 0xBA64, 0xB8E3, 0xBA65, 0xB8E4, 0xBA67, + 0xB8E5, 0xBA68, 0xB8E6, 0xBA69, 0xB8E7, 0xBA70, 0xB8E8, 0xBA71, 0xB8E9, 0xBA74, 0xB8EA, 0xBA78, 0xB8EB, 0xBA83, 0xB8EC, 0xBA84, + 0xB8ED, 0xBA85, 0xB8EE, 0xBA87, 0xB8EF, 0xBA8C, 0xB8F0, 0xBAA8, 0xB8F1, 0xBAA9, 0xB8F2, 0xBAAB, 0xB8F3, 0xBAAC, 0xB8F4, 0xBAB0, + 0xB8F5, 0xBAB2, 0xB8F6, 0xBAB8, 0xB8F7, 0xBAB9, 0xB8F8, 0xBABB, 0xB8F9, 0xBABD, 0xB8FA, 0xBAC4, 0xB8FB, 0xBAC8, 0xB8FC, 0xBAD8, + 0xB8FD, 0xBAD9, 0xB8FE, 0xBAFC, 0xB941, 0xD22A, 0xB942, 0xD22B, 0xB943, 0xD22E, 0xB944, 0xD22F, 0xB945, 0xD231, 0xB946, 0xD232, + 0xB947, 0xD233, 0xB948, 0xD235, 0xB949, 0xD236, 0xB94A, 0xD237, 0xB94B, 0xD238, 0xB94C, 0xD239, 0xB94D, 0xD23A, 0xB94E, 0xD23B, + 0xB94F, 0xD23E, 0xB950, 0xD240, 0xB951, 0xD242, 0xB952, 0xD243, 0xB953, 0xD244, 0xB954, 0xD245, 0xB955, 0xD246, 0xB956, 0xD247, + 0xB957, 0xD249, 0xB958, 0xD24A, 0xB959, 0xD24B, 0xB95A, 0xD24C, 0xB961, 0xD24D, 0xB962, 0xD24E, 0xB963, 0xD24F, 0xB964, 0xD250, + 0xB965, 0xD251, 0xB966, 0xD252, 0xB967, 0xD253, 0xB968, 0xD254, 0xB969, 0xD255, 0xB96A, 0xD256, 0xB96B, 0xD257, 0xB96C, 0xD258, + 0xB96D, 0xD259, 0xB96E, 0xD25A, 0xB96F, 0xD25B, 0xB970, 0xD25D, 0xB971, 0xD25E, 0xB972, 0xD25F, 0xB973, 0xD260, 0xB974, 0xD261, + 0xB975, 0xD262, 0xB976, 0xD263, 0xB977, 0xD265, 0xB978, 0xD266, 0xB979, 0xD267, 0xB97A, 0xD268, 0xB981, 0xD269, 0xB982, 0xD26A, + 0xB983, 0xD26B, 0xB984, 0xD26C, 0xB985, 0xD26D, 0xB986, 0xD26E, 0xB987, 0xD26F, 0xB988, 0xD270, 0xB989, 0xD271, 0xB98A, 0xD272, + 0xB98B, 0xD273, 0xB98C, 0xD274, 0xB98D, 0xD275, 0xB98E, 0xD276, 0xB98F, 0xD277, 0xB990, 0xD278, 0xB991, 0xD279, 0xB992, 0xD27A, + 0xB993, 0xD27B, 0xB994, 0xD27C, 0xB995, 0xD27D, 0xB996, 0xD27E, 0xB997, 0xD27F, 0xB998, 0xD282, 0xB999, 0xD283, 0xB99A, 0xD285, + 0xB99B, 0xD286, 0xB99C, 0xD287, 0xB99D, 0xD289, 0xB99E, 0xD28A, 0xB99F, 0xD28B, 0xB9A0, 0xD28C, 0xB9A1, 0xBB00, 0xB9A2, 0xBB04, + 0xB9A3, 0xBB0D, 0xB9A4, 0xBB0F, 0xB9A5, 0xBB11, 0xB9A6, 0xBB18, 0xB9A7, 0xBB1C, 0xB9A8, 0xBB20, 0xB9A9, 0xBB29, 0xB9AA, 0xBB2B, + 0xB9AB, 0xBB34, 0xB9AC, 0xBB35, 0xB9AD, 0xBB36, 0xB9AE, 0xBB38, 0xB9AF, 0xBB3B, 0xB9B0, 0xBB3C, 0xB9B1, 0xBB3D, 0xB9B2, 0xBB3E, + 0xB9B3, 0xBB44, 0xB9B4, 0xBB45, 0xB9B5, 0xBB47, 0xB9B6, 0xBB49, 0xB9B7, 0xBB4D, 0xB9B8, 0xBB4F, 0xB9B9, 0xBB50, 0xB9BA, 0xBB54, + 0xB9BB, 0xBB58, 0xB9BC, 0xBB61, 0xB9BD, 0xBB63, 0xB9BE, 0xBB6C, 0xB9BF, 0xBB88, 0xB9C0, 0xBB8C, 0xB9C1, 0xBB90, 0xB9C2, 0xBBA4, + 0xB9C3, 0xBBA8, 0xB9C4, 0xBBAC, 0xB9C5, 0xBBB4, 0xB9C6, 0xBBB7, 0xB9C7, 0xBBC0, 0xB9C8, 0xBBC4, 0xB9C9, 0xBBC8, 0xB9CA, 0xBBD0, + 0xB9CB, 0xBBD3, 0xB9CC, 0xBBF8, 0xB9CD, 0xBBF9, 0xB9CE, 0xBBFC, 0xB9CF, 0xBBFF, 0xB9D0, 0xBC00, 0xB9D1, 0xBC02, 0xB9D2, 0xBC08, + 0xB9D3, 0xBC09, 0xB9D4, 0xBC0B, 0xB9D5, 0xBC0C, 0xB9D6, 0xBC0D, 0xB9D7, 0xBC0F, 0xB9D8, 0xBC11, 0xB9D9, 0xBC14, 0xB9DA, 0xBC15, + 0xB9DB, 0xBC16, 0xB9DC, 0xBC17, 0xB9DD, 0xBC18, 0xB9DE, 0xBC1B, 0xB9DF, 0xBC1C, 0xB9E0, 0xBC1D, 0xB9E1, 0xBC1E, 0xB9E2, 0xBC1F, + 0xB9E3, 0xBC24, 0xB9E4, 0xBC25, 0xB9E5, 0xBC27, 0xB9E6, 0xBC29, 0xB9E7, 0xBC2D, 0xB9E8, 0xBC30, 0xB9E9, 0xBC31, 0xB9EA, 0xBC34, + 0xB9EB, 0xBC38, 0xB9EC, 0xBC40, 0xB9ED, 0xBC41, 0xB9EE, 0xBC43, 0xB9EF, 0xBC44, 0xB9F0, 0xBC45, 0xB9F1, 0xBC49, 0xB9F2, 0xBC4C, + 0xB9F3, 0xBC4D, 0xB9F4, 0xBC50, 0xB9F5, 0xBC5D, 0xB9F6, 0xBC84, 0xB9F7, 0xBC85, 0xB9F8, 0xBC88, 0xB9F9, 0xBC8B, 0xB9FA, 0xBC8C, + 0xB9FB, 0xBC8E, 0xB9FC, 0xBC94, 0xB9FD, 0xBC95, 0xB9FE, 0xBC97, 0xBA41, 0xD28D, 0xBA42, 0xD28E, 0xBA43, 0xD28F, 0xBA44, 0xD292, + 0xBA45, 0xD293, 0xBA46, 0xD294, 0xBA47, 0xD296, 0xBA48, 0xD297, 0xBA49, 0xD298, 0xBA4A, 0xD299, 0xBA4B, 0xD29A, 0xBA4C, 0xD29B, + 0xBA4D, 0xD29D, 0xBA4E, 0xD29E, 0xBA4F, 0xD29F, 0xBA50, 0xD2A1, 0xBA51, 0xD2A2, 0xBA52, 0xD2A3, 0xBA53, 0xD2A5, 0xBA54, 0xD2A6, + 0xBA55, 0xD2A7, 0xBA56, 0xD2A8, 0xBA57, 0xD2A9, 0xBA58, 0xD2AA, 0xBA59, 0xD2AB, 0xBA5A, 0xD2AD, 0xBA61, 0xD2AE, 0xBA62, 0xD2AF, + 0xBA63, 0xD2B0, 0xBA64, 0xD2B2, 0xBA65, 0xD2B3, 0xBA66, 0xD2B4, 0xBA67, 0xD2B5, 0xBA68, 0xD2B6, 0xBA69, 0xD2B7, 0xBA6A, 0xD2BA, + 0xBA6B, 0xD2BB, 0xBA6C, 0xD2BD, 0xBA6D, 0xD2BE, 0xBA6E, 0xD2C1, 0xBA6F, 0xD2C3, 0xBA70, 0xD2C4, 0xBA71, 0xD2C5, 0xBA72, 0xD2C6, + 0xBA73, 0xD2C7, 0xBA74, 0xD2CA, 0xBA75, 0xD2CC, 0xBA76, 0xD2CD, 0xBA77, 0xD2CE, 0xBA78, 0xD2CF, 0xBA79, 0xD2D0, 0xBA7A, 0xD2D1, + 0xBA81, 0xD2D2, 0xBA82, 0xD2D3, 0xBA83, 0xD2D5, 0xBA84, 0xD2D6, 0xBA85, 0xD2D7, 0xBA86, 0xD2D9, 0xBA87, 0xD2DA, 0xBA88, 0xD2DB, + 0xBA89, 0xD2DD, 0xBA8A, 0xD2DE, 0xBA8B, 0xD2DF, 0xBA8C, 0xD2E0, 0xBA8D, 0xD2E1, 0xBA8E, 0xD2E2, 0xBA8F, 0xD2E3, 0xBA90, 0xD2E6, + 0xBA91, 0xD2E7, 0xBA92, 0xD2E8, 0xBA93, 0xD2E9, 0xBA94, 0xD2EA, 0xBA95, 0xD2EB, 0xBA96, 0xD2EC, 0xBA97, 0xD2ED, 0xBA98, 0xD2EE, + 0xBA99, 0xD2EF, 0xBA9A, 0xD2F2, 0xBA9B, 0xD2F3, 0xBA9C, 0xD2F5, 0xBA9D, 0xD2F6, 0xBA9E, 0xD2F7, 0xBA9F, 0xD2F9, 0xBAA0, 0xD2FA, + 0xBAA1, 0xBC99, 0xBAA2, 0xBC9A, 0xBAA3, 0xBCA0, 0xBAA4, 0xBCA1, 0xBAA5, 0xBCA4, 0xBAA6, 0xBCA7, 0xBAA7, 0xBCA8, 0xBAA8, 0xBCB0, + 0xBAA9, 0xBCB1, 0xBAAA, 0xBCB3, 0xBAAB, 0xBCB4, 0xBAAC, 0xBCB5, 0xBAAD, 0xBCBC, 0xBAAE, 0xBCBD, 0xBAAF, 0xBCC0, 0xBAB0, 0xBCC4, + 0xBAB1, 0xBCCD, 0xBAB2, 0xBCCF, 0xBAB3, 0xBCD0, 0xBAB4, 0xBCD1, 0xBAB5, 0xBCD5, 0xBAB6, 0xBCD8, 0xBAB7, 0xBCDC, 0xBAB8, 0xBCF4, + 0xBAB9, 0xBCF5, 0xBABA, 0xBCF6, 0xBABB, 0xBCF8, 0xBABC, 0xBCFC, 0xBABD, 0xBD04, 0xBABE, 0xBD05, 0xBABF, 0xBD07, 0xBAC0, 0xBD09, + 0xBAC1, 0xBD10, 0xBAC2, 0xBD14, 0xBAC3, 0xBD24, 0xBAC4, 0xBD2C, 0xBAC5, 0xBD40, 0xBAC6, 0xBD48, 0xBAC7, 0xBD49, 0xBAC8, 0xBD4C, + 0xBAC9, 0xBD50, 0xBACA, 0xBD58, 0xBACB, 0xBD59, 0xBACC, 0xBD64, 0xBACD, 0xBD68, 0xBACE, 0xBD80, 0xBACF, 0xBD81, 0xBAD0, 0xBD84, + 0xBAD1, 0xBD87, 0xBAD2, 0xBD88, 0xBAD3, 0xBD89, 0xBAD4, 0xBD8A, 0xBAD5, 0xBD90, 0xBAD6, 0xBD91, 0xBAD7, 0xBD93, 0xBAD8, 0xBD95, + 0xBAD9, 0xBD99, 0xBADA, 0xBD9A, 0xBADB, 0xBD9C, 0xBADC, 0xBDA4, 0xBADD, 0xBDB0, 0xBADE, 0xBDB8, 0xBADF, 0xBDD4, 0xBAE0, 0xBDD5, + 0xBAE1, 0xBDD8, 0xBAE2, 0xBDDC, 0xBAE3, 0xBDE9, 0xBAE4, 0xBDF0, 0xBAE5, 0xBDF4, 0xBAE6, 0xBDF8, 0xBAE7, 0xBE00, 0xBAE8, 0xBE03, + 0xBAE9, 0xBE05, 0xBAEA, 0xBE0C, 0xBAEB, 0xBE0D, 0xBAEC, 0xBE10, 0xBAED, 0xBE14, 0xBAEE, 0xBE1C, 0xBAEF, 0xBE1D, 0xBAF0, 0xBE1F, + 0xBAF1, 0xBE44, 0xBAF2, 0xBE45, 0xBAF3, 0xBE48, 0xBAF4, 0xBE4C, 0xBAF5, 0xBE4E, 0xBAF6, 0xBE54, 0xBAF7, 0xBE55, 0xBAF8, 0xBE57, + 0xBAF9, 0xBE59, 0xBAFA, 0xBE5A, 0xBAFB, 0xBE5B, 0xBAFC, 0xBE60, 0xBAFD, 0xBE61, 0xBAFE, 0xBE64, 0xBB41, 0xD2FB, 0xBB42, 0xD2FC, + 0xBB43, 0xD2FD, 0xBB44, 0xD2FE, 0xBB45, 0xD2FF, 0xBB46, 0xD302, 0xBB47, 0xD304, 0xBB48, 0xD306, 0xBB49, 0xD307, 0xBB4A, 0xD308, + 0xBB4B, 0xD309, 0xBB4C, 0xD30A, 0xBB4D, 0xD30B, 0xBB4E, 0xD30F, 0xBB4F, 0xD311, 0xBB50, 0xD312, 0xBB51, 0xD313, 0xBB52, 0xD315, + 0xBB53, 0xD317, 0xBB54, 0xD318, 0xBB55, 0xD319, 0xBB56, 0xD31A, 0xBB57, 0xD31B, 0xBB58, 0xD31E, 0xBB59, 0xD322, 0xBB5A, 0xD323, + 0xBB61, 0xD324, 0xBB62, 0xD326, 0xBB63, 0xD327, 0xBB64, 0xD32A, 0xBB65, 0xD32B, 0xBB66, 0xD32D, 0xBB67, 0xD32E, 0xBB68, 0xD32F, + 0xBB69, 0xD331, 0xBB6A, 0xD332, 0xBB6B, 0xD333, 0xBB6C, 0xD334, 0xBB6D, 0xD335, 0xBB6E, 0xD336, 0xBB6F, 0xD337, 0xBB70, 0xD33A, + 0xBB71, 0xD33E, 0xBB72, 0xD33F, 0xBB73, 0xD340, 0xBB74, 0xD341, 0xBB75, 0xD342, 0xBB76, 0xD343, 0xBB77, 0xD346, 0xBB78, 0xD347, + 0xBB79, 0xD348, 0xBB7A, 0xD349, 0xBB81, 0xD34A, 0xBB82, 0xD34B, 0xBB83, 0xD34C, 0xBB84, 0xD34D, 0xBB85, 0xD34E, 0xBB86, 0xD34F, + 0xBB87, 0xD350, 0xBB88, 0xD351, 0xBB89, 0xD352, 0xBB8A, 0xD353, 0xBB8B, 0xD354, 0xBB8C, 0xD355, 0xBB8D, 0xD356, 0xBB8E, 0xD357, + 0xBB8F, 0xD358, 0xBB90, 0xD359, 0xBB91, 0xD35A, 0xBB92, 0xD35B, 0xBB93, 0xD35C, 0xBB94, 0xD35D, 0xBB95, 0xD35E, 0xBB96, 0xD35F, + 0xBB97, 0xD360, 0xBB98, 0xD361, 0xBB99, 0xD362, 0xBB9A, 0xD363, 0xBB9B, 0xD364, 0xBB9C, 0xD365, 0xBB9D, 0xD366, 0xBB9E, 0xD367, + 0xBB9F, 0xD368, 0xBBA0, 0xD369, 0xBBA1, 0xBE68, 0xBBA2, 0xBE6A, 0xBBA3, 0xBE70, 0xBBA4, 0xBE71, 0xBBA5, 0xBE73, 0xBBA6, 0xBE74, + 0xBBA7, 0xBE75, 0xBBA8, 0xBE7B, 0xBBA9, 0xBE7C, 0xBBAA, 0xBE7D, 0xBBAB, 0xBE80, 0xBBAC, 0xBE84, 0xBBAD, 0xBE8C, 0xBBAE, 0xBE8D, + 0xBBAF, 0xBE8F, 0xBBB0, 0xBE90, 0xBBB1, 0xBE91, 0xBBB2, 0xBE98, 0xBBB3, 0xBE99, 0xBBB4, 0xBEA8, 0xBBB5, 0xBED0, 0xBBB6, 0xBED1, + 0xBBB7, 0xBED4, 0xBBB8, 0xBED7, 0xBBB9, 0xBED8, 0xBBBA, 0xBEE0, 0xBBBB, 0xBEE3, 0xBBBC, 0xBEE4, 0xBBBD, 0xBEE5, 0xBBBE, 0xBEEC, + 0xBBBF, 0xBF01, 0xBBC0, 0xBF08, 0xBBC1, 0xBF09, 0xBBC2, 0xBF18, 0xBBC3, 0xBF19, 0xBBC4, 0xBF1B, 0xBBC5, 0xBF1C, 0xBBC6, 0xBF1D, + 0xBBC7, 0xBF40, 0xBBC8, 0xBF41, 0xBBC9, 0xBF44, 0xBBCA, 0xBF48, 0xBBCB, 0xBF50, 0xBBCC, 0xBF51, 0xBBCD, 0xBF55, 0xBBCE, 0xBF94, + 0xBBCF, 0xBFB0, 0xBBD0, 0xBFC5, 0xBBD1, 0xBFCC, 0xBBD2, 0xBFCD, 0xBBD3, 0xBFD0, 0xBBD4, 0xBFD4, 0xBBD5, 0xBFDC, 0xBBD6, 0xBFDF, + 0xBBD7, 0xBFE1, 0xBBD8, 0xC03C, 0xBBD9, 0xC051, 0xBBDA, 0xC058, 0xBBDB, 0xC05C, 0xBBDC, 0xC060, 0xBBDD, 0xC068, 0xBBDE, 0xC069, + 0xBBDF, 0xC090, 0xBBE0, 0xC091, 0xBBE1, 0xC094, 0xBBE2, 0xC098, 0xBBE3, 0xC0A0, 0xBBE4, 0xC0A1, 0xBBE5, 0xC0A3, 0xBBE6, 0xC0A5, + 0xBBE7, 0xC0AC, 0xBBE8, 0xC0AD, 0xBBE9, 0xC0AF, 0xBBEA, 0xC0B0, 0xBBEB, 0xC0B3, 0xBBEC, 0xC0B4, 0xBBED, 0xC0B5, 0xBBEE, 0xC0B6, + 0xBBEF, 0xC0BC, 0xBBF0, 0xC0BD, 0xBBF1, 0xC0BF, 0xBBF2, 0xC0C0, 0xBBF3, 0xC0C1, 0xBBF4, 0xC0C5, 0xBBF5, 0xC0C8, 0xBBF6, 0xC0C9, + 0xBBF7, 0xC0CC, 0xBBF8, 0xC0D0, 0xBBF9, 0xC0D8, 0xBBFA, 0xC0D9, 0xBBFB, 0xC0DB, 0xBBFC, 0xC0DC, 0xBBFD, 0xC0DD, 0xBBFE, 0xC0E4, + 0xBC41, 0xD36A, 0xBC42, 0xD36B, 0xBC43, 0xD36C, 0xBC44, 0xD36D, 0xBC45, 0xD36E, 0xBC46, 0xD36F, 0xBC47, 0xD370, 0xBC48, 0xD371, + 0xBC49, 0xD372, 0xBC4A, 0xD373, 0xBC4B, 0xD374, 0xBC4C, 0xD375, 0xBC4D, 0xD376, 0xBC4E, 0xD377, 0xBC4F, 0xD378, 0xBC50, 0xD379, + 0xBC51, 0xD37A, 0xBC52, 0xD37B, 0xBC53, 0xD37E, 0xBC54, 0xD37F, 0xBC55, 0xD381, 0xBC56, 0xD382, 0xBC57, 0xD383, 0xBC58, 0xD385, + 0xBC59, 0xD386, 0xBC5A, 0xD387, 0xBC61, 0xD388, 0xBC62, 0xD389, 0xBC63, 0xD38A, 0xBC64, 0xD38B, 0xBC65, 0xD38E, 0xBC66, 0xD392, + 0xBC67, 0xD393, 0xBC68, 0xD394, 0xBC69, 0xD395, 0xBC6A, 0xD396, 0xBC6B, 0xD397, 0xBC6C, 0xD39A, 0xBC6D, 0xD39B, 0xBC6E, 0xD39D, + 0xBC6F, 0xD39E, 0xBC70, 0xD39F, 0xBC71, 0xD3A1, 0xBC72, 0xD3A2, 0xBC73, 0xD3A3, 0xBC74, 0xD3A4, 0xBC75, 0xD3A5, 0xBC76, 0xD3A6, + 0xBC77, 0xD3A7, 0xBC78, 0xD3AA, 0xBC79, 0xD3AC, 0xBC7A, 0xD3AE, 0xBC81, 0xD3AF, 0xBC82, 0xD3B0, 0xBC83, 0xD3B1, 0xBC84, 0xD3B2, + 0xBC85, 0xD3B3, 0xBC86, 0xD3B5, 0xBC87, 0xD3B6, 0xBC88, 0xD3B7, 0xBC89, 0xD3B9, 0xBC8A, 0xD3BA, 0xBC8B, 0xD3BB, 0xBC8C, 0xD3BD, + 0xBC8D, 0xD3BE, 0xBC8E, 0xD3BF, 0xBC8F, 0xD3C0, 0xBC90, 0xD3C1, 0xBC91, 0xD3C2, 0xBC92, 0xD3C3, 0xBC93, 0xD3C6, 0xBC94, 0xD3C7, + 0xBC95, 0xD3CA, 0xBC96, 0xD3CB, 0xBC97, 0xD3CC, 0xBC98, 0xD3CD, 0xBC99, 0xD3CE, 0xBC9A, 0xD3CF, 0xBC9B, 0xD3D1, 0xBC9C, 0xD3D2, + 0xBC9D, 0xD3D3, 0xBC9E, 0xD3D4, 0xBC9F, 0xD3D5, 0xBCA0, 0xD3D6, 0xBCA1, 0xC0E5, 0xBCA2, 0xC0E8, 0xBCA3, 0xC0EC, 0xBCA4, 0xC0F4, + 0xBCA5, 0xC0F5, 0xBCA6, 0xC0F7, 0xBCA7, 0xC0F9, 0xBCA8, 0xC100, 0xBCA9, 0xC104, 0xBCAA, 0xC108, 0xBCAB, 0xC110, 0xBCAC, 0xC115, + 0xBCAD, 0xC11C, 0xBCAE, 0xC11D, 0xBCAF, 0xC11E, 0xBCB0, 0xC11F, 0xBCB1, 0xC120, 0xBCB2, 0xC123, 0xBCB3, 0xC124, 0xBCB4, 0xC126, + 0xBCB5, 0xC127, 0xBCB6, 0xC12C, 0xBCB7, 0xC12D, 0xBCB8, 0xC12F, 0xBCB9, 0xC130, 0xBCBA, 0xC131, 0xBCBB, 0xC136, 0xBCBC, 0xC138, + 0xBCBD, 0xC139, 0xBCBE, 0xC13C, 0xBCBF, 0xC140, 0xBCC0, 0xC148, 0xBCC1, 0xC149, 0xBCC2, 0xC14B, 0xBCC3, 0xC14C, 0xBCC4, 0xC14D, + 0xBCC5, 0xC154, 0xBCC6, 0xC155, 0xBCC7, 0xC158, 0xBCC8, 0xC15C, 0xBCC9, 0xC164, 0xBCCA, 0xC165, 0xBCCB, 0xC167, 0xBCCC, 0xC168, + 0xBCCD, 0xC169, 0xBCCE, 0xC170, 0xBCCF, 0xC174, 0xBCD0, 0xC178, 0xBCD1, 0xC185, 0xBCD2, 0xC18C, 0xBCD3, 0xC18D, 0xBCD4, 0xC18E, + 0xBCD5, 0xC190, 0xBCD6, 0xC194, 0xBCD7, 0xC196, 0xBCD8, 0xC19C, 0xBCD9, 0xC19D, 0xBCDA, 0xC19F, 0xBCDB, 0xC1A1, 0xBCDC, 0xC1A5, + 0xBCDD, 0xC1A8, 0xBCDE, 0xC1A9, 0xBCDF, 0xC1AC, 0xBCE0, 0xC1B0, 0xBCE1, 0xC1BD, 0xBCE2, 0xC1C4, 0xBCE3, 0xC1C8, 0xBCE4, 0xC1CC, + 0xBCE5, 0xC1D4, 0xBCE6, 0xC1D7, 0xBCE7, 0xC1D8, 0xBCE8, 0xC1E0, 0xBCE9, 0xC1E4, 0xBCEA, 0xC1E8, 0xBCEB, 0xC1F0, 0xBCEC, 0xC1F1, + 0xBCED, 0xC1F3, 0xBCEE, 0xC1FC, 0xBCEF, 0xC1FD, 0xBCF0, 0xC200, 0xBCF1, 0xC204, 0xBCF2, 0xC20C, 0xBCF3, 0xC20D, 0xBCF4, 0xC20F, + 0xBCF5, 0xC211, 0xBCF6, 0xC218, 0xBCF7, 0xC219, 0xBCF8, 0xC21C, 0xBCF9, 0xC21F, 0xBCFA, 0xC220, 0xBCFB, 0xC228, 0xBCFC, 0xC229, + 0xBCFD, 0xC22B, 0xBCFE, 0xC22D, 0xBD41, 0xD3D7, 0xBD42, 0xD3D9, 0xBD43, 0xD3DA, 0xBD44, 0xD3DB, 0xBD45, 0xD3DC, 0xBD46, 0xD3DD, + 0xBD47, 0xD3DE, 0xBD48, 0xD3DF, 0xBD49, 0xD3E0, 0xBD4A, 0xD3E2, 0xBD4B, 0xD3E4, 0xBD4C, 0xD3E5, 0xBD4D, 0xD3E6, 0xBD4E, 0xD3E7, + 0xBD4F, 0xD3E8, 0xBD50, 0xD3E9, 0xBD51, 0xD3EA, 0xBD52, 0xD3EB, 0xBD53, 0xD3EE, 0xBD54, 0xD3EF, 0xBD55, 0xD3F1, 0xBD56, 0xD3F2, + 0xBD57, 0xD3F3, 0xBD58, 0xD3F5, 0xBD59, 0xD3F6, 0xBD5A, 0xD3F7, 0xBD61, 0xD3F8, 0xBD62, 0xD3F9, 0xBD63, 0xD3FA, 0xBD64, 0xD3FB, + 0xBD65, 0xD3FE, 0xBD66, 0xD400, 0xBD67, 0xD402, 0xBD68, 0xD403, 0xBD69, 0xD404, 0xBD6A, 0xD405, 0xBD6B, 0xD406, 0xBD6C, 0xD407, + 0xBD6D, 0xD409, 0xBD6E, 0xD40A, 0xBD6F, 0xD40B, 0xBD70, 0xD40C, 0xBD71, 0xD40D, 0xBD72, 0xD40E, 0xBD73, 0xD40F, 0xBD74, 0xD410, + 0xBD75, 0xD411, 0xBD76, 0xD412, 0xBD77, 0xD413, 0xBD78, 0xD414, 0xBD79, 0xD415, 0xBD7A, 0xD416, 0xBD81, 0xD417, 0xBD82, 0xD418, + 0xBD83, 0xD419, 0xBD84, 0xD41A, 0xBD85, 0xD41B, 0xBD86, 0xD41C, 0xBD87, 0xD41E, 0xBD88, 0xD41F, 0xBD89, 0xD420, 0xBD8A, 0xD421, + 0xBD8B, 0xD422, 0xBD8C, 0xD423, 0xBD8D, 0xD424, 0xBD8E, 0xD425, 0xBD8F, 0xD426, 0xBD90, 0xD427, 0xBD91, 0xD428, 0xBD92, 0xD429, + 0xBD93, 0xD42A, 0xBD94, 0xD42B, 0xBD95, 0xD42C, 0xBD96, 0xD42D, 0xBD97, 0xD42E, 0xBD98, 0xD42F, 0xBD99, 0xD430, 0xBD9A, 0xD431, + 0xBD9B, 0xD432, 0xBD9C, 0xD433, 0xBD9D, 0xD434, 0xBD9E, 0xD435, 0xBD9F, 0xD436, 0xBDA0, 0xD437, 0xBDA1, 0xC22F, 0xBDA2, 0xC231, + 0xBDA3, 0xC232, 0xBDA4, 0xC234, 0xBDA5, 0xC248, 0xBDA6, 0xC250, 0xBDA7, 0xC251, 0xBDA8, 0xC254, 0xBDA9, 0xC258, 0xBDAA, 0xC260, + 0xBDAB, 0xC265, 0xBDAC, 0xC26C, 0xBDAD, 0xC26D, 0xBDAE, 0xC270, 0xBDAF, 0xC274, 0xBDB0, 0xC27C, 0xBDB1, 0xC27D, 0xBDB2, 0xC27F, + 0xBDB3, 0xC281, 0xBDB4, 0xC288, 0xBDB5, 0xC289, 0xBDB6, 0xC290, 0xBDB7, 0xC298, 0xBDB8, 0xC29B, 0xBDB9, 0xC29D, 0xBDBA, 0xC2A4, + 0xBDBB, 0xC2A5, 0xBDBC, 0xC2A8, 0xBDBD, 0xC2AC, 0xBDBE, 0xC2AD, 0xBDBF, 0xC2B4, 0xBDC0, 0xC2B5, 0xBDC1, 0xC2B7, 0xBDC2, 0xC2B9, + 0xBDC3, 0xC2DC, 0xBDC4, 0xC2DD, 0xBDC5, 0xC2E0, 0xBDC6, 0xC2E3, 0xBDC7, 0xC2E4, 0xBDC8, 0xC2EB, 0xBDC9, 0xC2EC, 0xBDCA, 0xC2ED, + 0xBDCB, 0xC2EF, 0xBDCC, 0xC2F1, 0xBDCD, 0xC2F6, 0xBDCE, 0xC2F8, 0xBDCF, 0xC2F9, 0xBDD0, 0xC2FB, 0xBDD1, 0xC2FC, 0xBDD2, 0xC300, + 0xBDD3, 0xC308, 0xBDD4, 0xC309, 0xBDD5, 0xC30C, 0xBDD6, 0xC30D, 0xBDD7, 0xC313, 0xBDD8, 0xC314, 0xBDD9, 0xC315, 0xBDDA, 0xC318, + 0xBDDB, 0xC31C, 0xBDDC, 0xC324, 0xBDDD, 0xC325, 0xBDDE, 0xC328, 0xBDDF, 0xC329, 0xBDE0, 0xC345, 0xBDE1, 0xC368, 0xBDE2, 0xC369, + 0xBDE3, 0xC36C, 0xBDE4, 0xC370, 0xBDE5, 0xC372, 0xBDE6, 0xC378, 0xBDE7, 0xC379, 0xBDE8, 0xC37C, 0xBDE9, 0xC37D, 0xBDEA, 0xC384, + 0xBDEB, 0xC388, 0xBDEC, 0xC38C, 0xBDED, 0xC3C0, 0xBDEE, 0xC3D8, 0xBDEF, 0xC3D9, 0xBDF0, 0xC3DC, 0xBDF1, 0xC3DF, 0xBDF2, 0xC3E0, + 0xBDF3, 0xC3E2, 0xBDF4, 0xC3E8, 0xBDF5, 0xC3E9, 0xBDF6, 0xC3ED, 0xBDF7, 0xC3F4, 0xBDF8, 0xC3F5, 0xBDF9, 0xC3F8, 0xBDFA, 0xC408, + 0xBDFB, 0xC410, 0xBDFC, 0xC424, 0xBDFD, 0xC42C, 0xBDFE, 0xC430, 0xBE41, 0xD438, 0xBE42, 0xD439, 0xBE43, 0xD43A, 0xBE44, 0xD43B, + 0xBE45, 0xD43C, 0xBE46, 0xD43D, 0xBE47, 0xD43E, 0xBE48, 0xD43F, 0xBE49, 0xD441, 0xBE4A, 0xD442, 0xBE4B, 0xD443, 0xBE4C, 0xD445, + 0xBE4D, 0xD446, 0xBE4E, 0xD447, 0xBE4F, 0xD448, 0xBE50, 0xD449, 0xBE51, 0xD44A, 0xBE52, 0xD44B, 0xBE53, 0xD44C, 0xBE54, 0xD44D, + 0xBE55, 0xD44E, 0xBE56, 0xD44F, 0xBE57, 0xD450, 0xBE58, 0xD451, 0xBE59, 0xD452, 0xBE5A, 0xD453, 0xBE61, 0xD454, 0xBE62, 0xD455, + 0xBE63, 0xD456, 0xBE64, 0xD457, 0xBE65, 0xD458, 0xBE66, 0xD459, 0xBE67, 0xD45A, 0xBE68, 0xD45B, 0xBE69, 0xD45D, 0xBE6A, 0xD45E, + 0xBE6B, 0xD45F, 0xBE6C, 0xD461, 0xBE6D, 0xD462, 0xBE6E, 0xD463, 0xBE6F, 0xD465, 0xBE70, 0xD466, 0xBE71, 0xD467, 0xBE72, 0xD468, + 0xBE73, 0xD469, 0xBE74, 0xD46A, 0xBE75, 0xD46B, 0xBE76, 0xD46C, 0xBE77, 0xD46E, 0xBE78, 0xD470, 0xBE79, 0xD471, 0xBE7A, 0xD472, + 0xBE81, 0xD473, 0xBE82, 0xD474, 0xBE83, 0xD475, 0xBE84, 0xD476, 0xBE85, 0xD477, 0xBE86, 0xD47A, 0xBE87, 0xD47B, 0xBE88, 0xD47D, + 0xBE89, 0xD47E, 0xBE8A, 0xD481, 0xBE8B, 0xD483, 0xBE8C, 0xD484, 0xBE8D, 0xD485, 0xBE8E, 0xD486, 0xBE8F, 0xD487, 0xBE90, 0xD48A, + 0xBE91, 0xD48C, 0xBE92, 0xD48E, 0xBE93, 0xD48F, 0xBE94, 0xD490, 0xBE95, 0xD491, 0xBE96, 0xD492, 0xBE97, 0xD493, 0xBE98, 0xD495, + 0xBE99, 0xD496, 0xBE9A, 0xD497, 0xBE9B, 0xD498, 0xBE9C, 0xD499, 0xBE9D, 0xD49A, 0xBE9E, 0xD49B, 0xBE9F, 0xD49C, 0xBEA0, 0xD49D, + 0xBEA1, 0xC434, 0xBEA2, 0xC43C, 0xBEA3, 0xC43D, 0xBEA4, 0xC448, 0xBEA5, 0xC464, 0xBEA6, 0xC465, 0xBEA7, 0xC468, 0xBEA8, 0xC46C, + 0xBEA9, 0xC474, 0xBEAA, 0xC475, 0xBEAB, 0xC479, 0xBEAC, 0xC480, 0xBEAD, 0xC494, 0xBEAE, 0xC49C, 0xBEAF, 0xC4B8, 0xBEB0, 0xC4BC, + 0xBEB1, 0xC4E9, 0xBEB2, 0xC4F0, 0xBEB3, 0xC4F1, 0xBEB4, 0xC4F4, 0xBEB5, 0xC4F8, 0xBEB6, 0xC4FA, 0xBEB7, 0xC4FF, 0xBEB8, 0xC500, + 0xBEB9, 0xC501, 0xBEBA, 0xC50C, 0xBEBB, 0xC510, 0xBEBC, 0xC514, 0xBEBD, 0xC51C, 0xBEBE, 0xC528, 0xBEBF, 0xC529, 0xBEC0, 0xC52C, + 0xBEC1, 0xC530, 0xBEC2, 0xC538, 0xBEC3, 0xC539, 0xBEC4, 0xC53B, 0xBEC5, 0xC53D, 0xBEC6, 0xC544, 0xBEC7, 0xC545, 0xBEC8, 0xC548, + 0xBEC9, 0xC549, 0xBECA, 0xC54A, 0xBECB, 0xC54C, 0xBECC, 0xC54D, 0xBECD, 0xC54E, 0xBECE, 0xC553, 0xBECF, 0xC554, 0xBED0, 0xC555, + 0xBED1, 0xC557, 0xBED2, 0xC558, 0xBED3, 0xC559, 0xBED4, 0xC55D, 0xBED5, 0xC55E, 0xBED6, 0xC560, 0xBED7, 0xC561, 0xBED8, 0xC564, + 0xBED9, 0xC568, 0xBEDA, 0xC570, 0xBEDB, 0xC571, 0xBEDC, 0xC573, 0xBEDD, 0xC574, 0xBEDE, 0xC575, 0xBEDF, 0xC57C, 0xBEE0, 0xC57D, + 0xBEE1, 0xC580, 0xBEE2, 0xC584, 0xBEE3, 0xC587, 0xBEE4, 0xC58C, 0xBEE5, 0xC58D, 0xBEE6, 0xC58F, 0xBEE7, 0xC591, 0xBEE8, 0xC595, + 0xBEE9, 0xC597, 0xBEEA, 0xC598, 0xBEEB, 0xC59C, 0xBEEC, 0xC5A0, 0xBEED, 0xC5A9, 0xBEEE, 0xC5B4, 0xBEEF, 0xC5B5, 0xBEF0, 0xC5B8, + 0xBEF1, 0xC5B9, 0xBEF2, 0xC5BB, 0xBEF3, 0xC5BC, 0xBEF4, 0xC5BD, 0xBEF5, 0xC5BE, 0xBEF6, 0xC5C4, 0xBEF7, 0xC5C5, 0xBEF8, 0xC5C6, + 0xBEF9, 0xC5C7, 0xBEFA, 0xC5C8, 0xBEFB, 0xC5C9, 0xBEFC, 0xC5CA, 0xBEFD, 0xC5CC, 0xBEFE, 0xC5CE, 0xBF41, 0xD49E, 0xBF42, 0xD49F, + 0xBF43, 0xD4A0, 0xBF44, 0xD4A1, 0xBF45, 0xD4A2, 0xBF46, 0xD4A3, 0xBF47, 0xD4A4, 0xBF48, 0xD4A5, 0xBF49, 0xD4A6, 0xBF4A, 0xD4A7, + 0xBF4B, 0xD4A8, 0xBF4C, 0xD4AA, 0xBF4D, 0xD4AB, 0xBF4E, 0xD4AC, 0xBF4F, 0xD4AD, 0xBF50, 0xD4AE, 0xBF51, 0xD4AF, 0xBF52, 0xD4B0, + 0xBF53, 0xD4B1, 0xBF54, 0xD4B2, 0xBF55, 0xD4B3, 0xBF56, 0xD4B4, 0xBF57, 0xD4B5, 0xBF58, 0xD4B6, 0xBF59, 0xD4B7, 0xBF5A, 0xD4B8, + 0xBF61, 0xD4B9, 0xBF62, 0xD4BA, 0xBF63, 0xD4BB, 0xBF64, 0xD4BC, 0xBF65, 0xD4BD, 0xBF66, 0xD4BE, 0xBF67, 0xD4BF, 0xBF68, 0xD4C0, + 0xBF69, 0xD4C1, 0xBF6A, 0xD4C2, 0xBF6B, 0xD4C3, 0xBF6C, 0xD4C4, 0xBF6D, 0xD4C5, 0xBF6E, 0xD4C6, 0xBF6F, 0xD4C7, 0xBF70, 0xD4C8, + 0xBF71, 0xD4C9, 0xBF72, 0xD4CA, 0xBF73, 0xD4CB, 0xBF74, 0xD4CD, 0xBF75, 0xD4CE, 0xBF76, 0xD4CF, 0xBF77, 0xD4D1, 0xBF78, 0xD4D2, + 0xBF79, 0xD4D3, 0xBF7A, 0xD4D5, 0xBF81, 0xD4D6, 0xBF82, 0xD4D7, 0xBF83, 0xD4D8, 0xBF84, 0xD4D9, 0xBF85, 0xD4DA, 0xBF86, 0xD4DB, + 0xBF87, 0xD4DD, 0xBF88, 0xD4DE, 0xBF89, 0xD4E0, 0xBF8A, 0xD4E1, 0xBF8B, 0xD4E2, 0xBF8C, 0xD4E3, 0xBF8D, 0xD4E4, 0xBF8E, 0xD4E5, + 0xBF8F, 0xD4E6, 0xBF90, 0xD4E7, 0xBF91, 0xD4E9, 0xBF92, 0xD4EA, 0xBF93, 0xD4EB, 0xBF94, 0xD4ED, 0xBF95, 0xD4EE, 0xBF96, 0xD4EF, + 0xBF97, 0xD4F1, 0xBF98, 0xD4F2, 0xBF99, 0xD4F3, 0xBF9A, 0xD4F4, 0xBF9B, 0xD4F5, 0xBF9C, 0xD4F6, 0xBF9D, 0xD4F7, 0xBF9E, 0xD4F9, + 0xBF9F, 0xD4FA, 0xBFA0, 0xD4FC, 0xBFA1, 0xC5D0, 0xBFA2, 0xC5D1, 0xBFA3, 0xC5D4, 0xBFA4, 0xC5D8, 0xBFA5, 0xC5E0, 0xBFA6, 0xC5E1, + 0xBFA7, 0xC5E3, 0xBFA8, 0xC5E5, 0xBFA9, 0xC5EC, 0xBFAA, 0xC5ED, 0xBFAB, 0xC5EE, 0xBFAC, 0xC5F0, 0xBFAD, 0xC5F4, 0xBFAE, 0xC5F6, + 0xBFAF, 0xC5F7, 0xBFB0, 0xC5FC, 0xBFB1, 0xC5FD, 0xBFB2, 0xC5FE, 0xBFB3, 0xC5FF, 0xBFB4, 0xC600, 0xBFB5, 0xC601, 0xBFB6, 0xC605, + 0xBFB7, 0xC606, 0xBFB8, 0xC607, 0xBFB9, 0xC608, 0xBFBA, 0xC60C, 0xBFBB, 0xC610, 0xBFBC, 0xC618, 0xBFBD, 0xC619, 0xBFBE, 0xC61B, + 0xBFBF, 0xC61C, 0xBFC0, 0xC624, 0xBFC1, 0xC625, 0xBFC2, 0xC628, 0xBFC3, 0xC62C, 0xBFC4, 0xC62D, 0xBFC5, 0xC62E, 0xBFC6, 0xC630, + 0xBFC7, 0xC633, 0xBFC8, 0xC634, 0xBFC9, 0xC635, 0xBFCA, 0xC637, 0xBFCB, 0xC639, 0xBFCC, 0xC63B, 0xBFCD, 0xC640, 0xBFCE, 0xC641, + 0xBFCF, 0xC644, 0xBFD0, 0xC648, 0xBFD1, 0xC650, 0xBFD2, 0xC651, 0xBFD3, 0xC653, 0xBFD4, 0xC654, 0xBFD5, 0xC655, 0xBFD6, 0xC65C, + 0xBFD7, 0xC65D, 0xBFD8, 0xC660, 0xBFD9, 0xC66C, 0xBFDA, 0xC66F, 0xBFDB, 0xC671, 0xBFDC, 0xC678, 0xBFDD, 0xC679, 0xBFDE, 0xC67C, + 0xBFDF, 0xC680, 0xBFE0, 0xC688, 0xBFE1, 0xC689, 0xBFE2, 0xC68B, 0xBFE3, 0xC68D, 0xBFE4, 0xC694, 0xBFE5, 0xC695, 0xBFE6, 0xC698, + 0xBFE7, 0xC69C, 0xBFE8, 0xC6A4, 0xBFE9, 0xC6A5, 0xBFEA, 0xC6A7, 0xBFEB, 0xC6A9, 0xBFEC, 0xC6B0, 0xBFED, 0xC6B1, 0xBFEE, 0xC6B4, + 0xBFEF, 0xC6B8, 0xBFF0, 0xC6B9, 0xBFF1, 0xC6BA, 0xBFF2, 0xC6C0, 0xBFF3, 0xC6C1, 0xBFF4, 0xC6C3, 0xBFF5, 0xC6C5, 0xBFF6, 0xC6CC, + 0xBFF7, 0xC6CD, 0xBFF8, 0xC6D0, 0xBFF9, 0xC6D4, 0xBFFA, 0xC6DC, 0xBFFB, 0xC6DD, 0xBFFC, 0xC6E0, 0xBFFD, 0xC6E1, 0xBFFE, 0xC6E8, + 0xC041, 0xD4FE, 0xC042, 0xD4FF, 0xC043, 0xD500, 0xC044, 0xD501, 0xC045, 0xD502, 0xC046, 0xD503, 0xC047, 0xD505, 0xC048, 0xD506, + 0xC049, 0xD507, 0xC04A, 0xD509, 0xC04B, 0xD50A, 0xC04C, 0xD50B, 0xC04D, 0xD50D, 0xC04E, 0xD50E, 0xC04F, 0xD50F, 0xC050, 0xD510, + 0xC051, 0xD511, 0xC052, 0xD512, 0xC053, 0xD513, 0xC054, 0xD516, 0xC055, 0xD518, 0xC056, 0xD519, 0xC057, 0xD51A, 0xC058, 0xD51B, + 0xC059, 0xD51C, 0xC05A, 0xD51D, 0xC061, 0xD51E, 0xC062, 0xD51F, 0xC063, 0xD520, 0xC064, 0xD521, 0xC065, 0xD522, 0xC066, 0xD523, + 0xC067, 0xD524, 0xC068, 0xD525, 0xC069, 0xD526, 0xC06A, 0xD527, 0xC06B, 0xD528, 0xC06C, 0xD529, 0xC06D, 0xD52A, 0xC06E, 0xD52B, + 0xC06F, 0xD52C, 0xC070, 0xD52D, 0xC071, 0xD52E, 0xC072, 0xD52F, 0xC073, 0xD530, 0xC074, 0xD531, 0xC075, 0xD532, 0xC076, 0xD533, + 0xC077, 0xD534, 0xC078, 0xD535, 0xC079, 0xD536, 0xC07A, 0xD537, 0xC081, 0xD538, 0xC082, 0xD539, 0xC083, 0xD53A, 0xC084, 0xD53B, + 0xC085, 0xD53E, 0xC086, 0xD53F, 0xC087, 0xD541, 0xC088, 0xD542, 0xC089, 0xD543, 0xC08A, 0xD545, 0xC08B, 0xD546, 0xC08C, 0xD547, + 0xC08D, 0xD548, 0xC08E, 0xD549, 0xC08F, 0xD54A, 0xC090, 0xD54B, 0xC091, 0xD54E, 0xC092, 0xD550, 0xC093, 0xD552, 0xC094, 0xD553, + 0xC095, 0xD554, 0xC096, 0xD555, 0xC097, 0xD556, 0xC098, 0xD557, 0xC099, 0xD55A, 0xC09A, 0xD55B, 0xC09B, 0xD55D, 0xC09C, 0xD55E, + 0xC09D, 0xD55F, 0xC09E, 0xD561, 0xC09F, 0xD562, 0xC0A0, 0xD563, 0xC0A1, 0xC6E9, 0xC0A2, 0xC6EC, 0xC0A3, 0xC6F0, 0xC0A4, 0xC6F8, + 0xC0A5, 0xC6F9, 0xC0A6, 0xC6FD, 0xC0A7, 0xC704, 0xC0A8, 0xC705, 0xC0A9, 0xC708, 0xC0AA, 0xC70C, 0xC0AB, 0xC714, 0xC0AC, 0xC715, + 0xC0AD, 0xC717, 0xC0AE, 0xC719, 0xC0AF, 0xC720, 0xC0B0, 0xC721, 0xC0B1, 0xC724, 0xC0B2, 0xC728, 0xC0B3, 0xC730, 0xC0B4, 0xC731, + 0xC0B5, 0xC733, 0xC0B6, 0xC735, 0xC0B7, 0xC737, 0xC0B8, 0xC73C, 0xC0B9, 0xC73D, 0xC0BA, 0xC740, 0xC0BB, 0xC744, 0xC0BC, 0xC74A, + 0xC0BD, 0xC74C, 0xC0BE, 0xC74D, 0xC0BF, 0xC74F, 0xC0C0, 0xC751, 0xC0C1, 0xC752, 0xC0C2, 0xC753, 0xC0C3, 0xC754, 0xC0C4, 0xC755, + 0xC0C5, 0xC756, 0xC0C6, 0xC757, 0xC0C7, 0xC758, 0xC0C8, 0xC75C, 0xC0C9, 0xC760, 0xC0CA, 0xC768, 0xC0CB, 0xC76B, 0xC0CC, 0xC774, + 0xC0CD, 0xC775, 0xC0CE, 0xC778, 0xC0CF, 0xC77C, 0xC0D0, 0xC77D, 0xC0D1, 0xC77E, 0xC0D2, 0xC783, 0xC0D3, 0xC784, 0xC0D4, 0xC785, + 0xC0D5, 0xC787, 0xC0D6, 0xC788, 0xC0D7, 0xC789, 0xC0D8, 0xC78A, 0xC0D9, 0xC78E, 0xC0DA, 0xC790, 0xC0DB, 0xC791, 0xC0DC, 0xC794, + 0xC0DD, 0xC796, 0xC0DE, 0xC797, 0xC0DF, 0xC798, 0xC0E0, 0xC79A, 0xC0E1, 0xC7A0, 0xC0E2, 0xC7A1, 0xC0E3, 0xC7A3, 0xC0E4, 0xC7A4, + 0xC0E5, 0xC7A5, 0xC0E6, 0xC7A6, 0xC0E7, 0xC7AC, 0xC0E8, 0xC7AD, 0xC0E9, 0xC7B0, 0xC0EA, 0xC7B4, 0xC0EB, 0xC7BC, 0xC0EC, 0xC7BD, + 0xC0ED, 0xC7BF, 0xC0EE, 0xC7C0, 0xC0EF, 0xC7C1, 0xC0F0, 0xC7C8, 0xC0F1, 0xC7C9, 0xC0F2, 0xC7CC, 0xC0F3, 0xC7CE, 0xC0F4, 0xC7D0, + 0xC0F5, 0xC7D8, 0xC0F6, 0xC7DD, 0xC0F7, 0xC7E4, 0xC0F8, 0xC7E8, 0xC0F9, 0xC7EC, 0xC0FA, 0xC800, 0xC0FB, 0xC801, 0xC0FC, 0xC804, + 0xC0FD, 0xC808, 0xC0FE, 0xC80A, 0xC141, 0xD564, 0xC142, 0xD566, 0xC143, 0xD567, 0xC144, 0xD56A, 0xC145, 0xD56C, 0xC146, 0xD56E, + 0xC147, 0xD56F, 0xC148, 0xD570, 0xC149, 0xD571, 0xC14A, 0xD572, 0xC14B, 0xD573, 0xC14C, 0xD576, 0xC14D, 0xD577, 0xC14E, 0xD579, + 0xC14F, 0xD57A, 0xC150, 0xD57B, 0xC151, 0xD57D, 0xC152, 0xD57E, 0xC153, 0xD57F, 0xC154, 0xD580, 0xC155, 0xD581, 0xC156, 0xD582, + 0xC157, 0xD583, 0xC158, 0xD586, 0xC159, 0xD58A, 0xC15A, 0xD58B, 0xC161, 0xD58C, 0xC162, 0xD58D, 0xC163, 0xD58E, 0xC164, 0xD58F, + 0xC165, 0xD591, 0xC166, 0xD592, 0xC167, 0xD593, 0xC168, 0xD594, 0xC169, 0xD595, 0xC16A, 0xD596, 0xC16B, 0xD597, 0xC16C, 0xD598, + 0xC16D, 0xD599, 0xC16E, 0xD59A, 0xC16F, 0xD59B, 0xC170, 0xD59C, 0xC171, 0xD59D, 0xC172, 0xD59E, 0xC173, 0xD59F, 0xC174, 0xD5A0, + 0xC175, 0xD5A1, 0xC176, 0xD5A2, 0xC177, 0xD5A3, 0xC178, 0xD5A4, 0xC179, 0xD5A6, 0xC17A, 0xD5A7, 0xC181, 0xD5A8, 0xC182, 0xD5A9, + 0xC183, 0xD5AA, 0xC184, 0xD5AB, 0xC185, 0xD5AC, 0xC186, 0xD5AD, 0xC187, 0xD5AE, 0xC188, 0xD5AF, 0xC189, 0xD5B0, 0xC18A, 0xD5B1, + 0xC18B, 0xD5B2, 0xC18C, 0xD5B3, 0xC18D, 0xD5B4, 0xC18E, 0xD5B5, 0xC18F, 0xD5B6, 0xC190, 0xD5B7, 0xC191, 0xD5B8, 0xC192, 0xD5B9, + 0xC193, 0xD5BA, 0xC194, 0xD5BB, 0xC195, 0xD5BC, 0xC196, 0xD5BD, 0xC197, 0xD5BE, 0xC198, 0xD5BF, 0xC199, 0xD5C0, 0xC19A, 0xD5C1, + 0xC19B, 0xD5C2, 0xC19C, 0xD5C3, 0xC19D, 0xD5C4, 0xC19E, 0xD5C5, 0xC19F, 0xD5C6, 0xC1A0, 0xD5C7, 0xC1A1, 0xC810, 0xC1A2, 0xC811, + 0xC1A3, 0xC813, 0xC1A4, 0xC815, 0xC1A5, 0xC816, 0xC1A6, 0xC81C, 0xC1A7, 0xC81D, 0xC1A8, 0xC820, 0xC1A9, 0xC824, 0xC1AA, 0xC82C, + 0xC1AB, 0xC82D, 0xC1AC, 0xC82F, 0xC1AD, 0xC831, 0xC1AE, 0xC838, 0xC1AF, 0xC83C, 0xC1B0, 0xC840, 0xC1B1, 0xC848, 0xC1B2, 0xC849, + 0xC1B3, 0xC84C, 0xC1B4, 0xC84D, 0xC1B5, 0xC854, 0xC1B6, 0xC870, 0xC1B7, 0xC871, 0xC1B8, 0xC874, 0xC1B9, 0xC878, 0xC1BA, 0xC87A, + 0xC1BB, 0xC880, 0xC1BC, 0xC881, 0xC1BD, 0xC883, 0xC1BE, 0xC885, 0xC1BF, 0xC886, 0xC1C0, 0xC887, 0xC1C1, 0xC88B, 0xC1C2, 0xC88C, + 0xC1C3, 0xC88D, 0xC1C4, 0xC894, 0xC1C5, 0xC89D, 0xC1C6, 0xC89F, 0xC1C7, 0xC8A1, 0xC1C8, 0xC8A8, 0xC1C9, 0xC8BC, 0xC1CA, 0xC8BD, + 0xC1CB, 0xC8C4, 0xC1CC, 0xC8C8, 0xC1CD, 0xC8CC, 0xC1CE, 0xC8D4, 0xC1CF, 0xC8D5, 0xC1D0, 0xC8D7, 0xC1D1, 0xC8D9, 0xC1D2, 0xC8E0, + 0xC1D3, 0xC8E1, 0xC1D4, 0xC8E4, 0xC1D5, 0xC8F5, 0xC1D6, 0xC8FC, 0xC1D7, 0xC8FD, 0xC1D8, 0xC900, 0xC1D9, 0xC904, 0xC1DA, 0xC905, + 0xC1DB, 0xC906, 0xC1DC, 0xC90C, 0xC1DD, 0xC90D, 0xC1DE, 0xC90F, 0xC1DF, 0xC911, 0xC1E0, 0xC918, 0xC1E1, 0xC92C, 0xC1E2, 0xC934, + 0xC1E3, 0xC950, 0xC1E4, 0xC951, 0xC1E5, 0xC954, 0xC1E6, 0xC958, 0xC1E7, 0xC960, 0xC1E8, 0xC961, 0xC1E9, 0xC963, 0xC1EA, 0xC96C, + 0xC1EB, 0xC970, 0xC1EC, 0xC974, 0xC1ED, 0xC97C, 0xC1EE, 0xC988, 0xC1EF, 0xC989, 0xC1F0, 0xC98C, 0xC1F1, 0xC990, 0xC1F2, 0xC998, + 0xC1F3, 0xC999, 0xC1F4, 0xC99B, 0xC1F5, 0xC99D, 0xC1F6, 0xC9C0, 0xC1F7, 0xC9C1, 0xC1F8, 0xC9C4, 0xC1F9, 0xC9C7, 0xC1FA, 0xC9C8, + 0xC1FB, 0xC9CA, 0xC1FC, 0xC9D0, 0xC1FD, 0xC9D1, 0xC1FE, 0xC9D3, 0xC241, 0xD5CA, 0xC242, 0xD5CB, 0xC243, 0xD5CD, 0xC244, 0xD5CE, + 0xC245, 0xD5CF, 0xC246, 0xD5D1, 0xC247, 0xD5D3, 0xC248, 0xD5D4, 0xC249, 0xD5D5, 0xC24A, 0xD5D6, 0xC24B, 0xD5D7, 0xC24C, 0xD5DA, + 0xC24D, 0xD5DC, 0xC24E, 0xD5DE, 0xC24F, 0xD5DF, 0xC250, 0xD5E0, 0xC251, 0xD5E1, 0xC252, 0xD5E2, 0xC253, 0xD5E3, 0xC254, 0xD5E6, + 0xC255, 0xD5E7, 0xC256, 0xD5E9, 0xC257, 0xD5EA, 0xC258, 0xD5EB, 0xC259, 0xD5ED, 0xC25A, 0xD5EE, 0xC261, 0xD5EF, 0xC262, 0xD5F0, + 0xC263, 0xD5F1, 0xC264, 0xD5F2, 0xC265, 0xD5F3, 0xC266, 0xD5F6, 0xC267, 0xD5F8, 0xC268, 0xD5FA, 0xC269, 0xD5FB, 0xC26A, 0xD5FC, + 0xC26B, 0xD5FD, 0xC26C, 0xD5FE, 0xC26D, 0xD5FF, 0xC26E, 0xD602, 0xC26F, 0xD603, 0xC270, 0xD605, 0xC271, 0xD606, 0xC272, 0xD607, + 0xC273, 0xD609, 0xC274, 0xD60A, 0xC275, 0xD60B, 0xC276, 0xD60C, 0xC277, 0xD60D, 0xC278, 0xD60E, 0xC279, 0xD60F, 0xC27A, 0xD612, + 0xC281, 0xD616, 0xC282, 0xD617, 0xC283, 0xD618, 0xC284, 0xD619, 0xC285, 0xD61A, 0xC286, 0xD61B, 0xC287, 0xD61D, 0xC288, 0xD61E, + 0xC289, 0xD61F, 0xC28A, 0xD621, 0xC28B, 0xD622, 0xC28C, 0xD623, 0xC28D, 0xD625, 0xC28E, 0xD626, 0xC28F, 0xD627, 0xC290, 0xD628, + 0xC291, 0xD629, 0xC292, 0xD62A, 0xC293, 0xD62B, 0xC294, 0xD62C, 0xC295, 0xD62E, 0xC296, 0xD62F, 0xC297, 0xD630, 0xC298, 0xD631, + 0xC299, 0xD632, 0xC29A, 0xD633, 0xC29B, 0xD634, 0xC29C, 0xD635, 0xC29D, 0xD636, 0xC29E, 0xD637, 0xC29F, 0xD63A, 0xC2A0, 0xD63B, + 0xC2A1, 0xC9D5, 0xC2A2, 0xC9D6, 0xC2A3, 0xC9D9, 0xC2A4, 0xC9DA, 0xC2A5, 0xC9DC, 0xC2A6, 0xC9DD, 0xC2A7, 0xC9E0, 0xC2A8, 0xC9E2, + 0xC2A9, 0xC9E4, 0xC2AA, 0xC9E7, 0xC2AB, 0xC9EC, 0xC2AC, 0xC9ED, 0xC2AD, 0xC9EF, 0xC2AE, 0xC9F0, 0xC2AF, 0xC9F1, 0xC2B0, 0xC9F8, + 0xC2B1, 0xC9F9, 0xC2B2, 0xC9FC, 0xC2B3, 0xCA00, 0xC2B4, 0xCA08, 0xC2B5, 0xCA09, 0xC2B6, 0xCA0B, 0xC2B7, 0xCA0C, 0xC2B8, 0xCA0D, + 0xC2B9, 0xCA14, 0xC2BA, 0xCA18, 0xC2BB, 0xCA29, 0xC2BC, 0xCA4C, 0xC2BD, 0xCA4D, 0xC2BE, 0xCA50, 0xC2BF, 0xCA54, 0xC2C0, 0xCA5C, + 0xC2C1, 0xCA5D, 0xC2C2, 0xCA5F, 0xC2C3, 0xCA60, 0xC2C4, 0xCA61, 0xC2C5, 0xCA68, 0xC2C6, 0xCA7D, 0xC2C7, 0xCA84, 0xC2C8, 0xCA98, + 0xC2C9, 0xCABC, 0xC2CA, 0xCABD, 0xC2CB, 0xCAC0, 0xC2CC, 0xCAC4, 0xC2CD, 0xCACC, 0xC2CE, 0xCACD, 0xC2CF, 0xCACF, 0xC2D0, 0xCAD1, + 0xC2D1, 0xCAD3, 0xC2D2, 0xCAD8, 0xC2D3, 0xCAD9, 0xC2D4, 0xCAE0, 0xC2D5, 0xCAEC, 0xC2D6, 0xCAF4, 0xC2D7, 0xCB08, 0xC2D8, 0xCB10, + 0xC2D9, 0xCB14, 0xC2DA, 0xCB18, 0xC2DB, 0xCB20, 0xC2DC, 0xCB21, 0xC2DD, 0xCB41, 0xC2DE, 0xCB48, 0xC2DF, 0xCB49, 0xC2E0, 0xCB4C, + 0xC2E1, 0xCB50, 0xC2E2, 0xCB58, 0xC2E3, 0xCB59, 0xC2E4, 0xCB5D, 0xC2E5, 0xCB64, 0xC2E6, 0xCB78, 0xC2E7, 0xCB79, 0xC2E8, 0xCB9C, + 0xC2E9, 0xCBB8, 0xC2EA, 0xCBD4, 0xC2EB, 0xCBE4, 0xC2EC, 0xCBE7, 0xC2ED, 0xCBE9, 0xC2EE, 0xCC0C, 0xC2EF, 0xCC0D, 0xC2F0, 0xCC10, + 0xC2F1, 0xCC14, 0xC2F2, 0xCC1C, 0xC2F3, 0xCC1D, 0xC2F4, 0xCC21, 0xC2F5, 0xCC22, 0xC2F6, 0xCC27, 0xC2F7, 0xCC28, 0xC2F8, 0xCC29, + 0xC2F9, 0xCC2C, 0xC2FA, 0xCC2E, 0xC2FB, 0xCC30, 0xC2FC, 0xCC38, 0xC2FD, 0xCC39, 0xC2FE, 0xCC3B, 0xC341, 0xD63D, 0xC342, 0xD63E, + 0xC343, 0xD63F, 0xC344, 0xD641, 0xC345, 0xD642, 0xC346, 0xD643, 0xC347, 0xD644, 0xC348, 0xD646, 0xC349, 0xD647, 0xC34A, 0xD64A, + 0xC34B, 0xD64C, 0xC34C, 0xD64E, 0xC34D, 0xD64F, 0xC34E, 0xD650, 0xC34F, 0xD652, 0xC350, 0xD653, 0xC351, 0xD656, 0xC352, 0xD657, + 0xC353, 0xD659, 0xC354, 0xD65A, 0xC355, 0xD65B, 0xC356, 0xD65D, 0xC357, 0xD65E, 0xC358, 0xD65F, 0xC359, 0xD660, 0xC35A, 0xD661, + 0xC361, 0xD662, 0xC362, 0xD663, 0xC363, 0xD664, 0xC364, 0xD665, 0xC365, 0xD666, 0xC366, 0xD668, 0xC367, 0xD66A, 0xC368, 0xD66B, + 0xC369, 0xD66C, 0xC36A, 0xD66D, 0xC36B, 0xD66E, 0xC36C, 0xD66F, 0xC36D, 0xD672, 0xC36E, 0xD673, 0xC36F, 0xD675, 0xC370, 0xD676, + 0xC371, 0xD677, 0xC372, 0xD678, 0xC373, 0xD679, 0xC374, 0xD67A, 0xC375, 0xD67B, 0xC376, 0xD67C, 0xC377, 0xD67D, 0xC378, 0xD67E, + 0xC379, 0xD67F, 0xC37A, 0xD680, 0xC381, 0xD681, 0xC382, 0xD682, 0xC383, 0xD684, 0xC384, 0xD686, 0xC385, 0xD687, 0xC386, 0xD688, + 0xC387, 0xD689, 0xC388, 0xD68A, 0xC389, 0xD68B, 0xC38A, 0xD68E, 0xC38B, 0xD68F, 0xC38C, 0xD691, 0xC38D, 0xD692, 0xC38E, 0xD693, + 0xC38F, 0xD695, 0xC390, 0xD696, 0xC391, 0xD697, 0xC392, 0xD698, 0xC393, 0xD699, 0xC394, 0xD69A, 0xC395, 0xD69B, 0xC396, 0xD69C, + 0xC397, 0xD69E, 0xC398, 0xD6A0, 0xC399, 0xD6A2, 0xC39A, 0xD6A3, 0xC39B, 0xD6A4, 0xC39C, 0xD6A5, 0xC39D, 0xD6A6, 0xC39E, 0xD6A7, + 0xC39F, 0xD6A9, 0xC3A0, 0xD6AA, 0xC3A1, 0xCC3C, 0xC3A2, 0xCC3D, 0xC3A3, 0xCC3E, 0xC3A4, 0xCC44, 0xC3A5, 0xCC45, 0xC3A6, 0xCC48, + 0xC3A7, 0xCC4C, 0xC3A8, 0xCC54, 0xC3A9, 0xCC55, 0xC3AA, 0xCC57, 0xC3AB, 0xCC58, 0xC3AC, 0xCC59, 0xC3AD, 0xCC60, 0xC3AE, 0xCC64, + 0xC3AF, 0xCC66, 0xC3B0, 0xCC68, 0xC3B1, 0xCC70, 0xC3B2, 0xCC75, 0xC3B3, 0xCC98, 0xC3B4, 0xCC99, 0xC3B5, 0xCC9C, 0xC3B6, 0xCCA0, + 0xC3B7, 0xCCA8, 0xC3B8, 0xCCA9, 0xC3B9, 0xCCAB, 0xC3BA, 0xCCAC, 0xC3BB, 0xCCAD, 0xC3BC, 0xCCB4, 0xC3BD, 0xCCB5, 0xC3BE, 0xCCB8, + 0xC3BF, 0xCCBC, 0xC3C0, 0xCCC4, 0xC3C1, 0xCCC5, 0xC3C2, 0xCCC7, 0xC3C3, 0xCCC9, 0xC3C4, 0xCCD0, 0xC3C5, 0xCCD4, 0xC3C6, 0xCCE4, + 0xC3C7, 0xCCEC, 0xC3C8, 0xCCF0, 0xC3C9, 0xCD01, 0xC3CA, 0xCD08, 0xC3CB, 0xCD09, 0xC3CC, 0xCD0C, 0xC3CD, 0xCD10, 0xC3CE, 0xCD18, + 0xC3CF, 0xCD19, 0xC3D0, 0xCD1B, 0xC3D1, 0xCD1D, 0xC3D2, 0xCD24, 0xC3D3, 0xCD28, 0xC3D4, 0xCD2C, 0xC3D5, 0xCD39, 0xC3D6, 0xCD5C, + 0xC3D7, 0xCD60, 0xC3D8, 0xCD64, 0xC3D9, 0xCD6C, 0xC3DA, 0xCD6D, 0xC3DB, 0xCD6F, 0xC3DC, 0xCD71, 0xC3DD, 0xCD78, 0xC3DE, 0xCD88, + 0xC3DF, 0xCD94, 0xC3E0, 0xCD95, 0xC3E1, 0xCD98, 0xC3E2, 0xCD9C, 0xC3E3, 0xCDA4, 0xC3E4, 0xCDA5, 0xC3E5, 0xCDA7, 0xC3E6, 0xCDA9, + 0xC3E7, 0xCDB0, 0xC3E8, 0xCDC4, 0xC3E9, 0xCDCC, 0xC3EA, 0xCDD0, 0xC3EB, 0xCDE8, 0xC3EC, 0xCDEC, 0xC3ED, 0xCDF0, 0xC3EE, 0xCDF8, + 0xC3EF, 0xCDF9, 0xC3F0, 0xCDFB, 0xC3F1, 0xCDFD, 0xC3F2, 0xCE04, 0xC3F3, 0xCE08, 0xC3F4, 0xCE0C, 0xC3F5, 0xCE14, 0xC3F6, 0xCE19, + 0xC3F7, 0xCE20, 0xC3F8, 0xCE21, 0xC3F9, 0xCE24, 0xC3FA, 0xCE28, 0xC3FB, 0xCE30, 0xC3FC, 0xCE31, 0xC3FD, 0xCE33, 0xC3FE, 0xCE35, + 0xC441, 0xD6AB, 0xC442, 0xD6AD, 0xC443, 0xD6AE, 0xC444, 0xD6AF, 0xC445, 0xD6B1, 0xC446, 0xD6B2, 0xC447, 0xD6B3, 0xC448, 0xD6B4, + 0xC449, 0xD6B5, 0xC44A, 0xD6B6, 0xC44B, 0xD6B7, 0xC44C, 0xD6B8, 0xC44D, 0xD6BA, 0xC44E, 0xD6BC, 0xC44F, 0xD6BD, 0xC450, 0xD6BE, + 0xC451, 0xD6BF, 0xC452, 0xD6C0, 0xC453, 0xD6C1, 0xC454, 0xD6C2, 0xC455, 0xD6C3, 0xC456, 0xD6C6, 0xC457, 0xD6C7, 0xC458, 0xD6C9, + 0xC459, 0xD6CA, 0xC45A, 0xD6CB, 0xC461, 0xD6CD, 0xC462, 0xD6CE, 0xC463, 0xD6CF, 0xC464, 0xD6D0, 0xC465, 0xD6D2, 0xC466, 0xD6D3, + 0xC467, 0xD6D5, 0xC468, 0xD6D6, 0xC469, 0xD6D8, 0xC46A, 0xD6DA, 0xC46B, 0xD6DB, 0xC46C, 0xD6DC, 0xC46D, 0xD6DD, 0xC46E, 0xD6DE, + 0xC46F, 0xD6DF, 0xC470, 0xD6E1, 0xC471, 0xD6E2, 0xC472, 0xD6E3, 0xC473, 0xD6E5, 0xC474, 0xD6E6, 0xC475, 0xD6E7, 0xC476, 0xD6E9, + 0xC477, 0xD6EA, 0xC478, 0xD6EB, 0xC479, 0xD6EC, 0xC47A, 0xD6ED, 0xC481, 0xD6EE, 0xC482, 0xD6EF, 0xC483, 0xD6F1, 0xC484, 0xD6F2, + 0xC485, 0xD6F3, 0xC486, 0xD6F4, 0xC487, 0xD6F6, 0xC488, 0xD6F7, 0xC489, 0xD6F8, 0xC48A, 0xD6F9, 0xC48B, 0xD6FA, 0xC48C, 0xD6FB, + 0xC48D, 0xD6FE, 0xC48E, 0xD6FF, 0xC48F, 0xD701, 0xC490, 0xD702, 0xC491, 0xD703, 0xC492, 0xD705, 0xC493, 0xD706, 0xC494, 0xD707, + 0xC495, 0xD708, 0xC496, 0xD709, 0xC497, 0xD70A, 0xC498, 0xD70B, 0xC499, 0xD70C, 0xC49A, 0xD70D, 0xC49B, 0xD70E, 0xC49C, 0xD70F, + 0xC49D, 0xD710, 0xC49E, 0xD712, 0xC49F, 0xD713, 0xC4A0, 0xD714, 0xC4A1, 0xCE58, 0xC4A2, 0xCE59, 0xC4A3, 0xCE5C, 0xC4A4, 0xCE5F, + 0xC4A5, 0xCE60, 0xC4A6, 0xCE61, 0xC4A7, 0xCE68, 0xC4A8, 0xCE69, 0xC4A9, 0xCE6B, 0xC4AA, 0xCE6D, 0xC4AB, 0xCE74, 0xC4AC, 0xCE75, + 0xC4AD, 0xCE78, 0xC4AE, 0xCE7C, 0xC4AF, 0xCE84, 0xC4B0, 0xCE85, 0xC4B1, 0xCE87, 0xC4B2, 0xCE89, 0xC4B3, 0xCE90, 0xC4B4, 0xCE91, + 0xC4B5, 0xCE94, 0xC4B6, 0xCE98, 0xC4B7, 0xCEA0, 0xC4B8, 0xCEA1, 0xC4B9, 0xCEA3, 0xC4BA, 0xCEA4, 0xC4BB, 0xCEA5, 0xC4BC, 0xCEAC, + 0xC4BD, 0xCEAD, 0xC4BE, 0xCEC1, 0xC4BF, 0xCEE4, 0xC4C0, 0xCEE5, 0xC4C1, 0xCEE8, 0xC4C2, 0xCEEB, 0xC4C3, 0xCEEC, 0xC4C4, 0xCEF4, + 0xC4C5, 0xCEF5, 0xC4C6, 0xCEF7, 0xC4C7, 0xCEF8, 0xC4C8, 0xCEF9, 0xC4C9, 0xCF00, 0xC4CA, 0xCF01, 0xC4CB, 0xCF04, 0xC4CC, 0xCF08, + 0xC4CD, 0xCF10, 0xC4CE, 0xCF11, 0xC4CF, 0xCF13, 0xC4D0, 0xCF15, 0xC4D1, 0xCF1C, 0xC4D2, 0xCF20, 0xC4D3, 0xCF24, 0xC4D4, 0xCF2C, + 0xC4D5, 0xCF2D, 0xC4D6, 0xCF2F, 0xC4D7, 0xCF30, 0xC4D8, 0xCF31, 0xC4D9, 0xCF38, 0xC4DA, 0xCF54, 0xC4DB, 0xCF55, 0xC4DC, 0xCF58, + 0xC4DD, 0xCF5C, 0xC4DE, 0xCF64, 0xC4DF, 0xCF65, 0xC4E0, 0xCF67, 0xC4E1, 0xCF69, 0xC4E2, 0xCF70, 0xC4E3, 0xCF71, 0xC4E4, 0xCF74, + 0xC4E5, 0xCF78, 0xC4E6, 0xCF80, 0xC4E7, 0xCF85, 0xC4E8, 0xCF8C, 0xC4E9, 0xCFA1, 0xC4EA, 0xCFA8, 0xC4EB, 0xCFB0, 0xC4EC, 0xCFC4, + 0xC4ED, 0xCFE0, 0xC4EE, 0xCFE1, 0xC4EF, 0xCFE4, 0xC4F0, 0xCFE8, 0xC4F1, 0xCFF0, 0xC4F2, 0xCFF1, 0xC4F3, 0xCFF3, 0xC4F4, 0xCFF5, + 0xC4F5, 0xCFFC, 0xC4F6, 0xD000, 0xC4F7, 0xD004, 0xC4F8, 0xD011, 0xC4F9, 0xD018, 0xC4FA, 0xD02D, 0xC4FB, 0xD034, 0xC4FC, 0xD035, + 0xC4FD, 0xD038, 0xC4FE, 0xD03C, 0xC541, 0xD715, 0xC542, 0xD716, 0xC543, 0xD717, 0xC544, 0xD71A, 0xC545, 0xD71B, 0xC546, 0xD71D, + 0xC547, 0xD71E, 0xC548, 0xD71F, 0xC549, 0xD721, 0xC54A, 0xD722, 0xC54B, 0xD723, 0xC54C, 0xD724, 0xC54D, 0xD725, 0xC54E, 0xD726, + 0xC54F, 0xD727, 0xC550, 0xD72A, 0xC551, 0xD72C, 0xC552, 0xD72E, 0xC553, 0xD72F, 0xC554, 0xD730, 0xC555, 0xD731, 0xC556, 0xD732, + 0xC557, 0xD733, 0xC558, 0xD736, 0xC559, 0xD737, 0xC55A, 0xD739, 0xC561, 0xD73A, 0xC562, 0xD73B, 0xC563, 0xD73D, 0xC564, 0xD73E, + 0xC565, 0xD73F, 0xC566, 0xD740, 0xC567, 0xD741, 0xC568, 0xD742, 0xC569, 0xD743, 0xC56A, 0xD745, 0xC56B, 0xD746, 0xC56C, 0xD748, + 0xC56D, 0xD74A, 0xC56E, 0xD74B, 0xC56F, 0xD74C, 0xC570, 0xD74D, 0xC571, 0xD74E, 0xC572, 0xD74F, 0xC573, 0xD752, 0xC574, 0xD753, + 0xC575, 0xD755, 0xC576, 0xD75A, 0xC577, 0xD75B, 0xC578, 0xD75C, 0xC579, 0xD75D, 0xC57A, 0xD75E, 0xC581, 0xD75F, 0xC582, 0xD762, + 0xC583, 0xD764, 0xC584, 0xD766, 0xC585, 0xD767, 0xC586, 0xD768, 0xC587, 0xD76A, 0xC588, 0xD76B, 0xC589, 0xD76D, 0xC58A, 0xD76E, + 0xC58B, 0xD76F, 0xC58C, 0xD771, 0xC58D, 0xD772, 0xC58E, 0xD773, 0xC58F, 0xD775, 0xC590, 0xD776, 0xC591, 0xD777, 0xC592, 0xD778, + 0xC593, 0xD779, 0xC594, 0xD77A, 0xC595, 0xD77B, 0xC596, 0xD77E, 0xC597, 0xD77F, 0xC598, 0xD780, 0xC599, 0xD782, 0xC59A, 0xD783, + 0xC59B, 0xD784, 0xC59C, 0xD785, 0xC59D, 0xD786, 0xC59E, 0xD787, 0xC59F, 0xD78A, 0xC5A0, 0xD78B, 0xC5A1, 0xD044, 0xC5A2, 0xD045, + 0xC5A3, 0xD047, 0xC5A4, 0xD049, 0xC5A5, 0xD050, 0xC5A6, 0xD054, 0xC5A7, 0xD058, 0xC5A8, 0xD060, 0xC5A9, 0xD06C, 0xC5AA, 0xD06D, + 0xC5AB, 0xD070, 0xC5AC, 0xD074, 0xC5AD, 0xD07C, 0xC5AE, 0xD07D, 0xC5AF, 0xD081, 0xC5B0, 0xD0A4, 0xC5B1, 0xD0A5, 0xC5B2, 0xD0A8, + 0xC5B3, 0xD0AC, 0xC5B4, 0xD0B4, 0xC5B5, 0xD0B5, 0xC5B6, 0xD0B7, 0xC5B7, 0xD0B9, 0xC5B8, 0xD0C0, 0xC5B9, 0xD0C1, 0xC5BA, 0xD0C4, + 0xC5BB, 0xD0C8, 0xC5BC, 0xD0C9, 0xC5BD, 0xD0D0, 0xC5BE, 0xD0D1, 0xC5BF, 0xD0D3, 0xC5C0, 0xD0D4, 0xC5C1, 0xD0D5, 0xC5C2, 0xD0DC, + 0xC5C3, 0xD0DD, 0xC5C4, 0xD0E0, 0xC5C5, 0xD0E4, 0xC5C6, 0xD0EC, 0xC5C7, 0xD0ED, 0xC5C8, 0xD0EF, 0xC5C9, 0xD0F0, 0xC5CA, 0xD0F1, + 0xC5CB, 0xD0F8, 0xC5CC, 0xD10D, 0xC5CD, 0xD130, 0xC5CE, 0xD131, 0xC5CF, 0xD134, 0xC5D0, 0xD138, 0xC5D1, 0xD13A, 0xC5D2, 0xD140, + 0xC5D3, 0xD141, 0xC5D4, 0xD143, 0xC5D5, 0xD144, 0xC5D6, 0xD145, 0xC5D7, 0xD14C, 0xC5D8, 0xD14D, 0xC5D9, 0xD150, 0xC5DA, 0xD154, + 0xC5DB, 0xD15C, 0xC5DC, 0xD15D, 0xC5DD, 0xD15F, 0xC5DE, 0xD161, 0xC5DF, 0xD168, 0xC5E0, 0xD16C, 0xC5E1, 0xD17C, 0xC5E2, 0xD184, + 0xC5E3, 0xD188, 0xC5E4, 0xD1A0, 0xC5E5, 0xD1A1, 0xC5E6, 0xD1A4, 0xC5E7, 0xD1A8, 0xC5E8, 0xD1B0, 0xC5E9, 0xD1B1, 0xC5EA, 0xD1B3, + 0xC5EB, 0xD1B5, 0xC5EC, 0xD1BA, 0xC5ED, 0xD1BC, 0xC5EE, 0xD1C0, 0xC5EF, 0xD1D8, 0xC5F0, 0xD1F4, 0xC5F1, 0xD1F8, 0xC5F2, 0xD207, + 0xC5F3, 0xD209, 0xC5F4, 0xD210, 0xC5F5, 0xD22C, 0xC5F6, 0xD22D, 0xC5F7, 0xD230, 0xC5F8, 0xD234, 0xC5F9, 0xD23C, 0xC5FA, 0xD23D, + 0xC5FB, 0xD23F, 0xC5FC, 0xD241, 0xC5FD, 0xD248, 0xC5FE, 0xD25C, 0xC641, 0xD78D, 0xC642, 0xD78E, 0xC643, 0xD78F, 0xC644, 0xD791, + 0xC645, 0xD792, 0xC646, 0xD793, 0xC647, 0xD794, 0xC648, 0xD795, 0xC649, 0xD796, 0xC64A, 0xD797, 0xC64B, 0xD79A, 0xC64C, 0xD79C, + 0xC64D, 0xD79E, 0xC64E, 0xD79F, 0xC64F, 0xD7A0, 0xC650, 0xD7A1, 0xC651, 0xD7A2, 0xC652, 0xD7A3, 0xC6A1, 0xD264, 0xC6A2, 0xD280, + 0xC6A3, 0xD281, 0xC6A4, 0xD284, 0xC6A5, 0xD288, 0xC6A6, 0xD290, 0xC6A7, 0xD291, 0xC6A8, 0xD295, 0xC6A9, 0xD29C, 0xC6AA, 0xD2A0, + 0xC6AB, 0xD2A4, 0xC6AC, 0xD2AC, 0xC6AD, 0xD2B1, 0xC6AE, 0xD2B8, 0xC6AF, 0xD2B9, 0xC6B0, 0xD2BC, 0xC6B1, 0xD2BF, 0xC6B2, 0xD2C0, + 0xC6B3, 0xD2C2, 0xC6B4, 0xD2C8, 0xC6B5, 0xD2C9, 0xC6B6, 0xD2CB, 0xC6B7, 0xD2D4, 0xC6B8, 0xD2D8, 0xC6B9, 0xD2DC, 0xC6BA, 0xD2E4, + 0xC6BB, 0xD2E5, 0xC6BC, 0xD2F0, 0xC6BD, 0xD2F1, 0xC6BE, 0xD2F4, 0xC6BF, 0xD2F8, 0xC6C0, 0xD300, 0xC6C1, 0xD301, 0xC6C2, 0xD303, + 0xC6C3, 0xD305, 0xC6C4, 0xD30C, 0xC6C5, 0xD30D, 0xC6C6, 0xD30E, 0xC6C7, 0xD310, 0xC6C8, 0xD314, 0xC6C9, 0xD316, 0xC6CA, 0xD31C, + 0xC6CB, 0xD31D, 0xC6CC, 0xD31F, 0xC6CD, 0xD320, 0xC6CE, 0xD321, 0xC6CF, 0xD325, 0xC6D0, 0xD328, 0xC6D1, 0xD329, 0xC6D2, 0xD32C, + 0xC6D3, 0xD330, 0xC6D4, 0xD338, 0xC6D5, 0xD339, 0xC6D6, 0xD33B, 0xC6D7, 0xD33C, 0xC6D8, 0xD33D, 0xC6D9, 0xD344, 0xC6DA, 0xD345, + 0xC6DB, 0xD37C, 0xC6DC, 0xD37D, 0xC6DD, 0xD380, 0xC6DE, 0xD384, 0xC6DF, 0xD38C, 0xC6E0, 0xD38D, 0xC6E1, 0xD38F, 0xC6E2, 0xD390, + 0xC6E3, 0xD391, 0xC6E4, 0xD398, 0xC6E5, 0xD399, 0xC6E6, 0xD39C, 0xC6E7, 0xD3A0, 0xC6E8, 0xD3A8, 0xC6E9, 0xD3A9, 0xC6EA, 0xD3AB, + 0xC6EB, 0xD3AD, 0xC6EC, 0xD3B4, 0xC6ED, 0xD3B8, 0xC6EE, 0xD3BC, 0xC6EF, 0xD3C4, 0xC6F0, 0xD3C5, 0xC6F1, 0xD3C8, 0xC6F2, 0xD3C9, + 0xC6F3, 0xD3D0, 0xC6F4, 0xD3D8, 0xC6F5, 0xD3E1, 0xC6F6, 0xD3E3, 0xC6F7, 0xD3EC, 0xC6F8, 0xD3ED, 0xC6F9, 0xD3F0, 0xC6FA, 0xD3F4, + 0xC6FB, 0xD3FC, 0xC6FC, 0xD3FD, 0xC6FD, 0xD3FF, 0xC6FE, 0xD401, 0xC7A1, 0xD408, 0xC7A2, 0xD41D, 0xC7A3, 0xD440, 0xC7A4, 0xD444, + 0xC7A5, 0xD45C, 0xC7A6, 0xD460, 0xC7A7, 0xD464, 0xC7A8, 0xD46D, 0xC7A9, 0xD46F, 0xC7AA, 0xD478, 0xC7AB, 0xD479, 0xC7AC, 0xD47C, + 0xC7AD, 0xD47F, 0xC7AE, 0xD480, 0xC7AF, 0xD482, 0xC7B0, 0xD488, 0xC7B1, 0xD489, 0xC7B2, 0xD48B, 0xC7B3, 0xD48D, 0xC7B4, 0xD494, + 0xC7B5, 0xD4A9, 0xC7B6, 0xD4CC, 0xC7B7, 0xD4D0, 0xC7B8, 0xD4D4, 0xC7B9, 0xD4DC, 0xC7BA, 0xD4DF, 0xC7BB, 0xD4E8, 0xC7BC, 0xD4EC, + 0xC7BD, 0xD4F0, 0xC7BE, 0xD4F8, 0xC7BF, 0xD4FB, 0xC7C0, 0xD4FD, 0xC7C1, 0xD504, 0xC7C2, 0xD508, 0xC7C3, 0xD50C, 0xC7C4, 0xD514, + 0xC7C5, 0xD515, 0xC7C6, 0xD517, 0xC7C7, 0xD53C, 0xC7C8, 0xD53D, 0xC7C9, 0xD540, 0xC7CA, 0xD544, 0xC7CB, 0xD54C, 0xC7CC, 0xD54D, + 0xC7CD, 0xD54F, 0xC7CE, 0xD551, 0xC7CF, 0xD558, 0xC7D0, 0xD559, 0xC7D1, 0xD55C, 0xC7D2, 0xD560, 0xC7D3, 0xD565, 0xC7D4, 0xD568, + 0xC7D5, 0xD569, 0xC7D6, 0xD56B, 0xC7D7, 0xD56D, 0xC7D8, 0xD574, 0xC7D9, 0xD575, 0xC7DA, 0xD578, 0xC7DB, 0xD57C, 0xC7DC, 0xD584, + 0xC7DD, 0xD585, 0xC7DE, 0xD587, 0xC7DF, 0xD588, 0xC7E0, 0xD589, 0xC7E1, 0xD590, 0xC7E2, 0xD5A5, 0xC7E3, 0xD5C8, 0xC7E4, 0xD5C9, + 0xC7E5, 0xD5CC, 0xC7E6, 0xD5D0, 0xC7E7, 0xD5D2, 0xC7E8, 0xD5D8, 0xC7E9, 0xD5D9, 0xC7EA, 0xD5DB, 0xC7EB, 0xD5DD, 0xC7EC, 0xD5E4, + 0xC7ED, 0xD5E5, 0xC7EE, 0xD5E8, 0xC7EF, 0xD5EC, 0xC7F0, 0xD5F4, 0xC7F1, 0xD5F5, 0xC7F2, 0xD5F7, 0xC7F3, 0xD5F9, 0xC7F4, 0xD600, + 0xC7F5, 0xD601, 0xC7F6, 0xD604, 0xC7F7, 0xD608, 0xC7F8, 0xD610, 0xC7F9, 0xD611, 0xC7FA, 0xD613, 0xC7FB, 0xD614, 0xC7FC, 0xD615, + 0xC7FD, 0xD61C, 0xC7FE, 0xD620, 0xC8A1, 0xD624, 0xC8A2, 0xD62D, 0xC8A3, 0xD638, 0xC8A4, 0xD639, 0xC8A5, 0xD63C, 0xC8A6, 0xD640, + 0xC8A7, 0xD645, 0xC8A8, 0xD648, 0xC8A9, 0xD649, 0xC8AA, 0xD64B, 0xC8AB, 0xD64D, 0xC8AC, 0xD651, 0xC8AD, 0xD654, 0xC8AE, 0xD655, + 0xC8AF, 0xD658, 0xC8B0, 0xD65C, 0xC8B1, 0xD667, 0xC8B2, 0xD669, 0xC8B3, 0xD670, 0xC8B4, 0xD671, 0xC8B5, 0xD674, 0xC8B6, 0xD683, + 0xC8B7, 0xD685, 0xC8B8, 0xD68C, 0xC8B9, 0xD68D, 0xC8BA, 0xD690, 0xC8BB, 0xD694, 0xC8BC, 0xD69D, 0xC8BD, 0xD69F, 0xC8BE, 0xD6A1, + 0xC8BF, 0xD6A8, 0xC8C0, 0xD6AC, 0xC8C1, 0xD6B0, 0xC8C2, 0xD6B9, 0xC8C3, 0xD6BB, 0xC8C4, 0xD6C4, 0xC8C5, 0xD6C5, 0xC8C6, 0xD6C8, + 0xC8C7, 0xD6CC, 0xC8C8, 0xD6D1, 0xC8C9, 0xD6D4, 0xC8CA, 0xD6D7, 0xC8CB, 0xD6D9, 0xC8CC, 0xD6E0, 0xC8CD, 0xD6E4, 0xC8CE, 0xD6E8, + 0xC8CF, 0xD6F0, 0xC8D0, 0xD6F5, 0xC8D1, 0xD6FC, 0xC8D2, 0xD6FD, 0xC8D3, 0xD700, 0xC8D4, 0xD704, 0xC8D5, 0xD711, 0xC8D6, 0xD718, + 0xC8D7, 0xD719, 0xC8D8, 0xD71C, 0xC8D9, 0xD720, 0xC8DA, 0xD728, 0xC8DB, 0xD729, 0xC8DC, 0xD72B, 0xC8DD, 0xD72D, 0xC8DE, 0xD734, + 0xC8DF, 0xD735, 0xC8E0, 0xD738, 0xC8E1, 0xD73C, 0xC8E2, 0xD744, 0xC8E3, 0xD747, 0xC8E4, 0xD749, 0xC8E5, 0xD750, 0xC8E6, 0xD751, + 0xC8E7, 0xD754, 0xC8E8, 0xD756, 0xC8E9, 0xD757, 0xC8EA, 0xD758, 0xC8EB, 0xD759, 0xC8EC, 0xD760, 0xC8ED, 0xD761, 0xC8EE, 0xD763, + 0xC8EF, 0xD765, 0xC8F0, 0xD769, 0xC8F1, 0xD76C, 0xC8F2, 0xD770, 0xC8F3, 0xD774, 0xC8F4, 0xD77C, 0xC8F5, 0xD77D, 0xC8F6, 0xD781, + 0xC8F7, 0xD788, 0xC8F8, 0xD789, 0xC8F9, 0xD78C, 0xC8FA, 0xD790, 0xC8FB, 0xD798, 0xC8FC, 0xD799, 0xC8FD, 0xD79B, 0xC8FE, 0xD79D, + 0xCAA1, 0x4F3D, 0xCAA2, 0x4F73, 0xCAA3, 0x5047, 0xCAA4, 0x50F9, 0xCAA5, 0x52A0, 0xCAA6, 0x53EF, 0xCAA7, 0x5475, 0xCAA8, 0x54E5, + 0xCAA9, 0x5609, 0xCAAA, 0x5AC1, 0xCAAB, 0x5BB6, 0xCAAC, 0x6687, 0xCAAD, 0x67B6, 0xCAAE, 0x67B7, 0xCAAF, 0x67EF, 0xCAB0, 0x6B4C, + 0xCAB1, 0x73C2, 0xCAB2, 0x75C2, 0xCAB3, 0x7A3C, 0xCAB4, 0x82DB, 0xCAB5, 0x8304, 0xCAB6, 0x8857, 0xCAB7, 0x8888, 0xCAB8, 0x8A36, + 0xCAB9, 0x8CC8, 0xCABA, 0x8DCF, 0xCABB, 0x8EFB, 0xCABC, 0x8FE6, 0xCABD, 0x99D5, 0xCABE, 0x523B, 0xCABF, 0x5374, 0xCAC0, 0x5404, + 0xCAC1, 0x606A, 0xCAC2, 0x6164, 0xCAC3, 0x6BBC, 0xCAC4, 0x73CF, 0xCAC5, 0x811A, 0xCAC6, 0x89BA, 0xCAC7, 0x89D2, 0xCAC8, 0x95A3, + 0xCAC9, 0x4F83, 0xCACA, 0x520A, 0xCACB, 0x58BE, 0xCACC, 0x5978, 0xCACD, 0x59E6, 0xCACE, 0x5E72, 0xCACF, 0x5E79, 0xCAD0, 0x61C7, + 0xCAD1, 0x63C0, 0xCAD2, 0x6746, 0xCAD3, 0x67EC, 0xCAD4, 0x687F, 0xCAD5, 0x6F97, 0xCAD6, 0x764E, 0xCAD7, 0x770B, 0xCAD8, 0x78F5, + 0xCAD9, 0x7A08, 0xCADA, 0x7AFF, 0xCADB, 0x7C21, 0xCADC, 0x809D, 0xCADD, 0x826E, 0xCADE, 0x8271, 0xCADF, 0x8AEB, 0xCAE0, 0x9593, + 0xCAE1, 0x4E6B, 0xCAE2, 0x559D, 0xCAE3, 0x66F7, 0xCAE4, 0x6E34, 0xCAE5, 0x78A3, 0xCAE6, 0x7AED, 0xCAE7, 0x845B, 0xCAE8, 0x8910, + 0xCAE9, 0x874E, 0xCAEA, 0x97A8, 0xCAEB, 0x52D8, 0xCAEC, 0x574E, 0xCAED, 0x582A, 0xCAEE, 0x5D4C, 0xCAEF, 0x611F, 0xCAF0, 0x61BE, + 0xCAF1, 0x6221, 0xCAF2, 0x6562, 0xCAF3, 0x67D1, 0xCAF4, 0x6A44, 0xCAF5, 0x6E1B, 0xCAF6, 0x7518, 0xCAF7, 0x75B3, 0xCAF8, 0x76E3, + 0xCAF9, 0x77B0, 0xCAFA, 0x7D3A, 0xCAFB, 0x90AF, 0xCAFC, 0x9451, 0xCAFD, 0x9452, 0xCAFE, 0x9F95, 0xCBA1, 0x5323, 0xCBA2, 0x5CAC, + 0xCBA3, 0x7532, 0xCBA4, 0x80DB, 0xCBA5, 0x9240, 0xCBA6, 0x9598, 0xCBA7, 0x525B, 0xCBA8, 0x5808, 0xCBA9, 0x59DC, 0xCBAA, 0x5CA1, + 0xCBAB, 0x5D17, 0xCBAC, 0x5EB7, 0xCBAD, 0x5F3A, 0xCBAE, 0x5F4A, 0xCBAF, 0x6177, 0xCBB0, 0x6C5F, 0xCBB1, 0x757A, 0xCBB2, 0x7586, + 0xCBB3, 0x7CE0, 0xCBB4, 0x7D73, 0xCBB5, 0x7DB1, 0xCBB6, 0x7F8C, 0xCBB7, 0x8154, 0xCBB8, 0x8221, 0xCBB9, 0x8591, 0xCBBA, 0x8941, + 0xCBBB, 0x8B1B, 0xCBBC, 0x92FC, 0xCBBD, 0x964D, 0xCBBE, 0x9C47, 0xCBBF, 0x4ECB, 0xCBC0, 0x4EF7, 0xCBC1, 0x500B, 0xCBC2, 0x51F1, + 0xCBC3, 0x584F, 0xCBC4, 0x6137, 0xCBC5, 0x613E, 0xCBC6, 0x6168, 0xCBC7, 0x6539, 0xCBC8, 0x69EA, 0xCBC9, 0x6F11, 0xCBCA, 0x75A5, + 0xCBCB, 0x7686, 0xCBCC, 0x76D6, 0xCBCD, 0x7B87, 0xCBCE, 0x82A5, 0xCBCF, 0x84CB, 0xCBD0, 0xF900, 0xCBD1, 0x93A7, 0xCBD2, 0x958B, + 0xCBD3, 0x5580, 0xCBD4, 0x5BA2, 0xCBD5, 0x5751, 0xCBD6, 0xF901, 0xCBD7, 0x7CB3, 0xCBD8, 0x7FB9, 0xCBD9, 0x91B5, 0xCBDA, 0x5028, + 0xCBDB, 0x53BB, 0xCBDC, 0x5C45, 0xCBDD, 0x5DE8, 0xCBDE, 0x62D2, 0xCBDF, 0x636E, 0xCBE0, 0x64DA, 0xCBE1, 0x64E7, 0xCBE2, 0x6E20, + 0xCBE3, 0x70AC, 0xCBE4, 0x795B, 0xCBE5, 0x8DDD, 0xCBE6, 0x8E1E, 0xCBE7, 0xF902, 0xCBE8, 0x907D, 0xCBE9, 0x9245, 0xCBEA, 0x92F8, + 0xCBEB, 0x4E7E, 0xCBEC, 0x4EF6, 0xCBED, 0x5065, 0xCBEE, 0x5DFE, 0xCBEF, 0x5EFA, 0xCBF0, 0x6106, 0xCBF1, 0x6957, 0xCBF2, 0x8171, + 0xCBF3, 0x8654, 0xCBF4, 0x8E47, 0xCBF5, 0x9375, 0xCBF6, 0x9A2B, 0xCBF7, 0x4E5E, 0xCBF8, 0x5091, 0xCBF9, 0x6770, 0xCBFA, 0x6840, + 0xCBFB, 0x5109, 0xCBFC, 0x528D, 0xCBFD, 0x5292, 0xCBFE, 0x6AA2, 0xCCA1, 0x77BC, 0xCCA2, 0x9210, 0xCCA3, 0x9ED4, 0xCCA4, 0x52AB, + 0xCCA5, 0x602F, 0xCCA6, 0x8FF2, 0xCCA7, 0x5048, 0xCCA8, 0x61A9, 0xCCA9, 0x63ED, 0xCCAA, 0x64CA, 0xCCAB, 0x683C, 0xCCAC, 0x6A84, + 0xCCAD, 0x6FC0, 0xCCAE, 0x8188, 0xCCAF, 0x89A1, 0xCCB0, 0x9694, 0xCCB1, 0x5805, 0xCCB2, 0x727D, 0xCCB3, 0x72AC, 0xCCB4, 0x7504, + 0xCCB5, 0x7D79, 0xCCB6, 0x7E6D, 0xCCB7, 0x80A9, 0xCCB8, 0x898B, 0xCCB9, 0x8B74, 0xCCBA, 0x9063, 0xCCBB, 0x9D51, 0xCCBC, 0x6289, + 0xCCBD, 0x6C7A, 0xCCBE, 0x6F54, 0xCCBF, 0x7D50, 0xCCC0, 0x7F3A, 0xCCC1, 0x8A23, 0xCCC2, 0x517C, 0xCCC3, 0x614A, 0xCCC4, 0x7B9D, + 0xCCC5, 0x8B19, 0xCCC6, 0x9257, 0xCCC7, 0x938C, 0xCCC8, 0x4EAC, 0xCCC9, 0x4FD3, 0xCCCA, 0x501E, 0xCCCB, 0x50BE, 0xCCCC, 0x5106, + 0xCCCD, 0x52C1, 0xCCCE, 0x52CD, 0xCCCF, 0x537F, 0xCCD0, 0x5770, 0xCCD1, 0x5883, 0xCCD2, 0x5E9A, 0xCCD3, 0x5F91, 0xCCD4, 0x6176, + 0xCCD5, 0x61AC, 0xCCD6, 0x64CE, 0xCCD7, 0x656C, 0xCCD8, 0x666F, 0xCCD9, 0x66BB, 0xCCDA, 0x66F4, 0xCCDB, 0x6897, 0xCCDC, 0x6D87, + 0xCCDD, 0x7085, 0xCCDE, 0x70F1, 0xCCDF, 0x749F, 0xCCE0, 0x74A5, 0xCCE1, 0x74CA, 0xCCE2, 0x75D9, 0xCCE3, 0x786C, 0xCCE4, 0x78EC, + 0xCCE5, 0x7ADF, 0xCCE6, 0x7AF6, 0xCCE7, 0x7D45, 0xCCE8, 0x7D93, 0xCCE9, 0x8015, 0xCCEA, 0x803F, 0xCCEB, 0x811B, 0xCCEC, 0x8396, + 0xCCED, 0x8B66, 0xCCEE, 0x8F15, 0xCCEF, 0x9015, 0xCCF0, 0x93E1, 0xCCF1, 0x9803, 0xCCF2, 0x9838, 0xCCF3, 0x9A5A, 0xCCF4, 0x9BE8, + 0xCCF5, 0x4FC2, 0xCCF6, 0x5553, 0xCCF7, 0x583A, 0xCCF8, 0x5951, 0xCCF9, 0x5B63, 0xCCFA, 0x5C46, 0xCCFB, 0x60B8, 0xCCFC, 0x6212, + 0xCCFD, 0x6842, 0xCCFE, 0x68B0, 0xCDA1, 0x68E8, 0xCDA2, 0x6EAA, 0xCDA3, 0x754C, 0xCDA4, 0x7678, 0xCDA5, 0x78CE, 0xCDA6, 0x7A3D, + 0xCDA7, 0x7CFB, 0xCDA8, 0x7E6B, 0xCDA9, 0x7E7C, 0xCDAA, 0x8A08, 0xCDAB, 0x8AA1, 0xCDAC, 0x8C3F, 0xCDAD, 0x968E, 0xCDAE, 0x9DC4, + 0xCDAF, 0x53E4, 0xCDB0, 0x53E9, 0xCDB1, 0x544A, 0xCDB2, 0x5471, 0xCDB3, 0x56FA, 0xCDB4, 0x59D1, 0xCDB5, 0x5B64, 0xCDB6, 0x5C3B, + 0xCDB7, 0x5EAB, 0xCDB8, 0x62F7, 0xCDB9, 0x6537, 0xCDBA, 0x6545, 0xCDBB, 0x6572, 0xCDBC, 0x66A0, 0xCDBD, 0x67AF, 0xCDBE, 0x69C1, + 0xCDBF, 0x6CBD, 0xCDC0, 0x75FC, 0xCDC1, 0x7690, 0xCDC2, 0x777E, 0xCDC3, 0x7A3F, 0xCDC4, 0x7F94, 0xCDC5, 0x8003, 0xCDC6, 0x80A1, + 0xCDC7, 0x818F, 0xCDC8, 0x82E6, 0xCDC9, 0x82FD, 0xCDCA, 0x83F0, 0xCDCB, 0x85C1, 0xCDCC, 0x8831, 0xCDCD, 0x88B4, 0xCDCE, 0x8AA5, + 0xCDCF, 0xF903, 0xCDD0, 0x8F9C, 0xCDD1, 0x932E, 0xCDD2, 0x96C7, 0xCDD3, 0x9867, 0xCDD4, 0x9AD8, 0xCDD5, 0x9F13, 0xCDD6, 0x54ED, + 0xCDD7, 0x659B, 0xCDD8, 0x66F2, 0xCDD9, 0x688F, 0xCDDA, 0x7A40, 0xCDDB, 0x8C37, 0xCDDC, 0x9D60, 0xCDDD, 0x56F0, 0xCDDE, 0x5764, + 0xCDDF, 0x5D11, 0xCDE0, 0x6606, 0xCDE1, 0x68B1, 0xCDE2, 0x68CD, 0xCDE3, 0x6EFE, 0xCDE4, 0x7428, 0xCDE5, 0x889E, 0xCDE6, 0x9BE4, + 0xCDE7, 0x6C68, 0xCDE8, 0xF904, 0xCDE9, 0x9AA8, 0xCDEA, 0x4F9B, 0xCDEB, 0x516C, 0xCDEC, 0x5171, 0xCDED, 0x529F, 0xCDEE, 0x5B54, + 0xCDEF, 0x5DE5, 0xCDF0, 0x6050, 0xCDF1, 0x606D, 0xCDF2, 0x62F1, 0xCDF3, 0x63A7, 0xCDF4, 0x653B, 0xCDF5, 0x73D9, 0xCDF6, 0x7A7A, + 0xCDF7, 0x86A3, 0xCDF8, 0x8CA2, 0xCDF9, 0x978F, 0xCDFA, 0x4E32, 0xCDFB, 0x5BE1, 0xCDFC, 0x6208, 0xCDFD, 0x679C, 0xCDFE, 0x74DC, + 0xCEA1, 0x79D1, 0xCEA2, 0x83D3, 0xCEA3, 0x8A87, 0xCEA4, 0x8AB2, 0xCEA5, 0x8DE8, 0xCEA6, 0x904E, 0xCEA7, 0x934B, 0xCEA8, 0x9846, + 0xCEA9, 0x5ED3, 0xCEAA, 0x69E8, 0xCEAB, 0x85FF, 0xCEAC, 0x90ED, 0xCEAD, 0xF905, 0xCEAE, 0x51A0, 0xCEAF, 0x5B98, 0xCEB0, 0x5BEC, + 0xCEB1, 0x6163, 0xCEB2, 0x68FA, 0xCEB3, 0x6B3E, 0xCEB4, 0x704C, 0xCEB5, 0x742F, 0xCEB6, 0x74D8, 0xCEB7, 0x7BA1, 0xCEB8, 0x7F50, + 0xCEB9, 0x83C5, 0xCEBA, 0x89C0, 0xCEBB, 0x8CAB, 0xCEBC, 0x95DC, 0xCEBD, 0x9928, 0xCEBE, 0x522E, 0xCEBF, 0x605D, 0xCEC0, 0x62EC, + 0xCEC1, 0x9002, 0xCEC2, 0x4F8A, 0xCEC3, 0x5149, 0xCEC4, 0x5321, 0xCEC5, 0x58D9, 0xCEC6, 0x5EE3, 0xCEC7, 0x66E0, 0xCEC8, 0x6D38, + 0xCEC9, 0x709A, 0xCECA, 0x72C2, 0xCECB, 0x73D6, 0xCECC, 0x7B50, 0xCECD, 0x80F1, 0xCECE, 0x945B, 0xCECF, 0x5366, 0xCED0, 0x639B, + 0xCED1, 0x7F6B, 0xCED2, 0x4E56, 0xCED3, 0x5080, 0xCED4, 0x584A, 0xCED5, 0x58DE, 0xCED6, 0x602A, 0xCED7, 0x6127, 0xCED8, 0x62D0, + 0xCED9, 0x69D0, 0xCEDA, 0x9B41, 0xCEDB, 0x5B8F, 0xCEDC, 0x7D18, 0xCEDD, 0x80B1, 0xCEDE, 0x8F5F, 0xCEDF, 0x4EA4, 0xCEE0, 0x50D1, + 0xCEE1, 0x54AC, 0xCEE2, 0x55AC, 0xCEE3, 0x5B0C, 0xCEE4, 0x5DA0, 0xCEE5, 0x5DE7, 0xCEE6, 0x652A, 0xCEE7, 0x654E, 0xCEE8, 0x6821, + 0xCEE9, 0x6A4B, 0xCEEA, 0x72E1, 0xCEEB, 0x768E, 0xCEEC, 0x77EF, 0xCEED, 0x7D5E, 0xCEEE, 0x7FF9, 0xCEEF, 0x81A0, 0xCEF0, 0x854E, + 0xCEF1, 0x86DF, 0xCEF2, 0x8F03, 0xCEF3, 0x8F4E, 0xCEF4, 0x90CA, 0xCEF5, 0x9903, 0xCEF6, 0x9A55, 0xCEF7, 0x9BAB, 0xCEF8, 0x4E18, + 0xCEF9, 0x4E45, 0xCEFA, 0x4E5D, 0xCEFB, 0x4EC7, 0xCEFC, 0x4FF1, 0xCEFD, 0x5177, 0xCEFE, 0x52FE, 0xCFA1, 0x5340, 0xCFA2, 0x53E3, + 0xCFA3, 0x53E5, 0xCFA4, 0x548E, 0xCFA5, 0x5614, 0xCFA6, 0x5775, 0xCFA7, 0x57A2, 0xCFA8, 0x5BC7, 0xCFA9, 0x5D87, 0xCFAA, 0x5ED0, + 0xCFAB, 0x61FC, 0xCFAC, 0x62D8, 0xCFAD, 0x6551, 0xCFAE, 0x67B8, 0xCFAF, 0x67E9, 0xCFB0, 0x69CB, 0xCFB1, 0x6B50, 0xCFB2, 0x6BC6, + 0xCFB3, 0x6BEC, 0xCFB4, 0x6C42, 0xCFB5, 0x6E9D, 0xCFB6, 0x7078, 0xCFB7, 0x72D7, 0xCFB8, 0x7396, 0xCFB9, 0x7403, 0xCFBA, 0x77BF, + 0xCFBB, 0x77E9, 0xCFBC, 0x7A76, 0xCFBD, 0x7D7F, 0xCFBE, 0x8009, 0xCFBF, 0x81FC, 0xCFC0, 0x8205, 0xCFC1, 0x820A, 0xCFC2, 0x82DF, + 0xCFC3, 0x8862, 0xCFC4, 0x8B33, 0xCFC5, 0x8CFC, 0xCFC6, 0x8EC0, 0xCFC7, 0x9011, 0xCFC8, 0x90B1, 0xCFC9, 0x9264, 0xCFCA, 0x92B6, + 0xCFCB, 0x99D2, 0xCFCC, 0x9A45, 0xCFCD, 0x9CE9, 0xCFCE, 0x9DD7, 0xCFCF, 0x9F9C, 0xCFD0, 0x570B, 0xCFD1, 0x5C40, 0xCFD2, 0x83CA, + 0xCFD3, 0x97A0, 0xCFD4, 0x97AB, 0xCFD5, 0x9EB4, 0xCFD6, 0x541B, 0xCFD7, 0x7A98, 0xCFD8, 0x7FA4, 0xCFD9, 0x88D9, 0xCFDA, 0x8ECD, + 0xCFDB, 0x90E1, 0xCFDC, 0x5800, 0xCFDD, 0x5C48, 0xCFDE, 0x6398, 0xCFDF, 0x7A9F, 0xCFE0, 0x5BAE, 0xCFE1, 0x5F13, 0xCFE2, 0x7A79, + 0xCFE3, 0x7AAE, 0xCFE4, 0x828E, 0xCFE5, 0x8EAC, 0xCFE6, 0x5026, 0xCFE7, 0x5238, 0xCFE8, 0x52F8, 0xCFE9, 0x5377, 0xCFEA, 0x5708, + 0xCFEB, 0x62F3, 0xCFEC, 0x6372, 0xCFED, 0x6B0A, 0xCFEE, 0x6DC3, 0xCFEF, 0x7737, 0xCFF0, 0x53A5, 0xCFF1, 0x7357, 0xCFF2, 0x8568, + 0xCFF3, 0x8E76, 0xCFF4, 0x95D5, 0xCFF5, 0x673A, 0xCFF6, 0x6AC3, 0xCFF7, 0x6F70, 0xCFF8, 0x8A6D, 0xCFF9, 0x8ECC, 0xCFFA, 0x994B, + 0xCFFB, 0xF906, 0xCFFC, 0x6677, 0xCFFD, 0x6B78, 0xCFFE, 0x8CB4, 0xD0A1, 0x9B3C, 0xD0A2, 0xF907, 0xD0A3, 0x53EB, 0xD0A4, 0x572D, + 0xD0A5, 0x594E, 0xD0A6, 0x63C6, 0xD0A7, 0x69FB, 0xD0A8, 0x73EA, 0xD0A9, 0x7845, 0xD0AA, 0x7ABA, 0xD0AB, 0x7AC5, 0xD0AC, 0x7CFE, + 0xD0AD, 0x8475, 0xD0AE, 0x898F, 0xD0AF, 0x8D73, 0xD0B0, 0x9035, 0xD0B1, 0x95A8, 0xD0B2, 0x52FB, 0xD0B3, 0x5747, 0xD0B4, 0x7547, + 0xD0B5, 0x7B60, 0xD0B6, 0x83CC, 0xD0B7, 0x921E, 0xD0B8, 0xF908, 0xD0B9, 0x6A58, 0xD0BA, 0x514B, 0xD0BB, 0x524B, 0xD0BC, 0x5287, + 0xD0BD, 0x621F, 0xD0BE, 0x68D8, 0xD0BF, 0x6975, 0xD0C0, 0x9699, 0xD0C1, 0x50C5, 0xD0C2, 0x52A4, 0xD0C3, 0x52E4, 0xD0C4, 0x61C3, + 0xD0C5, 0x65A4, 0xD0C6, 0x6839, 0xD0C7, 0x69FF, 0xD0C8, 0x747E, 0xD0C9, 0x7B4B, 0xD0CA, 0x82B9, 0xD0CB, 0x83EB, 0xD0CC, 0x89B2, + 0xD0CD, 0x8B39, 0xD0CE, 0x8FD1, 0xD0CF, 0x9949, 0xD0D0, 0xF909, 0xD0D1, 0x4ECA, 0xD0D2, 0x5997, 0xD0D3, 0x64D2, 0xD0D4, 0x6611, + 0xD0D5, 0x6A8E, 0xD0D6, 0x7434, 0xD0D7, 0x7981, 0xD0D8, 0x79BD, 0xD0D9, 0x82A9, 0xD0DA, 0x887E, 0xD0DB, 0x887F, 0xD0DC, 0x895F, + 0xD0DD, 0xF90A, 0xD0DE, 0x9326, 0xD0DF, 0x4F0B, 0xD0E0, 0x53CA, 0xD0E1, 0x6025, 0xD0E2, 0x6271, 0xD0E3, 0x6C72, 0xD0E4, 0x7D1A, + 0xD0E5, 0x7D66, 0xD0E6, 0x4E98, 0xD0E7, 0x5162, 0xD0E8, 0x77DC, 0xD0E9, 0x80AF, 0xD0EA, 0x4F01, 0xD0EB, 0x4F0E, 0xD0EC, 0x5176, + 0xD0ED, 0x5180, 0xD0EE, 0x55DC, 0xD0EF, 0x5668, 0xD0F0, 0x573B, 0xD0F1, 0x57FA, 0xD0F2, 0x57FC, 0xD0F3, 0x5914, 0xD0F4, 0x5947, + 0xD0F5, 0x5993, 0xD0F6, 0x5BC4, 0xD0F7, 0x5C90, 0xD0F8, 0x5D0E, 0xD0F9, 0x5DF1, 0xD0FA, 0x5E7E, 0xD0FB, 0x5FCC, 0xD0FC, 0x6280, + 0xD0FD, 0x65D7, 0xD0FE, 0x65E3, 0xD1A1, 0x671E, 0xD1A2, 0x671F, 0xD1A3, 0x675E, 0xD1A4, 0x68CB, 0xD1A5, 0x68C4, 0xD1A6, 0x6A5F, + 0xD1A7, 0x6B3A, 0xD1A8, 0x6C23, 0xD1A9, 0x6C7D, 0xD1AA, 0x6C82, 0xD1AB, 0x6DC7, 0xD1AC, 0x7398, 0xD1AD, 0x7426, 0xD1AE, 0x742A, + 0xD1AF, 0x7482, 0xD1B0, 0x74A3, 0xD1B1, 0x7578, 0xD1B2, 0x757F, 0xD1B3, 0x7881, 0xD1B4, 0x78EF, 0xD1B5, 0x7941, 0xD1B6, 0x7947, + 0xD1B7, 0x7948, 0xD1B8, 0x797A, 0xD1B9, 0x7B95, 0xD1BA, 0x7D00, 0xD1BB, 0x7DBA, 0xD1BC, 0x7F88, 0xD1BD, 0x8006, 0xD1BE, 0x802D, + 0xD1BF, 0x808C, 0xD1C0, 0x8A18, 0xD1C1, 0x8B4F, 0xD1C2, 0x8C48, 0xD1C3, 0x8D77, 0xD1C4, 0x9321, 0xD1C5, 0x9324, 0xD1C6, 0x98E2, + 0xD1C7, 0x9951, 0xD1C8, 0x9A0E, 0xD1C9, 0x9A0F, 0xD1CA, 0x9A65, 0xD1CB, 0x9E92, 0xD1CC, 0x7DCA, 0xD1CD, 0x4F76, 0xD1CE, 0x5409, + 0xD1CF, 0x62EE, 0xD1D0, 0x6854, 0xD1D1, 0x91D1, 0xD1D2, 0x55AB, 0xD1D3, 0x513A, 0xD1D4, 0xF90B, 0xD1D5, 0xF90C, 0xD1D6, 0x5A1C, + 0xD1D7, 0x61E6, 0xD1D8, 0xF90D, 0xD1D9, 0x62CF, 0xD1DA, 0x62FF, 0xD1DB, 0xF90E, 0xD1DC, 0xF90F, 0xD1DD, 0xF910, 0xD1DE, 0xF911, + 0xD1DF, 0xF912, 0xD1E0, 0xF913, 0xD1E1, 0x90A3, 0xD1E2, 0xF914, 0xD1E3, 0xF915, 0xD1E4, 0xF916, 0xD1E5, 0xF917, 0xD1E6, 0xF918, + 0xD1E7, 0x8AFE, 0xD1E8, 0xF919, 0xD1E9, 0xF91A, 0xD1EA, 0xF91B, 0xD1EB, 0xF91C, 0xD1EC, 0x6696, 0xD1ED, 0xF91D, 0xD1EE, 0x7156, + 0xD1EF, 0xF91E, 0xD1F0, 0xF91F, 0xD1F1, 0x96E3, 0xD1F2, 0xF920, 0xD1F3, 0x634F, 0xD1F4, 0x637A, 0xD1F5, 0x5357, 0xD1F6, 0xF921, + 0xD1F7, 0x678F, 0xD1F8, 0x6960, 0xD1F9, 0x6E73, 0xD1FA, 0xF922, 0xD1FB, 0x7537, 0xD1FC, 0xF923, 0xD1FD, 0xF924, 0xD1FE, 0xF925, + 0xD2A1, 0x7D0D, 0xD2A2, 0xF926, 0xD2A3, 0xF927, 0xD2A4, 0x8872, 0xD2A5, 0x56CA, 0xD2A6, 0x5A18, 0xD2A7, 0xF928, 0xD2A8, 0xF929, + 0xD2A9, 0xF92A, 0xD2AA, 0xF92B, 0xD2AB, 0xF92C, 0xD2AC, 0x4E43, 0xD2AD, 0xF92D, 0xD2AE, 0x5167, 0xD2AF, 0x5948, 0xD2B0, 0x67F0, + 0xD2B1, 0x8010, 0xD2B2, 0xF92E, 0xD2B3, 0x5973, 0xD2B4, 0x5E74, 0xD2B5, 0x649A, 0xD2B6, 0x79CA, 0xD2B7, 0x5FF5, 0xD2B8, 0x606C, + 0xD2B9, 0x62C8, 0xD2BA, 0x637B, 0xD2BB, 0x5BE7, 0xD2BC, 0x5BD7, 0xD2BD, 0x52AA, 0xD2BE, 0xF92F, 0xD2BF, 0x5974, 0xD2C0, 0x5F29, + 0xD2C1, 0x6012, 0xD2C2, 0xF930, 0xD2C3, 0xF931, 0xD2C4, 0xF932, 0xD2C5, 0x7459, 0xD2C6, 0xF933, 0xD2C7, 0xF934, 0xD2C8, 0xF935, + 0xD2C9, 0xF936, 0xD2CA, 0xF937, 0xD2CB, 0xF938, 0xD2CC, 0x99D1, 0xD2CD, 0xF939, 0xD2CE, 0xF93A, 0xD2CF, 0xF93B, 0xD2D0, 0xF93C, + 0xD2D1, 0xF93D, 0xD2D2, 0xF93E, 0xD2D3, 0xF93F, 0xD2D4, 0xF940, 0xD2D5, 0xF941, 0xD2D6, 0xF942, 0xD2D7, 0xF943, 0xD2D8, 0x6FC3, + 0xD2D9, 0xF944, 0xD2DA, 0xF945, 0xD2DB, 0x81BF, 0xD2DC, 0x8FB2, 0xD2DD, 0x60F1, 0xD2DE, 0xF946, 0xD2DF, 0xF947, 0xD2E0, 0x8166, + 0xD2E1, 0xF948, 0xD2E2, 0xF949, 0xD2E3, 0x5C3F, 0xD2E4, 0xF94A, 0xD2E5, 0xF94B, 0xD2E6, 0xF94C, 0xD2E7, 0xF94D, 0xD2E8, 0xF94E, + 0xD2E9, 0xF94F, 0xD2EA, 0xF950, 0xD2EB, 0xF951, 0xD2EC, 0x5AE9, 0xD2ED, 0x8A25, 0xD2EE, 0x677B, 0xD2EF, 0x7D10, 0xD2F0, 0xF952, + 0xD2F1, 0xF953, 0xD2F2, 0xF954, 0xD2F3, 0xF955, 0xD2F4, 0xF956, 0xD2F5, 0xF957, 0xD2F6, 0x80FD, 0xD2F7, 0xF958, 0xD2F8, 0xF959, + 0xD2F9, 0x5C3C, 0xD2FA, 0x6CE5, 0xD2FB, 0x533F, 0xD2FC, 0x6EBA, 0xD2FD, 0x591A, 0xD2FE, 0x8336, 0xD3A1, 0x4E39, 0xD3A2, 0x4EB6, + 0xD3A3, 0x4F46, 0xD3A4, 0x55AE, 0xD3A5, 0x5718, 0xD3A6, 0x58C7, 0xD3A7, 0x5F56, 0xD3A8, 0x65B7, 0xD3A9, 0x65E6, 0xD3AA, 0x6A80, + 0xD3AB, 0x6BB5, 0xD3AC, 0x6E4D, 0xD3AD, 0x77ED, 0xD3AE, 0x7AEF, 0xD3AF, 0x7C1E, 0xD3B0, 0x7DDE, 0xD3B1, 0x86CB, 0xD3B2, 0x8892, + 0xD3B3, 0x9132, 0xD3B4, 0x935B, 0xD3B5, 0x64BB, 0xD3B6, 0x6FBE, 0xD3B7, 0x737A, 0xD3B8, 0x75B8, 0xD3B9, 0x9054, 0xD3BA, 0x5556, + 0xD3BB, 0x574D, 0xD3BC, 0x61BA, 0xD3BD, 0x64D4, 0xD3BE, 0x66C7, 0xD3BF, 0x6DE1, 0xD3C0, 0x6E5B, 0xD3C1, 0x6F6D, 0xD3C2, 0x6FB9, + 0xD3C3, 0x75F0, 0xD3C4, 0x8043, 0xD3C5, 0x81BD, 0xD3C6, 0x8541, 0xD3C7, 0x8983, 0xD3C8, 0x8AC7, 0xD3C9, 0x8B5A, 0xD3CA, 0x931F, + 0xD3CB, 0x6C93, 0xD3CC, 0x7553, 0xD3CD, 0x7B54, 0xD3CE, 0x8E0F, 0xD3CF, 0x905D, 0xD3D0, 0x5510, 0xD3D1, 0x5802, 0xD3D2, 0x5858, + 0xD3D3, 0x5E62, 0xD3D4, 0x6207, 0xD3D5, 0x649E, 0xD3D6, 0x68E0, 0xD3D7, 0x7576, 0xD3D8, 0x7CD6, 0xD3D9, 0x87B3, 0xD3DA, 0x9EE8, + 0xD3DB, 0x4EE3, 0xD3DC, 0x5788, 0xD3DD, 0x576E, 0xD3DE, 0x5927, 0xD3DF, 0x5C0D, 0xD3E0, 0x5CB1, 0xD3E1, 0x5E36, 0xD3E2, 0x5F85, + 0xD3E3, 0x6234, 0xD3E4, 0x64E1, 0xD3E5, 0x73B3, 0xD3E6, 0x81FA, 0xD3E7, 0x888B, 0xD3E8, 0x8CB8, 0xD3E9, 0x968A, 0xD3EA, 0x9EDB, + 0xD3EB, 0x5B85, 0xD3EC, 0x5FB7, 0xD3ED, 0x60B3, 0xD3EE, 0x5012, 0xD3EF, 0x5200, 0xD3F0, 0x5230, 0xD3F1, 0x5716, 0xD3F2, 0x5835, + 0xD3F3, 0x5857, 0xD3F4, 0x5C0E, 0xD3F5, 0x5C60, 0xD3F6, 0x5CF6, 0xD3F7, 0x5D8B, 0xD3F8, 0x5EA6, 0xD3F9, 0x5F92, 0xD3FA, 0x60BC, + 0xD3FB, 0x6311, 0xD3FC, 0x6389, 0xD3FD, 0x6417, 0xD3FE, 0x6843, 0xD4A1, 0x68F9, 0xD4A2, 0x6AC2, 0xD4A3, 0x6DD8, 0xD4A4, 0x6E21, + 0xD4A5, 0x6ED4, 0xD4A6, 0x6FE4, 0xD4A7, 0x71FE, 0xD4A8, 0x76DC, 0xD4A9, 0x7779, 0xD4AA, 0x79B1, 0xD4AB, 0x7A3B, 0xD4AC, 0x8404, + 0xD4AD, 0x89A9, 0xD4AE, 0x8CED, 0xD4AF, 0x8DF3, 0xD4B0, 0x8E48, 0xD4B1, 0x9003, 0xD4B2, 0x9014, 0xD4B3, 0x9053, 0xD4B4, 0x90FD, + 0xD4B5, 0x934D, 0xD4B6, 0x9676, 0xD4B7, 0x97DC, 0xD4B8, 0x6BD2, 0xD4B9, 0x7006, 0xD4BA, 0x7258, 0xD4BB, 0x72A2, 0xD4BC, 0x7368, + 0xD4BD, 0x7763, 0xD4BE, 0x79BF, 0xD4BF, 0x7BE4, 0xD4C0, 0x7E9B, 0xD4C1, 0x8B80, 0xD4C2, 0x58A9, 0xD4C3, 0x60C7, 0xD4C4, 0x6566, + 0xD4C5, 0x65FD, 0xD4C6, 0x66BE, 0xD4C7, 0x6C8C, 0xD4C8, 0x711E, 0xD4C9, 0x71C9, 0xD4CA, 0x8C5A, 0xD4CB, 0x9813, 0xD4CC, 0x4E6D, + 0xD4CD, 0x7A81, 0xD4CE, 0x4EDD, 0xD4CF, 0x51AC, 0xD4D0, 0x51CD, 0xD4D1, 0x52D5, 0xD4D2, 0x540C, 0xD4D3, 0x61A7, 0xD4D4, 0x6771, + 0xD4D5, 0x6850, 0xD4D6, 0x68DF, 0xD4D7, 0x6D1E, 0xD4D8, 0x6F7C, 0xD4D9, 0x75BC, 0xD4DA, 0x77B3, 0xD4DB, 0x7AE5, 0xD4DC, 0x80F4, + 0xD4DD, 0x8463, 0xD4DE, 0x9285, 0xD4DF, 0x515C, 0xD4E0, 0x6597, 0xD4E1, 0x675C, 0xD4E2, 0x6793, 0xD4E3, 0x75D8, 0xD4E4, 0x7AC7, + 0xD4E5, 0x8373, 0xD4E6, 0xF95A, 0xD4E7, 0x8C46, 0xD4E8, 0x9017, 0xD4E9, 0x982D, 0xD4EA, 0x5C6F, 0xD4EB, 0x81C0, 0xD4EC, 0x829A, + 0xD4ED, 0x9041, 0xD4EE, 0x906F, 0xD4EF, 0x920D, 0xD4F0, 0x5F97, 0xD4F1, 0x5D9D, 0xD4F2, 0x6A59, 0xD4F3, 0x71C8, 0xD4F4, 0x767B, + 0xD4F5, 0x7B49, 0xD4F6, 0x85E4, 0xD4F7, 0x8B04, 0xD4F8, 0x9127, 0xD4F9, 0x9A30, 0xD4FA, 0x5587, 0xD4FB, 0x61F6, 0xD4FC, 0xF95B, + 0xD4FD, 0x7669, 0xD4FE, 0x7F85, 0xD5A1, 0x863F, 0xD5A2, 0x87BA, 0xD5A3, 0x88F8, 0xD5A4, 0x908F, 0xD5A5, 0xF95C, 0xD5A6, 0x6D1B, + 0xD5A7, 0x70D9, 0xD5A8, 0x73DE, 0xD5A9, 0x7D61, 0xD5AA, 0x843D, 0xD5AB, 0xF95D, 0xD5AC, 0x916A, 0xD5AD, 0x99F1, 0xD5AE, 0xF95E, + 0xD5AF, 0x4E82, 0xD5B0, 0x5375, 0xD5B1, 0x6B04, 0xD5B2, 0x6B12, 0xD5B3, 0x703E, 0xD5B4, 0x721B, 0xD5B5, 0x862D, 0xD5B6, 0x9E1E, + 0xD5B7, 0x524C, 0xD5B8, 0x8FA3, 0xD5B9, 0x5D50, 0xD5BA, 0x64E5, 0xD5BB, 0x652C, 0xD5BC, 0x6B16, 0xD5BD, 0x6FEB, 0xD5BE, 0x7C43, + 0xD5BF, 0x7E9C, 0xD5C0, 0x85CD, 0xD5C1, 0x8964, 0xD5C2, 0x89BD, 0xD5C3, 0x62C9, 0xD5C4, 0x81D8, 0xD5C5, 0x881F, 0xD5C6, 0x5ECA, + 0xD5C7, 0x6717, 0xD5C8, 0x6D6A, 0xD5C9, 0x72FC, 0xD5CA, 0x7405, 0xD5CB, 0x746F, 0xD5CC, 0x8782, 0xD5CD, 0x90DE, 0xD5CE, 0x4F86, + 0xD5CF, 0x5D0D, 0xD5D0, 0x5FA0, 0xD5D1, 0x840A, 0xD5D2, 0x51B7, 0xD5D3, 0x63A0, 0xD5D4, 0x7565, 0xD5D5, 0x4EAE, 0xD5D6, 0x5006, + 0xD5D7, 0x5169, 0xD5D8, 0x51C9, 0xD5D9, 0x6881, 0xD5DA, 0x6A11, 0xD5DB, 0x7CAE, 0xD5DC, 0x7CB1, 0xD5DD, 0x7CE7, 0xD5DE, 0x826F, + 0xD5DF, 0x8AD2, 0xD5E0, 0x8F1B, 0xD5E1, 0x91CF, 0xD5E2, 0x4FB6, 0xD5E3, 0x5137, 0xD5E4, 0x52F5, 0xD5E5, 0x5442, 0xD5E6, 0x5EEC, + 0xD5E7, 0x616E, 0xD5E8, 0x623E, 0xD5E9, 0x65C5, 0xD5EA, 0x6ADA, 0xD5EB, 0x6FFE, 0xD5EC, 0x792A, 0xD5ED, 0x85DC, 0xD5EE, 0x8823, + 0xD5EF, 0x95AD, 0xD5F0, 0x9A62, 0xD5F1, 0x9A6A, 0xD5F2, 0x9E97, 0xD5F3, 0x9ECE, 0xD5F4, 0x529B, 0xD5F5, 0x66C6, 0xD5F6, 0x6B77, + 0xD5F7, 0x701D, 0xD5F8, 0x792B, 0xD5F9, 0x8F62, 0xD5FA, 0x9742, 0xD5FB, 0x6190, 0xD5FC, 0x6200, 0xD5FD, 0x6523, 0xD5FE, 0x6F23, + 0xD6A1, 0x7149, 0xD6A2, 0x7489, 0xD6A3, 0x7DF4, 0xD6A4, 0x806F, 0xD6A5, 0x84EE, 0xD6A6, 0x8F26, 0xD6A7, 0x9023, 0xD6A8, 0x934A, + 0xD6A9, 0x51BD, 0xD6AA, 0x5217, 0xD6AB, 0x52A3, 0xD6AC, 0x6D0C, 0xD6AD, 0x70C8, 0xD6AE, 0x88C2, 0xD6AF, 0x5EC9, 0xD6B0, 0x6582, + 0xD6B1, 0x6BAE, 0xD6B2, 0x6FC2, 0xD6B3, 0x7C3E, 0xD6B4, 0x7375, 0xD6B5, 0x4EE4, 0xD6B6, 0x4F36, 0xD6B7, 0x56F9, 0xD6B8, 0xF95F, + 0xD6B9, 0x5CBA, 0xD6BA, 0x5DBA, 0xD6BB, 0x601C, 0xD6BC, 0x73B2, 0xD6BD, 0x7B2D, 0xD6BE, 0x7F9A, 0xD6BF, 0x7FCE, 0xD6C0, 0x8046, + 0xD6C1, 0x901E, 0xD6C2, 0x9234, 0xD6C3, 0x96F6, 0xD6C4, 0x9748, 0xD6C5, 0x9818, 0xD6C6, 0x9F61, 0xD6C7, 0x4F8B, 0xD6C8, 0x6FA7, + 0xD6C9, 0x79AE, 0xD6CA, 0x91B4, 0xD6CB, 0x96B7, 0xD6CC, 0x52DE, 0xD6CD, 0xF960, 0xD6CE, 0x6488, 0xD6CF, 0x64C4, 0xD6D0, 0x6AD3, + 0xD6D1, 0x6F5E, 0xD6D2, 0x7018, 0xD6D3, 0x7210, 0xD6D4, 0x76E7, 0xD6D5, 0x8001, 0xD6D6, 0x8606, 0xD6D7, 0x865C, 0xD6D8, 0x8DEF, + 0xD6D9, 0x8F05, 0xD6DA, 0x9732, 0xD6DB, 0x9B6F, 0xD6DC, 0x9DFA, 0xD6DD, 0x9E75, 0xD6DE, 0x788C, 0xD6DF, 0x797F, 0xD6E0, 0x7DA0, + 0xD6E1, 0x83C9, 0xD6E2, 0x9304, 0xD6E3, 0x9E7F, 0xD6E4, 0x9E93, 0xD6E5, 0x8AD6, 0xD6E6, 0x58DF, 0xD6E7, 0x5F04, 0xD6E8, 0x6727, + 0xD6E9, 0x7027, 0xD6EA, 0x74CF, 0xD6EB, 0x7C60, 0xD6EC, 0x807E, 0xD6ED, 0x5121, 0xD6EE, 0x7028, 0xD6EF, 0x7262, 0xD6F0, 0x78CA, + 0xD6F1, 0x8CC2, 0xD6F2, 0x8CDA, 0xD6F3, 0x8CF4, 0xD6F4, 0x96F7, 0xD6F5, 0x4E86, 0xD6F6, 0x50DA, 0xD6F7, 0x5BEE, 0xD6F8, 0x5ED6, + 0xD6F9, 0x6599, 0xD6FA, 0x71CE, 0xD6FB, 0x7642, 0xD6FC, 0x77AD, 0xD6FD, 0x804A, 0xD6FE, 0x84FC, 0xD7A1, 0x907C, 0xD7A2, 0x9B27, + 0xD7A3, 0x9F8D, 0xD7A4, 0x58D8, 0xD7A5, 0x5A41, 0xD7A6, 0x5C62, 0xD7A7, 0x6A13, 0xD7A8, 0x6DDA, 0xD7A9, 0x6F0F, 0xD7AA, 0x763B, + 0xD7AB, 0x7D2F, 0xD7AC, 0x7E37, 0xD7AD, 0x851E, 0xD7AE, 0x8938, 0xD7AF, 0x93E4, 0xD7B0, 0x964B, 0xD7B1, 0x5289, 0xD7B2, 0x65D2, + 0xD7B3, 0x67F3, 0xD7B4, 0x69B4, 0xD7B5, 0x6D41, 0xD7B6, 0x6E9C, 0xD7B7, 0x700F, 0xD7B8, 0x7409, 0xD7B9, 0x7460, 0xD7BA, 0x7559, + 0xD7BB, 0x7624, 0xD7BC, 0x786B, 0xD7BD, 0x8B2C, 0xD7BE, 0x985E, 0xD7BF, 0x516D, 0xD7C0, 0x622E, 0xD7C1, 0x9678, 0xD7C2, 0x4F96, + 0xD7C3, 0x502B, 0xD7C4, 0x5D19, 0xD7C5, 0x6DEA, 0xD7C6, 0x7DB8, 0xD7C7, 0x8F2A, 0xD7C8, 0x5F8B, 0xD7C9, 0x6144, 0xD7CA, 0x6817, + 0xD7CB, 0xF961, 0xD7CC, 0x9686, 0xD7CD, 0x52D2, 0xD7CE, 0x808B, 0xD7CF, 0x51DC, 0xD7D0, 0x51CC, 0xD7D1, 0x695E, 0xD7D2, 0x7A1C, + 0xD7D3, 0x7DBE, 0xD7D4, 0x83F1, 0xD7D5, 0x9675, 0xD7D6, 0x4FDA, 0xD7D7, 0x5229, 0xD7D8, 0x5398, 0xD7D9, 0x540F, 0xD7DA, 0x550E, + 0xD7DB, 0x5C65, 0xD7DC, 0x60A7, 0xD7DD, 0x674E, 0xD7DE, 0x68A8, 0xD7DF, 0x6D6C, 0xD7E0, 0x7281, 0xD7E1, 0x72F8, 0xD7E2, 0x7406, + 0xD7E3, 0x7483, 0xD7E4, 0xF962, 0xD7E5, 0x75E2, 0xD7E6, 0x7C6C, 0xD7E7, 0x7F79, 0xD7E8, 0x7FB8, 0xD7E9, 0x8389, 0xD7EA, 0x88CF, + 0xD7EB, 0x88E1, 0xD7EC, 0x91CC, 0xD7ED, 0x91D0, 0xD7EE, 0x96E2, 0xD7EF, 0x9BC9, 0xD7F0, 0x541D, 0xD7F1, 0x6F7E, 0xD7F2, 0x71D0, + 0xD7F3, 0x7498, 0xD7F4, 0x85FA, 0xD7F5, 0x8EAA, 0xD7F6, 0x96A3, 0xD7F7, 0x9C57, 0xD7F8, 0x9E9F, 0xD7F9, 0x6797, 0xD7FA, 0x6DCB, + 0xD7FB, 0x7433, 0xD7FC, 0x81E8, 0xD7FD, 0x9716, 0xD7FE, 0x782C, 0xD8A1, 0x7ACB, 0xD8A2, 0x7B20, 0xD8A3, 0x7C92, 0xD8A4, 0x6469, + 0xD8A5, 0x746A, 0xD8A6, 0x75F2, 0xD8A7, 0x78BC, 0xD8A8, 0x78E8, 0xD8A9, 0x99AC, 0xD8AA, 0x9B54, 0xD8AB, 0x9EBB, 0xD8AC, 0x5BDE, + 0xD8AD, 0x5E55, 0xD8AE, 0x6F20, 0xD8AF, 0x819C, 0xD8B0, 0x83AB, 0xD8B1, 0x9088, 0xD8B2, 0x4E07, 0xD8B3, 0x534D, 0xD8B4, 0x5A29, + 0xD8B5, 0x5DD2, 0xD8B6, 0x5F4E, 0xD8B7, 0x6162, 0xD8B8, 0x633D, 0xD8B9, 0x6669, 0xD8BA, 0x66FC, 0xD8BB, 0x6EFF, 0xD8BC, 0x6F2B, + 0xD8BD, 0x7063, 0xD8BE, 0x779E, 0xD8BF, 0x842C, 0xD8C0, 0x8513, 0xD8C1, 0x883B, 0xD8C2, 0x8F13, 0xD8C3, 0x9945, 0xD8C4, 0x9C3B, + 0xD8C5, 0x551C, 0xD8C6, 0x62B9, 0xD8C7, 0x672B, 0xD8C8, 0x6CAB, 0xD8C9, 0x8309, 0xD8CA, 0x896A, 0xD8CB, 0x977A, 0xD8CC, 0x4EA1, + 0xD8CD, 0x5984, 0xD8CE, 0x5FD8, 0xD8CF, 0x5FD9, 0xD8D0, 0x671B, 0xD8D1, 0x7DB2, 0xD8D2, 0x7F54, 0xD8D3, 0x8292, 0xD8D4, 0x832B, + 0xD8D5, 0x83BD, 0xD8D6, 0x8F1E, 0xD8D7, 0x9099, 0xD8D8, 0x57CB, 0xD8D9, 0x59B9, 0xD8DA, 0x5A92, 0xD8DB, 0x5BD0, 0xD8DC, 0x6627, + 0xD8DD, 0x679A, 0xD8DE, 0x6885, 0xD8DF, 0x6BCF, 0xD8E0, 0x7164, 0xD8E1, 0x7F75, 0xD8E2, 0x8CB7, 0xD8E3, 0x8CE3, 0xD8E4, 0x9081, + 0xD8E5, 0x9B45, 0xD8E6, 0x8108, 0xD8E7, 0x8C8A, 0xD8E8, 0x964C, 0xD8E9, 0x9A40, 0xD8EA, 0x9EA5, 0xD8EB, 0x5B5F, 0xD8EC, 0x6C13, + 0xD8ED, 0x731B, 0xD8EE, 0x76F2, 0xD8EF, 0x76DF, 0xD8F0, 0x840C, 0xD8F1, 0x51AA, 0xD8F2, 0x8993, 0xD8F3, 0x514D, 0xD8F4, 0x5195, + 0xD8F5, 0x52C9, 0xD8F6, 0x68C9, 0xD8F7, 0x6C94, 0xD8F8, 0x7704, 0xD8F9, 0x7720, 0xD8FA, 0x7DBF, 0xD8FB, 0x7DEC, 0xD8FC, 0x9762, + 0xD8FD, 0x9EB5, 0xD8FE, 0x6EC5, 0xD9A1, 0x8511, 0xD9A2, 0x51A5, 0xD9A3, 0x540D, 0xD9A4, 0x547D, 0xD9A5, 0x660E, 0xD9A6, 0x669D, + 0xD9A7, 0x6927, 0xD9A8, 0x6E9F, 0xD9A9, 0x76BF, 0xD9AA, 0x7791, 0xD9AB, 0x8317, 0xD9AC, 0x84C2, 0xD9AD, 0x879F, 0xD9AE, 0x9169, + 0xD9AF, 0x9298, 0xD9B0, 0x9CF4, 0xD9B1, 0x8882, 0xD9B2, 0x4FAE, 0xD9B3, 0x5192, 0xD9B4, 0x52DF, 0xD9B5, 0x59C6, 0xD9B6, 0x5E3D, + 0xD9B7, 0x6155, 0xD9B8, 0x6478, 0xD9B9, 0x6479, 0xD9BA, 0x66AE, 0xD9BB, 0x67D0, 0xD9BC, 0x6A21, 0xD9BD, 0x6BCD, 0xD9BE, 0x6BDB, + 0xD9BF, 0x725F, 0xD9C0, 0x7261, 0xD9C1, 0x7441, 0xD9C2, 0x7738, 0xD9C3, 0x77DB, 0xD9C4, 0x8017, 0xD9C5, 0x82BC, 0xD9C6, 0x8305, + 0xD9C7, 0x8B00, 0xD9C8, 0x8B28, 0xD9C9, 0x8C8C, 0xD9CA, 0x6728, 0xD9CB, 0x6C90, 0xD9CC, 0x7267, 0xD9CD, 0x76EE, 0xD9CE, 0x7766, + 0xD9CF, 0x7A46, 0xD9D0, 0x9DA9, 0xD9D1, 0x6B7F, 0xD9D2, 0x6C92, 0xD9D3, 0x5922, 0xD9D4, 0x6726, 0xD9D5, 0x8499, 0xD9D6, 0x536F, + 0xD9D7, 0x5893, 0xD9D8, 0x5999, 0xD9D9, 0x5EDF, 0xD9DA, 0x63CF, 0xD9DB, 0x6634, 0xD9DC, 0x6773, 0xD9DD, 0x6E3A, 0xD9DE, 0x732B, + 0xD9DF, 0x7AD7, 0xD9E0, 0x82D7, 0xD9E1, 0x9328, 0xD9E2, 0x52D9, 0xD9E3, 0x5DEB, 0xD9E4, 0x61AE, 0xD9E5, 0x61CB, 0xD9E6, 0x620A, + 0xD9E7, 0x62C7, 0xD9E8, 0x64AB, 0xD9E9, 0x65E0, 0xD9EA, 0x6959, 0xD9EB, 0x6B66, 0xD9EC, 0x6BCB, 0xD9ED, 0x7121, 0xD9EE, 0x73F7, + 0xD9EF, 0x755D, 0xD9F0, 0x7E46, 0xD9F1, 0x821E, 0xD9F2, 0x8302, 0xD9F3, 0x856A, 0xD9F4, 0x8AA3, 0xD9F5, 0x8CBF, 0xD9F6, 0x9727, + 0xD9F7, 0x9D61, 0xD9F8, 0x58A8, 0xD9F9, 0x9ED8, 0xD9FA, 0x5011, 0xD9FB, 0x520E, 0xD9FC, 0x543B, 0xD9FD, 0x554F, 0xD9FE, 0x6587, + 0xDAA1, 0x6C76, 0xDAA2, 0x7D0A, 0xDAA3, 0x7D0B, 0xDAA4, 0x805E, 0xDAA5, 0x868A, 0xDAA6, 0x9580, 0xDAA7, 0x96EF, 0xDAA8, 0x52FF, + 0xDAA9, 0x6C95, 0xDAAA, 0x7269, 0xDAAB, 0x5473, 0xDAAC, 0x5A9A, 0xDAAD, 0x5C3E, 0xDAAE, 0x5D4B, 0xDAAF, 0x5F4C, 0xDAB0, 0x5FAE, + 0xDAB1, 0x672A, 0xDAB2, 0x68B6, 0xDAB3, 0x6963, 0xDAB4, 0x6E3C, 0xDAB5, 0x6E44, 0xDAB6, 0x7709, 0xDAB7, 0x7C73, 0xDAB8, 0x7F8E, + 0xDAB9, 0x8587, 0xDABA, 0x8B0E, 0xDABB, 0x8FF7, 0xDABC, 0x9761, 0xDABD, 0x9EF4, 0xDABE, 0x5CB7, 0xDABF, 0x60B6, 0xDAC0, 0x610D, + 0xDAC1, 0x61AB, 0xDAC2, 0x654F, 0xDAC3, 0x65FB, 0xDAC4, 0x65FC, 0xDAC5, 0x6C11, 0xDAC6, 0x6CEF, 0xDAC7, 0x739F, 0xDAC8, 0x73C9, + 0xDAC9, 0x7DE1, 0xDACA, 0x9594, 0xDACB, 0x5BC6, 0xDACC, 0x871C, 0xDACD, 0x8B10, 0xDACE, 0x525D, 0xDACF, 0x535A, 0xDAD0, 0x62CD, + 0xDAD1, 0x640F, 0xDAD2, 0x64B2, 0xDAD3, 0x6734, 0xDAD4, 0x6A38, 0xDAD5, 0x6CCA, 0xDAD6, 0x73C0, 0xDAD7, 0x749E, 0xDAD8, 0x7B94, + 0xDAD9, 0x7C95, 0xDADA, 0x7E1B, 0xDADB, 0x818A, 0xDADC, 0x8236, 0xDADD, 0x8584, 0xDADE, 0x8FEB, 0xDADF, 0x96F9, 0xDAE0, 0x99C1, + 0xDAE1, 0x4F34, 0xDAE2, 0x534A, 0xDAE3, 0x53CD, 0xDAE4, 0x53DB, 0xDAE5, 0x62CC, 0xDAE6, 0x642C, 0xDAE7, 0x6500, 0xDAE8, 0x6591, + 0xDAE9, 0x69C3, 0xDAEA, 0x6CEE, 0xDAEB, 0x6F58, 0xDAEC, 0x73ED, 0xDAED, 0x7554, 0xDAEE, 0x7622, 0xDAEF, 0x76E4, 0xDAF0, 0x76FC, + 0xDAF1, 0x78D0, 0xDAF2, 0x78FB, 0xDAF3, 0x792C, 0xDAF4, 0x7D46, 0xDAF5, 0x822C, 0xDAF6, 0x87E0, 0xDAF7, 0x8FD4, 0xDAF8, 0x9812, + 0xDAF9, 0x98EF, 0xDAFA, 0x52C3, 0xDAFB, 0x62D4, 0xDAFC, 0x64A5, 0xDAFD, 0x6E24, 0xDAFE, 0x6F51, 0xDBA1, 0x767C, 0xDBA2, 0x8DCB, + 0xDBA3, 0x91B1, 0xDBA4, 0x9262, 0xDBA5, 0x9AEE, 0xDBA6, 0x9B43, 0xDBA7, 0x5023, 0xDBA8, 0x508D, 0xDBA9, 0x574A, 0xDBAA, 0x59A8, + 0xDBAB, 0x5C28, 0xDBAC, 0x5E47, 0xDBAD, 0x5F77, 0xDBAE, 0x623F, 0xDBAF, 0x653E, 0xDBB0, 0x65B9, 0xDBB1, 0x65C1, 0xDBB2, 0x6609, + 0xDBB3, 0x678B, 0xDBB4, 0x699C, 0xDBB5, 0x6EC2, 0xDBB6, 0x78C5, 0xDBB7, 0x7D21, 0xDBB8, 0x80AA, 0xDBB9, 0x8180, 0xDBBA, 0x822B, + 0xDBBB, 0x82B3, 0xDBBC, 0x84A1, 0xDBBD, 0x868C, 0xDBBE, 0x8A2A, 0xDBBF, 0x8B17, 0xDBC0, 0x90A6, 0xDBC1, 0x9632, 0xDBC2, 0x9F90, + 0xDBC3, 0x500D, 0xDBC4, 0x4FF3, 0xDBC5, 0xF963, 0xDBC6, 0x57F9, 0xDBC7, 0x5F98, 0xDBC8, 0x62DC, 0xDBC9, 0x6392, 0xDBCA, 0x676F, + 0xDBCB, 0x6E43, 0xDBCC, 0x7119, 0xDBCD, 0x76C3, 0xDBCE, 0x80CC, 0xDBCF, 0x80DA, 0xDBD0, 0x88F4, 0xDBD1, 0x88F5, 0xDBD2, 0x8919, + 0xDBD3, 0x8CE0, 0xDBD4, 0x8F29, 0xDBD5, 0x914D, 0xDBD6, 0x966A, 0xDBD7, 0x4F2F, 0xDBD8, 0x4F70, 0xDBD9, 0x5E1B, 0xDBDA, 0x67CF, + 0xDBDB, 0x6822, 0xDBDC, 0x767D, 0xDBDD, 0x767E, 0xDBDE, 0x9B44, 0xDBDF, 0x5E61, 0xDBE0, 0x6A0A, 0xDBE1, 0x7169, 0xDBE2, 0x71D4, + 0xDBE3, 0x756A, 0xDBE4, 0xF964, 0xDBE5, 0x7E41, 0xDBE6, 0x8543, 0xDBE7, 0x85E9, 0xDBE8, 0x98DC, 0xDBE9, 0x4F10, 0xDBEA, 0x7B4F, + 0xDBEB, 0x7F70, 0xDBEC, 0x95A5, 0xDBED, 0x51E1, 0xDBEE, 0x5E06, 0xDBEF, 0x68B5, 0xDBF0, 0x6C3E, 0xDBF1, 0x6C4E, 0xDBF2, 0x6CDB, + 0xDBF3, 0x72AF, 0xDBF4, 0x7BC4, 0xDBF5, 0x8303, 0xDBF6, 0x6CD5, 0xDBF7, 0x743A, 0xDBF8, 0x50FB, 0xDBF9, 0x5288, 0xDBFA, 0x58C1, + 0xDBFB, 0x64D8, 0xDBFC, 0x6A97, 0xDBFD, 0x74A7, 0xDBFE, 0x7656, 0xDCA1, 0x78A7, 0xDCA2, 0x8617, 0xDCA3, 0x95E2, 0xDCA4, 0x9739, + 0xDCA5, 0xF965, 0xDCA6, 0x535E, 0xDCA7, 0x5F01, 0xDCA8, 0x8B8A, 0xDCA9, 0x8FA8, 0xDCAA, 0x8FAF, 0xDCAB, 0x908A, 0xDCAC, 0x5225, + 0xDCAD, 0x77A5, 0xDCAE, 0x9C49, 0xDCAF, 0x9F08, 0xDCB0, 0x4E19, 0xDCB1, 0x5002, 0xDCB2, 0x5175, 0xDCB3, 0x5C5B, 0xDCB4, 0x5E77, + 0xDCB5, 0x661E, 0xDCB6, 0x663A, 0xDCB7, 0x67C4, 0xDCB8, 0x68C5, 0xDCB9, 0x70B3, 0xDCBA, 0x7501, 0xDCBB, 0x75C5, 0xDCBC, 0x79C9, + 0xDCBD, 0x7ADD, 0xDCBE, 0x8F27, 0xDCBF, 0x9920, 0xDCC0, 0x9A08, 0xDCC1, 0x4FDD, 0xDCC2, 0x5821, 0xDCC3, 0x5831, 0xDCC4, 0x5BF6, + 0xDCC5, 0x666E, 0xDCC6, 0x6B65, 0xDCC7, 0x6D11, 0xDCC8, 0x6E7A, 0xDCC9, 0x6F7D, 0xDCCA, 0x73E4, 0xDCCB, 0x752B, 0xDCCC, 0x83E9, + 0xDCCD, 0x88DC, 0xDCCE, 0x8913, 0xDCCF, 0x8B5C, 0xDCD0, 0x8F14, 0xDCD1, 0x4F0F, 0xDCD2, 0x50D5, 0xDCD3, 0x5310, 0xDCD4, 0x535C, + 0xDCD5, 0x5B93, 0xDCD6, 0x5FA9, 0xDCD7, 0x670D, 0xDCD8, 0x798F, 0xDCD9, 0x8179, 0xDCDA, 0x832F, 0xDCDB, 0x8514, 0xDCDC, 0x8907, + 0xDCDD, 0x8986, 0xDCDE, 0x8F39, 0xDCDF, 0x8F3B, 0xDCE0, 0x99A5, 0xDCE1, 0x9C12, 0xDCE2, 0x672C, 0xDCE3, 0x4E76, 0xDCE4, 0x4FF8, + 0xDCE5, 0x5949, 0xDCE6, 0x5C01, 0xDCE7, 0x5CEF, 0xDCE8, 0x5CF0, 0xDCE9, 0x6367, 0xDCEA, 0x68D2, 0xDCEB, 0x70FD, 0xDCEC, 0x71A2, + 0xDCED, 0x742B, 0xDCEE, 0x7E2B, 0xDCEF, 0x84EC, 0xDCF0, 0x8702, 0xDCF1, 0x9022, 0xDCF2, 0x92D2, 0xDCF3, 0x9CF3, 0xDCF4, 0x4E0D, + 0xDCF5, 0x4ED8, 0xDCF6, 0x4FEF, 0xDCF7, 0x5085, 0xDCF8, 0x5256, 0xDCF9, 0x526F, 0xDCFA, 0x5426, 0xDCFB, 0x5490, 0xDCFC, 0x57E0, + 0xDCFD, 0x592B, 0xDCFE, 0x5A66, 0xDDA1, 0x5B5A, 0xDDA2, 0x5B75, 0xDDA3, 0x5BCC, 0xDDA4, 0x5E9C, 0xDDA5, 0xF966, 0xDDA6, 0x6276, + 0xDDA7, 0x6577, 0xDDA8, 0x65A7, 0xDDA9, 0x6D6E, 0xDDAA, 0x6EA5, 0xDDAB, 0x7236, 0xDDAC, 0x7B26, 0xDDAD, 0x7C3F, 0xDDAE, 0x7F36, + 0xDDAF, 0x8150, 0xDDB0, 0x8151, 0xDDB1, 0x819A, 0xDDB2, 0x8240, 0xDDB3, 0x8299, 0xDDB4, 0x83A9, 0xDDB5, 0x8A03, 0xDDB6, 0x8CA0, + 0xDDB7, 0x8CE6, 0xDDB8, 0x8CFB, 0xDDB9, 0x8D74, 0xDDBA, 0x8DBA, 0xDDBB, 0x90E8, 0xDDBC, 0x91DC, 0xDDBD, 0x961C, 0xDDBE, 0x9644, + 0xDDBF, 0x99D9, 0xDDC0, 0x9CE7, 0xDDC1, 0x5317, 0xDDC2, 0x5206, 0xDDC3, 0x5429, 0xDDC4, 0x5674, 0xDDC5, 0x58B3, 0xDDC6, 0x5954, + 0xDDC7, 0x596E, 0xDDC8, 0x5FFF, 0xDDC9, 0x61A4, 0xDDCA, 0x626E, 0xDDCB, 0x6610, 0xDDCC, 0x6C7E, 0xDDCD, 0x711A, 0xDDCE, 0x76C6, + 0xDDCF, 0x7C89, 0xDDD0, 0x7CDE, 0xDDD1, 0x7D1B, 0xDDD2, 0x82AC, 0xDDD3, 0x8CC1, 0xDDD4, 0x96F0, 0xDDD5, 0xF967, 0xDDD6, 0x4F5B, + 0xDDD7, 0x5F17, 0xDDD8, 0x5F7F, 0xDDD9, 0x62C2, 0xDDDA, 0x5D29, 0xDDDB, 0x670B, 0xDDDC, 0x68DA, 0xDDDD, 0x787C, 0xDDDE, 0x7E43, + 0xDDDF, 0x9D6C, 0xDDE0, 0x4E15, 0xDDE1, 0x5099, 0xDDE2, 0x5315, 0xDDE3, 0x532A, 0xDDE4, 0x5351, 0xDDE5, 0x5983, 0xDDE6, 0x5A62, + 0xDDE7, 0x5E87, 0xDDE8, 0x60B2, 0xDDE9, 0x618A, 0xDDEA, 0x6249, 0xDDEB, 0x6279, 0xDDEC, 0x6590, 0xDDED, 0x6787, 0xDDEE, 0x69A7, + 0xDDEF, 0x6BD4, 0xDDF0, 0x6BD6, 0xDDF1, 0x6BD7, 0xDDF2, 0x6BD8, 0xDDF3, 0x6CB8, 0xDDF4, 0xF968, 0xDDF5, 0x7435, 0xDDF6, 0x75FA, + 0xDDF7, 0x7812, 0xDDF8, 0x7891, 0xDDF9, 0x79D5, 0xDDFA, 0x79D8, 0xDDFB, 0x7C83, 0xDDFC, 0x7DCB, 0xDDFD, 0x7FE1, 0xDDFE, 0x80A5, + 0xDEA1, 0x813E, 0xDEA2, 0x81C2, 0xDEA3, 0x83F2, 0xDEA4, 0x871A, 0xDEA5, 0x88E8, 0xDEA6, 0x8AB9, 0xDEA7, 0x8B6C, 0xDEA8, 0x8CBB, + 0xDEA9, 0x9119, 0xDEAA, 0x975E, 0xDEAB, 0x98DB, 0xDEAC, 0x9F3B, 0xDEAD, 0x56AC, 0xDEAE, 0x5B2A, 0xDEAF, 0x5F6C, 0xDEB0, 0x658C, + 0xDEB1, 0x6AB3, 0xDEB2, 0x6BAF, 0xDEB3, 0x6D5C, 0xDEB4, 0x6FF1, 0xDEB5, 0x7015, 0xDEB6, 0x725D, 0xDEB7, 0x73AD, 0xDEB8, 0x8CA7, + 0xDEB9, 0x8CD3, 0xDEBA, 0x983B, 0xDEBB, 0x6191, 0xDEBC, 0x6C37, 0xDEBD, 0x8058, 0xDEBE, 0x9A01, 0xDEBF, 0x4E4D, 0xDEC0, 0x4E8B, + 0xDEC1, 0x4E9B, 0xDEC2, 0x4ED5, 0xDEC3, 0x4F3A, 0xDEC4, 0x4F3C, 0xDEC5, 0x4F7F, 0xDEC6, 0x4FDF, 0xDEC7, 0x50FF, 0xDEC8, 0x53F2, + 0xDEC9, 0x53F8, 0xDECA, 0x5506, 0xDECB, 0x55E3, 0xDECC, 0x56DB, 0xDECD, 0x58EB, 0xDECE, 0x5962, 0xDECF, 0x5A11, 0xDED0, 0x5BEB, + 0xDED1, 0x5BFA, 0xDED2, 0x5C04, 0xDED3, 0x5DF3, 0xDED4, 0x5E2B, 0xDED5, 0x5F99, 0xDED6, 0x601D, 0xDED7, 0x6368, 0xDED8, 0x659C, + 0xDED9, 0x65AF, 0xDEDA, 0x67F6, 0xDEDB, 0x67FB, 0xDEDC, 0x68AD, 0xDEDD, 0x6B7B, 0xDEDE, 0x6C99, 0xDEDF, 0x6CD7, 0xDEE0, 0x6E23, + 0xDEE1, 0x7009, 0xDEE2, 0x7345, 0xDEE3, 0x7802, 0xDEE4, 0x793E, 0xDEE5, 0x7940, 0xDEE6, 0x7960, 0xDEE7, 0x79C1, 0xDEE8, 0x7BE9, + 0xDEE9, 0x7D17, 0xDEEA, 0x7D72, 0xDEEB, 0x8086, 0xDEEC, 0x820D, 0xDEED, 0x838E, 0xDEEE, 0x84D1, 0xDEEF, 0x86C7, 0xDEF0, 0x88DF, + 0xDEF1, 0x8A50, 0xDEF2, 0x8A5E, 0xDEF3, 0x8B1D, 0xDEF4, 0x8CDC, 0xDEF5, 0x8D66, 0xDEF6, 0x8FAD, 0xDEF7, 0x90AA, 0xDEF8, 0x98FC, + 0xDEF9, 0x99DF, 0xDEFA, 0x9E9D, 0xDEFB, 0x524A, 0xDEFC, 0xF969, 0xDEFD, 0x6714, 0xDEFE, 0xF96A, 0xDFA1, 0x5098, 0xDFA2, 0x522A, + 0xDFA3, 0x5C71, 0xDFA4, 0x6563, 0xDFA5, 0x6C55, 0xDFA6, 0x73CA, 0xDFA7, 0x7523, 0xDFA8, 0x759D, 0xDFA9, 0x7B97, 0xDFAA, 0x849C, + 0xDFAB, 0x9178, 0xDFAC, 0x9730, 0xDFAD, 0x4E77, 0xDFAE, 0x6492, 0xDFAF, 0x6BBA, 0xDFB0, 0x715E, 0xDFB1, 0x85A9, 0xDFB2, 0x4E09, + 0xDFB3, 0xF96B, 0xDFB4, 0x6749, 0xDFB5, 0x68EE, 0xDFB6, 0x6E17, 0xDFB7, 0x829F, 0xDFB8, 0x8518, 0xDFB9, 0x886B, 0xDFBA, 0x63F7, + 0xDFBB, 0x6F81, 0xDFBC, 0x9212, 0xDFBD, 0x98AF, 0xDFBE, 0x4E0A, 0xDFBF, 0x50B7, 0xDFC0, 0x50CF, 0xDFC1, 0x511F, 0xDFC2, 0x5546, + 0xDFC3, 0x55AA, 0xDFC4, 0x5617, 0xDFC5, 0x5B40, 0xDFC6, 0x5C19, 0xDFC7, 0x5CE0, 0xDFC8, 0x5E38, 0xDFC9, 0x5E8A, 0xDFCA, 0x5EA0, + 0xDFCB, 0x5EC2, 0xDFCC, 0x60F3, 0xDFCD, 0x6851, 0xDFCE, 0x6A61, 0xDFCF, 0x6E58, 0xDFD0, 0x723D, 0xDFD1, 0x7240, 0xDFD2, 0x72C0, + 0xDFD3, 0x76F8, 0xDFD4, 0x7965, 0xDFD5, 0x7BB1, 0xDFD6, 0x7FD4, 0xDFD7, 0x88F3, 0xDFD8, 0x89F4, 0xDFD9, 0x8A73, 0xDFDA, 0x8C61, + 0xDFDB, 0x8CDE, 0xDFDC, 0x971C, 0xDFDD, 0x585E, 0xDFDE, 0x74BD, 0xDFDF, 0x8CFD, 0xDFE0, 0x55C7, 0xDFE1, 0xF96C, 0xDFE2, 0x7A61, + 0xDFE3, 0x7D22, 0xDFE4, 0x8272, 0xDFE5, 0x7272, 0xDFE6, 0x751F, 0xDFE7, 0x7525, 0xDFE8, 0xF96D, 0xDFE9, 0x7B19, 0xDFEA, 0x5885, + 0xDFEB, 0x58FB, 0xDFEC, 0x5DBC, 0xDFED, 0x5E8F, 0xDFEE, 0x5EB6, 0xDFEF, 0x5F90, 0xDFF0, 0x6055, 0xDFF1, 0x6292, 0xDFF2, 0x637F, + 0xDFF3, 0x654D, 0xDFF4, 0x6691, 0xDFF5, 0x66D9, 0xDFF6, 0x66F8, 0xDFF7, 0x6816, 0xDFF8, 0x68F2, 0xDFF9, 0x7280, 0xDFFA, 0x745E, + 0xDFFB, 0x7B6E, 0xDFFC, 0x7D6E, 0xDFFD, 0x7DD6, 0xDFFE, 0x7F72, 0xE0A1, 0x80E5, 0xE0A2, 0x8212, 0xE0A3, 0x85AF, 0xE0A4, 0x897F, + 0xE0A5, 0x8A93, 0xE0A6, 0x901D, 0xE0A7, 0x92E4, 0xE0A8, 0x9ECD, 0xE0A9, 0x9F20, 0xE0AA, 0x5915, 0xE0AB, 0x596D, 0xE0AC, 0x5E2D, + 0xE0AD, 0x60DC, 0xE0AE, 0x6614, 0xE0AF, 0x6673, 0xE0B0, 0x6790, 0xE0B1, 0x6C50, 0xE0B2, 0x6DC5, 0xE0B3, 0x6F5F, 0xE0B4, 0x77F3, + 0xE0B5, 0x78A9, 0xE0B6, 0x84C6, 0xE0B7, 0x91CB, 0xE0B8, 0x932B, 0xE0B9, 0x4ED9, 0xE0BA, 0x50CA, 0xE0BB, 0x5148, 0xE0BC, 0x5584, + 0xE0BD, 0x5B0B, 0xE0BE, 0x5BA3, 0xE0BF, 0x6247, 0xE0C0, 0x657E, 0xE0C1, 0x65CB, 0xE0C2, 0x6E32, 0xE0C3, 0x717D, 0xE0C4, 0x7401, + 0xE0C5, 0x7444, 0xE0C6, 0x7487, 0xE0C7, 0x74BF, 0xE0C8, 0x766C, 0xE0C9, 0x79AA, 0xE0CA, 0x7DDA, 0xE0CB, 0x7E55, 0xE0CC, 0x7FA8, + 0xE0CD, 0x817A, 0xE0CE, 0x81B3, 0xE0CF, 0x8239, 0xE0D0, 0x861A, 0xE0D1, 0x87EC, 0xE0D2, 0x8A75, 0xE0D3, 0x8DE3, 0xE0D4, 0x9078, + 0xE0D5, 0x9291, 0xE0D6, 0x9425, 0xE0D7, 0x994D, 0xE0D8, 0x9BAE, 0xE0D9, 0x5368, 0xE0DA, 0x5C51, 0xE0DB, 0x6954, 0xE0DC, 0x6CC4, + 0xE0DD, 0x6D29, 0xE0DE, 0x6E2B, 0xE0DF, 0x820C, 0xE0E0, 0x859B, 0xE0E1, 0x893B, 0xE0E2, 0x8A2D, 0xE0E3, 0x8AAA, 0xE0E4, 0x96EA, + 0xE0E5, 0x9F67, 0xE0E6, 0x5261, 0xE0E7, 0x66B9, 0xE0E8, 0x6BB2, 0xE0E9, 0x7E96, 0xE0EA, 0x87FE, 0xE0EB, 0x8D0D, 0xE0EC, 0x9583, + 0xE0ED, 0x965D, 0xE0EE, 0x651D, 0xE0EF, 0x6D89, 0xE0F0, 0x71EE, 0xE0F1, 0xF96E, 0xE0F2, 0x57CE, 0xE0F3, 0x59D3, 0xE0F4, 0x5BAC, + 0xE0F5, 0x6027, 0xE0F6, 0x60FA, 0xE0F7, 0x6210, 0xE0F8, 0x661F, 0xE0F9, 0x665F, 0xE0FA, 0x7329, 0xE0FB, 0x73F9, 0xE0FC, 0x76DB, + 0xE0FD, 0x7701, 0xE0FE, 0x7B6C, 0xE1A1, 0x8056, 0xE1A2, 0x8072, 0xE1A3, 0x8165, 0xE1A4, 0x8AA0, 0xE1A5, 0x9192, 0xE1A6, 0x4E16, + 0xE1A7, 0x52E2, 0xE1A8, 0x6B72, 0xE1A9, 0x6D17, 0xE1AA, 0x7A05, 0xE1AB, 0x7B39, 0xE1AC, 0x7D30, 0xE1AD, 0xF96F, 0xE1AE, 0x8CB0, + 0xE1AF, 0x53EC, 0xE1B0, 0x562F, 0xE1B1, 0x5851, 0xE1B2, 0x5BB5, 0xE1B3, 0x5C0F, 0xE1B4, 0x5C11, 0xE1B5, 0x5DE2, 0xE1B6, 0x6240, + 0xE1B7, 0x6383, 0xE1B8, 0x6414, 0xE1B9, 0x662D, 0xE1BA, 0x68B3, 0xE1BB, 0x6CBC, 0xE1BC, 0x6D88, 0xE1BD, 0x6EAF, 0xE1BE, 0x701F, + 0xE1BF, 0x70A4, 0xE1C0, 0x71D2, 0xE1C1, 0x7526, 0xE1C2, 0x758F, 0xE1C3, 0x758E, 0xE1C4, 0x7619, 0xE1C5, 0x7B11, 0xE1C6, 0x7BE0, + 0xE1C7, 0x7C2B, 0xE1C8, 0x7D20, 0xE1C9, 0x7D39, 0xE1CA, 0x852C, 0xE1CB, 0x856D, 0xE1CC, 0x8607, 0xE1CD, 0x8A34, 0xE1CE, 0x900D, + 0xE1CF, 0x9061, 0xE1D0, 0x90B5, 0xE1D1, 0x92B7, 0xE1D2, 0x97F6, 0xE1D3, 0x9A37, 0xE1D4, 0x4FD7, 0xE1D5, 0x5C6C, 0xE1D6, 0x675F, + 0xE1D7, 0x6D91, 0xE1D8, 0x7C9F, 0xE1D9, 0x7E8C, 0xE1DA, 0x8B16, 0xE1DB, 0x8D16, 0xE1DC, 0x901F, 0xE1DD, 0x5B6B, 0xE1DE, 0x5DFD, + 0xE1DF, 0x640D, 0xE1E0, 0x84C0, 0xE1E1, 0x905C, 0xE1E2, 0x98E1, 0xE1E3, 0x7387, 0xE1E4, 0x5B8B, 0xE1E5, 0x609A, 0xE1E6, 0x677E, + 0xE1E7, 0x6DDE, 0xE1E8, 0x8A1F, 0xE1E9, 0x8AA6, 0xE1EA, 0x9001, 0xE1EB, 0x980C, 0xE1EC, 0x5237, 0xE1ED, 0xF970, 0xE1EE, 0x7051, + 0xE1EF, 0x788E, 0xE1F0, 0x9396, 0xE1F1, 0x8870, 0xE1F2, 0x91D7, 0xE1F3, 0x4FEE, 0xE1F4, 0x53D7, 0xE1F5, 0x55FD, 0xE1F6, 0x56DA, + 0xE1F7, 0x5782, 0xE1F8, 0x58FD, 0xE1F9, 0x5AC2, 0xE1FA, 0x5B88, 0xE1FB, 0x5CAB, 0xE1FC, 0x5CC0, 0xE1FD, 0x5E25, 0xE1FE, 0x6101, + 0xE2A1, 0x620D, 0xE2A2, 0x624B, 0xE2A3, 0x6388, 0xE2A4, 0x641C, 0xE2A5, 0x6536, 0xE2A6, 0x6578, 0xE2A7, 0x6A39, 0xE2A8, 0x6B8A, + 0xE2A9, 0x6C34, 0xE2AA, 0x6D19, 0xE2AB, 0x6F31, 0xE2AC, 0x71E7, 0xE2AD, 0x72E9, 0xE2AE, 0x7378, 0xE2AF, 0x7407, 0xE2B0, 0x74B2, + 0xE2B1, 0x7626, 0xE2B2, 0x7761, 0xE2B3, 0x79C0, 0xE2B4, 0x7A57, 0xE2B5, 0x7AEA, 0xE2B6, 0x7CB9, 0xE2B7, 0x7D8F, 0xE2B8, 0x7DAC, + 0xE2B9, 0x7E61, 0xE2BA, 0x7F9E, 0xE2BB, 0x8129, 0xE2BC, 0x8331, 0xE2BD, 0x8490, 0xE2BE, 0x84DA, 0xE2BF, 0x85EA, 0xE2C0, 0x8896, + 0xE2C1, 0x8AB0, 0xE2C2, 0x8B90, 0xE2C3, 0x8F38, 0xE2C4, 0x9042, 0xE2C5, 0x9083, 0xE2C6, 0x916C, 0xE2C7, 0x9296, 0xE2C8, 0x92B9, + 0xE2C9, 0x968B, 0xE2CA, 0x96A7, 0xE2CB, 0x96A8, 0xE2CC, 0x96D6, 0xE2CD, 0x9700, 0xE2CE, 0x9808, 0xE2CF, 0x9996, 0xE2D0, 0x9AD3, + 0xE2D1, 0x9B1A, 0xE2D2, 0x53D4, 0xE2D3, 0x587E, 0xE2D4, 0x5919, 0xE2D5, 0x5B70, 0xE2D6, 0x5BBF, 0xE2D7, 0x6DD1, 0xE2D8, 0x6F5A, + 0xE2D9, 0x719F, 0xE2DA, 0x7421, 0xE2DB, 0x74B9, 0xE2DC, 0x8085, 0xE2DD, 0x83FD, 0xE2DE, 0x5DE1, 0xE2DF, 0x5F87, 0xE2E0, 0x5FAA, + 0xE2E1, 0x6042, 0xE2E2, 0x65EC, 0xE2E3, 0x6812, 0xE2E4, 0x696F, 0xE2E5, 0x6A53, 0xE2E6, 0x6B89, 0xE2E7, 0x6D35, 0xE2E8, 0x6DF3, + 0xE2E9, 0x73E3, 0xE2EA, 0x76FE, 0xE2EB, 0x77AC, 0xE2EC, 0x7B4D, 0xE2ED, 0x7D14, 0xE2EE, 0x8123, 0xE2EF, 0x821C, 0xE2F0, 0x8340, + 0xE2F1, 0x84F4, 0xE2F2, 0x8563, 0xE2F3, 0x8A62, 0xE2F4, 0x8AC4, 0xE2F5, 0x9187, 0xE2F6, 0x931E, 0xE2F7, 0x9806, 0xE2F8, 0x99B4, + 0xE2F9, 0x620C, 0xE2FA, 0x8853, 0xE2FB, 0x8FF0, 0xE2FC, 0x9265, 0xE2FD, 0x5D07, 0xE2FE, 0x5D27, 0xE3A1, 0x5D69, 0xE3A2, 0x745F, + 0xE3A3, 0x819D, 0xE3A4, 0x8768, 0xE3A5, 0x6FD5, 0xE3A6, 0x62FE, 0xE3A7, 0x7FD2, 0xE3A8, 0x8936, 0xE3A9, 0x8972, 0xE3AA, 0x4E1E, + 0xE3AB, 0x4E58, 0xE3AC, 0x50E7, 0xE3AD, 0x52DD, 0xE3AE, 0x5347, 0xE3AF, 0x627F, 0xE3B0, 0x6607, 0xE3B1, 0x7E69, 0xE3B2, 0x8805, + 0xE3B3, 0x965E, 0xE3B4, 0x4F8D, 0xE3B5, 0x5319, 0xE3B6, 0x5636, 0xE3B7, 0x59CB, 0xE3B8, 0x5AA4, 0xE3B9, 0x5C38, 0xE3BA, 0x5C4E, + 0xE3BB, 0x5C4D, 0xE3BC, 0x5E02, 0xE3BD, 0x5F11, 0xE3BE, 0x6043, 0xE3BF, 0x65BD, 0xE3C0, 0x662F, 0xE3C1, 0x6642, 0xE3C2, 0x67BE, + 0xE3C3, 0x67F4, 0xE3C4, 0x731C, 0xE3C5, 0x77E2, 0xE3C6, 0x793A, 0xE3C7, 0x7FC5, 0xE3C8, 0x8494, 0xE3C9, 0x84CD, 0xE3CA, 0x8996, + 0xE3CB, 0x8A66, 0xE3CC, 0x8A69, 0xE3CD, 0x8AE1, 0xE3CE, 0x8C55, 0xE3CF, 0x8C7A, 0xE3D0, 0x57F4, 0xE3D1, 0x5BD4, 0xE3D2, 0x5F0F, + 0xE3D3, 0x606F, 0xE3D4, 0x62ED, 0xE3D5, 0x690D, 0xE3D6, 0x6B96, 0xE3D7, 0x6E5C, 0xE3D8, 0x7184, 0xE3D9, 0x7BD2, 0xE3DA, 0x8755, + 0xE3DB, 0x8B58, 0xE3DC, 0x8EFE, 0xE3DD, 0x98DF, 0xE3DE, 0x98FE, 0xE3DF, 0x4F38, 0xE3E0, 0x4F81, 0xE3E1, 0x4FE1, 0xE3E2, 0x547B, + 0xE3E3, 0x5A20, 0xE3E4, 0x5BB8, 0xE3E5, 0x613C, 0xE3E6, 0x65B0, 0xE3E7, 0x6668, 0xE3E8, 0x71FC, 0xE3E9, 0x7533, 0xE3EA, 0x795E, + 0xE3EB, 0x7D33, 0xE3EC, 0x814E, 0xE3ED, 0x81E3, 0xE3EE, 0x8398, 0xE3EF, 0x85AA, 0xE3F0, 0x85CE, 0xE3F1, 0x8703, 0xE3F2, 0x8A0A, + 0xE3F3, 0x8EAB, 0xE3F4, 0x8F9B, 0xE3F5, 0xF971, 0xE3F6, 0x8FC5, 0xE3F7, 0x5931, 0xE3F8, 0x5BA4, 0xE3F9, 0x5BE6, 0xE3FA, 0x6089, + 0xE3FB, 0x5BE9, 0xE3FC, 0x5C0B, 0xE3FD, 0x5FC3, 0xE3FE, 0x6C81, 0xE4A1, 0xF972, 0xE4A2, 0x6DF1, 0xE4A3, 0x700B, 0xE4A4, 0x751A, + 0xE4A5, 0x82AF, 0xE4A6, 0x8AF6, 0xE4A7, 0x4EC0, 0xE4A8, 0x5341, 0xE4A9, 0xF973, 0xE4AA, 0x96D9, 0xE4AB, 0x6C0F, 0xE4AC, 0x4E9E, + 0xE4AD, 0x4FC4, 0xE4AE, 0x5152, 0xE4AF, 0x555E, 0xE4B0, 0x5A25, 0xE4B1, 0x5CE8, 0xE4B2, 0x6211, 0xE4B3, 0x7259, 0xE4B4, 0x82BD, + 0xE4B5, 0x83AA, 0xE4B6, 0x86FE, 0xE4B7, 0x8859, 0xE4B8, 0x8A1D, 0xE4B9, 0x963F, 0xE4BA, 0x96C5, 0xE4BB, 0x9913, 0xE4BC, 0x9D09, + 0xE4BD, 0x9D5D, 0xE4BE, 0x580A, 0xE4BF, 0x5CB3, 0xE4C0, 0x5DBD, 0xE4C1, 0x5E44, 0xE4C2, 0x60E1, 0xE4C3, 0x6115, 0xE4C4, 0x63E1, + 0xE4C5, 0x6A02, 0xE4C6, 0x6E25, 0xE4C7, 0x9102, 0xE4C8, 0x9354, 0xE4C9, 0x984E, 0xE4CA, 0x9C10, 0xE4CB, 0x9F77, 0xE4CC, 0x5B89, + 0xE4CD, 0x5CB8, 0xE4CE, 0x6309, 0xE4CF, 0x664F, 0xE4D0, 0x6848, 0xE4D1, 0x773C, 0xE4D2, 0x96C1, 0xE4D3, 0x978D, 0xE4D4, 0x9854, + 0xE4D5, 0x9B9F, 0xE4D6, 0x65A1, 0xE4D7, 0x8B01, 0xE4D8, 0x8ECB, 0xE4D9, 0x95BC, 0xE4DA, 0x5535, 0xE4DB, 0x5CA9, 0xE4DC, 0x5DD6, + 0xE4DD, 0x5EB5, 0xE4DE, 0x6697, 0xE4DF, 0x764C, 0xE4E0, 0x83F4, 0xE4E1, 0x95C7, 0xE4E2, 0x58D3, 0xE4E3, 0x62BC, 0xE4E4, 0x72CE, + 0xE4E5, 0x9D28, 0xE4E6, 0x4EF0, 0xE4E7, 0x592E, 0xE4E8, 0x600F, 0xE4E9, 0x663B, 0xE4EA, 0x6B83, 0xE4EB, 0x79E7, 0xE4EC, 0x9D26, + 0xE4ED, 0x5393, 0xE4EE, 0x54C0, 0xE4EF, 0x57C3, 0xE4F0, 0x5D16, 0xE4F1, 0x611B, 0xE4F2, 0x66D6, 0xE4F3, 0x6DAF, 0xE4F4, 0x788D, + 0xE4F5, 0x827E, 0xE4F6, 0x9698, 0xE4F7, 0x9744, 0xE4F8, 0x5384, 0xE4F9, 0x627C, 0xE4FA, 0x6396, 0xE4FB, 0x6DB2, 0xE4FC, 0x7E0A, + 0xE4FD, 0x814B, 0xE4FE, 0x984D, 0xE5A1, 0x6AFB, 0xE5A2, 0x7F4C, 0xE5A3, 0x9DAF, 0xE5A4, 0x9E1A, 0xE5A5, 0x4E5F, 0xE5A6, 0x503B, + 0xE5A7, 0x51B6, 0xE5A8, 0x591C, 0xE5A9, 0x60F9, 0xE5AA, 0x63F6, 0xE5AB, 0x6930, 0xE5AC, 0x723A, 0xE5AD, 0x8036, 0xE5AE, 0xF974, + 0xE5AF, 0x91CE, 0xE5B0, 0x5F31, 0xE5B1, 0xF975, 0xE5B2, 0xF976, 0xE5B3, 0x7D04, 0xE5B4, 0x82E5, 0xE5B5, 0x846F, 0xE5B6, 0x84BB, + 0xE5B7, 0x85E5, 0xE5B8, 0x8E8D, 0xE5B9, 0xF977, 0xE5BA, 0x4F6F, 0xE5BB, 0xF978, 0xE5BC, 0xF979, 0xE5BD, 0x58E4, 0xE5BE, 0x5B43, + 0xE5BF, 0x6059, 0xE5C0, 0x63DA, 0xE5C1, 0x6518, 0xE5C2, 0x656D, 0xE5C3, 0x6698, 0xE5C4, 0xF97A, 0xE5C5, 0x694A, 0xE5C6, 0x6A23, + 0xE5C7, 0x6D0B, 0xE5C8, 0x7001, 0xE5C9, 0x716C, 0xE5CA, 0x75D2, 0xE5CB, 0x760D, 0xE5CC, 0x79B3, 0xE5CD, 0x7A70, 0xE5CE, 0xF97B, + 0xE5CF, 0x7F8A, 0xE5D0, 0xF97C, 0xE5D1, 0x8944, 0xE5D2, 0xF97D, 0xE5D3, 0x8B93, 0xE5D4, 0x91C0, 0xE5D5, 0x967D, 0xE5D6, 0xF97E, + 0xE5D7, 0x990A, 0xE5D8, 0x5704, 0xE5D9, 0x5FA1, 0xE5DA, 0x65BC, 0xE5DB, 0x6F01, 0xE5DC, 0x7600, 0xE5DD, 0x79A6, 0xE5DE, 0x8A9E, + 0xE5DF, 0x99AD, 0xE5E0, 0x9B5A, 0xE5E1, 0x9F6C, 0xE5E2, 0x5104, 0xE5E3, 0x61B6, 0xE5E4, 0x6291, 0xE5E5, 0x6A8D, 0xE5E6, 0x81C6, + 0xE5E7, 0x5043, 0xE5E8, 0x5830, 0xE5E9, 0x5F66, 0xE5EA, 0x7109, 0xE5EB, 0x8A00, 0xE5EC, 0x8AFA, 0xE5ED, 0x5B7C, 0xE5EE, 0x8616, + 0xE5EF, 0x4FFA, 0xE5F0, 0x513C, 0xE5F1, 0x56B4, 0xE5F2, 0x5944, 0xE5F3, 0x63A9, 0xE5F4, 0x6DF9, 0xE5F5, 0x5DAA, 0xE5F6, 0x696D, + 0xE5F7, 0x5186, 0xE5F8, 0x4E88, 0xE5F9, 0x4F59, 0xE5FA, 0xF97F, 0xE5FB, 0xF980, 0xE5FC, 0xF981, 0xE5FD, 0x5982, 0xE5FE, 0xF982, + 0xE6A1, 0xF983, 0xE6A2, 0x6B5F, 0xE6A3, 0x6C5D, 0xE6A4, 0xF984, 0xE6A5, 0x74B5, 0xE6A6, 0x7916, 0xE6A7, 0xF985, 0xE6A8, 0x8207, + 0xE6A9, 0x8245, 0xE6AA, 0x8339, 0xE6AB, 0x8F3F, 0xE6AC, 0x8F5D, 0xE6AD, 0xF986, 0xE6AE, 0x9918, 0xE6AF, 0xF987, 0xE6B0, 0xF988, + 0xE6B1, 0xF989, 0xE6B2, 0x4EA6, 0xE6B3, 0xF98A, 0xE6B4, 0x57DF, 0xE6B5, 0x5F79, 0xE6B6, 0x6613, 0xE6B7, 0xF98B, 0xE6B8, 0xF98C, + 0xE6B9, 0x75AB, 0xE6BA, 0x7E79, 0xE6BB, 0x8B6F, 0xE6BC, 0xF98D, 0xE6BD, 0x9006, 0xE6BE, 0x9A5B, 0xE6BF, 0x56A5, 0xE6C0, 0x5827, + 0xE6C1, 0x59F8, 0xE6C2, 0x5A1F, 0xE6C3, 0x5BB4, 0xE6C4, 0xF98E, 0xE6C5, 0x5EF6, 0xE6C6, 0xF98F, 0xE6C7, 0xF990, 0xE6C8, 0x6350, + 0xE6C9, 0x633B, 0xE6CA, 0xF991, 0xE6CB, 0x693D, 0xE6CC, 0x6C87, 0xE6CD, 0x6CBF, 0xE6CE, 0x6D8E, 0xE6CF, 0x6D93, 0xE6D0, 0x6DF5, + 0xE6D1, 0x6F14, 0xE6D2, 0xF992, 0xE6D3, 0x70DF, 0xE6D4, 0x7136, 0xE6D5, 0x7159, 0xE6D6, 0xF993, 0xE6D7, 0x71C3, 0xE6D8, 0x71D5, + 0xE6D9, 0xF994, 0xE6DA, 0x784F, 0xE6DB, 0x786F, 0xE6DC, 0xF995, 0xE6DD, 0x7B75, 0xE6DE, 0x7DE3, 0xE6DF, 0xF996, 0xE6E0, 0x7E2F, + 0xE6E1, 0xF997, 0xE6E2, 0x884D, 0xE6E3, 0x8EDF, 0xE6E4, 0xF998, 0xE6E5, 0xF999, 0xE6E6, 0xF99A, 0xE6E7, 0x925B, 0xE6E8, 0xF99B, + 0xE6E9, 0x9CF6, 0xE6EA, 0xF99C, 0xE6EB, 0xF99D, 0xE6EC, 0xF99E, 0xE6ED, 0x6085, 0xE6EE, 0x6D85, 0xE6EF, 0xF99F, 0xE6F0, 0x71B1, + 0xE6F1, 0xF9A0, 0xE6F2, 0xF9A1, 0xE6F3, 0x95B1, 0xE6F4, 0x53AD, 0xE6F5, 0xF9A2, 0xE6F6, 0xF9A3, 0xE6F7, 0xF9A4, 0xE6F8, 0x67D3, + 0xE6F9, 0xF9A5, 0xE6FA, 0x708E, 0xE6FB, 0x7130, 0xE6FC, 0x7430, 0xE6FD, 0x8276, 0xE6FE, 0x82D2, 0xE7A1, 0xF9A6, 0xE7A2, 0x95BB, + 0xE7A3, 0x9AE5, 0xE7A4, 0x9E7D, 0xE7A5, 0x66C4, 0xE7A6, 0xF9A7, 0xE7A7, 0x71C1, 0xE7A8, 0x8449, 0xE7A9, 0xF9A8, 0xE7AA, 0xF9A9, + 0xE7AB, 0x584B, 0xE7AC, 0xF9AA, 0xE7AD, 0xF9AB, 0xE7AE, 0x5DB8, 0xE7AF, 0x5F71, 0xE7B0, 0xF9AC, 0xE7B1, 0x6620, 0xE7B2, 0x668E, + 0xE7B3, 0x6979, 0xE7B4, 0x69AE, 0xE7B5, 0x6C38, 0xE7B6, 0x6CF3, 0xE7B7, 0x6E36, 0xE7B8, 0x6F41, 0xE7B9, 0x6FDA, 0xE7BA, 0x701B, + 0xE7BB, 0x702F, 0xE7BC, 0x7150, 0xE7BD, 0x71DF, 0xE7BE, 0x7370, 0xE7BF, 0xF9AD, 0xE7C0, 0x745B, 0xE7C1, 0xF9AE, 0xE7C2, 0x74D4, + 0xE7C3, 0x76C8, 0xE7C4, 0x7A4E, 0xE7C5, 0x7E93, 0xE7C6, 0xF9AF, 0xE7C7, 0xF9B0, 0xE7C8, 0x82F1, 0xE7C9, 0x8A60, 0xE7CA, 0x8FCE, + 0xE7CB, 0xF9B1, 0xE7CC, 0x9348, 0xE7CD, 0xF9B2, 0xE7CE, 0x9719, 0xE7CF, 0xF9B3, 0xE7D0, 0xF9B4, 0xE7D1, 0x4E42, 0xE7D2, 0x502A, + 0xE7D3, 0xF9B5, 0xE7D4, 0x5208, 0xE7D5, 0x53E1, 0xE7D6, 0x66F3, 0xE7D7, 0x6C6D, 0xE7D8, 0x6FCA, 0xE7D9, 0x730A, 0xE7DA, 0x777F, + 0xE7DB, 0x7A62, 0xE7DC, 0x82AE, 0xE7DD, 0x85DD, 0xE7DE, 0x8602, 0xE7DF, 0xF9B6, 0xE7E0, 0x88D4, 0xE7E1, 0x8A63, 0xE7E2, 0x8B7D, + 0xE7E3, 0x8C6B, 0xE7E4, 0xF9B7, 0xE7E5, 0x92B3, 0xE7E6, 0xF9B8, 0xE7E7, 0x9713, 0xE7E8, 0x9810, 0xE7E9, 0x4E94, 0xE7EA, 0x4F0D, + 0xE7EB, 0x4FC9, 0xE7EC, 0x50B2, 0xE7ED, 0x5348, 0xE7EE, 0x543E, 0xE7EF, 0x5433, 0xE7F0, 0x55DA, 0xE7F1, 0x5862, 0xE7F2, 0x58BA, + 0xE7F3, 0x5967, 0xE7F4, 0x5A1B, 0xE7F5, 0x5BE4, 0xE7F6, 0x609F, 0xE7F7, 0xF9B9, 0xE7F8, 0x61CA, 0xE7F9, 0x6556, 0xE7FA, 0x65FF, + 0xE7FB, 0x6664, 0xE7FC, 0x68A7, 0xE7FD, 0x6C5A, 0xE7FE, 0x6FB3, 0xE8A1, 0x70CF, 0xE8A2, 0x71AC, 0xE8A3, 0x7352, 0xE8A4, 0x7B7D, + 0xE8A5, 0x8708, 0xE8A6, 0x8AA4, 0xE8A7, 0x9C32, 0xE8A8, 0x9F07, 0xE8A9, 0x5C4B, 0xE8AA, 0x6C83, 0xE8AB, 0x7344, 0xE8AC, 0x7389, + 0xE8AD, 0x923A, 0xE8AE, 0x6EAB, 0xE8AF, 0x7465, 0xE8B0, 0x761F, 0xE8B1, 0x7A69, 0xE8B2, 0x7E15, 0xE8B3, 0x860A, 0xE8B4, 0x5140, + 0xE8B5, 0x58C5, 0xE8B6, 0x64C1, 0xE8B7, 0x74EE, 0xE8B8, 0x7515, 0xE8B9, 0x7670, 0xE8BA, 0x7FC1, 0xE8BB, 0x9095, 0xE8BC, 0x96CD, + 0xE8BD, 0x9954, 0xE8BE, 0x6E26, 0xE8BF, 0x74E6, 0xE8C0, 0x7AA9, 0xE8C1, 0x7AAA, 0xE8C2, 0x81E5, 0xE8C3, 0x86D9, 0xE8C4, 0x8778, + 0xE8C5, 0x8A1B, 0xE8C6, 0x5A49, 0xE8C7, 0x5B8C, 0xE8C8, 0x5B9B, 0xE8C9, 0x68A1, 0xE8CA, 0x6900, 0xE8CB, 0x6D63, 0xE8CC, 0x73A9, + 0xE8CD, 0x7413, 0xE8CE, 0x742C, 0xE8CF, 0x7897, 0xE8D0, 0x7DE9, 0xE8D1, 0x7FEB, 0xE8D2, 0x8118, 0xE8D3, 0x8155, 0xE8D4, 0x839E, + 0xE8D5, 0x8C4C, 0xE8D6, 0x962E, 0xE8D7, 0x9811, 0xE8D8, 0x66F0, 0xE8D9, 0x5F80, 0xE8DA, 0x65FA, 0xE8DB, 0x6789, 0xE8DC, 0x6C6A, + 0xE8DD, 0x738B, 0xE8DE, 0x502D, 0xE8DF, 0x5A03, 0xE8E0, 0x6B6A, 0xE8E1, 0x77EE, 0xE8E2, 0x5916, 0xE8E3, 0x5D6C, 0xE8E4, 0x5DCD, + 0xE8E5, 0x7325, 0xE8E6, 0x754F, 0xE8E7, 0xF9BA, 0xE8E8, 0xF9BB, 0xE8E9, 0x50E5, 0xE8EA, 0x51F9, 0xE8EB, 0x582F, 0xE8EC, 0x592D, + 0xE8ED, 0x5996, 0xE8EE, 0x59DA, 0xE8EF, 0x5BE5, 0xE8F0, 0xF9BC, 0xE8F1, 0xF9BD, 0xE8F2, 0x5DA2, 0xE8F3, 0x62D7, 0xE8F4, 0x6416, + 0xE8F5, 0x6493, 0xE8F6, 0x64FE, 0xE8F7, 0xF9BE, 0xE8F8, 0x66DC, 0xE8F9, 0xF9BF, 0xE8FA, 0x6A48, 0xE8FB, 0xF9C0, 0xE8FC, 0x71FF, + 0xE8FD, 0x7464, 0xE8FE, 0xF9C1, 0xE9A1, 0x7A88, 0xE9A2, 0x7AAF, 0xE9A3, 0x7E47, 0xE9A4, 0x7E5E, 0xE9A5, 0x8000, 0xE9A6, 0x8170, + 0xE9A7, 0xF9C2, 0xE9A8, 0x87EF, 0xE9A9, 0x8981, 0xE9AA, 0x8B20, 0xE9AB, 0x9059, 0xE9AC, 0xF9C3, 0xE9AD, 0x9080, 0xE9AE, 0x9952, + 0xE9AF, 0x617E, 0xE9B0, 0x6B32, 0xE9B1, 0x6D74, 0xE9B2, 0x7E1F, 0xE9B3, 0x8925, 0xE9B4, 0x8FB1, 0xE9B5, 0x4FD1, 0xE9B6, 0x50AD, + 0xE9B7, 0x5197, 0xE9B8, 0x52C7, 0xE9B9, 0x57C7, 0xE9BA, 0x5889, 0xE9BB, 0x5BB9, 0xE9BC, 0x5EB8, 0xE9BD, 0x6142, 0xE9BE, 0x6995, + 0xE9BF, 0x6D8C, 0xE9C0, 0x6E67, 0xE9C1, 0x6EB6, 0xE9C2, 0x7194, 0xE9C3, 0x7462, 0xE9C4, 0x7528, 0xE9C5, 0x752C, 0xE9C6, 0x8073, + 0xE9C7, 0x8338, 0xE9C8, 0x84C9, 0xE9C9, 0x8E0A, 0xE9CA, 0x9394, 0xE9CB, 0x93DE, 0xE9CC, 0xF9C4, 0xE9CD, 0x4E8E, 0xE9CE, 0x4F51, + 0xE9CF, 0x5076, 0xE9D0, 0x512A, 0xE9D1, 0x53C8, 0xE9D2, 0x53CB, 0xE9D3, 0x53F3, 0xE9D4, 0x5B87, 0xE9D5, 0x5BD3, 0xE9D6, 0x5C24, + 0xE9D7, 0x611A, 0xE9D8, 0x6182, 0xE9D9, 0x65F4, 0xE9DA, 0x725B, 0xE9DB, 0x7397, 0xE9DC, 0x7440, 0xE9DD, 0x76C2, 0xE9DE, 0x7950, + 0xE9DF, 0x7991, 0xE9E0, 0x79B9, 0xE9E1, 0x7D06, 0xE9E2, 0x7FBD, 0xE9E3, 0x828B, 0xE9E4, 0x85D5, 0xE9E5, 0x865E, 0xE9E6, 0x8FC2, + 0xE9E7, 0x9047, 0xE9E8, 0x90F5, 0xE9E9, 0x91EA, 0xE9EA, 0x9685, 0xE9EB, 0x96E8, 0xE9EC, 0x96E9, 0xE9ED, 0x52D6, 0xE9EE, 0x5F67, + 0xE9EF, 0x65ED, 0xE9F0, 0x6631, 0xE9F1, 0x682F, 0xE9F2, 0x715C, 0xE9F3, 0x7A36, 0xE9F4, 0x90C1, 0xE9F5, 0x980A, 0xE9F6, 0x4E91, + 0xE9F7, 0xF9C5, 0xE9F8, 0x6A52, 0xE9F9, 0x6B9E, 0xE9FA, 0x6F90, 0xE9FB, 0x7189, 0xE9FC, 0x8018, 0xE9FD, 0x82B8, 0xE9FE, 0x8553, + 0xEAA1, 0x904B, 0xEAA2, 0x9695, 0xEAA3, 0x96F2, 0xEAA4, 0x97FB, 0xEAA5, 0x851A, 0xEAA6, 0x9B31, 0xEAA7, 0x4E90, 0xEAA8, 0x718A, + 0xEAA9, 0x96C4, 0xEAAA, 0x5143, 0xEAAB, 0x539F, 0xEAAC, 0x54E1, 0xEAAD, 0x5713, 0xEAAE, 0x5712, 0xEAAF, 0x57A3, 0xEAB0, 0x5A9B, + 0xEAB1, 0x5AC4, 0xEAB2, 0x5BC3, 0xEAB3, 0x6028, 0xEAB4, 0x613F, 0xEAB5, 0x63F4, 0xEAB6, 0x6C85, 0xEAB7, 0x6D39, 0xEAB8, 0x6E72, + 0xEAB9, 0x6E90, 0xEABA, 0x7230, 0xEABB, 0x733F, 0xEABC, 0x7457, 0xEABD, 0x82D1, 0xEABE, 0x8881, 0xEABF, 0x8F45, 0xEAC0, 0x9060, + 0xEAC1, 0xF9C6, 0xEAC2, 0x9662, 0xEAC3, 0x9858, 0xEAC4, 0x9D1B, 0xEAC5, 0x6708, 0xEAC6, 0x8D8A, 0xEAC7, 0x925E, 0xEAC8, 0x4F4D, + 0xEAC9, 0x5049, 0xEACA, 0x50DE, 0xEACB, 0x5371, 0xEACC, 0x570D, 0xEACD, 0x59D4, 0xEACE, 0x5A01, 0xEACF, 0x5C09, 0xEAD0, 0x6170, + 0xEAD1, 0x6690, 0xEAD2, 0x6E2D, 0xEAD3, 0x7232, 0xEAD4, 0x744B, 0xEAD5, 0x7DEF, 0xEAD6, 0x80C3, 0xEAD7, 0x840E, 0xEAD8, 0x8466, + 0xEAD9, 0x853F, 0xEADA, 0x875F, 0xEADB, 0x885B, 0xEADC, 0x8918, 0xEADD, 0x8B02, 0xEADE, 0x9055, 0xEADF, 0x97CB, 0xEAE0, 0x9B4F, + 0xEAE1, 0x4E73, 0xEAE2, 0x4F91, 0xEAE3, 0x5112, 0xEAE4, 0x516A, 0xEAE5, 0xF9C7, 0xEAE6, 0x552F, 0xEAE7, 0x55A9, 0xEAE8, 0x5B7A, + 0xEAE9, 0x5BA5, 0xEAEA, 0x5E7C, 0xEAEB, 0x5E7D, 0xEAEC, 0x5EBE, 0xEAED, 0x60A0, 0xEAEE, 0x60DF, 0xEAEF, 0x6108, 0xEAF0, 0x6109, + 0xEAF1, 0x63C4, 0xEAF2, 0x6538, 0xEAF3, 0x6709, 0xEAF4, 0xF9C8, 0xEAF5, 0x67D4, 0xEAF6, 0x67DA, 0xEAF7, 0xF9C9, 0xEAF8, 0x6961, + 0xEAF9, 0x6962, 0xEAFA, 0x6CB9, 0xEAFB, 0x6D27, 0xEAFC, 0xF9CA, 0xEAFD, 0x6E38, 0xEAFE, 0xF9CB, 0xEBA1, 0x6FE1, 0xEBA2, 0x7336, + 0xEBA3, 0x7337, 0xEBA4, 0xF9CC, 0xEBA5, 0x745C, 0xEBA6, 0x7531, 0xEBA7, 0xF9CD, 0xEBA8, 0x7652, 0xEBA9, 0xF9CE, 0xEBAA, 0xF9CF, + 0xEBAB, 0x7DAD, 0xEBAC, 0x81FE, 0xEBAD, 0x8438, 0xEBAE, 0x88D5, 0xEBAF, 0x8A98, 0xEBB0, 0x8ADB, 0xEBB1, 0x8AED, 0xEBB2, 0x8E30, + 0xEBB3, 0x8E42, 0xEBB4, 0x904A, 0xEBB5, 0x903E, 0xEBB6, 0x907A, 0xEBB7, 0x9149, 0xEBB8, 0x91C9, 0xEBB9, 0x936E, 0xEBBA, 0xF9D0, + 0xEBBB, 0xF9D1, 0xEBBC, 0x5809, 0xEBBD, 0xF9D2, 0xEBBE, 0x6BD3, 0xEBBF, 0x8089, 0xEBC0, 0x80B2, 0xEBC1, 0xF9D3, 0xEBC2, 0xF9D4, + 0xEBC3, 0x5141, 0xEBC4, 0x596B, 0xEBC5, 0x5C39, 0xEBC6, 0xF9D5, 0xEBC7, 0xF9D6, 0xEBC8, 0x6F64, 0xEBC9, 0x73A7, 0xEBCA, 0x80E4, + 0xEBCB, 0x8D07, 0xEBCC, 0xF9D7, 0xEBCD, 0x9217, 0xEBCE, 0x958F, 0xEBCF, 0xF9D8, 0xEBD0, 0xF9D9, 0xEBD1, 0xF9DA, 0xEBD2, 0xF9DB, + 0xEBD3, 0x807F, 0xEBD4, 0x620E, 0xEBD5, 0x701C, 0xEBD6, 0x7D68, 0xEBD7, 0x878D, 0xEBD8, 0xF9DC, 0xEBD9, 0x57A0, 0xEBDA, 0x6069, + 0xEBDB, 0x6147, 0xEBDC, 0x6BB7, 0xEBDD, 0x8ABE, 0xEBDE, 0x9280, 0xEBDF, 0x96B1, 0xEBE0, 0x4E59, 0xEBE1, 0x541F, 0xEBE2, 0x6DEB, + 0xEBE3, 0x852D, 0xEBE4, 0x9670, 0xEBE5, 0x97F3, 0xEBE6, 0x98EE, 0xEBE7, 0x63D6, 0xEBE8, 0x6CE3, 0xEBE9, 0x9091, 0xEBEA, 0x51DD, + 0xEBEB, 0x61C9, 0xEBEC, 0x81BA, 0xEBED, 0x9DF9, 0xEBEE, 0x4F9D, 0xEBEF, 0x501A, 0xEBF0, 0x5100, 0xEBF1, 0x5B9C, 0xEBF2, 0x610F, + 0xEBF3, 0x61FF, 0xEBF4, 0x64EC, 0xEBF5, 0x6905, 0xEBF6, 0x6BC5, 0xEBF7, 0x7591, 0xEBF8, 0x77E3, 0xEBF9, 0x7FA9, 0xEBFA, 0x8264, + 0xEBFB, 0x858F, 0xEBFC, 0x87FB, 0xEBFD, 0x8863, 0xEBFE, 0x8ABC, 0xECA1, 0x8B70, 0xECA2, 0x91AB, 0xECA3, 0x4E8C, 0xECA4, 0x4EE5, + 0xECA5, 0x4F0A, 0xECA6, 0xF9DD, 0xECA7, 0xF9DE, 0xECA8, 0x5937, 0xECA9, 0x59E8, 0xECAA, 0xF9DF, 0xECAB, 0x5DF2, 0xECAC, 0x5F1B, + 0xECAD, 0x5F5B, 0xECAE, 0x6021, 0xECAF, 0xF9E0, 0xECB0, 0xF9E1, 0xECB1, 0xF9E2, 0xECB2, 0xF9E3, 0xECB3, 0x723E, 0xECB4, 0x73E5, + 0xECB5, 0xF9E4, 0xECB6, 0x7570, 0xECB7, 0x75CD, 0xECB8, 0xF9E5, 0xECB9, 0x79FB, 0xECBA, 0xF9E6, 0xECBB, 0x800C, 0xECBC, 0x8033, + 0xECBD, 0x8084, 0xECBE, 0x82E1, 0xECBF, 0x8351, 0xECC0, 0xF9E7, 0xECC1, 0xF9E8, 0xECC2, 0x8CBD, 0xECC3, 0x8CB3, 0xECC4, 0x9087, + 0xECC5, 0xF9E9, 0xECC6, 0xF9EA, 0xECC7, 0x98F4, 0xECC8, 0x990C, 0xECC9, 0xF9EB, 0xECCA, 0xF9EC, 0xECCB, 0x7037, 0xECCC, 0x76CA, + 0xECCD, 0x7FCA, 0xECCE, 0x7FCC, 0xECCF, 0x7FFC, 0xECD0, 0x8B1A, 0xECD1, 0x4EBA, 0xECD2, 0x4EC1, 0xECD3, 0x5203, 0xECD4, 0x5370, + 0xECD5, 0xF9ED, 0xECD6, 0x54BD, 0xECD7, 0x56E0, 0xECD8, 0x59FB, 0xECD9, 0x5BC5, 0xECDA, 0x5F15, 0xECDB, 0x5FCD, 0xECDC, 0x6E6E, + 0xECDD, 0xF9EE, 0xECDE, 0xF9EF, 0xECDF, 0x7D6A, 0xECE0, 0x8335, 0xECE1, 0xF9F0, 0xECE2, 0x8693, 0xECE3, 0x8A8D, 0xECE4, 0xF9F1, + 0xECE5, 0x976D, 0xECE6, 0x9777, 0xECE7, 0xF9F2, 0xECE8, 0xF9F3, 0xECE9, 0x4E00, 0xECEA, 0x4F5A, 0xECEB, 0x4F7E, 0xECEC, 0x58F9, + 0xECED, 0x65E5, 0xECEE, 0x6EA2, 0xECEF, 0x9038, 0xECF0, 0x93B0, 0xECF1, 0x99B9, 0xECF2, 0x4EFB, 0xECF3, 0x58EC, 0xECF4, 0x598A, + 0xECF5, 0x59D9, 0xECF6, 0x6041, 0xECF7, 0xF9F4, 0xECF8, 0xF9F5, 0xECF9, 0x7A14, 0xECFA, 0xF9F6, 0xECFB, 0x834F, 0xECFC, 0x8CC3, + 0xECFD, 0x5165, 0xECFE, 0x5344, 0xEDA1, 0xF9F7, 0xEDA2, 0xF9F8, 0xEDA3, 0xF9F9, 0xEDA4, 0x4ECD, 0xEDA5, 0x5269, 0xEDA6, 0x5B55, + 0xEDA7, 0x82BF, 0xEDA8, 0x4ED4, 0xEDA9, 0x523A, 0xEDAA, 0x54A8, 0xEDAB, 0x59C9, 0xEDAC, 0x59FF, 0xEDAD, 0x5B50, 0xEDAE, 0x5B57, + 0xEDAF, 0x5B5C, 0xEDB0, 0x6063, 0xEDB1, 0x6148, 0xEDB2, 0x6ECB, 0xEDB3, 0x7099, 0xEDB4, 0x716E, 0xEDB5, 0x7386, 0xEDB6, 0x74F7, + 0xEDB7, 0x75B5, 0xEDB8, 0x78C1, 0xEDB9, 0x7D2B, 0xEDBA, 0x8005, 0xEDBB, 0x81EA, 0xEDBC, 0x8328, 0xEDBD, 0x8517, 0xEDBE, 0x85C9, + 0xEDBF, 0x8AEE, 0xEDC0, 0x8CC7, 0xEDC1, 0x96CC, 0xEDC2, 0x4F5C, 0xEDC3, 0x52FA, 0xEDC4, 0x56BC, 0xEDC5, 0x65AB, 0xEDC6, 0x6628, + 0xEDC7, 0x707C, 0xEDC8, 0x70B8, 0xEDC9, 0x7235, 0xEDCA, 0x7DBD, 0xEDCB, 0x828D, 0xEDCC, 0x914C, 0xEDCD, 0x96C0, 0xEDCE, 0x9D72, + 0xEDCF, 0x5B71, 0xEDD0, 0x68E7, 0xEDD1, 0x6B98, 0xEDD2, 0x6F7A, 0xEDD3, 0x76DE, 0xEDD4, 0x5C91, 0xEDD5, 0x66AB, 0xEDD6, 0x6F5B, + 0xEDD7, 0x7BB4, 0xEDD8, 0x7C2A, 0xEDD9, 0x8836, 0xEDDA, 0x96DC, 0xEDDB, 0x4E08, 0xEDDC, 0x4ED7, 0xEDDD, 0x5320, 0xEDDE, 0x5834, + 0xEDDF, 0x58BB, 0xEDE0, 0x58EF, 0xEDE1, 0x596C, 0xEDE2, 0x5C07, 0xEDE3, 0x5E33, 0xEDE4, 0x5E84, 0xEDE5, 0x5F35, 0xEDE6, 0x638C, + 0xEDE7, 0x66B2, 0xEDE8, 0x6756, 0xEDE9, 0x6A1F, 0xEDEA, 0x6AA3, 0xEDEB, 0x6B0C, 0xEDEC, 0x6F3F, 0xEDED, 0x7246, 0xEDEE, 0xF9FA, + 0xEDEF, 0x7350, 0xEDF0, 0x748B, 0xEDF1, 0x7AE0, 0xEDF2, 0x7CA7, 0xEDF3, 0x8178, 0xEDF4, 0x81DF, 0xEDF5, 0x81E7, 0xEDF6, 0x838A, + 0xEDF7, 0x846C, 0xEDF8, 0x8523, 0xEDF9, 0x8594, 0xEDFA, 0x85CF, 0xEDFB, 0x88DD, 0xEDFC, 0x8D13, 0xEDFD, 0x91AC, 0xEDFE, 0x9577, + 0xEEA1, 0x969C, 0xEEA2, 0x518D, 0xEEA3, 0x54C9, 0xEEA4, 0x5728, 0xEEA5, 0x5BB0, 0xEEA6, 0x624D, 0xEEA7, 0x6750, 0xEEA8, 0x683D, + 0xEEA9, 0x6893, 0xEEAA, 0x6E3D, 0xEEAB, 0x6ED3, 0xEEAC, 0x707D, 0xEEAD, 0x7E21, 0xEEAE, 0x88C1, 0xEEAF, 0x8CA1, 0xEEB0, 0x8F09, + 0xEEB1, 0x9F4B, 0xEEB2, 0x9F4E, 0xEEB3, 0x722D, 0xEEB4, 0x7B8F, 0xEEB5, 0x8ACD, 0xEEB6, 0x931A, 0xEEB7, 0x4F47, 0xEEB8, 0x4F4E, + 0xEEB9, 0x5132, 0xEEBA, 0x5480, 0xEEBB, 0x59D0, 0xEEBC, 0x5E95, 0xEEBD, 0x62B5, 0xEEBE, 0x6775, 0xEEBF, 0x696E, 0xEEC0, 0x6A17, + 0xEEC1, 0x6CAE, 0xEEC2, 0x6E1A, 0xEEC3, 0x72D9, 0xEEC4, 0x732A, 0xEEC5, 0x75BD, 0xEEC6, 0x7BB8, 0xEEC7, 0x7D35, 0xEEC8, 0x82E7, + 0xEEC9, 0x83F9, 0xEECA, 0x8457, 0xEECB, 0x85F7, 0xEECC, 0x8A5B, 0xEECD, 0x8CAF, 0xEECE, 0x8E87, 0xEECF, 0x9019, 0xEED0, 0x90B8, + 0xEED1, 0x96CE, 0xEED2, 0x9F5F, 0xEED3, 0x52E3, 0xEED4, 0x540A, 0xEED5, 0x5AE1, 0xEED6, 0x5BC2, 0xEED7, 0x6458, 0xEED8, 0x6575, + 0xEED9, 0x6EF4, 0xEEDA, 0x72C4, 0xEEDB, 0xF9FB, 0xEEDC, 0x7684, 0xEEDD, 0x7A4D, 0xEEDE, 0x7B1B, 0xEEDF, 0x7C4D, 0xEEE0, 0x7E3E, + 0xEEE1, 0x7FDF, 0xEEE2, 0x837B, 0xEEE3, 0x8B2B, 0xEEE4, 0x8CCA, 0xEEE5, 0x8D64, 0xEEE6, 0x8DE1, 0xEEE7, 0x8E5F, 0xEEE8, 0x8FEA, + 0xEEE9, 0x8FF9, 0xEEEA, 0x9069, 0xEEEB, 0x93D1, 0xEEEC, 0x4F43, 0xEEED, 0x4F7A, 0xEEEE, 0x50B3, 0xEEEF, 0x5168, 0xEEF0, 0x5178, + 0xEEF1, 0x524D, 0xEEF2, 0x526A, 0xEEF3, 0x5861, 0xEEF4, 0x587C, 0xEEF5, 0x5960, 0xEEF6, 0x5C08, 0xEEF7, 0x5C55, 0xEEF8, 0x5EDB, + 0xEEF9, 0x609B, 0xEEFA, 0x6230, 0xEEFB, 0x6813, 0xEEFC, 0x6BBF, 0xEEFD, 0x6C08, 0xEEFE, 0x6FB1, 0xEFA1, 0x714E, 0xEFA2, 0x7420, + 0xEFA3, 0x7530, 0xEFA4, 0x7538, 0xEFA5, 0x7551, 0xEFA6, 0x7672, 0xEFA7, 0x7B4C, 0xEFA8, 0x7B8B, 0xEFA9, 0x7BAD, 0xEFAA, 0x7BC6, + 0xEFAB, 0x7E8F, 0xEFAC, 0x8A6E, 0xEFAD, 0x8F3E, 0xEFAE, 0x8F49, 0xEFAF, 0x923F, 0xEFB0, 0x9293, 0xEFB1, 0x9322, 0xEFB2, 0x942B, + 0xEFB3, 0x96FB, 0xEFB4, 0x985A, 0xEFB5, 0x986B, 0xEFB6, 0x991E, 0xEFB7, 0x5207, 0xEFB8, 0x622A, 0xEFB9, 0x6298, 0xEFBA, 0x6D59, + 0xEFBB, 0x7664, 0xEFBC, 0x7ACA, 0xEFBD, 0x7BC0, 0xEFBE, 0x7D76, 0xEFBF, 0x5360, 0xEFC0, 0x5CBE, 0xEFC1, 0x5E97, 0xEFC2, 0x6F38, + 0xEFC3, 0x70B9, 0xEFC4, 0x7C98, 0xEFC5, 0x9711, 0xEFC6, 0x9B8E, 0xEFC7, 0x9EDE, 0xEFC8, 0x63A5, 0xEFC9, 0x647A, 0xEFCA, 0x8776, + 0xEFCB, 0x4E01, 0xEFCC, 0x4E95, 0xEFCD, 0x4EAD, 0xEFCE, 0x505C, 0xEFCF, 0x5075, 0xEFD0, 0x5448, 0xEFD1, 0x59C3, 0xEFD2, 0x5B9A, + 0xEFD3, 0x5E40, 0xEFD4, 0x5EAD, 0xEFD5, 0x5EF7, 0xEFD6, 0x5F81, 0xEFD7, 0x60C5, 0xEFD8, 0x633A, 0xEFD9, 0x653F, 0xEFDA, 0x6574, + 0xEFDB, 0x65CC, 0xEFDC, 0x6676, 0xEFDD, 0x6678, 0xEFDE, 0x67FE, 0xEFDF, 0x6968, 0xEFE0, 0x6A89, 0xEFE1, 0x6B63, 0xEFE2, 0x6C40, + 0xEFE3, 0x6DC0, 0xEFE4, 0x6DE8, 0xEFE5, 0x6E1F, 0xEFE6, 0x6E5E, 0xEFE7, 0x701E, 0xEFE8, 0x70A1, 0xEFE9, 0x738E, 0xEFEA, 0x73FD, + 0xEFEB, 0x753A, 0xEFEC, 0x775B, 0xEFED, 0x7887, 0xEFEE, 0x798E, 0xEFEF, 0x7A0B, 0xEFF0, 0x7A7D, 0xEFF1, 0x7CBE, 0xEFF2, 0x7D8E, + 0xEFF3, 0x8247, 0xEFF4, 0x8A02, 0xEFF5, 0x8AEA, 0xEFF6, 0x8C9E, 0xEFF7, 0x912D, 0xEFF8, 0x914A, 0xEFF9, 0x91D8, 0xEFFA, 0x9266, + 0xEFFB, 0x92CC, 0xEFFC, 0x9320, 0xEFFD, 0x9706, 0xEFFE, 0x9756, 0xF0A1, 0x975C, 0xF0A2, 0x9802, 0xF0A3, 0x9F0E, 0xF0A4, 0x5236, + 0xF0A5, 0x5291, 0xF0A6, 0x557C, 0xF0A7, 0x5824, 0xF0A8, 0x5E1D, 0xF0A9, 0x5F1F, 0xF0AA, 0x608C, 0xF0AB, 0x63D0, 0xF0AC, 0x68AF, + 0xF0AD, 0x6FDF, 0xF0AE, 0x796D, 0xF0AF, 0x7B2C, 0xF0B0, 0x81CD, 0xF0B1, 0x85BA, 0xF0B2, 0x88FD, 0xF0B3, 0x8AF8, 0xF0B4, 0x8E44, + 0xF0B5, 0x918D, 0xF0B6, 0x9664, 0xF0B7, 0x969B, 0xF0B8, 0x973D, 0xF0B9, 0x984C, 0xF0BA, 0x9F4A, 0xF0BB, 0x4FCE, 0xF0BC, 0x5146, + 0xF0BD, 0x51CB, 0xF0BE, 0x52A9, 0xF0BF, 0x5632, 0xF0C0, 0x5F14, 0xF0C1, 0x5F6B, 0xF0C2, 0x63AA, 0xF0C3, 0x64CD, 0xF0C4, 0x65E9, + 0xF0C5, 0x6641, 0xF0C6, 0x66FA, 0xF0C7, 0x66F9, 0xF0C8, 0x671D, 0xF0C9, 0x689D, 0xF0CA, 0x68D7, 0xF0CB, 0x69FD, 0xF0CC, 0x6F15, + 0xF0CD, 0x6F6E, 0xF0CE, 0x7167, 0xF0CF, 0x71E5, 0xF0D0, 0x722A, 0xF0D1, 0x74AA, 0xF0D2, 0x773A, 0xF0D3, 0x7956, 0xF0D4, 0x795A, + 0xF0D5, 0x79DF, 0xF0D6, 0x7A20, 0xF0D7, 0x7A95, 0xF0D8, 0x7C97, 0xF0D9, 0x7CDF, 0xF0DA, 0x7D44, 0xF0DB, 0x7E70, 0xF0DC, 0x8087, + 0xF0DD, 0x85FB, 0xF0DE, 0x86A4, 0xF0DF, 0x8A54, 0xF0E0, 0x8ABF, 0xF0E1, 0x8D99, 0xF0E2, 0x8E81, 0xF0E3, 0x9020, 0xF0E4, 0x906D, + 0xF0E5, 0x91E3, 0xF0E6, 0x963B, 0xF0E7, 0x96D5, 0xF0E8, 0x9CE5, 0xF0E9, 0x65CF, 0xF0EA, 0x7C07, 0xF0EB, 0x8DB3, 0xF0EC, 0x93C3, + 0xF0ED, 0x5B58, 0xF0EE, 0x5C0A, 0xF0EF, 0x5352, 0xF0F0, 0x62D9, 0xF0F1, 0x731D, 0xF0F2, 0x5027, 0xF0F3, 0x5B97, 0xF0F4, 0x5F9E, + 0xF0F5, 0x60B0, 0xF0F6, 0x616B, 0xF0F7, 0x68D5, 0xF0F8, 0x6DD9, 0xF0F9, 0x742E, 0xF0FA, 0x7A2E, 0xF0FB, 0x7D42, 0xF0FC, 0x7D9C, + 0xF0FD, 0x7E31, 0xF0FE, 0x816B, 0xF1A1, 0x8E2A, 0xF1A2, 0x8E35, 0xF1A3, 0x937E, 0xF1A4, 0x9418, 0xF1A5, 0x4F50, 0xF1A6, 0x5750, + 0xF1A7, 0x5DE6, 0xF1A8, 0x5EA7, 0xF1A9, 0x632B, 0xF1AA, 0x7F6A, 0xF1AB, 0x4E3B, 0xF1AC, 0x4F4F, 0xF1AD, 0x4F8F, 0xF1AE, 0x505A, + 0xF1AF, 0x59DD, 0xF1B0, 0x80C4, 0xF1B1, 0x546A, 0xF1B2, 0x5468, 0xF1B3, 0x55FE, 0xF1B4, 0x594F, 0xF1B5, 0x5B99, 0xF1B6, 0x5DDE, + 0xF1B7, 0x5EDA, 0xF1B8, 0x665D, 0xF1B9, 0x6731, 0xF1BA, 0x67F1, 0xF1BB, 0x682A, 0xF1BC, 0x6CE8, 0xF1BD, 0x6D32, 0xF1BE, 0x6E4A, + 0xF1BF, 0x6F8D, 0xF1C0, 0x70B7, 0xF1C1, 0x73E0, 0xF1C2, 0x7587, 0xF1C3, 0x7C4C, 0xF1C4, 0x7D02, 0xF1C5, 0x7D2C, 0xF1C6, 0x7DA2, + 0xF1C7, 0x821F, 0xF1C8, 0x86DB, 0xF1C9, 0x8A3B, 0xF1CA, 0x8A85, 0xF1CB, 0x8D70, 0xF1CC, 0x8E8A, 0xF1CD, 0x8F33, 0xF1CE, 0x9031, + 0xF1CF, 0x914E, 0xF1D0, 0x9152, 0xF1D1, 0x9444, 0xF1D2, 0x99D0, 0xF1D3, 0x7AF9, 0xF1D4, 0x7CA5, 0xF1D5, 0x4FCA, 0xF1D6, 0x5101, + 0xF1D7, 0x51C6, 0xF1D8, 0x57C8, 0xF1D9, 0x5BEF, 0xF1DA, 0x5CFB, 0xF1DB, 0x6659, 0xF1DC, 0x6A3D, 0xF1DD, 0x6D5A, 0xF1DE, 0x6E96, + 0xF1DF, 0x6FEC, 0xF1E0, 0x710C, 0xF1E1, 0x756F, 0xF1E2, 0x7AE3, 0xF1E3, 0x8822, 0xF1E4, 0x9021, 0xF1E5, 0x9075, 0xF1E6, 0x96CB, + 0xF1E7, 0x99FF, 0xF1E8, 0x8301, 0xF1E9, 0x4E2D, 0xF1EA, 0x4EF2, 0xF1EB, 0x8846, 0xF1EC, 0x91CD, 0xF1ED, 0x537D, 0xF1EE, 0x6ADB, + 0xF1EF, 0x696B, 0xF1F0, 0x6C41, 0xF1F1, 0x847A, 0xF1F2, 0x589E, 0xF1F3, 0x618E, 0xF1F4, 0x66FE, 0xF1F5, 0x62EF, 0xF1F6, 0x70DD, + 0xF1F7, 0x7511, 0xF1F8, 0x75C7, 0xF1F9, 0x7E52, 0xF1FA, 0x84B8, 0xF1FB, 0x8B49, 0xF1FC, 0x8D08, 0xF1FD, 0x4E4B, 0xF1FE, 0x53EA, + 0xF2A1, 0x54AB, 0xF2A2, 0x5730, 0xF2A3, 0x5740, 0xF2A4, 0x5FD7, 0xF2A5, 0x6301, 0xF2A6, 0x6307, 0xF2A7, 0x646F, 0xF2A8, 0x652F, + 0xF2A9, 0x65E8, 0xF2AA, 0x667A, 0xF2AB, 0x679D, 0xF2AC, 0x67B3, 0xF2AD, 0x6B62, 0xF2AE, 0x6C60, 0xF2AF, 0x6C9A, 0xF2B0, 0x6F2C, + 0xF2B1, 0x77E5, 0xF2B2, 0x7825, 0xF2B3, 0x7949, 0xF2B4, 0x7957, 0xF2B5, 0x7D19, 0xF2B6, 0x80A2, 0xF2B7, 0x8102, 0xF2B8, 0x81F3, + 0xF2B9, 0x829D, 0xF2BA, 0x82B7, 0xF2BB, 0x8718, 0xF2BC, 0x8A8C, 0xF2BD, 0xF9FC, 0xF2BE, 0x8D04, 0xF2BF, 0x8DBE, 0xF2C0, 0x9072, + 0xF2C1, 0x76F4, 0xF2C2, 0x7A19, 0xF2C3, 0x7A37, 0xF2C4, 0x7E54, 0xF2C5, 0x8077, 0xF2C6, 0x5507, 0xF2C7, 0x55D4, 0xF2C8, 0x5875, + 0xF2C9, 0x632F, 0xF2CA, 0x6422, 0xF2CB, 0x6649, 0xF2CC, 0x664B, 0xF2CD, 0x686D, 0xF2CE, 0x699B, 0xF2CF, 0x6B84, 0xF2D0, 0x6D25, + 0xF2D1, 0x6EB1, 0xF2D2, 0x73CD, 0xF2D3, 0x7468, 0xF2D4, 0x74A1, 0xF2D5, 0x755B, 0xF2D6, 0x75B9, 0xF2D7, 0x76E1, 0xF2D8, 0x771E, + 0xF2D9, 0x778B, 0xF2DA, 0x79E6, 0xF2DB, 0x7E09, 0xF2DC, 0x7E1D, 0xF2DD, 0x81FB, 0xF2DE, 0x852F, 0xF2DF, 0x8897, 0xF2E0, 0x8A3A, + 0xF2E1, 0x8CD1, 0xF2E2, 0x8EEB, 0xF2E3, 0x8FB0, 0xF2E4, 0x9032, 0xF2E5, 0x93AD, 0xF2E6, 0x9663, 0xF2E7, 0x9673, 0xF2E8, 0x9707, + 0xF2E9, 0x4F84, 0xF2EA, 0x53F1, 0xF2EB, 0x59EA, 0xF2EC, 0x5AC9, 0xF2ED, 0x5E19, 0xF2EE, 0x684E, 0xF2EF, 0x74C6, 0xF2F0, 0x75BE, + 0xF2F1, 0x79E9, 0xF2F2, 0x7A92, 0xF2F3, 0x81A3, 0xF2F4, 0x86ED, 0xF2F5, 0x8CEA, 0xF2F6, 0x8DCC, 0xF2F7, 0x8FED, 0xF2F8, 0x659F, + 0xF2F9, 0x6715, 0xF2FA, 0xF9FD, 0xF2FB, 0x57F7, 0xF2FC, 0x6F57, 0xF2FD, 0x7DDD, 0xF2FE, 0x8F2F, 0xF3A1, 0x93F6, 0xF3A2, 0x96C6, + 0xF3A3, 0x5FB5, 0xF3A4, 0x61F2, 0xF3A5, 0x6F84, 0xF3A6, 0x4E14, 0xF3A7, 0x4F98, 0xF3A8, 0x501F, 0xF3A9, 0x53C9, 0xF3AA, 0x55DF, + 0xF3AB, 0x5D6F, 0xF3AC, 0x5DEE, 0xF3AD, 0x6B21, 0xF3AE, 0x6B64, 0xF3AF, 0x78CB, 0xF3B0, 0x7B9A, 0xF3B1, 0xF9FE, 0xF3B2, 0x8E49, + 0xF3B3, 0x8ECA, 0xF3B4, 0x906E, 0xF3B5, 0x6349, 0xF3B6, 0x643E, 0xF3B7, 0x7740, 0xF3B8, 0x7A84, 0xF3B9, 0x932F, 0xF3BA, 0x947F, + 0xF3BB, 0x9F6A, 0xF3BC, 0x64B0, 0xF3BD, 0x6FAF, 0xF3BE, 0x71E6, 0xF3BF, 0x74A8, 0xF3C0, 0x74DA, 0xF3C1, 0x7AC4, 0xF3C2, 0x7C12, + 0xF3C3, 0x7E82, 0xF3C4, 0x7CB2, 0xF3C5, 0x7E98, 0xF3C6, 0x8B9A, 0xF3C7, 0x8D0A, 0xF3C8, 0x947D, 0xF3C9, 0x9910, 0xF3CA, 0x994C, + 0xF3CB, 0x5239, 0xF3CC, 0x5BDF, 0xF3CD, 0x64E6, 0xF3CE, 0x672D, 0xF3CF, 0x7D2E, 0xF3D0, 0x50ED, 0xF3D1, 0x53C3, 0xF3D2, 0x5879, + 0xF3D3, 0x6158, 0xF3D4, 0x6159, 0xF3D5, 0x61FA, 0xF3D6, 0x65AC, 0xF3D7, 0x7AD9, 0xF3D8, 0x8B92, 0xF3D9, 0x8B96, 0xF3DA, 0x5009, + 0xF3DB, 0x5021, 0xF3DC, 0x5275, 0xF3DD, 0x5531, 0xF3DE, 0x5A3C, 0xF3DF, 0x5EE0, 0xF3E0, 0x5F70, 0xF3E1, 0x6134, 0xF3E2, 0x655E, + 0xF3E3, 0x660C, 0xF3E4, 0x6636, 0xF3E5, 0x66A2, 0xF3E6, 0x69CD, 0xF3E7, 0x6EC4, 0xF3E8, 0x6F32, 0xF3E9, 0x7316, 0xF3EA, 0x7621, + 0xF3EB, 0x7A93, 0xF3EC, 0x8139, 0xF3ED, 0x8259, 0xF3EE, 0x83D6, 0xF3EF, 0x84BC, 0xF3F0, 0x50B5, 0xF3F1, 0x57F0, 0xF3F2, 0x5BC0, + 0xF3F3, 0x5BE8, 0xF3F4, 0x5F69, 0xF3F5, 0x63A1, 0xF3F6, 0x7826, 0xF3F7, 0x7DB5, 0xF3F8, 0x83DC, 0xF3F9, 0x8521, 0xF3FA, 0x91C7, + 0xF3FB, 0x91F5, 0xF3FC, 0x518A, 0xF3FD, 0x67F5, 0xF3FE, 0x7B56, 0xF4A1, 0x8CAC, 0xF4A2, 0x51C4, 0xF4A3, 0x59BB, 0xF4A4, 0x60BD, + 0xF4A5, 0x8655, 0xF4A6, 0x501C, 0xF4A7, 0xF9FF, 0xF4A8, 0x5254, 0xF4A9, 0x5C3A, 0xF4AA, 0x617D, 0xF4AB, 0x621A, 0xF4AC, 0x62D3, + 0xF4AD, 0x64F2, 0xF4AE, 0x65A5, 0xF4AF, 0x6ECC, 0xF4B0, 0x7620, 0xF4B1, 0x810A, 0xF4B2, 0x8E60, 0xF4B3, 0x965F, 0xF4B4, 0x96BB, + 0xF4B5, 0x4EDF, 0xF4B6, 0x5343, 0xF4B7, 0x5598, 0xF4B8, 0x5929, 0xF4B9, 0x5DDD, 0xF4BA, 0x64C5, 0xF4BB, 0x6CC9, 0xF4BC, 0x6DFA, + 0xF4BD, 0x7394, 0xF4BE, 0x7A7F, 0xF4BF, 0x821B, 0xF4C0, 0x85A6, 0xF4C1, 0x8CE4, 0xF4C2, 0x8E10, 0xF4C3, 0x9077, 0xF4C4, 0x91E7, + 0xF4C5, 0x95E1, 0xF4C6, 0x9621, 0xF4C7, 0x97C6, 0xF4C8, 0x51F8, 0xF4C9, 0x54F2, 0xF4CA, 0x5586, 0xF4CB, 0x5FB9, 0xF4CC, 0x64A4, + 0xF4CD, 0x6F88, 0xF4CE, 0x7DB4, 0xF4CF, 0x8F1F, 0xF4D0, 0x8F4D, 0xF4D1, 0x9435, 0xF4D2, 0x50C9, 0xF4D3, 0x5C16, 0xF4D4, 0x6CBE, + 0xF4D5, 0x6DFB, 0xF4D6, 0x751B, 0xF4D7, 0x77BB, 0xF4D8, 0x7C3D, 0xF4D9, 0x7C64, 0xF4DA, 0x8A79, 0xF4DB, 0x8AC2, 0xF4DC, 0x581E, + 0xF4DD, 0x59BE, 0xF4DE, 0x5E16, 0xF4DF, 0x6377, 0xF4E0, 0x7252, 0xF4E1, 0x758A, 0xF4E2, 0x776B, 0xF4E3, 0x8ADC, 0xF4E4, 0x8CBC, + 0xF4E5, 0x8F12, 0xF4E6, 0x5EF3, 0xF4E7, 0x6674, 0xF4E8, 0x6DF8, 0xF4E9, 0x807D, 0xF4EA, 0x83C1, 0xF4EB, 0x8ACB, 0xF4EC, 0x9751, + 0xF4ED, 0x9BD6, 0xF4EE, 0xFA00, 0xF4EF, 0x5243, 0xF4F0, 0x66FF, 0xF4F1, 0x6D95, 0xF4F2, 0x6EEF, 0xF4F3, 0x7DE0, 0xF4F4, 0x8AE6, + 0xF4F5, 0x902E, 0xF4F6, 0x905E, 0xF4F7, 0x9AD4, 0xF4F8, 0x521D, 0xF4F9, 0x527F, 0xF4FA, 0x54E8, 0xF4FB, 0x6194, 0xF4FC, 0x6284, + 0xF4FD, 0x62DB, 0xF4FE, 0x68A2, 0xF5A1, 0x6912, 0xF5A2, 0x695A, 0xF5A3, 0x6A35, 0xF5A4, 0x7092, 0xF5A5, 0x7126, 0xF5A6, 0x785D, + 0xF5A7, 0x7901, 0xF5A8, 0x790E, 0xF5A9, 0x79D2, 0xF5AA, 0x7A0D, 0xF5AB, 0x8096, 0xF5AC, 0x8278, 0xF5AD, 0x82D5, 0xF5AE, 0x8349, + 0xF5AF, 0x8549, 0xF5B0, 0x8C82, 0xF5B1, 0x8D85, 0xF5B2, 0x9162, 0xF5B3, 0x918B, 0xF5B4, 0x91AE, 0xF5B5, 0x4FC3, 0xF5B6, 0x56D1, + 0xF5B7, 0x71ED, 0xF5B8, 0x77D7, 0xF5B9, 0x8700, 0xF5BA, 0x89F8, 0xF5BB, 0x5BF8, 0xF5BC, 0x5FD6, 0xF5BD, 0x6751, 0xF5BE, 0x90A8, + 0xF5BF, 0x53E2, 0xF5C0, 0x585A, 0xF5C1, 0x5BF5, 0xF5C2, 0x60A4, 0xF5C3, 0x6181, 0xF5C4, 0x6460, 0xF5C5, 0x7E3D, 0xF5C6, 0x8070, + 0xF5C7, 0x8525, 0xF5C8, 0x9283, 0xF5C9, 0x64AE, 0xF5CA, 0x50AC, 0xF5CB, 0x5D14, 0xF5CC, 0x6700, 0xF5CD, 0x589C, 0xF5CE, 0x62BD, + 0xF5CF, 0x63A8, 0xF5D0, 0x690E, 0xF5D1, 0x6978, 0xF5D2, 0x6A1E, 0xF5D3, 0x6E6B, 0xF5D4, 0x76BA, 0xF5D5, 0x79CB, 0xF5D6, 0x82BB, + 0xF5D7, 0x8429, 0xF5D8, 0x8ACF, 0xF5D9, 0x8DA8, 0xF5DA, 0x8FFD, 0xF5DB, 0x9112, 0xF5DC, 0x914B, 0xF5DD, 0x919C, 0xF5DE, 0x9310, + 0xF5DF, 0x9318, 0xF5E0, 0x939A, 0xF5E1, 0x96DB, 0xF5E2, 0x9A36, 0xF5E3, 0x9C0D, 0xF5E4, 0x4E11, 0xF5E5, 0x755C, 0xF5E6, 0x795D, + 0xF5E7, 0x7AFA, 0xF5E8, 0x7B51, 0xF5E9, 0x7BC9, 0xF5EA, 0x7E2E, 0xF5EB, 0x84C4, 0xF5EC, 0x8E59, 0xF5ED, 0x8E74, 0xF5EE, 0x8EF8, + 0xF5EF, 0x9010, 0xF5F0, 0x6625, 0xF5F1, 0x693F, 0xF5F2, 0x7443, 0xF5F3, 0x51FA, 0xF5F4, 0x672E, 0xF5F5, 0x9EDC, 0xF5F6, 0x5145, + 0xF5F7, 0x5FE0, 0xF5F8, 0x6C96, 0xF5F9, 0x87F2, 0xF5FA, 0x885D, 0xF5FB, 0x8877, 0xF5FC, 0x60B4, 0xF5FD, 0x81B5, 0xF5FE, 0x8403, + 0xF6A1, 0x8D05, 0xF6A2, 0x53D6, 0xF6A3, 0x5439, 0xF6A4, 0x5634, 0xF6A5, 0x5A36, 0xF6A6, 0x5C31, 0xF6A7, 0x708A, 0xF6A8, 0x7FE0, + 0xF6A9, 0x805A, 0xF6AA, 0x8106, 0xF6AB, 0x81ED, 0xF6AC, 0x8DA3, 0xF6AD, 0x9189, 0xF6AE, 0x9A5F, 0xF6AF, 0x9DF2, 0xF6B0, 0x5074, + 0xF6B1, 0x4EC4, 0xF6B2, 0x53A0, 0xF6B3, 0x60FB, 0xF6B4, 0x6E2C, 0xF6B5, 0x5C64, 0xF6B6, 0x4F88, 0xF6B7, 0x5024, 0xF6B8, 0x55E4, + 0xF6B9, 0x5CD9, 0xF6BA, 0x5E5F, 0xF6BB, 0x6065, 0xF6BC, 0x6894, 0xF6BD, 0x6CBB, 0xF6BE, 0x6DC4, 0xF6BF, 0x71BE, 0xF6C0, 0x75D4, + 0xF6C1, 0x75F4, 0xF6C2, 0x7661, 0xF6C3, 0x7A1A, 0xF6C4, 0x7A49, 0xF6C5, 0x7DC7, 0xF6C6, 0x7DFB, 0xF6C7, 0x7F6E, 0xF6C8, 0x81F4, + 0xF6C9, 0x86A9, 0xF6CA, 0x8F1C, 0xF6CB, 0x96C9, 0xF6CC, 0x99B3, 0xF6CD, 0x9F52, 0xF6CE, 0x5247, 0xF6CF, 0x52C5, 0xF6D0, 0x98ED, + 0xF6D1, 0x89AA, 0xF6D2, 0x4E03, 0xF6D3, 0x67D2, 0xF6D4, 0x6F06, 0xF6D5, 0x4FB5, 0xF6D6, 0x5BE2, 0xF6D7, 0x6795, 0xF6D8, 0x6C88, + 0xF6D9, 0x6D78, 0xF6DA, 0x741B, 0xF6DB, 0x7827, 0xF6DC, 0x91DD, 0xF6DD, 0x937C, 0xF6DE, 0x87C4, 0xF6DF, 0x79E4, 0xF6E0, 0x7A31, + 0xF6E1, 0x5FEB, 0xF6E2, 0x4ED6, 0xF6E3, 0x54A4, 0xF6E4, 0x553E, 0xF6E5, 0x58AE, 0xF6E6, 0x59A5, 0xF6E7, 0x60F0, 0xF6E8, 0x6253, + 0xF6E9, 0x62D6, 0xF6EA, 0x6736, 0xF6EB, 0x6955, 0xF6EC, 0x8235, 0xF6ED, 0x9640, 0xF6EE, 0x99B1, 0xF6EF, 0x99DD, 0xF6F0, 0x502C, + 0xF6F1, 0x5353, 0xF6F2, 0x5544, 0xF6F3, 0x577C, 0xF6F4, 0xFA01, 0xF6F5, 0x6258, 0xF6F6, 0xFA02, 0xF6F7, 0x64E2, 0xF6F8, 0x666B, + 0xF6F9, 0x67DD, 0xF6FA, 0x6FC1, 0xF6FB, 0x6FEF, 0xF6FC, 0x7422, 0xF6FD, 0x7438, 0xF6FE, 0x8A17, 0xF7A1, 0x9438, 0xF7A2, 0x5451, + 0xF7A3, 0x5606, 0xF7A4, 0x5766, 0xF7A5, 0x5F48, 0xF7A6, 0x619A, 0xF7A7, 0x6B4E, 0xF7A8, 0x7058, 0xF7A9, 0x70AD, 0xF7AA, 0x7DBB, + 0xF7AB, 0x8A95, 0xF7AC, 0x596A, 0xF7AD, 0x812B, 0xF7AE, 0x63A2, 0xF7AF, 0x7708, 0xF7B0, 0x803D, 0xF7B1, 0x8CAA, 0xF7B2, 0x5854, + 0xF7B3, 0x642D, 0xF7B4, 0x69BB, 0xF7B5, 0x5B95, 0xF7B6, 0x5E11, 0xF7B7, 0x6E6F, 0xF7B8, 0xFA03, 0xF7B9, 0x8569, 0xF7BA, 0x514C, + 0xF7BB, 0x53F0, 0xF7BC, 0x592A, 0xF7BD, 0x6020, 0xF7BE, 0x614B, 0xF7BF, 0x6B86, 0xF7C0, 0x6C70, 0xF7C1, 0x6CF0, 0xF7C2, 0x7B1E, + 0xF7C3, 0x80CE, 0xF7C4, 0x82D4, 0xF7C5, 0x8DC6, 0xF7C6, 0x90B0, 0xF7C7, 0x98B1, 0xF7C8, 0xFA04, 0xF7C9, 0x64C7, 0xF7CA, 0x6FA4, + 0xF7CB, 0x6491, 0xF7CC, 0x6504, 0xF7CD, 0x514E, 0xF7CE, 0x5410, 0xF7CF, 0x571F, 0xF7D0, 0x8A0E, 0xF7D1, 0x615F, 0xF7D2, 0x6876, + 0xF7D3, 0xFA05, 0xF7D4, 0x75DB, 0xF7D5, 0x7B52, 0xF7D6, 0x7D71, 0xF7D7, 0x901A, 0xF7D8, 0x5806, 0xF7D9, 0x69CC, 0xF7DA, 0x817F, + 0xF7DB, 0x892A, 0xF7DC, 0x9000, 0xF7DD, 0x9839, 0xF7DE, 0x5078, 0xF7DF, 0x5957, 0xF7E0, 0x59AC, 0xF7E1, 0x6295, 0xF7E2, 0x900F, + 0xF7E3, 0x9B2A, 0xF7E4, 0x615D, 0xF7E5, 0x7279, 0xF7E6, 0x95D6, 0xF7E7, 0x5761, 0xF7E8, 0x5A46, 0xF7E9, 0x5DF4, 0xF7EA, 0x628A, + 0xF7EB, 0x64AD, 0xF7EC, 0x64FA, 0xF7ED, 0x6777, 0xF7EE, 0x6CE2, 0xF7EF, 0x6D3E, 0xF7F0, 0x722C, 0xF7F1, 0x7436, 0xF7F2, 0x7834, + 0xF7F3, 0x7F77, 0xF7F4, 0x82AD, 0xF7F5, 0x8DDB, 0xF7F6, 0x9817, 0xF7F7, 0x5224, 0xF7F8, 0x5742, 0xF7F9, 0x677F, 0xF7FA, 0x7248, + 0xF7FB, 0x74E3, 0xF7FC, 0x8CA9, 0xF7FD, 0x8FA6, 0xF7FE, 0x9211, 0xF8A1, 0x962A, 0xF8A2, 0x516B, 0xF8A3, 0x53ED, 0xF8A4, 0x634C, + 0xF8A5, 0x4F69, 0xF8A6, 0x5504, 0xF8A7, 0x6096, 0xF8A8, 0x6557, 0xF8A9, 0x6C9B, 0xF8AA, 0x6D7F, 0xF8AB, 0x724C, 0xF8AC, 0x72FD, + 0xF8AD, 0x7A17, 0xF8AE, 0x8987, 0xF8AF, 0x8C9D, 0xF8B0, 0x5F6D, 0xF8B1, 0x6F8E, 0xF8B2, 0x70F9, 0xF8B3, 0x81A8, 0xF8B4, 0x610E, + 0xF8B5, 0x4FBF, 0xF8B6, 0x504F, 0xF8B7, 0x6241, 0xF8B8, 0x7247, 0xF8B9, 0x7BC7, 0xF8BA, 0x7DE8, 0xF8BB, 0x7FE9, 0xF8BC, 0x904D, + 0xF8BD, 0x97AD, 0xF8BE, 0x9A19, 0xF8BF, 0x8CB6, 0xF8C0, 0x576A, 0xF8C1, 0x5E73, 0xF8C2, 0x67B0, 0xF8C3, 0x840D, 0xF8C4, 0x8A55, + 0xF8C5, 0x5420, 0xF8C6, 0x5B16, 0xF8C7, 0x5E63, 0xF8C8, 0x5EE2, 0xF8C9, 0x5F0A, 0xF8CA, 0x6583, 0xF8CB, 0x80BA, 0xF8CC, 0x853D, + 0xF8CD, 0x9589, 0xF8CE, 0x965B, 0xF8CF, 0x4F48, 0xF8D0, 0x5305, 0xF8D1, 0x530D, 0xF8D2, 0x530F, 0xF8D3, 0x5486, 0xF8D4, 0x54FA, + 0xF8D5, 0x5703, 0xF8D6, 0x5E03, 0xF8D7, 0x6016, 0xF8D8, 0x629B, 0xF8D9, 0x62B1, 0xF8DA, 0x6355, 0xF8DB, 0xFA06, 0xF8DC, 0x6CE1, + 0xF8DD, 0x6D66, 0xF8DE, 0x75B1, 0xF8DF, 0x7832, 0xF8E0, 0x80DE, 0xF8E1, 0x812F, 0xF8E2, 0x82DE, 0xF8E3, 0x8461, 0xF8E4, 0x84B2, + 0xF8E5, 0x888D, 0xF8E6, 0x8912, 0xF8E7, 0x900B, 0xF8E8, 0x92EA, 0xF8E9, 0x98FD, 0xF8EA, 0x9B91, 0xF8EB, 0x5E45, 0xF8EC, 0x66B4, + 0xF8ED, 0x66DD, 0xF8EE, 0x7011, 0xF8EF, 0x7206, 0xF8F0, 0xFA07, 0xF8F1, 0x4FF5, 0xF8F2, 0x527D, 0xF8F3, 0x5F6A, 0xF8F4, 0x6153, + 0xF8F5, 0x6753, 0xF8F6, 0x6A19, 0xF8F7, 0x6F02, 0xF8F8, 0x74E2, 0xF8F9, 0x7968, 0xF8FA, 0x8868, 0xF8FB, 0x8C79, 0xF8FC, 0x98C7, + 0xF8FD, 0x98C4, 0xF8FE, 0x9A43, 0xF9A1, 0x54C1, 0xF9A2, 0x7A1F, 0xF9A3, 0x6953, 0xF9A4, 0x8AF7, 0xF9A5, 0x8C4A, 0xF9A6, 0x98A8, + 0xF9A7, 0x99AE, 0xF9A8, 0x5F7C, 0xF9A9, 0x62AB, 0xF9AA, 0x75B2, 0xF9AB, 0x76AE, 0xF9AC, 0x88AB, 0xF9AD, 0x907F, 0xF9AE, 0x9642, + 0xF9AF, 0x5339, 0xF9B0, 0x5F3C, 0xF9B1, 0x5FC5, 0xF9B2, 0x6CCC, 0xF9B3, 0x73CC, 0xF9B4, 0x7562, 0xF9B5, 0x758B, 0xF9B6, 0x7B46, + 0xF9B7, 0x82FE, 0xF9B8, 0x999D, 0xF9B9, 0x4E4F, 0xF9BA, 0x903C, 0xF9BB, 0x4E0B, 0xF9BC, 0x4F55, 0xF9BD, 0x53A6, 0xF9BE, 0x590F, + 0xF9BF, 0x5EC8, 0xF9C0, 0x6630, 0xF9C1, 0x6CB3, 0xF9C2, 0x7455, 0xF9C3, 0x8377, 0xF9C4, 0x8766, 0xF9C5, 0x8CC0, 0xF9C6, 0x9050, + 0xF9C7, 0x971E, 0xF9C8, 0x9C15, 0xF9C9, 0x58D1, 0xF9CA, 0x5B78, 0xF9CB, 0x8650, 0xF9CC, 0x8B14, 0xF9CD, 0x9DB4, 0xF9CE, 0x5BD2, + 0xF9CF, 0x6068, 0xF9D0, 0x608D, 0xF9D1, 0x65F1, 0xF9D2, 0x6C57, 0xF9D3, 0x6F22, 0xF9D4, 0x6FA3, 0xF9D5, 0x701A, 0xF9D6, 0x7F55, + 0xF9D7, 0x7FF0, 0xF9D8, 0x9591, 0xF9D9, 0x9592, 0xF9DA, 0x9650, 0xF9DB, 0x97D3, 0xF9DC, 0x5272, 0xF9DD, 0x8F44, 0xF9DE, 0x51FD, + 0xF9DF, 0x542B, 0xF9E0, 0x54B8, 0xF9E1, 0x5563, 0xF9E2, 0x558A, 0xF9E3, 0x6ABB, 0xF9E4, 0x6DB5, 0xF9E5, 0x7DD8, 0xF9E6, 0x8266, + 0xF9E7, 0x929C, 0xF9E8, 0x9677, 0xF9E9, 0x9E79, 0xF9EA, 0x5408, 0xF9EB, 0x54C8, 0xF9EC, 0x76D2, 0xF9ED, 0x86E4, 0xF9EE, 0x95A4, + 0xF9EF, 0x95D4, 0xF9F0, 0x965C, 0xF9F1, 0x4EA2, 0xF9F2, 0x4F09, 0xF9F3, 0x59EE, 0xF9F4, 0x5AE6, 0xF9F5, 0x5DF7, 0xF9F6, 0x6052, + 0xF9F7, 0x6297, 0xF9F8, 0x676D, 0xF9F9, 0x6841, 0xF9FA, 0x6C86, 0xF9FB, 0x6E2F, 0xF9FC, 0x7F38, 0xF9FD, 0x809B, 0xF9FE, 0x822A, + 0xFAA1, 0xFA08, 0xFAA2, 0xFA09, 0xFAA3, 0x9805, 0xFAA4, 0x4EA5, 0xFAA5, 0x5055, 0xFAA6, 0x54B3, 0xFAA7, 0x5793, 0xFAA8, 0x595A, + 0xFAA9, 0x5B69, 0xFAAA, 0x5BB3, 0xFAAB, 0x61C8, 0xFAAC, 0x6977, 0xFAAD, 0x6D77, 0xFAAE, 0x7023, 0xFAAF, 0x87F9, 0xFAB0, 0x89E3, + 0xFAB1, 0x8A72, 0xFAB2, 0x8AE7, 0xFAB3, 0x9082, 0xFAB4, 0x99ED, 0xFAB5, 0x9AB8, 0xFAB6, 0x52BE, 0xFAB7, 0x6838, 0xFAB8, 0x5016, + 0xFAB9, 0x5E78, 0xFABA, 0x674F, 0xFABB, 0x8347, 0xFABC, 0x884C, 0xFABD, 0x4EAB, 0xFABE, 0x5411, 0xFABF, 0x56AE, 0xFAC0, 0x73E6, + 0xFAC1, 0x9115, 0xFAC2, 0x97FF, 0xFAC3, 0x9909, 0xFAC4, 0x9957, 0xFAC5, 0x9999, 0xFAC6, 0x5653, 0xFAC7, 0x589F, 0xFAC8, 0x865B, + 0xFAC9, 0x8A31, 0xFACA, 0x61B2, 0xFACB, 0x6AF6, 0xFACC, 0x737B, 0xFACD, 0x8ED2, 0xFACE, 0x6B47, 0xFACF, 0x96AA, 0xFAD0, 0x9A57, + 0xFAD1, 0x5955, 0xFAD2, 0x7200, 0xFAD3, 0x8D6B, 0xFAD4, 0x9769, 0xFAD5, 0x4FD4, 0xFAD6, 0x5CF4, 0xFAD7, 0x5F26, 0xFAD8, 0x61F8, + 0xFAD9, 0x665B, 0xFADA, 0x6CEB, 0xFADB, 0x70AB, 0xFADC, 0x7384, 0xFADD, 0x73B9, 0xFADE, 0x73FE, 0xFADF, 0x7729, 0xFAE0, 0x774D, + 0xFAE1, 0x7D43, 0xFAE2, 0x7D62, 0xFAE3, 0x7E23, 0xFAE4, 0x8237, 0xFAE5, 0x8852, 0xFAE6, 0xFA0A, 0xFAE7, 0x8CE2, 0xFAE8, 0x9249, + 0xFAE9, 0x986F, 0xFAEA, 0x5B51, 0xFAEB, 0x7A74, 0xFAEC, 0x8840, 0xFAED, 0x9801, 0xFAEE, 0x5ACC, 0xFAEF, 0x4FE0, 0xFAF0, 0x5354, + 0xFAF1, 0x593E, 0xFAF2, 0x5CFD, 0xFAF3, 0x633E, 0xFAF4, 0x6D79, 0xFAF5, 0x72F9, 0xFAF6, 0x8105, 0xFAF7, 0x8107, 0xFAF8, 0x83A2, + 0xFAF9, 0x92CF, 0xFAFA, 0x9830, 0xFAFB, 0x4EA8, 0xFAFC, 0x5144, 0xFAFD, 0x5211, 0xFAFE, 0x578B, 0xFBA1, 0x5F62, 0xFBA2, 0x6CC2, + 0xFBA3, 0x6ECE, 0xFBA4, 0x7005, 0xFBA5, 0x7050, 0xFBA6, 0x70AF, 0xFBA7, 0x7192, 0xFBA8, 0x73E9, 0xFBA9, 0x7469, 0xFBAA, 0x834A, + 0xFBAB, 0x87A2, 0xFBAC, 0x8861, 0xFBAD, 0x9008, 0xFBAE, 0x90A2, 0xFBAF, 0x93A3, 0xFBB0, 0x99A8, 0xFBB1, 0x516E, 0xFBB2, 0x5F57, + 0xFBB3, 0x60E0, 0xFBB4, 0x6167, 0xFBB5, 0x66B3, 0xFBB6, 0x8559, 0xFBB7, 0x8E4A, 0xFBB8, 0x91AF, 0xFBB9, 0x978B, 0xFBBA, 0x4E4E, + 0xFBBB, 0x4E92, 0xFBBC, 0x547C, 0xFBBD, 0x58D5, 0xFBBE, 0x58FA, 0xFBBF, 0x597D, 0xFBC0, 0x5CB5, 0xFBC1, 0x5F27, 0xFBC2, 0x6236, + 0xFBC3, 0x6248, 0xFBC4, 0x660A, 0xFBC5, 0x6667, 0xFBC6, 0x6BEB, 0xFBC7, 0x6D69, 0xFBC8, 0x6DCF, 0xFBC9, 0x6E56, 0xFBCA, 0x6EF8, + 0xFBCB, 0x6F94, 0xFBCC, 0x6FE0, 0xFBCD, 0x6FE9, 0xFBCE, 0x705D, 0xFBCF, 0x72D0, 0xFBD0, 0x7425, 0xFBD1, 0x745A, 0xFBD2, 0x74E0, + 0xFBD3, 0x7693, 0xFBD4, 0x795C, 0xFBD5, 0x7CCA, 0xFBD6, 0x7E1E, 0xFBD7, 0x80E1, 0xFBD8, 0x82A6, 0xFBD9, 0x846B, 0xFBDA, 0x84BF, + 0xFBDB, 0x864E, 0xFBDC, 0x865F, 0xFBDD, 0x8774, 0xFBDE, 0x8B77, 0xFBDF, 0x8C6A, 0xFBE0, 0x93AC, 0xFBE1, 0x9800, 0xFBE2, 0x9865, + 0xFBE3, 0x60D1, 0xFBE4, 0x6216, 0xFBE5, 0x9177, 0xFBE6, 0x5A5A, 0xFBE7, 0x660F, 0xFBE8, 0x6DF7, 0xFBE9, 0x6E3E, 0xFBEA, 0x743F, + 0xFBEB, 0x9B42, 0xFBEC, 0x5FFD, 0xFBED, 0x60DA, 0xFBEE, 0x7B0F, 0xFBEF, 0x54C4, 0xFBF0, 0x5F18, 0xFBF1, 0x6C5E, 0xFBF2, 0x6CD3, + 0xFBF3, 0x6D2A, 0xFBF4, 0x70D8, 0xFBF5, 0x7D05, 0xFBF6, 0x8679, 0xFBF7, 0x8A0C, 0xFBF8, 0x9D3B, 0xFBF9, 0x5316, 0xFBFA, 0x548C, + 0xFBFB, 0x5B05, 0xFBFC, 0x6A3A, 0xFBFD, 0x706B, 0xFBFE, 0x7575, 0xFCA1, 0x798D, 0xFCA2, 0x79BE, 0xFCA3, 0x82B1, 0xFCA4, 0x83EF, + 0xFCA5, 0x8A71, 0xFCA6, 0x8B41, 0xFCA7, 0x8CA8, 0xFCA8, 0x9774, 0xFCA9, 0xFA0B, 0xFCAA, 0x64F4, 0xFCAB, 0x652B, 0xFCAC, 0x78BA, + 0xFCAD, 0x78BB, 0xFCAE, 0x7A6B, 0xFCAF, 0x4E38, 0xFCB0, 0x559A, 0xFCB1, 0x5950, 0xFCB2, 0x5BA6, 0xFCB3, 0x5E7B, 0xFCB4, 0x60A3, + 0xFCB5, 0x63DB, 0xFCB6, 0x6B61, 0xFCB7, 0x6665, 0xFCB8, 0x6853, 0xFCB9, 0x6E19, 0xFCBA, 0x7165, 0xFCBB, 0x74B0, 0xFCBC, 0x7D08, + 0xFCBD, 0x9084, 0xFCBE, 0x9A69, 0xFCBF, 0x9C25, 0xFCC0, 0x6D3B, 0xFCC1, 0x6ED1, 0xFCC2, 0x733E, 0xFCC3, 0x8C41, 0xFCC4, 0x95CA, + 0xFCC5, 0x51F0, 0xFCC6, 0x5E4C, 0xFCC7, 0x5FA8, 0xFCC8, 0x604D, 0xFCC9, 0x60F6, 0xFCCA, 0x6130, 0xFCCB, 0x614C, 0xFCCC, 0x6643, + 0xFCCD, 0x6644, 0xFCCE, 0x69A5, 0xFCCF, 0x6CC1, 0xFCD0, 0x6E5F, 0xFCD1, 0x6EC9, 0xFCD2, 0x6F62, 0xFCD3, 0x714C, 0xFCD4, 0x749C, + 0xFCD5, 0x7687, 0xFCD6, 0x7BC1, 0xFCD7, 0x7C27, 0xFCD8, 0x8352, 0xFCD9, 0x8757, 0xFCDA, 0x9051, 0xFCDB, 0x968D, 0xFCDC, 0x9EC3, + 0xFCDD, 0x532F, 0xFCDE, 0x56DE, 0xFCDF, 0x5EFB, 0xFCE0, 0x5F8A, 0xFCE1, 0x6062, 0xFCE2, 0x6094, 0xFCE3, 0x61F7, 0xFCE4, 0x6666, + 0xFCE5, 0x6703, 0xFCE6, 0x6A9C, 0xFCE7, 0x6DEE, 0xFCE8, 0x6FAE, 0xFCE9, 0x7070, 0xFCEA, 0x736A, 0xFCEB, 0x7E6A, 0xFCEC, 0x81BE, + 0xFCED, 0x8334, 0xFCEE, 0x86D4, 0xFCEF, 0x8AA8, 0xFCF0, 0x8CC4, 0xFCF1, 0x5283, 0xFCF2, 0x7372, 0xFCF3, 0x5B96, 0xFCF4, 0x6A6B, + 0xFCF5, 0x9404, 0xFCF6, 0x54EE, 0xFCF7, 0x5686, 0xFCF8, 0x5B5D, 0xFCF9, 0x6548, 0xFCFA, 0x6585, 0xFCFB, 0x66C9, 0xFCFC, 0x689F, + 0xFCFD, 0x6D8D, 0xFCFE, 0x6DC6, 0xFDA1, 0x723B, 0xFDA2, 0x80B4, 0xFDA3, 0x9175, 0xFDA4, 0x9A4D, 0xFDA5, 0x4FAF, 0xFDA6, 0x5019, + 0xFDA7, 0x539A, 0xFDA8, 0x540E, 0xFDA9, 0x543C, 0xFDAA, 0x5589, 0xFDAB, 0x55C5, 0xFDAC, 0x5E3F, 0xFDAD, 0x5F8C, 0xFDAE, 0x673D, + 0xFDAF, 0x7166, 0xFDB0, 0x73DD, 0xFDB1, 0x9005, 0xFDB2, 0x52DB, 0xFDB3, 0x52F3, 0xFDB4, 0x5864, 0xFDB5, 0x58CE, 0xFDB6, 0x7104, + 0xFDB7, 0x718F, 0xFDB8, 0x71FB, 0xFDB9, 0x85B0, 0xFDBA, 0x8A13, 0xFDBB, 0x6688, 0xFDBC, 0x85A8, 0xFDBD, 0x55A7, 0xFDBE, 0x6684, + 0xFDBF, 0x714A, 0xFDC0, 0x8431, 0xFDC1, 0x5349, 0xFDC2, 0x5599, 0xFDC3, 0x6BC1, 0xFDC4, 0x5F59, 0xFDC5, 0x5FBD, 0xFDC6, 0x63EE, + 0xFDC7, 0x6689, 0xFDC8, 0x7147, 0xFDC9, 0x8AF1, 0xFDCA, 0x8F1D, 0xFDCB, 0x9EBE, 0xFDCC, 0x4F11, 0xFDCD, 0x643A, 0xFDCE, 0x70CB, + 0xFDCF, 0x7566, 0xFDD0, 0x8667, 0xFDD1, 0x6064, 0xFDD2, 0x8B4E, 0xFDD3, 0x9DF8, 0xFDD4, 0x5147, 0xFDD5, 0x51F6, 0xFDD6, 0x5308, + 0xFDD7, 0x6D36, 0xFDD8, 0x80F8, 0xFDD9, 0x9ED1, 0xFDDA, 0x6615, 0xFDDB, 0x6B23, 0xFDDC, 0x7098, 0xFDDD, 0x75D5, 0xFDDE, 0x5403, + 0xFDDF, 0x5C79, 0xFDE0, 0x7D07, 0xFDE1, 0x8A16, 0xFDE2, 0x6B20, 0xFDE3, 0x6B3D, 0xFDE4, 0x6B46, 0xFDE5, 0x5438, 0xFDE6, 0x6070, + 0xFDE7, 0x6D3D, 0xFDE8, 0x7FD5, 0xFDE9, 0x8208, 0xFDEA, 0x50D6, 0xFDEB, 0x51DE, 0xFDEC, 0x559C, 0xFDED, 0x566B, 0xFDEE, 0x56CD, + 0xFDEF, 0x59EC, 0xFDF0, 0x5B09, 0xFDF1, 0x5E0C, 0xFDF2, 0x6199, 0xFDF3, 0x6198, 0xFDF4, 0x6231, 0xFDF5, 0x665E, 0xFDF6, 0x66E6, + 0xFDF7, 0x7199, 0xFDF8, 0x71B9, 0xFDF9, 0x71BA, 0xFDFA, 0x72A7, 0xFDFB, 0x79A7, 0xFDFC, 0x7A00, 0xFDFD, 0x7FB2, 0xFDFE, 0x8A70, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */ +static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ + 0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE, + 0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346, + 0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E, + 0x039C, 0xA34F, 0x039D, 0xA350, 0x039E, 0xA351, 0x039F, 0xA352, 0x03A0, 0xA353, 0x03A1, 0xA354, 0x03A3, 0xA355, 0x03A4, 0xA356, + 0x03A5, 0xA357, 0x03A6, 0xA358, 0x03A7, 0xA359, 0x03A8, 0xA35A, 0x03A9, 0xA35B, 0x03B1, 0xA35C, 0x03B2, 0xA35D, 0x03B3, 0xA35E, + 0x03B4, 0xA35F, 0x03B5, 0xA360, 0x03B6, 0xA361, 0x03B7, 0xA362, 0x03B8, 0xA363, 0x03B9, 0xA364, 0x03BA, 0xA365, 0x03BB, 0xA366, + 0x03BC, 0xA367, 0x03BD, 0xA368, 0x03BE, 0xA369, 0x03BF, 0xA36A, 0x03C0, 0xA36B, 0x03C1, 0xA36C, 0x03C3, 0xA36D, 0x03C4, 0xA36E, + 0x03C5, 0xA36F, 0x03C6, 0xA370, 0x03C7, 0xA371, 0x03C8, 0xA372, 0x03C9, 0xA373, 0x2013, 0xA156, 0x2014, 0xA158, 0x2018, 0xA1A5, + 0x2019, 0xA1A6, 0x201C, 0xA1A7, 0x201D, 0xA1A8, 0x2025, 0xA14C, 0x2026, 0xA14B, 0x2027, 0xA145, 0x2032, 0xA1AC, 0x2035, 0xA1AB, + 0x203B, 0xA1B0, 0x20AC, 0xA3E1, 0x2103, 0xA24A, 0x2105, 0xA1C1, 0x2109, 0xA24B, 0x2160, 0xA2B9, 0x2161, 0xA2BA, 0x2162, 0xA2BB, + 0x2163, 0xA2BC, 0x2164, 0xA2BD, 0x2165, 0xA2BE, 0x2166, 0xA2BF, 0x2167, 0xA2C0, 0x2168, 0xA2C1, 0x2169, 0xA2C2, 0x2190, 0xA1F6, + 0x2191, 0xA1F4, 0x2192, 0xA1F7, 0x2193, 0xA1F5, 0x2196, 0xA1F8, 0x2197, 0xA1F9, 0x2198, 0xA1FB, 0x2199, 0xA1FA, 0x2215, 0xA241, + 0x221A, 0xA1D4, 0x221E, 0xA1DB, 0x221F, 0xA1E8, 0x2220, 0xA1E7, 0x2223, 0xA1FD, 0x2225, 0xA1FC, 0x2229, 0xA1E4, 0x222A, 0xA1E5, + 0x222B, 0xA1EC, 0x222E, 0xA1ED, 0x2234, 0xA1EF, 0x2235, 0xA1EE, 0x2252, 0xA1DC, 0x2260, 0xA1DA, 0x2261, 0xA1DD, 0x2266, 0xA1D8, + 0x2267, 0xA1D9, 0x2295, 0xA1F2, 0x2299, 0xA1F3, 0x22A5, 0xA1E6, 0x22BF, 0xA1E9, 0x2500, 0xA277, 0x2502, 0xA278, 0x250C, 0xA27A, + 0x2510, 0xA27B, 0x2514, 0xA27C, 0x2518, 0xA27D, 0x251C, 0xA275, 0x2524, 0xA274, 0x252C, 0xA273, 0x2534, 0xA272, 0x253C, 0xA271, + 0x2550, 0xA2A4, 0x2550, 0xF9F9, 0x2551, 0xF9F8, 0x2552, 0xF9E6, 0x2553, 0xF9EF, 0x2554, 0xF9DD, 0x2555, 0xF9E8, 0x2556, 0xF9F1, + 0x2557, 0xF9DF, 0x2558, 0xF9EC, 0x2559, 0xF9F5, 0x255A, 0xF9E3, 0x255B, 0xF9EE, 0x255C, 0xF9F7, 0x255D, 0xF9E5, 0x255E, 0xA2A5, + 0x255E, 0xF9E9, 0x255F, 0xF9F2, 0x2560, 0xF9E0, 0x2561, 0xA2A7, 0x2561, 0xF9EB, 0x2562, 0xF9F4, 0x2563, 0xF9E2, 0x2564, 0xF9E7, + 0x2565, 0xF9F0, 0x2566, 0xF9DE, 0x2567, 0xF9ED, 0x2568, 0xF9F6, 0x2569, 0xF9E4, 0x256A, 0xA2A6, 0x256A, 0xF9EA, 0x256B, 0xF9F3, + 0x256C, 0xF9E1, 0x256D, 0xA27E, 0x256D, 0xF9FA, 0x256E, 0xA2A1, 0x256E, 0xF9FB, 0x256F, 0xA2A3, 0x256F, 0xF9FD, 0x2570, 0xA2A2, + 0x2570, 0xF9FC, 0x2571, 0xA2AC, 0x2572, 0xA2AD, 0x2573, 0xA2AE, 0x2574, 0xA15A, 0x2581, 0xA262, 0x2582, 0xA263, 0x2583, 0xA264, + 0x2584, 0xA265, 0x2585, 0xA266, 0x2586, 0xA267, 0x2587, 0xA268, 0x2588, 0xA269, 0x2589, 0xA270, 0x258A, 0xA26F, 0x258B, 0xA26E, + 0x258C, 0xA26D, 0x258D, 0xA26C, 0x258E, 0xA26B, 0x258F, 0xA26A, 0x2593, 0xF9FE, 0x2594, 0xA276, 0x2595, 0xA279, 0x25A0, 0xA1BD, + 0x25A1, 0xA1BC, 0x25B2, 0xA1B6, 0x25B3, 0xA1B5, 0x25BC, 0xA1BF, 0x25BD, 0xA1BE, 0x25C6, 0xA1BB, 0x25C7, 0xA1BA, 0x25CB, 0xA1B3, + 0x25CE, 0xA1B7, 0x25CF, 0xA1B4, 0x25E2, 0xA2A8, 0x25E3, 0xA2A9, 0x25E4, 0xA2AB, 0x25E5, 0xA2AA, 0x2605, 0xA1B9, 0x2606, 0xA1B8, + 0x2640, 0xA1F0, 0x2642, 0xA1F1, 0x3000, 0xA140, 0x3001, 0xA142, 0x3002, 0xA143, 0x3003, 0xA1B2, 0x3008, 0xA171, 0x3009, 0xA172, + 0x300A, 0xA16D, 0x300B, 0xA16E, 0x300C, 0xA175, 0x300D, 0xA176, 0x300E, 0xA179, 0x300F, 0xA17A, 0x3010, 0xA169, 0x3011, 0xA16A, + 0x3012, 0xA245, 0x3014, 0xA165, 0x3015, 0xA166, 0x301D, 0xA1A9, 0x301E, 0xA1AA, 0x3021, 0xA2C3, 0x3022, 0xA2C4, 0x3023, 0xA2C5, + 0x3024, 0xA2C6, 0x3025, 0xA2C7, 0x3026, 0xA2C8, 0x3027, 0xA2C9, 0x3028, 0xA2CA, 0x3029, 0xA2CB, 0x3105, 0xA374, 0x3106, 0xA375, + 0x3107, 0xA376, 0x3108, 0xA377, 0x3109, 0xA378, 0x310A, 0xA379, 0x310B, 0xA37A, 0x310C, 0xA37B, 0x310D, 0xA37C, 0x310E, 0xA37D, + 0x310F, 0xA37E, 0x3110, 0xA3A1, 0x3111, 0xA3A2, 0x3112, 0xA3A3, 0x3113, 0xA3A4, 0x3114, 0xA3A5, 0x3115, 0xA3A6, 0x3116, 0xA3A7, + 0x3117, 0xA3A8, 0x3118, 0xA3A9, 0x3119, 0xA3AA, 0x311A, 0xA3AB, 0x311B, 0xA3AC, 0x311C, 0xA3AD, 0x311D, 0xA3AE, 0x311E, 0xA3AF, + 0x311F, 0xA3B0, 0x3120, 0xA3B1, 0x3121, 0xA3B2, 0x3122, 0xA3B3, 0x3123, 0xA3B4, 0x3124, 0xA3B5, 0x3125, 0xA3B6, 0x3126, 0xA3B7, + 0x3127, 0xA3B8, 0x3128, 0xA3B9, 0x3129, 0xA3BA, 0x32A3, 0xA1C0, 0x338E, 0xA255, 0x338F, 0xA256, 0x339C, 0xA250, 0x339D, 0xA251, + 0x339E, 0xA252, 0x33A1, 0xA254, 0x33C4, 0xA257, 0x33CE, 0xA253, 0x33D1, 0xA1EB, 0x33D2, 0xA1EA, 0x33D5, 0xA24F, 0x4E00, 0xA440, + 0x4E01, 0xA442, 0x4E03, 0xA443, 0x4E07, 0xC945, 0x4E08, 0xA456, 0x4E09, 0xA454, 0x4E0A, 0xA457, 0x4E0B, 0xA455, 0x4E0C, 0xC946, + 0x4E0D, 0xA4A3, 0x4E0E, 0xC94F, 0x4E0F, 0xC94D, 0x4E10, 0xA4A2, 0x4E11, 0xA4A1, 0x4E14, 0xA542, 0x4E15, 0xA541, 0x4E16, 0xA540, + 0x4E18, 0xA543, 0x4E19, 0xA4FE, 0x4E1E, 0xA5E0, 0x4E1F, 0xA5E1, 0x4E26, 0xA8C3, 0x4E2B, 0xA458, 0x4E2D, 0xA4A4, 0x4E2E, 0xC950, + 0x4E30, 0xA4A5, 0x4E31, 0xC963, 0x4E32, 0xA6EA, 0x4E33, 0xCBB1, 0x4E38, 0xA459, 0x4E39, 0xA4A6, 0x4E3B, 0xA544, 0x4E3C, 0xC964, + 0x4E42, 0xC940, 0x4E43, 0xA444, 0x4E45, 0xA45B, 0x4E47, 0xC947, 0x4E48, 0xA45C, 0x4E4B, 0xA4A7, 0x4E4D, 0xA545, 0x4E4E, 0xA547, + 0x4E4F, 0xA546, 0x4E52, 0xA5E2, 0x4E53, 0xA5E3, 0x4E56, 0xA8C4, 0x4E58, 0xADBC, 0x4E59, 0xA441, 0x4E5C, 0xC941, 0x4E5D, 0xA445, + 0x4E5E, 0xA45E, 0x4E5F, 0xA45D, 0x4E69, 0xA5E4, 0x4E73, 0xA8C5, 0x4E7E, 0xB0AE, 0x4E7F, 0xD44B, 0x4E82, 0xB6C3, 0x4E83, 0xDCB1, + 0x4E84, 0xDCB2, 0x4E86, 0xA446, 0x4E88, 0xA4A9, 0x4E8B, 0xA8C6, 0x4E8C, 0xA447, 0x4E8D, 0xC948, 0x4E8E, 0xA45F, 0x4E91, 0xA4AA, + 0x4E92, 0xA4AC, 0x4E93, 0xC951, 0x4E94, 0xA4AD, 0x4E95, 0xA4AB, 0x4E99, 0xA5E5, 0x4E9B, 0xA8C7, 0x4E9E, 0xA8C8, 0x4E9F, 0xAB45, + 0x4EA1, 0xA460, 0x4EA2, 0xA4AE, 0x4EA4, 0xA5E6, 0x4EA5, 0xA5E8, 0x4EA6, 0xA5E7, 0x4EA8, 0xA6EB, 0x4EAB, 0xA8C9, 0x4EAC, 0xA8CA, + 0x4EAD, 0xAB46, 0x4EAE, 0xAB47, 0x4EB3, 0xADBD, 0x4EB6, 0xDCB3, 0x4EB9, 0xF6D6, 0x4EBA, 0xA448, 0x4EC0, 0xA4B0, 0x4EC1, 0xA4AF, + 0x4EC2, 0xC952, 0x4EC3, 0xA4B1, 0x4EC4, 0xA4B7, 0x4EC6, 0xA4B2, 0x4EC7, 0xA4B3, 0x4EC8, 0xC954, 0x4EC9, 0xC953, 0x4ECA, 0xA4B5, + 0x4ECB, 0xA4B6, 0x4ECD, 0xA4B4, 0x4ED4, 0xA54A, 0x4ED5, 0xA54B, 0x4ED6, 0xA54C, 0x4ED7, 0xA54D, 0x4ED8, 0xA549, 0x4ED9, 0xA550, + 0x4EDA, 0xC96A, 0x4EDC, 0xC966, 0x4EDD, 0xC969, 0x4EDE, 0xA551, 0x4EDF, 0xA561, 0x4EE1, 0xC968, 0x4EE3, 0xA54E, 0x4EE4, 0xA54F, + 0x4EE5, 0xA548, 0x4EE8, 0xC965, 0x4EE9, 0xC967, 0x4EF0, 0xA5F5, 0x4EF1, 0xC9B0, 0x4EF2, 0xA5F2, 0x4EF3, 0xA5F6, 0x4EF4, 0xC9BA, + 0x4EF5, 0xC9AE, 0x4EF6, 0xA5F3, 0x4EF7, 0xC9B2, 0x4EFB, 0xA5F4, 0x4EFD, 0xA5F7, 0x4EFF, 0xA5E9, 0x4F00, 0xC9B1, 0x4F01, 0xA5F8, + 0x4F02, 0xC9B5, 0x4F04, 0xC9B9, 0x4F05, 0xC9B6, 0x4F08, 0xC9B3, 0x4F09, 0xA5EA, 0x4F0A, 0xA5EC, 0x4F0B, 0xA5F9, 0x4F0D, 0xA5EE, + 0x4F0E, 0xC9AB, 0x4F0F, 0xA5F1, 0x4F10, 0xA5EF, 0x4F11, 0xA5F0, 0x4F12, 0xC9BB, 0x4F13, 0xC9B8, 0x4F14, 0xC9AF, 0x4F15, 0xA5ED, + 0x4F18, 0xC9AC, 0x4F19, 0xA5EB, 0x4F1D, 0xC9B4, 0x4F22, 0xC9B7, 0x4F2C, 0xC9AD, 0x4F2D, 0xCA66, 0x4F2F, 0xA742, 0x4F30, 0xA6F4, + 0x4F33, 0xCA67, 0x4F34, 0xA6F1, 0x4F36, 0xA744, 0x4F38, 0xA6F9, 0x4F3A, 0xA6F8, 0x4F3B, 0xCA5B, 0x4F3C, 0xA6FC, 0x4F3D, 0xA6F7, + 0x4F3E, 0xCA60, 0x4F3F, 0xCA68, 0x4F41, 0xCA64, 0x4F43, 0xA6FA, 0x4F46, 0xA6FD, 0x4F47, 0xA6EE, 0x4F48, 0xA747, 0x4F49, 0xCA5D, + 0x4F4C, 0xCBBD, 0x4F4D, 0xA6EC, 0x4F4E, 0xA743, 0x4F4F, 0xA6ED, 0x4F50, 0xA6F5, 0x4F51, 0xA6F6, 0x4F52, 0xCA62, 0x4F53, 0xCA5E, + 0x4F54, 0xA6FB, 0x4F55, 0xA6F3, 0x4F56, 0xCA5A, 0x4F57, 0xA6EF, 0x4F58, 0xCA65, 0x4F59, 0xA745, 0x4F5A, 0xA748, 0x4F5B, 0xA6F2, + 0x4F5C, 0xA740, 0x4F5D, 0xA746, 0x4F5E, 0xA6F0, 0x4F5F, 0xCA63, 0x4F60, 0xA741, 0x4F61, 0xCA69, 0x4F62, 0xCA5C, 0x4F63, 0xA6FE, + 0x4F64, 0xCA5F, 0x4F67, 0xCA61, 0x4F69, 0xA8D8, 0x4F6A, 0xCBBF, 0x4F6B, 0xCBCB, 0x4F6C, 0xA8D0, 0x4F6E, 0xCBCC, 0x4F6F, 0xA8CB, + 0x4F70, 0xA8D5, 0x4F73, 0xA8CE, 0x4F74, 0xCBB9, 0x4F75, 0xA8D6, 0x4F76, 0xCBB8, 0x4F77, 0xCBBC, 0x4F78, 0xCBC3, 0x4F79, 0xCBC1, + 0x4F7A, 0xA8DE, 0x4F7B, 0xA8D9, 0x4F7C, 0xCBB3, 0x4F7D, 0xCBB5, 0x4F7E, 0xA8DB, 0x4F7F, 0xA8CF, 0x4F80, 0xCBB6, 0x4F81, 0xCBC2, + 0x4F82, 0xCBC9, 0x4F83, 0xA8D4, 0x4F84, 0xCBBB, 0x4F85, 0xCBB4, 0x4F86, 0xA8D3, 0x4F87, 0xCBB7, 0x4F88, 0xA8D7, 0x4F89, 0xCBBA, + 0x4F8B, 0xA8D2, 0x4F8D, 0xA8CD, 0x4F8F, 0xA8DC, 0x4F90, 0xCBC4, 0x4F91, 0xA8DD, 0x4F92, 0xCBC8, 0x4F94, 0xCBC6, 0x4F95, 0xCBCA, + 0x4F96, 0xA8DA, 0x4F97, 0xCBBE, 0x4F98, 0xCBB2, 0x4F9A, 0xCBC0, 0x4F9B, 0xA8D1, 0x4F9C, 0xCBC5, 0x4F9D, 0xA8CC, 0x4F9E, 0xCBC7, + 0x4FAE, 0xAB56, 0x4FAF, 0xAB4A, 0x4FB2, 0xCDE0, 0x4FB3, 0xCDE8, 0x4FB5, 0xAB49, 0x4FB6, 0xAB51, 0x4FB7, 0xAB5D, 0x4FB9, 0xCDEE, + 0x4FBA, 0xCDEC, 0x4FBB, 0xCDE7, 0x4FBF, 0xAB4B, 0x4FC0, 0xCDED, 0x4FC1, 0xCDE3, 0x4FC2, 0xAB59, 0x4FC3, 0xAB50, 0x4FC4, 0xAB58, + 0x4FC5, 0xCDDE, 0x4FC7, 0xCDEA, 0x4FC9, 0xCDE1, 0x4FCA, 0xAB54, 0x4FCB, 0xCDE2, 0x4FCD, 0xCDDD, 0x4FCE, 0xAB5B, 0x4FCF, 0xAB4E, + 0x4FD0, 0xAB57, 0x4FD1, 0xAB4D, 0x4FD3, 0xCDDF, 0x4FD4, 0xCDE4, 0x4FD6, 0xCDEB, 0x4FD7, 0xAB55, 0x4FD8, 0xAB52, 0x4FD9, 0xCDE6, + 0x4FDA, 0xAB5A, 0x4FDB, 0xCDE9, 0x4FDC, 0xCDE5, 0x4FDD, 0xAB4F, 0x4FDE, 0xAB5C, 0x4FDF, 0xAB53, 0x4FE0, 0xAB4C, 0x4FE1, 0xAB48, + 0x4FEC, 0xCDEF, 0x4FEE, 0xADD7, 0x4FEF, 0xADC1, 0x4FF1, 0xADD1, 0x4FF3, 0xADD6, 0x4FF4, 0xD0D0, 0x4FF5, 0xD0CF, 0x4FF6, 0xD0D4, + 0x4FF7, 0xD0D5, 0x4FF8, 0xADC4, 0x4FFA, 0xADCD, 0x4FFE, 0xADDA, 0x5000, 0xADCE, 0x5005, 0xD0C9, 0x5006, 0xADC7, 0x5007, 0xD0CA, + 0x5009, 0xADDC, 0x500B, 0xADD3, 0x500C, 0xADBE, 0x500D, 0xADBF, 0x500E, 0xD0DD, 0x500F, 0xB0BF, 0x5011, 0xADCC, 0x5012, 0xADCB, + 0x5013, 0xD0CB, 0x5014, 0xADCF, 0x5015, 0xD45B, 0x5016, 0xADC6, 0x5017, 0xD0D6, 0x5018, 0xADD5, 0x5019, 0xADD4, 0x501A, 0xADCA, + 0x501B, 0xD0CE, 0x501C, 0xD0D7, 0x501E, 0xD0C8, 0x501F, 0xADC9, 0x5020, 0xD0D8, 0x5021, 0xADD2, 0x5022, 0xD0CC, 0x5023, 0xADC0, + 0x5025, 0xADC3, 0x5026, 0xADC2, 0x5027, 0xD0D9, 0x5028, 0xADD0, 0x5029, 0xADC5, 0x502A, 0xADD9, 0x502B, 0xADDB, 0x502C, 0xD0D3, + 0x502D, 0xADD8, 0x502F, 0xD0DB, 0x5030, 0xD0CD, 0x5031, 0xD0DC, 0x5033, 0xD0D1, 0x5035, 0xD0DA, 0x5037, 0xD0D2, 0x503C, 0xADC8, + 0x5040, 0xD463, 0x5041, 0xD457, 0x5043, 0xB0B3, 0x5045, 0xD45C, 0x5046, 0xD462, 0x5047, 0xB0B2, 0x5048, 0xD455, 0x5049, 0xB0B6, + 0x504A, 0xD459, 0x504B, 0xD452, 0x504C, 0xB0B4, 0x504D, 0xD456, 0x504E, 0xB0B9, 0x504F, 0xB0BE, 0x5051, 0xD467, 0x5053, 0xD451, + 0x5055, 0xB0BA, 0x5057, 0xD466, 0x505A, 0xB0B5, 0x505B, 0xD458, 0x505C, 0xB0B1, 0x505D, 0xD453, 0x505E, 0xD44F, 0x505F, 0xD45D, + 0x5060, 0xD450, 0x5061, 0xD44E, 0x5062, 0xD45A, 0x5063, 0xD460, 0x5064, 0xD461, 0x5065, 0xB0B7, 0x5068, 0xD85B, 0x5069, 0xD45E, + 0x506A, 0xD44D, 0x506B, 0xD45F, 0x506D, 0xB0C1, 0x506E, 0xD464, 0x506F, 0xB0C0, 0x5070, 0xD44C, 0x5072, 0xD454, 0x5073, 0xD465, + 0x5074, 0xB0BC, 0x5075, 0xB0BB, 0x5076, 0xB0B8, 0x5077, 0xB0BD, 0x507A, 0xB0AF, 0x507D, 0xB0B0, 0x5080, 0xB3C8, 0x5082, 0xD85E, + 0x5083, 0xD857, 0x5085, 0xB3C5, 0x5087, 0xD85F, 0x508B, 0xD855, 0x508C, 0xD858, 0x508D, 0xB3C4, 0x508E, 0xD859, 0x5091, 0xB3C7, + 0x5092, 0xD85D, 0x5094, 0xD853, 0x5095, 0xD852, 0x5096, 0xB3C9, 0x5098, 0xB3CA, 0x5099, 0xB3C6, 0x509A, 0xB3CB, 0x509B, 0xD851, + 0x509C, 0xD85C, 0x509D, 0xD85A, 0x509E, 0xD854, 0x50A2, 0xB3C3, 0x50A3, 0xD856, 0x50AC, 0xB6CA, 0x50AD, 0xB6C4, 0x50AE, 0xDCB7, + 0x50AF, 0xB6CD, 0x50B0, 0xDCBD, 0x50B1, 0xDCC0, 0x50B2, 0xB6C6, 0x50B3, 0xB6C7, 0x50B4, 0xDCBA, 0x50B5, 0xB6C5, 0x50B6, 0xDCC3, + 0x50B7, 0xB6CB, 0x50B8, 0xDCC4, 0x50BA, 0xDCBF, 0x50BB, 0xB6CC, 0x50BD, 0xDCB4, 0x50BE, 0xB6C9, 0x50BF, 0xDCB5, 0x50C1, 0xDCBE, + 0x50C2, 0xDCBC, 0x50C4, 0xDCB8, 0x50C5, 0xB6C8, 0x50C6, 0xDCB6, 0x50C7, 0xB6CE, 0x50C8, 0xDCBB, 0x50C9, 0xDCC2, 0x50CA, 0xDCB9, + 0x50CB, 0xDCC1, 0x50CE, 0xB9B6, 0x50CF, 0xB9B3, 0x50D1, 0xB9B4, 0x50D3, 0xE0F9, 0x50D4, 0xE0F1, 0x50D5, 0xB9B2, 0x50D6, 0xB9AF, + 0x50D7, 0xE0F2, 0x50DA, 0xB9B1, 0x50DB, 0xE0F5, 0x50DD, 0xE0F7, 0x50E0, 0xE0FE, 0x50E3, 0xE0FD, 0x50E4, 0xE0F8, 0x50E5, 0xB9AE, + 0x50E6, 0xE0F0, 0x50E7, 0xB9AC, 0x50E8, 0xE0F3, 0x50E9, 0xB9B7, 0x50EA, 0xE0F6, 0x50EC, 0xE0FA, 0x50ED, 0xB9B0, 0x50EE, 0xB9AD, + 0x50EF, 0xE0FC, 0x50F0, 0xE0FB, 0x50F1, 0xB9B5, 0x50F3, 0xE0F4, 0x50F5, 0xBBF8, 0x50F6, 0xE4EC, 0x50F8, 0xE4E9, 0x50F9, 0xBBF9, + 0x50FB, 0xBBF7, 0x50FD, 0xE4F0, 0x50FE, 0xE4ED, 0x50FF, 0xE4E6, 0x5100, 0xBBF6, 0x5102, 0xBBFA, 0x5103, 0xE4E7, 0x5104, 0xBBF5, + 0x5105, 0xBBFD, 0x5106, 0xE4EA, 0x5107, 0xE4EB, 0x5108, 0xBBFB, 0x5109, 0xBBFC, 0x510A, 0xE4F1, 0x510B, 0xE4EE, 0x510C, 0xE4EF, + 0x5110, 0xBEAA, 0x5111, 0xE8F8, 0x5112, 0xBEA7, 0x5113, 0xE8F5, 0x5114, 0xBEA9, 0x5115, 0xBEAB, 0x5117, 0xE8F6, 0x5118, 0xBEA8, + 0x511A, 0xE8F7, 0x511C, 0xE8F4, 0x511F, 0xC076, 0x5120, 0xECBD, 0x5121, 0xC077, 0x5122, 0xECBB, 0x5124, 0xECBC, 0x5125, 0xECBA, + 0x5126, 0xECB9, 0x5129, 0xECBE, 0x512A, 0xC075, 0x512D, 0xEFB8, 0x512E, 0xEFB9, 0x5130, 0xE4E8, 0x5131, 0xEFB7, 0x5132, 0xC078, + 0x5133, 0xC35F, 0x5134, 0xF1EB, 0x5135, 0xF1EC, 0x5137, 0xC4D7, 0x5138, 0xC4D8, 0x5139, 0xF5C1, 0x513A, 0xF5C0, 0x513B, 0xC56C, + 0x513C, 0xC56B, 0x513D, 0xF7D0, 0x513F, 0xA449, 0x5140, 0xA461, 0x5141, 0xA4B9, 0x5143, 0xA4B8, 0x5144, 0xA553, 0x5145, 0xA552, + 0x5146, 0xA5FC, 0x5147, 0xA5FB, 0x5148, 0xA5FD, 0x5149, 0xA5FA, 0x514B, 0xA74A, 0x514C, 0xA749, 0x514D, 0xA74B, 0x5152, 0xA8E0, + 0x5154, 0xA8DF, 0x5155, 0xA8E1, 0x5157, 0xAB5E, 0x5159, 0xA259, 0x515A, 0xD0DE, 0x515B, 0xA25A, 0x515C, 0xB0C2, 0x515D, 0xA25C, + 0x515E, 0xA25B, 0x515F, 0xD860, 0x5161, 0xA25D, 0x5162, 0xB9B8, 0x5163, 0xA25E, 0x5165, 0xA44A, 0x5167, 0xA4BA, 0x5168, 0xA5FE, + 0x5169, 0xA8E2, 0x516B, 0xA44B, 0x516C, 0xA4BD, 0x516D, 0xA4BB, 0x516E, 0xA4BC, 0x5171, 0xA640, 0x5175, 0xA74C, 0x5176, 0xA8E4, + 0x5177, 0xA8E3, 0x5178, 0xA8E5, 0x517C, 0xADDD, 0x5180, 0xBEAC, 0x5187, 0xC94E, 0x5189, 0xA554, 0x518A, 0xA555, 0x518D, 0xA641, + 0x518F, 0xCA6A, 0x5191, 0xAB60, 0x5192, 0xAB5F, 0x5193, 0xD0E0, 0x5194, 0xD0DF, 0x5195, 0xB0C3, 0x5197, 0xA4BE, 0x5198, 0xC955, + 0x519E, 0xCBCD, 0x51A0, 0xAB61, 0x51A2, 0xADE0, 0x51A4, 0xADDE, 0x51A5, 0xADDF, 0x51AA, 0xBEAD, 0x51AC, 0xA556, 0x51B0, 0xA642, + 0x51B1, 0xC9BC, 0x51B6, 0xA74D, 0x51B7, 0xA74E, 0x51B9, 0xCA6B, 0x51BC, 0xCBCE, 0x51BD, 0xA8E6, 0x51BE, 0xCBCF, 0x51C4, 0xD0E2, + 0x51C5, 0xD0E3, 0x51C6, 0xADE3, 0x51C8, 0xD0E4, 0x51CA, 0xD0E1, 0x51CB, 0xADE4, 0x51CC, 0xADE2, 0x51CD, 0xADE1, 0x51CE, 0xD0E5, + 0x51D0, 0xD468, 0x51D4, 0xD861, 0x51D7, 0xDCC5, 0x51D8, 0xE140, 0x51DC, 0xBBFE, 0x51DD, 0xBEAE, 0x51DE, 0xE8F9, 0x51E0, 0xA44C, + 0x51E1, 0xA45A, 0x51F0, 0xB0C4, 0x51F1, 0xB3CD, 0x51F3, 0xB9B9, 0x51F5, 0xC942, 0x51F6, 0xA4BF, 0x51F8, 0xA559, 0x51F9, 0xA557, + 0x51FA, 0xA558, 0x51FD, 0xA8E7, 0x5200, 0xA44D, 0x5201, 0xA44E, 0x5203, 0xA462, 0x5206, 0xA4C0, 0x5207, 0xA4C1, 0x5208, 0xA4C2, + 0x5209, 0xC9BE, 0x520A, 0xA55A, 0x520C, 0xC96B, 0x520E, 0xA646, 0x5210, 0xC9BF, 0x5211, 0xA644, 0x5212, 0xA645, 0x5213, 0xC9BD, + 0x5216, 0xA647, 0x5217, 0xA643, 0x521C, 0xCA6C, 0x521D, 0xAAEC, 0x521E, 0xCA6D, 0x5221, 0xCA6E, 0x5224, 0xA750, 0x5225, 0xA74F, + 0x5228, 0xA753, 0x5229, 0xA751, 0x522A, 0xA752, 0x522E, 0xA8ED, 0x5230, 0xA8EC, 0x5231, 0xCBD4, 0x5232, 0xCBD1, 0x5233, 0xCBD2, + 0x5235, 0xCBD0, 0x5236, 0xA8EE, 0x5237, 0xA8EA, 0x5238, 0xA8E9, 0x523A, 0xA8EB, 0x523B, 0xA8E8, 0x5241, 0xA8EF, 0x5243, 0xAB63, + 0x5244, 0xCDF0, 0x5246, 0xCBD3, 0x5247, 0xAB68, 0x5249, 0xCDF1, 0x524A, 0xAB64, 0x524B, 0xAB67, 0x524C, 0xAB66, 0x524D, 0xAB65, + 0x524E, 0xAB62, 0x5252, 0xD0E8, 0x5254, 0xADE7, 0x5255, 0xD0EB, 0x5256, 0xADE5, 0x525A, 0xD0E7, 0x525B, 0xADE8, 0x525C, 0xADE6, + 0x525D, 0xADE9, 0x525E, 0xD0E9, 0x525F, 0xD0EA, 0x5261, 0xD0E6, 0x5262, 0xD0EC, 0x5269, 0xB3D1, 0x526A, 0xB0C5, 0x526B, 0xD469, + 0x526C, 0xD46B, 0x526D, 0xD46A, 0x526E, 0xD46C, 0x526F, 0xB0C6, 0x5272, 0xB3CE, 0x5274, 0xB3CF, 0x5275, 0xB3D0, 0x5277, 0xB6D0, + 0x5278, 0xDCC7, 0x527A, 0xDCC6, 0x527B, 0xDCC8, 0x527C, 0xDCC9, 0x527D, 0xB6D1, 0x527F, 0xB6CF, 0x5280, 0xE141, 0x5281, 0xE142, + 0x5282, 0xB9BB, 0x5283, 0xB9BA, 0x5284, 0xE35A, 0x5287, 0xBC40, 0x5288, 0xBC41, 0x5289, 0xBC42, 0x528A, 0xBC44, 0x528B, 0xE4F2, + 0x528C, 0xE4F3, 0x528D, 0xBC43, 0x5291, 0xBEAF, 0x5293, 0xBEB0, 0x5296, 0xF1ED, 0x5297, 0xF5C3, 0x5298, 0xF5C2, 0x5299, 0xF7D1, + 0x529B, 0xA44F, 0x529F, 0xA55C, 0x52A0, 0xA55B, 0x52A3, 0xA648, 0x52A6, 0xC9C0, 0x52A9, 0xA755, 0x52AA, 0xA756, 0x52AB, 0xA754, + 0x52AC, 0xA757, 0x52AD, 0xCA6F, 0x52AE, 0xCA70, 0x52BB, 0xA8F1, 0x52BC, 0xCBD5, 0x52BE, 0xA8F0, 0x52C0, 0xCDF2, 0x52C1, 0xAB6C, + 0x52C2, 0xCDF3, 0x52C3, 0xAB6B, 0x52C7, 0xAB69, 0x52C9, 0xAB6A, 0x52CD, 0xD0ED, 0x52D2, 0xB0C7, 0x52D3, 0xD46E, 0x52D5, 0xB0CA, + 0x52D6, 0xD46D, 0x52D7, 0xB1E5, 0x52D8, 0xB0C9, 0x52D9, 0xB0C8, 0x52DB, 0xB3D4, 0x52DD, 0xB3D3, 0x52DE, 0xB3D2, 0x52DF, 0xB6D2, + 0x52E2, 0xB6D5, 0x52E3, 0xB6D6, 0x52E4, 0xB6D4, 0x52E6, 0xB6D3, 0x52E9, 0xE143, 0x52EB, 0xE144, 0x52EF, 0xE4F5, 0x52F0, 0xBC45, + 0x52F1, 0xE4F4, 0x52F3, 0xBEB1, 0x52F4, 0xECBF, 0x52F5, 0xC079, 0x52F7, 0xF1EE, 0x52F8, 0xC455, 0x52FA, 0xA463, 0x52FB, 0xA4C3, + 0x52FC, 0xC956, 0x52FE, 0xA4C4, 0x52FF, 0xA4C5, 0x5305, 0xA55D, 0x5306, 0xA55E, 0x5308, 0xA649, 0x5309, 0xCA71, 0x530A, 0xCBD6, + 0x530B, 0xCBD7, 0x530D, 0xAB6D, 0x530E, 0xD0EE, 0x530F, 0xB0CC, 0x5310, 0xB0CB, 0x5311, 0xD863, 0x5312, 0xD862, 0x5315, 0xA450, + 0x5316, 0xA4C6, 0x5317, 0xA55F, 0x5319, 0xB0CD, 0x531A, 0xC943, 0x531C, 0xC96C, 0x531D, 0xA560, 0x531F, 0xC9C2, 0x5320, 0xA64B, + 0x5321, 0xA64A, 0x5322, 0xC9C1, 0x5323, 0xA758, 0x532A, 0xADEA, 0x532D, 0xD46F, 0x532F, 0xB6D7, 0x5330, 0xE145, 0x5331, 0xB9BC, + 0x5334, 0xE8FA, 0x5337, 0xF3FD, 0x5339, 0xA4C7, 0x533C, 0xCBD8, 0x533D, 0xCDF4, 0x533E, 0xB0D0, 0x533F, 0xB0CE, 0x5340, 0xB0CF, + 0x5341, 0xA2CC, 0x5341, 0xA451, 0x5343, 0xA464, 0x5344, 0xA2CD, 0x5345, 0xA2CE, 0x5345, 0xA4CA, 0x5347, 0xA4C9, 0x5348, 0xA4C8, + 0x5349, 0xA563, 0x534A, 0xA562, 0x534C, 0xC96D, 0x534D, 0xC9C3, 0x5351, 0xA8F5, 0x5352, 0xA8F2, 0x5353, 0xA8F4, 0x5354, 0xA8F3, + 0x5357, 0xAB6E, 0x535A, 0xB3D5, 0x535C, 0xA452, 0x535E, 0xA4CB, 0x5360, 0xA565, 0x5361, 0xA564, 0x5363, 0xCA72, 0x5366, 0xA8F6, + 0x536C, 0xC957, 0x536E, 0xA567, 0x536F, 0xA566, 0x5370, 0xA64C, 0x5371, 0xA64D, 0x5372, 0xCA73, 0x5373, 0xA759, 0x5375, 0xA75A, + 0x5377, 0xA8F7, 0x5378, 0xA8F8, 0x5379, 0xA8F9, 0x537B, 0xAB6F, 0x537C, 0xCDF5, 0x537F, 0xADEB, 0x5382, 0xC944, 0x5384, 0xA4CC, + 0x538A, 0xC9C4, 0x538E, 0xCA74, 0x538F, 0xCA75, 0x5392, 0xCBD9, 0x5394, 0xCBDA, 0x5396, 0xCDF7, 0x5397, 0xCDF6, 0x5398, 0xCDF9, + 0x5399, 0xCDF8, 0x539A, 0xAB70, 0x539C, 0xD470, 0x539D, 0xADED, 0x539E, 0xD0EF, 0x539F, 0xADEC, 0x53A4, 0xD864, 0x53A5, 0xB3D6, + 0x53A7, 0xD865, 0x53AC, 0xE146, 0x53AD, 0xB9BD, 0x53B2, 0xBC46, 0x53B4, 0xF1EF, 0x53B9, 0xC958, 0x53BB, 0xA568, 0x53C3, 0xB0D1, + 0x53C8, 0xA453, 0x53C9, 0xA465, 0x53CA, 0xA4CE, 0x53CB, 0xA4CD, 0x53CD, 0xA4CF, 0x53D4, 0xA8FB, 0x53D6, 0xA8FA, 0x53D7, 0xA8FC, + 0x53DB, 0xAB71, 0x53DF, 0xADEE, 0x53E1, 0xE8FB, 0x53E2, 0xC24F, 0x53E3, 0xA466, 0x53E4, 0xA56A, 0x53E5, 0xA579, 0x53E6, 0xA574, + 0x53E8, 0xA56F, 0x53E9, 0xA56E, 0x53EA, 0xA575, 0x53EB, 0xA573, 0x53EC, 0xA56C, 0x53ED, 0xA57A, 0x53EE, 0xA56D, 0x53EF, 0xA569, + 0x53F0, 0xA578, 0x53F1, 0xA577, 0x53F2, 0xA576, 0x53F3, 0xA56B, 0x53F5, 0xA572, 0x53F8, 0xA571, 0x53FB, 0xA57B, 0x53FC, 0xA570, + 0x5401, 0xA653, 0x5403, 0xA659, 0x5404, 0xA655, 0x5406, 0xA65B, 0x5407, 0xC9C5, 0x5408, 0xA658, 0x5409, 0xA64E, 0x540A, 0xA651, + 0x540B, 0xA654, 0x540C, 0xA650, 0x540D, 0xA657, 0x540E, 0xA65A, 0x540F, 0xA64F, 0x5410, 0xA652, 0x5411, 0xA656, 0x5412, 0xA65C, + 0x5418, 0xCA7E, 0x5419, 0xCA7B, 0x541B, 0xA767, 0x541C, 0xCA7C, 0x541D, 0xA75B, 0x541E, 0xA75D, 0x541F, 0xA775, 0x5420, 0xA770, + 0x5424, 0xCAA5, 0x5425, 0xCA7D, 0x5426, 0xA75F, 0x5427, 0xA761, 0x5428, 0xCAA4, 0x5429, 0xA768, 0x542A, 0xCA78, 0x542B, 0xA774, + 0x542C, 0xA776, 0x542D, 0xA75C, 0x542E, 0xA76D, 0x5430, 0xCA76, 0x5431, 0xA773, 0x5433, 0xA764, 0x5435, 0xA76E, 0x5436, 0xA76F, + 0x5437, 0xCA77, 0x5438, 0xA76C, 0x5439, 0xA76A, 0x543B, 0xA76B, 0x543C, 0xA771, 0x543D, 0xCAA1, 0x543E, 0xA75E, 0x5440, 0xA772, + 0x5441, 0xCAA3, 0x5442, 0xA766, 0x5443, 0xA763, 0x5445, 0xCA7A, 0x5446, 0xA762, 0x5447, 0xCAA6, 0x5448, 0xA765, 0x544A, 0xA769, + 0x544E, 0xA760, 0x544F, 0xCAA2, 0x5454, 0xCA79, 0x5460, 0xCBEB, 0x5461, 0xCBEA, 0x5462, 0xA94F, 0x5463, 0xCBED, 0x5464, 0xCBEF, + 0x5465, 0xCBE4, 0x5466, 0xCBE7, 0x5467, 0xCBEE, 0x5468, 0xA950, 0x546B, 0xCBE1, 0x546C, 0xCBE5, 0x546F, 0xCBE9, 0x5470, 0xCE49, + 0x5471, 0xA94B, 0x5472, 0xCE4D, 0x5473, 0xA8FD, 0x5474, 0xCBE6, 0x5475, 0xA8FE, 0x5476, 0xA94C, 0x5477, 0xA945, 0x5478, 0xA941, + 0x547A, 0xCBE2, 0x547B, 0xA944, 0x547C, 0xA949, 0x547D, 0xA952, 0x547E, 0xCBE3, 0x547F, 0xCBDC, 0x5480, 0xA943, 0x5481, 0xCBDD, + 0x5482, 0xCBDF, 0x5484, 0xA946, 0x5486, 0xA948, 0x5487, 0xCBDB, 0x5488, 0xCBE0, 0x548B, 0xA951, 0x548C, 0xA94D, 0x548D, 0xCBE8, + 0x548E, 0xA953, 0x5490, 0xA94A, 0x5491, 0xCBDE, 0x5492, 0xA947, 0x5495, 0xA942, 0x5496, 0xA940, 0x5498, 0xCBEC, 0x549A, 0xA94E, + 0x54A0, 0xCE48, 0x54A1, 0xCDFB, 0x54A2, 0xCE4B, 0x54A5, 0xCDFD, 0x54A6, 0xAB78, 0x54A7, 0xABA8, 0x54A8, 0xAB74, 0x54A9, 0xABA7, + 0x54AA, 0xAB7D, 0x54AB, 0xABA4, 0x54AC, 0xAB72, 0x54AD, 0xCDFC, 0x54AE, 0xCE43, 0x54AF, 0xABA3, 0x54B0, 0xCE4F, 0x54B1, 0xABA5, + 0x54B3, 0xAB79, 0x54B6, 0xCE45, 0x54B7, 0xCE42, 0x54B8, 0xAB77, 0x54BA, 0xCDFA, 0x54BB, 0xABA6, 0x54BC, 0xCE4A, 0x54BD, 0xAB7C, + 0x54BE, 0xCE4C, 0x54BF, 0xABA9, 0x54C0, 0xAB73, 0x54C1, 0xAB7E, 0x54C2, 0xAB7B, 0x54C3, 0xCE40, 0x54C4, 0xABA1, 0x54C5, 0xCE46, + 0x54C6, 0xCE47, 0x54C7, 0xAB7A, 0x54C8, 0xABA2, 0x54C9, 0xAB76, 0x54CE, 0xAB75, 0x54CF, 0xCDFE, 0x54D6, 0xCE44, 0x54DE, 0xCE4E, + 0x54E0, 0xD144, 0x54E1, 0xADFB, 0x54E2, 0xD0F1, 0x54E4, 0xD0F6, 0x54E5, 0xADF4, 0x54E6, 0xAE40, 0x54E7, 0xD0F4, 0x54E8, 0xADEF, + 0x54E9, 0xADF9, 0x54EA, 0xADFE, 0x54EB, 0xD0FB, 0x54ED, 0xADFA, 0x54EE, 0xADFD, 0x54F1, 0xD0FE, 0x54F2, 0xADF5, 0x54F3, 0xD0F5, + 0x54F7, 0xD142, 0x54F8, 0xD143, 0x54FA, 0xADF7, 0x54FB, 0xD141, 0x54FC, 0xADF3, 0x54FD, 0xAE43, 0x54FF, 0xD0F8, 0x5501, 0xADF1, + 0x5503, 0xD146, 0x5504, 0xD0F9, 0x5505, 0xD0FD, 0x5506, 0xADF6, 0x5507, 0xAE42, 0x5508, 0xD0FA, 0x5509, 0xADFC, 0x550A, 0xD140, + 0x550B, 0xD147, 0x550C, 0xD4A1, 0x550E, 0xD145, 0x550F, 0xAE44, 0x5510, 0xADF0, 0x5511, 0xD0FC, 0x5512, 0xD0F3, 0x5514, 0xADF8, + 0x5517, 0xD0F2, 0x551A, 0xD0F7, 0x5526, 0xD0F0, 0x5527, 0xAE41, 0x552A, 0xD477, 0x552C, 0xB0E4, 0x552D, 0xD4A7, 0x552E, 0xB0E2, + 0x552F, 0xB0DF, 0x5530, 0xD47C, 0x5531, 0xB0DB, 0x5532, 0xD4A2, 0x5533, 0xB0E6, 0x5534, 0xD476, 0x5535, 0xD47B, 0x5536, 0xD47A, + 0x5537, 0xADF2, 0x5538, 0xB0E1, 0x5539, 0xD4A5, 0x553B, 0xD4A8, 0x553C, 0xD473, 0x553E, 0xB3E8, 0x5540, 0xD4A9, 0x5541, 0xB0E7, + 0x5543, 0xB0D9, 0x5544, 0xB0D6, 0x5545, 0xD47E, 0x5546, 0xB0D3, 0x5548, 0xD4A6, 0x554A, 0xB0DA, 0x554B, 0xD4AA, 0x554D, 0xD474, + 0x554E, 0xD4A4, 0x554F, 0xB0DD, 0x5550, 0xD475, 0x5551, 0xD478, 0x5552, 0xD47D, 0x5555, 0xB0DE, 0x5556, 0xB0DC, 0x5557, 0xB0E8, + 0x555C, 0xB0E3, 0x555E, 0xB0D7, 0x555F, 0xB1D2, 0x5561, 0xB0D8, 0x5562, 0xD479, 0x5563, 0xB0E5, 0x5564, 0xB0E0, 0x5565, 0xD4A3, + 0x5566, 0xB0D5, 0x556A, 0xB0D4, 0x5575, 0xD471, 0x5576, 0xD472, 0x5577, 0xD86A, 0x557B, 0xB3D7, 0x557C, 0xB3DA, 0x557D, 0xD875, + 0x557E, 0xB3EE, 0x557F, 0xD878, 0x5580, 0xB3D8, 0x5581, 0xD871, 0x5582, 0xB3DE, 0x5583, 0xB3E4, 0x5584, 0xB5BD, 0x5587, 0xB3E2, + 0x5588, 0xD86E, 0x5589, 0xB3EF, 0x558A, 0xB3DB, 0x558B, 0xB3E3, 0x558C, 0xD876, 0x558D, 0xDCD7, 0x558E, 0xD87B, 0x558F, 0xD86F, + 0x5591, 0xD866, 0x5592, 0xD873, 0x5593, 0xD86D, 0x5594, 0xB3E1, 0x5595, 0xD879, 0x5598, 0xB3DD, 0x5599, 0xB3F1, 0x559A, 0xB3EA, + 0x559C, 0xB3DF, 0x559D, 0xB3DC, 0x559F, 0xB3E7, 0x55A1, 0xD87A, 0x55A2, 0xD86C, 0x55A3, 0xD872, 0x55A4, 0xD874, 0x55A5, 0xD868, + 0x55A6, 0xD877, 0x55A7, 0xB3D9, 0x55A8, 0xD867, 0x55AA, 0xB3E0, 0x55AB, 0xB3F0, 0x55AC, 0xB3EC, 0x55AD, 0xD869, 0x55AE, 0xB3E6, + 0x55B1, 0xB3ED, 0x55B2, 0xB3E9, 0x55B3, 0xB3E5, 0x55B5, 0xD870, 0x55BB, 0xB3EB, 0x55BF, 0xDCD5, 0x55C0, 0xDCD1, 0x55C2, 0xDCE0, + 0x55C3, 0xDCCA, 0x55C4, 0xDCD3, 0x55C5, 0xB6E5, 0x55C6, 0xB6E6, 0x55C7, 0xB6DE, 0x55C8, 0xDCDC, 0x55C9, 0xB6E8, 0x55CA, 0xDCCF, + 0x55CB, 0xDCCE, 0x55CC, 0xDCCC, 0x55CD, 0xDCDE, 0x55CE, 0xB6DC, 0x55CF, 0xDCD8, 0x55D0, 0xDCCD, 0x55D1, 0xB6DF, 0x55D2, 0xDCD6, + 0x55D3, 0xB6DA, 0x55D4, 0xDCD2, 0x55D5, 0xDCD9, 0x55D6, 0xDCDB, 0x55D9, 0xDCDF, 0x55DA, 0xB6E3, 0x55DB, 0xDCCB, 0x55DC, 0xB6DD, + 0x55DD, 0xDCD0, 0x55DF, 0xB6D8, 0x55E1, 0xB6E4, 0x55E2, 0xDCDA, 0x55E3, 0xB6E0, 0x55E4, 0xB6E1, 0x55E5, 0xB6E7, 0x55E6, 0xB6DB, + 0x55E7, 0xA25F, 0x55E8, 0xB6D9, 0x55E9, 0xDCD4, 0x55EF, 0xB6E2, 0x55F2, 0xDCDD, 0x55F6, 0xB9CD, 0x55F7, 0xB9C8, 0x55F9, 0xE155, + 0x55FA, 0xE151, 0x55FC, 0xE14B, 0x55FD, 0xB9C2, 0x55FE, 0xB9BE, 0x55FF, 0xE154, 0x5600, 0xB9BF, 0x5601, 0xE14E, 0x5602, 0xE150, + 0x5604, 0xE153, 0x5606, 0xB9C4, 0x5608, 0xB9CB, 0x5609, 0xB9C5, 0x560C, 0xE149, 0x560D, 0xB9C6, 0x560E, 0xB9C7, 0x560F, 0xE14C, + 0x5610, 0xB9CC, 0x5612, 0xE14A, 0x5613, 0xE14F, 0x5614, 0xB9C3, 0x5615, 0xE148, 0x5616, 0xB9C9, 0x5617, 0xB9C1, 0x561B, 0xB9C0, + 0x561C, 0xE14D, 0x561D, 0xE152, 0x561F, 0xB9CA, 0x5627, 0xE147, 0x5629, 0xBC4D, 0x562A, 0xE547, 0x562C, 0xE544, 0x562E, 0xBC47, + 0x562F, 0xBC53, 0x5630, 0xBC54, 0x5632, 0xBC4A, 0x5633, 0xE542, 0x5634, 0xBC4C, 0x5635, 0xE4F9, 0x5636, 0xBC52, 0x5638, 0xE546, + 0x5639, 0xBC49, 0x563A, 0xE548, 0x563B, 0xBC48, 0x563D, 0xE543, 0x563E, 0xE545, 0x563F, 0xBC4B, 0x5640, 0xE541, 0x5641, 0xE4FA, + 0x5642, 0xE4F7, 0x5645, 0xD86B, 0x5646, 0xE4FD, 0x5648, 0xE4F6, 0x5649, 0xE4FC, 0x564A, 0xE4FB, 0x564C, 0xE4F8, 0x564E, 0xBC4F, + 0x5653, 0xBC4E, 0x5657, 0xBC50, 0x5658, 0xE4FE, 0x5659, 0xBEB2, 0x565A, 0xE540, 0x565E, 0xE945, 0x5660, 0xE8FD, 0x5662, 0xBEBE, + 0x5663, 0xE942, 0x5664, 0xBEB6, 0x5665, 0xBEBA, 0x5666, 0xE941, 0x5668, 0xBEB9, 0x5669, 0xBEB5, 0x566A, 0xBEB8, 0x566B, 0xBEB3, + 0x566C, 0xBEBD, 0x566D, 0xE943, 0x566E, 0xE8FE, 0x566F, 0xBEBC, 0x5670, 0xE8FC, 0x5671, 0xBEBB, 0x5672, 0xE944, 0x5673, 0xE940, + 0x5674, 0xBC51, 0x5676, 0xBEBF, 0x5677, 0xE946, 0x5678, 0xBEB7, 0x5679, 0xBEB4, 0x567E, 0xECC6, 0x567F, 0xECC8, 0x5680, 0xC07B, + 0x5681, 0xECC9, 0x5682, 0xECC7, 0x5683, 0xECC5, 0x5684, 0xECC4, 0x5685, 0xC07D, 0x5686, 0xECC3, 0x5687, 0xC07E, 0x568C, 0xECC1, + 0x568D, 0xECC2, 0x568E, 0xC07A, 0x568F, 0xC0A1, 0x5690, 0xC07C, 0x5693, 0xECC0, 0x5695, 0xC250, 0x5697, 0xEFBC, 0x5698, 0xEFBA, + 0x5699, 0xEFBF, 0x569A, 0xEFBD, 0x569C, 0xEFBB, 0x569D, 0xEFBE, 0x56A5, 0xC360, 0x56A6, 0xF1F2, 0x56A7, 0xF1F3, 0x56A8, 0xC456, + 0x56AA, 0xF1F4, 0x56AB, 0xF1F0, 0x56AC, 0xF1F5, 0x56AD, 0xF1F1, 0x56AE, 0xC251, 0x56B2, 0xF3FE, 0x56B3, 0xF441, 0x56B4, 0xC459, + 0x56B5, 0xF440, 0x56B6, 0xC458, 0x56B7, 0xC457, 0x56BC, 0xC45A, 0x56BD, 0xF5C5, 0x56BE, 0xF5C6, 0x56C0, 0xC4DA, 0x56C1, 0xC4D9, + 0x56C2, 0xC4DB, 0x56C3, 0xF5C4, 0x56C5, 0xF6D8, 0x56C6, 0xF6D7, 0x56C8, 0xC56D, 0x56C9, 0xC56F, 0x56CA, 0xC56E, 0x56CB, 0xF6D9, + 0x56CC, 0xC5C8, 0x56CD, 0xF8A6, 0x56D1, 0xC5F1, 0x56D3, 0xF8A5, 0x56D4, 0xF8EE, 0x56D7, 0xC949, 0x56DA, 0xA57D, 0x56DB, 0xA57C, + 0x56DD, 0xA65F, 0x56DE, 0xA65E, 0x56DF, 0xC9C7, 0x56E0, 0xA65D, 0x56E1, 0xC9C6, 0x56E4, 0xA779, 0x56E5, 0xCAA9, 0x56E7, 0xCAA8, + 0x56EA, 0xA777, 0x56EB, 0xA77A, 0x56EE, 0xCAA7, 0x56F0, 0xA778, 0x56F7, 0xCBF0, 0x56F9, 0xCBF1, 0x56FA, 0xA954, 0x56FF, 0xABAA, + 0x5701, 0xD148, 0x5702, 0xD149, 0x5703, 0xAE45, 0x5704, 0xAE46, 0x5707, 0xD4AC, 0x5708, 0xB0E9, 0x5709, 0xB0EB, 0x570A, 0xD4AB, + 0x570B, 0xB0EA, 0x570C, 0xD87C, 0x570D, 0xB3F2, 0x5712, 0xB6E9, 0x5713, 0xB6EA, 0x5714, 0xDCE1, 0x5716, 0xB9CF, 0x5718, 0xB9CE, + 0x571A, 0xE549, 0x571B, 0xE948, 0x571C, 0xE947, 0x571E, 0xF96B, 0x571F, 0xA467, 0x5720, 0xC959, 0x5722, 0xC96E, 0x5723, 0xC96F, + 0x5728, 0xA662, 0x5729, 0xA666, 0x572A, 0xC9C9, 0x572C, 0xA664, 0x572D, 0xA663, 0x572E, 0xC9C8, 0x572F, 0xA665, 0x5730, 0xA661, + 0x5733, 0xA660, 0x5734, 0xC9CA, 0x573B, 0xA7A6, 0x573E, 0xA7A3, 0x5740, 0xA77D, 0x5741, 0xCAAA, 0x5745, 0xCAAB, 0x5747, 0xA7A1, + 0x5749, 0xCAAD, 0x574A, 0xA77B, 0x574B, 0xCAAE, 0x574C, 0xCAAC, 0x574D, 0xA77E, 0x574E, 0xA7A2, 0x574F, 0xA7A5, 0x5750, 0xA7A4, + 0x5751, 0xA77C, 0x5752, 0xCAAF, 0x5761, 0xA959, 0x5762, 0xCBFE, 0x5764, 0xA95B, 0x5766, 0xA95A, 0x5768, 0xCC40, 0x5769, 0xA958, + 0x576A, 0xA957, 0x576B, 0xCBF5, 0x576D, 0xCBF4, 0x576F, 0xCBF2, 0x5770, 0xCBF7, 0x5771, 0xCBF6, 0x5772, 0xCBF3, 0x5773, 0xCBFC, + 0x5774, 0xCBFD, 0x5775, 0xCBFA, 0x5776, 0xCBF8, 0x5777, 0xA956, 0x577B, 0xCBFB, 0x577C, 0xA95C, 0x577D, 0xCC41, 0x5780, 0xCBF9, + 0x5782, 0xABAB, 0x5783, 0xA955, 0x578B, 0xABAC, 0x578C, 0xCE54, 0x578F, 0xCE5A, 0x5793, 0xABB2, 0x5794, 0xCE58, 0x5795, 0xCE5E, + 0x5797, 0xCE55, 0x5798, 0xCE59, 0x5799, 0xCE5B, 0x579A, 0xCE5D, 0x579B, 0xCE57, 0x579D, 0xCE56, 0x579E, 0xCE51, 0x579F, 0xCE52, + 0x57A0, 0xABAD, 0x57A2, 0xABAF, 0x57A3, 0xABAE, 0x57A4, 0xCE53, 0x57A5, 0xCE5C, 0x57AE, 0xABB1, 0x57B5, 0xCE50, 0x57B6, 0xD153, + 0x57B8, 0xD152, 0x57B9, 0xD157, 0x57BA, 0xD14E, 0x57BC, 0xD151, 0x57BD, 0xD150, 0x57BF, 0xD154, 0x57C1, 0xD158, 0x57C2, 0xAE47, + 0x57C3, 0xAE4A, 0x57C6, 0xD14F, 0x57C7, 0xD155, 0x57CB, 0xAE49, 0x57CC, 0xD14A, 0x57CE, 0xABB0, 0x57CF, 0xD4BA, 0x57D0, 0xD156, + 0x57D2, 0xD14D, 0x57D4, 0xAE48, 0x57D5, 0xD14C, 0x57DC, 0xD4B1, 0x57DF, 0xB0EC, 0x57E0, 0xB0F0, 0x57E1, 0xD4C1, 0x57E2, 0xD4AF, + 0x57E3, 0xD4BD, 0x57E4, 0xB0F1, 0x57E5, 0xD4BF, 0x57E7, 0xD4C5, 0x57E9, 0xD4C9, 0x57EC, 0xD4C0, 0x57ED, 0xD4B4, 0x57EE, 0xD4BC, + 0x57F0, 0xD4CA, 0x57F1, 0xD4C8, 0x57F2, 0xD4BE, 0x57F3, 0xD4B9, 0x57F4, 0xD4B2, 0x57F5, 0xD8A6, 0x57F6, 0xD4B0, 0x57F7, 0xB0F5, + 0x57F8, 0xD4B7, 0x57F9, 0xB0F6, 0x57FA, 0xB0F2, 0x57FB, 0xD4AD, 0x57FC, 0xD4C3, 0x57FD, 0xD4B5, 0x5800, 0xD4B3, 0x5801, 0xD4C6, + 0x5802, 0xB0F3, 0x5804, 0xD4CC, 0x5805, 0xB0ED, 0x5806, 0xB0EF, 0x5807, 0xD4BB, 0x5808, 0xD4B6, 0x5809, 0xAE4B, 0x580A, 0xB0EE, + 0x580B, 0xD4B8, 0x580C, 0xD4C7, 0x580D, 0xD4CB, 0x580E, 0xD4C2, 0x5810, 0xD4C4, 0x5814, 0xD4AE, 0x5819, 0xD8A1, 0x581B, 0xD8AA, + 0x581C, 0xD8A9, 0x581D, 0xB3FA, 0x581E, 0xD8A2, 0x5820, 0xB3FB, 0x5821, 0xB3F9, 0x5823, 0xD8A4, 0x5824, 0xB3F6, 0x5825, 0xD8A8, + 0x5827, 0xD8A3, 0x5828, 0xD8A5, 0x5829, 0xD87D, 0x582A, 0xB3F4, 0x582C, 0xD8B2, 0x582D, 0xD8B1, 0x582E, 0xD8AE, 0x582F, 0xB3F3, + 0x5830, 0xB3F7, 0x5831, 0xB3F8, 0x5832, 0xD14B, 0x5833, 0xD8AB, 0x5834, 0xB3F5, 0x5835, 0xB0F4, 0x5836, 0xD8AD, 0x5837, 0xD87E, + 0x5838, 0xD8B0, 0x5839, 0xD8AF, 0x583B, 0xD8B3, 0x583D, 0xDCEF, 0x583F, 0xD8AC, 0x5848, 0xD8A7, 0x5849, 0xDCE7, 0x584A, 0xB6F4, + 0x584B, 0xB6F7, 0x584C, 0xB6F2, 0x584D, 0xDCE6, 0x584E, 0xDCEA, 0x584F, 0xDCE5, 0x5851, 0xB6EC, 0x5852, 0xB6F6, 0x5853, 0xDCE2, + 0x5854, 0xB6F0, 0x5855, 0xDCE9, 0x5857, 0xB6EE, 0x5858, 0xB6ED, 0x5859, 0xDCEC, 0x585A, 0xB6EF, 0x585B, 0xDCEE, 0x585D, 0xDCEB, + 0x585E, 0xB6EB, 0x5862, 0xB6F5, 0x5863, 0xDCF0, 0x5864, 0xDCE4, 0x5865, 0xDCED, 0x5868, 0xDCE3, 0x586B, 0xB6F1, 0x586D, 0xB6F3, + 0x586F, 0xDCE8, 0x5871, 0xDCF1, 0x5874, 0xE15D, 0x5875, 0xB9D0, 0x5876, 0xE163, 0x5879, 0xB9D5, 0x587A, 0xE15F, 0x587B, 0xE166, + 0x587C, 0xE157, 0x587D, 0xB9D7, 0x587E, 0xB9D1, 0x587F, 0xE15C, 0x5880, 0xBC55, 0x5881, 0xE15B, 0x5882, 0xE164, 0x5883, 0xB9D2, + 0x5885, 0xB9D6, 0x5886, 0xE15A, 0x5887, 0xE160, 0x5888, 0xE165, 0x5889, 0xE156, 0x588A, 0xB9D4, 0x588B, 0xE15E, 0x588E, 0xE162, + 0x588F, 0xE168, 0x5890, 0xE158, 0x5891, 0xE161, 0x5893, 0xB9D3, 0x5894, 0xE167, 0x5898, 0xE159, 0x589C, 0xBC59, 0x589D, 0xE54B, + 0x589E, 0xBC57, 0x589F, 0xBC56, 0x58A0, 0xE54D, 0x58A1, 0xE552, 0x58A3, 0xE54E, 0x58A5, 0xE551, 0x58A6, 0xBC5C, 0x58A8, 0xBEA5, + 0x58A9, 0xBC5B, 0x58AB, 0xE54A, 0x58AC, 0xE550, 0x58AE, 0xBC5A, 0x58AF, 0xE54F, 0x58B1, 0xE54C, 0x58B3, 0xBC58, 0x58BA, 0xE94D, + 0x58BB, 0xF9D9, 0x58BC, 0xE94F, 0x58BD, 0xE94A, 0x58BE, 0xBEC1, 0x58BF, 0xE94C, 0x58C1, 0xBEC0, 0x58C2, 0xE94E, 0x58C5, 0xBEC3, + 0x58C6, 0xE950, 0x58C7, 0xBEC2, 0x58C8, 0xE949, 0x58C9, 0xE94B, 0x58CE, 0xC0A5, 0x58CF, 0xECCC, 0x58D1, 0xC0A4, 0x58D2, 0xECCD, + 0x58D3, 0xC0A3, 0x58D4, 0xECCB, 0x58D5, 0xC0A2, 0x58D6, 0xECCA, 0x58D8, 0xC253, 0x58D9, 0xC252, 0x58DA, 0xF1F6, 0x58DB, 0xF1F8, + 0x58DD, 0xF1F7, 0x58DE, 0xC361, 0x58DF, 0xC362, 0x58E2, 0xC363, 0x58E3, 0xF442, 0x58E4, 0xC45B, 0x58E7, 0xF7D3, 0x58E8, 0xF7D2, + 0x58E9, 0xC5F2, 0x58EB, 0xA468, 0x58EC, 0xA4D0, 0x58EF, 0xA7A7, 0x58F4, 0xCE5F, 0x58F9, 0xB3FC, 0x58FA, 0xB3FD, 0x58FC, 0xDCF2, + 0x58FD, 0xB9D8, 0x58FE, 0xE169, 0x58FF, 0xE553, 0x5903, 0xC95A, 0x5906, 0xCAB0, 0x590C, 0xCC42, 0x590D, 0xCE60, 0x590E, 0xD159, + 0x590F, 0xAE4C, 0x5912, 0xF1F9, 0x5914, 0xC4DC, 0x5915, 0xA469, 0x5916, 0xA57E, 0x5917, 0xC970, 0x5919, 0xA667, 0x591A, 0xA668, + 0x591C, 0xA95D, 0x5920, 0xB0F7, 0x5922, 0xB9DA, 0x5924, 0xB9DB, 0x5925, 0xB9D9, 0x5927, 0xA46A, 0x5929, 0xA4D1, 0x592A, 0xA4D3, + 0x592B, 0xA4D2, 0x592C, 0xC95B, 0x592D, 0xA4D4, 0x592E, 0xA5A1, 0x592F, 0xC971, 0x5931, 0xA5A2, 0x5937, 0xA669, 0x5938, 0xA66A, + 0x593C, 0xC9CB, 0x593E, 0xA7A8, 0x5940, 0xCAB1, 0x5944, 0xA961, 0x5945, 0xCC43, 0x5947, 0xA95F, 0x5948, 0xA960, 0x5949, 0xA95E, + 0x594A, 0xD15A, 0x594E, 0xABB6, 0x594F, 0xABB5, 0x5950, 0xABB7, 0x5951, 0xABB4, 0x5953, 0xCE61, 0x5954, 0xA962, 0x5955, 0xABB3, + 0x5957, 0xAE4D, 0x5958, 0xAE4E, 0x595A, 0xAE4F, 0x595C, 0xD4CD, 0x5960, 0xB3FE, 0x5961, 0xD8B4, 0x5962, 0xB0F8, 0x5967, 0xB6F8, + 0x5969, 0xB9DD, 0x596A, 0xB9DC, 0x596B, 0xE16A, 0x596D, 0xBC5D, 0x596E, 0xBEC4, 0x5970, 0xEFC0, 0x5971, 0xF6DA, 0x5972, 0xF7D4, + 0x5973, 0xA46B, 0x5974, 0xA5A3, 0x5976, 0xA5A4, 0x5977, 0xC9D1, 0x5978, 0xA66C, 0x5979, 0xA66F, 0x597B, 0xC9CF, 0x597C, 0xC9CD, + 0x597D, 0xA66E, 0x597E, 0xC9D0, 0x597F, 0xC9D2, 0x5980, 0xC9CC, 0x5981, 0xA671, 0x5982, 0xA670, 0x5983, 0xA66D, 0x5984, 0xA66B, + 0x5985, 0xC9CE, 0x598A, 0xA7B3, 0x598D, 0xA7B0, 0x598E, 0xCAB6, 0x598F, 0xCAB9, 0x5990, 0xCAB8, 0x5992, 0xA7AA, 0x5993, 0xA7B2, + 0x5996, 0xA7AF, 0x5997, 0xCAB5, 0x5998, 0xCAB3, 0x5999, 0xA7AE, 0x599D, 0xA7A9, 0x599E, 0xA7AC, 0x59A0, 0xCAB4, 0x59A1, 0xCABB, + 0x59A2, 0xCAB7, 0x59A3, 0xA7AD, 0x59A4, 0xA7B1, 0x59A5, 0xA7B4, 0x59A6, 0xCAB2, 0x59A7, 0xCABA, 0x59A8, 0xA7AB, 0x59AE, 0xA967, + 0x59AF, 0xA96F, 0x59B1, 0xCC4F, 0x59B2, 0xCC48, 0x59B3, 0xA970, 0x59B4, 0xCC53, 0x59B5, 0xCC44, 0x59B6, 0xCC4B, 0x59B9, 0xA966, + 0x59BA, 0xCC45, 0x59BB, 0xA964, 0x59BC, 0xCC4C, 0x59BD, 0xCC50, 0x59BE, 0xA963, 0x59C0, 0xCC51, 0x59C1, 0xCC4A, 0x59C3, 0xCC4D, + 0x59C5, 0xA972, 0x59C6, 0xA969, 0x59C7, 0xCC54, 0x59C8, 0xCC52, 0x59CA, 0xA96E, 0x59CB, 0xA96C, 0x59CC, 0xCC49, 0x59CD, 0xA96B, + 0x59CE, 0xCC47, 0x59CF, 0xCC46, 0x59D0, 0xA96A, 0x59D1, 0xA968, 0x59D2, 0xA971, 0x59D3, 0xA96D, 0x59D4, 0xA965, 0x59D6, 0xCC4E, + 0x59D8, 0xABB9, 0x59DA, 0xABC0, 0x59DB, 0xCE6F, 0x59DC, 0xABB8, 0x59DD, 0xCE67, 0x59DE, 0xCE63, 0x59E0, 0xCE73, 0x59E1, 0xCE62, + 0x59E3, 0xABBB, 0x59E4, 0xCE6C, 0x59E5, 0xABBE, 0x59E6, 0xABC1, 0x59E8, 0xABBC, 0x59E9, 0xCE70, 0x59EA, 0xABBF, 0x59EC, 0xAE56, + 0x59ED, 0xCE76, 0x59EE, 0xCE64, 0x59F1, 0xCE66, 0x59F2, 0xCE6D, 0x59F3, 0xCE71, 0x59F4, 0xCE75, 0x59F5, 0xCE72, 0x59F6, 0xCE6B, + 0x59F7, 0xCE6E, 0x59FA, 0xCE68, 0x59FB, 0xABC3, 0x59FC, 0xCE6A, 0x59FD, 0xCE69, 0x59FE, 0xCE74, 0x59FF, 0xABBA, 0x5A00, 0xCE65, + 0x5A01, 0xABC2, 0x5A03, 0xABBD, 0x5A09, 0xAE5C, 0x5A0A, 0xD162, 0x5A0C, 0xAE5B, 0x5A0F, 0xD160, 0x5A11, 0xAE50, 0x5A13, 0xAE55, + 0x5A15, 0xD15F, 0x5A16, 0xD15C, 0x5A17, 0xD161, 0x5A18, 0xAE51, 0x5A19, 0xD15B, 0x5A1B, 0xAE54, 0x5A1C, 0xAE52, 0x5A1E, 0xD163, + 0x5A1F, 0xAE53, 0x5A20, 0xAE57, 0x5A23, 0xAE58, 0x5A25, 0xAE5A, 0x5A29, 0xAE59, 0x5A2D, 0xD15D, 0x5A2E, 0xD15E, 0x5A33, 0xD164, + 0x5A35, 0xD4D4, 0x5A36, 0xB0F9, 0x5A37, 0xD8C2, 0x5A38, 0xD4D3, 0x5A39, 0xD4E6, 0x5A3C, 0xB140, 0x5A3E, 0xD4E4, 0x5A40, 0xB0FE, + 0x5A41, 0xB0FA, 0x5A42, 0xD4ED, 0x5A43, 0xD4DD, 0x5A44, 0xD4E0, 0x5A46, 0xB143, 0x5A47, 0xD4EA, 0x5A48, 0xD4E2, 0x5A49, 0xB0FB, + 0x5A4A, 0xB144, 0x5A4C, 0xD4E7, 0x5A4D, 0xD4E5, 0x5A50, 0xD4D6, 0x5A51, 0xD4EB, 0x5A52, 0xD4DF, 0x5A53, 0xD4DA, 0x5A55, 0xD4D0, + 0x5A56, 0xD4EC, 0x5A57, 0xD4DC, 0x5A58, 0xD4CF, 0x5A5A, 0xB142, 0x5A5B, 0xD4E1, 0x5A5C, 0xD4EE, 0x5A5D, 0xD4DE, 0x5A5E, 0xD4D2, + 0x5A5F, 0xD4D7, 0x5A60, 0xD4CE, 0x5A62, 0xB141, 0x5A64, 0xD4DB, 0x5A65, 0xD4D8, 0x5A66, 0xB0FC, 0x5A67, 0xD4D1, 0x5A69, 0xD4E9, + 0x5A6A, 0xB0FD, 0x5A6C, 0xD4D9, 0x5A6D, 0xD4D5, 0x5A70, 0xD4E8, 0x5A77, 0xB440, 0x5A78, 0xD8BB, 0x5A7A, 0xD8B8, 0x5A7B, 0xD8C9, + 0x5A7C, 0xD8BD, 0x5A7D, 0xD8CA, 0x5A7F, 0xB442, 0x5A83, 0xD8C6, 0x5A84, 0xD8C3, 0x5A8A, 0xD8C4, 0x5A8B, 0xD8C7, 0x5A8C, 0xD8CB, + 0x5A8E, 0xD4E3, 0x5A8F, 0xD8CD, 0x5A90, 0xDD47, 0x5A92, 0xB443, 0x5A93, 0xD8CE, 0x5A94, 0xD8B6, 0x5A95, 0xD8C0, 0x5A97, 0xD8C5, + 0x5A9A, 0xB441, 0x5A9B, 0xB444, 0x5A9C, 0xD8CC, 0x5A9D, 0xD8CF, 0x5A9E, 0xD8BA, 0x5A9F, 0xD8B7, 0x5AA2, 0xD8B9, 0x5AA5, 0xD8BE, + 0x5AA6, 0xD8BC, 0x5AA7, 0xB445, 0x5AA9, 0xD8C8, 0x5AAC, 0xD8BF, 0x5AAE, 0xD8C1, 0x5AAF, 0xD8B5, 0x5AB0, 0xDCFA, 0x5AB1, 0xDCF8, + 0x5AB2, 0xB742, 0x5AB3, 0xB740, 0x5AB4, 0xDD43, 0x5AB5, 0xDCF9, 0x5AB6, 0xDD44, 0x5AB7, 0xDD40, 0x5AB8, 0xDCF7, 0x5AB9, 0xDD46, + 0x5ABA, 0xDCF6, 0x5ABB, 0xDCFD, 0x5ABC, 0xB6FE, 0x5ABD, 0xB6FD, 0x5ABE, 0xB6FC, 0x5ABF, 0xDCFB, 0x5AC0, 0xDD41, 0x5AC1, 0xB6F9, + 0x5AC2, 0xB741, 0x5AC4, 0xDCF4, 0x5AC6, 0xDCFE, 0x5AC7, 0xDCF3, 0x5AC8, 0xDCFC, 0x5AC9, 0xB6FA, 0x5ACA, 0xDD42, 0x5ACB, 0xDCF5, + 0x5ACC, 0xB6FB, 0x5ACD, 0xDD45, 0x5AD5, 0xE16E, 0x5AD6, 0xB9E2, 0x5AD7, 0xB9E1, 0x5AD8, 0xB9E3, 0x5AD9, 0xE17A, 0x5ADA, 0xE170, + 0x5ADB, 0xE176, 0x5ADC, 0xE16B, 0x5ADD, 0xE179, 0x5ADE, 0xE178, 0x5ADF, 0xE17C, 0x5AE0, 0xE175, 0x5AE1, 0xB9DE, 0x5AE2, 0xE174, + 0x5AE3, 0xB9E4, 0x5AE5, 0xE16D, 0x5AE6, 0xB9DF, 0x5AE8, 0xE17B, 0x5AE9, 0xB9E0, 0x5AEA, 0xE16F, 0x5AEB, 0xE172, 0x5AEC, 0xE177, + 0x5AED, 0xE171, 0x5AEE, 0xE16C, 0x5AF3, 0xE173, 0x5AF4, 0xE555, 0x5AF5, 0xBC61, 0x5AF6, 0xE558, 0x5AF7, 0xE557, 0x5AF8, 0xE55A, + 0x5AF9, 0xE55C, 0x5AFA, 0xF9DC, 0x5AFB, 0xBC5F, 0x5AFD, 0xE556, 0x5AFF, 0xE554, 0x5B01, 0xE55D, 0x5B02, 0xE55B, 0x5B03, 0xE559, + 0x5B05, 0xE55F, 0x5B07, 0xE55E, 0x5B08, 0xBC63, 0x5B09, 0xBC5E, 0x5B0B, 0xBC60, 0x5B0C, 0xBC62, 0x5B0F, 0xE560, 0x5B10, 0xE957, + 0x5B13, 0xE956, 0x5B14, 0xE955, 0x5B16, 0xE958, 0x5B17, 0xE951, 0x5B19, 0xE952, 0x5B1A, 0xE95A, 0x5B1B, 0xE953, 0x5B1D, 0xBEC5, + 0x5B1E, 0xE95C, 0x5B20, 0xE95B, 0x5B21, 0xE954, 0x5B23, 0xECD1, 0x5B24, 0xC0A8, 0x5B25, 0xECCF, 0x5B26, 0xECD4, 0x5B27, 0xECD3, + 0x5B28, 0xE959, 0x5B2A, 0xC0A7, 0x5B2C, 0xECD2, 0x5B2D, 0xECCE, 0x5B2E, 0xECD6, 0x5B2F, 0xECD5, 0x5B30, 0xC0A6, 0x5B32, 0xECD0, + 0x5B34, 0xBEC6, 0x5B38, 0xC254, 0x5B3C, 0xEFC1, 0x5B3D, 0xF1FA, 0x5B3E, 0xF1FB, 0x5B3F, 0xF1FC, 0x5B40, 0xC45C, 0x5B43, 0xC45D, + 0x5B45, 0xF443, 0x5B47, 0xF5C8, 0x5B48, 0xF5C7, 0x5B4B, 0xF6DB, 0x5B4C, 0xF6DC, 0x5B4D, 0xF7D5, 0x5B4E, 0xF8A7, 0x5B50, 0xA46C, + 0x5B51, 0xA46D, 0x5B53, 0xA46E, 0x5B54, 0xA4D5, 0x5B55, 0xA5A5, 0x5B56, 0xC9D3, 0x5B57, 0xA672, 0x5B58, 0xA673, 0x5B5A, 0xA7B7, + 0x5B5B, 0xA7B8, 0x5B5C, 0xA7B6, 0x5B5D, 0xA7B5, 0x5B5F, 0xA973, 0x5B62, 0xCC55, 0x5B63, 0xA975, 0x5B64, 0xA974, 0x5B65, 0xCC56, + 0x5B69, 0xABC4, 0x5B6B, 0xAE5D, 0x5B6C, 0xD165, 0x5B6E, 0xD4F0, 0x5B70, 0xB145, 0x5B71, 0xB447, 0x5B72, 0xD4EF, 0x5B73, 0xB446, + 0x5B75, 0xB9E5, 0x5B77, 0xE17D, 0x5B78, 0xBEC7, 0x5B7A, 0xC0A9, 0x5B7B, 0xECD7, 0x5B7D, 0xC45E, 0x5B7F, 0xC570, 0x5B81, 0xC972, + 0x5B83, 0xA5A6, 0x5B84, 0xC973, 0x5B85, 0xA676, 0x5B87, 0xA674, 0x5B88, 0xA675, 0x5B89, 0xA677, 0x5B8B, 0xA7BA, 0x5B8C, 0xA7B9, + 0x5B8E, 0xCABC, 0x5B8F, 0xA7BB, 0x5B92, 0xCABD, 0x5B93, 0xCC57, 0x5B95, 0xCC58, 0x5B97, 0xA976, 0x5B98, 0xA978, 0x5B99, 0xA97A, + 0x5B9A, 0xA977, 0x5B9B, 0xA97B, 0x5B9C, 0xA979, 0x5BA2, 0xABC8, 0x5BA3, 0xABC5, 0x5BA4, 0xABC7, 0x5BA5, 0xABC9, 0x5BA6, 0xABC6, + 0x5BA7, 0xD166, 0x5BA8, 0xCE77, 0x5BAC, 0xD168, 0x5BAD, 0xD167, 0x5BAE, 0xAE63, 0x5BB0, 0xAE5F, 0x5BB3, 0xAE60, 0x5BB4, 0xAE62, + 0x5BB5, 0xAE64, 0x5BB6, 0xAE61, 0x5BB8, 0xAE66, 0x5BB9, 0xAE65, 0x5BBF, 0xB14A, 0x5BC0, 0xD4F2, 0x5BC1, 0xD4F1, 0x5BC2, 0xB149, + 0x5BC4, 0xB148, 0x5BC5, 0xB147, 0x5BC6, 0xB14B, 0x5BC7, 0xB146, 0x5BCA, 0xD8D5, 0x5BCB, 0xD8D2, 0x5BCC, 0xB449, 0x5BCD, 0xD8D1, + 0x5BCE, 0xD8D6, 0x5BD0, 0xB44B, 0x5BD1, 0xD8D4, 0x5BD2, 0xB448, 0x5BD3, 0xB44A, 0x5BD4, 0xD8D3, 0x5BD6, 0xDD48, 0x5BD8, 0xDD49, + 0x5BD9, 0xDD4A, 0x5BDE, 0xB9E6, 0x5BDF, 0xB9EE, 0x5BE0, 0xE17E, 0x5BE1, 0xB9E8, 0x5BE2, 0xB9EC, 0x5BE3, 0xE1A1, 0x5BE4, 0xB9ED, + 0x5BE5, 0xB9E9, 0x5BE6, 0xB9EA, 0x5BE7, 0xB9E7, 0x5BE8, 0xB9EB, 0x5BE9, 0xBC66, 0x5BEA, 0xD8D0, 0x5BEB, 0xBC67, 0x5BEC, 0xBC65, + 0x5BEE, 0xBC64, 0x5BEF, 0xE95D, 0x5BF0, 0xBEC8, 0x5BF1, 0xECD8, 0x5BF2, 0xECD9, 0x5BF5, 0xC364, 0x5BF6, 0xC45F, 0x5BF8, 0xA46F, + 0x5BFA, 0xA678, 0x5C01, 0xABCA, 0x5C03, 0xD169, 0x5C04, 0xAE67, 0x5C07, 0xB14E, 0x5C08, 0xB14D, 0x5C09, 0xB14C, 0x5C0A, 0xB44C, + 0x5C0B, 0xB44D, 0x5C0C, 0xD8D7, 0x5C0D, 0xB9EF, 0x5C0E, 0xBEC9, 0x5C0F, 0xA470, 0x5C10, 0xC95C, 0x5C11, 0xA4D6, 0x5C12, 0xC974, + 0x5C15, 0xC9D4, 0x5C16, 0xA679, 0x5C1A, 0xA97C, 0x5C1F, 0xDD4B, 0x5C22, 0xA471, 0x5C24, 0xA4D7, 0x5C25, 0xC9D5, 0x5C28, 0xCABE, + 0x5C2A, 0xCABF, 0x5C2C, 0xA7BC, 0x5C30, 0xD8D8, 0x5C31, 0xB44E, 0x5C33, 0xDD4C, 0x5C37, 0xC0AA, 0x5C38, 0xA472, 0x5C39, 0xA4A8, + 0x5C3A, 0xA4D8, 0x5C3B, 0xC975, 0x5C3C, 0xA5A7, 0x5C3E, 0xA7C0, 0x5C3F, 0xA7BF, 0x5C40, 0xA7BD, 0x5C41, 0xA7BE, 0x5C44, 0xCC59, + 0x5C45, 0xA97E, 0x5C46, 0xA9A1, 0x5C47, 0xCC5A, 0x5C48, 0xA97D, 0x5C4B, 0xABCE, 0x5C4C, 0xCE78, 0x5C4D, 0xABCD, 0x5C4E, 0xABCB, + 0x5C4F, 0xABCC, 0x5C50, 0xAE6A, 0x5C51, 0xAE68, 0x5C54, 0xD16B, 0x5C55, 0xAE69, 0x5C56, 0xD16A, 0x5C58, 0xAE5E, 0x5C59, 0xD4F3, + 0x5C5C, 0xB150, 0x5C5D, 0xB151, 0x5C60, 0xB14F, 0x5C62, 0xB9F0, 0x5C63, 0xE1A2, 0x5C64, 0xBC68, 0x5C65, 0xBC69, 0x5C67, 0xE561, + 0x5C68, 0xC0AB, 0x5C69, 0xEFC2, 0x5C6A, 0xEFC3, 0x5C6C, 0xC4DD, 0x5C6D, 0xF8A8, 0x5C6E, 0xC94B, 0x5C6F, 0xA4D9, 0x5C71, 0xA473, + 0x5C73, 0xC977, 0x5C74, 0xC976, 0x5C79, 0xA67A, 0x5C7A, 0xC9D7, 0x5C7B, 0xC9D8, 0x5C7C, 0xC9D6, 0x5C7E, 0xC9D9, 0x5C86, 0xCAC7, + 0x5C88, 0xCAC2, 0x5C89, 0xCAC4, 0x5C8A, 0xCAC6, 0x5C8B, 0xCAC3, 0x5C8C, 0xA7C4, 0x5C8D, 0xCAC0, 0x5C8F, 0xCAC1, 0x5C90, 0xA7C1, + 0x5C91, 0xA7C2, 0x5C92, 0xCAC5, 0x5C93, 0xCAC8, 0x5C94, 0xA7C3, 0x5C95, 0xCAC9, 0x5C9D, 0xCC68, 0x5C9F, 0xCC62, 0x5CA0, 0xCC5D, + 0x5CA1, 0xA9A3, 0x5CA2, 0xCC65, 0x5CA3, 0xCC63, 0x5CA4, 0xCC5C, 0x5CA5, 0xCC69, 0x5CA6, 0xCC6C, 0x5CA7, 0xCC67, 0x5CA8, 0xCC60, + 0x5CA9, 0xA9A5, 0x5CAA, 0xCC66, 0x5CAB, 0xA9A6, 0x5CAC, 0xCC61, 0x5CAD, 0xCC64, 0x5CAE, 0xCC5B, 0x5CAF, 0xCC5F, 0x5CB0, 0xCC6B, + 0x5CB1, 0xA9A7, 0x5CB3, 0xA9A8, 0x5CB5, 0xCC5E, 0x5CB6, 0xCC6A, 0x5CB7, 0xA9A2, 0x5CB8, 0xA9A4, 0x5CC6, 0xCEAB, 0x5CC7, 0xCEA4, + 0x5CC8, 0xCEAA, 0x5CC9, 0xCEA3, 0x5CCA, 0xCEA5, 0x5CCB, 0xCE7D, 0x5CCC, 0xCE7B, 0x5CCE, 0xCEAC, 0x5CCF, 0xCEA9, 0x5CD0, 0xCE79, + 0x5CD2, 0xABD0, 0x5CD3, 0xCEA7, 0x5CD4, 0xCEA8, 0x5CD6, 0xCEA6, 0x5CD7, 0xCE7C, 0x5CD8, 0xCE7A, 0x5CD9, 0xABCF, 0x5CDA, 0xCEA2, + 0x5CDB, 0xCE7E, 0x5CDE, 0xCEA1, 0x5CDF, 0xCEAD, 0x5CE8, 0xAE6F, 0x5CEA, 0xAE6E, 0x5CEC, 0xD16C, 0x5CED, 0xAE6B, 0x5CEE, 0xD16E, + 0x5CF0, 0xAE70, 0x5CF1, 0xD16F, 0x5CF4, 0xAE73, 0x5CF6, 0xAE71, 0x5CF7, 0xD170, 0x5CF8, 0xCEAE, 0x5CF9, 0xD172, 0x5CFB, 0xAE6D, + 0x5CFD, 0xAE6C, 0x5CFF, 0xD16D, 0x5D00, 0xD171, 0x5D01, 0xAE72, 0x5D06, 0xB153, 0x5D07, 0xB152, 0x5D0B, 0xD4F5, 0x5D0C, 0xD4F9, + 0x5D0D, 0xD4FB, 0x5D0E, 0xB154, 0x5D0F, 0xD4FE, 0x5D11, 0xB158, 0x5D12, 0xD541, 0x5D14, 0xB15A, 0x5D16, 0xB156, 0x5D17, 0xB15E, + 0x5D19, 0xB15B, 0x5D1A, 0xD4F7, 0x5D1B, 0xB155, 0x5D1D, 0xD4F6, 0x5D1E, 0xD4F4, 0x5D1F, 0xD543, 0x5D20, 0xD4F8, 0x5D22, 0xB157, + 0x5D23, 0xD542, 0x5D24, 0xB15C, 0x5D25, 0xD4FD, 0x5D26, 0xD4FC, 0x5D27, 0xB15D, 0x5D28, 0xD4FA, 0x5D29, 0xB159, 0x5D2E, 0xD544, + 0x5D30, 0xD540, 0x5D31, 0xD8E7, 0x5D32, 0xD8EE, 0x5D33, 0xD8E3, 0x5D34, 0xB451, 0x5D35, 0xD8DF, 0x5D36, 0xD8EF, 0x5D37, 0xD8D9, + 0x5D38, 0xD8EC, 0x5D39, 0xD8EA, 0x5D3A, 0xD8E4, 0x5D3C, 0xD8ED, 0x5D3D, 0xD8E6, 0x5D3F, 0xD8DE, 0x5D40, 0xD8F0, 0x5D41, 0xD8DC, + 0x5D42, 0xD8E9, 0x5D43, 0xD8DA, 0x5D45, 0xD8F1, 0x5D47, 0xB452, 0x5D49, 0xD8EB, 0x5D4A, 0xDD4F, 0x5D4B, 0xD8DD, 0x5D4C, 0xB44F, + 0x5D4E, 0xD8E1, 0x5D50, 0xB450, 0x5D51, 0xD8E0, 0x5D52, 0xD8E5, 0x5D55, 0xD8E2, 0x5D59, 0xD8E8, 0x5D5E, 0xDD53, 0x5D62, 0xDD56, + 0x5D63, 0xDD4E, 0x5D65, 0xDD50, 0x5D67, 0xDD55, 0x5D68, 0xDD54, 0x5D69, 0xB743, 0x5D6B, 0xD8DB, 0x5D6C, 0xDD52, 0x5D6F, 0xB744, + 0x5D71, 0xDD4D, 0x5D72, 0xDD51, 0x5D77, 0xE1A9, 0x5D79, 0xE1B0, 0x5D7A, 0xE1A7, 0x5D7C, 0xE1AE, 0x5D7D, 0xE1A5, 0x5D7E, 0xE1AD, + 0x5D7F, 0xE1B1, 0x5D80, 0xE1A4, 0x5D81, 0xE1A8, 0x5D82, 0xE1A3, 0x5D84, 0xB9F1, 0x5D86, 0xE1A6, 0x5D87, 0xB9F2, 0x5D88, 0xE1AC, + 0x5D89, 0xE1AB, 0x5D8A, 0xE1AA, 0x5D8D, 0xE1AF, 0x5D92, 0xE565, 0x5D93, 0xE567, 0x5D94, 0xBC6B, 0x5D95, 0xE568, 0x5D97, 0xE563, + 0x5D99, 0xE562, 0x5D9A, 0xE56C, 0x5D9C, 0xE56A, 0x5D9D, 0xBC6A, 0x5D9E, 0xE56D, 0x5D9F, 0xE564, 0x5DA0, 0xE569, 0x5DA1, 0xE56B, + 0x5DA2, 0xE566, 0x5DA7, 0xE961, 0x5DA8, 0xE966, 0x5DA9, 0xE960, 0x5DAA, 0xE965, 0x5DAC, 0xE95E, 0x5DAD, 0xE968, 0x5DAE, 0xE964, + 0x5DAF, 0xE969, 0x5DB0, 0xE963, 0x5DB1, 0xE95F, 0x5DB2, 0xE967, 0x5DB4, 0xE96A, 0x5DB5, 0xE962, 0x5DB7, 0xECDA, 0x5DB8, 0xC0AF, + 0x5DBA, 0xC0AD, 0x5DBC, 0xC0AC, 0x5DBD, 0xC0AE, 0x5DC0, 0xEFC4, 0x5DC2, 0xF172, 0x5DC3, 0xF1FD, 0x5DC6, 0xF444, 0x5DC7, 0xF445, + 0x5DC9, 0xC460, 0x5DCB, 0xF5C9, 0x5DCD, 0xC4DE, 0x5DCF, 0xF5CA, 0x5DD1, 0xF6DE, 0x5DD2, 0xC572, 0x5DD4, 0xC571, 0x5DD5, 0xF6DD, + 0x5DD6, 0xC5C9, 0x5DD8, 0xF7D6, 0x5DDD, 0xA474, 0x5DDE, 0xA67B, 0x5DDF, 0xC9DA, 0x5DE0, 0xCACA, 0x5DE1, 0xA8B5, 0x5DE2, 0xB15F, + 0x5DE5, 0xA475, 0x5DE6, 0xA5AA, 0x5DE7, 0xA5A9, 0x5DE8, 0xA5A8, 0x5DEB, 0xA7C5, 0x5DEE, 0xAE74, 0x5DF0, 0xDD57, 0x5DF1, 0xA476, + 0x5DF2, 0xA477, 0x5DF3, 0xA478, 0x5DF4, 0xA4DA, 0x5DF7, 0xABD1, 0x5DF9, 0xCEAF, 0x5DFD, 0xB453, 0x5DFE, 0xA479, 0x5DFF, 0xC95D, + 0x5E02, 0xA5AB, 0x5E03, 0xA5AC, 0x5E04, 0xC978, 0x5E06, 0xA67C, 0x5E0A, 0xCACB, 0x5E0C, 0xA7C6, 0x5E0E, 0xCACC, 0x5E11, 0xA9AE, + 0x5E14, 0xCC6E, 0x5E15, 0xA9AC, 0x5E16, 0xA9AB, 0x5E17, 0xCC6D, 0x5E18, 0xA9A9, 0x5E19, 0xCC6F, 0x5E1A, 0xA9AA, 0x5E1B, 0xA9AD, + 0x5E1D, 0xABD2, 0x5E1F, 0xABD4, 0x5E20, 0xCEB3, 0x5E21, 0xCEB0, 0x5E22, 0xCEB1, 0x5E23, 0xCEB2, 0x5E24, 0xCEB4, 0x5E25, 0xABD3, + 0x5E28, 0xD174, 0x5E29, 0xD173, 0x5E2B, 0xAE76, 0x5E2D, 0xAE75, 0x5E33, 0xB162, 0x5E34, 0xD546, 0x5E36, 0xB161, 0x5E37, 0xB163, + 0x5E38, 0xB160, 0x5E3D, 0xB455, 0x5E3E, 0xD545, 0x5E40, 0xB456, 0x5E41, 0xD8F3, 0x5E43, 0xB457, 0x5E44, 0xD8F2, 0x5E45, 0xB454, + 0x5E4A, 0xDD5A, 0x5E4B, 0xDD5C, 0x5E4C, 0xB745, 0x5E4D, 0xDD5B, 0x5E4E, 0xDD59, 0x5E4F, 0xDD58, 0x5E53, 0xE1B4, 0x5E54, 0xB9F7, + 0x5E55, 0xB9F5, 0x5E57, 0xB9F6, 0x5E58, 0xE1B2, 0x5E59, 0xE1B3, 0x5E5B, 0xB9F3, 0x5E5C, 0xE571, 0x5E5D, 0xE56F, 0x5E5F, 0xBC6D, + 0x5E60, 0xE570, 0x5E61, 0xBC6E, 0x5E62, 0xBC6C, 0x5E63, 0xB9F4, 0x5E66, 0xE96D, 0x5E67, 0xE96B, 0x5E68, 0xE96C, 0x5E69, 0xE56E, + 0x5E6A, 0xECDC, 0x5E6B, 0xC0B0, 0x5E6C, 0xECDB, 0x5E6D, 0xEFC5, 0x5E6E, 0xEFC6, 0x5E6F, 0xE96E, 0x5E70, 0xF1FE, 0x5E72, 0xA47A, + 0x5E73, 0xA5AD, 0x5E74, 0xA67E, 0x5E75, 0xC9DB, 0x5E76, 0xA67D, 0x5E78, 0xA9AF, 0x5E79, 0xB746, 0x5E7B, 0xA4DB, 0x5E7C, 0xA5AE, + 0x5E7D, 0xABD5, 0x5E7E, 0xB458, 0x5E80, 0xC979, 0x5E82, 0xC97A, 0x5E84, 0xC9DC, 0x5E87, 0xA7C8, 0x5E88, 0xCAD0, 0x5E89, 0xCACE, + 0x5E8A, 0xA7C9, 0x5E8B, 0xCACD, 0x5E8C, 0xCACF, 0x5E8D, 0xCAD1, 0x5E8F, 0xA7C7, 0x5E95, 0xA9B3, 0x5E96, 0xA9B4, 0x5E97, 0xA9B1, + 0x5E9A, 0xA9B0, 0x5E9B, 0xCEB8, 0x5E9C, 0xA9B2, 0x5EA0, 0xABD6, 0x5EA2, 0xCEB7, 0x5EA3, 0xCEB9, 0x5EA4, 0xCEB6, 0x5EA5, 0xCEBA, + 0x5EA6, 0xABD7, 0x5EA7, 0xAE79, 0x5EA8, 0xD175, 0x5EAA, 0xD177, 0x5EAB, 0xAE77, 0x5EAC, 0xD178, 0x5EAD, 0xAE78, 0x5EAE, 0xD176, + 0x5EB0, 0xCEB5, 0x5EB1, 0xD547, 0x5EB2, 0xD54A, 0x5EB3, 0xD54B, 0x5EB4, 0xD548, 0x5EB5, 0xB167, 0x5EB6, 0xB166, 0x5EB7, 0xB164, + 0x5EB8, 0xB165, 0x5EB9, 0xD549, 0x5EBE, 0xB168, 0x5EC1, 0xB45A, 0x5EC2, 0xB45B, 0x5EC4, 0xB45C, 0x5EC5, 0xDD5D, 0x5EC6, 0xDD5F, + 0x5EC7, 0xDD61, 0x5EC8, 0xB748, 0x5EC9, 0xB747, 0x5ECA, 0xB459, 0x5ECB, 0xDD60, 0x5ECC, 0xDD5E, 0x5ECE, 0xE1B8, 0x5ED1, 0xE1B6, + 0x5ED2, 0xE1BC, 0x5ED3, 0xB9F8, 0x5ED4, 0xE1BD, 0x5ED5, 0xE1BA, 0x5ED6, 0xB9F9, 0x5ED7, 0xE1B7, 0x5ED8, 0xE1B5, 0x5ED9, 0xE1BB, + 0x5EDA, 0xBC70, 0x5EDB, 0xE573, 0x5EDC, 0xE1B9, 0x5EDD, 0xBC72, 0x5EDE, 0xE574, 0x5EDF, 0xBC71, 0x5EE0, 0xBC74, 0x5EE1, 0xE575, + 0x5EE2, 0xBC6F, 0x5EE3, 0xBC73, 0x5EE5, 0xE973, 0x5EE6, 0xE971, 0x5EE7, 0xE970, 0x5EE8, 0xE972, 0x5EE9, 0xE96F, 0x5EEC, 0xC366, + 0x5EEE, 0xF446, 0x5EEF, 0xF447, 0x5EF1, 0xF5CB, 0x5EF2, 0xF6DF, 0x5EF3, 0xC655, 0x5EF6, 0xA9B5, 0x5EF7, 0xA7CA, 0x5EFA, 0xABD8, + 0x5EFE, 0xA47B, 0x5EFF, 0xA4DC, 0x5F01, 0xA5AF, 0x5F02, 0xC9DD, 0x5F04, 0xA7CB, 0x5F05, 0xCAD2, 0x5F07, 0xCEBB, 0x5F08, 0xABD9, + 0x5F0A, 0xB9FA, 0x5F0B, 0xA47C, 0x5F0F, 0xA6A1, 0x5F12, 0xB749, 0x5F13, 0xA47D, 0x5F14, 0xA4DD, 0x5F15, 0xA4DE, 0x5F17, 0xA5B1, + 0x5F18, 0xA5B0, 0x5F1A, 0xC9DE, 0x5F1B, 0xA6A2, 0x5F1D, 0xCAD3, 0x5F1F, 0xA7CC, 0x5F22, 0xCC71, 0x5F23, 0xCC72, 0x5F24, 0xCC73, + 0x5F26, 0xA9B6, 0x5F27, 0xA9B7, 0x5F28, 0xCC70, 0x5F29, 0xA9B8, 0x5F2D, 0xABDA, 0x5F2E, 0xCEBC, 0x5F30, 0xD17A, 0x5F31, 0xAE7A, + 0x5F33, 0xD179, 0x5F35, 0xB169, 0x5F36, 0xD54C, 0x5F37, 0xB16A, 0x5F38, 0xD54D, 0x5F3C, 0xB45D, 0x5F40, 0xDD62, 0x5F43, 0xE1BF, + 0x5F44, 0xE1BE, 0x5F46, 0xB9FB, 0x5F48, 0xBC75, 0x5F49, 0xE576, 0x5F4A, 0xBECA, 0x5F4B, 0xE974, 0x5F4C, 0xC0B1, 0x5F4E, 0xC573, + 0x5F4F, 0xF7D8, 0x5F54, 0xCC74, 0x5F56, 0xCEBD, 0x5F57, 0xB16B, 0x5F58, 0xD8F4, 0x5F59, 0xB74A, 0x5F5D, 0xC255, 0x5F62, 0xA7CE, + 0x5F64, 0xA7CD, 0x5F65, 0xABDB, 0x5F67, 0xD17B, 0x5F69, 0xB16D, 0x5F6A, 0xB343, 0x5F6B, 0xB16E, 0x5F6C, 0xB16C, 0x5F6D, 0xB45E, + 0x5F6F, 0xE1C0, 0x5F70, 0xB9FC, 0x5F71, 0xBC76, 0x5F73, 0xC94C, 0x5F74, 0xC9DF, 0x5F76, 0xCAD5, 0x5F77, 0xA7CF, 0x5F78, 0xCAD4, + 0x5F79, 0xA7D0, 0x5F7C, 0xA9BC, 0x5F7D, 0xCC77, 0x5F7E, 0xCC76, 0x5F7F, 0xA9BB, 0x5F80, 0xA9B9, 0x5F81, 0xA9BA, 0x5F82, 0xCC75, + 0x5F85, 0xABDD, 0x5F86, 0xCEBE, 0x5F87, 0xABE0, 0x5F88, 0xABDC, 0x5F89, 0xABE2, 0x5F8A, 0xABDE, 0x5F8B, 0xABDF, 0x5F8C, 0xABE1, + 0x5F90, 0xAE7D, 0x5F91, 0xAE7C, 0x5F92, 0xAE7B, 0x5F96, 0xD54F, 0x5F97, 0xB16F, 0x5F98, 0xB172, 0x5F99, 0xB170, 0x5F9B, 0xD54E, + 0x5F9C, 0xB175, 0x5F9E, 0xB171, 0x5F9F, 0xD550, 0x5FA0, 0xB174, 0x5FA1, 0xB173, 0x5FA5, 0xD8F6, 0x5FA6, 0xD8F5, 0x5FA8, 0xB461, + 0x5FA9, 0xB45F, 0x5FAA, 0xB460, 0x5FAB, 0xD8F7, 0x5FAC, 0xB74B, 0x5FAD, 0xDD64, 0x5FAE, 0xB74C, 0x5FAF, 0xDD63, 0x5FB2, 0xE577, + 0x5FB5, 0xBC78, 0x5FB6, 0xE1C1, 0x5FB7, 0xBC77, 0x5FB9, 0xB9FD, 0x5FBB, 0xECDE, 0x5FBC, 0xE975, 0x5FBD, 0xC0B2, 0x5FBE, 0xECDD, + 0x5FBF, 0xF240, 0x5FC0, 0xF448, 0x5FC1, 0xF449, 0x5FC3, 0xA4DF, 0x5FC5, 0xA5B2, 0x5FC9, 0xC97B, 0x5FCC, 0xA7D2, 0x5FCD, 0xA7D4, + 0x5FCF, 0xC9E2, 0x5FD0, 0xCAD8, 0x5FD1, 0xCAD7, 0x5FD2, 0xCAD6, 0x5FD4, 0xC9E1, 0x5FD5, 0xC9E0, 0x5FD6, 0xA6A4, 0x5FD7, 0xA7D3, + 0x5FD8, 0xA7D1, 0x5FD9, 0xA6A3, 0x5FDD, 0xA9BD, 0x5FDE, 0xCC78, 0x5FE0, 0xA9BE, 0x5FE1, 0xCADD, 0x5FE3, 0xCADF, 0x5FE4, 0xCADE, + 0x5FE5, 0xCC79, 0x5FE8, 0xCADA, 0x5FEA, 0xA7D8, 0x5FEB, 0xA7D6, 0x5FED, 0xCAD9, 0x5FEE, 0xCADB, 0x5FEF, 0xCAE1, 0x5FF1, 0xA7D5, + 0x5FF3, 0xCADC, 0x5FF4, 0xCAE5, 0x5FF5, 0xA9C0, 0x5FF7, 0xCAE2, 0x5FF8, 0xA7D7, 0x5FFA, 0xCAE0, 0x5FFB, 0xCAE3, 0x5FFD, 0xA9BF, + 0x5FFF, 0xA9C1, 0x6000, 0xCAE4, 0x6009, 0xCCAF, 0x600A, 0xCCA2, 0x600B, 0xCC7E, 0x600C, 0xCCAE, 0x600D, 0xCCA9, 0x600E, 0xABE7, + 0x600F, 0xA9C2, 0x6010, 0xCCAA, 0x6011, 0xCCAD, 0x6012, 0xABE3, 0x6013, 0xCCAC, 0x6014, 0xA9C3, 0x6015, 0xA9C8, 0x6016, 0xA9C6, + 0x6017, 0xCCA3, 0x6019, 0xCC7C, 0x601A, 0xCCA5, 0x601B, 0xA9CD, 0x601C, 0xCCB0, 0x601D, 0xABE4, 0x601E, 0xCCA6, 0x6020, 0xABE5, + 0x6021, 0xA9C9, 0x6022, 0xCCA8, 0x6024, 0xCECD, 0x6025, 0xABE6, 0x6026, 0xCC7B, 0x6027, 0xA9CA, 0x6028, 0xABE8, 0x6029, 0xA9CB, + 0x602A, 0xA9C7, 0x602B, 0xA9CC, 0x602C, 0xCCA7, 0x602D, 0xCC7A, 0x602E, 0xCCAB, 0x602F, 0xA9C4, 0x6032, 0xCC7D, 0x6033, 0xCCA4, + 0x6034, 0xCCA1, 0x6035, 0xA9C5, 0x6037, 0xCEBF, 0x6039, 0xCEC0, 0x6040, 0xCECA, 0x6041, 0xD1A1, 0x6042, 0xCECB, 0x6043, 0xABEE, + 0x6044, 0xCECE, 0x6045, 0xCEC4, 0x6046, 0xABED, 0x6047, 0xCEC6, 0x6049, 0xCEC7, 0x604C, 0xCEC9, 0x604D, 0xABE9, 0x6050, 0xAEA3, + 0x6052, 0xF9DA, 0x6053, 0xCEC5, 0x6054, 0xCEC1, 0x6055, 0xAEA4, 0x6058, 0xCECF, 0x6059, 0xAE7E, 0x605A, 0xD17D, 0x605B, 0xCEC8, + 0x605D, 0xD17C, 0x605E, 0xCEC3, 0x605F, 0xCECC, 0x6062, 0xABEC, 0x6063, 0xAEA1, 0x6064, 0xABF2, 0x6065, 0xAEA2, 0x6066, 0xCED0, + 0x6067, 0xD17E, 0x6068, 0xABEB, 0x6069, 0xAEA6, 0x606A, 0xABF1, 0x606B, 0xABF0, 0x606C, 0xABEF, 0x606D, 0xAEA5, 0x606E, 0xCED1, + 0x606F, 0xAEA7, 0x6070, 0xABEA, 0x6072, 0xCEC2, 0x607F, 0xB176, 0x6080, 0xD1A4, 0x6081, 0xD1A6, 0x6083, 0xD1A8, 0x6084, 0xAEA8, + 0x6085, 0xAEAE, 0x6086, 0xD553, 0x6087, 0xD1AC, 0x6088, 0xD1A3, 0x6089, 0xB178, 0x608A, 0xD551, 0x608C, 0xAEAD, 0x608D, 0xAEAB, + 0x608E, 0xD1AE, 0x6090, 0xD552, 0x6092, 0xD1A5, 0x6094, 0xAEAC, 0x6095, 0xD1A9, 0x6096, 0xAEAF, 0x6097, 0xD1AB, 0x609A, 0xAEAA, + 0x609B, 0xD1AA, 0x609C, 0xD1AD, 0x609D, 0xD1A7, 0x609F, 0xAEA9, 0x60A0, 0xB179, 0x60A2, 0xD1A2, 0x60A3, 0xB177, 0x60A8, 0xB17A, + 0x60B0, 0xD555, 0x60B1, 0xD55E, 0x60B2, 0xB464, 0x60B4, 0xB17C, 0x60B5, 0xB1A3, 0x60B6, 0xB465, 0x60B7, 0xD560, 0x60B8, 0xB1AA, + 0x60B9, 0xD8F9, 0x60BA, 0xD556, 0x60BB, 0xB1A2, 0x60BC, 0xB1A5, 0x60BD, 0xB17E, 0x60BE, 0xD554, 0x60BF, 0xD562, 0x60C0, 0xD565, + 0x60C1, 0xD949, 0x60C3, 0xD563, 0x60C4, 0xD8FD, 0x60C5, 0xB1A1, 0x60C6, 0xB1A8, 0x60C7, 0xB1AC, 0x60C8, 0xD55D, 0x60C9, 0xD8F8, + 0x60CA, 0xD561, 0x60CB, 0xB17B, 0x60CC, 0xD8FA, 0x60CD, 0xD564, 0x60CE, 0xD8FC, 0x60CF, 0xD559, 0x60D1, 0xB462, 0x60D3, 0xD557, + 0x60D4, 0xD558, 0x60D5, 0xB1A7, 0x60D8, 0xB1A6, 0x60D9, 0xD55B, 0x60DA, 0xB1AB, 0x60DB, 0xD55F, 0x60DC, 0xB1A4, 0x60DD, 0xD55C, + 0x60DF, 0xB1A9, 0x60E0, 0xB466, 0x60E1, 0xB463, 0x60E2, 0xD8FB, 0x60E4, 0xD55A, 0x60E6, 0xB17D, 0x60F0, 0xB46B, 0x60F1, 0xB46F, + 0x60F2, 0xD940, 0x60F3, 0xB751, 0x60F4, 0xB46D, 0x60F5, 0xD944, 0x60F6, 0xB471, 0x60F7, 0xDD65, 0x60F8, 0xD946, 0x60F9, 0xB753, + 0x60FA, 0xB469, 0x60FB, 0xB46C, 0x60FC, 0xD947, 0x60FE, 0xD948, 0x60FF, 0xD94E, 0x6100, 0xB473, 0x6101, 0xB754, 0x6103, 0xD94A, + 0x6104, 0xD94F, 0x6105, 0xD943, 0x6106, 0xB75E, 0x6108, 0xB755, 0x6109, 0xB472, 0x610A, 0xD941, 0x610B, 0xD950, 0x610D, 0xB75D, + 0x610E, 0xB470, 0x610F, 0xB74E, 0x6110, 0xD94D, 0x6112, 0xB474, 0x6113, 0xD945, 0x6114, 0xD8FE, 0x6115, 0xB46A, 0x6116, 0xD942, + 0x6118, 0xD94B, 0x611A, 0xB74D, 0x611B, 0xB752, 0x611C, 0xB467, 0x611D, 0xD94C, 0x611F, 0xB750, 0x6123, 0xB468, 0x6127, 0xB75C, + 0x6128, 0xE1C3, 0x6129, 0xDD70, 0x612B, 0xDD68, 0x612C, 0xE1C2, 0x612E, 0xDD6C, 0x612F, 0xDD6E, 0x6132, 0xDD6B, 0x6134, 0xB75B, + 0x6136, 0xDD6A, 0x6137, 0xB75F, 0x613B, 0xE1D2, 0x613E, 0xB75A, 0x613F, 0xBA40, 0x6140, 0xDD71, 0x6141, 0xE1C4, 0x6144, 0xB758, + 0x6145, 0xDD69, 0x6146, 0xDD6D, 0x6147, 0xB9FE, 0x6148, 0xB74F, 0x6149, 0xDD66, 0x614A, 0xDD67, 0x614B, 0xBA41, 0x614C, 0xB757, + 0x614D, 0xB759, 0x614E, 0xB756, 0x614F, 0xDD6F, 0x6152, 0xE1C8, 0x6153, 0xE1C9, 0x6154, 0xE1CE, 0x6155, 0xBC7D, 0x6156, 0xE1D5, + 0x6158, 0xBA47, 0x615A, 0xBA46, 0x615B, 0xE1D0, 0x615D, 0xBC7C, 0x615E, 0xE1C5, 0x615F, 0xBA45, 0x6161, 0xE1D4, 0x6162, 0xBA43, + 0x6163, 0xBA44, 0x6165, 0xE1D1, 0x6166, 0xE5AA, 0x6167, 0xBC7A, 0x6168, 0xB46E, 0x616A, 0xE1D3, 0x616B, 0xBCA3, 0x616C, 0xE1CB, + 0x616E, 0xBC7B, 0x6170, 0xBCA2, 0x6171, 0xE1C6, 0x6172, 0xE1CA, 0x6173, 0xE1C7, 0x6174, 0xE1CD, 0x6175, 0xBA48, 0x6176, 0xBC79, + 0x6177, 0xBA42, 0x6179, 0xE57A, 0x617A, 0xE1CF, 0x617C, 0xBCA1, 0x617E, 0xBCA4, 0x6180, 0xE1CC, 0x6182, 0xBC7E, 0x6183, 0xE579, + 0x6189, 0xE57E, 0x618A, 0xBECE, 0x618B, 0xE578, 0x618C, 0xE9A3, 0x618D, 0xE5A9, 0x618E, 0xBCA8, 0x6190, 0xBCA6, 0x6191, 0xBECC, + 0x6192, 0xE5A6, 0x6193, 0xE5A2, 0x6194, 0xBCAC, 0x6196, 0xE978, 0x619A, 0xBCAA, 0x619B, 0xE5A1, 0x619D, 0xE976, 0x619F, 0xE5A5, + 0x61A1, 0xE5A8, 0x61A2, 0xE57D, 0x61A4, 0xBCAB, 0x61A7, 0xBCA5, 0x61A8, 0xE977, 0x61A9, 0xBECD, 0x61AA, 0xE5A7, 0x61AB, 0xBCA7, + 0x61AC, 0xBCA9, 0x61AD, 0xE5A4, 0x61AE, 0xBCAD, 0x61AF, 0xE5A3, 0x61B0, 0xE57C, 0x61B1, 0xE57B, 0x61B2, 0xBECB, 0x61B3, 0xE5AB, + 0x61B4, 0xE97A, 0x61B5, 0xECE0, 0x61B6, 0xBED0, 0x61B8, 0xE9A2, 0x61BA, 0xE97E, 0x61BC, 0xECE1, 0x61BE, 0xBED1, 0x61BF, 0xE9A1, + 0x61C1, 0xE97C, 0x61C2, 0xC0B4, 0x61C3, 0xECDF, 0x61C5, 0xE979, 0x61C6, 0xE97B, 0x61C7, 0xC0B5, 0x61C8, 0xBED3, 0x61C9, 0xC0B3, + 0x61CA, 0xBED2, 0x61CB, 0xC0B7, 0x61CC, 0xE97D, 0x61CD, 0xBECF, 0x61D6, 0xEFCF, 0x61D8, 0xEFC7, 0x61DE, 0xECE7, 0x61DF, 0xEFC8, + 0x61E0, 0xECE3, 0x61E3, 0xC256, 0x61E4, 0xECE5, 0x61E5, 0xECE4, 0x61E6, 0xC0B6, 0x61E7, 0xECE2, 0x61E8, 0xECE6, 0x61E9, 0xEFD0, + 0x61EA, 0xEFCC, 0x61EB, 0xEFCE, 0x61ED, 0xEFC9, 0x61EE, 0xEFCA, 0x61F0, 0xEFCD, 0x61F1, 0xEFCB, 0x61F2, 0xC367, 0x61F5, 0xC36A, + 0x61F6, 0xC369, 0x61F7, 0xC368, 0x61F8, 0xC461, 0x61F9, 0xF44A, 0x61FA, 0xC462, 0x61FB, 0xF241, 0x61FC, 0xC4DF, 0x61FD, 0xF5CC, + 0x61FE, 0xC4E0, 0x61FF, 0xC574, 0x6200, 0xC5CA, 0x6201, 0xF7D9, 0x6203, 0xF7DA, 0x6204, 0xF7DB, 0x6207, 0xF9BA, 0x6208, 0xA4E0, + 0x6209, 0xC97C, 0x620A, 0xA5B3, 0x620C, 0xA6A6, 0x620D, 0xA6A7, 0x620E, 0xA6A5, 0x6210, 0xA6A8, 0x6211, 0xA7DA, 0x6212, 0xA7D9, + 0x6214, 0xCCB1, 0x6215, 0xA9CF, 0x6216, 0xA9CE, 0x6219, 0xD1AF, 0x621A, 0xB1AD, 0x621B, 0xB1AE, 0x621F, 0xB475, 0x6220, 0xDD72, + 0x6221, 0xB760, 0x6222, 0xB761, 0x6223, 0xDD74, 0x6224, 0xDD76, 0x6225, 0xDD75, 0x6227, 0xE1D7, 0x6229, 0xE1D6, 0x622A, 0xBA49, + 0x622B, 0xE1D8, 0x622D, 0xE5AC, 0x622E, 0xBCAE, 0x6230, 0xBED4, 0x6232, 0xC0B8, 0x6233, 0xC257, 0x6234, 0xC0B9, 0x6236, 0xA4E1, + 0x623A, 0xCAE6, 0x623D, 0xCCB2, 0x623E, 0xA9D1, 0x623F, 0xA9D0, 0x6240, 0xA9D2, 0x6241, 0xABF3, 0x6242, 0xCED2, 0x6243, 0xCED3, + 0x6246, 0xD1B0, 0x6247, 0xAEB0, 0x6248, 0xB1AF, 0x6249, 0xB476, 0x624A, 0xD951, 0x624B, 0xA4E2, 0x624D, 0xA47E, 0x624E, 0xA4E3, + 0x6250, 0xC97D, 0x6251, 0xA5B7, 0x6252, 0xA5B6, 0x6253, 0xA5B4, 0x6254, 0xA5B5, 0x6258, 0xA6AB, 0x6259, 0xC9E9, 0x625A, 0xC9EB, + 0x625B, 0xA6AA, 0x625C, 0xC9E3, 0x625E, 0xC9E4, 0x6260, 0xC9EA, 0x6261, 0xC9E6, 0x6262, 0xC9E8, 0x6263, 0xA6A9, 0x6264, 0xC9E5, + 0x6265, 0xC9EC, 0x6266, 0xC9E7, 0x626D, 0xA7E1, 0x626E, 0xA7EA, 0x626F, 0xA7E8, 0x6270, 0xCAF0, 0x6271, 0xCAED, 0x6272, 0xCAF5, + 0x6273, 0xA7E6, 0x6274, 0xCAF6, 0x6276, 0xA7DF, 0x6277, 0xCAF3, 0x6279, 0xA7E5, 0x627A, 0xCAEF, 0x627B, 0xCAEE, 0x627C, 0xA7E3, + 0x627D, 0xCAF4, 0x627E, 0xA7E4, 0x627F, 0xA9D3, 0x6280, 0xA7DE, 0x6281, 0xCAF1, 0x6283, 0xCAE7, 0x6284, 0xA7DB, 0x6286, 0xA7EE, + 0x6287, 0xCAEC, 0x6288, 0xCAF2, 0x6289, 0xA7E0, 0x628A, 0xA7E2, 0x628C, 0xCAE8, 0x628E, 0xCAE9, 0x628F, 0xCAEA, 0x6291, 0xA7ED, + 0x6292, 0xA7E7, 0x6293, 0xA7EC, 0x6294, 0xCAEB, 0x6295, 0xA7EB, 0x6296, 0xA7DD, 0x6297, 0xA7DC, 0x6298, 0xA7E9, 0x62A8, 0xA9E1, + 0x62A9, 0xCCBE, 0x62AA, 0xCCB7, 0x62AB, 0xA9DC, 0x62AC, 0xA9EF, 0x62AD, 0xCCB3, 0x62AE, 0xCCBA, 0x62AF, 0xCCBC, 0x62B0, 0xCCBF, + 0x62B1, 0xA9EA, 0x62B3, 0xCCBB, 0x62B4, 0xCCB4, 0x62B5, 0xA9E8, 0x62B6, 0xCCB8, 0x62B8, 0xCCC0, 0x62B9, 0xA9D9, 0x62BB, 0xCCBD, + 0x62BC, 0xA9E3, 0x62BD, 0xA9E2, 0x62BE, 0xCCB6, 0x62BF, 0xA9D7, 0x62C2, 0xA9D8, 0x62C4, 0xA9D6, 0x62C6, 0xA9EE, 0x62C7, 0xA9E6, + 0x62C8, 0xA9E0, 0x62C9, 0xA9D4, 0x62CA, 0xCCB9, 0x62CB, 0xA9DF, 0x62CC, 0xA9D5, 0x62CD, 0xA9E7, 0x62CE, 0xA9F0, 0x62CF, 0xCED4, + 0x62D0, 0xA9E4, 0x62D1, 0xCCB5, 0x62D2, 0xA9DA, 0x62D3, 0xA9DD, 0x62D4, 0xA9DE, 0x62D6, 0xA9EC, 0x62D7, 0xA9ED, 0x62D8, 0xA9EB, + 0x62D9, 0xA9E5, 0x62DA, 0xA9E9, 0x62DB, 0xA9DB, 0x62DC, 0xABF4, 0x62EB, 0xCEDA, 0x62EC, 0xAC41, 0x62ED, 0xABF8, 0x62EE, 0xABFA, + 0x62EF, 0xAC40, 0x62F0, 0xCEE6, 0x62F1, 0xABFD, 0x62F2, 0xD1B1, 0x62F3, 0xAEB1, 0x62F4, 0xAC43, 0x62F5, 0xCED7, 0x62F6, 0xCEDF, + 0x62F7, 0xABFE, 0x62F8, 0xCEDE, 0x62F9, 0xCEDB, 0x62FA, 0xCEE3, 0x62FB, 0xCEE5, 0x62FC, 0xABF7, 0x62FD, 0xABFB, 0x62FE, 0xAC42, + 0x62FF, 0xAEB3, 0x6300, 0xCEE0, 0x6301, 0xABF9, 0x6302, 0xAC45, 0x6303, 0xCED9, 0x6307, 0xABFC, 0x6308, 0xAEB2, 0x6309, 0xABF6, + 0x630B, 0xCED6, 0x630C, 0xCEDD, 0x630D, 0xCED5, 0x630E, 0xCED8, 0x630F, 0xCEDC, 0x6310, 0xD1B2, 0x6311, 0xAC44, 0x6313, 0xCEE1, + 0x6314, 0xCEE2, 0x6315, 0xCEE4, 0x6316, 0xABF5, 0x6328, 0xAEC1, 0x6329, 0xD1BE, 0x632A, 0xAEBF, 0x632B, 0xAEC0, 0x632C, 0xD1B4, + 0x632D, 0xD1C4, 0x632F, 0xAEB6, 0x6332, 0xD566, 0x6333, 0xD1C6, 0x6334, 0xD1C0, 0x6336, 0xD1B7, 0x6338, 0xD1C9, 0x6339, 0xD1BA, + 0x633A, 0xAEBC, 0x633B, 0xD57D, 0x633C, 0xD1BD, 0x633D, 0xAEBE, 0x633E, 0xAEB5, 0x6340, 0xD1CB, 0x6341, 0xD1BF, 0x6342, 0xAEB8, + 0x6343, 0xD1B8, 0x6344, 0xD1B5, 0x6345, 0xD1B6, 0x6346, 0xAEB9, 0x6347, 0xD1C5, 0x6348, 0xD1CC, 0x6349, 0xAEBB, 0x634A, 0xD1BC, + 0x634B, 0xD1BB, 0x634C, 0xAEC3, 0x634D, 0xAEC2, 0x634E, 0xAEB4, 0x634F, 0xAEBA, 0x6350, 0xAEBD, 0x6351, 0xD1C8, 0x6354, 0xD1C2, + 0x6355, 0xAEB7, 0x6356, 0xD1B3, 0x6357, 0xD1CA, 0x6358, 0xD1C1, 0x6359, 0xD1C3, 0x635A, 0xD1C7, 0x6365, 0xD567, 0x6367, 0xB1B7, + 0x6368, 0xB1CB, 0x6369, 0xB1CA, 0x636B, 0xB1BF, 0x636D, 0xD579, 0x636E, 0xD575, 0x636F, 0xD572, 0x6370, 0xD5A6, 0x6371, 0xB1BA, + 0x6372, 0xB1B2, 0x6375, 0xD577, 0x6376, 0xB4A8, 0x6377, 0xB1B6, 0x6378, 0xD5A1, 0x637A, 0xB1CC, 0x637B, 0xB1C9, 0x637C, 0xD57B, + 0x637D, 0xD56A, 0x6380, 0xB1C8, 0x6381, 0xD5A3, 0x6382, 0xD569, 0x6383, 0xB1BD, 0x6384, 0xB1C1, 0x6385, 0xD5A2, 0x6387, 0xD573, + 0x6388, 0xB1C2, 0x6389, 0xB1BC, 0x638A, 0xD568, 0x638C, 0xB478, 0x638D, 0xD5A5, 0x638E, 0xD571, 0x638F, 0xB1C7, 0x6390, 0xD574, + 0x6391, 0xD5A4, 0x6392, 0xB1C6, 0x6394, 0xD952, 0x6396, 0xB1B3, 0x6397, 0xD56F, 0x6398, 0xB1B8, 0x6399, 0xB1C3, 0x639B, 0xB1BE, + 0x639C, 0xD578, 0x639D, 0xD56E, 0x639E, 0xD56C, 0x639F, 0xD57E, 0x63A0, 0xB1B0, 0x63A1, 0xB1C4, 0x63A2, 0xB1B4, 0x63A3, 0xB477, + 0x63A4, 0xD57C, 0x63A5, 0xB1B5, 0x63A7, 0xB1B1, 0x63A8, 0xB1C0, 0x63A9, 0xB1BB, 0x63AA, 0xB1B9, 0x63AB, 0xD570, 0x63AC, 0xB1C5, + 0x63AD, 0xD56D, 0x63AE, 0xD57A, 0x63AF, 0xD576, 0x63B0, 0xD954, 0x63B1, 0xD953, 0x63BD, 0xD56B, 0x63BE, 0xD964, 0x63C0, 0xB47A, + 0x63C2, 0xD96A, 0x63C3, 0xD959, 0x63C4, 0xD967, 0x63C5, 0xDD77, 0x63C6, 0xB47D, 0x63C7, 0xD96B, 0x63C8, 0xD96E, 0x63C9, 0xB47C, + 0x63CA, 0xD95C, 0x63CB, 0xD96D, 0x63CC, 0xD96C, 0x63CD, 0xB47E, 0x63CE, 0xD955, 0x63CF, 0xB479, 0x63D0, 0xB4A3, 0x63D2, 0xB4A1, + 0x63D3, 0xD969, 0x63D5, 0xD95F, 0x63D6, 0xB4A5, 0x63D7, 0xD970, 0x63D8, 0xD968, 0x63D9, 0xD971, 0x63DA, 0xB4AD, 0x63DB, 0xB4AB, + 0x63DC, 0xD966, 0x63DD, 0xD965, 0x63DF, 0xD963, 0x63E0, 0xD95D, 0x63E1, 0xB4A4, 0x63E3, 0xB4A2, 0x63E4, 0xD1B9, 0x63E5, 0xD956, + 0x63E7, 0xDDB7, 0x63E8, 0xD957, 0x63E9, 0xB47B, 0x63EA, 0xB4AA, 0x63EB, 0xDD79, 0x63ED, 0xB4A6, 0x63EE, 0xB4A7, 0x63EF, 0xD958, + 0x63F0, 0xD96F, 0x63F1, 0xDD78, 0x63F2, 0xD960, 0x63F3, 0xD95B, 0x63F4, 0xB4A9, 0x63F5, 0xD961, 0x63F6, 0xD95E, 0x63F9, 0xB4AE, + 0x6406, 0xB770, 0x6409, 0xDD7C, 0x640A, 0xDDB1, 0x640B, 0xDDB6, 0x640C, 0xDDAA, 0x640D, 0xB76C, 0x640E, 0xDDBB, 0x640F, 0xB769, + 0x6410, 0xDD7A, 0x6412, 0xDD7B, 0x6413, 0xB762, 0x6414, 0xB76B, 0x6415, 0xDDA4, 0x6416, 0xB76E, 0x6417, 0xB76F, 0x6418, 0xDDA5, + 0x641A, 0xDDB2, 0x641B, 0xDDB8, 0x641C, 0xB76A, 0x641E, 0xB764, 0x641F, 0xDDA3, 0x6420, 0xDD7D, 0x6421, 0xDDBA, 0x6422, 0xDDA8, + 0x6423, 0xDDA9, 0x6424, 0xDD7E, 0x6425, 0xDDB4, 0x6426, 0xDDAB, 0x6427, 0xDDB5, 0x6428, 0xDDAD, 0x642A, 0xB765, 0x642B, 0xE1D9, + 0x642C, 0xB768, 0x642D, 0xB766, 0x642E, 0xDDB9, 0x642F, 0xDDB0, 0x6430, 0xDDAC, 0x6433, 0xDDA1, 0x6434, 0xBA53, 0x6435, 0xDDAF, + 0x6436, 0xB76D, 0x6437, 0xDDA7, 0x6439, 0xDDA6, 0x643D, 0xB767, 0x643E, 0xB763, 0x643F, 0xE1EE, 0x6440, 0xDDB3, 0x6441, 0xDDAE, + 0x6443, 0xDDA2, 0x644B, 0xE1E9, 0x644D, 0xE1DA, 0x644E, 0xE1E5, 0x6450, 0xE1EC, 0x6451, 0xBA51, 0x6452, 0xB4AC, 0x6453, 0xE1EA, + 0x6454, 0xBA4C, 0x6458, 0xBA4B, 0x6459, 0xE1F1, 0x645B, 0xE1DB, 0x645C, 0xE1E8, 0x645D, 0xE1DC, 0x645E, 0xE1E7, 0x645F, 0xBA4F, + 0x6460, 0xE1EB, 0x6461, 0xD962, 0x6465, 0xE1F2, 0x6466, 0xE1E3, 0x6467, 0xBA52, 0x6468, 0xE5BA, 0x6469, 0xBCAF, 0x646B, 0xE1F0, + 0x646C, 0xE1EF, 0x646D, 0xBA54, 0x646E, 0xE5AD, 0x646F, 0xBCB0, 0x6470, 0xE5AE, 0x6472, 0xE1DF, 0x6473, 0xE1E0, 0x6474, 0xE1DD, + 0x6475, 0xE1E2, 0x6476, 0xE1DE, 0x6477, 0xE1F3, 0x6478, 0xBA4E, 0x6479, 0xBCB1, 0x647A, 0xBA50, 0x647B, 0xBA55, 0x647D, 0xE1E1, + 0x647F, 0xE1ED, 0x6482, 0xE1E6, 0x6485, 0xE5B1, 0x6487, 0xBA4A, 0x6488, 0xBCB4, 0x6489, 0xE9AA, 0x648A, 0xE5B6, 0x648B, 0xE5B5, + 0x648C, 0xE5B7, 0x648F, 0xE5B4, 0x6490, 0xBCB5, 0x6492, 0xBCBB, 0x6493, 0xBCB8, 0x6495, 0xBCB9, 0x6496, 0xE5AF, 0x6497, 0xE5B2, + 0x6498, 0xE5BC, 0x6499, 0xBCC1, 0x649A, 0xBCBF, 0x649C, 0xE5B3, 0x649D, 0xD95A, 0x649E, 0xBCB2, 0x649F, 0xE5B9, 0x64A0, 0xE5B0, + 0x64A2, 0xBCC2, 0x64A3, 0xE5B8, 0x64A4, 0xBA4D, 0x64A5, 0xBCB7, 0x64A6, 0xE1E4, 0x64A9, 0xBCBA, 0x64AB, 0xBCBE, 0x64AC, 0xBCC0, + 0x64AD, 0xBCBD, 0x64AE, 0xBCBC, 0x64B0, 0xBCB6, 0x64B1, 0xE5BB, 0x64B2, 0xBCB3, 0x64B3, 0xBCC3, 0x64BB, 0xBED8, 0x64BC, 0xBED9, + 0x64BD, 0xE9A9, 0x64BE, 0xBEE2, 0x64BF, 0xBEDF, 0x64C1, 0xBED6, 0x64C2, 0xBEDD, 0x64C3, 0xE9AB, 0x64C4, 0xBEDB, 0x64C5, 0xBED5, + 0x64C7, 0xBEDC, 0x64C9, 0xE9A8, 0x64CA, 0xC0BB, 0x64CB, 0xBED7, 0x64CD, 0xBEDE, 0x64CE, 0xC0BA, 0x64CF, 0xE9A7, 0x64D0, 0xE9A6, + 0x64D2, 0xBEE0, 0x64D4, 0xBEE1, 0x64D6, 0xE9A5, 0x64D7, 0xE9A4, 0x64D8, 0xC0BC, 0x64D9, 0xE9AE, 0x64DA, 0xBEDA, 0x64DB, 0xE9AC, + 0x64E0, 0xC0BD, 0x64E2, 0xC0C2, 0x64E3, 0xECEA, 0x64E4, 0xECEC, 0x64E6, 0xC0BF, 0x64E8, 0xECED, 0x64E9, 0xECE9, 0x64EB, 0xECEB, + 0x64EC, 0xC0C0, 0x64ED, 0xC0C3, 0x64EF, 0xECE8, 0x64F0, 0xC0BE, 0x64F1, 0xC0C1, 0x64F2, 0xC259, 0x64F3, 0xE9AD, 0x64F4, 0xC258, + 0x64F7, 0xC25E, 0x64F8, 0xEFD4, 0x64FA, 0xC25C, 0x64FB, 0xC25D, 0x64FC, 0xEFD7, 0x64FD, 0xEFD3, 0x64FE, 0xC25A, 0x64FF, 0xEFD1, + 0x6500, 0xC36B, 0x6501, 0xEFD5, 0x6503, 0xEFD6, 0x6504, 0xEFD2, 0x6506, 0xC25B, 0x6507, 0xF242, 0x6509, 0xF245, 0x650C, 0xF246, + 0x650D, 0xF244, 0x650E, 0xF247, 0x650F, 0xC36C, 0x6510, 0xF243, 0x6513, 0xF44E, 0x6514, 0xC464, 0x6515, 0xF44D, 0x6516, 0xF44C, + 0x6517, 0xF44B, 0x6518, 0xC463, 0x6519, 0xC465, 0x651B, 0xF5CD, 0x651C, 0xC4E2, 0x651D, 0xC4E1, 0x6520, 0xF6E1, 0x6521, 0xF6E0, + 0x6522, 0xF6E3, 0x6523, 0xC5CB, 0x6524, 0xC575, 0x6525, 0xF7DD, 0x6526, 0xF6E2, 0x6529, 0xF7DC, 0x652A, 0xC5CD, 0x652B, 0xC5CC, + 0x652C, 0xC5F3, 0x652D, 0xF8A9, 0x652E, 0xF8EF, 0x652F, 0xA4E4, 0x6532, 0xD972, 0x6533, 0xE9AF, 0x6536, 0xA6AC, 0x6537, 0xCAF7, + 0x6538, 0xA7F1, 0x6539, 0xA7EF, 0x653B, 0xA7F0, 0x653D, 0xCCC1, 0x653E, 0xA9F1, 0x653F, 0xAC46, 0x6541, 0xCEE7, 0x6543, 0xCEE8, + 0x6545, 0xAC47, 0x6546, 0xD1CE, 0x6548, 0xAEC4, 0x6549, 0xAEC5, 0x654A, 0xD1CD, 0x654F, 0xB1D3, 0x6551, 0xB1CF, 0x6553, 0xD5A7, + 0x6554, 0xB1D6, 0x6555, 0xB1D5, 0x6556, 0xB1CE, 0x6557, 0xB1D1, 0x6558, 0xB1D4, 0x6559, 0xB1D0, 0x655C, 0xD976, 0x655D, 0xB1CD, + 0x655E, 0xB4AF, 0x6562, 0xB4B1, 0x6563, 0xB4B2, 0x6564, 0xD975, 0x6565, 0xD978, 0x6566, 0xB4B0, 0x6567, 0xD973, 0x6568, 0xD977, + 0x656A, 0xD974, 0x656C, 0xB771, 0x656F, 0xDDBC, 0x6572, 0xBA56, 0x6573, 0xE1F4, 0x6574, 0xBEE3, 0x6575, 0xBCC4, 0x6576, 0xE5BD, + 0x6577, 0xBCC5, 0x6578, 0xBCC6, 0x6579, 0xE5BF, 0x657A, 0xE5BE, 0x657B, 0xE5C0, 0x657C, 0xE9B1, 0x657F, 0xE9B0, 0x6580, 0xECEF, + 0x6581, 0xECEE, 0x6582, 0xC0C4, 0x6583, 0xC0C5, 0x6584, 0xF248, 0x6587, 0xA4E5, 0x658C, 0xD979, 0x6590, 0xB4B4, 0x6591, 0xB4B3, + 0x6592, 0xDDBD, 0x6594, 0xEFD8, 0x6595, 0xC4E3, 0x6596, 0xF7DE, 0x6597, 0xA4E6, 0x6599, 0xAEC6, 0x659B, 0xB1D8, 0x659C, 0xB1D7, + 0x659D, 0xD97A, 0x659E, 0xD97B, 0x659F, 0xB772, 0x65A0, 0xE1F5, 0x65A1, 0xBA57, 0x65A2, 0xE9B2, 0x65A4, 0xA4E7, 0x65A5, 0xA5B8, + 0x65A7, 0xA9F2, 0x65A8, 0xCCC2, 0x65AA, 0xCEE9, 0x65AB, 0xAC48, 0x65AC, 0xB1D9, 0x65AE, 0xD97C, 0x65AF, 0xB4B5, 0x65B0, 0xB773, + 0x65B2, 0xE5C1, 0x65B3, 0xE5C2, 0x65B6, 0xECF0, 0x65B7, 0xC25F, 0x65B8, 0xF8F0, 0x65B9, 0xA4E8, 0x65BB, 0xCCC3, 0x65BC, 0xA9F3, + 0x65BD, 0xAC49, 0x65BF, 0xCEEA, 0x65C1, 0xAEC7, 0x65C2, 0xD1D2, 0x65C3, 0xD1D0, 0x65C4, 0xD1D1, 0x65C5, 0xAEC8, 0x65C6, 0xD1CF, + 0x65CB, 0xB1DB, 0x65CC, 0xB1DC, 0x65CD, 0xD5A8, 0x65CE, 0xB1DD, 0x65CF, 0xB1DA, 0x65D0, 0xD97D, 0x65D2, 0xD97E, 0x65D3, 0xDDBE, + 0x65D6, 0xBA59, 0x65D7, 0xBA58, 0x65DA, 0xECF1, 0x65DB, 0xEFD9, 0x65DD, 0xF24A, 0x65DE, 0xF249, 0x65DF, 0xF44F, 0x65E1, 0xC95E, + 0x65E2, 0xAC4A, 0x65E5, 0xA4E9, 0x65E6, 0xA5B9, 0x65E8, 0xA6AE, 0x65E9, 0xA6AD, 0x65EC, 0xA6AF, 0x65ED, 0xA6B0, 0x65EE, 0xC9EE, + 0x65EF, 0xC9ED, 0x65F0, 0xCAF8, 0x65F1, 0xA7F2, 0x65F2, 0xCAFB, 0x65F3, 0xCAFA, 0x65F4, 0xCAF9, 0x65F5, 0xCAFC, 0x65FA, 0xA9F4, + 0x65FB, 0xCCC9, 0x65FC, 0xCCC5, 0x65FD, 0xCCCE, 0x6600, 0xA9FB, 0x6602, 0xA9F9, 0x6603, 0xCCCA, 0x6604, 0xCCC6, 0x6605, 0xCCCD, + 0x6606, 0xA9F8, 0x6607, 0xAA40, 0x6608, 0xCCC8, 0x6609, 0xCCC4, 0x660A, 0xA9FE, 0x660B, 0xCCCB, 0x660C, 0xA9F7, 0x660D, 0xCCCC, + 0x660E, 0xA9FA, 0x660F, 0xA9FC, 0x6610, 0xCCD0, 0x6611, 0xCCCF, 0x6612, 0xCCC7, 0x6613, 0xA9F6, 0x6614, 0xA9F5, 0x6615, 0xA9FD, + 0x661C, 0xCEEF, 0x661D, 0xCEF5, 0x661F, 0xAC50, 0x6620, 0xAC4D, 0x6621, 0xCEEC, 0x6622, 0xCEF1, 0x6624, 0xAC53, 0x6625, 0xAC4B, + 0x6626, 0xCEF0, 0x6627, 0xAC4E, 0x6628, 0xAC51, 0x662B, 0xCEF3, 0x662D, 0xAC4C, 0x662E, 0xCEF8, 0x662F, 0xAC4F, 0x6631, 0xAC52, + 0x6632, 0xCEED, 0x6633, 0xCEF2, 0x6634, 0xCEF6, 0x6635, 0xCEEE, 0x6636, 0xCEEB, 0x6639, 0xCEF7, 0x663A, 0xCEF4, 0x6641, 0xAED0, + 0x6642, 0xAEC9, 0x6643, 0xAECC, 0x6645, 0xAECF, 0x6647, 0xD1D5, 0x6649, 0xAECA, 0x664A, 0xD1D3, 0x664C, 0xAECE, 0x664F, 0xAECB, + 0x6651, 0xD1D6, 0x6652, 0xAECD, 0x6659, 0xD5AC, 0x665A, 0xB1DF, 0x665B, 0xD5AB, 0x665C, 0xD5AD, 0x665D, 0xB1DE, 0x665E, 0xB1E3, + 0x665F, 0xD1D4, 0x6661, 0xD5AA, 0x6662, 0xD5AE, 0x6664, 0xB1E0, 0x6665, 0xD5A9, 0x6666, 0xB1E2, 0x6668, 0xB1E1, 0x666A, 0xD9A7, + 0x666C, 0xD9A2, 0x666E, 0xB4B6, 0x666F, 0xB4BA, 0x6670, 0xB4B7, 0x6671, 0xD9A5, 0x6672, 0xD9A8, 0x6674, 0xB4B8, 0x6676, 0xB4B9, + 0x6677, 0xB4BE, 0x6678, 0xDDC7, 0x6679, 0xD9A6, 0x667A, 0xB4BC, 0x667B, 0xD9A3, 0x667C, 0xD9A1, 0x667E, 0xB4BD, 0x6680, 0xD9A4, + 0x6684, 0xB779, 0x6686, 0xDDBF, 0x6687, 0xB776, 0x6688, 0xB777, 0x6689, 0xB775, 0x668A, 0xDDC4, 0x668B, 0xDDC3, 0x668C, 0xDDC0, + 0x668D, 0xB77B, 0x6690, 0xDDC2, 0x6691, 0xB4BB, 0x6694, 0xDDC6, 0x6695, 0xDDC1, 0x6696, 0xB778, 0x6697, 0xB774, 0x6698, 0xB77A, + 0x6699, 0xDDC5, 0x669D, 0xBA5C, 0x669F, 0xE1F8, 0x66A0, 0xE1F7, 0x66A1, 0xE1F6, 0x66A2, 0xBA5A, 0x66A8, 0xBA5B, 0x66A9, 0xE5C5, + 0x66AA, 0xE5C8, 0x66AB, 0xBCC8, 0x66AE, 0xBCC7, 0x66AF, 0xE5C9, 0x66B0, 0xE5C4, 0x66B1, 0xBCCA, 0x66B2, 0xE5C6, 0x66B4, 0xBCC9, + 0x66B5, 0xE5C3, 0x66B7, 0xE5C7, 0x66B8, 0xBEE9, 0x66B9, 0xBEE6, 0x66BA, 0xE9BB, 0x66BB, 0xE9BA, 0x66BD, 0xE9B9, 0x66BE, 0xE9B4, + 0x66C0, 0xE9B5, 0x66C4, 0xBEE7, 0x66C6, 0xBEE4, 0x66C7, 0xBEE8, 0x66C8, 0xE9B3, 0x66C9, 0xBEE5, 0x66CA, 0xE9B6, 0x66CB, 0xE9B7, + 0x66CC, 0xE9BC, 0x66CF, 0xE9B8, 0x66D2, 0xECF2, 0x66D6, 0xC0C7, 0x66D8, 0xEFDC, 0x66D9, 0xC0C6, 0x66DA, 0xEFDA, 0x66DB, 0xEFDB, + 0x66DC, 0xC260, 0x66DD, 0xC36E, 0x66DE, 0xF24B, 0x66E0, 0xC36D, 0x66E3, 0xF451, 0x66E4, 0xF452, 0x66E6, 0xC466, 0x66E8, 0xF450, + 0x66E9, 0xC4E4, 0x66EB, 0xF7DF, 0x66EC, 0xC5CE, 0x66ED, 0xF8AA, 0x66EE, 0xF8AB, 0x66F0, 0xA4EA, 0x66F2, 0xA6B1, 0x66F3, 0xA6B2, + 0x66F4, 0xA7F3, 0x66F6, 0xCCD1, 0x66F7, 0xAC54, 0x66F8, 0xAED1, 0x66F9, 0xB1E4, 0x66FC, 0xB0D2, 0x66FE, 0xB4BF, 0x66FF, 0xB4C0, + 0x6700, 0xB3CC, 0x6701, 0xD9A9, 0x6703, 0xB77C, 0x6704, 0xE1FA, 0x6705, 0xE1F9, 0x6708, 0xA4EB, 0x6709, 0xA6B3, 0x670A, 0xCCD2, + 0x670B, 0xAA42, 0x670D, 0xAA41, 0x670F, 0xCEF9, 0x6710, 0xCEFA, 0x6712, 0xD1D7, 0x6713, 0xD1D8, 0x6714, 0xAED2, 0x6715, 0xAED3, + 0x6717, 0xAED4, 0x6718, 0xD5AF, 0x671B, 0xB1E6, 0x671D, 0xB4C2, 0x671F, 0xB4C1, 0x6720, 0xDDC8, 0x6721, 0xDF7A, 0x6722, 0xE1FB, + 0x6723, 0xE9BD, 0x6726, 0xC261, 0x6727, 0xC467, 0x6728, 0xA4EC, 0x672A, 0xA5BC, 0x672B, 0xA5BD, 0x672C, 0xA5BB, 0x672D, 0xA5BE, + 0x672E, 0xA5BA, 0x6731, 0xA6B6, 0x6733, 0xC9F6, 0x6734, 0xA6B5, 0x6735, 0xA6B7, 0x6738, 0xC9F1, 0x6739, 0xC9F0, 0x673A, 0xC9F3, + 0x673B, 0xC9F2, 0x673C, 0xC9F5, 0x673D, 0xA6B4, 0x673E, 0xC9EF, 0x673F, 0xC9F4, 0x6745, 0xCAFD, 0x6746, 0xA7FD, 0x6747, 0xCAFE, + 0x6748, 0xCB43, 0x6749, 0xA7FC, 0x674B, 0xCB47, 0x674C, 0xCB42, 0x674D, 0xCB45, 0x674E, 0xA7F5, 0x674F, 0xA7F6, 0x6750, 0xA7F7, + 0x6751, 0xA7F8, 0x6753, 0xA840, 0x6755, 0xCB41, 0x6756, 0xA7FA, 0x6757, 0xA841, 0x6759, 0xCB40, 0x675A, 0xCB46, 0x675C, 0xA7F9, + 0x675D, 0xCB44, 0x675E, 0xA7FB, 0x675F, 0xA7F4, 0x6760, 0xA7FE, 0x676A, 0xAA57, 0x676C, 0xCCD4, 0x676D, 0xAA43, 0x676F, 0xAA4D, + 0x6770, 0xAA4E, 0x6771, 0xAA46, 0x6772, 0xAA58, 0x6773, 0xAA48, 0x6774, 0xCCDC, 0x6775, 0xAA53, 0x6776, 0xCCD7, 0x6777, 0xAA49, + 0x6778, 0xCCE6, 0x6779, 0xCCE7, 0x677A, 0xCCDF, 0x677B, 0xCCD8, 0x677C, 0xAA56, 0x677D, 0xCCE4, 0x677E, 0xAA51, 0x677F, 0xAA4F, + 0x6781, 0xCCE5, 0x6783, 0xCCE3, 0x6784, 0xCCDB, 0x6785, 0xCCD3, 0x6786, 0xCCDA, 0x6787, 0xAA4A, 0x6789, 0xAA50, 0x678B, 0xAA44, + 0x678C, 0xCCDE, 0x678D, 0xCCDD, 0x678E, 0xCCD5, 0x6790, 0xAA52, 0x6791, 0xCCE1, 0x6792, 0xCCD6, 0x6793, 0xAA55, 0x6794, 0xCCE8, + 0x6795, 0xAA45, 0x6797, 0xAA4C, 0x6798, 0xCCD9, 0x6799, 0xCCE2, 0x679A, 0xAA54, 0x679C, 0xAA47, 0x679D, 0xAA4B, 0x679F, 0xCCE0, + 0x67AE, 0xCF5B, 0x67AF, 0xAC5C, 0x67B0, 0xAC69, 0x67B2, 0xCF56, 0x67B3, 0xCF4C, 0x67B4, 0xAC62, 0x67B5, 0xCF4A, 0x67B6, 0xAC5B, + 0x67B7, 0xCF45, 0x67B8, 0xAC65, 0x67B9, 0xCF52, 0x67BA, 0xCEFE, 0x67BB, 0xCF41, 0x67C0, 0xCF44, 0x67C1, 0xCEFB, 0x67C2, 0xCF51, + 0x67C3, 0xCF61, 0x67C4, 0xAC60, 0x67C5, 0xCF46, 0x67C6, 0xCF58, 0x67C8, 0xCEFD, 0x67C9, 0xCF5F, 0x67CA, 0xCF60, 0x67CB, 0xCF63, + 0x67CC, 0xCF5A, 0x67CD, 0xCF4B, 0x67CE, 0xCF53, 0x67CF, 0xAC66, 0x67D0, 0xAC59, 0x67D1, 0xAC61, 0x67D2, 0xAC6D, 0x67D3, 0xAC56, + 0x67D4, 0xAC58, 0x67D8, 0xCF43, 0x67D9, 0xAC6A, 0x67DA, 0xAC63, 0x67DB, 0xCF5D, 0x67DC, 0xCF40, 0x67DD, 0xAC6C, 0x67DE, 0xAC67, + 0x67DF, 0xCF49, 0x67E2, 0xAC6B, 0x67E3, 0xCF50, 0x67E4, 0xCF48, 0x67E5, 0xAC64, 0x67E6, 0xCF5C, 0x67E7, 0xCF54, 0x67E9, 0xAC5E, + 0x67EA, 0xCF62, 0x67EB, 0xCF47, 0x67EC, 0xAC5A, 0x67ED, 0xCF59, 0x67EE, 0xCF4F, 0x67EF, 0xAC5F, 0x67F0, 0xCF55, 0x67F1, 0xAC57, + 0x67F2, 0xCEFC, 0x67F3, 0xAC68, 0x67F4, 0xAEE3, 0x67F5, 0xAC5D, 0x67F6, 0xCF4E, 0x67F7, 0xCF4D, 0x67F8, 0xCF42, 0x67FA, 0xCF5E, + 0x67FC, 0xCF57, 0x67FF, 0xAC55, 0x6812, 0xD1EC, 0x6813, 0xAEEA, 0x6814, 0xD1ED, 0x6816, 0xD1E1, 0x6817, 0xAEDF, 0x6818, 0xAEEB, + 0x681A, 0xD1DA, 0x681C, 0xD1E3, 0x681D, 0xD1EB, 0x681F, 0xD1D9, 0x6820, 0xD1F4, 0x6821, 0xAED5, 0x6825, 0xD1F3, 0x6826, 0xD1EE, + 0x6828, 0xD1EF, 0x6829, 0xAEDD, 0x682A, 0xAEE8, 0x682B, 0xD1E5, 0x682D, 0xD1E6, 0x682E, 0xD1F0, 0x682F, 0xD1E7, 0x6831, 0xD1E2, + 0x6832, 0xD1DC, 0x6833, 0xD1DD, 0x6834, 0xD1EA, 0x6835, 0xD1E4, 0x6838, 0xAED6, 0x6839, 0xAEDA, 0x683A, 0xD1F2, 0x683B, 0xD1DE, + 0x683C, 0xAEE6, 0x683D, 0xAEE2, 0x6840, 0xAEE5, 0x6841, 0xAEEC, 0x6842, 0xAEDB, 0x6843, 0xAEE7, 0x6844, 0xD1E9, 0x6845, 0xAEE9, + 0x6846, 0xAED8, 0x6848, 0xAED7, 0x6849, 0xD1DB, 0x684B, 0xD1DF, 0x684C, 0xAEE0, 0x684D, 0xD1F1, 0x684E, 0xD1E8, 0x684F, 0xD1E0, + 0x6850, 0xAEE4, 0x6851, 0xAEE1, 0x6853, 0xAED9, 0x6854, 0xAEDC, 0x686B, 0xD5C4, 0x686D, 0xD5B4, 0x686E, 0xD5B5, 0x686F, 0xD5B9, + 0x6871, 0xD5C8, 0x6872, 0xD5C5, 0x6874, 0xD5BE, 0x6875, 0xD5BD, 0x6876, 0xB1ED, 0x6877, 0xD5C1, 0x6878, 0xD5D0, 0x6879, 0xD5B0, + 0x687B, 0xD5D1, 0x687C, 0xD5C3, 0x687D, 0xD5D5, 0x687E, 0xD5C9, 0x687F, 0xB1EC, 0x6880, 0xD5C7, 0x6881, 0xB1E7, 0x6882, 0xB1FC, + 0x6883, 0xB1F2, 0x6885, 0xB1F6, 0x6886, 0xB1F5, 0x6887, 0xD5B1, 0x6889, 0xD5CE, 0x688A, 0xD5D4, 0x688B, 0xD5CC, 0x688C, 0xD5D3, + 0x688F, 0xD5C0, 0x6890, 0xD5B2, 0x6891, 0xD5D2, 0x6892, 0xD5C2, 0x6893, 0xB1EA, 0x6894, 0xB1F7, 0x6896, 0xD5CB, 0x6897, 0xB1F0, + 0x689B, 0xD5CA, 0x689C, 0xD5B3, 0x689D, 0xB1F8, 0x689F, 0xB1FA, 0x68A0, 0xD5CD, 0x68A1, 0xB1FB, 0x68A2, 0xB1E9, 0x68A3, 0xD5BA, + 0x68A4, 0xD5CF, 0x68A7, 0xB1EF, 0x68A8, 0xB1F9, 0x68A9, 0xD5BC, 0x68AA, 0xD5C6, 0x68AB, 0xD5B7, 0x68AC, 0xD5BB, 0x68AD, 0xB1F4, + 0x68AE, 0xD5B6, 0x68AF, 0xB1E8, 0x68B0, 0xB1F1, 0x68B1, 0xB1EE, 0x68B2, 0xD5BF, 0x68B3, 0xAEDE, 0x68B4, 0xD9C0, 0x68B5, 0xB1EB, + 0x68C4, 0xB1F3, 0x68C6, 0xD9C3, 0x68C7, 0xD9D9, 0x68C8, 0xD9CE, 0x68C9, 0xB4D6, 0x68CB, 0xB4D1, 0x68CC, 0xD9BD, 0x68CD, 0xB4D2, + 0x68CE, 0xD9CD, 0x68D0, 0xD9C6, 0x68D1, 0xD9D3, 0x68D2, 0xB4CE, 0x68D3, 0xD9AB, 0x68D4, 0xD9D5, 0x68D5, 0xB4C4, 0x68D6, 0xD9B3, + 0x68D7, 0xB4C7, 0x68D8, 0xB4C6, 0x68DA, 0xB4D7, 0x68DC, 0xD9AD, 0x68DD, 0xD9CF, 0x68DE, 0xD9D0, 0x68DF, 0xB4C9, 0x68E0, 0xB4C5, + 0x68E1, 0xD9BB, 0x68E3, 0xB4D0, 0x68E4, 0xD9B6, 0x68E6, 0xD9D1, 0x68E7, 0xB4CC, 0x68E8, 0xD9C9, 0x68E9, 0xD9D6, 0x68EA, 0xD9B0, + 0x68EB, 0xD9B5, 0x68EC, 0xD9AF, 0x68EE, 0xB4CB, 0x68EF, 0xD9C2, 0x68F0, 0xDDDE, 0x68F1, 0xD9B1, 0x68F2, 0xB4CF, 0x68F3, 0xD9BA, + 0x68F4, 0xD9D2, 0x68F5, 0xB4CA, 0x68F6, 0xD9B7, 0x68F7, 0xD9B4, 0x68F8, 0xD9C5, 0x68F9, 0xB4CD, 0x68FA, 0xB4C3, 0x68FB, 0xB4D9, + 0x68FC, 0xD9C8, 0x68FD, 0xD9C7, 0x6904, 0xD9AC, 0x6905, 0xB4C8, 0x6906, 0xD9D4, 0x6907, 0xD9BC, 0x6908, 0xD9BE, 0x690A, 0xD9CB, + 0x690B, 0xD9CA, 0x690C, 0xD9AA, 0x690D, 0xB4D3, 0x690E, 0xB4D5, 0x690F, 0xD9B2, 0x6910, 0xD9B9, 0x6911, 0xD9C1, 0x6912, 0xB4D4, + 0x6913, 0xD9B8, 0x6914, 0xD9C4, 0x6915, 0xD9D7, 0x6917, 0xD9CC, 0x6925, 0xD9D8, 0x692A, 0xD9AE, 0x692F, 0xDDF2, 0x6930, 0xB7A6, + 0x6932, 0xDDF0, 0x6933, 0xDDDB, 0x6934, 0xDDE0, 0x6935, 0xDDD9, 0x6937, 0xDDEC, 0x6938, 0xDDCB, 0x6939, 0xDDD2, 0x693B, 0xDDEA, + 0x693C, 0xDDF4, 0x693D, 0xDDDC, 0x693F, 0xDDCF, 0x6940, 0xDDE2, 0x6941, 0xDDE7, 0x6942, 0xDDD3, 0x6944, 0xDDE4, 0x6945, 0xDDD0, + 0x6948, 0xDDD7, 0x6949, 0xDDD8, 0x694A, 0xB7A8, 0x694B, 0xDDEB, 0x694C, 0xDDE9, 0x694E, 0xDDCC, 0x694F, 0xDDEE, 0x6951, 0xDDEF, + 0x6952, 0xDDF1, 0x6953, 0xB7AC, 0x6954, 0xB7A4, 0x6956, 0xD5B8, 0x6957, 0xDDD4, 0x6958, 0xDDE6, 0x6959, 0xDDD5, 0x695A, 0xB7A1, + 0x695B, 0xB7B1, 0x695C, 0xDDED, 0x695D, 0xB7AF, 0x695E, 0xB7AB, 0x695F, 0xDDCA, 0x6960, 0xB7A3, 0x6962, 0xDDCD, 0x6963, 0xB7B0, + 0x6965, 0xDDDD, 0x6966, 0xDDC9, 0x6968, 0xB7A9, 0x6969, 0xDDE1, 0x696A, 0xDDD1, 0x696B, 0xB7AA, 0x696C, 0xDDDA, 0x696D, 0xB77E, + 0x696E, 0xB4D8, 0x696F, 0xDDE3, 0x6970, 0xD9BF, 0x6971, 0xDDCE, 0x6974, 0xDDE8, 0x6975, 0xB7A5, 0x6976, 0xDDE5, 0x6977, 0xB7A2, + 0x6978, 0xDDDF, 0x6979, 0xB7AD, 0x697A, 0xDDD6, 0x697B, 0xDDF3, 0x6982, 0xB7A7, 0x6983, 0xDEC6, 0x6986, 0xB7AE, 0x698D, 0xE24A, + 0x698E, 0xE248, 0x6990, 0xE25E, 0x6991, 0xE246, 0x6993, 0xE258, 0x6994, 0xB77D, 0x6995, 0xBA5F, 0x6996, 0xE242, 0x6997, 0xE25D, + 0x6999, 0xE247, 0x699A, 0xE255, 0x699B, 0xBA64, 0x699C, 0xBA5D, 0x699E, 0xE25B, 0x69A0, 0xE240, 0x69A1, 0xE25A, 0x69A3, 0xBA6F, + 0x69A4, 0xE251, 0x69A5, 0xE261, 0x69A6, 0xBA6D, 0x69A7, 0xE249, 0x69A8, 0xBA5E, 0x69A9, 0xE24B, 0x69AA, 0xE259, 0x69AB, 0xBA67, + 0x69AC, 0xE244, 0x69AD, 0xBA6B, 0x69AE, 0xBA61, 0x69AF, 0xE24D, 0x69B0, 0xE243, 0x69B1, 0xE1FC, 0x69B3, 0xE257, 0x69B4, 0xBA68, + 0x69B5, 0xE260, 0x69B6, 0xE1FD, 0x69B7, 0xBA65, 0x69B9, 0xE253, 0x69BB, 0xBA66, 0x69BC, 0xE245, 0x69BD, 0xE250, 0x69BE, 0xE24C, + 0x69BF, 0xE24E, 0x69C1, 0xBA60, 0x69C2, 0xE25F, 0x69C3, 0xBA6E, 0x69C4, 0xE24F, 0x69C6, 0xE262, 0x69C9, 0xE1FE, 0x69CA, 0xE254, + 0x69CB, 0xBA63, 0x69CC, 0xBA6C, 0x69CD, 0xBA6A, 0x69CE, 0xE241, 0x69CF, 0xE256, 0x69D0, 0xBA69, 0x69D3, 0xBA62, 0x69D4, 0xE252, + 0x69D9, 0xE25C, 0x69E2, 0xE5D5, 0x69E4, 0xE5D1, 0x69E5, 0xE5CD, 0x69E6, 0xE5E1, 0x69E7, 0xE5DE, 0x69E8, 0xBCCD, 0x69EB, 0xE5E5, + 0x69EC, 0xE5D4, 0x69ED, 0xBCD8, 0x69EE, 0xE5DB, 0x69F1, 0xE5D0, 0x69F2, 0xE5DA, 0x69F3, 0xBCD5, 0x69F4, 0xE5EE, 0x69F6, 0xE5EB, + 0x69F7, 0xE5DD, 0x69F8, 0xE5CE, 0x69FB, 0xE5E2, 0x69FC, 0xE5E4, 0x69FD, 0xBCD1, 0x69FE, 0xE5D8, 0x69FF, 0xE5D3, 0x6A00, 0xE5CA, + 0x6A01, 0xBCCE, 0x6A02, 0xBCD6, 0x6A04, 0xE5E7, 0x6A05, 0xBCD7, 0x6A06, 0xE5CB, 0x6A07, 0xE5ED, 0x6A08, 0xE5E0, 0x6A09, 0xE5E6, + 0x6A0A, 0xBCD4, 0x6A0D, 0xE5E3, 0x6A0F, 0xE5EA, 0x6A11, 0xBCD9, 0x6A13, 0xBCD3, 0x6A14, 0xE5DC, 0x6A15, 0xE5CF, 0x6A16, 0xE5EF, + 0x6A17, 0xE5CC, 0x6A18, 0xE5E8, 0x6A19, 0xBCD0, 0x6A1B, 0xE5D6, 0x6A1D, 0xE5D7, 0x6A1E, 0xBCCF, 0x6A1F, 0xBCCC, 0x6A20, 0xE5D2, + 0x6A21, 0xBCD2, 0x6A23, 0xBCCB, 0x6A25, 0xE5E9, 0x6A26, 0xE5EC, 0x6A27, 0xE5D9, 0x6A28, 0xE9CA, 0x6A32, 0xE9C2, 0x6A34, 0xE9BE, + 0x6A35, 0xBEF6, 0x6A38, 0xBEEB, 0x6A39, 0xBEF0, 0x6A3A, 0xBEEC, 0x6A3B, 0xE9CC, 0x6A3C, 0xE9D7, 0x6A3D, 0xBEEA, 0x6A3E, 0xE9C4, + 0x6A3F, 0xE9CD, 0x6A40, 0xE5DF, 0x6A41, 0xE9CE, 0x6A44, 0xBEF1, 0x6A46, 0xE9DD, 0x6A47, 0xBEF5, 0x6A48, 0xBEF8, 0x6A49, 0xE9C0, + 0x6A4B, 0xBEF4, 0x6A4D, 0xE9DB, 0x6A4E, 0xE9DC, 0x6A4F, 0xE9D2, 0x6A50, 0xE9D1, 0x6A51, 0xE9C9, 0x6A54, 0xE9D3, 0x6A55, 0xE9DA, + 0x6A56, 0xE9D9, 0x6A58, 0xBEEF, 0x6A59, 0xBEED, 0x6A5A, 0xE9CB, 0x6A5B, 0xE9C8, 0x6A5D, 0xE9C5, 0x6A5E, 0xE9D8, 0x6A5F, 0xBEF7, + 0x6A60, 0xE9D6, 0x6A61, 0xBEF3, 0x6A62, 0xBEF2, 0x6A64, 0xE9D0, 0x6A66, 0xE9BF, 0x6A67, 0xE9C1, 0x6A68, 0xE9C3, 0x6A69, 0xE9D5, + 0x6A6A, 0xE9CF, 0x6A6B, 0xBEEE, 0x6A6D, 0xE9C6, 0x6A6F, 0xE9D4, 0x6A76, 0xE9C7, 0x6A7E, 0xC0CF, 0x6A7F, 0xED45, 0x6A80, 0xC0C8, + 0x6A81, 0xECF5, 0x6A83, 0xED41, 0x6A84, 0xC0CA, 0x6A85, 0xED48, 0x6A87, 0xECFC, 0x6A89, 0xECF7, 0x6A8C, 0xED49, 0x6A8D, 0xECF3, + 0x6A8E, 0xECFE, 0x6A90, 0xC0D1, 0x6A91, 0xED44, 0x6A92, 0xED4A, 0x6A93, 0xECFD, 0x6A94, 0xC0C9, 0x6A95, 0xED40, 0x6A96, 0xECF4, + 0x6A97, 0xC0D0, 0x6A9A, 0xED47, 0x6A9B, 0xECF9, 0x6A9C, 0xC0CC, 0x6A9E, 0xECFB, 0x6A9F, 0xECF8, 0x6AA0, 0xC0D2, 0x6AA1, 0xECFA, + 0x6AA2, 0xC0CB, 0x6AA3, 0xC0CE, 0x6AA4, 0xED43, 0x6AA5, 0xECF6, 0x6AA6, 0xED46, 0x6AA8, 0xED42, 0x6AAC, 0xC263, 0x6AAD, 0xEFE7, + 0x6AAE, 0xC268, 0x6AAF, 0xC269, 0x6AB3, 0xC262, 0x6AB4, 0xEFE6, 0x6AB6, 0xEFE3, 0x6AB7, 0xEFE4, 0x6AB8, 0xC266, 0x6AB9, 0xEFDE, + 0x6ABA, 0xEFE2, 0x6ABB, 0xC265, 0x6ABD, 0xEFDF, 0x6AC2, 0xC267, 0x6AC3, 0xC264, 0x6AC5, 0xEFDD, 0x6AC6, 0xEFE1, 0x6AC7, 0xEFE5, + 0x6ACB, 0xF251, 0x6ACC, 0xF24E, 0x6ACD, 0xF257, 0x6ACF, 0xF256, 0x6AD0, 0xF254, 0x6AD1, 0xF24F, 0x6AD3, 0xC372, 0x6AD9, 0xF250, + 0x6ADA, 0xC371, 0x6ADB, 0xC0CD, 0x6ADC, 0xF253, 0x6ADD, 0xC370, 0x6ADE, 0xF258, 0x6ADF, 0xF252, 0x6AE0, 0xF24D, 0x6AE1, 0xEFE0, + 0x6AE5, 0xC36F, 0x6AE7, 0xF24C, 0x6AE8, 0xF456, 0x6AEA, 0xF455, 0x6AEB, 0xF255, 0x6AEC, 0xC468, 0x6AEE, 0xF459, 0x6AEF, 0xF45A, + 0x6AF0, 0xF454, 0x6AF1, 0xF458, 0x6AF3, 0xF453, 0x6AF8, 0xF5D1, 0x6AF9, 0xF457, 0x6AFA, 0xC4E7, 0x6AFB, 0xC4E5, 0x6AFC, 0xF5CF, + 0x6B00, 0xF5D2, 0x6B02, 0xF5CE, 0x6B03, 0xF5D0, 0x6B04, 0xC4E6, 0x6B08, 0xF6E5, 0x6B09, 0xF6E6, 0x6B0A, 0xC576, 0x6B0B, 0xF6E4, + 0x6B0F, 0xF7E2, 0x6B10, 0xC5CF, 0x6B11, 0xF7E0, 0x6B12, 0xF7E1, 0x6B13, 0xF8AC, 0x6B16, 0xC656, 0x6B17, 0xF8F3, 0x6B18, 0xF8F1, + 0x6B19, 0xF8F2, 0x6B1A, 0xF8F4, 0x6B1E, 0xF9BB, 0x6B20, 0xA4ED, 0x6B21, 0xA6B8, 0x6B23, 0xAA59, 0x6B25, 0xCCE9, 0x6B28, 0xCF64, + 0x6B2C, 0xD1F5, 0x6B2D, 0xD1F7, 0x6B2F, 0xD1F6, 0x6B31, 0xD1F8, 0x6B32, 0xB1FD, 0x6B33, 0xD5D7, 0x6B34, 0xD1F9, 0x6B36, 0xD5D6, + 0x6B37, 0xD5D8, 0x6B38, 0xD5D9, 0x6B39, 0xD9DA, 0x6B3A, 0xB4DB, 0x6B3B, 0xD9DB, 0x6B3C, 0xD9DD, 0x6B3D, 0xB4DC, 0x6B3E, 0xB4DA, + 0x6B3F, 0xD9DC, 0x6B41, 0xDDFA, 0x6B42, 0xDDF8, 0x6B43, 0xDDF7, 0x6B45, 0xDDF6, 0x6B46, 0xDDF5, 0x6B47, 0xB7B2, 0x6B48, 0xDDF9, + 0x6B49, 0xBA70, 0x6B4A, 0xE263, 0x6B4B, 0xE265, 0x6B4C, 0xBA71, 0x6B4D, 0xE264, 0x6B4E, 0xBCDB, 0x6B50, 0xBCDA, 0x6B51, 0xE5F0, + 0x6B54, 0xE9DF, 0x6B55, 0xE9DE, 0x6B56, 0xE9E0, 0x6B59, 0xBEF9, 0x6B5B, 0xED4B, 0x6B5C, 0xC0D3, 0x6B5E, 0xEFE8, 0x6B5F, 0xC26A, + 0x6B60, 0xF259, 0x6B61, 0xC577, 0x6B62, 0xA4EE, 0x6B63, 0xA5BF, 0x6B64, 0xA6B9, 0x6B65, 0xA842, 0x6B66, 0xAA5A, 0x6B67, 0xAA5B, + 0x6B6A, 0xAC6E, 0x6B6D, 0xD1FA, 0x6B72, 0xB7B3, 0x6B76, 0xE6D1, 0x6B77, 0xBEFA, 0x6B78, 0xC26B, 0x6B79, 0xA4EF, 0x6B7B, 0xA6BA, + 0x6B7E, 0xCCEB, 0x6B7F, 0xAA5C, 0x6B80, 0xCCEA, 0x6B82, 0xCF65, 0x6B83, 0xAC6F, 0x6B84, 0xCF66, 0x6B86, 0xAC70, 0x6B88, 0xD1FC, + 0x6B89, 0xAEEE, 0x6B8A, 0xAEED, 0x6B8C, 0xD5DE, 0x6B8D, 0xD5DC, 0x6B8E, 0xD5DD, 0x6B8F, 0xD5DB, 0x6B91, 0xD5DA, 0x6B94, 0xD9DE, + 0x6B95, 0xD9E1, 0x6B96, 0xB4DE, 0x6B97, 0xD9DF, 0x6B98, 0xB4DD, 0x6B99, 0xD9E0, 0x6B9B, 0xDDFB, 0x6B9E, 0xE266, 0x6B9F, 0xE267, + 0x6BA0, 0xE268, 0x6BA2, 0xE5F3, 0x6BA3, 0xE5F2, 0x6BA4, 0xBCDC, 0x6BA5, 0xE5F1, 0x6BA6, 0xE5F4, 0x6BA7, 0xE9E1, 0x6BAA, 0xE9E2, + 0x6BAB, 0xE9E3, 0x6BAD, 0xED4C, 0x6BAE, 0xC0D4, 0x6BAF, 0xC26C, 0x6BB0, 0xF25A, 0x6BB2, 0xC4E8, 0x6BB3, 0xC95F, 0x6BB5, 0xAC71, + 0x6BB6, 0xCF67, 0x6BB7, 0xAEEF, 0x6BBA, 0xB1FE, 0x6BBC, 0xB4DF, 0x6BBD, 0xD9E2, 0x6BBF, 0xB7B5, 0x6BC0, 0xB7B4, 0x6BC3, 0xE269, + 0x6BC4, 0xE26A, 0x6BC5, 0xBCDD, 0x6BC6, 0xBCDE, 0x6BC7, 0xE9E5, 0x6BC8, 0xE9E4, 0x6BC9, 0xEFE9, 0x6BCA, 0xF7E3, 0x6BCB, 0xA4F0, + 0x6BCC, 0xC960, 0x6BCD, 0xA5C0, 0x6BCF, 0xA843, 0x6BD0, 0xCB48, 0x6BD2, 0xAC72, 0x6BD3, 0xB7B6, 0x6BD4, 0xA4F1, 0x6BD6, 0xCF68, + 0x6BD7, 0xAC73, 0x6BD8, 0xCF69, 0x6BDA, 0xC0D5, 0x6BDB, 0xA4F2, 0x6BDE, 0xCCEC, 0x6BE0, 0xCF6A, 0x6BE2, 0xD242, 0x6BE3, 0xD241, + 0x6BE4, 0xD1FE, 0x6BE6, 0xD1FD, 0x6BE7, 0xD243, 0x6BE8, 0xD240, 0x6BEB, 0xB240, 0x6BEC, 0xB241, 0x6BEF, 0xB4E0, 0x6BF0, 0xD9E3, + 0x6BF2, 0xD9E4, 0x6BF3, 0xD9E5, 0x6BF7, 0xDE41, 0x6BF8, 0xDE42, 0x6BF9, 0xDE40, 0x6BFB, 0xDDFD, 0x6BFC, 0xDDFE, 0x6BFD, 0xB7B7, + 0x6BFE, 0xE26B, 0x6BFF, 0xE5F7, 0x6C00, 0xE5F6, 0x6C01, 0xE5F5, 0x6C02, 0xE5F8, 0x6C03, 0xE9E7, 0x6C04, 0xE9E6, 0x6C05, 0xBEFB, + 0x6C06, 0xE9E8, 0x6C08, 0xC0D6, 0x6C09, 0xED4D, 0x6C0B, 0xEFEA, 0x6C0C, 0xF25B, 0x6C0D, 0xF6E7, 0x6C0F, 0xA4F3, 0x6C10, 0xA5C2, + 0x6C11, 0xA5C1, 0x6C13, 0xAA5D, 0x6C14, 0xC961, 0x6C15, 0xC97E, 0x6C16, 0xA6BB, 0x6C18, 0xC9F7, 0x6C19, 0xCB49, 0x6C1A, 0xCB4A, + 0x6C1B, 0xAA5E, 0x6C1D, 0xCCED, 0x6C1F, 0xAC74, 0x6C20, 0xCF6B, 0x6C21, 0xCF6C, 0x6C23, 0xAEF0, 0x6C24, 0xAEF4, 0x6C25, 0xD244, + 0x6C26, 0xAEF3, 0x6C27, 0xAEF1, 0x6C28, 0xAEF2, 0x6C2A, 0xD5DF, 0x6C2B, 0xB242, 0x6C2C, 0xB4E3, 0x6C2E, 0xB4E1, 0x6C2F, 0xB4E2, + 0x6C30, 0xD9E6, 0x6C33, 0xBA72, 0x6C34, 0xA4F4, 0x6C36, 0xC9A1, 0x6C38, 0xA5C3, 0x6C3B, 0xC9A4, 0x6C3E, 0xA5C6, 0x6C3F, 0xC9A3, + 0x6C40, 0xA5C5, 0x6C41, 0xA5C4, 0x6C42, 0xA844, 0x6C43, 0xC9A2, 0x6C46, 0xC9F8, 0x6C4A, 0xC9FC, 0x6C4B, 0xC9FE, 0x6C4C, 0xCA40, + 0x6C4D, 0xA6C5, 0x6C4E, 0xA6C6, 0x6C4F, 0xC9FB, 0x6C50, 0xA6C1, 0x6C52, 0xC9F9, 0x6C54, 0xC9FD, 0x6C55, 0xA6C2, 0x6C57, 0xA6BD, + 0x6C59, 0xA6BE, 0x6C5B, 0xA6C4, 0x6C5C, 0xC9FA, 0x6C5D, 0xA6BC, 0x6C5E, 0xA845, 0x6C5F, 0xA6BF, 0x6C60, 0xA6C0, 0x6C61, 0xA6C3, + 0x6C65, 0xCB5B, 0x6C66, 0xCB59, 0x6C67, 0xCB4C, 0x6C68, 0xA851, 0x6C69, 0xCB53, 0x6C6A, 0xA84C, 0x6C6B, 0xCB4D, 0x6C6D, 0xCB55, + 0x6C6F, 0xCB52, 0x6C70, 0xA84F, 0x6C71, 0xCB51, 0x6C72, 0xA856, 0x6C73, 0xCB5A, 0x6C74, 0xA858, 0x6C76, 0xA85A, 0x6C78, 0xCB4B, + 0x6C7A, 0xA84D, 0x6C7B, 0xCB5C, 0x6C7D, 0xA854, 0x6C7E, 0xA857, 0x6C80, 0xCD45, 0x6C81, 0xA847, 0x6C82, 0xA85E, 0x6C83, 0xA855, + 0x6C84, 0xCB4E, 0x6C85, 0xA84A, 0x6C86, 0xA859, 0x6C87, 0xCB56, 0x6C88, 0xA848, 0x6C89, 0xA849, 0x6C8A, 0xCD43, 0x6C8B, 0xCB4F, + 0x6C8C, 0xA850, 0x6C8D, 0xA85B, 0x6C8E, 0xCB5D, 0x6C8F, 0xCB50, 0x6C90, 0xA84E, 0x6C92, 0xA853, 0x6C93, 0xCCEE, 0x6C94, 0xA85C, + 0x6C95, 0xCB57, 0x6C96, 0xA852, 0x6C98, 0xA85D, 0x6C99, 0xA846, 0x6C9A, 0xCB54, 0x6C9B, 0xA84B, 0x6C9C, 0xCB58, 0x6C9D, 0xCD44, + 0x6CAB, 0xAA6A, 0x6CAC, 0xAA7A, 0x6CAD, 0xCCF5, 0x6CAE, 0xAA71, 0x6CB0, 0xCD4B, 0x6CB1, 0xAA62, 0x6CB3, 0xAA65, 0x6CB4, 0xCD42, + 0x6CB6, 0xCCF3, 0x6CB7, 0xCCF7, 0x6CB8, 0xAA6D, 0x6CB9, 0xAA6F, 0x6CBA, 0xCCFA, 0x6CBB, 0xAA76, 0x6CBC, 0xAA68, 0x6CBD, 0xAA66, + 0x6CBE, 0xAA67, 0x6CBF, 0xAA75, 0x6CC0, 0xCD47, 0x6CC1, 0xAA70, 0x6CC2, 0xCCF9, 0x6CC3, 0xCCFB, 0x6CC4, 0xAA6E, 0x6CC5, 0xAA73, + 0x6CC6, 0xCCFC, 0x6CC7, 0xCD4A, 0x6CC9, 0xAC75, 0x6CCA, 0xAA79, 0x6CCC, 0xAA63, 0x6CCD, 0xCD49, 0x6CCF, 0xCD4D, 0x6CD0, 0xCCF8, + 0x6CD1, 0xCD4F, 0x6CD2, 0xCD40, 0x6CD3, 0xAA6C, 0x6CD4, 0xCCF4, 0x6CD5, 0xAA6B, 0x6CD6, 0xAA7D, 0x6CD7, 0xAA72, 0x6CD9, 0xCCF2, + 0x6CDA, 0xCF75, 0x6CDB, 0xAA78, 0x6CDC, 0xAA7C, 0x6CDD, 0xCD41, 0x6CDE, 0xCD46, 0x6CE0, 0xAA7E, 0x6CE1, 0xAA77, 0x6CE2, 0xAA69, + 0x6CE3, 0xAA5F, 0x6CE5, 0xAA64, 0x6CE7, 0xCCF6, 0x6CE8, 0xAA60, 0x6CE9, 0xCD4E, 0x6CEB, 0xCCF0, 0x6CEC, 0xCCEF, 0x6CED, 0xCCFD, + 0x6CEE, 0xCCF1, 0x6CEF, 0xAA7B, 0x6CF0, 0xAEF5, 0x6CF1, 0xAA74, 0x6CF2, 0xCCFE, 0x6CF3, 0xAA61, 0x6CF5, 0xACA6, 0x6CF9, 0xCD4C, + 0x6D00, 0xCF7C, 0x6D01, 0xCFA1, 0x6D03, 0xCFA4, 0x6D04, 0xCF77, 0x6D07, 0xCFA7, 0x6D08, 0xCFAA, 0x6D09, 0xCFAC, 0x6D0A, 0xCF74, + 0x6D0B, 0xAC76, 0x6D0C, 0xAC7B, 0x6D0D, 0xD249, 0x6D0E, 0xACAD, 0x6D0F, 0xCFA5, 0x6D10, 0xCFAD, 0x6D11, 0xCF7B, 0x6D12, 0xCF73, + 0x6D16, 0xD264, 0x6D17, 0xAC7E, 0x6D18, 0xCFA2, 0x6D19, 0xCF78, 0x6D1A, 0xCF7A, 0x6D1B, 0xACA5, 0x6D1D, 0xCF7D, 0x6D1E, 0xAC7D, + 0x6D1F, 0xCF70, 0x6D20, 0xCFA8, 0x6D22, 0xCFAB, 0x6D25, 0xAC7A, 0x6D27, 0xACA8, 0x6D28, 0xCF6D, 0x6D29, 0xACAA, 0x6D2A, 0xAC78, + 0x6D2B, 0xACAE, 0x6D2C, 0xCFA9, 0x6D2D, 0xCF6F, 0x6D2E, 0xACAB, 0x6D2F, 0xD25E, 0x6D30, 0xCD48, 0x6D31, 0xAC7C, 0x6D32, 0xAC77, + 0x6D33, 0xCF76, 0x6D34, 0xCF6E, 0x6D35, 0xACAC, 0x6D36, 0xACA4, 0x6D37, 0xCFA3, 0x6D38, 0xACA9, 0x6D39, 0xACA7, 0x6D3A, 0xCF79, + 0x6D3B, 0xACA1, 0x6D3C, 0xCF71, 0x6D3D, 0xACA2, 0x6D3E, 0xACA3, 0x6D3F, 0xCF72, 0x6D40, 0xCFA6, 0x6D41, 0xAC79, 0x6D42, 0xCF7E, + 0x6D58, 0xD24C, 0x6D59, 0xAEFD, 0x6D5A, 0xAF43, 0x6D5E, 0xD255, 0x6D5F, 0xD25B, 0x6D60, 0xD257, 0x6D61, 0xD24A, 0x6D62, 0xD24D, + 0x6D63, 0xD246, 0x6D64, 0xD247, 0x6D65, 0xAF4A, 0x6D66, 0xAEFA, 0x6D67, 0xD256, 0x6D68, 0xD25F, 0x6D69, 0xAF45, 0x6D6A, 0xAEF6, + 0x6D6C, 0xAF40, 0x6D6D, 0xD24E, 0x6D6E, 0xAF42, 0x6D6F, 0xD24F, 0x6D70, 0xD259, 0x6D74, 0xAF44, 0x6D75, 0xD268, 0x6D76, 0xD248, + 0x6D77, 0xAEFC, 0x6D78, 0xAEFB, 0x6D79, 0xAF48, 0x6D7A, 0xD245, 0x6D7B, 0xD266, 0x6D7C, 0xD25A, 0x6D7D, 0xD267, 0x6D7E, 0xD261, + 0x6D7F, 0xD253, 0x6D80, 0xD262, 0x6D82, 0xD25C, 0x6D83, 0xD265, 0x6D84, 0xD263, 0x6D85, 0xAF49, 0x6D86, 0xD254, 0x6D87, 0xAEF9, + 0x6D88, 0xAEF8, 0x6D89, 0xAF41, 0x6D8A, 0xAF47, 0x6D8B, 0xD260, 0x6D8C, 0xAF46, 0x6D8D, 0xD251, 0x6D8E, 0xB243, 0x6D90, 0xD269, + 0x6D91, 0xD250, 0x6D92, 0xD24B, 0x6D93, 0xAEFE, 0x6D94, 0xAF4B, 0x6D95, 0xAEF7, 0x6D97, 0xD258, 0x6D98, 0xD25D, 0x6DAA, 0xB265, + 0x6DAB, 0xD5E1, 0x6DAC, 0xD5E5, 0x6DAE, 0xB252, 0x6DAF, 0xB250, 0x6DB2, 0xB247, 0x6DB3, 0xD5E3, 0x6DB4, 0xD5E2, 0x6DB5, 0xB25B, + 0x6DB7, 0xD5E8, 0x6DB8, 0xB255, 0x6DBA, 0xD5FA, 0x6DBB, 0xD647, 0x6DBC, 0xB244, 0x6DBD, 0xD5F7, 0x6DBE, 0xD5F0, 0x6DBF, 0xB267, + 0x6DC0, 0xD5E0, 0x6DC2, 0xD5FC, 0x6DC4, 0xB264, 0x6DC5, 0xB258, 0x6DC6, 0xB263, 0x6DC7, 0xB24E, 0x6DC8, 0xD5EC, 0x6DC9, 0xD5FE, + 0x6DCA, 0xD5F6, 0x6DCB, 0xB24F, 0x6DCC, 0xB249, 0x6DCD, 0xD645, 0x6DCF, 0xD5FD, 0x6DD0, 0xD640, 0x6DD1, 0xB251, 0x6DD2, 0xB259, + 0x6DD3, 0xD642, 0x6DD4, 0xD5EA, 0x6DD5, 0xD5FB, 0x6DD6, 0xD5EF, 0x6DD7, 0xD644, 0x6DD8, 0xB25E, 0x6DD9, 0xB246, 0x6DDA, 0xB25C, + 0x6DDB, 0xD5F4, 0x6DDC, 0xD5F2, 0x6DDD, 0xD5F3, 0x6DDE, 0xB253, 0x6DDF, 0xD5EE, 0x6DE0, 0xD5ED, 0x6DE1, 0xB248, 0x6DE2, 0xD5E7, + 0x6DE3, 0xD646, 0x6DE4, 0xB24A, 0x6DE5, 0xD5F1, 0x6DE6, 0xB268, 0x6DE8, 0xB262, 0x6DE9, 0xD5E6, 0x6DEA, 0xB25F, 0x6DEB, 0xB25D, + 0x6DEC, 0xB266, 0x6DED, 0xD5F8, 0x6DEE, 0xB261, 0x6DEF, 0xD252, 0x6DF0, 0xD5F9, 0x6DF1, 0xB260, 0x6DF2, 0xD641, 0x6DF3, 0xB245, + 0x6DF4, 0xD5F5, 0x6DF5, 0xB257, 0x6DF6, 0xD5E9, 0x6DF7, 0xB256, 0x6DF9, 0xB254, 0x6DFA, 0xB24C, 0x6DFB, 0xB24B, 0x6DFC, 0xD9E7, + 0x6DFD, 0xD643, 0x6E00, 0xD5EB, 0x6E03, 0xD9FC, 0x6E05, 0xB24D, 0x6E19, 0xB541, 0x6E1A, 0xB25A, 0x6E1B, 0xB4EE, 0x6E1C, 0xD9F6, + 0x6E1D, 0xB4FC, 0x6E1F, 0xD9EA, 0x6E20, 0xB4EB, 0x6E21, 0xB4E7, 0x6E22, 0xDA49, 0x6E23, 0xB4ED, 0x6E24, 0xB4F1, 0x6E25, 0xB4EC, + 0x6E26, 0xB4F5, 0x6E27, 0xDA4D, 0x6E28, 0xDA44, 0x6E2B, 0xD9F1, 0x6E2C, 0xB4FA, 0x6E2D, 0xB4F4, 0x6E2E, 0xD9FD, 0x6E2F, 0xB4E4, + 0x6E30, 0xDA4A, 0x6E31, 0xDA43, 0x6E32, 0xB4E8, 0x6E33, 0xD9F7, 0x6E34, 0xB4F7, 0x6E35, 0xDA55, 0x6E36, 0xDA56, 0x6E38, 0xB4E5, + 0x6E39, 0xDA48, 0x6E3A, 0xB4F9, 0x6E3B, 0xD9FB, 0x6E3C, 0xD9ED, 0x6E3D, 0xD9EE, 0x6E3E, 0xB4FD, 0x6E3F, 0xD9F2, 0x6E40, 0xD9F9, + 0x6E41, 0xD9F3, 0x6E43, 0xB4FB, 0x6E44, 0xB544, 0x6E45, 0xD9EF, 0x6E46, 0xD9E8, 0x6E47, 0xD9E9, 0x6E49, 0xD9EB, 0x6E4A, 0xB4EA, + 0x6E4B, 0xD9F8, 0x6E4D, 0xB4F8, 0x6E4E, 0xB542, 0x6E51, 0xD9FA, 0x6E52, 0xDA53, 0x6E53, 0xDA4B, 0x6E54, 0xB4E6, 0x6E55, 0xDA51, + 0x6E56, 0xB4F2, 0x6E58, 0xB4F0, 0x6E5A, 0xDA57, 0x6E5B, 0xB4EF, 0x6E5C, 0xDA41, 0x6E5D, 0xD9F4, 0x6E5E, 0xD9FE, 0x6E5F, 0xB547, + 0x6E60, 0xDA45, 0x6E61, 0xDA42, 0x6E62, 0xD9F0, 0x6E63, 0xB543, 0x6E64, 0xDA4F, 0x6E65, 0xDA4C, 0x6E66, 0xDA54, 0x6E67, 0xB4E9, + 0x6E68, 0xDA40, 0x6E69, 0xB546, 0x6E6B, 0xDA47, 0x6E6E, 0xB4F3, 0x6E6F, 0xB4F6, 0x6E71, 0xDA46, 0x6E72, 0xB545, 0x6E73, 0xD9F5, + 0x6E74, 0xD5E4, 0x6E77, 0xDA50, 0x6E78, 0xDA4E, 0x6E79, 0xDA52, 0x6E88, 0xD9EC, 0x6E89, 0xB540, 0x6E8D, 0xDE61, 0x6E8E, 0xDE60, + 0x6E8F, 0xDE46, 0x6E90, 0xB7BD, 0x6E92, 0xDE5F, 0x6E93, 0xDE49, 0x6E94, 0xDE4A, 0x6E96, 0xB7C7, 0x6E97, 0xDE68, 0x6E98, 0xB7C2, + 0x6E99, 0xDE5E, 0x6E9B, 0xDE43, 0x6E9C, 0xB7C8, 0x6E9D, 0xB7BE, 0x6E9E, 0xDE52, 0x6E9F, 0xDE48, 0x6EA0, 0xDE4B, 0x6EA1, 0xDE63, + 0x6EA2, 0xB7B8, 0x6EA3, 0xDE6A, 0x6EA4, 0xDE62, 0x6EA5, 0xB7C1, 0x6EA6, 0xDE57, 0x6EA7, 0xB7CC, 0x6EAA, 0xB7CB, 0x6EAB, 0xB7C5, + 0x6EAE, 0xDE69, 0x6EAF, 0xB7B9, 0x6EB0, 0xDE55, 0x6EB1, 0xDE4C, 0x6EB2, 0xDE59, 0x6EB3, 0xDE65, 0x6EB4, 0xB7CD, 0x6EB6, 0xB7BB, + 0x6EB7, 0xDE54, 0x6EB9, 0xDE4D, 0x6EBA, 0xB7C4, 0x6EBC, 0xB7C3, 0x6EBD, 0xDE50, 0x6EBE, 0xDE5A, 0x6EBF, 0xDE64, 0x6EC0, 0xDE47, + 0x6EC1, 0xDE51, 0x6EC2, 0xB7BC, 0x6EC3, 0xDE5B, 0x6EC4, 0xB7C9, 0x6EC5, 0xB7C0, 0x6EC6, 0xDE4E, 0x6EC7, 0xB7BF, 0x6EC8, 0xDE45, + 0x6EC9, 0xDE53, 0x6ECA, 0xDE67, 0x6ECB, 0xB4FE, 0x6ECC, 0xBAB0, 0x6ECD, 0xDE56, 0x6ECE, 0xE26C, 0x6ECF, 0xDE58, 0x6ED0, 0xDE66, + 0x6ED1, 0xB7C6, 0x6ED2, 0xDE4F, 0x6ED3, 0xB7BA, 0x6ED4, 0xB7CA, 0x6ED5, 0xBCF0, 0x6ED6, 0xDE44, 0x6ED8, 0xDE5D, 0x6EDC, 0xDE5C, + 0x6EEB, 0xE2AA, 0x6EEC, 0xBAAD, 0x6EED, 0xE27D, 0x6EEE, 0xE2A4, 0x6EEF, 0xBAA2, 0x6EF1, 0xE26E, 0x6EF2, 0xBAAF, 0x6EF4, 0xBA77, + 0x6EF5, 0xE26D, 0x6EF6, 0xE2B0, 0x6EF7, 0xBAB1, 0x6EF8, 0xE271, 0x6EF9, 0xE2A3, 0x6EFB, 0xE273, 0x6EFC, 0xE2B3, 0x6EFD, 0xE2AF, + 0x6EFE, 0xBA75, 0x6EFF, 0xBAA1, 0x6F00, 0xE653, 0x6F01, 0xBAAE, 0x6F02, 0xBA7D, 0x6F03, 0xE26F, 0x6F05, 0xE2AE, 0x6F06, 0xBAA3, + 0x6F07, 0xE2AB, 0x6F08, 0xE2B8, 0x6F09, 0xE275, 0x6F0A, 0xE27E, 0x6F0D, 0xE2B6, 0x6F0E, 0xE2AC, 0x6F0F, 0xBA7C, 0x6F12, 0xE27C, + 0x6F13, 0xBA76, 0x6F14, 0xBA74, 0x6F15, 0xBAA8, 0x6F18, 0xE27A, 0x6F19, 0xE277, 0x6F1A, 0xE278, 0x6F1C, 0xE2B2, 0x6F1E, 0xE2B7, + 0x6F1F, 0xE2B5, 0x6F20, 0xBA7A, 0x6F21, 0xE2B9, 0x6F22, 0xBA7E, 0x6F23, 0xBAA7, 0x6F25, 0xE270, 0x6F26, 0xE5FA, 0x6F27, 0xE279, + 0x6F29, 0xBA78, 0x6F2A, 0xBAAC, 0x6F2B, 0xBAA9, 0x6F2C, 0xBA7B, 0x6F2D, 0xE2A5, 0x6F2E, 0xE274, 0x6F2F, 0xBAAA, 0x6F30, 0xE2A7, + 0x6F31, 0xBAA4, 0x6F32, 0xBAA6, 0x6F33, 0xBA73, 0x6F35, 0xE2A9, 0x6F36, 0xE2A1, 0x6F37, 0xE272, 0x6F38, 0xBAA5, 0x6F39, 0xE2B1, + 0x6F3A, 0xE2B4, 0x6F3B, 0xE27B, 0x6F3C, 0xE2A8, 0x6F3E, 0xBA79, 0x6F3F, 0xBCDF, 0x6F40, 0xE2A6, 0x6F41, 0xE5F9, 0x6F43, 0xE2AD, + 0x6F4E, 0xE276, 0x6F4F, 0xE644, 0x6F50, 0xE64E, 0x6F51, 0xBCE2, 0x6F52, 0xE64D, 0x6F53, 0xE659, 0x6F54, 0xBCE4, 0x6F55, 0xE64B, + 0x6F57, 0xE64F, 0x6F58, 0xBCEF, 0x6F5A, 0xE646, 0x6F5B, 0xBCE7, 0x6F5D, 0xE652, 0x6F5E, 0xE9F0, 0x6F5F, 0xBCF3, 0x6F60, 0xBCF2, + 0x6F61, 0xE654, 0x6F62, 0xE643, 0x6F63, 0xE65E, 0x6F64, 0xBCED, 0x6F66, 0xBCE3, 0x6F67, 0xE657, 0x6F69, 0xE65B, 0x6F6A, 0xE660, + 0x6F6B, 0xE655, 0x6F6C, 0xE649, 0x6F6D, 0xBCE6, 0x6F6E, 0xBCE9, 0x6F6F, 0xBCF1, 0x6F70, 0xBCEC, 0x6F72, 0xE64C, 0x6F73, 0xE2A2, + 0x6F76, 0xE648, 0x6F77, 0xE65F, 0x6F78, 0xBCE8, 0x6F7A, 0xBCEB, 0x6F7B, 0xE661, 0x6F7C, 0xBCE0, 0x6F7D, 0xE656, 0x6F7E, 0xE5FB, + 0x6F7F, 0xE65C, 0x6F80, 0xC0DF, 0x6F82, 0xE64A, 0x6F84, 0xBCE1, 0x6F85, 0xE645, 0x6F86, 0xBCE5, 0x6F87, 0xE5FC, 0x6F88, 0xBAAB, + 0x6F89, 0xE641, 0x6F8B, 0xE65A, 0x6F8C, 0xE642, 0x6F8D, 0xE640, 0x6F8E, 0xBCEA, 0x6F90, 0xE658, 0x6F92, 0xE5FE, 0x6F93, 0xE651, + 0x6F94, 0xE650, 0x6F95, 0xE65D, 0x6F96, 0xE647, 0x6F97, 0xBCEE, 0x6F9E, 0xE9F3, 0x6FA0, 0xBF49, 0x6FA1, 0xBEFE, 0x6FA2, 0xEA40, + 0x6FA3, 0xE9EB, 0x6FA4, 0xBF41, 0x6FA5, 0xE9F7, 0x6FA6, 0xBF48, 0x6FA7, 0xBF43, 0x6FA8, 0xE9F5, 0x6FA9, 0xED4F, 0x6FAA, 0xE9FB, + 0x6FAB, 0xEA42, 0x6FAC, 0xE9FA, 0x6FAD, 0xE9E9, 0x6FAE, 0xE9F8, 0x6FAF, 0xEA44, 0x6FB0, 0xEA46, 0x6FB1, 0xBEFD, 0x6FB2, 0xEA45, + 0x6FB3, 0xBF44, 0x6FB4, 0xBF4A, 0x6FB6, 0xBF47, 0x6FB8, 0xE9FE, 0x6FB9, 0xBF46, 0x6FBA, 0xE9F9, 0x6FBC, 0xE9ED, 0x6FBD, 0xE9F2, + 0x6FBF, 0xE9FD, 0x6FC0, 0xBF45, 0x6FC1, 0xBF42, 0x6FC2, 0xBEFC, 0x6FC3, 0xBF40, 0x6FC4, 0xE9F1, 0x6FC6, 0xE5FD, 0x6FC7, 0xE9EC, + 0x6FC8, 0xE9EF, 0x6FC9, 0xEA41, 0x6FCA, 0xE9F4, 0x6FCB, 0xE9EA, 0x6FCC, 0xED4E, 0x6FCD, 0xEA43, 0x6FCE, 0xE9EE, 0x6FCF, 0xE9FC, + 0x6FD4, 0xED51, 0x6FD5, 0xC0E3, 0x6FD8, 0xC0D7, 0x6FDB, 0xC0DB, 0x6FDC, 0xED53, 0x6FDD, 0xED59, 0x6FDE, 0xED57, 0x6FDF, 0xC0D9, + 0x6FE0, 0xC0DA, 0x6FE1, 0xC0E1, 0x6FE2, 0xED5A, 0x6FE3, 0xED52, 0x6FE4, 0xC0DC, 0x6FE6, 0xED56, 0x6FE7, 0xED55, 0x6FE8, 0xED5B, + 0x6FE9, 0xC0E2, 0x6FEB, 0xC0DD, 0x6FEC, 0xC0E0, 0x6FED, 0xED54, 0x6FEE, 0xC0E4, 0x6FEF, 0xC0DE, 0x6FF0, 0xC0E5, 0x6FF1, 0xC0D8, + 0x6FF2, 0xED58, 0x6FF4, 0xED50, 0x6FF7, 0xEFF7, 0x6FFA, 0xC271, 0x6FFB, 0xEFF4, 0x6FFC, 0xEFF6, 0x6FFE, 0xC26F, 0x6FFF, 0xEFF2, + 0x7000, 0xEFF3, 0x7001, 0xEFEE, 0x7004, 0xE9F6, 0x7005, 0xEFEF, 0x7006, 0xC270, 0x7007, 0xEFEB, 0x7009, 0xC26D, 0x700A, 0xEFF8, + 0x700B, 0xC26E, 0x700C, 0xEFEC, 0x700D, 0xEFED, 0x700E, 0xEFF1, 0x700F, 0xC273, 0x7011, 0xC272, 0x7014, 0xEFF0, 0x7015, 0xC378, + 0x7016, 0xF25F, 0x7017, 0xF265, 0x7018, 0xC379, 0x7019, 0xF25C, 0x701A, 0xC376, 0x701B, 0xC373, 0x701C, 0xF267, 0x701D, 0xC377, + 0x701F, 0xC374, 0x7020, 0xF25E, 0x7021, 0xF261, 0x7022, 0xF262, 0x7023, 0xF263, 0x7024, 0xF266, 0x7026, 0xEFF5, 0x7027, 0xF25D, + 0x7028, 0xC375, 0x7029, 0xF264, 0x702A, 0xF268, 0x702B, 0xF260, 0x702F, 0xF45D, 0x7030, 0xC46A, 0x7031, 0xF460, 0x7032, 0xC46B, + 0x7033, 0xF468, 0x7034, 0xF45F, 0x7035, 0xF45C, 0x7037, 0xF45E, 0x7038, 0xF462, 0x7039, 0xF465, 0x703A, 0xF464, 0x703B, 0xF467, + 0x703C, 0xF45B, 0x703E, 0xC469, 0x703F, 0xF463, 0x7040, 0xF466, 0x7041, 0xF469, 0x7042, 0xF461, 0x7043, 0xF5D3, 0x7044, 0xF5D4, + 0x7045, 0xF5D8, 0x7046, 0xF5D9, 0x7048, 0xF5D6, 0x7049, 0xF5D7, 0x704A, 0xF5D5, 0x704C, 0xC4E9, 0x7051, 0xC578, 0x7052, 0xF6EB, + 0x7055, 0xF6E8, 0x7056, 0xF6E9, 0x7057, 0xF6EA, 0x7058, 0xC579, 0x705A, 0xF7E5, 0x705B, 0xF7E4, 0x705D, 0xF8AF, 0x705E, 0xC5F4, + 0x705F, 0xF8AD, 0x7060, 0xF8B0, 0x7061, 0xF8AE, 0x7062, 0xF8F5, 0x7063, 0xC657, 0x7064, 0xC665, 0x7065, 0xF9A3, 0x7066, 0xF96C, + 0x7068, 0xF9A2, 0x7069, 0xF9D0, 0x706A, 0xF9D1, 0x706B, 0xA4F5, 0x7070, 0xA6C7, 0x7071, 0xCA41, 0x7074, 0xCB5E, 0x7076, 0xA85F, + 0x7078, 0xA862, 0x707A, 0xCB5F, 0x707C, 0xA860, 0x707D, 0xA861, 0x7082, 0xCD58, 0x7083, 0xCD5A, 0x7084, 0xCD55, 0x7085, 0xCD52, + 0x7086, 0xCD54, 0x708A, 0xAAA4, 0x708E, 0xAAA2, 0x7091, 0xCD56, 0x7092, 0xAAA3, 0x7093, 0xCD53, 0x7094, 0xCD50, 0x7095, 0xAAA1, + 0x7096, 0xCD57, 0x7098, 0xCD51, 0x7099, 0xAAA5, 0x709A, 0xCD59, 0x709F, 0xCFAF, 0x70A1, 0xCFB3, 0x70A4, 0xACB7, 0x70A9, 0xCFB6, + 0x70AB, 0xACAF, 0x70AC, 0xACB2, 0x70AD, 0xACB4, 0x70AE, 0xACB6, 0x70AF, 0xACB3, 0x70B0, 0xCFB2, 0x70B1, 0xCFB1, 0x70B3, 0xACB1, + 0x70B4, 0xCFB4, 0x70B5, 0xCFB5, 0x70B7, 0xCFAE, 0x70B8, 0xACB5, 0x70BA, 0xACB0, 0x70BE, 0xCFB0, 0x70C5, 0xD277, 0x70C6, 0xD278, + 0x70C7, 0xD279, 0x70C8, 0xAF50, 0x70CA, 0xAF4C, 0x70CB, 0xD26E, 0x70CD, 0xD276, 0x70CE, 0xD27B, 0x70CF, 0xAF51, 0x70D1, 0xD26C, + 0x70D2, 0xD272, 0x70D3, 0xD26B, 0x70D4, 0xD275, 0x70D7, 0xD271, 0x70D8, 0xAF4D, 0x70D9, 0xAF4F, 0x70DA, 0xD27A, 0x70DC, 0xD26A, + 0x70DD, 0xD26D, 0x70DE, 0xD273, 0x70E0, 0xD274, 0x70E1, 0xD27C, 0x70E2, 0xD270, 0x70E4, 0xAF4E, 0x70EF, 0xB26D, 0x70F0, 0xD64E, + 0x70F3, 0xD650, 0x70F4, 0xD64C, 0x70F6, 0xD658, 0x70F7, 0xD64A, 0x70F8, 0xD657, 0x70F9, 0xB269, 0x70FA, 0xD648, 0x70FB, 0xDA5B, + 0x70FC, 0xD652, 0x70FD, 0xB26C, 0x70FF, 0xD653, 0x7100, 0xD656, 0x7102, 0xD65A, 0x7104, 0xD64F, 0x7106, 0xD654, 0x7109, 0xB26A, + 0x710A, 0xB26B, 0x710B, 0xD659, 0x710C, 0xD64D, 0x710D, 0xD649, 0x710E, 0xD65B, 0x7110, 0xD651, 0x7113, 0xD655, 0x7117, 0xD64B, + 0x7119, 0xB548, 0x711A, 0xB549, 0x711B, 0xDA65, 0x711C, 0xB54F, 0x711E, 0xDA59, 0x711F, 0xDA62, 0x7120, 0xDA58, 0x7121, 0xB54C, + 0x7122, 0xDA60, 0x7123, 0xDA5E, 0x7125, 0xDA5F, 0x7126, 0xB54A, 0x7128, 0xDA63, 0x712E, 0xDA5C, 0x712F, 0xDA5A, 0x7130, 0xB54B, + 0x7131, 0xDA5D, 0x7132, 0xDA61, 0x7136, 0xB54D, 0x713A, 0xDA64, 0x7141, 0xDE70, 0x7142, 0xDE77, 0x7143, 0xDE79, 0x7144, 0xDEA1, + 0x7146, 0xB7DA, 0x7147, 0xDE6B, 0x7149, 0xB7D2, 0x714B, 0xDE7A, 0x714C, 0xB7D7, 0x714D, 0xDEA2, 0x714E, 0xB7CE, 0x7150, 0xDE7D, + 0x7152, 0xDE6D, 0x7153, 0xDE7E, 0x7154, 0xDE6C, 0x7156, 0xB7DC, 0x7158, 0xDE78, 0x7159, 0xB7CF, 0x715A, 0xDEA3, 0x715C, 0xB7D4, + 0x715D, 0xDE71, 0x715E, 0xB7D9, 0x715F, 0xDE7C, 0x7160, 0xDE6F, 0x7161, 0xDE76, 0x7162, 0xDE72, 0x7163, 0xDE6E, 0x7164, 0xB7D1, + 0x7165, 0xB7D8, 0x7166, 0xB7D6, 0x7167, 0xB7D3, 0x7168, 0xB7DB, 0x7169, 0xB7D0, 0x716A, 0xDE75, 0x716C, 0xB7D5, 0x716E, 0xB54E, + 0x7170, 0xDE7B, 0x7172, 0xDE73, 0x7178, 0xDE74, 0x717B, 0xE2C1, 0x717D, 0xBAB4, 0x7180, 0xE2BD, 0x7181, 0xE2C3, 0x7182, 0xE2BF, + 0x7184, 0xBAB6, 0x7185, 0xE2BE, 0x7186, 0xE2C2, 0x7187, 0xE2BA, 0x7189, 0xE2BC, 0x718A, 0xBAB5, 0x718F, 0xE2C0, 0x7190, 0xE2BB, + 0x7192, 0xBAB7, 0x7194, 0xBAB2, 0x7197, 0xE2C4, 0x7199, 0xBAB3, 0x719A, 0xE667, 0x719B, 0xE664, 0x719C, 0xE670, 0x719D, 0xE66A, + 0x719E, 0xE66C, 0x719F, 0xBCF4, 0x71A0, 0xE666, 0x71A1, 0xE66E, 0x71A4, 0xE66D, 0x71A5, 0xE66B, 0x71A7, 0xE671, 0x71A8, 0xBCF7, + 0x71A9, 0xE668, 0x71AA, 0xE66F, 0x71AC, 0xBCF5, 0x71AF, 0xE663, 0x71B0, 0xE665, 0x71B1, 0xBCF6, 0x71B2, 0xE662, 0x71B3, 0xE672, + 0x71B5, 0xE669, 0x71B8, 0xEA4A, 0x71B9, 0xBF51, 0x71BC, 0xEA55, 0x71BD, 0xEA53, 0x71BE, 0xBF4B, 0x71BF, 0xEA49, 0x71C0, 0xEA4C, + 0x71C1, 0xEA4D, 0x71C2, 0xEA48, 0x71C3, 0xBF55, 0x71C4, 0xBF56, 0x71C5, 0xEA47, 0x71C6, 0xEA56, 0x71C7, 0xEA51, 0x71C8, 0xBF4F, + 0x71C9, 0xBF4C, 0x71CA, 0xEA50, 0x71CB, 0xEA4E, 0x71CE, 0xBF52, 0x71CF, 0xEA52, 0x71D0, 0xBF4D, 0x71D2, 0xBF4E, 0x71D4, 0xEA4F, + 0x71D5, 0xBF50, 0x71D6, 0xEA4B, 0x71D8, 0xEA54, 0x71D9, 0xBF53, 0x71DA, 0xEA57, 0x71DB, 0xEA58, 0x71DC, 0xBF54, 0x71DF, 0xC0E7, + 0x71E0, 0xC0EE, 0x71E1, 0xED5C, 0x71E2, 0xED62, 0x71E4, 0xED60, 0x71E5, 0xC0EA, 0x71E6, 0xC0E9, 0x71E7, 0xC0E6, 0x71E8, 0xED5E, + 0x71EC, 0xC0EC, 0x71ED, 0xC0EB, 0x71EE, 0xC0E8, 0x71F0, 0xED61, 0x71F1, 0xED5D, 0x71F2, 0xED5F, 0x71F4, 0xC0ED, 0x71F8, 0xC277, + 0x71F9, 0xEFFB, 0x71FB, 0xC274, 0x71FC, 0xC275, 0x71FD, 0xEFFD, 0x71FE, 0xC276, 0x71FF, 0xEFFA, 0x7201, 0xEFF9, 0x7202, 0xF26C, + 0x7203, 0xEFFC, 0x7205, 0xF26D, 0x7206, 0xC37A, 0x7207, 0xF26B, 0x720A, 0xF26A, 0x720C, 0xF269, 0x720D, 0xC37B, 0x7210, 0xC46C, + 0x7213, 0xF46A, 0x7214, 0xF46B, 0x7219, 0xF5DC, 0x721A, 0xF5DB, 0x721B, 0xC4EA, 0x721D, 0xF5DA, 0x721E, 0xF6EC, 0x721F, 0xF6ED, + 0x7222, 0xF7E6, 0x7223, 0xF8B1, 0x7226, 0xF8F6, 0x7227, 0xF9BC, 0x7228, 0xC679, 0x7229, 0xF9C6, 0x722A, 0xA4F6, 0x722C, 0xAAA6, + 0x722D, 0xAAA7, 0x7230, 0xACB8, 0x7235, 0xC0EF, 0x7236, 0xA4F7, 0x7238, 0xAAA8, 0x7239, 0xAF52, 0x723A, 0xB7DD, 0x723B, 0xA4F8, + 0x723D, 0xB26E, 0x723E, 0xBAB8, 0x723F, 0xC962, 0x7241, 0xCFB7, 0x7242, 0xD27D, 0x7244, 0xE2C5, 0x7246, 0xC0F0, 0x7247, 0xA4F9, + 0x7248, 0xAAA9, 0x7249, 0xCFB8, 0x724A, 0xCFB9, 0x724B, 0xDA66, 0x724C, 0xB550, 0x724F, 0xDEA4, 0x7252, 0xB7DE, 0x7253, 0xE2C6, + 0x7256, 0xBCF8, 0x7258, 0xC37C, 0x7259, 0xA4FA, 0x725A, 0xDA67, 0x725B, 0xA4FB, 0x725D, 0xA6C9, 0x725E, 0xCA42, 0x725F, 0xA6C8, + 0x7260, 0xA865, 0x7261, 0xA864, 0x7262, 0xA863, 0x7263, 0xCB60, 0x7267, 0xAAAA, 0x7269, 0xAAAB, 0x726A, 0xCD5B, 0x726C, 0xCFBA, + 0x726E, 0xCFBD, 0x726F, 0xACBA, 0x7270, 0xCFBB, 0x7272, 0xACB9, 0x7273, 0xCFBC, 0x7274, 0xACBB, 0x7276, 0xD2A2, 0x7277, 0xD2A1, + 0x7278, 0xD27E, 0x7279, 0xAF53, 0x727B, 0xD65D, 0x727C, 0xD65E, 0x727D, 0xB26F, 0x727E, 0xD65C, 0x727F, 0xD65F, 0x7280, 0xB552, + 0x7281, 0xB270, 0x7284, 0xB551, 0x7285, 0xDA6B, 0x7286, 0xDA6A, 0x7288, 0xDA68, 0x7289, 0xDA69, 0x728B, 0xDA6C, 0x728C, 0xDEA6, + 0x728D, 0xDEA5, 0x728E, 0xDEA9, 0x7290, 0xDEA8, 0x7291, 0xDEA7, 0x7292, 0xBAB9, 0x7293, 0xE2C9, 0x7295, 0xE2C8, 0x7296, 0xBABA, + 0x7297, 0xE2C7, 0x7298, 0xE673, 0x729A, 0xE674, 0x729B, 0xBCF9, 0x729D, 0xEA59, 0x729E, 0xEA5A, 0x72A1, 0xF272, 0x72A2, 0xC37D, + 0x72A3, 0xF271, 0x72A4, 0xF270, 0x72A5, 0xF26E, 0x72A6, 0xF26F, 0x72A7, 0xC4EB, 0x72A8, 0xF46C, 0x72A9, 0xF6EE, 0x72AA, 0xF8F7, + 0x72AC, 0xA4FC, 0x72AE, 0xC9A5, 0x72AF, 0xA5C7, 0x72B0, 0xC9A6, 0x72B4, 0xCA43, 0x72B5, 0xCA44, 0x72BA, 0xCB66, 0x72BD, 0xCB62, + 0x72BF, 0xCB61, 0x72C0, 0xAAAC, 0x72C1, 0xCB65, 0x72C2, 0xA867, 0x72C3, 0xCB63, 0x72C4, 0xA866, 0x72C5, 0xCB67, 0x72C6, 0xCB64, + 0x72C9, 0xCD5F, 0x72CA, 0xCFBE, 0x72CB, 0xCD5D, 0x72CC, 0xCD64, 0x72CE, 0xAAAD, 0x72D0, 0xAAB0, 0x72D1, 0xCD65, 0x72D2, 0xCD61, + 0x72D4, 0xCD62, 0x72D6, 0xCD5C, 0x72D7, 0xAAAF, 0x72D8, 0xCD5E, 0x72D9, 0xAAAE, 0x72DA, 0xCD63, 0x72DC, 0xCD60, 0x72DF, 0xCFC2, + 0x72E0, 0xACBD, 0x72E1, 0xACBE, 0x72E3, 0xCFC5, 0x72E4, 0xCFBF, 0x72E6, 0xCFC4, 0x72E8, 0xCFC0, 0x72E9, 0xACBC, 0x72EA, 0xCFC3, + 0x72EB, 0xCFC1, 0x72F3, 0xD2A8, 0x72F4, 0xD2A5, 0x72F6, 0xD2A7, 0x72F7, 0xAF58, 0x72F8, 0xAF57, 0x72F9, 0xAF55, 0x72FA, 0xD2A4, + 0x72FB, 0xD2A9, 0x72FC, 0xAF54, 0x72FD, 0xAF56, 0x72FE, 0xD2A6, 0x72FF, 0xD667, 0x7300, 0xD2A3, 0x7301, 0xD2AA, 0x7307, 0xD662, + 0x7308, 0xD666, 0x730A, 0xD665, 0x730B, 0xDA6E, 0x730C, 0xDA79, 0x730F, 0xD668, 0x7311, 0xD663, 0x7312, 0xDA6D, 0x7313, 0xB274, + 0x7316, 0xB273, 0x7317, 0xD661, 0x7318, 0xD664, 0x7319, 0xB275, 0x731B, 0xB272, 0x731C, 0xB271, 0x731D, 0xD660, 0x731E, 0xD669, + 0x7322, 0xDA70, 0x7323, 0xDA77, 0x7325, 0xB554, 0x7326, 0xDA76, 0x7327, 0xDA73, 0x7329, 0xB556, 0x732D, 0xDA75, 0x7330, 0xDA6F, + 0x7331, 0xDA71, 0x7332, 0xDA74, 0x7333, 0xDA72, 0x7334, 0xB555, 0x7335, 0xDA78, 0x7336, 0xB553, 0x7337, 0xB7DF, 0x733A, 0xDEAD, + 0x733B, 0xDEAC, 0x733C, 0xDEAA, 0x733E, 0xB7E2, 0x733F, 0xB7E1, 0x7340, 0xDEAE, 0x7342, 0xDEAB, 0x7343, 0xE2CA, 0x7344, 0xBABB, + 0x7345, 0xB7E0, 0x7349, 0xDEB0, 0x734A, 0xDEAF, 0x734C, 0xE2CD, 0x734D, 0xE2CB, 0x734E, 0xBCFA, 0x7350, 0xBABC, 0x7351, 0xE2CC, + 0x7352, 0xE676, 0x7357, 0xBCFB, 0x7358, 0xE675, 0x7359, 0xE67E, 0x735A, 0xE67D, 0x735B, 0xE67B, 0x735D, 0xE67A, 0x735E, 0xE677, + 0x735F, 0xE678, 0x7360, 0xE679, 0x7361, 0xE67C, 0x7362, 0xE6A1, 0x7365, 0xEA5F, 0x7366, 0xEA5C, 0x7367, 0xEA5D, 0x7368, 0xBF57, + 0x7369, 0xEA5B, 0x736A, 0xEA61, 0x736B, 0xEA60, 0x736C, 0xEA5E, 0x736E, 0xED64, 0x736F, 0xED65, 0x7370, 0xC0F1, 0x7372, 0xC0F2, + 0x7373, 0xED63, 0x7375, 0xC279, 0x7376, 0xEFFE, 0x7377, 0xC278, 0x7378, 0xC37E, 0x737A, 0xC3A1, 0x737B, 0xC46D, 0x737C, 0xF46E, + 0x737D, 0xF46D, 0x737E, 0xF5DD, 0x737F, 0xF6EF, 0x7380, 0xC57A, 0x7381, 0xF7E8, 0x7382, 0xF7E7, 0x7383, 0xF7E9, 0x7384, 0xA5C8, + 0x7385, 0xCFC6, 0x7386, 0xAF59, 0x7387, 0xB276, 0x7388, 0xD66A, 0x7389, 0xA5C9, 0x738A, 0xC9A7, 0x738B, 0xA4FD, 0x738E, 0xCA45, + 0x7392, 0xCB6C, 0x7393, 0xCB6A, 0x7394, 0xCB6B, 0x7395, 0xCB68, 0x7396, 0xA868, 0x7397, 0xCB69, 0x739D, 0xCD6D, 0x739F, 0xAAB3, + 0x73A0, 0xCD6B, 0x73A1, 0xCD67, 0x73A2, 0xCD6A, 0x73A4, 0xCD66, 0x73A5, 0xAAB5, 0x73A6, 0xCD69, 0x73A8, 0xAAB2, 0x73A9, 0xAAB1, + 0x73AB, 0xAAB4, 0x73AC, 0xCD6C, 0x73AD, 0xCD68, 0x73B2, 0xACC2, 0x73B3, 0xACC5, 0x73B4, 0xCFCE, 0x73B5, 0xCFCD, 0x73B6, 0xCFCC, + 0x73B7, 0xACBF, 0x73B8, 0xCFD5, 0x73B9, 0xCFCB, 0x73BB, 0xACC1, 0x73BC, 0xD2AF, 0x73BE, 0xCFD2, 0x73BF, 0xCFD0, 0x73C0, 0xACC4, + 0x73C2, 0xCFC8, 0x73C3, 0xCFD3, 0x73C5, 0xCFCA, 0x73C6, 0xCFD4, 0x73C7, 0xCFD1, 0x73C8, 0xCFC9, 0x73CA, 0xACC0, 0x73CB, 0xCFD6, + 0x73CC, 0xCFC7, 0x73CD, 0xACC3, 0x73D2, 0xD2B4, 0x73D3, 0xD2AB, 0x73D4, 0xD2B6, 0x73D6, 0xD2AE, 0x73D7, 0xD2B9, 0x73D8, 0xD2BA, + 0x73D9, 0xD2AC, 0x73DA, 0xD2B8, 0x73DB, 0xD2B5, 0x73DC, 0xD2B3, 0x73DD, 0xD2B7, 0x73DE, 0xAF5F, 0x73E0, 0xAF5D, 0x73E3, 0xD2B1, + 0x73E5, 0xD2AD, 0x73E7, 0xD2B0, 0x73E8, 0xD2BB, 0x73E9, 0xD2B2, 0x73EA, 0xAF5E, 0x73EB, 0xCFCF, 0x73ED, 0xAF5A, 0x73EE, 0xAF5C, + 0x73F4, 0xD678, 0x73F5, 0xD66D, 0x73F6, 0xD66B, 0x73F8, 0xD66C, 0x73FA, 0xD673, 0x73FC, 0xD674, 0x73FD, 0xD670, 0x73FE, 0xB27B, + 0x73FF, 0xD675, 0x7400, 0xD672, 0x7401, 0xD66F, 0x7403, 0xB279, 0x7404, 0xD66E, 0x7405, 0xB277, 0x7406, 0xB27A, 0x7407, 0xD671, + 0x7408, 0xD679, 0x7409, 0xAF5B, 0x740A, 0xB278, 0x740B, 0xD677, 0x740C, 0xD676, 0x740D, 0xB27C, 0x7416, 0xDA7E, 0x741A, 0xDAA1, + 0x741B, 0xB560, 0x741D, 0xDAA7, 0x7420, 0xDAA9, 0x7421, 0xDAA2, 0x7422, 0xB55A, 0x7423, 0xDAA6, 0x7424, 0xDAA5, 0x7425, 0xB55B, + 0x7426, 0xB561, 0x7428, 0xB562, 0x7429, 0xDAA8, 0x742A, 0xB558, 0x742B, 0xDA7D, 0x742C, 0xDA7B, 0x742D, 0xDAA3, 0x742E, 0xDA7A, + 0x742F, 0xB55F, 0x7430, 0xDA7C, 0x7431, 0xDAA4, 0x7432, 0xDAAA, 0x7433, 0xB559, 0x7434, 0xB55E, 0x7435, 0xB55C, 0x7436, 0xB55D, + 0x743A, 0xB557, 0x743F, 0xB7E9, 0x7440, 0xDEB7, 0x7441, 0xB7E8, 0x7442, 0xDEBB, 0x7444, 0xDEB1, 0x7446, 0xDEBC, 0x744A, 0xDEB2, + 0x744B, 0xDEB3, 0x744D, 0xDEBD, 0x744E, 0xDEBA, 0x744F, 0xDEB8, 0x7450, 0xDEB9, 0x7451, 0xDEB5, 0x7452, 0xDEB4, 0x7454, 0xDEBE, + 0x7455, 0xB7E5, 0x7457, 0xDEB6, 0x7459, 0xB7EA, 0x745A, 0xB7E4, 0x745B, 0xB7EB, 0x745C, 0xB7EC, 0x745E, 0xB7E7, 0x745F, 0xB7E6, + 0x7462, 0xE2CE, 0x7463, 0xBABE, 0x7464, 0xBABD, 0x7467, 0xE2D3, 0x7469, 0xBCFC, 0x746A, 0xBABF, 0x746D, 0xBAC1, 0x746E, 0xE2D4, + 0x746F, 0xB7E3, 0x7470, 0xBAC0, 0x7471, 0xE2D0, 0x7472, 0xE2D2, 0x7473, 0xE2CF, 0x7475, 0xE2D1, 0x7479, 0xE6AB, 0x747C, 0xE6AA, + 0x747D, 0xE6A7, 0x747E, 0xBD40, 0x747F, 0xEA62, 0x7480, 0xBD41, 0x7481, 0xE6A6, 0x7483, 0xBCFE, 0x7485, 0xE6A8, 0x7486, 0xE6A5, + 0x7487, 0xE6A2, 0x7488, 0xE6A9, 0x7489, 0xE6A3, 0x748A, 0xE6A4, 0x748B, 0xBCFD, 0x7490, 0xED69, 0x7492, 0xEA66, 0x7494, 0xEA65, + 0x7495, 0xEA67, 0x7497, 0xED66, 0x7498, 0xBF5A, 0x749A, 0xEA63, 0x749C, 0xBF58, 0x749E, 0xBF5C, 0x749F, 0xBF5B, 0x74A0, 0xEA64, + 0x74A1, 0xEA68, 0x74A3, 0xBF59, 0x74A5, 0xED6D, 0x74A6, 0xC0F5, 0x74A7, 0xC27A, 0x74A8, 0xC0F6, 0x74A9, 0xC0F3, 0x74AA, 0xED6A, + 0x74AB, 0xED68, 0x74AD, 0xED6B, 0x74AF, 0xED6E, 0x74B0, 0xC0F4, 0x74B1, 0xED6C, 0x74B2, 0xED67, 0x74B5, 0xF042, 0x74B6, 0xF045, + 0x74B7, 0xF275, 0x74B8, 0xF040, 0x74BA, 0xF46F, 0x74BB, 0xF046, 0x74BD, 0xC3A2, 0x74BE, 0xF044, 0x74BF, 0xC27B, 0x74C0, 0xF041, + 0x74C1, 0xF043, 0x74C2, 0xF047, 0x74C3, 0xF276, 0x74C5, 0xF274, 0x74CA, 0xC3A3, 0x74CB, 0xF273, 0x74CF, 0xC46E, 0x74D4, 0xC4ED, + 0x74D5, 0xF6F1, 0x74D6, 0xC4EC, 0x74D7, 0xF6F3, 0x74D8, 0xF6F0, 0x74D9, 0xF6F2, 0x74DA, 0xC5D0, 0x74DB, 0xF8B2, 0x74DC, 0xA5CA, + 0x74DD, 0xCD6E, 0x74DE, 0xD2BC, 0x74DF, 0xD2BD, 0x74E0, 0xB27D, 0x74E1, 0xDEBF, 0x74E2, 0xBF5D, 0x74E3, 0xC3A4, 0x74E4, 0xC57B, + 0x74E5, 0xF8B3, 0x74E6, 0xA5CB, 0x74E8, 0xCD6F, 0x74E9, 0xA260, 0x74EC, 0xCFD7, 0x74EE, 0xCFD8, 0x74F4, 0xD2BE, 0x74F5, 0xD2BF, + 0x74F6, 0xB27E, 0x74F7, 0xB2A1, 0x74FB, 0xDAAB, 0x74FD, 0xDEC2, 0x74FE, 0xDEC1, 0x74FF, 0xDEC0, 0x7500, 0xE2D5, 0x7502, 0xE2D6, + 0x7503, 0xE2D7, 0x7504, 0xBAC2, 0x7507, 0xE6AD, 0x7508, 0xE6AC, 0x750B, 0xEA69, 0x750C, 0xBF5E, 0x750D, 0xBF5F, 0x750F, 0xED72, + 0x7510, 0xED6F, 0x7511, 0xED70, 0x7512, 0xED71, 0x7513, 0xF049, 0x7514, 0xF048, 0x7515, 0xC27C, 0x7516, 0xF277, 0x7517, 0xF5DE, + 0x7518, 0xA5CC, 0x751A, 0xACC6, 0x751C, 0xB2A2, 0x751D, 0xDEC3, 0x751F, 0xA5CD, 0x7521, 0xD2C0, 0x7522, 0xB2A3, 0x7525, 0xB563, + 0x7526, 0xB564, 0x7528, 0xA5CE, 0x7529, 0xA5CF, 0x752A, 0xCA46, 0x752B, 0xA86A, 0x752C, 0xA869, 0x752D, 0xACC7, 0x752E, 0xCFD9, + 0x752F, 0xDAAC, 0x7530, 0xA5D0, 0x7531, 0xA5D1, 0x7532, 0xA5D2, 0x7533, 0xA5D3, 0x7537, 0xA86B, 0x7538, 0xA86C, 0x7539, 0xCB6E, + 0x753A, 0xCB6D, 0x753D, 0xAAB6, 0x753E, 0xCD72, 0x753F, 0xCD70, 0x7540, 0xCD71, 0x7547, 0xCFDA, 0x7548, 0xCFDB, 0x754B, 0xACCB, + 0x754C, 0xACC9, 0x754E, 0xACCA, 0x754F, 0xACC8, 0x7554, 0xAF60, 0x7559, 0xAF64, 0x755A, 0xAF63, 0x755B, 0xD2C1, 0x755C, 0xAF62, + 0x755D, 0xAF61, 0x755F, 0xD2C2, 0x7562, 0xB2A6, 0x7563, 0xD67B, 0x7564, 0xD67A, 0x7565, 0xB2A4, 0x7566, 0xB2A5, 0x756A, 0xB566, + 0x756B, 0xB565, 0x756C, 0xDAAE, 0x756F, 0xDAAD, 0x7570, 0xB2A7, 0x7576, 0xB7ED, 0x7577, 0xDEC5, 0x7578, 0xB7EE, 0x7579, 0xDEC4, + 0x757D, 0xE2D8, 0x757E, 0xE6AE, 0x757F, 0xBD42, 0x7580, 0xEA6A, 0x7584, 0xED73, 0x7586, 0xC3A6, 0x7587, 0xC3A5, 0x758A, 0xC57C, + 0x758B, 0xA5D4, 0x758C, 0xCD73, 0x758F, 0xB2A8, 0x7590, 0xE2D9, 0x7591, 0xBAC3, 0x7594, 0xCB6F, 0x7595, 0xCB70, 0x7598, 0xCD74, + 0x7599, 0xAAB8, 0x759A, 0xAAB9, 0x759D, 0xAAB7, 0x75A2, 0xACCF, 0x75A3, 0xACD0, 0x75A4, 0xACCD, 0x75A5, 0xACCE, 0x75A7, 0xCFDC, + 0x75AA, 0xCFDD, 0x75AB, 0xACCC, 0x75B0, 0xD2C3, 0x75B2, 0xAF68, 0x75B3, 0xAF69, 0x75B5, 0xB2AB, 0x75B6, 0xD2C9, 0x75B8, 0xAF6E, + 0x75B9, 0xAF6C, 0x75BA, 0xD2CA, 0x75BB, 0xD2C5, 0x75BC, 0xAF6B, 0x75BD, 0xAF6A, 0x75BE, 0xAF65, 0x75BF, 0xD2C8, 0x75C0, 0xD2C7, + 0x75C1, 0xD2C4, 0x75C2, 0xAF6D, 0x75C4, 0xD2C6, 0x75C5, 0xAF66, 0x75C7, 0xAF67, 0x75CA, 0xB2AC, 0x75CB, 0xD6A1, 0x75CC, 0xD6A2, + 0x75CD, 0xB2AD, 0x75CE, 0xD67C, 0x75CF, 0xD67E, 0x75D0, 0xD6A4, 0x75D1, 0xD6A3, 0x75D2, 0xD67D, 0x75D4, 0xB2A9, 0x75D5, 0xB2AA, + 0x75D7, 0xDAB6, 0x75D8, 0xB56B, 0x75D9, 0xB56A, 0x75DA, 0xDAB0, 0x75DB, 0xB568, 0x75DD, 0xDAB3, 0x75DE, 0xB56C, 0x75DF, 0xDAB4, + 0x75E0, 0xB56D, 0x75E1, 0xDAB1, 0x75E2, 0xB567, 0x75E3, 0xB569, 0x75E4, 0xDAB5, 0x75E6, 0xDAB2, 0x75E7, 0xDAAF, 0x75ED, 0xDED2, + 0x75EF, 0xDEC7, 0x75F0, 0xB7F0, 0x75F1, 0xB7F3, 0x75F2, 0xB7F2, 0x75F3, 0xB7F7, 0x75F4, 0xB7F6, 0x75F5, 0xDED3, 0x75F6, 0xDED1, + 0x75F7, 0xDECA, 0x75F8, 0xDECE, 0x75F9, 0xDECD, 0x75FA, 0xB7F4, 0x75FB, 0xDED0, 0x75FC, 0xDECC, 0x75FD, 0xDED4, 0x75FE, 0xDECB, + 0x75FF, 0xB7F5, 0x7600, 0xB7EF, 0x7601, 0xB7F1, 0x7603, 0xDEC9, 0x7608, 0xE2DB, 0x7609, 0xBAC7, 0x760A, 0xE2DF, 0x760B, 0xBAC6, + 0x760C, 0xE2DC, 0x760D, 0xBAC5, 0x760F, 0xDEC8, 0x7610, 0xDECF, 0x7611, 0xE2DE, 0x7613, 0xBAC8, 0x7614, 0xE2E0, 0x7615, 0xE2DD, + 0x7616, 0xE2DA, 0x7619, 0xE6B1, 0x761A, 0xE6B5, 0x761B, 0xE6B7, 0x761C, 0xE6B3, 0x761D, 0xE6B2, 0x761E, 0xE6B0, 0x761F, 0xBD45, + 0x7620, 0xBD43, 0x7621, 0xBD48, 0x7622, 0xBD49, 0x7623, 0xE6B4, 0x7624, 0xBD46, 0x7625, 0xE6AF, 0x7626, 0xBD47, 0x7627, 0xBAC4, + 0x7628, 0xE6B6, 0x7629, 0xBD44, 0x762D, 0xEA6C, 0x762F, 0xEA6B, 0x7630, 0xEA73, 0x7631, 0xEA6D, 0x7632, 0xEA72, 0x7633, 0xEA6F, + 0x7634, 0xBF60, 0x7635, 0xEA71, 0x7638, 0xBF61, 0x763A, 0xBF62, 0x763C, 0xEA70, 0x763D, 0xEA6E, 0x7642, 0xC0F8, 0x7643, 0xED74, + 0x7646, 0xC0F7, 0x7647, 0xED77, 0x7648, 0xED75, 0x7649, 0xED76, 0x764C, 0xC0F9, 0x7650, 0xF04D, 0x7652, 0xC2A1, 0x7653, 0xF04E, + 0x7656, 0xC27D, 0x7657, 0xF04F, 0x7658, 0xC27E, 0x7659, 0xF04C, 0x765A, 0xF050, 0x765C, 0xF04A, 0x765F, 0xC3A7, 0x7660, 0xF278, + 0x7661, 0xC3A8, 0x7662, 0xC46F, 0x7664, 0xF04B, 0x7665, 0xC470, 0x7669, 0xC4EE, 0x766A, 0xF5DF, 0x766C, 0xC57E, 0x766D, 0xF6F4, + 0x766E, 0xC57D, 0x7670, 0xF7EA, 0x7671, 0xC5F5, 0x7672, 0xC5F6, 0x7675, 0xF9CC, 0x7678, 0xACD1, 0x7679, 0xCFDE, 0x767B, 0xB56E, + 0x767C, 0xB56F, 0x767D, 0xA5D5, 0x767E, 0xA6CA, 0x767F, 0xCA47, 0x7681, 0xCB71, 0x7682, 0xA86D, 0x7684, 0xAABA, 0x7686, 0xACD2, + 0x7687, 0xACD3, 0x7688, 0xACD4, 0x7689, 0xD6A6, 0x768A, 0xD2CB, 0x768B, 0xAF6F, 0x768E, 0xB2AE, 0x768F, 0xD6A5, 0x7692, 0xDAB8, + 0x7693, 0xB571, 0x7695, 0xDAB7, 0x7696, 0xB570, 0x7699, 0xDED5, 0x769A, 0xBD4A, 0x769B, 0xE6BB, 0x769C, 0xE6B8, 0x769D, 0xE6B9, + 0x769E, 0xE6BA, 0x76A4, 0xED78, 0x76A6, 0xF051, 0x76AA, 0xF471, 0x76AB, 0xF470, 0x76AD, 0xF6F5, 0x76AE, 0xA5D6, 0x76AF, 0xCD75, + 0x76B0, 0xAF70, 0x76B4, 0xB572, 0x76B5, 0xDED6, 0x76B8, 0xE2E1, 0x76BA, 0xBD4B, 0x76BB, 0xEA74, 0x76BD, 0xF052, 0x76BE, 0xF472, + 0x76BF, 0xA5D7, 0x76C2, 0xAABB, 0x76C3, 0xACD7, 0x76C4, 0xCFDF, 0x76C5, 0xACD8, 0x76C6, 0xACD6, 0x76C8, 0xACD5, 0x76C9, 0xD2CC, + 0x76CA, 0xAF71, 0x76CD, 0xAF72, 0x76CE, 0xAF73, 0x76D2, 0xB2B0, 0x76D3, 0xD6A7, 0x76D4, 0xB2AF, 0x76DA, 0xDAB9, 0x76DB, 0xB2B1, + 0x76DC, 0xB573, 0x76DD, 0xDED7, 0x76DE, 0xB7F8, 0x76DF, 0xB7F9, 0x76E1, 0xBAC9, 0x76E3, 0xBACA, 0x76E4, 0xBD4C, 0x76E5, 0xBF64, + 0x76E6, 0xEA75, 0x76E7, 0xBF63, 0x76E9, 0xED79, 0x76EA, 0xC0FA, 0x76EC, 0xF053, 0x76ED, 0xF473, 0x76EE, 0xA5D8, 0x76EF, 0xA86E, + 0x76F0, 0xCD78, 0x76F1, 0xCD77, 0x76F2, 0xAABC, 0x76F3, 0xCD76, 0x76F4, 0xAABD, 0x76F5, 0xCD79, 0x76F7, 0xCFE5, 0x76F8, 0xACDB, + 0x76F9, 0xACDA, 0x76FA, 0xCFE7, 0x76FB, 0xCFE6, 0x76FC, 0xACDF, 0x76FE, 0xACDE, 0x7701, 0xACD9, 0x7703, 0xCFE1, 0x7704, 0xCFE2, + 0x7705, 0xCFE3, 0x7707, 0xACE0, 0x7708, 0xCFE0, 0x7709, 0xACDC, 0x770A, 0xCFE4, 0x770B, 0xACDD, 0x7710, 0xD2CF, 0x7711, 0xD2D3, + 0x7712, 0xD2D1, 0x7713, 0xD2D0, 0x7715, 0xD2D4, 0x7719, 0xD2D5, 0x771A, 0xD2D6, 0x771B, 0xD2CE, 0x771D, 0xD2CD, 0x771F, 0xAF75, + 0x7720, 0xAF76, 0x7722, 0xD2D7, 0x7723, 0xD2D2, 0x7725, 0xD6B0, 0x7727, 0xD2D8, 0x7728, 0xAF77, 0x7729, 0xAF74, 0x772D, 0xD6AA, + 0x772F, 0xD6A9, 0x7731, 0xD6AB, 0x7732, 0xD6AC, 0x7733, 0xD6AE, 0x7734, 0xD6AD, 0x7735, 0xD6B2, 0x7736, 0xB2B5, 0x7737, 0xB2B2, + 0x7738, 0xB2B6, 0x7739, 0xD6A8, 0x773A, 0xB2B7, 0x773B, 0xD6B1, 0x773C, 0xB2B4, 0x773D, 0xD6AF, 0x773E, 0xB2B3, 0x7744, 0xDABC, + 0x7745, 0xDABE, 0x7746, 0xDABA, 0x7747, 0xDABB, 0x774A, 0xDABF, 0x774B, 0xDAC1, 0x774C, 0xDAC2, 0x774D, 0xDABD, 0x774E, 0xDAC0, + 0x774F, 0xB574, 0x7752, 0xDEDB, 0x7754, 0xDEE0, 0x7755, 0xDED8, 0x7756, 0xDEDC, 0x7759, 0xDEE1, 0x775A, 0xDEDD, 0x775B, 0xB7FA, + 0x775C, 0xB843, 0x775E, 0xB7FD, 0x775F, 0xDED9, 0x7760, 0xDEDA, 0x7761, 0xBACE, 0x7762, 0xB846, 0x7763, 0xB7FE, 0x7765, 0xB844, + 0x7766, 0xB7FC, 0x7767, 0xDEDF, 0x7768, 0xB845, 0x7769, 0xDEDE, 0x776A, 0xB841, 0x776B, 0xB7FB, 0x776C, 0xB842, 0x776D, 0xDEE2, + 0x776E, 0xE2E6, 0x776F, 0xE2E8, 0x7779, 0xB840, 0x777C, 0xE2E3, 0x777D, 0xBACC, 0x777E, 0xE2E9, 0x777F, 0xBACD, 0x7780, 0xE2E7, + 0x7781, 0xE2E2, 0x7782, 0xE2E5, 0x7783, 0xE2EA, 0x7784, 0xBACB, 0x7785, 0xE2E4, 0x7787, 0xBD4E, 0x7788, 0xE6BF, 0x7789, 0xE6BE, + 0x778B, 0xBD51, 0x778C, 0xBD4F, 0x778D, 0xE6BC, 0x778E, 0xBD4D, 0x778F, 0xE6BD, 0x7791, 0xBD50, 0x7795, 0xEA7D, 0x7797, 0xEAA1, + 0x7799, 0xEA7E, 0x779A, 0xEA76, 0x779B, 0xEA7A, 0x779C, 0xEA79, 0x779D, 0xEA77, 0x779E, 0xBF66, 0x779F, 0xBF67, 0x77A0, 0xBF65, + 0x77A1, 0xEA78, 0x77A2, 0xEA7B, 0x77A3, 0xEA7C, 0x77A5, 0xBF68, 0x77A7, 0xC140, 0x77A8, 0xEDA3, 0x77AA, 0xC0FC, 0x77AB, 0xED7B, + 0x77AC, 0xC0FE, 0x77AD, 0xC141, 0x77B0, 0xC0FD, 0x77B1, 0xEDA2, 0x77B2, 0xED7C, 0x77B3, 0xC0FB, 0x77B4, 0xEDA1, 0x77B5, 0xED7A, + 0x77B6, 0xED7E, 0x77B7, 0xED7D, 0x77BA, 0xF055, 0x77BB, 0xC2A4, 0x77BC, 0xC2A5, 0x77BD, 0xC2A2, 0x77BF, 0xC2A3, 0x77C2, 0xF054, + 0x77C4, 0xF27B, 0x77C7, 0xC3A9, 0x77C9, 0xF279, 0x77CA, 0xF27A, 0x77CC, 0xF474, 0x77CD, 0xF477, 0x77CE, 0xF475, 0x77CF, 0xF476, + 0x77D0, 0xF5E0, 0x77D3, 0xC4EF, 0x77D4, 0xF7EB, 0x77D5, 0xF8B4, 0x77D7, 0xC5F7, 0x77D8, 0xF8F8, 0x77D9, 0xF8F9, 0x77DA, 0xC666, + 0x77DB, 0xA5D9, 0x77DC, 0xACE1, 0x77DE, 0xDAC3, 0x77E0, 0xDEE3, 0x77E2, 0xA5DA, 0x77E3, 0xA86F, 0x77E5, 0xAABE, 0x77E7, 0xCFE8, + 0x77E8, 0xCFE9, 0x77E9, 0xAF78, 0x77EC, 0xDAC4, 0x77ED, 0xB575, 0x77EE, 0xB847, 0x77EF, 0xC142, 0x77F0, 0xEDA4, 0x77F1, 0xF27C, + 0x77F2, 0xF478, 0x77F3, 0xA5DB, 0x77F7, 0xCDA1, 0x77F8, 0xCD7A, 0x77F9, 0xCD7C, 0x77FA, 0xCD7E, 0x77FB, 0xCD7D, 0x77FC, 0xCD7B, + 0x77FD, 0xAABF, 0x7802, 0xACE2, 0x7803, 0xCFF2, 0x7805, 0xCFED, 0x7806, 0xCFEA, 0x7809, 0xCFF1, 0x780C, 0xACE4, 0x780D, 0xACE5, + 0x780E, 0xCFF0, 0x780F, 0xCFEF, 0x7810, 0xCFEE, 0x7811, 0xCFEB, 0x7812, 0xCFEC, 0x7813, 0xCFF3, 0x7814, 0xACE3, 0x781D, 0xAF7C, + 0x781F, 0xAFA4, 0x7820, 0xAFA3, 0x7821, 0xD2E1, 0x7822, 0xD2DB, 0x7823, 0xD2D9, 0x7825, 0xAFA1, 0x7826, 0xD6B9, 0x7827, 0xAF7A, + 0x7828, 0xD2DE, 0x7829, 0xD2E2, 0x782A, 0xD2E4, 0x782B, 0xD2E0, 0x782C, 0xD2DA, 0x782D, 0xAFA2, 0x782E, 0xD2DF, 0x782F, 0xD2DD, + 0x7830, 0xAF79, 0x7831, 0xD2E5, 0x7832, 0xAFA5, 0x7833, 0xD2E3, 0x7834, 0xAF7D, 0x7835, 0xD2DC, 0x7837, 0xAF7E, 0x7838, 0xAF7B, + 0x7843, 0xB2B9, 0x7845, 0xD6BA, 0x7848, 0xD6B3, 0x7849, 0xD6B5, 0x784A, 0xD6B7, 0x784C, 0xD6B8, 0x784D, 0xD6B6, 0x784E, 0xB2BA, + 0x7850, 0xD6BB, 0x7852, 0xD6B4, 0x785C, 0xDAC8, 0x785D, 0xB576, 0x785E, 0xDAD0, 0x7860, 0xDAC5, 0x7862, 0xDAD1, 0x7864, 0xDAC6, + 0x7865, 0xDAC7, 0x7868, 0xDACF, 0x7869, 0xDACE, 0x786A, 0xDACB, 0x786B, 0xB2B8, 0x786C, 0xB577, 0x786D, 0xDAC9, 0x786E, 0xDACC, + 0x786F, 0xB578, 0x7870, 0xDACD, 0x7871, 0xDACA, 0x7879, 0xDEEE, 0x787B, 0xDEF2, 0x787C, 0xB84E, 0x787E, 0xE2F0, 0x787F, 0xB851, + 0x7880, 0xDEF0, 0x7881, 0xF9D6, 0x7883, 0xDEED, 0x7884, 0xDEE8, 0x7885, 0xDEEA, 0x7886, 0xDEEB, 0x7887, 0xDEE4, 0x7889, 0xB84D, + 0x788C, 0xB84C, 0x788E, 0xB848, 0x788F, 0xDEE7, 0x7891, 0xB84F, 0x7893, 0xB850, 0x7894, 0xDEE6, 0x7895, 0xDEE9, 0x7896, 0xDEF1, + 0x7897, 0xB84A, 0x7898, 0xB84B, 0x7899, 0xDEEF, 0x789A, 0xDEE5, 0x789E, 0xE2F2, 0x789F, 0xBAD0, 0x78A0, 0xE2F4, 0x78A1, 0xDEEC, + 0x78A2, 0xE2F6, 0x78A3, 0xBAD4, 0x78A4, 0xE2F7, 0x78A5, 0xE2F3, 0x78A7, 0xBAD1, 0x78A8, 0xE2EF, 0x78A9, 0xBAD3, 0x78AA, 0xE2EC, + 0x78AB, 0xE2F1, 0x78AC, 0xE2F5, 0x78AD, 0xE2EE, 0x78B0, 0xB849, 0x78B2, 0xE2EB, 0x78B3, 0xBAD2, 0x78B4, 0xE2ED, 0x78BA, 0xBD54, + 0x78BB, 0xE6C1, 0x78BC, 0xBD58, 0x78BE, 0xBD56, 0x78C1, 0xBACF, 0x78C3, 0xE6C8, 0x78C4, 0xE6C9, 0x78C5, 0xBD53, 0x78C8, 0xE6C7, + 0x78C9, 0xE6CA, 0x78CA, 0xBD55, 0x78CB, 0xBD52, 0x78CC, 0xE6C3, 0x78CD, 0xE6C0, 0x78CE, 0xE6C5, 0x78CF, 0xE6C2, 0x78D0, 0xBD59, + 0x78D1, 0xE6C4, 0x78D4, 0xE6C6, 0x78D5, 0xBD57, 0x78DA, 0xBF6A, 0x78DB, 0xEAA8, 0x78DD, 0xEAA2, 0x78DE, 0xEAA6, 0x78DF, 0xEAAC, + 0x78E0, 0xEAAD, 0x78E1, 0xEAA9, 0x78E2, 0xEAAA, 0x78E3, 0xEAA7, 0x78E5, 0xEAA4, 0x78E7, 0xBF6C, 0x78E8, 0xBF69, 0x78E9, 0xEAA3, + 0x78EA, 0xEAA5, 0x78EC, 0xBF6B, 0x78ED, 0xEAAB, 0x78EF, 0xC146, 0x78F2, 0xEDAA, 0x78F3, 0xEDA5, 0x78F4, 0xC145, 0x78F7, 0xC143, + 0x78F9, 0xEDAC, 0x78FA, 0xC144, 0x78FB, 0xEDA8, 0x78FC, 0xEDA9, 0x78FD, 0xEDA6, 0x78FE, 0xEDAD, 0x78FF, 0xF056, 0x7901, 0xC147, + 0x7902, 0xEDA7, 0x7904, 0xEDAE, 0x7905, 0xEDAB, 0x7909, 0xF05A, 0x790C, 0xF057, 0x790E, 0xC2A6, 0x7910, 0xF05B, 0x7911, 0xF05D, + 0x7912, 0xF05C, 0x7913, 0xF058, 0x7914, 0xF059, 0x7917, 0xF2A3, 0x7919, 0xC3AA, 0x791B, 0xF27E, 0x791C, 0xF2A2, 0x791D, 0xF27D, + 0x791E, 0xF2A4, 0x7921, 0xF2A1, 0x7923, 0xF47A, 0x7924, 0xF47D, 0x7925, 0xF479, 0x7926, 0xC471, 0x7927, 0xF47B, 0x7928, 0xF47C, + 0x7929, 0xF47E, 0x792A, 0xC472, 0x792B, 0xC474, 0x792C, 0xC473, 0x792D, 0xF5E1, 0x792F, 0xF5E3, 0x7931, 0xF5E2, 0x7935, 0xF6F6, + 0x7938, 0xF8B5, 0x7939, 0xF8FA, 0x793A, 0xA5DC, 0x793D, 0xCB72, 0x793E, 0xAAC0, 0x793F, 0xCDA3, 0x7940, 0xAAC1, 0x7941, 0xAAC2, + 0x7942, 0xCDA2, 0x7944, 0xCFF8, 0x7945, 0xCFF7, 0x7946, 0xACE6, 0x7947, 0xACE9, 0x7948, 0xACE8, 0x7949, 0xACE7, 0x794A, 0xCFF4, + 0x794B, 0xCFF6, 0x794C, 0xCFF5, 0x794F, 0xD2E8, 0x7950, 0xAFA7, 0x7951, 0xD2EC, 0x7952, 0xD2EB, 0x7953, 0xD2EA, 0x7954, 0xD2E6, + 0x7955, 0xAFA6, 0x7956, 0xAFAA, 0x7957, 0xAFAD, 0x795A, 0xAFAE, 0x795B, 0xD2E7, 0x795C, 0xD2E9, 0x795D, 0xAFAC, 0x795E, 0xAFAB, + 0x795F, 0xAFA9, 0x7960, 0xAFA8, 0x7961, 0xD6C2, 0x7963, 0xD6C0, 0x7964, 0xD6BC, 0x7965, 0xB2BB, 0x7967, 0xD6BD, 0x7968, 0xB2BC, + 0x7969, 0xD6BE, 0x796A, 0xD6BF, 0x796B, 0xD6C1, 0x796D, 0xB2BD, 0x7970, 0xDAD5, 0x7972, 0xDAD4, 0x7973, 0xDAD3, 0x7974, 0xDAD2, + 0x7979, 0xDEF6, 0x797A, 0xB852, 0x797C, 0xDEF3, 0x797D, 0xDEF5, 0x797F, 0xB853, 0x7981, 0xB854, 0x7982, 0xDEF4, 0x7988, 0xE341, + 0x798A, 0xE2F9, 0x798B, 0xE2FA, 0x798D, 0xBAD7, 0x798E, 0xBAD5, 0x798F, 0xBAD6, 0x7990, 0xE343, 0x7992, 0xE342, 0x7993, 0xE2FE, + 0x7994, 0xE2FD, 0x7995, 0xE2FC, 0x7996, 0xE2FB, 0x7997, 0xE340, 0x7998, 0xE2F8, 0x799A, 0xE6CB, 0x799B, 0xE6D0, 0x799C, 0xE6CE, + 0x79A0, 0xE6CD, 0x79A1, 0xE6CC, 0x79A2, 0xE6CF, 0x79A4, 0xEAAE, 0x79A6, 0xBF6D, 0x79A7, 0xC148, 0x79A8, 0xEDB0, 0x79AA, 0xC149, + 0x79AB, 0xEDAF, 0x79AC, 0xF05F, 0x79AD, 0xF05E, 0x79AE, 0xC2A7, 0x79B0, 0xF2A5, 0x79B1, 0xC3AB, 0x79B2, 0xF4A1, 0x79B3, 0xC5A1, + 0x79B4, 0xF6F7, 0x79B6, 0xF8B7, 0x79B7, 0xF8B6, 0x79B8, 0xC9A8, 0x79B9, 0xACEA, 0x79BA, 0xACEB, 0x79BB, 0xD6C3, 0x79BD, 0xB856, + 0x79BE, 0xA5DD, 0x79BF, 0xA872, 0x79C0, 0xA871, 0x79C1, 0xA870, 0x79C5, 0xCDA4, 0x79C8, 0xAAC4, 0x79C9, 0xAAC3, 0x79CB, 0xACEE, + 0x79CD, 0xCFFA, 0x79CE, 0xCFFD, 0x79CF, 0xCFFB, 0x79D1, 0xACEC, 0x79D2, 0xACED, 0x79D5, 0xCFF9, 0x79D6, 0xCFFC, 0x79D8, 0xAFB5, + 0x79DC, 0xD2F3, 0x79DD, 0xD2F5, 0x79DE, 0xD2F4, 0x79DF, 0xAFB2, 0x79E0, 0xD2EF, 0x79E3, 0xAFB0, 0x79E4, 0xAFAF, 0x79E6, 0xAFB3, + 0x79E7, 0xAFB1, 0x79E9, 0xAFB4, 0x79EA, 0xD2F2, 0x79EB, 0xD2ED, 0x79EC, 0xD2EE, 0x79ED, 0xD2F1, 0x79EE, 0xD2F0, 0x79F6, 0xD6C6, + 0x79F7, 0xD6C7, 0x79F8, 0xD6C5, 0x79FA, 0xD6C4, 0x79FB, 0xB2BE, 0x7A00, 0xB57D, 0x7A02, 0xDAD6, 0x7A03, 0xDAD8, 0x7A04, 0xDADA, + 0x7A05, 0xB57C, 0x7A08, 0xB57A, 0x7A0A, 0xDAD7, 0x7A0B, 0xB57B, 0x7A0C, 0xDAD9, 0x7A0D, 0xB579, 0x7A10, 0xDF41, 0x7A11, 0xDEF7, + 0x7A12, 0xDEFA, 0x7A13, 0xDEFE, 0x7A14, 0xB85A, 0x7A15, 0xDEFC, 0x7A17, 0xDEFB, 0x7A18, 0xDEF8, 0x7A19, 0xDEF9, 0x7A1A, 0xB858, + 0x7A1B, 0xDF40, 0x7A1C, 0xB857, 0x7A1E, 0xB85C, 0x7A1F, 0xB85B, 0x7A20, 0xB859, 0x7A22, 0xDEFD, 0x7A26, 0xE349, 0x7A28, 0xE348, + 0x7A2B, 0xE344, 0x7A2E, 0xBAD8, 0x7A2F, 0xE347, 0x7A30, 0xE346, 0x7A31, 0xBAD9, 0x7A37, 0xBD5E, 0x7A39, 0xE6D2, 0x7A3B, 0xBD5F, + 0x7A3C, 0xBD5B, 0x7A3D, 0xBD5D, 0x7A3F, 0xBD5A, 0x7A40, 0xBD5C, 0x7A44, 0xEAAF, 0x7A46, 0xBF70, 0x7A47, 0xEAB1, 0x7A48, 0xEAB0, + 0x7A4A, 0xE345, 0x7A4B, 0xBF72, 0x7A4C, 0xBF71, 0x7A4D, 0xBF6E, 0x7A4E, 0xBF6F, 0x7A54, 0xEDB5, 0x7A56, 0xEDB3, 0x7A57, 0xC14A, + 0x7A58, 0xEDB4, 0x7A5A, 0xEDB6, 0x7A5B, 0xEDB2, 0x7A5C, 0xEDB1, 0x7A5F, 0xF060, 0x7A60, 0xC2AA, 0x7A61, 0xC2A8, 0x7A62, 0xC2A9, + 0x7A67, 0xF2A6, 0x7A68, 0xF2A7, 0x7A69, 0xC3AD, 0x7A6B, 0xC3AC, 0x7A6C, 0xF4A3, 0x7A6D, 0xF4A4, 0x7A6E, 0xF4A2, 0x7A70, 0xF6F8, + 0x7A71, 0xF6F9, 0x7A74, 0xA5DE, 0x7A75, 0xCA48, 0x7A76, 0xA873, 0x7A78, 0xCDA5, 0x7A79, 0xAAC6, 0x7A7A, 0xAAC5, 0x7A7B, 0xCDA6, + 0x7A7E, 0xD040, 0x7A7F, 0xACEF, 0x7A80, 0xCFFE, 0x7A81, 0xACF0, 0x7A84, 0xAFB6, 0x7A85, 0xD2F8, 0x7A86, 0xD2F6, 0x7A87, 0xD2FC, + 0x7A88, 0xAFB7, 0x7A89, 0xD2F7, 0x7A8A, 0xD2FB, 0x7A8B, 0xD2F9, 0x7A8C, 0xD2FA, 0x7A8F, 0xD6C8, 0x7A90, 0xD6CA, 0x7A92, 0xB2BF, + 0x7A94, 0xD6C9, 0x7A95, 0xB2C0, 0x7A96, 0xB5A2, 0x7A97, 0xB5A1, 0x7A98, 0xB57E, 0x7A99, 0xDADB, 0x7A9E, 0xDF44, 0x7A9F, 0xB85D, + 0x7AA0, 0xB85E, 0x7AA2, 0xDF43, 0x7AA3, 0xDF42, 0x7AA8, 0xE34A, 0x7AA9, 0xBADB, 0x7AAA, 0xBADA, 0x7AAB, 0xE34B, 0x7AAC, 0xE34C, + 0x7AAE, 0xBD61, 0x7AAF, 0xBD60, 0x7AB1, 0xEAB5, 0x7AB2, 0xE6D3, 0x7AB3, 0xE6D5, 0x7AB4, 0xE6D4, 0x7AB5, 0xEAB4, 0x7AB6, 0xEAB2, + 0x7AB7, 0xEAB6, 0x7AB8, 0xEAB3, 0x7ABA, 0xBF73, 0x7ABE, 0xEDB7, 0x7ABF, 0xC14B, 0x7AC0, 0xEDB8, 0x7AC1, 0xEDB9, 0x7AC4, 0xC2AB, + 0x7AC5, 0xC2AC, 0x7AC7, 0xC475, 0x7ACA, 0xC5D1, 0x7ACB, 0xA5DF, 0x7AD1, 0xD041, 0x7AD8, 0xD2FD, 0x7AD9, 0xAFB8, 0x7ADF, 0xB3BA, + 0x7AE0, 0xB3B9, 0x7AE3, 0xB5A4, 0x7AE4, 0xDADD, 0x7AE5, 0xB5A3, 0x7AE6, 0xDADC, 0x7AEB, 0xDF45, 0x7AED, 0xBADC, 0x7AEE, 0xE34D, + 0x7AEF, 0xBADD, 0x7AF6, 0xC476, 0x7AF7, 0xF4A5, 0x7AF9, 0xA6CB, 0x7AFA, 0xAAC7, 0x7AFB, 0xCDA7, 0x7AFD, 0xACF2, 0x7AFF, 0xACF1, + 0x7B00, 0xD042, 0x7B01, 0xD043, 0x7B04, 0xD340, 0x7B05, 0xD342, 0x7B06, 0xAFB9, 0x7B08, 0xD344, 0x7B09, 0xD347, 0x7B0A, 0xD345, + 0x7B0E, 0xD346, 0x7B0F, 0xD343, 0x7B10, 0xD2FE, 0x7B11, 0xAFBA, 0x7B12, 0xD348, 0x7B13, 0xD341, 0x7B18, 0xD6D3, 0x7B19, 0xB2C6, + 0x7B1A, 0xD6DC, 0x7B1B, 0xB2C3, 0x7B1D, 0xD6D5, 0x7B1E, 0xB2C7, 0x7B20, 0xB2C1, 0x7B22, 0xD6D0, 0x7B23, 0xD6DD, 0x7B24, 0xD6D1, + 0x7B25, 0xD6CE, 0x7B26, 0xB2C5, 0x7B28, 0xB2C2, 0x7B2A, 0xD6D4, 0x7B2B, 0xD6D7, 0x7B2C, 0xB2C4, 0x7B2D, 0xD6D8, 0x7B2E, 0xB2C8, + 0x7B2F, 0xD6D9, 0x7B30, 0xD6CF, 0x7B31, 0xD6D6, 0x7B32, 0xD6DA, 0x7B33, 0xD6D2, 0x7B34, 0xD6CD, 0x7B35, 0xD6CB, 0x7B38, 0xD6DB, + 0x7B3B, 0xDADF, 0x7B40, 0xDAE4, 0x7B44, 0xDAE0, 0x7B45, 0xDAE6, 0x7B46, 0xB5A7, 0x7B47, 0xD6CC, 0x7B48, 0xDAE1, 0x7B49, 0xB5A5, + 0x7B4A, 0xDADE, 0x7B4B, 0xB5AC, 0x7B4C, 0xDAE2, 0x7B4D, 0xB5AB, 0x7B4E, 0xDAE3, 0x7B4F, 0xB5AD, 0x7B50, 0xB5A8, 0x7B51, 0xB5AE, + 0x7B52, 0xB5A9, 0x7B54, 0xB5AA, 0x7B56, 0xB5A6, 0x7B58, 0xDAE5, 0x7B60, 0xB861, 0x7B61, 0xDF50, 0x7B63, 0xDF53, 0x7B64, 0xDF47, + 0x7B65, 0xDF4C, 0x7B66, 0xDF46, 0x7B67, 0xB863, 0x7B69, 0xDF4A, 0x7B6D, 0xDF48, 0x7B6E, 0xB862, 0x7B70, 0xDF4F, 0x7B71, 0xDF4E, + 0x7B72, 0xDF4B, 0x7B73, 0xDF4D, 0x7B74, 0xDF49, 0x7B75, 0xBAE1, 0x7B76, 0xDF52, 0x7B77, 0xB85F, 0x7B78, 0xDF51, 0x7B82, 0xE35D, + 0x7B84, 0xBAE8, 0x7B85, 0xE358, 0x7B87, 0xBAE7, 0x7B88, 0xE34E, 0x7B8A, 0xE350, 0x7B8B, 0xBAE0, 0x7B8C, 0xE355, 0x7B8D, 0xE354, + 0x7B8E, 0xE357, 0x7B8F, 0xBAE5, 0x7B90, 0xE352, 0x7B91, 0xE351, 0x7B94, 0xBAE4, 0x7B95, 0xBADF, 0x7B96, 0xE353, 0x7B97, 0xBAE2, + 0x7B98, 0xE359, 0x7B99, 0xE35B, 0x7B9B, 0xE356, 0x7B9C, 0xE34F, 0x7B9D, 0xBAE3, 0x7BA0, 0xBD69, 0x7BA1, 0xBADE, 0x7BA4, 0xE35C, + 0x7BAC, 0xE6D9, 0x7BAD, 0xBD62, 0x7BAF, 0xE6DB, 0x7BB1, 0xBD63, 0x7BB4, 0xBD65, 0x7BB5, 0xE6DE, 0x7BB7, 0xE6D6, 0x7BB8, 0xBAE6, + 0x7BB9, 0xE6DC, 0x7BBE, 0xE6D8, 0x7BC0, 0xB860, 0x7BC1, 0xBD68, 0x7BC4, 0xBD64, 0x7BC6, 0xBD66, 0x7BC7, 0xBD67, 0x7BC9, 0xBF76, + 0x7BCA, 0xE6DD, 0x7BCB, 0xE6D7, 0x7BCC, 0xBD6A, 0x7BCE, 0xE6DA, 0x7BD4, 0xEAC0, 0x7BD5, 0xEABB, 0x7BD8, 0xEAC5, 0x7BD9, 0xBF74, + 0x7BDA, 0xEABD, 0x7BDB, 0xBF78, 0x7BDC, 0xEAC3, 0x7BDD, 0xEABA, 0x7BDE, 0xEAB7, 0x7BDF, 0xEAC6, 0x7BE0, 0xC151, 0x7BE1, 0xBF79, + 0x7BE2, 0xEAC2, 0x7BE3, 0xEAB8, 0x7BE4, 0xBF77, 0x7BE5, 0xEABC, 0x7BE6, 0xBF7B, 0x7BE7, 0xEAB9, 0x7BE8, 0xEABE, 0x7BE9, 0xBF7A, + 0x7BEA, 0xEAC1, 0x7BEB, 0xEAC4, 0x7BF0, 0xEDCB, 0x7BF1, 0xEDCC, 0x7BF2, 0xEDBC, 0x7BF3, 0xEDC3, 0x7BF4, 0xEDC1, 0x7BF7, 0xC14F, + 0x7BF8, 0xEDC8, 0x7BF9, 0xEABF, 0x7BFB, 0xEDBF, 0x7BFD, 0xEDC9, 0x7BFE, 0xC14E, 0x7BFF, 0xEDBE, 0x7C00, 0xEDBD, 0x7C01, 0xEDC7, + 0x7C02, 0xEDC4, 0x7C03, 0xEDC6, 0x7C05, 0xEDBA, 0x7C06, 0xEDCA, 0x7C07, 0xC14C, 0x7C09, 0xEDC5, 0x7C0A, 0xEDCE, 0x7C0B, 0xEDC2, + 0x7C0C, 0xC150, 0x7C0D, 0xC14D, 0x7C0E, 0xEDC0, 0x7C0F, 0xEDBB, 0x7C10, 0xEDCD, 0x7C11, 0xBF75, 0x7C19, 0xF063, 0x7C1C, 0xF061, + 0x7C1D, 0xF067, 0x7C1E, 0xC2B0, 0x7C1F, 0xF065, 0x7C20, 0xF064, 0x7C21, 0xC2B2, 0x7C22, 0xF06A, 0x7C23, 0xC2B1, 0x7C25, 0xF06B, + 0x7C26, 0xF068, 0x7C27, 0xC2AE, 0x7C28, 0xF069, 0x7C29, 0xF062, 0x7C2A, 0xC2AF, 0x7C2B, 0xC2AD, 0x7C2C, 0xF2AB, 0x7C2D, 0xF066, + 0x7C30, 0xF06C, 0x7C33, 0xF2A8, 0x7C37, 0xC3B2, 0x7C38, 0xC3B0, 0x7C39, 0xF2AA, 0x7C3B, 0xF2AC, 0x7C3C, 0xF2A9, 0x7C3D, 0xC3B1, + 0x7C3E, 0xC3AE, 0x7C3F, 0xC3AF, 0x7C40, 0xC3B3, 0x7C43, 0xC478, 0x7C45, 0xF4AA, 0x7C47, 0xF4A9, 0x7C48, 0xF4A7, 0x7C49, 0xF4A6, + 0x7C4A, 0xF4A8, 0x7C4C, 0xC477, 0x7C4D, 0xC479, 0x7C50, 0xC4F0, 0x7C53, 0xF5E5, 0x7C54, 0xF5E4, 0x7C57, 0xF6FA, 0x7C59, 0xF6FC, + 0x7C5A, 0xF6FE, 0x7C5B, 0xF6FD, 0x7C5C, 0xF6FB, 0x7C5F, 0xC5A3, 0x7C60, 0xC5A2, 0x7C63, 0xC5D3, 0x7C64, 0xC5D2, 0x7C65, 0xC5D4, + 0x7C66, 0xF7ED, 0x7C67, 0xF7EC, 0x7C69, 0xF8FB, 0x7C6A, 0xF8B8, 0x7C6B, 0xF8FC, 0x7C6C, 0xC658, 0x7C6E, 0xC659, 0x7C6F, 0xF96D, + 0x7C72, 0xC67E, 0x7C73, 0xA6CC, 0x7C75, 0xCDA8, 0x7C78, 0xD045, 0x7C79, 0xD046, 0x7C7A, 0xD044, 0x7C7D, 0xACF3, 0x7C7F, 0xD047, + 0x7C80, 0xD048, 0x7C81, 0xD049, 0x7C84, 0xD349, 0x7C85, 0xD34F, 0x7C88, 0xD34D, 0x7C89, 0xAFBB, 0x7C8A, 0xD34B, 0x7C8C, 0xD34C, + 0x7C8D, 0xD34E, 0x7C91, 0xD34A, 0x7C92, 0xB2C9, 0x7C94, 0xD6DE, 0x7C95, 0xB2CB, 0x7C96, 0xD6E0, 0x7C97, 0xB2CA, 0x7C98, 0xD6DF, + 0x7C9E, 0xDAE8, 0x7C9F, 0xB5AF, 0x7CA1, 0xDAEA, 0x7CA2, 0xDAE7, 0x7CA3, 0xD6E1, 0x7CA5, 0xB5B0, 0x7CA7, 0xF9DB, 0x7CA8, 0xDAE9, + 0x7CAF, 0xDF56, 0x7CB1, 0xB864, 0x7CB2, 0xDF54, 0x7CB3, 0xB865, 0x7CB4, 0xDF55, 0x7CB5, 0xB866, 0x7CB9, 0xBAE9, 0x7CBA, 0xE361, + 0x7CBB, 0xE35E, 0x7CBC, 0xE360, 0x7CBD, 0xBAEA, 0x7CBE, 0xBAEB, 0x7CBF, 0xE35F, 0x7CC5, 0xE6DF, 0x7CC8, 0xE6E0, 0x7CCA, 0xBD6B, + 0x7CCB, 0xE6E2, 0x7CCC, 0xE6E1, 0x7CCE, 0xA261, 0x7CD0, 0xEACA, 0x7CD1, 0xEACB, 0x7CD2, 0xEAC7, 0x7CD4, 0xEAC8, 0x7CD5, 0xBF7C, + 0x7CD6, 0xBF7D, 0x7CD7, 0xEAC9, 0x7CD9, 0xC157, 0x7CDC, 0xC153, 0x7CDD, 0xC158, 0x7CDE, 0xC154, 0x7CDF, 0xC156, 0x7CE0, 0xC152, + 0x7CE2, 0xC155, 0x7CE7, 0xC2B3, 0x7CE8, 0xEDCF, 0x7CEA, 0xF2AE, 0x7CEC, 0xF2AD, 0x7CEE, 0xF4AB, 0x7CEF, 0xC47A, 0x7CF0, 0xC47B, + 0x7CF1, 0xF741, 0x7CF2, 0xF5E6, 0x7CF4, 0xF740, 0x7CF6, 0xF8FD, 0x7CF7, 0xF9A4, 0x7CF8, 0xA6CD, 0x7CFB, 0xA874, 0x7CFD, 0xCDA9, + 0x7CFE, 0xAAC8, 0x7D00, 0xACF6, 0x7D01, 0xD04C, 0x7D02, 0xACF4, 0x7D03, 0xD04A, 0x7D04, 0xACF9, 0x7D05, 0xACF5, 0x7D06, 0xACFA, + 0x7D07, 0xACF8, 0x7D08, 0xD04B, 0x7D09, 0xACF7, 0x7D0A, 0xAFBF, 0x7D0B, 0xAFBE, 0x7D0C, 0xD35A, 0x7D0D, 0xAFC7, 0x7D0E, 0xD353, + 0x7D0F, 0xD359, 0x7D10, 0xAFC3, 0x7D11, 0xD352, 0x7D12, 0xD358, 0x7D13, 0xD356, 0x7D14, 0xAFC2, 0x7D15, 0xAFC4, 0x7D16, 0xD355, + 0x7D17, 0xAFBD, 0x7D18, 0xD354, 0x7D19, 0xAFC8, 0x7D1A, 0xAFC5, 0x7D1B, 0xAFC9, 0x7D1C, 0xAFC6, 0x7D1D, 0xD351, 0x7D1E, 0xD350, + 0x7D1F, 0xD357, 0x7D20, 0xAFC0, 0x7D21, 0xAFBC, 0x7D22, 0xAFC1, 0x7D28, 0xD6F0, 0x7D29, 0xD6E9, 0x7D2B, 0xB5B5, 0x7D2C, 0xD6E8, + 0x7D2E, 0xB2CF, 0x7D2F, 0xB2D6, 0x7D30, 0xB2D3, 0x7D31, 0xB2D9, 0x7D32, 0xB2D8, 0x7D33, 0xB2D4, 0x7D35, 0xD6E2, 0x7D36, 0xD6E5, + 0x7D38, 0xD6E4, 0x7D39, 0xB2D0, 0x7D3A, 0xD6E6, 0x7D3B, 0xD6EF, 0x7D3C, 0xB2D1, 0x7D3D, 0xD6E3, 0x7D3E, 0xD6EC, 0x7D3F, 0xD6ED, + 0x7D40, 0xB2D2, 0x7D41, 0xD6EA, 0x7D42, 0xB2D7, 0x7D43, 0xB2CD, 0x7D44, 0xB2D5, 0x7D45, 0xD6E7, 0x7D46, 0xB2CC, 0x7D47, 0xD6EB, + 0x7D4A, 0xD6EE, 0x7D4E, 0xDAFB, 0x7D4F, 0xDAF2, 0x7D50, 0xB5B2, 0x7D51, 0xDAF9, 0x7D52, 0xDAF6, 0x7D53, 0xDAEE, 0x7D54, 0xDAF7, + 0x7D55, 0xB5B4, 0x7D56, 0xDAEF, 0x7D58, 0xDAEB, 0x7D5B, 0xB86C, 0x7D5C, 0xDAF4, 0x7D5E, 0xB5B1, 0x7D5F, 0xDAFA, 0x7D61, 0xB5B8, + 0x7D62, 0xB5BA, 0x7D63, 0xDAED, 0x7D66, 0xB5B9, 0x7D67, 0xDAF0, 0x7D68, 0xB5B3, 0x7D69, 0xDAF8, 0x7D6A, 0xDAF1, 0x7D6B, 0xDAF5, + 0x7D6D, 0xDAF3, 0x7D6E, 0xB5B6, 0x7D6F, 0xDAEC, 0x7D70, 0xB5BB, 0x7D71, 0xB2CE, 0x7D72, 0xB5B7, 0x7D73, 0xB5BC, 0x7D79, 0xB868, + 0x7D7A, 0xDF5D, 0x7D7B, 0xDF5F, 0x7D7C, 0xDF61, 0x7D7D, 0xDF65, 0x7D7F, 0xDF5B, 0x7D80, 0xDF59, 0x7D81, 0xB86A, 0x7D83, 0xDF60, + 0x7D84, 0xDF64, 0x7D85, 0xDF5C, 0x7D86, 0xDF58, 0x7D88, 0xDF57, 0x7D8C, 0xDF62, 0x7D8D, 0xDF5A, 0x7D8E, 0xDF5E, 0x7D8F, 0xB86B, + 0x7D91, 0xB869, 0x7D92, 0xDF66, 0x7D93, 0xB867, 0x7D94, 0xDF63, 0x7D96, 0xE372, 0x7D9C, 0xBAEE, 0x7D9D, 0xE36A, 0x7D9E, 0xBD78, + 0x7D9F, 0xE374, 0x7DA0, 0xBAF1, 0x7DA1, 0xE378, 0x7DA2, 0xBAF7, 0x7DA3, 0xE365, 0x7DA6, 0xE375, 0x7DA7, 0xE362, 0x7DA9, 0xE377, + 0x7DAA, 0xE366, 0x7DAC, 0xBAFE, 0x7DAD, 0xBAFB, 0x7DAE, 0xE376, 0x7DAF, 0xE370, 0x7DB0, 0xBAED, 0x7DB1, 0xBAF5, 0x7DB2, 0xBAF4, + 0x7DB4, 0xBAF3, 0x7DB5, 0xBAF9, 0x7DB7, 0xE363, 0x7DB8, 0xBAFA, 0x7DB9, 0xE371, 0x7DBA, 0xBAF6, 0x7DBB, 0xBAEC, 0x7DBC, 0xE373, + 0x7DBD, 0xBAEF, 0x7DBE, 0xBAF0, 0x7DBF, 0xBAF8, 0x7DC0, 0xE368, 0x7DC1, 0xE367, 0x7DC2, 0xE364, 0x7DC4, 0xE36C, 0x7DC5, 0xE369, + 0x7DC6, 0xE36D, 0x7DC7, 0xBAFD, 0x7DC9, 0xE379, 0x7DCA, 0xBAF2, 0x7DCB, 0xE36E, 0x7DCC, 0xE36F, 0x7DCE, 0xE36B, 0x7DD2, 0xBAFC, + 0x7DD7, 0xE6E7, 0x7DD8, 0xBD70, 0x7DD9, 0xBD79, 0x7DDA, 0xBD75, 0x7DDB, 0xE6E4, 0x7DDD, 0xBD72, 0x7DDE, 0xBD76, 0x7DDF, 0xE6F0, + 0x7DE0, 0xBD6C, 0x7DE1, 0xE6E8, 0x7DE3, 0xBD74, 0x7DE6, 0xE6EB, 0x7DE7, 0xE6E6, 0x7DE8, 0xBD73, 0x7DE9, 0xBD77, 0x7DEA, 0xE6E5, + 0x7DEC, 0xBD71, 0x7DEE, 0xE6EF, 0x7DEF, 0xBD6E, 0x7DF0, 0xE6EE, 0x7DF1, 0xE6ED, 0x7DF2, 0xBD7A, 0x7DF3, 0xE572, 0x7DF4, 0xBD6D, + 0x7DF6, 0xE6EC, 0x7DF7, 0xE6E3, 0x7DF9, 0xBD7B, 0x7DFA, 0xE6EA, 0x7DFB, 0xBD6F, 0x7E03, 0xE6E9, 0x7E08, 0xBFA2, 0x7E09, 0xBFA7, + 0x7E0A, 0xBF7E, 0x7E0B, 0xEAD8, 0x7E0C, 0xEACF, 0x7E0D, 0xEADB, 0x7E0E, 0xEAD3, 0x7E0F, 0xEAD9, 0x7E10, 0xBFA8, 0x7E11, 0xBFA1, + 0x7E12, 0xEACC, 0x7E13, 0xEAD2, 0x7E14, 0xEADC, 0x7E15, 0xEAD5, 0x7E16, 0xEADA, 0x7E17, 0xEACE, 0x7E1A, 0xEAD6, 0x7E1B, 0xBFA3, + 0x7E1C, 0xEAD4, 0x7E1D, 0xBFA6, 0x7E1E, 0xBFA5, 0x7E1F, 0xEAD0, 0x7E20, 0xEAD1, 0x7E21, 0xEACD, 0x7E22, 0xEAD7, 0x7E23, 0xBFA4, + 0x7E24, 0xEADE, 0x7E25, 0xEADD, 0x7E29, 0xEDDA, 0x7E2A, 0xEDD6, 0x7E2B, 0xC15F, 0x7E2D, 0xEDD0, 0x7E2E, 0xC159, 0x7E2F, 0xC169, + 0x7E30, 0xEDDC, 0x7E31, 0xC161, 0x7E32, 0xC15D, 0x7E33, 0xEDD3, 0x7E34, 0xC164, 0x7E35, 0xC167, 0x7E36, 0xEDDE, 0x7E37, 0xC15C, + 0x7E38, 0xEDD5, 0x7E39, 0xC165, 0x7E3A, 0xEDE0, 0x7E3B, 0xEDDD, 0x7E3C, 0xEDD1, 0x7E3D, 0xC160, 0x7E3E, 0xC15A, 0x7E3F, 0xC168, + 0x7E40, 0xEDD8, 0x7E41, 0xC163, 0x7E42, 0xEDD2, 0x7E43, 0xC15E, 0x7E44, 0xEDDF, 0x7E45, 0xC162, 0x7E46, 0xC15B, 0x7E47, 0xEDD9, + 0x7E48, 0xC166, 0x7E49, 0xEDD7, 0x7E4C, 0xEDDB, 0x7E50, 0xF06E, 0x7E51, 0xF074, 0x7E52, 0xC2B9, 0x7E53, 0xF077, 0x7E54, 0xC2B4, + 0x7E55, 0xC2B5, 0x7E56, 0xF06F, 0x7E57, 0xF076, 0x7E58, 0xF071, 0x7E59, 0xC2BA, 0x7E5A, 0xC2B7, 0x7E5C, 0xF06D, 0x7E5E, 0xC2B6, + 0x7E5F, 0xF073, 0x7E60, 0xF075, 0x7E61, 0xC2B8, 0x7E62, 0xF072, 0x7E63, 0xF070, 0x7E68, 0xF2B8, 0x7E69, 0xC3B7, 0x7E6A, 0xC3B8, + 0x7E6B, 0xC3B4, 0x7E6D, 0xC3B5, 0x7E6F, 0xF2B4, 0x7E70, 0xF2B2, 0x7E72, 0xF2B6, 0x7E73, 0xC3BA, 0x7E74, 0xF2B7, 0x7E75, 0xF2B0, + 0x7E76, 0xF2AF, 0x7E77, 0xF2B3, 0x7E78, 0xF2B1, 0x7E79, 0xC3B6, 0x7E7A, 0xF2B5, 0x7E7B, 0xF4AC, 0x7E7C, 0xC47E, 0x7E7D, 0xC47D, + 0x7E7E, 0xF4AD, 0x7E80, 0xF4AF, 0x7E81, 0xF4AE, 0x7E82, 0xC4A1, 0x7E86, 0xF5EB, 0x7E87, 0xF5E8, 0x7E88, 0xF5E9, 0x7E8A, 0xF5E7, + 0x7E8B, 0xF5EA, 0x7E8C, 0xC4F2, 0x7E8D, 0xF5EC, 0x7E8F, 0xC4F1, 0x7E91, 0xF742, 0x7E93, 0xC5D5, 0x7E94, 0xC5D7, 0x7E95, 0xF7EE, + 0x7E96, 0xC5D6, 0x7E97, 0xF8B9, 0x7E98, 0xF940, 0x7E99, 0xF942, 0x7E9A, 0xF8FE, 0x7E9B, 0xF941, 0x7E9C, 0xC66C, 0x7F36, 0xA6CE, + 0x7F38, 0xACFB, 0x7F39, 0xD26F, 0x7F3A, 0xAFCA, 0x7F3D, 0xB2DA, 0x7F3E, 0xDAFC, 0x7F3F, 0xDAFD, 0x7F43, 0xEADF, 0x7F44, 0xC16A, + 0x7F45, 0xEDE1, 0x7F48, 0xC2BB, 0x7F4A, 0xF2BA, 0x7F4B, 0xF2B9, 0x7F4C, 0xC4A2, 0x7F4D, 0xF5ED, 0x7F4F, 0xF743, 0x7F50, 0xC5F8, + 0x7F51, 0xCA49, 0x7F54, 0xAAC9, 0x7F55, 0xA875, 0x7F58, 0xD04D, 0x7F5B, 0xD360, 0x7F5C, 0xD35B, 0x7F5D, 0xD35F, 0x7F5E, 0xD35D, + 0x7F5F, 0xAFCB, 0x7F60, 0xD35E, 0x7F61, 0xD35C, 0x7F63, 0xD6F1, 0x7F65, 0xDAFE, 0x7F66, 0xDB40, 0x7F67, 0xDF69, 0x7F68, 0xDF6A, + 0x7F69, 0xB86E, 0x7F6A, 0xB86F, 0x7F6B, 0xDF68, 0x7F6C, 0xDF6B, 0x7F6D, 0xDF67, 0x7F6E, 0xB86D, 0x7F70, 0xBB40, 0x7F72, 0xB870, + 0x7F73, 0xE37A, 0x7F75, 0xBD7C, 0x7F76, 0xE6F1, 0x7F77, 0xBD7D, 0x7F79, 0xBFA9, 0x7F7A, 0xEAE2, 0x7F7B, 0xEAE0, 0x7F7C, 0xEAE1, + 0x7F7D, 0xEDE4, 0x7F7E, 0xEDE3, 0x7F7F, 0xEDE2, 0x7F83, 0xF2BB, 0x7F85, 0xC3B9, 0x7F86, 0xF2BC, 0x7F87, 0xF744, 0x7F88, 0xC5F9, + 0x7F89, 0xF8BA, 0x7F8A, 0xA6CF, 0x7F8B, 0xAACB, 0x7F8C, 0xAACA, 0x7F8D, 0xD04F, 0x7F8E, 0xACFC, 0x7F91, 0xD04E, 0x7F92, 0xD362, + 0x7F94, 0xAFCC, 0x7F95, 0xD6F2, 0x7F96, 0xD361, 0x7F9A, 0xB2DC, 0x7F9B, 0xD6F5, 0x7F9C, 0xD6F3, 0x7F9D, 0xD6F4, 0x7F9E, 0xB2DB, + 0x7FA0, 0xDB42, 0x7FA1, 0xDB43, 0x7FA2, 0xDB41, 0x7FA4, 0xB873, 0x7FA5, 0xDF6D, 0x7FA6, 0xDF6C, 0x7FA7, 0xDF6E, 0x7FA8, 0xB872, + 0x7FA9, 0xB871, 0x7FAC, 0xE6F2, 0x7FAD, 0xE6F4, 0x7FAF, 0xBD7E, 0x7FB0, 0xE6F3, 0x7FB1, 0xEAE3, 0x7FB2, 0xBFAA, 0x7FB3, 0xF079, + 0x7FB5, 0xF078, 0x7FB6, 0xC3BB, 0x7FB7, 0xF2BD, 0x7FB8, 0xC3BD, 0x7FB9, 0xC3BC, 0x7FBA, 0xF4B0, 0x7FBB, 0xF5EE, 0x7FBC, 0xC4F3, + 0x7FBD, 0xA6D0, 0x7FBE, 0xD050, 0x7FBF, 0xACFD, 0x7FC0, 0xD365, 0x7FC1, 0xAFCE, 0x7FC2, 0xD364, 0x7FC3, 0xD363, 0x7FC5, 0xAFCD, + 0x7FC7, 0xD6FB, 0x7FC9, 0xD6FD, 0x7FCA, 0xD6F6, 0x7FCB, 0xD6F7, 0x7FCC, 0xB2DD, 0x7FCD, 0xD6F8, 0x7FCE, 0xB2DE, 0x7FCF, 0xD6FC, + 0x7FD0, 0xD6F9, 0x7FD1, 0xD6FA, 0x7FD2, 0xB2DF, 0x7FD4, 0xB5BE, 0x7FD5, 0xB5BF, 0x7FD7, 0xDB44, 0x7FDB, 0xDF6F, 0x7FDC, 0xDF70, + 0x7FDE, 0xE37E, 0x7FDF, 0xBB43, 0x7FE0, 0xBB41, 0x7FE1, 0xBB42, 0x7FE2, 0xE37B, 0x7FE3, 0xE37C, 0x7FE5, 0xE37D, 0x7FE6, 0xE6F9, + 0x7FE8, 0xE6FA, 0x7FE9, 0xBDA1, 0x7FEA, 0xE6F7, 0x7FEB, 0xE6F6, 0x7FEC, 0xE6F8, 0x7FED, 0xE6F5, 0x7FEE, 0xBFAD, 0x7FEF, 0xEAE4, + 0x7FF0, 0xBFAB, 0x7FF1, 0xBFAC, 0x7FF2, 0xEDE6, 0x7FF3, 0xC16B, 0x7FF4, 0xEDE5, 0x7FF5, 0xEFA8, 0x7FF7, 0xF07A, 0x7FF8, 0xF07B, + 0x7FF9, 0xC2BC, 0x7FFB, 0xC2BD, 0x7FFC, 0xC16C, 0x7FFD, 0xF2BE, 0x7FFE, 0xF2BF, 0x7FFF, 0xF4B1, 0x8000, 0xC4A3, 0x8001, 0xA6D1, + 0x8003, 0xA6D2, 0x8004, 0xACFE, 0x8005, 0xAACC, 0x8006, 0xAFCF, 0x8007, 0xD051, 0x800B, 0xB5C0, 0x800C, 0xA6D3, 0x800D, 0xAD41, + 0x800E, 0xD052, 0x800F, 0xD053, 0x8010, 0xAD40, 0x8011, 0xAD42, 0x8012, 0xA6D4, 0x8014, 0xD054, 0x8015, 0xAFD1, 0x8016, 0xD366, + 0x8017, 0xAFD3, 0x8018, 0xAFD0, 0x8019, 0xAFD2, 0x801B, 0xD741, 0x801C, 0xB2E0, 0x801E, 0xD740, 0x801F, 0xD6FE, 0x8021, 0xDF71, + 0x8024, 0xE3A1, 0x8026, 0xBDA2, 0x8028, 0xBFAE, 0x8029, 0xEAE6, 0x802A, 0xEAE5, 0x802C, 0xEDE7, 0x8030, 0xF5EF, 0x8033, 0xA6D5, + 0x8034, 0xCB73, 0x8035, 0xCDAA, 0x8036, 0xAD43, 0x8037, 0xD055, 0x8039, 0xD368, 0x803D, 0xAFD4, 0x803E, 0xD367, 0x803F, 0xAFD5, + 0x8043, 0xD743, 0x8046, 0xB2E2, 0x8047, 0xD742, 0x8048, 0xD744, 0x804A, 0xB2E1, 0x804F, 0xDB46, 0x8050, 0xDB47, 0x8051, 0xDB45, + 0x8052, 0xB5C1, 0x8056, 0xB874, 0x8058, 0xB875, 0x805A, 0xBB45, 0x805C, 0xE3A3, 0x805D, 0xE3A2, 0x805E, 0xBB44, 0x8064, 0xE6FB, + 0x8067, 0xE6FC, 0x806C, 0xEAE7, 0x806F, 0xC170, 0x8070, 0xC16F, 0x8071, 0xC16D, 0x8072, 0xC16E, 0x8073, 0xC171, 0x8075, 0xF07C, + 0x8076, 0xC2BF, 0x8077, 0xC2BE, 0x8078, 0xF2C0, 0x8079, 0xF4B2, 0x807D, 0xC5A5, 0x807E, 0xC5A4, 0x807F, 0xA6D6, 0x8082, 0xD1FB, + 0x8084, 0xB877, 0x8085, 0xB5C2, 0x8086, 0xB876, 0x8087, 0xBB46, 0x8089, 0xA6D7, 0x808A, 0xC9A9, 0x808B, 0xA6D8, 0x808C, 0xA6D9, + 0x808F, 0xCDAB, 0x8090, 0xCB76, 0x8092, 0xCB77, 0x8093, 0xA877, 0x8095, 0xCB74, 0x8096, 0xA876, 0x8098, 0xA879, 0x8099, 0xCB75, + 0x809A, 0xA87B, 0x809B, 0xA87A, 0x809C, 0xCB78, 0x809D, 0xA878, 0x80A1, 0xAAD1, 0x80A2, 0xAACF, 0x80A3, 0xCDAD, 0x80A5, 0xAACE, + 0x80A9, 0xAAD3, 0x80AA, 0xAAD5, 0x80AB, 0xAAD2, 0x80AD, 0xCDB0, 0x80AE, 0xCDAC, 0x80AF, 0xAAD6, 0x80B1, 0xAAD0, 0x80B2, 0xA87C, + 0x80B4, 0xAAD4, 0x80B5, 0xCDAF, 0x80B8, 0xCDAE, 0x80BA, 0xAACD, 0x80C2, 0xD05B, 0x80C3, 0xAD47, 0x80C4, 0xAD48, 0x80C5, 0xD05D, + 0x80C7, 0xD057, 0x80C8, 0xD05A, 0x80C9, 0xD063, 0x80CA, 0xD061, 0x80CC, 0xAD49, 0x80CD, 0xD067, 0x80CE, 0xAD4C, 0x80CF, 0xD064, + 0x80D0, 0xD05C, 0x80D1, 0xD059, 0x80D4, 0xDB49, 0x80D5, 0xD062, 0x80D6, 0xAD44, 0x80D7, 0xD065, 0x80D8, 0xD056, 0x80D9, 0xD05F, + 0x80DA, 0xAD46, 0x80DB, 0xAD4B, 0x80DC, 0xD060, 0x80DD, 0xAD4F, 0x80DE, 0xAD4D, 0x80E0, 0xD058, 0x80E1, 0xAD4A, 0x80E3, 0xD05E, + 0x80E4, 0xAD4E, 0x80E5, 0xAD45, 0x80E6, 0xD066, 0x80ED, 0xAFDA, 0x80EF, 0xAFE3, 0x80F0, 0xAFD8, 0x80F1, 0xAFD6, 0x80F2, 0xD36A, + 0x80F3, 0xAFDE, 0x80F4, 0xAFDB, 0x80F5, 0xD36C, 0x80F8, 0xAFDD, 0x80F9, 0xD36B, 0x80FA, 0xD369, 0x80FB, 0xD36E, 0x80FC, 0xAFE2, + 0x80FD, 0xAFE0, 0x80FE, 0xDB48, 0x8100, 0xD36F, 0x8101, 0xD36D, 0x8102, 0xAFD7, 0x8105, 0xAFD9, 0x8106, 0xAFDC, 0x8108, 0xAFDF, + 0x810A, 0xAFE1, 0x8115, 0xD74E, 0x8116, 0xB2E4, 0x8118, 0xD745, 0x8119, 0xD747, 0x811B, 0xD748, 0x811D, 0xD750, 0x811E, 0xD74C, + 0x811F, 0xD74A, 0x8121, 0xD74D, 0x8122, 0xD751, 0x8123, 0xB2E5, 0x8124, 0xB2E9, 0x8125, 0xD746, 0x8127, 0xD74F, 0x8129, 0xB2E7, + 0x812B, 0xB2E6, 0x812C, 0xD74B, 0x812D, 0xD749, 0x812F, 0xB2E3, 0x8130, 0xB2E8, 0x8139, 0xB5C8, 0x813A, 0xDB51, 0x813D, 0xDB4F, + 0x813E, 0xB5CA, 0x8143, 0xDB4A, 0x8144, 0xDFA1, 0x8146, 0xB5C9, 0x8147, 0xDB4E, 0x814A, 0xDB4B, 0x814B, 0xB5C5, 0x814C, 0xB5CB, + 0x814D, 0xDB50, 0x814E, 0xB5C7, 0x814F, 0xDB4D, 0x8150, 0xBB47, 0x8151, 0xB5C6, 0x8152, 0xDB4C, 0x8153, 0xB5CC, 0x8154, 0xB5C4, + 0x8155, 0xB5C3, 0x815B, 0xDF77, 0x815C, 0xDF75, 0x815E, 0xDF7B, 0x8160, 0xDF73, 0x8161, 0xDFA2, 0x8162, 0xDF78, 0x8164, 0xDF72, + 0x8165, 0xB87B, 0x8166, 0xB8A3, 0x8167, 0xDF7D, 0x8169, 0xDF76, 0x816B, 0xB87E, 0x816E, 0xB87C, 0x816F, 0xDF7E, 0x8170, 0xB879, + 0x8171, 0xB878, 0x8172, 0xDF79, 0x8173, 0xB87D, 0x8174, 0xB5CD, 0x8176, 0xDF7C, 0x8177, 0xDF74, 0x8178, 0xB87A, 0x8179, 0xB8A1, + 0x817A, 0xB8A2, 0x817F, 0xBB4C, 0x8180, 0xBB48, 0x8182, 0xBB4D, 0x8183, 0xE3A6, 0x8186, 0xE3A5, 0x8187, 0xE3A7, 0x8188, 0xBB4A, + 0x8189, 0xE3A4, 0x818A, 0xBB4B, 0x818B, 0xE3AA, 0x818C, 0xE3A9, 0x818D, 0xE3A8, 0x818F, 0xBB49, 0x8195, 0xE741, 0x8197, 0xE744, + 0x8198, 0xBDA8, 0x8199, 0xE743, 0x819A, 0xBDA7, 0x819B, 0xBDA3, 0x819C, 0xBDA4, 0x819D, 0xBDA5, 0x819E, 0xE740, 0x819F, 0xE6FE, + 0x81A0, 0xBDA6, 0x81A2, 0xE742, 0x81A3, 0xE6FD, 0x81A6, 0xEAE9, 0x81A7, 0xEAF3, 0x81A8, 0xBFB1, 0x81A9, 0xBFB0, 0x81AB, 0xEAED, + 0x81AC, 0xEAEF, 0x81AE, 0xEAEA, 0x81B0, 0xEAEE, 0x81B1, 0xEAE8, 0x81B2, 0xEAF1, 0x81B3, 0xBFAF, 0x81B4, 0xEAF0, 0x81B5, 0xEAEC, + 0x81B7, 0xEAF2, 0x81B9, 0xEAEB, 0x81BA, 0xC174, 0x81BB, 0xEDE8, 0x81BC, 0xEDEE, 0x81BD, 0xC178, 0x81BE, 0xC17A, 0x81BF, 0xC177, + 0x81C0, 0xC176, 0x81C2, 0xC175, 0x81C3, 0xC173, 0x81C4, 0xEDE9, 0x81C5, 0xEDEC, 0x81C6, 0xC172, 0x81C7, 0xEDED, 0x81C9, 0xC179, + 0x81CA, 0xEDEB, 0x81CC, 0xEDEA, 0x81CD, 0xC2C0, 0x81CF, 0xC2C1, 0x81D0, 0xF0A1, 0x81D1, 0xF07D, 0x81D2, 0xF07E, 0x81D5, 0xF2C2, + 0x81D7, 0xF2C1, 0x81D8, 0xC3BE, 0x81D9, 0xF4B4, 0x81DA, 0xC4A4, 0x81DB, 0xF4B3, 0x81DD, 0xF5F0, 0x81DE, 0xF745, 0x81DF, 0xC5A6, + 0x81E0, 0xF943, 0x81E1, 0xF944, 0x81E2, 0xC5D8, 0x81E3, 0xA6DA, 0x81E5, 0xAAD7, 0x81E6, 0xDB52, 0x81E7, 0xBB4E, 0x81E8, 0xC17B, + 0x81E9, 0xEDEF, 0x81EA, 0xA6DB, 0x81EC, 0xAFE5, 0x81ED, 0xAFE4, 0x81EE, 0xDB53, 0x81F2, 0xEAF4, 0x81F3, 0xA6DC, 0x81F4, 0xAD50, + 0x81F7, 0xDB54, 0x81F8, 0xDB55, 0x81F9, 0xDB56, 0x81FA, 0xBB4F, 0x81FB, 0xBFB2, 0x81FC, 0xA6DD, 0x81FE, 0xAAD8, 0x81FF, 0xD068, + 0x8200, 0xAFE6, 0x8201, 0xD370, 0x8202, 0xB2EA, 0x8204, 0xDB57, 0x8205, 0xB8A4, 0x8207, 0xBB50, 0x8208, 0xBFB3, 0x8209, 0xC17C, + 0x820A, 0xC2C2, 0x820B, 0xF4B5, 0x820C, 0xA6DE, 0x820D, 0xAAD9, 0x8210, 0xAFE7, 0x8211, 0xD752, 0x8212, 0xB5CE, 0x8214, 0xBB51, + 0x8215, 0xE3AB, 0x8216, 0xE745, 0x821B, 0xA6DF, 0x821C, 0xB5CF, 0x821D, 0xDFA3, 0x821E, 0xBB52, 0x821F, 0xA6E0, 0x8220, 0xCDB1, + 0x8221, 0xD069, 0x8222, 0xAD51, 0x8225, 0xD372, 0x8228, 0xAFEA, 0x822A, 0xAFE8, 0x822B, 0xAFE9, 0x822C, 0xAFEB, 0x822F, 0xD371, + 0x8232, 0xD757, 0x8233, 0xD754, 0x8234, 0xD756, 0x8235, 0xB2EB, 0x8236, 0xB2ED, 0x8237, 0xB2EC, 0x8238, 0xD753, 0x8239, 0xB2EE, + 0x823A, 0xD755, 0x823C, 0xDB58, 0x823D, 0xDB59, 0x823F, 0xDB5A, 0x8240, 0xDFA6, 0x8242, 0xDFA7, 0x8244, 0xDFA5, 0x8245, 0xDFA8, + 0x8247, 0xB8A5, 0x8249, 0xDFA4, 0x824B, 0xBB53, 0x824E, 0xE74A, 0x824F, 0xE746, 0x8250, 0xE749, 0x8251, 0xE74B, 0x8252, 0xE748, + 0x8253, 0xE747, 0x8255, 0xEAF5, 0x8256, 0xEAF6, 0x8257, 0xEAF7, 0x8258, 0xBFB4, 0x8259, 0xBFB5, 0x825A, 0xEDF1, 0x825B, 0xEDF0, + 0x825C, 0xEDF2, 0x825E, 0xF0A3, 0x825F, 0xF0A2, 0x8261, 0xF2C4, 0x8263, 0xF2C5, 0x8264, 0xF2C3, 0x8266, 0xC4A5, 0x8268, 0xF4B6, + 0x8269, 0xF4B7, 0x826B, 0xF746, 0x826C, 0xF7EF, 0x826D, 0xF8BB, 0x826E, 0xA6E1, 0x826F, 0xA87D, 0x8271, 0xC17D, 0x8272, 0xA6E2, + 0x8274, 0xD758, 0x8275, 0xDB5B, 0x8277, 0xC641, 0x8278, 0xCA4A, 0x827C, 0xCA4B, 0x827D, 0xCA4D, 0x827E, 0xA6E3, 0x827F, 0xCA4E, + 0x8280, 0xCA4C, 0x8283, 0xCBA2, 0x8284, 0xCBA3, 0x8285, 0xCB7B, 0x828A, 0xCBA1, 0x828B, 0xA8A1, 0x828D, 0xA8A2, 0x828E, 0xCB7C, + 0x828F, 0xCB7A, 0x8290, 0xCB79, 0x8291, 0xCB7D, 0x8292, 0xA87E, 0x8293, 0xCB7E, 0x8294, 0xD06A, 0x8298, 0xCDB6, 0x8299, 0xAADC, + 0x829A, 0xCDB5, 0x829B, 0xCDB7, 0x829D, 0xAADB, 0x829E, 0xCDBC, 0x829F, 0xAADF, 0x82A0, 0xCDB2, 0x82A1, 0xCDC0, 0x82A2, 0xCDC6, + 0x82A3, 0xAAE6, 0x82A4, 0xCDC3, 0x82A5, 0xAAE3, 0x82A7, 0xCDB9, 0x82A8, 0xCDBF, 0x82A9, 0xCDC1, 0x82AB, 0xCDB4, 0x82AC, 0xAAE2, + 0x82AD, 0xAADD, 0x82AE, 0xCDBA, 0x82AF, 0xAAE4, 0x82B0, 0xAAE7, 0x82B1, 0xAAE1, 0x82B3, 0xAADA, 0x82B4, 0xCDBE, 0x82B5, 0xCDB8, + 0x82B6, 0xCDC5, 0x82B7, 0xAAE9, 0x82B8, 0xAAE5, 0x82B9, 0xAAE0, 0x82BA, 0xCDBD, 0x82BB, 0xAFEC, 0x82BC, 0xCDBB, 0x82BD, 0xAADE, + 0x82BE, 0xAAE8, 0x82C0, 0xCDB3, 0x82C2, 0xCDC2, 0x82C3, 0xCDC4, 0x82D1, 0xAD62, 0x82D2, 0xAD5C, 0x82D3, 0xAD64, 0x82D4, 0xAD61, + 0x82D5, 0xD071, 0x82D6, 0xD074, 0x82D7, 0xAD5D, 0x82D9, 0xD06B, 0x82DB, 0xAD56, 0x82DC, 0xAD60, 0x82DE, 0xAD63, 0x82DF, 0xAD65, + 0x82E0, 0xD0A2, 0x82E1, 0xD077, 0x82E3, 0xAD55, 0x82E4, 0xD0A1, 0x82E5, 0xAD59, 0x82E6, 0xAD57, 0x82E7, 0xAD52, 0x82E8, 0xD06F, + 0x82EA, 0xD07E, 0x82EB, 0xD073, 0x82EC, 0xD076, 0x82ED, 0xD0A5, 0x82EF, 0xAD66, 0x82F0, 0xD07D, 0x82F1, 0xAD5E, 0x82F2, 0xD078, + 0x82F3, 0xD0A4, 0x82F4, 0xD075, 0x82F5, 0xD079, 0x82F6, 0xD07C, 0x82F9, 0xD06D, 0x82FA, 0xD0A3, 0x82FB, 0xD07B, 0x82FE, 0xD06C, + 0x8300, 0xD070, 0x8301, 0xAD5F, 0x8302, 0xAD5A, 0x8303, 0xAD53, 0x8304, 0xAD58, 0x8305, 0xAD54, 0x8306, 0xAD67, 0x8307, 0xD06E, + 0x8308, 0xD3A5, 0x8309, 0xAD5B, 0x830C, 0xD07A, 0x830D, 0xCE41, 0x8316, 0xD3A8, 0x8317, 0xAFFA, 0x8319, 0xD376, 0x831B, 0xD3A3, + 0x831C, 0xD37D, 0x831E, 0xD3B2, 0x8320, 0xD3AA, 0x8322, 0xD37E, 0x8324, 0xD3A9, 0x8325, 0xD378, 0x8326, 0xD37C, 0x8327, 0xD3B5, + 0x8328, 0xAFFD, 0x8329, 0xD3AD, 0x832A, 0xD3A4, 0x832B, 0xAFED, 0x832C, 0xD3B3, 0x832D, 0xD374, 0x832F, 0xD3AC, 0x8331, 0xAFFC, + 0x8332, 0xAFF7, 0x8333, 0xD373, 0x8334, 0xAFF5, 0x8335, 0xAFF4, 0x8336, 0xAFF9, 0x8337, 0xD3AB, 0x8338, 0xAFF1, 0x8339, 0xAFF8, + 0x833A, 0xD072, 0x833B, 0xDB5C, 0x833C, 0xD3A6, 0x833F, 0xD37A, 0x8340, 0xAFFB, 0x8341, 0xD37B, 0x8342, 0xD3A1, 0x8343, 0xAFFE, + 0x8344, 0xD375, 0x8345, 0xD3AF, 0x8347, 0xD3AE, 0x8348, 0xD3B6, 0x8349, 0xAFF3, 0x834A, 0xAFF0, 0x834B, 0xD3B4, 0x834C, 0xD3B0, + 0x834D, 0xD3A7, 0x834E, 0xD3A2, 0x834F, 0xAFF6, 0x8350, 0xAFF2, 0x8351, 0xD377, 0x8352, 0xAFEE, 0x8353, 0xD3B1, 0x8354, 0xAFEF, + 0x8356, 0xD379, 0x8373, 0xD75E, 0x8374, 0xD760, 0x8375, 0xD765, 0x8376, 0xD779, 0x8377, 0xB2FC, 0x8378, 0xB2F2, 0x837A, 0xD75D, + 0x837B, 0xB2FD, 0x837C, 0xB2FE, 0x837D, 0xD768, 0x837E, 0xD76F, 0x837F, 0xD775, 0x8381, 0xD762, 0x8383, 0xD769, 0x8386, 0xB340, + 0x8387, 0xD777, 0x8388, 0xD772, 0x8389, 0xB2FA, 0x838A, 0xB2F8, 0x838B, 0xD76E, 0x838C, 0xD76A, 0x838D, 0xD75C, 0x838E, 0xB2EF, + 0x838F, 0xD761, 0x8390, 0xD759, 0x8392, 0xB2F7, 0x8393, 0xB2F9, 0x8394, 0xD766, 0x8395, 0xD763, 0x8396, 0xB2F4, 0x8397, 0xD773, + 0x8398, 0xB2F1, 0x8399, 0xD764, 0x839A, 0xD77A, 0x839B, 0xD76C, 0x839D, 0xD76B, 0x839E, 0xB2F0, 0x83A0, 0xB2FB, 0x83A2, 0xB2F3, + 0x83A3, 0xD75A, 0x83A4, 0xD75F, 0x83A5, 0xD770, 0x83A6, 0xD776, 0x83A7, 0xB341, 0x83A8, 0xD75B, 0x83A9, 0xD767, 0x83AA, 0xD76D, + 0x83AB, 0xB2F6, 0x83AE, 0xD778, 0x83AF, 0xD771, 0x83B0, 0xD774, 0x83BD, 0xB2F5, 0x83BF, 0xDB6C, 0x83C0, 0xDB60, 0x83C1, 0xB5D7, + 0x83C2, 0xDB7D, 0x83C3, 0xDBA7, 0x83C4, 0xDBAA, 0x83C5, 0xB5D5, 0x83C6, 0xDB68, 0x83C7, 0xDBA3, 0x83C8, 0xDB69, 0x83C9, 0xDB77, + 0x83CA, 0xB5E2, 0x83CB, 0xDB73, 0x83CC, 0xB5DF, 0x83CE, 0xDB74, 0x83CF, 0xDB5D, 0x83D1, 0xDBA4, 0x83D4, 0xB5E8, 0x83D5, 0xDBA1, + 0x83D6, 0xDB75, 0x83D7, 0xDBAC, 0x83D8, 0xDB70, 0x83D9, 0xDFC8, 0x83DB, 0xDBAF, 0x83DC, 0xB5E6, 0x83DD, 0xDB6E, 0x83DE, 0xDB7A, + 0x83DF, 0xB5E9, 0x83E0, 0xB5D4, 0x83E1, 0xDB72, 0x83E2, 0xDBAD, 0x83E3, 0xDB6B, 0x83E4, 0xDB64, 0x83E5, 0xDB6F, 0x83E7, 0xDB63, + 0x83E8, 0xDB61, 0x83E9, 0xB5D0, 0x83EA, 0xDBA5, 0x83EB, 0xDB6A, 0x83EC, 0xDBA8, 0x83EE, 0xDBA9, 0x83EF, 0xB5D8, 0x83F0, 0xB5DD, + 0x83F1, 0xB5D9, 0x83F2, 0xB5E1, 0x83F3, 0xDB7E, 0x83F4, 0xB5DA, 0x83F5, 0xDB76, 0x83F6, 0xDB66, 0x83F8, 0xB5D2, 0x83F9, 0xDB5E, + 0x83FA, 0xDBA2, 0x83FB, 0xDBAB, 0x83FC, 0xDB65, 0x83FD, 0xB5E0, 0x83FE, 0xDBB0, 0x83FF, 0xDB71, 0x8401, 0xDB6D, 0x8403, 0xB5D1, + 0x8404, 0xB5E5, 0x8406, 0xDB7C, 0x8407, 0xB5E7, 0x8409, 0xDB78, 0x840A, 0xB5DC, 0x840B, 0xB5D6, 0x840C, 0xB5DE, 0x840D, 0xB5D3, + 0x840E, 0xB5E4, 0x840F, 0xDB79, 0x8410, 0xDB67, 0x8411, 0xDB7B, 0x8412, 0xDB62, 0x8413, 0xDBA6, 0x841B, 0xDBAE, 0x8423, 0xDB5F, + 0x8429, 0xDFC7, 0x842B, 0xDFDD, 0x842C, 0xB855, 0x842D, 0xDFCC, 0x842F, 0xDFCA, 0x8430, 0xDFB5, 0x8431, 0xB8A9, 0x8432, 0xDFC5, + 0x8433, 0xDFD9, 0x8434, 0xDFC1, 0x8435, 0xB8B1, 0x8436, 0xDFD8, 0x8437, 0xDFBF, 0x8438, 0xB5E3, 0x8439, 0xDFCF, 0x843A, 0xDFC0, + 0x843B, 0xDFD6, 0x843C, 0xB8B0, 0x843D, 0xB8A8, 0x843F, 0xDFAA, 0x8440, 0xDFB2, 0x8442, 0xDFCB, 0x8443, 0xDFC3, 0x8444, 0xDFDC, + 0x8445, 0xDFC6, 0x8446, 0xB8B6, 0x8447, 0xDFD7, 0x8449, 0xB8AD, 0x844B, 0xDFC9, 0x844C, 0xDFD1, 0x844D, 0xDFB6, 0x844E, 0xDFD0, + 0x8450, 0xDFE1, 0x8451, 0xDFB1, 0x8452, 0xDFD2, 0x8454, 0xDFDF, 0x8456, 0xDFAB, 0x8457, 0xB5DB, 0x8459, 0xDFB9, 0x845A, 0xDFB8, + 0x845B, 0xB8AF, 0x845D, 0xDFBC, 0x845E, 0xDFBE, 0x845F, 0xDFCD, 0x8460, 0xDFDE, 0x8461, 0xB8B2, 0x8463, 0xB8B3, 0x8465, 0xDFB0, + 0x8466, 0xB8AB, 0x8467, 0xDFB4, 0x8468, 0xDFDA, 0x8469, 0xB8B4, 0x846B, 0xB8AC, 0x846C, 0xB8AE, 0x846D, 0xB8B5, 0x846E, 0xDFE0, + 0x846F, 0xDFD3, 0x8470, 0xDFCE, 0x8473, 0xDFBB, 0x8474, 0xDFBA, 0x8475, 0xB8AA, 0x8476, 0xDFAC, 0x8477, 0xB8A7, 0x8478, 0xDFC4, + 0x8479, 0xDFAD, 0x847A, 0xDFC2, 0x847D, 0xDFB7, 0x847E, 0xDFDB, 0x8482, 0xB8A6, 0x8486, 0xDFB3, 0x848D, 0xDFAF, 0x848E, 0xDFD5, + 0x848F, 0xDFAE, 0x8490, 0xBB60, 0x8491, 0xE3D3, 0x8494, 0xE3C2, 0x8497, 0xE3AC, 0x8498, 0xE3CA, 0x8499, 0xBB58, 0x849A, 0xE3BB, + 0x849B, 0xE3C5, 0x849C, 0xBB5B, 0x849D, 0xE3BE, 0x849E, 0xBB59, 0x849F, 0xE3AF, 0x84A0, 0xE3CD, 0x84A1, 0xE3AE, 0x84A2, 0xE3C1, + 0x84A4, 0xE3AD, 0x84A7, 0xE3BF, 0x84A8, 0xE3C8, 0x84A9, 0xE3C6, 0x84AA, 0xE3BA, 0x84AB, 0xE3B5, 0x84AC, 0xE3B3, 0x84AE, 0xE3B4, + 0x84AF, 0xE3C7, 0x84B0, 0xE3D2, 0x84B1, 0xE3BC, 0x84B2, 0xBB5A, 0x84B4, 0xE3B7, 0x84B6, 0xE3CB, 0x84B8, 0xBB5D, 0x84B9, 0xE3B6, + 0x84BA, 0xE3B0, 0x84BB, 0xE3C0, 0x84BC, 0xBB61, 0x84BF, 0xBB55, 0x84C0, 0xBB5E, 0x84C1, 0xE3B8, 0x84C2, 0xE3B2, 0x84C4, 0xBB57, + 0x84C5, 0xDFD4, 0x84C6, 0xBB56, 0x84C7, 0xE3C3, 0x84C9, 0xBB54, 0x84CA, 0xBB63, 0x84CB, 0xBB5C, 0x84CC, 0xE3C4, 0x84CD, 0xE3B9, + 0x84CE, 0xE3B1, 0x84CF, 0xE3CC, 0x84D0, 0xE3BD, 0x84D1, 0xBB62, 0x84D2, 0xE3D0, 0x84D3, 0xBB5F, 0x84D4, 0xE3CF, 0x84D6, 0xE3C9, + 0x84D7, 0xE3CE, 0x84DB, 0xE3D1, 0x84E7, 0xE773, 0x84E8, 0xE774, 0x84E9, 0xE767, 0x84EA, 0xE766, 0x84EB, 0xE762, 0x84EC, 0xBDB4, + 0x84EE, 0xBDAC, 0x84EF, 0xE776, 0x84F0, 0xE775, 0x84F1, 0xDFA9, 0x84F2, 0xE75F, 0x84F3, 0xE763, 0x84F4, 0xE75D, 0x84F6, 0xE770, + 0x84F7, 0xE761, 0x84F9, 0xE777, 0x84FA, 0xE75A, 0x84FB, 0xE758, 0x84FC, 0xE764, 0x84FD, 0xE76E, 0x84FE, 0xE769, 0x84FF, 0xBDB6, + 0x8500, 0xE74F, 0x8502, 0xE76D, 0x8506, 0xBDB7, 0x8507, 0xDFBD, 0x8508, 0xE75B, 0x8509, 0xE752, 0x850A, 0xE755, 0x850B, 0xE77B, + 0x850C, 0xE75C, 0x850D, 0xE753, 0x850E, 0xE751, 0x850F, 0xE74E, 0x8511, 0xBDB0, 0x8512, 0xE765, 0x8513, 0xBDAF, 0x8514, 0xBDB3, + 0x8515, 0xE760, 0x8516, 0xE768, 0x8517, 0xBDA9, 0x8518, 0xE778, 0x8519, 0xE77C, 0x851A, 0xBDAB, 0x851C, 0xE757, 0x851D, 0xE76B, + 0x851E, 0xE76F, 0x851F, 0xE754, 0x8520, 0xE779, 0x8521, 0xBDB2, 0x8523, 0xBDB1, 0x8524, 0xE74C, 0x8525, 0xBDB5, 0x8526, 0xE772, + 0x8527, 0xE756, 0x8528, 0xE76A, 0x8529, 0xE750, 0x852A, 0xE75E, 0x852B, 0xE759, 0x852C, 0xBDAD, 0x852D, 0xBDAE, 0x852E, 0xE76C, + 0x852F, 0xE77D, 0x8530, 0xE77A, 0x8531, 0xE771, 0x853B, 0xE74D, 0x853D, 0xBDAA, 0x853E, 0xEB49, 0x8540, 0xEB40, 0x8541, 0xEB43, + 0x8543, 0xBFBB, 0x8544, 0xEB45, 0x8545, 0xEAF9, 0x8546, 0xEB41, 0x8547, 0xEB47, 0x8548, 0xBFB8, 0x8549, 0xBFBC, 0x854A, 0xBFB6, + 0x854D, 0xEAFB, 0x854E, 0xEB4C, 0x8551, 0xEB46, 0x8553, 0xEAFC, 0x8554, 0xEB55, 0x8555, 0xEB4F, 0x8556, 0xEAF8, 0x8557, 0xEE46, + 0x8558, 0xEAFE, 0x8559, 0xBFB7, 0x855B, 0xEB4A, 0x855D, 0xEB54, 0x855E, 0xBFBF, 0x8560, 0xEB51, 0x8561, 0xEAFD, 0x8562, 0xEB44, + 0x8563, 0xEB48, 0x8564, 0xEB42, 0x8565, 0xEB56, 0x8566, 0xEB53, 0x8567, 0xEB50, 0x8568, 0xBFB9, 0x8569, 0xBFBA, 0x856A, 0xBFBE, + 0x856B, 0xEAFA, 0x856C, 0xEB57, 0x856D, 0xBFBD, 0x856E, 0xEB4D, 0x8571, 0xEB4B, 0x8575, 0xEB4E, 0x8576, 0xEE53, 0x8577, 0xEE40, + 0x8578, 0xEE45, 0x8579, 0xEE52, 0x857A, 0xEE44, 0x857B, 0xEDFB, 0x857C, 0xEE41, 0x857E, 0xC1A2, 0x8580, 0xEDF4, 0x8581, 0xEE4D, + 0x8582, 0xEE4F, 0x8583, 0xEDF3, 0x8584, 0xC1A1, 0x8585, 0xEE51, 0x8586, 0xEE49, 0x8587, 0xC1A8, 0x8588, 0xEE50, 0x8589, 0xEE42, + 0x858A, 0xC1AA, 0x858B, 0xEDF9, 0x858C, 0xEB52, 0x858D, 0xEE4A, 0x858E, 0xEE47, 0x858F, 0xEDF5, 0x8590, 0xEE55, 0x8591, 0xC1A4, + 0x8594, 0xC1A5, 0x8595, 0xEDF7, 0x8596, 0xEE48, 0x8598, 0xEE54, 0x8599, 0xEE4B, 0x859A, 0xEDFD, 0x859B, 0xC1A7, 0x859C, 0xC1A3, + 0x859D, 0xEE4C, 0x859E, 0xEDFE, 0x859F, 0xEE56, 0x85A0, 0xEDF8, 0x85A1, 0xEE43, 0x85A2, 0xEE4E, 0x85A3, 0xEDFA, 0x85A4, 0xEDFC, + 0x85A6, 0xC2CB, 0x85A7, 0xEDF6, 0x85A8, 0xC1A9, 0x85A9, 0xC2C4, 0x85AA, 0xC17E, 0x85AF, 0xC1A6, 0x85B0, 0xC2C8, 0x85B1, 0xF0B3, + 0x85B3, 0xF0A9, 0x85B4, 0xF0A4, 0x85B5, 0xF0AA, 0x85B6, 0xF0B4, 0x85B7, 0xF0B8, 0x85B8, 0xF0B7, 0x85B9, 0xC2CA, 0x85BA, 0xC2C9, + 0x85BD, 0xF0AB, 0x85BE, 0xF0B9, 0x85BF, 0xF0AE, 0x85C0, 0xF0A6, 0x85C2, 0xF0A8, 0x85C3, 0xF0A7, 0x85C4, 0xF0AD, 0x85C5, 0xF0B2, + 0x85C6, 0xF0A5, 0x85C7, 0xF0AC, 0x85C8, 0xF0B1, 0x85C9, 0xC2C7, 0x85CB, 0xF0AF, 0x85CD, 0xC2C5, 0x85CE, 0xF0B0, 0x85CF, 0xC2C3, + 0x85D0, 0xC2C6, 0x85D1, 0xF2D5, 0x85D2, 0xF0B5, 0x85D5, 0xC3C2, 0x85D7, 0xF2CD, 0x85D8, 0xF2D1, 0x85D9, 0xF2C9, 0x85DA, 0xF2CC, + 0x85DC, 0xF2D4, 0x85DD, 0xC3C0, 0x85DE, 0xF2D9, 0x85DF, 0xF2D2, 0x85E1, 0xF2CA, 0x85E2, 0xF2DA, 0x85E3, 0xF2D3, 0x85E4, 0xC3C3, + 0x85E5, 0xC3C4, 0x85E6, 0xF2D7, 0x85E8, 0xF2CB, 0x85E9, 0xC3BF, 0x85EA, 0xC3C1, 0x85EB, 0xF2C6, 0x85EC, 0xF2CE, 0x85ED, 0xF2C8, + 0x85EF, 0xF2D8, 0x85F0, 0xF2D6, 0x85F1, 0xF2C7, 0x85F2, 0xF2CF, 0x85F6, 0xF4BE, 0x85F7, 0xC3C5, 0x85F8, 0xF2D0, 0x85F9, 0xC4A7, + 0x85FA, 0xC4A9, 0x85FB, 0xC4A6, 0x85FD, 0xF4C3, 0x85FE, 0xF4BB, 0x85FF, 0xF4B9, 0x8600, 0xF4BD, 0x8601, 0xF4BA, 0x8604, 0xF4BF, + 0x8605, 0xF4C1, 0x8606, 0xC4AA, 0x8607, 0xC4AC, 0x8609, 0xF4C0, 0x860A, 0xC4AD, 0x860B, 0xC4AB, 0x860C, 0xF4C2, 0x8611, 0xC4A8, + 0x8617, 0xC4F4, 0x8618, 0xF5F1, 0x8619, 0xF5F7, 0x861A, 0xC4F6, 0x861B, 0xF4BC, 0x861C, 0xF5F6, 0x861E, 0xF5FD, 0x861F, 0xF5F4, + 0x8620, 0xF5FB, 0x8621, 0xF5FA, 0x8622, 0xF4B8, 0x8623, 0xF5F5, 0x8624, 0xF0B6, 0x8625, 0xF5FE, 0x8626, 0xF5F3, 0x8627, 0xF5F8, + 0x8629, 0xF5FC, 0x862A, 0xF5F2, 0x862C, 0xF74A, 0x862D, 0xC4F5, 0x862E, 0xF5F9, 0x8631, 0xF7F4, 0x8632, 0xF74B, 0x8633, 0xF749, + 0x8634, 0xF747, 0x8635, 0xF748, 0x8636, 0xF74C, 0x8638, 0xC5D9, 0x8639, 0xF7F2, 0x863A, 0xF7F0, 0x863B, 0xF7F5, 0x863C, 0xF7F3, + 0x863E, 0xF7F6, 0x863F, 0xC5DA, 0x8640, 0xF7F1, 0x8643, 0xF8BC, 0x8646, 0xF945, 0x8647, 0xF946, 0x8648, 0xF947, 0x864B, 0xF9C7, + 0x864C, 0xF9BD, 0x864D, 0xCA4F, 0x864E, 0xAAEA, 0x8650, 0xAD68, 0x8652, 0xD3B8, 0x8653, 0xD3B7, 0x8654, 0xB040, 0x8655, 0xB342, + 0x8656, 0xD77C, 0x8659, 0xD77B, 0x865B, 0xB5EA, 0x865C, 0xB8B8, 0x865E, 0xB8B7, 0x865F, 0xB8B9, 0x8661, 0xE3D4, 0x8662, 0xE77E, + 0x8663, 0xEB58, 0x8664, 0xEB5A, 0x8665, 0xEB59, 0x8667, 0xC1AB, 0x8668, 0xEE57, 0x8669, 0xF0BA, 0x866A, 0xF9A5, 0x866B, 0xA6E4, + 0x866D, 0xCDC9, 0x866E, 0xCDCA, 0x866F, 0xCDC8, 0x8670, 0xCDC7, 0x8671, 0xAAEB, 0x8673, 0xD0A9, 0x8674, 0xD0A7, 0x8677, 0xD0A6, + 0x8679, 0xAD69, 0x867A, 0xAD6B, 0x867B, 0xAD6A, 0x867C, 0xD0A8, 0x8685, 0xD3C4, 0x8686, 0xD3C1, 0x8687, 0xD3BF, 0x868A, 0xB041, + 0x868B, 0xD3C2, 0x868C, 0xB046, 0x868D, 0xD3BC, 0x868E, 0xD3CB, 0x8690, 0xD3CD, 0x8691, 0xD3BD, 0x8693, 0xB043, 0x8694, 0xD3CE, + 0x8695, 0xD3C9, 0x8696, 0xD3BB, 0x8697, 0xD3C0, 0x8698, 0xD3CA, 0x8699, 0xD3C6, 0x869A, 0xD3C3, 0x869C, 0xB048, 0x869D, 0xD3CC, + 0x869E, 0xD3BE, 0x86A1, 0xD3C7, 0x86A2, 0xD3B9, 0x86A3, 0xB047, 0x86A4, 0xB044, 0x86A5, 0xD3C5, 0x86A7, 0xD3C8, 0x86A8, 0xD3BA, + 0x86A9, 0xB045, 0x86AA, 0xB042, 0x86AF, 0xB34C, 0x86B0, 0xD7A5, 0x86B1, 0xB34B, 0x86B3, 0xD7A8, 0x86B4, 0xD7AB, 0x86B5, 0xB348, + 0x86B6, 0xB346, 0x86B7, 0xD77E, 0x86B8, 0xD7A9, 0x86B9, 0xD7A7, 0x86BA, 0xD7A4, 0x86BB, 0xD7AC, 0x86BC, 0xD7AD, 0x86BD, 0xD7AF, + 0x86BE, 0xD7B0, 0x86BF, 0xD77D, 0x86C0, 0xB345, 0x86C1, 0xD7A2, 0x86C2, 0xD7A1, 0x86C3, 0xD7AE, 0x86C4, 0xB347, 0x86C5, 0xD7A3, + 0x86C6, 0xB349, 0x86C7, 0xB344, 0x86C8, 0xD7A6, 0x86C9, 0xB34D, 0x86CB, 0xB34A, 0x86CC, 0xD7AA, 0x86D0, 0xB5F1, 0x86D1, 0xDBBF, + 0x86D3, 0xDBB4, 0x86D4, 0xB5EE, 0x86D6, 0xDFE7, 0x86D7, 0xDBBD, 0x86D8, 0xDBB1, 0x86D9, 0xB5EC, 0x86DA, 0xDBB6, 0x86DB, 0xB5EF, + 0x86DC, 0xDBBA, 0x86DD, 0xDBB8, 0x86DE, 0xB5F2, 0x86DF, 0xB5EB, 0x86E2, 0xDBB2, 0x86E3, 0xDBB5, 0x86E4, 0xB5F0, 0x86E6, 0xDBB3, + 0x86E8, 0xDBBE, 0x86E9, 0xDBBC, 0x86EA, 0xDBB7, 0x86EB, 0xDBB9, 0x86EC, 0xDBBB, 0x86ED, 0xB5ED, 0x86F5, 0xDFE8, 0x86F6, 0xDFEE, + 0x86F7, 0xDFE4, 0x86F8, 0xDFEA, 0x86F9, 0xB8BA, 0x86FA, 0xDFE6, 0x86FB, 0xB8C0, 0x86FE, 0xB8BF, 0x8700, 0xB8BE, 0x8701, 0xDFED, + 0x8702, 0xB8C1, 0x8703, 0xB8C2, 0x8704, 0xDFE3, 0x8705, 0xDFF0, 0x8706, 0xB8C3, 0x8707, 0xB8BD, 0x8708, 0xB8BC, 0x8709, 0xDFEC, + 0x870A, 0xB8C4, 0x870B, 0xDFE2, 0x870C, 0xDFE5, 0x870D, 0xDFEF, 0x870E, 0xDFEB, 0x8711, 0xE3F4, 0x8712, 0xE3E9, 0x8713, 0xB8BB, + 0x8718, 0xBB6A, 0x8719, 0xE3DD, 0x871A, 0xE3F2, 0x871B, 0xE3DE, 0x871C, 0xBB65, 0x871E, 0xE3DB, 0x8720, 0xE3E4, 0x8721, 0xE3DC, + 0x8722, 0xBB67, 0x8723, 0xE3D6, 0x8724, 0xE3F1, 0x8725, 0xBB68, 0x8726, 0xE3EE, 0x8727, 0xE3EF, 0x8728, 0xE3D7, 0x8729, 0xBB6D, + 0x872A, 0xE3E6, 0x872C, 0xE3E0, 0x872D, 0xE3E7, 0x872E, 0xE3DA, 0x8730, 0xE3F3, 0x8731, 0xE3EB, 0x8732, 0xE3E5, 0x8733, 0xE3D5, + 0x8734, 0xBB69, 0x8735, 0xE3EC, 0x8737, 0xBB6C, 0x8738, 0xE3F0, 0x873A, 0xE3EA, 0x873B, 0xBB66, 0x873C, 0xE3E8, 0x873E, 0xE3E2, + 0x873F, 0xBB64, 0x8740, 0xE3D9, 0x8741, 0xE3E1, 0x8742, 0xE3ED, 0x8743, 0xE3DF, 0x8746, 0xE3E3, 0x874C, 0xBDC1, 0x874D, 0xDFE9, + 0x874E, 0xE7B2, 0x874F, 0xE7BB, 0x8750, 0xE7B1, 0x8751, 0xE7AD, 0x8752, 0xE7AA, 0x8753, 0xBDC2, 0x8754, 0xE7A8, 0x8755, 0xBB6B, + 0x8756, 0xE7A1, 0x8757, 0xBDC0, 0x8758, 0xE7A7, 0x8759, 0xBDBF, 0x875A, 0xE7AC, 0x875B, 0xE7A9, 0x875C, 0xE7B9, 0x875D, 0xE7B4, + 0x875E, 0xE7AE, 0x875F, 0xE7B3, 0x8760, 0xBDBB, 0x8761, 0xE7AB, 0x8762, 0xE7BE, 0x8763, 0xE7A2, 0x8764, 0xE7A3, 0x8765, 0xE7BA, + 0x8766, 0xBDBC, 0x8767, 0xE7BF, 0x8768, 0xBDBE, 0x8769, 0xE7C0, 0x876A, 0xE7B0, 0x876B, 0xE3D8, 0x876C, 0xE7B6, 0x876D, 0xE7AF, + 0x876E, 0xE7B8, 0x876F, 0xE7B5, 0x8773, 0xE7A6, 0x8774, 0xBDB9, 0x8775, 0xE7BD, 0x8776, 0xBDBA, 0x8777, 0xE7A4, 0x8778, 0xBDBD, + 0x8779, 0xEB64, 0x877A, 0xE7B7, 0x877B, 0xE7BC, 0x8781, 0xEB61, 0x8782, 0xBDB8, 0x8783, 0xBFC0, 0x8784, 0xEB6B, 0x8785, 0xEB67, + 0x8787, 0xEB65, 0x8788, 0xEB60, 0x8789, 0xEB6F, 0x878D, 0xBFC4, 0x878F, 0xEB5C, 0x8790, 0xEB68, 0x8791, 0xEB69, 0x8792, 0xEB5F, + 0x8793, 0xEB5E, 0x8794, 0xEB6C, 0x8796, 0xEB62, 0x8797, 0xEB5D, 0x8798, 0xEB63, 0x879A, 0xEB6E, 0x879B, 0xEB5B, 0x879C, 0xEB6D, + 0x879D, 0xEB6A, 0x879E, 0xBFC2, 0x879F, 0xBFC1, 0x87A2, 0xBFC3, 0x87A3, 0xEB66, 0x87A4, 0xF0CB, 0x87AA, 0xEE59, 0x87AB, 0xC1B1, + 0x87AC, 0xEE5D, 0x87AD, 0xEE5A, 0x87AE, 0xEE61, 0x87AF, 0xEE67, 0x87B0, 0xEE5C, 0x87B2, 0xEE70, 0x87B3, 0xC1AE, 0x87B4, 0xEE6A, + 0x87B5, 0xEE5F, 0x87B6, 0xEE6B, 0x87B7, 0xEE66, 0x87B8, 0xEE6D, 0x87B9, 0xEE5E, 0x87BA, 0xC1B3, 0x87BB, 0xC1B2, 0x87BC, 0xEE60, + 0x87BD, 0xEE6E, 0x87BE, 0xEE58, 0x87BF, 0xEE6C, 0x87C0, 0xC1AC, 0x87C2, 0xEE64, 0x87C3, 0xEE63, 0x87C4, 0xEE68, 0x87C5, 0xEE5B, + 0x87C6, 0xC1B0, 0x87C8, 0xC1B4, 0x87C9, 0xEE62, 0x87CA, 0xEE69, 0x87CB, 0xC1B5, 0x87CC, 0xEE65, 0x87D1, 0xC1AD, 0x87D2, 0xC1AF, + 0x87D3, 0xF0C7, 0x87D4, 0xF0C5, 0x87D7, 0xF0CC, 0x87D8, 0xF0C9, 0x87D9, 0xF0CD, 0x87DB, 0xF0BE, 0x87DC, 0xF0C6, 0x87DD, 0xF0D1, + 0x87DE, 0xEE6F, 0x87DF, 0xF0C2, 0x87E0, 0xC2CF, 0x87E1, 0xE7A5, 0x87E2, 0xF0BD, 0x87E3, 0xF0CA, 0x87E4, 0xF0C4, 0x87E5, 0xF0C1, + 0x87E6, 0xF0BC, 0x87E7, 0xF0BB, 0x87E8, 0xF0D0, 0x87EA, 0xF0C0, 0x87EB, 0xF0BF, 0x87EC, 0xC2CD, 0x87ED, 0xF0C8, 0x87EF, 0xC2CC, + 0x87F2, 0xC2CE, 0x87F3, 0xF0C3, 0x87F4, 0xF0CF, 0x87F6, 0xF2DE, 0x87F7, 0xF2DF, 0x87F9, 0xC3C9, 0x87FA, 0xF2DC, 0x87FB, 0xC3C6, + 0x87FC, 0xF2E4, 0x87FE, 0xC3CA, 0x87FF, 0xF2E6, 0x8800, 0xF2DB, 0x8801, 0xF0CE, 0x8802, 0xF2E8, 0x8803, 0xF2DD, 0x8805, 0xC3C7, + 0x8806, 0xF2E3, 0x8808, 0xF2E5, 0x8809, 0xF2E0, 0x880A, 0xF2E7, 0x880B, 0xF2E2, 0x880C, 0xF2E1, 0x880D, 0xC3C8, 0x8810, 0xF4C5, + 0x8811, 0xF4C6, 0x8813, 0xF4C8, 0x8814, 0xC4AE, 0x8815, 0xC4AF, 0x8816, 0xF4C9, 0x8817, 0xF4C7, 0x8819, 0xF4C4, 0x881B, 0xF642, + 0x881C, 0xF645, 0x881D, 0xF641, 0x881F, 0xC4FA, 0x8820, 0xF643, 0x8821, 0xC4F9, 0x8822, 0xC4F8, 0x8823, 0xC4F7, 0x8824, 0xF644, + 0x8825, 0xF751, 0x8826, 0xF74F, 0x8828, 0xF74E, 0x8829, 0xF640, 0x882A, 0xF750, 0x882B, 0xF646, 0x882C, 0xF74D, 0x882E, 0xF7F9, + 0x882F, 0xF7D7, 0x8830, 0xF7F7, 0x8831, 0xC5DB, 0x8832, 0xF7F8, 0x8833, 0xF7FA, 0x8835, 0xF8BF, 0x8836, 0xC5FA, 0x8837, 0xF8BE, + 0x8838, 0xF8BD, 0x8839, 0xC5FB, 0x883B, 0xC65A, 0x883C, 0xF96E, 0x883D, 0xF9A7, 0x883E, 0xF9A6, 0x883F, 0xF9A8, 0x8840, 0xA6E5, + 0x8841, 0xD0AA, 0x8843, 0xD3CF, 0x8844, 0xD3D0, 0x8848, 0xDBC0, 0x884A, 0xF647, 0x884B, 0xF8C0, 0x884C, 0xA6E6, 0x884D, 0xAD6C, + 0x884E, 0xD0AB, 0x8852, 0xD7B1, 0x8853, 0xB34E, 0x8855, 0xDBC2, 0x8856, 0xDBC1, 0x8857, 0xB5F3, 0x8859, 0xB8C5, 0x885A, 0xE7C1, + 0x885B, 0xBDC3, 0x885D, 0xBDC4, 0x8861, 0xBFC5, 0x8862, 0xC5FC, 0x8863, 0xA6E7, 0x8867, 0xD0AC, 0x8868, 0xAAED, 0x8869, 0xD0AE, + 0x886A, 0xD0AD, 0x886B, 0xAD6D, 0x886D, 0xD3D1, 0x886F, 0xD3D8, 0x8870, 0xB049, 0x8871, 0xD3D6, 0x8872, 0xD3D4, 0x8874, 0xD3DB, + 0x8875, 0xD3D2, 0x8876, 0xD3D3, 0x8877, 0xB04A, 0x8879, 0xB04E, 0x887C, 0xD3DC, 0x887D, 0xB04D, 0x887E, 0xD3DA, 0x887F, 0xD3D7, + 0x8880, 0xD3D5, 0x8881, 0xB04B, 0x8882, 0xB04C, 0x8883, 0xD3D9, 0x8888, 0xB350, 0x8889, 0xD7B2, 0x888B, 0xB355, 0x888C, 0xD7C2, + 0x888D, 0xB354, 0x888E, 0xD7C4, 0x8891, 0xD7B8, 0x8892, 0xB352, 0x8893, 0xD7C3, 0x8895, 0xD7B3, 0x8896, 0xB353, 0x8897, 0xD7BF, + 0x8898, 0xD7BB, 0x8899, 0xD7BD, 0x889A, 0xD7B7, 0x889B, 0xD7BE, 0x889E, 0xB34F, 0x889F, 0xD7BA, 0x88A1, 0xD7B9, 0x88A2, 0xD7B5, + 0x88A4, 0xD7C0, 0x88A7, 0xD7BC, 0x88A8, 0xD7B4, 0x88AA, 0xD7B6, 0x88AB, 0xB351, 0x88AC, 0xD7C1, 0x88B1, 0xB5F6, 0x88B2, 0xDBCD, + 0x88B6, 0xDBC9, 0x88B7, 0xDBCB, 0x88B8, 0xDBC6, 0x88B9, 0xDBC5, 0x88BA, 0xDBC3, 0x88BC, 0xDBCA, 0x88BD, 0xDBCC, 0x88BE, 0xDBC8, + 0x88C0, 0xDBC7, 0x88C1, 0xB5F4, 0x88C2, 0xB5F5, 0x88C9, 0xDBCF, 0x88CA, 0xB8CD, 0x88CB, 0xDFF2, 0x88CC, 0xDFF8, 0x88CD, 0xDFF3, + 0x88CE, 0xDFF4, 0x88CF, 0xF9D8, 0x88D0, 0xDFF9, 0x88D2, 0xB8CF, 0x88D4, 0xB8C7, 0x88D5, 0xB8CE, 0x88D6, 0xDFF1, 0x88D7, 0xDBC4, + 0x88D8, 0xB8CA, 0x88D9, 0xB8C8, 0x88DA, 0xDFF7, 0x88DB, 0xDFF6, 0x88DC, 0xB8C9, 0x88DD, 0xB8CB, 0x88DE, 0xDFF5, 0x88DF, 0xB8C6, + 0x88E1, 0xB8CC, 0x88E7, 0xE3F6, 0x88E8, 0xBB74, 0x88EB, 0xE442, 0x88EC, 0xE441, 0x88EE, 0xE3FB, 0x88EF, 0xBB76, 0x88F0, 0xE440, + 0x88F1, 0xE3F7, 0x88F2, 0xE3F8, 0x88F3, 0xBB6E, 0x88F4, 0xBB70, 0x88F6, 0xE3FD, 0x88F7, 0xE3F5, 0x88F8, 0xBB72, 0x88F9, 0xBB71, + 0x88FA, 0xE3F9, 0x88FB, 0xE3FE, 0x88FC, 0xE3FC, 0x88FD, 0xBB73, 0x88FE, 0xE3FA, 0x8901, 0xDBCE, 0x8902, 0xBB6F, 0x8905, 0xE7C2, + 0x8906, 0xE7C9, 0x8907, 0xBDC6, 0x8909, 0xE7CD, 0x890A, 0xBDCA, 0x890B, 0xE7C5, 0x890C, 0xE7C3, 0x890E, 0xE7CC, 0x8910, 0xBDC5, + 0x8911, 0xE7CB, 0x8912, 0xBDC7, 0x8913, 0xBDC8, 0x8914, 0xE7C4, 0x8915, 0xBDC9, 0x8916, 0xE7CA, 0x8917, 0xE7C6, 0x8918, 0xE7C7, + 0x8919, 0xE7C8, 0x891A, 0xBB75, 0x891E, 0xEB70, 0x891F, 0xEB7C, 0x8921, 0xBFCA, 0x8922, 0xEB77, 0x8923, 0xEB79, 0x8925, 0xBFC8, + 0x8926, 0xEB71, 0x8927, 0xEB75, 0x8929, 0xEB78, 0x892A, 0xBFC6, 0x892B, 0xBFC9, 0x892C, 0xEB7B, 0x892D, 0xEB73, 0x892E, 0xEB74, + 0x892F, 0xEB7A, 0x8930, 0xEB72, 0x8931, 0xEB76, 0x8932, 0xBFC7, 0x8933, 0xEE72, 0x8935, 0xEE71, 0x8936, 0xC1B7, 0x8937, 0xEE77, + 0x8938, 0xC1B9, 0x893B, 0xC1B6, 0x893C, 0xEE73, 0x893D, 0xC1BA, 0x893E, 0xEE74, 0x8941, 0xEE75, 0x8942, 0xEE78, 0x8944, 0xC1B8, + 0x8946, 0xF0D6, 0x8949, 0xF0D9, 0x894B, 0xF0D3, 0x894C, 0xF0D5, 0x894F, 0xF0D4, 0x8950, 0xF0D7, 0x8951, 0xF0D8, 0x8952, 0xEE76, + 0x8953, 0xF0D2, 0x8956, 0xC3CD, 0x8957, 0xF2EC, 0x8958, 0xF2EF, 0x8959, 0xF2F1, 0x895A, 0xF2EA, 0x895B, 0xF2EB, 0x895C, 0xF2EE, + 0x895D, 0xF2F0, 0x895E, 0xC3CE, 0x895F, 0xC3CC, 0x8960, 0xC3CB, 0x8961, 0xF2ED, 0x8962, 0xF2E9, 0x8963, 0xF4CA, 0x8964, 0xC4B0, + 0x8966, 0xF4CB, 0x8969, 0xF649, 0x896A, 0xC4FB, 0x896B, 0xF64B, 0x896C, 0xC4FC, 0x896D, 0xF648, 0x896E, 0xF64A, 0x896F, 0xC5A8, + 0x8971, 0xF752, 0x8972, 0xC5A7, 0x8973, 0xF7FD, 0x8974, 0xF7FC, 0x8976, 0xF7FB, 0x8979, 0xF948, 0x897A, 0xF949, 0x897B, 0xF94B, + 0x897C, 0xF94A, 0x897E, 0xCA50, 0x897F, 0xA6E8, 0x8981, 0xAD6E, 0x8982, 0xD7C5, 0x8983, 0xB5F7, 0x8985, 0xDFFA, 0x8986, 0xC2D0, + 0x8988, 0xF2F2, 0x898B, 0xA8A3, 0x898F, 0xB357, 0x8993, 0xB356, 0x8995, 0xDBD0, 0x8996, 0xB5F8, 0x8997, 0xDBD2, 0x8998, 0xDBD1, + 0x899B, 0xDFFB, 0x899C, 0xB8D0, 0x899D, 0xE443, 0x899E, 0xE446, 0x899F, 0xE445, 0x89A1, 0xE444, 0x89A2, 0xE7CE, 0x89A3, 0xE7D0, + 0x89A4, 0xE7CF, 0x89A6, 0xBFCC, 0x89AA, 0xBFCB, 0x89AC, 0xC1BB, 0x89AD, 0xEE79, 0x89AE, 0xEE7B, 0x89AF, 0xEE7A, 0x89B2, 0xC2D1, + 0x89B6, 0xF2F4, 0x89B7, 0xF2F3, 0x89B9, 0xF4CC, 0x89BA, 0xC4B1, 0x89BD, 0xC4FD, 0x89BE, 0xF754, 0x89BF, 0xF753, 0x89C0, 0xC65B, + 0x89D2, 0xA8A4, 0x89D3, 0xD0AF, 0x89D4, 0xAD6F, 0x89D5, 0xD7C8, 0x89D6, 0xD7C6, 0x89D9, 0xD7C7, 0x89DA, 0xDBD4, 0x89DB, 0xDBD5, + 0x89DC, 0xE043, 0x89DD, 0xDBD3, 0x89DF, 0xDFFC, 0x89E0, 0xE041, 0x89E1, 0xE040, 0x89E2, 0xE042, 0x89E3, 0xB8D1, 0x89E4, 0xDFFE, + 0x89E5, 0xDFFD, 0x89E6, 0xE044, 0x89E8, 0xE449, 0x89E9, 0xE447, 0x89EB, 0xE448, 0x89EC, 0xE7D3, 0x89ED, 0xE7D1, 0x89F0, 0xE7D2, + 0x89F1, 0xEB7D, 0x89F2, 0xEE7C, 0x89F3, 0xEE7D, 0x89F4, 0xC2D2, 0x89F6, 0xF2F5, 0x89F7, 0xF4CD, 0x89F8, 0xC4B2, 0x89FA, 0xF64C, + 0x89FB, 0xF755, 0x89FC, 0xC5A9, 0x89FE, 0xF7FE, 0x89FF, 0xF94C, 0x8A00, 0xA8A5, 0x8A02, 0xAD71, 0x8A03, 0xAD72, 0x8A04, 0xD0B0, + 0x8A07, 0xD0B1, 0x8A08, 0xAD70, 0x8A0A, 0xB054, 0x8A0C, 0xB052, 0x8A0E, 0xB051, 0x8A0F, 0xB058, 0x8A10, 0xB050, 0x8A11, 0xB059, + 0x8A12, 0xD3DD, 0x8A13, 0xB056, 0x8A15, 0xB053, 0x8A16, 0xB057, 0x8A17, 0xB055, 0x8A18, 0xB04F, 0x8A1B, 0xB35F, 0x8A1D, 0xB359, + 0x8A1E, 0xD7CC, 0x8A1F, 0xB35E, 0x8A22, 0xB360, 0x8A23, 0xB35A, 0x8A25, 0xB35B, 0x8A27, 0xD7CA, 0x8A2A, 0xB358, 0x8A2C, 0xD7CB, + 0x8A2D, 0xB35D, 0x8A30, 0xD7C9, 0x8A31, 0xB35C, 0x8A34, 0xB644, 0x8A36, 0xB646, 0x8A39, 0xDBD8, 0x8A3A, 0xB645, 0x8A3B, 0xB5F9, + 0x8A3C, 0xB5FD, 0x8A3E, 0xB8E4, 0x8A3F, 0xE049, 0x8A40, 0xDBDA, 0x8A41, 0xB5FE, 0x8A44, 0xDBDD, 0x8A45, 0xDBDE, 0x8A46, 0xB643, + 0x8A48, 0xDBE0, 0x8A4A, 0xDBE2, 0x8A4C, 0xDBE3, 0x8A4D, 0xDBD7, 0x8A4E, 0xDBD6, 0x8A4F, 0xDBE4, 0x8A50, 0xB642, 0x8A51, 0xDBE1, + 0x8A52, 0xDBDF, 0x8A54, 0xB640, 0x8A55, 0xB5FB, 0x8A56, 0xB647, 0x8A57, 0xDBDB, 0x8A58, 0xDBDC, 0x8A59, 0xDBD9, 0x8A5B, 0xB641, + 0x8A5E, 0xB5FC, 0x8A60, 0xB5FA, 0x8A61, 0xE048, 0x8A62, 0xB8DF, 0x8A63, 0xB8DA, 0x8A66, 0xB8D5, 0x8A68, 0xB8E5, 0x8A69, 0xB8D6, + 0x8A6B, 0xB8D2, 0x8A6C, 0xB8E1, 0x8A6D, 0xB8DE, 0x8A6E, 0xB8E0, 0x8A70, 0xB8D7, 0x8A71, 0xB8DC, 0x8A72, 0xB8D3, 0x8A73, 0xB8D4, + 0x8A74, 0xE050, 0x8A75, 0xE04D, 0x8A76, 0xE045, 0x8A77, 0xE04A, 0x8A79, 0xB8E2, 0x8A7A, 0xE051, 0x8A7B, 0xB8E3, 0x8A7C, 0xB8D9, + 0x8A7F, 0xE047, 0x8A81, 0xE04F, 0x8A82, 0xE04B, 0x8A83, 0xE04E, 0x8A84, 0xE04C, 0x8A85, 0xB8DD, 0x8A86, 0xE046, 0x8A87, 0xB8D8, + 0x8A8B, 0xE44C, 0x8A8C, 0xBB78, 0x8A8D, 0xBB7B, 0x8A8F, 0xE44E, 0x8A91, 0xBBA5, 0x8A92, 0xE44D, 0x8A93, 0xBB7D, 0x8A95, 0xBDCF, + 0x8A96, 0xE44F, 0x8A98, 0xBBA4, 0x8A99, 0xE44B, 0x8A9A, 0xBBA6, 0x8A9E, 0xBB79, 0x8AA0, 0xB8DB, 0x8AA1, 0xBB7C, 0x8AA3, 0xBB7A, + 0x8AA4, 0xBB7E, 0x8AA5, 0xBBA2, 0x8AA6, 0xBB77, 0x8AA7, 0xBBA7, 0x8AA8, 0xBBA3, 0x8AAA, 0xBBA1, 0x8AAB, 0xE44A, 0x8AB0, 0xBDD6, + 0x8AB2, 0xBDD2, 0x8AB6, 0xBDD9, 0x8AB8, 0xE7D6, 0x8AB9, 0xBDDA, 0x8ABA, 0xE7E2, 0x8ABB, 0xE7DB, 0x8ABC, 0xBDCB, 0x8ABD, 0xE7E3, + 0x8ABE, 0xE7DD, 0x8ABF, 0xBDD5, 0x8AC0, 0xE7DE, 0x8AC2, 0xBDD4, 0x8AC3, 0xE7E1, 0x8AC4, 0xBDCE, 0x8AC5, 0xE7DF, 0x8AC6, 0xE7D5, + 0x8AC7, 0xBDCD, 0x8AC8, 0xEBAA, 0x8AC9, 0xBDD3, 0x8ACB, 0xBDD0, 0x8ACD, 0xBDD8, 0x8ACF, 0xE7D4, 0x8AD1, 0xE7D8, 0x8AD2, 0xBDCC, + 0x8AD3, 0xE7D7, 0x8AD4, 0xE7D9, 0x8AD5, 0xE7DA, 0x8AD6, 0xBDD7, 0x8AD7, 0xE7DC, 0x8AD8, 0xE7E0, 0x8AD9, 0xE7E4, 0x8ADB, 0xBDDB, + 0x8ADC, 0xBFD2, 0x8ADD, 0xEBA5, 0x8ADE, 0xEBAB, 0x8ADF, 0xEBA8, 0x8AE0, 0xEB7E, 0x8AE1, 0xEBAC, 0x8AE2, 0xEBA1, 0x8AE4, 0xEBA7, + 0x8AE6, 0xBFCD, 0x8AE7, 0xBFD3, 0x8AE8, 0xEBAD, 0x8AEB, 0xBFCF, 0x8AED, 0xBFD9, 0x8AEE, 0xBFD4, 0x8AEF, 0xEBAF, 0x8AF0, 0xEBA9, + 0x8AF1, 0xBFD0, 0x8AF2, 0xEBA2, 0x8AF3, 0xBFDA, 0x8AF4, 0xEBA3, 0x8AF5, 0xEBA4, 0x8AF6, 0xBFDB, 0x8AF7, 0xBFD8, 0x8AF8, 0xBDD1, + 0x8AFA, 0xBFCE, 0x8AFB, 0xEBB0, 0x8AFC, 0xBFDC, 0x8AFE, 0xBFD5, 0x8AFF, 0xEBAE, 0x8B00, 0xBFD1, 0x8B01, 0xBFD6, 0x8B02, 0xBFD7, + 0x8B04, 0xC1C3, 0x8B05, 0xEEA4, 0x8B06, 0xEEAD, 0x8B07, 0xEEAA, 0x8B08, 0xEEAC, 0x8B0A, 0xC1C0, 0x8B0B, 0xEEA5, 0x8B0D, 0xEEAB, + 0x8B0E, 0xC1BC, 0x8B0F, 0xEEA7, 0x8B10, 0xC1C4, 0x8B11, 0xEEA3, 0x8B12, 0xEEA8, 0x8B13, 0xEEAF, 0x8B14, 0xEBA6, 0x8B15, 0xEEA9, + 0x8B16, 0xEEA2, 0x8B17, 0xC1BD, 0x8B18, 0xEEA1, 0x8B19, 0xC1BE, 0x8B1A, 0xEEB0, 0x8B1B, 0xC1BF, 0x8B1C, 0xEEAE, 0x8B1D, 0xC1C2, + 0x8B1E, 0xEE7E, 0x8B20, 0xC1C1, 0x8B22, 0xEEA6, 0x8B23, 0xF0DC, 0x8B24, 0xF0EA, 0x8B25, 0xF0E5, 0x8B26, 0xF0E7, 0x8B27, 0xF0DB, + 0x8B28, 0xC2D3, 0x8B2A, 0xF0DA, 0x8B2B, 0xC2D6, 0x8B2C, 0xC2D5, 0x8B2E, 0xF0E9, 0x8B2F, 0xF0E1, 0x8B30, 0xF0DE, 0x8B31, 0xF0E4, + 0x8B33, 0xF0DD, 0x8B35, 0xF0DF, 0x8B36, 0xF0E8, 0x8B37, 0xF0E6, 0x8B39, 0xC2D4, 0x8B3A, 0xF0ED, 0x8B3B, 0xF0EB, 0x8B3C, 0xF0E2, + 0x8B3D, 0xF0EC, 0x8B3E, 0xF0E3, 0x8B40, 0xF2F9, 0x8B41, 0xC3CF, 0x8B42, 0xF341, 0x8B45, 0xF64F, 0x8B46, 0xC3D6, 0x8B47, 0xF0E0, + 0x8B48, 0xF2F7, 0x8B49, 0xC3D2, 0x8B4A, 0xF2F8, 0x8B4B, 0xF2FD, 0x8B4E, 0xC3D4, 0x8B4F, 0xC3D5, 0x8B50, 0xF2F6, 0x8B51, 0xF340, + 0x8B52, 0xF342, 0x8B53, 0xF2FA, 0x8B54, 0xF2FC, 0x8B55, 0xF2FE, 0x8B56, 0xF2FB, 0x8B57, 0xF343, 0x8B58, 0xC3D1, 0x8B59, 0xC3D7, + 0x8B5A, 0xC3D3, 0x8B5C, 0xC3D0, 0x8B5D, 0xF4D0, 0x8B5F, 0xC4B7, 0x8B60, 0xF4CE, 0x8B63, 0xF4D2, 0x8B65, 0xF4D3, 0x8B66, 0xC4B5, + 0x8B67, 0xF4D4, 0x8B68, 0xF4D1, 0x8B6A, 0xF4CF, 0x8B6B, 0xC4B8, 0x8B6C, 0xC4B4, 0x8B6D, 0xF4D5, 0x8B6F, 0xC4B6, 0x8B70, 0xC4B3, + 0x8B74, 0xC4FE, 0x8B77, 0xC540, 0x8B78, 0xF64E, 0x8B79, 0xF64D, 0x8B7A, 0xF650, 0x8B7B, 0xF651, 0x8B7D, 0xC541, 0x8B7E, 0xF756, + 0x8B7F, 0xF75B, 0x8B80, 0xC5AA, 0x8B82, 0xF758, 0x8B84, 0xF757, 0x8B85, 0xF75A, 0x8B86, 0xF759, 0x8B88, 0xF843, 0x8B8A, 0xC5DC, + 0x8B8B, 0xF842, 0x8B8C, 0xF840, 0x8B8E, 0xF841, 0x8B92, 0xC5FE, 0x8B93, 0xC5FD, 0x8B94, 0xF8C1, 0x8B95, 0xF8C2, 0x8B96, 0xC640, + 0x8B98, 0xF94D, 0x8B99, 0xF94E, 0x8B9A, 0xC667, 0x8B9C, 0xC66D, 0x8B9E, 0xF9A9, 0x8B9F, 0xF9C8, 0x8C37, 0xA8A6, 0x8C39, 0xD7CD, + 0x8C3B, 0xD7CE, 0x8C3C, 0xE052, 0x8C3D, 0xE450, 0x8C3E, 0xE7E5, 0x8C3F, 0xC1C6, 0x8C41, 0xC1C5, 0x8C42, 0xF0EE, 0x8C43, 0xF344, + 0x8C45, 0xF844, 0x8C46, 0xA8A7, 0x8C47, 0xD3DE, 0x8C48, 0xB05A, 0x8C49, 0xB361, 0x8C4A, 0xE054, 0x8C4B, 0xE053, 0x8C4C, 0xBDDC, + 0x8C4D, 0xE7E6, 0x8C4E, 0xBDDD, 0x8C4F, 0xEEB1, 0x8C50, 0xC2D7, 0x8C54, 0xC676, 0x8C55, 0xA8A8, 0x8C56, 0xCDCB, 0x8C57, 0xD3DF, + 0x8C5A, 0xB362, 0x8C5C, 0xD7CF, 0x8C5D, 0xD7D0, 0x8C5F, 0xDBE5, 0x8C61, 0xB648, 0x8C62, 0xB8E6, 0x8C64, 0xE056, 0x8C65, 0xE055, + 0x8C66, 0xE057, 0x8C68, 0xE451, 0x8C69, 0xE452, 0x8C6A, 0xBBA8, 0x8C6B, 0xBFDD, 0x8C6C, 0xBDDE, 0x8C6D, 0xBFDE, 0x8C6F, 0xEEB5, + 0x8C70, 0xEEB2, 0x8C71, 0xEEB4, 0x8C72, 0xEEB3, 0x8C73, 0xC1C7, 0x8C75, 0xF0EF, 0x8C76, 0xF346, 0x8C77, 0xF345, 0x8C78, 0xCBA4, + 0x8C79, 0xB05C, 0x8C7A, 0xB05B, 0x8C7B, 0xD3E0, 0x8C7D, 0xD7D1, 0x8C80, 0xDBE7, 0x8C81, 0xDBE6, 0x8C82, 0xB649, 0x8C84, 0xE059, + 0x8C85, 0xE05A, 0x8C86, 0xE058, 0x8C89, 0xB8E8, 0x8C8A, 0xB8E7, 0x8C8C, 0xBBAA, 0x8C8D, 0xBBA9, 0x8C8F, 0xE7E7, 0x8C90, 0xEBB3, + 0x8C91, 0xEBB1, 0x8C92, 0xEBB2, 0x8C93, 0xBFDF, 0x8C94, 0xEEB7, 0x8C95, 0xEEB6, 0x8C97, 0xF0F2, 0x8C98, 0xF0F1, 0x8C99, 0xF0F0, + 0x8C9A, 0xF347, 0x8C9C, 0xF9AA, 0x8C9D, 0xA8A9, 0x8C9E, 0xAD73, 0x8CA0, 0xAD74, 0x8CA1, 0xB05D, 0x8CA2, 0xB05E, 0x8CA3, 0xD3E2, + 0x8CA4, 0xD3E1, 0x8CA5, 0xD7D2, 0x8CA7, 0xB368, 0x8CA8, 0xB366, 0x8CA9, 0xB363, 0x8CAA, 0xB367, 0x8CAB, 0xB365, 0x8CAC, 0xB364, + 0x8CAF, 0xB64A, 0x8CB0, 0xDBEA, 0x8CB2, 0xB8ED, 0x8CB3, 0xB64C, 0x8CB4, 0xB651, 0x8CB5, 0xDBEC, 0x8CB6, 0xB653, 0x8CB7, 0xB652, + 0x8CB8, 0xB655, 0x8CB9, 0xDBEB, 0x8CBA, 0xDBE8, 0x8CBB, 0xB64F, 0x8CBC, 0xB64B, 0x8CBD, 0xB64D, 0x8CBE, 0xDBE9, 0x8CBF, 0xB654, + 0x8CC0, 0xB650, 0x8CC1, 0xB64E, 0x8CC2, 0xB8EF, 0x8CC3, 0xB8EE, 0x8CC4, 0xB8EC, 0x8CC5, 0xB8F0, 0x8CC7, 0xB8EA, 0x8CC8, 0xB8EB, + 0x8CCA, 0xB8E9, 0x8CCC, 0xE05B, 0x8CCF, 0xE454, 0x8CD1, 0xBBAC, 0x8CD2, 0xBBAD, 0x8CD3, 0xBBAB, 0x8CD5, 0xE453, 0x8CD7, 0xE455, + 0x8CD9, 0xE7EA, 0x8CDA, 0xE7EC, 0x8CDC, 0xBDE7, 0x8CDD, 0xE7ED, 0x8CDE, 0xBDE0, 0x8CDF, 0xE7E9, 0x8CE0, 0xBDDF, 0x8CE1, 0xBDE9, + 0x8CE2, 0xBDE5, 0x8CE3, 0xBDE6, 0x8CE4, 0xBDE2, 0x8CE5, 0xE7E8, 0x8CE6, 0xBDE1, 0x8CE7, 0xE7EE, 0x8CE8, 0xE7EB, 0x8CEA, 0xBDE8, + 0x8CEC, 0xBDE3, 0x8CED, 0xBDE4, 0x8CEE, 0xEBB5, 0x8CF0, 0xEBB7, 0x8CF1, 0xEBB6, 0x8CF3, 0xEBB8, 0x8CF4, 0xBFE0, 0x8CF5, 0xEBB4, + 0x8CF8, 0xC1CB, 0x8CF9, 0xEEB8, 0x8CFA, 0xC1C8, 0x8CFB, 0xC1CC, 0x8CFC, 0xC1CA, 0x8CFD, 0xC1C9, 0x8CFE, 0xF0F3, 0x8D00, 0xF0F6, + 0x8D02, 0xF0F5, 0x8D04, 0xF0F4, 0x8D05, 0xC2D8, 0x8D06, 0xF348, 0x8D07, 0xF349, 0x8D08, 0xC3D8, 0x8D09, 0xF34A, 0x8D0A, 0xC3D9, + 0x8D0D, 0xC4BA, 0x8D0F, 0xC4B9, 0x8D10, 0xF652, 0x8D13, 0xC542, 0x8D14, 0xF653, 0x8D15, 0xF75C, 0x8D16, 0xC5AB, 0x8D17, 0xC5AC, + 0x8D19, 0xF845, 0x8D1B, 0xC642, 0x8D64, 0xA8AA, 0x8D66, 0xB36A, 0x8D67, 0xB369, 0x8D68, 0xE05C, 0x8D69, 0xE05D, 0x8D6B, 0xBBAE, + 0x8D6C, 0xEBB9, 0x8D6D, 0xBDEA, 0x8D6E, 0xEBBA, 0x8D6F, 0xEEB9, 0x8D70, 0xA8AB, 0x8D72, 0xD0B2, 0x8D73, 0xAD76, 0x8D74, 0xAD75, + 0x8D76, 0xD3E3, 0x8D77, 0xB05F, 0x8D78, 0xD3E4, 0x8D79, 0xD7D5, 0x8D7B, 0xD7D4, 0x8D7D, 0xD7D3, 0x8D80, 0xDBEE, 0x8D81, 0xB658, + 0x8D84, 0xDBED, 0x8D85, 0xB657, 0x8D89, 0xDBEF, 0x8D8A, 0xB656, 0x8D8C, 0xE05F, 0x8D8D, 0xE062, 0x8D8E, 0xE060, 0x8D8F, 0xE061, + 0x8D90, 0xE065, 0x8D91, 0xE05E, 0x8D92, 0xE066, 0x8D93, 0xE063, 0x8D94, 0xE064, 0x8D95, 0xBBB0, 0x8D96, 0xE456, 0x8D99, 0xBBAF, + 0x8D9B, 0xE7F2, 0x8D9C, 0xE7F0, 0x8D9F, 0xBDEB, 0x8DA0, 0xE7EF, 0x8DA1, 0xE7F1, 0x8DA3, 0xBDEC, 0x8DA5, 0xEBBB, 0x8DA7, 0xEBBC, + 0x8DA8, 0xC1CD, 0x8DAA, 0xF34C, 0x8DAB, 0xF34E, 0x8DAC, 0xF34B, 0x8DAD, 0xF34D, 0x8DAE, 0xF4D6, 0x8DAF, 0xF654, 0x8DB2, 0xF96F, + 0x8DB3, 0xA8AC, 0x8DB4, 0xAD77, 0x8DB5, 0xD3E5, 0x8DB6, 0xD3E7, 0x8DB7, 0xD3E6, 0x8DB9, 0xD7D8, 0x8DBA, 0xB36C, 0x8DBC, 0xD7D6, + 0x8DBE, 0xB36B, 0x8DBF, 0xD7D9, 0x8DC1, 0xD7DA, 0x8DC2, 0xD7D7, 0x8DC5, 0xDBFB, 0x8DC6, 0xB660, 0x8DC7, 0xDBF3, 0x8DC8, 0xDBF9, + 0x8DCB, 0xB65B, 0x8DCC, 0xB65E, 0x8DCD, 0xDBF2, 0x8DCE, 0xB659, 0x8DCF, 0xDBF6, 0x8DD0, 0xE06C, 0x8DD1, 0xB65D, 0x8DD3, 0xDBF1, + 0x8DD5, 0xDBF7, 0x8DD6, 0xDBF4, 0x8DD7, 0xDBFA, 0x8DD8, 0xDBF0, 0x8DD9, 0xDBF8, 0x8DDA, 0xB65C, 0x8DDB, 0xB65F, 0x8DDC, 0xDBF5, + 0x8DDD, 0xB65A, 0x8DDF, 0xB8F2, 0x8DE0, 0xE068, 0x8DE1, 0xB8F1, 0x8DE2, 0xE06F, 0x8DE3, 0xE06E, 0x8DE4, 0xB8F8, 0x8DE6, 0xB8F9, + 0x8DE7, 0xE070, 0x8DE8, 0xB8F3, 0x8DE9, 0xE06D, 0x8DEA, 0xB8F7, 0x8DEB, 0xE072, 0x8DEC, 0xE069, 0x8DEE, 0xE06B, 0x8DEF, 0xB8F4, + 0x8DF0, 0xE067, 0x8DF1, 0xE06A, 0x8DF2, 0xE071, 0x8DF3, 0xB8F5, 0x8DF4, 0xE073, 0x8DFA, 0xB8F6, 0x8DFC, 0xBBB1, 0x8DFD, 0xE45B, + 0x8DFE, 0xE461, 0x8DFF, 0xE459, 0x8E00, 0xE462, 0x8E02, 0xE458, 0x8E03, 0xE45D, 0x8E04, 0xE463, 0x8E05, 0xE460, 0x8E06, 0xE45F, + 0x8E07, 0xE45E, 0x8E09, 0xE457, 0x8E0A, 0xE45C, 0x8E0D, 0xE45A, 0x8E0F, 0xBDF1, 0x8E10, 0xBDEE, 0x8E11, 0xE7FB, 0x8E12, 0xE841, + 0x8E13, 0xE843, 0x8E14, 0xE840, 0x8E15, 0xE7F8, 0x8E16, 0xE7FA, 0x8E17, 0xE845, 0x8E18, 0xE842, 0x8E19, 0xE7FC, 0x8E1A, 0xE846, + 0x8E1B, 0xE7F9, 0x8E1C, 0xE844, 0x8E1D, 0xBDEF, 0x8E1E, 0xBDF5, 0x8E1F, 0xBDF3, 0x8E20, 0xE7F3, 0x8E21, 0xBDF4, 0x8E22, 0xBDF0, + 0x8E23, 0xE7F4, 0x8E24, 0xE7F6, 0x8E25, 0xE7F5, 0x8E26, 0xE7FD, 0x8E27, 0xE7FE, 0x8E29, 0xBDF2, 0x8E2B, 0xBDED, 0x8E2E, 0xE7F7, + 0x8E30, 0xEBC6, 0x8E31, 0xBFE2, 0x8E33, 0xEBBD, 0x8E34, 0xBFE3, 0x8E35, 0xBFE6, 0x8E36, 0xEBC2, 0x8E38, 0xEBBF, 0x8E39, 0xBFE5, + 0x8E3C, 0xEBC3, 0x8E3D, 0xEBC4, 0x8E3E, 0xEBBE, 0x8E3F, 0xEBC7, 0x8E40, 0xEBC0, 0x8E41, 0xEBC5, 0x8E42, 0xBFE4, 0x8E44, 0xBFE1, + 0x8E45, 0xEBC1, 0x8E47, 0xEEBF, 0x8E48, 0xC1D0, 0x8E49, 0xC1CE, 0x8E4A, 0xC1D1, 0x8E4B, 0xC1CF, 0x8E4C, 0xEEBE, 0x8E4D, 0xEEBB, + 0x8E4E, 0xEEBA, 0x8E50, 0xEEBD, 0x8E53, 0xEEBC, 0x8E54, 0xF145, 0x8E55, 0xC2DE, 0x8E56, 0xF0FB, 0x8E57, 0xF0FA, 0x8E59, 0xC2D9, + 0x8E5A, 0xF141, 0x8E5B, 0xF140, 0x8E5C, 0xF0F7, 0x8E5D, 0xF143, 0x8E5E, 0xF0FC, 0x8E5F, 0xC2DD, 0x8E60, 0xF0F9, 0x8E61, 0xF142, + 0x8E62, 0xF0F8, 0x8E63, 0xC2DA, 0x8E64, 0xC2DC, 0x8E65, 0xF0FD, 0x8E66, 0xC2DB, 0x8E67, 0xF0FE, 0x8E69, 0xF144, 0x8E6A, 0xF352, + 0x8E6C, 0xC3DE, 0x8E6D, 0xF34F, 0x8E6F, 0xF353, 0x8E72, 0xC3DB, 0x8E73, 0xF351, 0x8E74, 0xC3E0, 0x8E76, 0xC3DD, 0x8E78, 0xF350, + 0x8E7A, 0xC3DF, 0x8E7B, 0xF354, 0x8E7C, 0xC3DA, 0x8E81, 0xC4BC, 0x8E82, 0xC4BE, 0x8E84, 0xF4D9, 0x8E85, 0xC4BD, 0x8E86, 0xF4D7, + 0x8E87, 0xC3DC, 0x8E88, 0xF4D8, 0x8E89, 0xC4BB, 0x8E8A, 0xC543, 0x8E8B, 0xC545, 0x8E8C, 0xF656, 0x8E8D, 0xC544, 0x8E8E, 0xF655, + 0x8E90, 0xF761, 0x8E91, 0xC5AD, 0x8E92, 0xF760, 0x8E93, 0xC5AE, 0x8E94, 0xF75E, 0x8E95, 0xF75D, 0x8E96, 0xF762, 0x8E97, 0xF763, + 0x8E98, 0xF846, 0x8E9A, 0xF75F, 0x8E9D, 0xF8C6, 0x8E9E, 0xF8C3, 0x8E9F, 0xF8C4, 0x8EA0, 0xF8C5, 0x8EA1, 0xC65C, 0x8EA3, 0xF951, + 0x8EA4, 0xF950, 0x8EA5, 0xF94F, 0x8EA6, 0xF970, 0x8EA8, 0xF9BE, 0x8EA9, 0xF9AB, 0x8EAA, 0xC66E, 0x8EAB, 0xA8AD, 0x8EAC, 0xB060, + 0x8EB2, 0xB8FA, 0x8EBA, 0xBDF6, 0x8EBD, 0xEBC8, 0x8EC0, 0xC2DF, 0x8EC2, 0xF355, 0x8EC9, 0xF9AC, 0x8ECA, 0xA8AE, 0x8ECB, 0xAAEE, + 0x8ECC, 0xAD79, 0x8ECD, 0xAD78, 0x8ECF, 0xB063, 0x8ED1, 0xD3E8, 0x8ED2, 0xB061, 0x8ED3, 0xD3E9, 0x8ED4, 0xB062, 0x8ED7, 0xD7DF, + 0x8ED8, 0xD7DB, 0x8EDB, 0xB36D, 0x8EDC, 0xD7DE, 0x8EDD, 0xD7DD, 0x8EDE, 0xD7DC, 0x8EDF, 0xB36E, 0x8EE0, 0xD7E0, 0x8EE1, 0xD7E1, + 0x8EE5, 0xDC43, 0x8EE6, 0xDC41, 0x8EE7, 0xDC45, 0x8EE8, 0xDC46, 0x8EE9, 0xDC4C, 0x8EEB, 0xDC48, 0x8EEC, 0xDC4A, 0x8EEE, 0xDC42, + 0x8EEF, 0xDBFC, 0x8EF1, 0xDC49, 0x8EF4, 0xDC4B, 0x8EF5, 0xDC44, 0x8EF6, 0xDC47, 0x8EF7, 0xDBFD, 0x8EF8, 0xB662, 0x8EF9, 0xDC40, + 0x8EFA, 0xDBFE, 0x8EFB, 0xB661, 0x8EFC, 0xB663, 0x8EFE, 0xB8FD, 0x8EFF, 0xE075, 0x8F00, 0xE077, 0x8F01, 0xE076, 0x8F02, 0xE07B, + 0x8F03, 0xB8FB, 0x8F05, 0xE078, 0x8F06, 0xE074, 0x8F07, 0xE079, 0x8F08, 0xE07A, 0x8F09, 0xB8FC, 0x8F0A, 0xB8FE, 0x8F0B, 0xE07C, + 0x8F0D, 0xE467, 0x8F0E, 0xE466, 0x8F10, 0xE464, 0x8F11, 0xE465, 0x8F12, 0xBBB3, 0x8F13, 0xBBB5, 0x8F14, 0xBBB2, 0x8F15, 0xBBB4, + 0x8F16, 0xE84D, 0x8F17, 0xE84E, 0x8F18, 0xE849, 0x8F1A, 0xE84A, 0x8F1B, 0xBDF8, 0x8F1C, 0xBDFD, 0x8F1D, 0xBDF7, 0x8F1E, 0xBDFE, + 0x8F1F, 0xBDF9, 0x8F20, 0xE84B, 0x8F23, 0xE84C, 0x8F24, 0xE848, 0x8F25, 0xBE40, 0x8F26, 0xBDFB, 0x8F29, 0xBDFA, 0x8F2A, 0xBDFC, + 0x8F2C, 0xE847, 0x8F2E, 0xEBCA, 0x8F2F, 0xBFE8, 0x8F32, 0xEBCC, 0x8F33, 0xBFEA, 0x8F34, 0xEBCF, 0x8F35, 0xEBCB, 0x8F36, 0xEBC9, + 0x8F37, 0xEBCE, 0x8F38, 0xBFE9, 0x8F39, 0xEBCD, 0x8F3B, 0xBFE7, 0x8F3E, 0xC1D3, 0x8F3F, 0xC1D6, 0x8F40, 0xEEC1, 0x8F42, 0xC1D4, + 0x8F43, 0xEEC0, 0x8F44, 0xC1D2, 0x8F45, 0xC1D5, 0x8F46, 0xF146, 0x8F47, 0xF147, 0x8F48, 0xF148, 0x8F49, 0xC2E0, 0x8F4B, 0xF149, + 0x8F4D, 0xC2E1, 0x8F4E, 0xC3E2, 0x8F4F, 0xF358, 0x8F50, 0xF359, 0x8F51, 0xF357, 0x8F52, 0xF356, 0x8F53, 0xF35A, 0x8F54, 0xC3E1, + 0x8F55, 0xF4DD, 0x8F56, 0xF4DB, 0x8F57, 0xF4DC, 0x8F58, 0xF4DE, 0x8F59, 0xF4DA, 0x8F5A, 0xF4DF, 0x8F5B, 0xF658, 0x8F5D, 0xF659, + 0x8F5E, 0xF657, 0x8F5F, 0xC546, 0x8F60, 0xF764, 0x8F61, 0xC5AF, 0x8F62, 0xF765, 0x8F63, 0xF848, 0x8F64, 0xF847, 0x8F9B, 0xA8AF, + 0x8F9C, 0xB664, 0x8F9F, 0xB940, 0x8FA3, 0xBBB6, 0x8FA6, 0xBFEC, 0x8FA8, 0xBFEB, 0x8FAD, 0xC3E3, 0x8FAE, 0xC47C, 0x8FAF, 0xC547, + 0x8FB0, 0xA8B0, 0x8FB1, 0xB064, 0x8FB2, 0xB941, 0x8FB4, 0xF35B, 0x8FBF, 0xCBA6, 0x8FC2, 0xA8B1, 0x8FC4, 0xA8B4, 0x8FC5, 0xA8B3, + 0x8FC6, 0xA8B2, 0x8FC9, 0xCBA5, 0x8FCB, 0xCDCD, 0x8FCD, 0xCDCF, 0x8FCE, 0xAAEF, 0x8FD1, 0xAAF1, 0x8FD2, 0xCDCC, 0x8FD3, 0xCDCE, + 0x8FD4, 0xAAF0, 0x8FD5, 0xCDD1, 0x8FD6, 0xCDD0, 0x8FD7, 0xCDD2, 0x8FE0, 0xD0B6, 0x8FE1, 0xD0B4, 0x8FE2, 0xAD7C, 0x8FE3, 0xD0B3, + 0x8FE4, 0xADA3, 0x8FE5, 0xAD7E, 0x8FE6, 0xAD7B, 0x8FE8, 0xADA4, 0x8FEA, 0xAD7D, 0x8FEB, 0xADA2, 0x8FED, 0xADA1, 0x8FEE, 0xD0B5, + 0x8FF0, 0xAD7A, 0x8FF4, 0xB06A, 0x8FF5, 0xD3EB, 0x8FF6, 0xD3F1, 0x8FF7, 0xB067, 0x8FF8, 0xB06E, 0x8FFA, 0xB069, 0x8FFB, 0xD3EE, + 0x8FFC, 0xD3F0, 0x8FFD, 0xB06C, 0x8FFE, 0xD3EA, 0x8FFF, 0xD3ED, 0x9000, 0xB068, 0x9001, 0xB065, 0x9002, 0xD3EC, 0x9003, 0xB06B, + 0x9004, 0xD3EF, 0x9005, 0xB06D, 0x9006, 0xB066, 0x900B, 0xD7E3, 0x900C, 0xD7E6, 0x900D, 0xB370, 0x900F, 0xB37A, 0x9010, 0xB376, + 0x9011, 0xD7E4, 0x9014, 0xB37E, 0x9015, 0xB377, 0x9016, 0xB37C, 0x9017, 0xB372, 0x9019, 0xB36F, 0x901A, 0xB371, 0x901B, 0xB37D, + 0x901C, 0xD7E5, 0x901D, 0xB375, 0x901E, 0xB378, 0x901F, 0xB374, 0x9020, 0xB379, 0x9021, 0xD7E7, 0x9022, 0xB37B, 0x9023, 0xB373, + 0x9024, 0xD7E2, 0x902D, 0xDC4D, 0x902E, 0xB665, 0x902F, 0xDC4F, 0x9031, 0xB667, 0x9032, 0xB669, 0x9034, 0xDC4E, 0x9035, 0xB666, + 0x9036, 0xB66A, 0x9038, 0xB668, 0x903C, 0xB947, 0x903D, 0xE0A3, 0x903E, 0xB94F, 0x903F, 0xE07E, 0x9041, 0xB950, 0x9042, 0xB945, + 0x9044, 0xE0A1, 0x9047, 0xB94A, 0x9049, 0xE0A2, 0x904A, 0xB943, 0x904B, 0xB942, 0x904D, 0xB94D, 0x904E, 0xB94C, 0x904F, 0xB94B, + 0x9050, 0xB949, 0x9051, 0xB94E, 0x9052, 0xE07D, 0x9053, 0xB944, 0x9054, 0xB946, 0x9055, 0xB948, 0x9058, 0xBBB8, 0x9059, 0xBBBB, + 0x905B, 0xBBBF, 0x905C, 0xBBB9, 0x905D, 0xBBBE, 0x905E, 0xBBBC, 0x9060, 0xBBB7, 0x9062, 0xBBBD, 0x9063, 0xBBBA, 0x9067, 0xE852, + 0x9068, 0xBE43, 0x9069, 0xBE41, 0x906B, 0xE853, 0x906D, 0xBE44, 0x906E, 0xBE42, 0x906F, 0xE851, 0x9070, 0xE850, 0x9072, 0xBFF0, + 0x9073, 0xE84F, 0x9074, 0xBFEE, 0x9075, 0xBFED, 0x9076, 0xEBD0, 0x9077, 0xBE45, 0x9078, 0xBFEF, 0x9079, 0xEBD1, 0x907A, 0xBFF2, + 0x907B, 0xEBD2, 0x907C, 0xBFF1, 0x907D, 0xC1D8, 0x907E, 0xEEC3, 0x907F, 0xC1D7, 0x9080, 0xC1DC, 0x9081, 0xC1DA, 0x9082, 0xC1DB, + 0x9083, 0xC2E3, 0x9084, 0xC1D9, 0x9085, 0xEEC2, 0x9086, 0xEBD3, 0x9087, 0xC2E2, 0x9088, 0xC2E4, 0x908A, 0xC3E4, 0x908B, 0xC3E5, + 0x908D, 0xF4E0, 0x908F, 0xC5DE, 0x9090, 0xC5DD, 0x9091, 0xA8B6, 0x9094, 0xCA55, 0x9095, 0xB06F, 0x9097, 0xCA52, 0x9098, 0xCA53, + 0x9099, 0xCA51, 0x909B, 0xCA54, 0x909E, 0xCBAA, 0x909F, 0xCBA7, 0x90A0, 0xCBAC, 0x90A1, 0xCBA8, 0x90A2, 0xA8B7, 0x90A3, 0xA8BA, + 0x90A5, 0xCBA9, 0x90A6, 0xA8B9, 0x90A7, 0xCBAB, 0x90AA, 0xA8B8, 0x90AF, 0xCDD5, 0x90B0, 0xCDD7, 0x90B1, 0xAAF4, 0x90B2, 0xCDD3, + 0x90B3, 0xCDD6, 0x90B4, 0xCDD4, 0x90B5, 0xAAF2, 0x90B6, 0xAAF5, 0x90B8, 0xAAF3, 0x90BD, 0xD0B8, 0x90BE, 0xD0BC, 0x90BF, 0xD0B9, + 0x90C1, 0xADA7, 0x90C3, 0xADA8, 0x90C5, 0xD0BB, 0x90C7, 0xD0BD, 0x90C8, 0xD0BF, 0x90CA, 0xADA5, 0x90CB, 0xD0BE, 0x90CE, 0xADA6, + 0x90D4, 0xD7EE, 0x90D5, 0xD0BA, 0x90D6, 0xD3F2, 0x90D7, 0xD3FB, 0x90D8, 0xD3F9, 0x90D9, 0xD3F4, 0x90DA, 0xD3F5, 0x90DB, 0xD3FA, + 0x90DC, 0xD3FC, 0x90DD, 0xB071, 0x90DF, 0xD3F7, 0x90E0, 0xD3F3, 0x90E1, 0xB070, 0x90E2, 0xB072, 0x90E3, 0xD3F6, 0x90E4, 0xD3FD, + 0x90E5, 0xD3F8, 0x90E8, 0xB3A1, 0x90E9, 0xD7F1, 0x90EA, 0xD7E9, 0x90EB, 0xD7EF, 0x90EC, 0xD7F0, 0x90ED, 0xB3A2, 0x90EF, 0xD7E8, + 0x90F0, 0xD7EA, 0x90F1, 0xD0B7, 0x90F2, 0xD7EC, 0x90F3, 0xD7ED, 0x90F4, 0xD7EB, 0x90F5, 0xB66C, 0x90F9, 0xDC56, 0x90FA, 0xEBD4, + 0x90FB, 0xDC57, 0x90FC, 0xDC54, 0x90FD, 0xB3A3, 0x90FE, 0xB66E, 0x90FF, 0xDC53, 0x9100, 0xDC59, 0x9101, 0xDC58, 0x9102, 0xB66B, + 0x9103, 0xDC5C, 0x9104, 0xDC52, 0x9105, 0xDC5B, 0x9106, 0xDC50, 0x9107, 0xDC5A, 0x9108, 0xDC55, 0x9109, 0xB66D, 0x910B, 0xE0AA, + 0x910D, 0xE0A5, 0x910E, 0xE0AB, 0x910F, 0xE0A6, 0x9110, 0xE0A4, 0x9111, 0xE0A7, 0x9112, 0xB951, 0x9114, 0xE0A9, 0x9116, 0xE0A8, + 0x9117, 0xB952, 0x9118, 0xBBC1, 0x9119, 0xBBC0, 0x911A, 0xE46E, 0x911B, 0xE471, 0x911C, 0xE469, 0x911D, 0xE46D, 0x911E, 0xBBC2, + 0x911F, 0xE46C, 0x9120, 0xE46A, 0x9121, 0xE470, 0x9122, 0xE46B, 0x9123, 0xE468, 0x9124, 0xE46F, 0x9126, 0xE859, 0x9127, 0xBE48, + 0x9128, 0xF14A, 0x9129, 0xE856, 0x912A, 0xE857, 0x912B, 0xE855, 0x912C, 0xDC51, 0x912D, 0xBE47, 0x912E, 0xE85A, 0x912F, 0xE854, + 0x9130, 0xBE46, 0x9131, 0xBE49, 0x9132, 0xE858, 0x9133, 0xEBD5, 0x9134, 0xBFF3, 0x9135, 0xEBD6, 0x9136, 0xEBD7, 0x9138, 0xEEC4, + 0x9139, 0xC1DD, 0x913A, 0xF14B, 0x913B, 0xF14C, 0x913E, 0xF14D, 0x913F, 0xF35D, 0x9140, 0xF35C, 0x9141, 0xF4E2, 0x9143, 0xF4E1, + 0x9144, 0xF65B, 0x9145, 0xF65C, 0x9146, 0xF65A, 0x9147, 0xF766, 0x9148, 0xC5B0, 0x9149, 0xA8BB, 0x914A, 0xADAA, 0x914B, 0xADA9, + 0x914C, 0xB075, 0x914D, 0xB074, 0x914E, 0xD440, 0x914F, 0xD441, 0x9150, 0xD3FE, 0x9152, 0xB073, 0x9153, 0xD7F5, 0x9155, 0xD7F6, + 0x9156, 0xD7F2, 0x9157, 0xB3A4, 0x9158, 0xD7F3, 0x915A, 0xD7F4, 0x915F, 0xDC5F, 0x9160, 0xDC61, 0x9161, 0xDC5D, 0x9162, 0xDC60, + 0x9163, 0xB66F, 0x9164, 0xDC5E, 0x9165, 0xB670, 0x9168, 0xDD73, 0x9169, 0xB955, 0x916A, 0xB954, 0x916C, 0xB953, 0x916E, 0xE0AC, + 0x916F, 0xE0AD, 0x9172, 0xE473, 0x9173, 0xE475, 0x9174, 0xBBC6, 0x9175, 0xBBC3, 0x9177, 0xBBC5, 0x9178, 0xBBC4, 0x9179, 0xE474, + 0x917A, 0xE472, 0x9180, 0xE861, 0x9181, 0xE85E, 0x9182, 0xE85F, 0x9183, 0xBE4D, 0x9184, 0xE860, 0x9185, 0xE85B, 0x9186, 0xE85C, + 0x9187, 0xBE4A, 0x9189, 0xBE4B, 0x918A, 0xE85D, 0x918B, 0xBE4C, 0x918D, 0xEBDB, 0x918F, 0xEBDC, 0x9190, 0xEBD9, 0x9191, 0xEBDA, + 0x9192, 0xBFF4, 0x9193, 0xEBD8, 0x9199, 0xEEC8, 0x919A, 0xEEC5, 0x919B, 0xEEC7, 0x919C, 0xC1E0, 0x919D, 0xEECB, 0x919E, 0xC1DF, + 0x919F, 0xEEC9, 0x91A0, 0xEECC, 0x91A1, 0xEECA, 0x91A2, 0xEEC6, 0x91A3, 0xC1DE, 0x91A5, 0xF14F, 0x91A7, 0xF150, 0x91A8, 0xF14E, + 0x91AA, 0xF152, 0x91AB, 0xC2E5, 0x91AC, 0xC2E6, 0x91AD, 0xF35F, 0x91AE, 0xC3E7, 0x91AF, 0xF151, 0x91B0, 0xF35E, 0x91B1, 0xC3E6, + 0x91B2, 0xF4E5, 0x91B3, 0xF4E6, 0x91B4, 0xC4BF, 0x91B5, 0xF4E4, 0x91B7, 0xF4E3, 0x91B9, 0xF65D, 0x91BA, 0xC548, 0x91BC, 0xF849, + 0x91BD, 0xF8C8, 0x91BE, 0xF8C7, 0x91C0, 0xC643, 0x91C1, 0xC65D, 0x91C2, 0xF8C9, 0x91C3, 0xF971, 0x91C5, 0xC66F, 0x91C6, 0xA8BC, + 0x91C7, 0xAAF6, 0x91C9, 0xB956, 0x91CB, 0xC4C0, 0x91CC, 0xA8BD, 0x91CD, 0xADAB, 0x91CE, 0xB3A5, 0x91CF, 0xB671, 0x91D0, 0xC2E7, + 0x91D1, 0xAAF7, 0x91D3, 0xD0C1, 0x91D4, 0xD0C0, 0x91D5, 0xD442, 0x91D7, 0xB078, 0x91D8, 0xB076, 0x91D9, 0xB07A, 0x91DA, 0xD444, + 0x91DC, 0xB079, 0x91DD, 0xB077, 0x91E2, 0xD443, 0x91E3, 0xB3A8, 0x91E4, 0xD7FC, 0x91E6, 0xB3A7, 0x91E7, 0xB3A9, 0x91E8, 0xD842, + 0x91E9, 0xB3AB, 0x91EA, 0xD7FE, 0x91EB, 0xD840, 0x91EC, 0xD7F7, 0x91ED, 0xB3AA, 0x91EE, 0xD843, 0x91F1, 0xD7F9, 0x91F3, 0xD7FA, + 0x91F4, 0xD7F8, 0x91F5, 0xB3A6, 0x91F7, 0xD841, 0x91F8, 0xD7FB, 0x91F9, 0xD7FD, 0x91FD, 0xDC6D, 0x91FF, 0xDC6C, 0x9200, 0xDC6A, + 0x9201, 0xDC62, 0x9202, 0xDC71, 0x9203, 0xDC65, 0x9204, 0xDC6F, 0x9205, 0xDC76, 0x9206, 0xDC6E, 0x9207, 0xB679, 0x9209, 0xB675, + 0x920A, 0xDC63, 0x920C, 0xDC69, 0x920D, 0xB677, 0x920F, 0xDC68, 0x9210, 0xB678, 0x9211, 0xB67A, 0x9212, 0xDC6B, 0x9214, 0xB672, + 0x9215, 0xB673, 0x9216, 0xDC77, 0x9217, 0xDC75, 0x9219, 0xDC74, 0x921A, 0xDC66, 0x921C, 0xDC72, 0x921E, 0xB676, 0x9223, 0xB674, + 0x9224, 0xDC73, 0x9225, 0xDC64, 0x9226, 0xDC67, 0x9227, 0xDC70, 0x922D, 0xE4BA, 0x922E, 0xE0B7, 0x9230, 0xE0B0, 0x9231, 0xE0C3, + 0x9232, 0xE0CC, 0x9233, 0xE0B3, 0x9234, 0xB961, 0x9236, 0xE0C0, 0x9237, 0xB957, 0x9238, 0xB959, 0x9239, 0xB965, 0x923A, 0xE0B1, + 0x923D, 0xB95A, 0x923E, 0xB95C, 0x923F, 0xB966, 0x9240, 0xB95B, 0x9245, 0xB964, 0x9246, 0xE0B9, 0x9248, 0xE0AE, 0x9249, 0xB962, + 0x924A, 0xE0B8, 0x924B, 0xB95E, 0x924C, 0xE0CA, 0x924D, 0xB963, 0x924E, 0xE0C8, 0x924F, 0xE0BC, 0x9250, 0xE0C6, 0x9251, 0xB960, + 0x9252, 0xE0AF, 0x9253, 0xE0C9, 0x9254, 0xE0C4, 0x9256, 0xE0CB, 0x9257, 0xB958, 0x925A, 0xB967, 0x925B, 0xB95D, 0x925E, 0xE0B5, + 0x9260, 0xE0BD, 0x9261, 0xE0C1, 0x9263, 0xE0C5, 0x9264, 0xB95F, 0x9265, 0xE0B4, 0x9266, 0xE0B2, 0x9267, 0xE0BE, 0x926C, 0xE0BB, + 0x926D, 0xE0BA, 0x926F, 0xE0BF, 0x9270, 0xE0C2, 0x9272, 0xE0C7, 0x9276, 0xE478, 0x9278, 0xBBC7, 0x9279, 0xE4A4, 0x927A, 0xE47A, + 0x927B, 0xBBCC, 0x927C, 0xBBD0, 0x927D, 0xE4AD, 0x927E, 0xE4B5, 0x927F, 0xE4A6, 0x9280, 0xBBC8, 0x9282, 0xE4AA, 0x9283, 0xE0B6, + 0x9285, 0xBBC9, 0x9286, 0xE4B1, 0x9287, 0xE4B6, 0x9288, 0xE4AE, 0x928A, 0xE4B0, 0x928B, 0xE4B9, 0x928C, 0xE4B2, 0x928D, 0xE47E, + 0x928E, 0xE4A9, 0x9291, 0xBBD1, 0x9293, 0xBBCD, 0x9294, 0xE47C, 0x9295, 0xE4AB, 0x9296, 0xBBCB, 0x9297, 0xE4A5, 0x9298, 0xBBCA, + 0x9299, 0xE4B3, 0x929A, 0xE4A2, 0x929B, 0xE479, 0x929C, 0xBBCE, 0x929D, 0xE4B8, 0x92A0, 0xE47B, 0x92A1, 0xE4AF, 0x92A2, 0xE4AC, + 0x92A3, 0xE4A7, 0x92A4, 0xE477, 0x92A5, 0xE476, 0x92A6, 0xE4A1, 0x92A7, 0xE4B4, 0x92A8, 0xBBCF, 0x92A9, 0xE4B7, 0x92AA, 0xE47D, + 0x92AB, 0xE4A3, 0x92AC, 0xBE52, 0x92B2, 0xBE5A, 0x92B3, 0xBE55, 0x92B4, 0xE8A4, 0x92B5, 0xE8A1, 0x92B6, 0xE867, 0x92B7, 0xBE50, + 0x92B9, 0xF9D7, 0x92BB, 0xBE4F, 0x92BC, 0xBE56, 0x92C0, 0xE865, 0x92C1, 0xBE54, 0x92C2, 0xE871, 0x92C3, 0xE863, 0x92C4, 0xE864, + 0x92C5, 0xBE4E, 0x92C6, 0xE8A3, 0x92C7, 0xBE58, 0x92C8, 0xE874, 0x92C9, 0xE879, 0x92CA, 0xE873, 0x92CB, 0xEBEE, 0x92CC, 0xE86F, + 0x92CD, 0xE877, 0x92CE, 0xE875, 0x92CF, 0xE868, 0x92D0, 0xE862, 0x92D1, 0xE87D, 0x92D2, 0xBE57, 0x92D3, 0xE87E, 0x92D5, 0xE878, + 0x92D7, 0xE86D, 0x92D8, 0xE86B, 0x92D9, 0xE866, 0x92DD, 0xE86E, 0x92DE, 0xE87B, 0x92DF, 0xE86A, 0x92E0, 0xE87A, 0x92E1, 0xE8A2, + 0x92E4, 0xBE53, 0x92E6, 0xE876, 0x92E7, 0xE87C, 0x92E8, 0xE872, 0x92E9, 0xE86C, 0x92EA, 0xBE51, 0x92EE, 0xE4A8, 0x92EF, 0xE870, + 0x92F0, 0xBE59, 0x92F1, 0xE869, 0x92F7, 0xEBF4, 0x92F8, 0xBFF7, 0x92F9, 0xEBF3, 0x92FA, 0xEBF0, 0x92FB, 0xEC44, 0x92FC, 0xBFFB, + 0x92FE, 0xEC41, 0x92FF, 0xEBF8, 0x9300, 0xEC43, 0x9301, 0xEBE9, 0x9302, 0xEBF6, 0x9304, 0xBFFD, 0x9306, 0xEBE1, 0x9308, 0xEBDF, + 0x9309, 0xEC42, 0x930B, 0xEC40, 0x930C, 0xEBFE, 0x930D, 0xEBED, 0x930E, 0xEBEC, 0x930F, 0xEBE2, 0x9310, 0xC040, 0x9312, 0xEBE8, + 0x9313, 0xEBF2, 0x9314, 0xEBFD, 0x9315, 0xC043, 0x9316, 0xEC45, 0x9318, 0xC1E8, 0x9319, 0xC045, 0x931A, 0xBFFE, 0x931B, 0xEBE6, + 0x931D, 0xEBEF, 0x931E, 0xEBDE, 0x931F, 0xEBE0, 0x9320, 0xBFF5, 0x9321, 0xC042, 0x9322, 0xBFFA, 0x9323, 0xEBE7, 0x9324, 0xEBF7, + 0x9325, 0xEBF1, 0x9326, 0xC041, 0x9327, 0xEBDD, 0x9328, 0xC1E3, 0x9329, 0xEBF9, 0x932A, 0xEBFC, 0x932B, 0xBFFC, 0x932D, 0xEBEB, + 0x932E, 0xC044, 0x932F, 0xBFF9, 0x9333, 0xBFF8, 0x9334, 0xEBF5, 0x9335, 0xEBFB, 0x9336, 0xBFF6, 0x9338, 0xEBE4, 0x9339, 0xEBFA, + 0x933C, 0xEBE5, 0x9346, 0xEBEA, 0x9347, 0xEED2, 0x9349, 0xEED7, 0x934A, 0xC1E5, 0x934B, 0xC1E7, 0x934C, 0xEEDD, 0x934D, 0xC1E1, + 0x934E, 0xEEEC, 0x934F, 0xEEE3, 0x9350, 0xEED8, 0x9351, 0xEED9, 0x9352, 0xEEE2, 0x9354, 0xC1EE, 0x9355, 0xEEE1, 0x9356, 0xEED1, + 0x9357, 0xEEE0, 0x9358, 0xEED4, 0x9359, 0xEEED, 0x935A, 0xC1ED, 0x935B, 0xC1EB, 0x935C, 0xEED5, 0x935E, 0xEEE8, 0x9360, 0xEEDA, + 0x9361, 0xEEE7, 0x9363, 0xEEE9, 0x9364, 0xEED0, 0x9365, 0xC1E6, 0x9367, 0xEEEA, 0x936A, 0xEEDE, 0x936C, 0xC1EA, 0x936D, 0xEEDB, + 0x9370, 0xC1EC, 0x9371, 0xEEE4, 0x9375, 0xC1E4, 0x9376, 0xEED6, 0x9377, 0xEEE5, 0x9379, 0xEEDF, 0x937A, 0xEBE3, 0x937B, 0xEEE6, + 0x937C, 0xEED3, 0x937E, 0xC1E9, 0x9380, 0xEEEB, 0x9382, 0xC1E2, 0x9383, 0xEECE, 0x9388, 0xF160, 0x9389, 0xF159, 0x938A, 0xC2E9, + 0x938C, 0xF154, 0x938D, 0xF163, 0x938E, 0xF15B, 0x938F, 0xEEDC, 0x9391, 0xF165, 0x9392, 0xF155, 0x9394, 0xC2E8, 0x9395, 0xF15F, + 0x9396, 0xC2EA, 0x9397, 0xC2F2, 0x9398, 0xC2F0, 0x9399, 0xF161, 0x939A, 0xC2F1, 0x939B, 0xF157, 0x939D, 0xF158, 0x939E, 0xF15D, + 0x939F, 0xF162, 0x93A1, 0xEECD, 0x93A2, 0xC2EB, 0x93A3, 0xF16A, 0x93A4, 0xF167, 0x93A5, 0xF16B, 0x93A6, 0xF15E, 0x93A7, 0xF15A, + 0x93A8, 0xF168, 0x93A9, 0xF36A, 0x93AA, 0xF15C, 0x93AC, 0xC2EE, 0x93AE, 0xC2ED, 0x93AF, 0xEECF, 0x93B0, 0xC2EF, 0x93B1, 0xF164, + 0x93B2, 0xF166, 0x93B3, 0xC2EC, 0x93B4, 0xF169, 0x93B5, 0xF153, 0x93B7, 0xF156, 0x93C0, 0xF373, 0x93C2, 0xF363, 0x93C3, 0xC3EB, + 0x93C4, 0xF371, 0x93C7, 0xF361, 0x93C8, 0xC3EC, 0x93CA, 0xF36C, 0x93CC, 0xF368, 0x93CD, 0xC3F1, 0x93CE, 0xF372, 0x93CF, 0xF362, + 0x93D0, 0xF365, 0x93D1, 0xC3E9, 0x93D2, 0xF374, 0x93D4, 0xF36D, 0x93D5, 0xF370, 0x93D6, 0xC3EF, 0x93D7, 0xC3F4, 0x93D8, 0xC3F2, + 0x93D9, 0xF369, 0x93DA, 0xF364, 0x93DC, 0xC3ED, 0x93DD, 0xC3EE, 0x93DE, 0xF360, 0x93DF, 0xC3EA, 0x93E1, 0xC3E8, 0x93E2, 0xC3F0, + 0x93E3, 0xF36F, 0x93E4, 0xC3F3, 0x93E6, 0xF36B, 0x93E7, 0xF375, 0x93E8, 0xC3F5, 0x93EC, 0xF367, 0x93EE, 0xF36E, 0x93F5, 0xF4F3, + 0x93F6, 0xF542, 0x93F7, 0xF4F5, 0x93F8, 0xF4FC, 0x93F9, 0xF366, 0x93FA, 0xF4FA, 0x93FB, 0xF4E9, 0x93FC, 0xF540, 0x93FD, 0xC4C3, + 0x93FE, 0xF4ED, 0x93FF, 0xF4FE, 0x9400, 0xF4F4, 0x9403, 0xC4C2, 0x9406, 0xF544, 0x9407, 0xF4F6, 0x9409, 0xF4FB, 0x940A, 0xF4FD, + 0x940B, 0xF4E7, 0x940C, 0xF541, 0x940D, 0xF4F2, 0x940E, 0xF4F7, 0x940F, 0xF4EB, 0x9410, 0xF4EF, 0x9411, 0xF543, 0x9412, 0xF4F9, + 0x9413, 0xF4E8, 0x9414, 0xF4EC, 0x9415, 0xF4EE, 0x9416, 0xF4F8, 0x9418, 0xC4C1, 0x9419, 0xF4F1, 0x9420, 0xF4EA, 0x9428, 0xF4F0, + 0x9429, 0xF661, 0x942A, 0xF666, 0x942B, 0xC54F, 0x942C, 0xF668, 0x942E, 0xC549, 0x9430, 0xF664, 0x9431, 0xF66A, 0x9432, 0xC54E, + 0x9433, 0xC54A, 0x9435, 0xC54B, 0x9436, 0xF660, 0x9437, 0xF667, 0x9438, 0xC54D, 0x9439, 0xF665, 0x943A, 0xC54C, 0x943B, 0xF65F, + 0x943C, 0xF663, 0x943D, 0xF662, 0x943F, 0xF65E, 0x9440, 0xF669, 0x9444, 0xC5B1, 0x9445, 0xF76D, 0x9446, 0xF770, 0x9447, 0xF76C, + 0x9448, 0xF76E, 0x9449, 0xF76F, 0x944A, 0xF769, 0x944B, 0xF76A, 0x944C, 0xF767, 0x944F, 0xF76B, 0x9450, 0xF768, 0x9451, 0xC5B2, + 0x9452, 0xC5B3, 0x9455, 0xF84B, 0x9457, 0xF84D, 0x945D, 0xF84C, 0x945E, 0xF84E, 0x9460, 0xC5E0, 0x9462, 0xF84A, 0x9463, 0xC5DF, + 0x9464, 0xC5E1, 0x9468, 0xF8CB, 0x9469, 0xF8CC, 0x946A, 0xC644, 0x946B, 0xF8CA, 0x946D, 0xF953, 0x946E, 0xF952, 0x946F, 0xF954, + 0x9470, 0xC65F, 0x9471, 0xF955, 0x9472, 0xC65E, 0x9473, 0xF956, 0x9474, 0xF972, 0x9475, 0xF975, 0x9476, 0xF974, 0x9477, 0xC668, + 0x9478, 0xF973, 0x947C, 0xC672, 0x947D, 0xC670, 0x947E, 0xC671, 0x947F, 0xC677, 0x9480, 0xF9C0, 0x9481, 0xF9C1, 0x9482, 0xF9BF, + 0x9483, 0xF9C9, 0x9577, 0xAAF8, 0x957A, 0xD844, 0x957B, 0xDC78, 0x957C, 0xE8A5, 0x957D, 0xF376, 0x9580, 0xAAF9, 0x9582, 0xADAC, + 0x9583, 0xB07B, 0x9586, 0xD845, 0x9588, 0xD846, 0x9589, 0xB3AC, 0x958B, 0xB67D, 0x958C, 0xDC7A, 0x958D, 0xDC79, 0x958E, 0xB6A3, + 0x958F, 0xB67C, 0x9590, 0xDC7B, 0x9591, 0xB67E, 0x9592, 0xB6A2, 0x9593, 0xB6A1, 0x9594, 0xB67B, 0x9598, 0xB968, 0x959B, 0xE0D0, + 0x959C, 0xE0CE, 0x959E, 0xE0CF, 0x959F, 0xE0CD, 0x95A1, 0xBBD2, 0x95A3, 0xBBD5, 0x95A4, 0xBBD7, 0x95A5, 0xBBD6, 0x95A8, 0xBBD3, + 0x95A9, 0xBBD4, 0x95AB, 0xE8A7, 0x95AC, 0xE8A6, 0x95AD, 0xBE5B, 0x95AE, 0xE8A8, 0x95B0, 0xE8A9, 0x95B1, 0xBE5C, 0x95B5, 0xEC4D, + 0x95B6, 0xEC4B, 0x95B7, 0xEEF3, 0x95B9, 0xEC49, 0x95BA, 0xEC4A, 0x95BB, 0xC046, 0x95BC, 0xEC46, 0x95BD, 0xEC4E, 0x95BE, 0xEC48, + 0x95BF, 0xEC4C, 0x95C0, 0xEEEF, 0x95C3, 0xEEF1, 0x95C5, 0xEEF2, 0x95C6, 0xC1F3, 0x95C7, 0xEEEE, 0x95C8, 0xC1F2, 0x95C9, 0xEEF0, + 0x95CA, 0xC1EF, 0x95CB, 0xC1F0, 0x95CC, 0xC1F1, 0x95CD, 0xEC47, 0x95D0, 0xC2F5, 0x95D1, 0xF16E, 0x95D2, 0xF16C, 0x95D3, 0xF16D, + 0x95D4, 0xC2F3, 0x95D5, 0xC2F6, 0x95D6, 0xC2F4, 0x95DA, 0xF377, 0x95DB, 0xF378, 0x95DC, 0xC3F6, 0x95DE, 0xF545, 0x95DF, 0xF547, + 0x95E0, 0xF546, 0x95E1, 0xC4C4, 0x95E2, 0xC550, 0x95E3, 0xF66D, 0x95E4, 0xF66C, 0x95E5, 0xF66B, 0x961C, 0xAAFA, 0x961E, 0xC9AA, + 0x9620, 0xCA58, 0x9621, 0xA6E9, 0x9622, 0xCA56, 0x9623, 0xCA59, 0x9624, 0xCA57, 0x9628, 0xCBAE, 0x962A, 0xA8C1, 0x962C, 0xA8C2, + 0x962D, 0xCBB0, 0x962E, 0xA8BF, 0x962F, 0xCBAF, 0x9630, 0xCBAD, 0x9631, 0xA8C0, 0x9632, 0xA8BE, 0x9639, 0xCDD8, 0x963A, 0xCDDB, + 0x963B, 0xAAFD, 0x963C, 0xCDDA, 0x963D, 0xCDD9, 0x963F, 0xAAFC, 0x9640, 0xAAFB, 0x9642, 0xAB40, 0x9643, 0xCDDC, 0x9644, 0xAAFE, + 0x964A, 0xD0C6, 0x964B, 0xADAE, 0x964C, 0xADAF, 0x964D, 0xADB0, 0x964E, 0xD0C7, 0x964F, 0xD0C3, 0x9650, 0xADAD, 0x9651, 0xD0C4, + 0x9653, 0xD0C5, 0x9654, 0xD0C2, 0x9658, 0xB0A4, 0x965B, 0xB0A1, 0x965C, 0xD445, 0x965D, 0xB0A2, 0x965E, 0xB0A5, 0x965F, 0xD446, + 0x9661, 0xB07E, 0x9662, 0xB07C, 0x9663, 0xB07D, 0x9664, 0xB0A3, 0x966A, 0xB3AD, 0x966B, 0xD849, 0x966C, 0xB3B5, 0x966D, 0xD848, + 0x966F, 0xD84B, 0x9670, 0xB3B1, 0x9671, 0xD84A, 0x9672, 0xB6AB, 0x9673, 0xB3AF, 0x9674, 0xB3B2, 0x9675, 0xB3AE, 0x9676, 0xB3B3, + 0x9677, 0xB3B4, 0x9678, 0xB3B0, 0x967C, 0xD847, 0x967D, 0xB6A7, 0x967E, 0xDC7D, 0x9680, 0xDCA3, 0x9683, 0xDCA2, 0x9684, 0xB6AC, + 0x9685, 0xB6A8, 0x9686, 0xB6A9, 0x9687, 0xDC7C, 0x9688, 0xDC7E, 0x9689, 0xDCA1, 0x968A, 0xB6A4, 0x968B, 0xB6A6, 0x968D, 0xB6AA, + 0x968E, 0xB6A5, 0x9691, 0xE0D3, 0x9692, 0xE0D1, 0x9693, 0xE0D2, 0x9694, 0xB96A, 0x9695, 0xB96B, 0x9697, 0xE0D4, 0x9698, 0xB969, + 0x9699, 0xBBD8, 0x969B, 0xBBDA, 0x969C, 0xBBD9, 0x969E, 0xE4BB, 0x96A1, 0xE4BC, 0x96A2, 0xE8AB, 0x96A4, 0xE8AA, 0x96A7, 0xC047, + 0x96A8, 0xC048, 0x96A9, 0xEC4F, 0x96AA, 0xC049, 0x96AC, 0xEEF6, 0x96AE, 0xEEF4, 0x96B0, 0xEEF5, 0x96B1, 0xC1F4, 0x96B3, 0xF16F, + 0x96B4, 0xC3F7, 0x96B8, 0xC1F5, 0x96B9, 0xAB41, 0x96BB, 0xB0A6, 0x96BC, 0xD447, 0x96BF, 0xD84C, 0x96C0, 0xB3B6, 0x96C1, 0xB6AD, + 0x96C2, 0xDCA4, 0x96C3, 0xDCA6, 0x96C4, 0xB6AF, 0x96C5, 0xB6AE, 0x96C6, 0xB6B0, 0x96C7, 0xB6B1, 0x96C8, 0xDCA5, 0x96C9, 0xB96E, + 0x96CA, 0xB96F, 0x96CB, 0xB96D, 0x96CC, 0xBBDB, 0x96CD, 0xB96C, 0x96CE, 0xE0D5, 0x96D2, 0xBBDC, 0x96D3, 0xE8AC, 0x96D4, 0xEC50, + 0x96D5, 0xC04A, 0x96D6, 0xC1F6, 0x96D7, 0xF170, 0x96D8, 0xF174, 0x96D9, 0xC2F9, 0x96DA, 0xF171, 0x96DB, 0xC2FA, 0x96DC, 0xC2F8, + 0x96DD, 0xF175, 0x96DE, 0xC2FB, 0x96DF, 0xF173, 0x96E1, 0xF379, 0x96E2, 0xC2F7, 0x96E3, 0xC3F8, 0x96E5, 0xF8CD, 0x96E8, 0xAB42, + 0x96E9, 0xB3B8, 0x96EA, 0xB3B7, 0x96EF, 0xB6B2, 0x96F0, 0xDCA8, 0x96F1, 0xDCA7, 0x96F2, 0xB6B3, 0x96F5, 0xE0D9, 0x96F6, 0xB973, + 0x96F7, 0xB970, 0x96F8, 0xE0D8, 0x96F9, 0xB972, 0x96FA, 0xE0D6, 0x96FB, 0xB971, 0x96FD, 0xE0D7, 0x96FF, 0xE4BD, 0x9700, 0xBBDD, + 0x9702, 0xE8AF, 0x9704, 0xBE5D, 0x9705, 0xE8AD, 0x9706, 0xBE5E, 0x9707, 0xBE5F, 0x9708, 0xE8AE, 0x9709, 0xBE60, 0x970B, 0xEC51, + 0x970D, 0xC04E, 0x970E, 0xC04B, 0x970F, 0xC050, 0x9710, 0xEC53, 0x9711, 0xC04C, 0x9712, 0xEC52, 0x9713, 0xC04F, 0x9716, 0xC04D, + 0x9718, 0xEEF9, 0x9719, 0xEEFB, 0x971C, 0xC1F7, 0x971D, 0xEEFA, 0x971E, 0xC1F8, 0x971F, 0xEEF8, 0x9720, 0xEEF7, 0x9722, 0xF177, + 0x9723, 0xF176, 0x9724, 0xC2FC, 0x9725, 0xF178, 0x9726, 0xF37E, 0x9727, 0xC3FA, 0x9728, 0xF37D, 0x9729, 0xF37A, 0x972A, 0xC3F9, + 0x972B, 0xF37B, 0x972C, 0xF37C, 0x972E, 0xF548, 0x972F, 0xF549, 0x9730, 0xC4C5, 0x9732, 0xC553, 0x9735, 0xF66E, 0x9738, 0xC551, + 0x9739, 0xC552, 0x973A, 0xF66F, 0x973D, 0xC5B4, 0x973E, 0xC5B5, 0x973F, 0xF771, 0x9742, 0xC645, 0x9743, 0xF8CF, 0x9744, 0xC647, + 0x9746, 0xF8CE, 0x9747, 0xF8D0, 0x9748, 0xC646, 0x9749, 0xF957, 0x974B, 0xF9AD, 0x9752, 0xAB43, 0x9756, 0xB974, 0x9758, 0xE4BE, + 0x975A, 0xE8B0, 0x975B, 0xC051, 0x975C, 0xC052, 0x975E, 0xAB44, 0x9760, 0xBE61, 0x9761, 0xC3FB, 0x9762, 0xADB1, 0x9766, 0xC053, + 0x9768, 0xC5E2, 0x9769, 0xADB2, 0x976A, 0xD84D, 0x976C, 0xDCA9, 0x976E, 0xDCAB, 0x9770, 0xDCAA, 0x9772, 0xE0DD, 0x9773, 0xE0DA, + 0x9774, 0xB975, 0x9776, 0xB976, 0x9777, 0xE0DB, 0x9778, 0xE0DC, 0x977A, 0xE4C0, 0x977B, 0xE4C5, 0x977C, 0xBBDE, 0x977D, 0xE4BF, + 0x977E, 0xE4C1, 0x977F, 0xE4C8, 0x9780, 0xE4C3, 0x9781, 0xE4C7, 0x9782, 0xE4C4, 0x9783, 0xE4C2, 0x9784, 0xE4C6, 0x9785, 0xBBDF, + 0x9788, 0xE8B3, 0x978A, 0xE8B1, 0x978B, 0xBE63, 0x978D, 0xBE62, 0x978E, 0xE8B2, 0x978F, 0xBE64, 0x9794, 0xEC56, 0x9797, 0xEC55, + 0x9798, 0xC054, 0x9799, 0xEC54, 0x979A, 0xEEFC, 0x979C, 0xEEFE, 0x979D, 0xEF41, 0x979E, 0xEF40, 0x97A0, 0xC1F9, 0x97A1, 0xEEFD, + 0x97A2, 0xF1A1, 0x97A3, 0xC2FD, 0x97A4, 0xF17D, 0x97A5, 0xF1A2, 0x97A6, 0xC2FE, 0x97A8, 0xF17B, 0x97AA, 0xF17E, 0x97AB, 0xF17C, + 0x97AC, 0xF179, 0x97AD, 0xC340, 0x97AE, 0xF17A, 0x97B3, 0xF3A1, 0x97B6, 0xF3A3, 0x97B7, 0xF3A2, 0x97B9, 0xF54A, 0x97BB, 0xF54B, + 0x97BF, 0xF670, 0x97C1, 0xC5B7, 0x97C3, 0xC5B6, 0x97C4, 0xF84F, 0x97C5, 0xF850, 0x97C6, 0xC648, 0x97C7, 0xF8D1, 0x97C9, 0xC669, + 0x97CB, 0xADB3, 0x97CC, 0xB6B4, 0x97CD, 0xE4CA, 0x97CE, 0xE4C9, 0x97CF, 0xE8B5, 0x97D0, 0xE8B4, 0x97D3, 0xC1FA, 0x97D4, 0xEF43, + 0x97D5, 0xEF42, 0x97D6, 0xF1A5, 0x97D7, 0xF1A3, 0x97D8, 0xF1A6, 0x97D9, 0xF1A4, 0x97DC, 0xC3FC, 0x97DD, 0xF3A4, 0x97DE, 0xF3A5, + 0x97DF, 0xF3A6, 0x97E1, 0xF671, 0x97E3, 0xF772, 0x97E5, 0xF8D2, 0x97ED, 0xADB4, 0x97F0, 0xEC57, 0x97F1, 0xEF44, 0x97F3, 0xADB5, + 0x97F6, 0xBBE0, 0x97F8, 0xEC58, 0x97F9, 0xC341, 0x97FA, 0xF1A7, 0x97FB, 0xC3FD, 0x97FD, 0xF54C, 0x97FE, 0xF54D, 0x97FF, 0xC554, + 0x9800, 0xF851, 0x9801, 0xADB6, 0x9802, 0xB3BB, 0x9803, 0xB3BC, 0x9804, 0xD84E, 0x9805, 0xB6B5, 0x9806, 0xB6B6, 0x9807, 0xDCAC, + 0x9808, 0xB6B7, 0x980A, 0xB97A, 0x980C, 0xB97C, 0x980D, 0xE0DF, 0x980E, 0xE0E0, 0x980F, 0xE0DE, 0x9810, 0xB977, 0x9811, 0xB978, + 0x9812, 0xB97B, 0x9813, 0xB979, 0x9816, 0xE4CB, 0x9817, 0xBBE1, 0x9818, 0xBBE2, 0x981B, 0xE8BC, 0x981C, 0xBE67, 0x981D, 0xE8B7, + 0x981E, 0xE8B6, 0x9820, 0xE8BB, 0x9821, 0xBE65, 0x9824, 0xC05B, 0x9826, 0xE8B8, 0x9827, 0xE8BD, 0x9828, 0xE8BA, 0x9829, 0xE8B9, + 0x982B, 0xBE66, 0x982D, 0xC059, 0x982F, 0xEC5A, 0x9830, 0xC055, 0x9832, 0xEC5B, 0x9835, 0xEC59, 0x9837, 0xC058, 0x9838, 0xC056, + 0x9839, 0xC05A, 0x983B, 0xC057, 0x9841, 0xEF45, 0x9843, 0xEF4A, 0x9844, 0xEF46, 0x9845, 0xEF49, 0x9846, 0xC1FB, 0x9848, 0xEDD4, + 0x9849, 0xEF48, 0x984A, 0xEF47, 0x984C, 0xC344, 0x984D, 0xC342, 0x984E, 0xC345, 0x984F, 0xC343, 0x9850, 0xF1A8, 0x9851, 0xF1A9, + 0x9852, 0xF1AA, 0x9853, 0xC346, 0x9857, 0xF3AA, 0x9858, 0xC440, 0x9859, 0xF3A8, 0x985B, 0xC441, 0x985C, 0xF3A7, 0x985D, 0xF3A9, + 0x985E, 0xC3FE, 0x985F, 0xF551, 0x9860, 0xF54E, 0x9862, 0xF54F, 0x9863, 0xF550, 0x9864, 0xF672, 0x9865, 0xC556, 0x9867, 0xC555, + 0x9869, 0xF774, 0x986A, 0xF773, 0x986B, 0xC5B8, 0x986F, 0xC5E3, 0x9870, 0xC649, 0x9871, 0xC660, 0x9872, 0xF958, 0x9873, 0xF9AE, + 0x9874, 0xF9AF, 0x98A8, 0xADB7, 0x98A9, 0xDCAD, 0x98AC, 0xE0E1, 0x98AD, 0xE4CC, 0x98AE, 0xE4CD, 0x98AF, 0xBBE3, 0x98B1, 0xBBE4, + 0x98B2, 0xE8BE, 0x98B3, 0xBE68, 0x98B6, 0xC1FC, 0x98B8, 0xF1AB, 0x98BA, 0xC347, 0x98BB, 0xF3AD, 0x98BC, 0xC442, 0x98BD, 0xF3AC, + 0x98BE, 0xF3AE, 0x98BF, 0xF3AB, 0x98C0, 0xF675, 0x98C1, 0xF552, 0x98C2, 0xF553, 0x98C4, 0xC4C6, 0x98C6, 0xF674, 0x98C9, 0xF673, + 0x98CB, 0xF775, 0x98CC, 0xF9B0, 0x98DB, 0xADB8, 0x98DF, 0xADB9, 0x98E2, 0xB0A7, 0x98E3, 0xD448, 0x98E5, 0xD84F, 0x98E7, 0xB6B8, + 0x98E9, 0xB6BB, 0x98EA, 0xB6B9, 0x98EB, 0xDCAE, 0x98ED, 0xB6BD, 0x98EF, 0xB6BA, 0x98F2, 0xB6BC, 0x98F4, 0xB97E, 0x98F6, 0xE0E2, + 0x98F9, 0xE0E3, 0x98FA, 0xE8C0, 0x98FC, 0xB97D, 0x98FD, 0xB9A1, 0x98FE, 0xB9A2, 0x9900, 0xE4CF, 0x9902, 0xE4CE, 0x9903, 0xBBE5, + 0x9905, 0xBBE6, 0x9907, 0xE4D0, 0x9908, 0xE8BF, 0x9909, 0xBBE8, 0x990A, 0xBE69, 0x990C, 0xBBE7, 0x9910, 0xC05C, 0x9911, 0xE8C1, + 0x9912, 0xBE6B, 0x9913, 0xBE6A, 0x9914, 0xE8C2, 0x9915, 0xE8C5, 0x9916, 0xE8C3, 0x9917, 0xE8C4, 0x9918, 0xBE6C, 0x991A, 0xC061, + 0x991B, 0xC05F, 0x991E, 0xC05E, 0x991F, 0xEC5D, 0x9921, 0xC060, 0x9924, 0xEC5C, 0x9925, 0xEF4B, 0x9927, 0xEC5E, 0x9928, 0xC05D, + 0x9929, 0xEC5F, 0x992A, 0xEF4E, 0x992B, 0xEF4C, 0x992C, 0xEF4D, 0x992D, 0xEF52, 0x992E, 0xC34B, 0x992F, 0xEF51, 0x9930, 0xEF54, + 0x9931, 0xEF53, 0x9932, 0xEF50, 0x9933, 0xEF4F, 0x9935, 0xC1FD, 0x993A, 0xF1AE, 0x993C, 0xF1AD, 0x993D, 0xC34A, 0x993E, 0xC348, + 0x993F, 0xC349, 0x9941, 0xF1AC, 0x9943, 0xF3B1, 0x9945, 0xC443, 0x9947, 0xF3B0, 0x9948, 0xF3AF, 0x9949, 0xC444, 0x994B, 0xF558, + 0x994C, 0xF557, 0x994E, 0xF555, 0x9950, 0xF554, 0x9951, 0xC4C8, 0x9952, 0xC4C7, 0x9953, 0xF559, 0x9954, 0xF776, 0x9955, 0xC5B9, + 0x9956, 0xF677, 0x9957, 0xC557, 0x9958, 0xF676, 0x9959, 0xF556, 0x995B, 0xF777, 0x995C, 0xC5E4, 0x995E, 0xC661, 0x995F, 0xF959, + 0x9961, 0xF9B1, 0x9996, 0xADBA, 0x9997, 0xD850, 0x9998, 0xEF55, 0x9999, 0xADBB, 0x999C, 0xE4D2, 0x999D, 0xE4D1, 0x999E, 0xEC60, + 0x99A1, 0xEF57, 0x99A3, 0xEF56, 0x99A5, 0xC34C, 0x99A6, 0xF3B2, 0x99A7, 0xF3B3, 0x99A8, 0xC4C9, 0x99AB, 0xF9B2, 0x99AC, 0xB0A8, + 0x99AD, 0xB6BF, 0x99AE, 0xB6BE, 0x99AF, 0xE0E4, 0x99B0, 0xE0E6, 0x99B1, 0xB9A4, 0x99B2, 0xE0E5, 0x99B3, 0xB9A3, 0x99B4, 0xB9A5, + 0x99B5, 0xE0E7, 0x99B9, 0xE4D4, 0x99BA, 0xE4D6, 0x99BB, 0xE4D5, 0x99BD, 0xE4D8, 0x99C1, 0xBBE9, 0x99C2, 0xE4D7, 0x99C3, 0xE4D3, + 0x99C7, 0xE4D9, 0x99C9, 0xE8CC, 0x99CB, 0xE8CF, 0x99CC, 0xE8D1, 0x99CD, 0xE8C7, 0x99CE, 0xE8CB, 0x99CF, 0xE8C8, 0x99D0, 0xBE6E, + 0x99D1, 0xBE71, 0x99D2, 0xBE73, 0x99D3, 0xE8C9, 0x99D4, 0xE8CA, 0x99D5, 0xBE72, 0x99D6, 0xE8CD, 0x99D7, 0xE8D0, 0x99D8, 0xE8CE, + 0x99D9, 0xBE74, 0x99DB, 0xBE70, 0x99DC, 0xE8C6, 0x99DD, 0xBE6D, 0x99DF, 0xBE6F, 0x99E2, 0xC063, 0x99E3, 0xEC66, 0x99E4, 0xEC64, + 0x99E5, 0xEC63, 0x99E7, 0xEC69, 0x99E9, 0xEC68, 0x99EA, 0xEC67, 0x99EC, 0xEC62, 0x99ED, 0xC062, 0x99EE, 0xEC61, 0x99F0, 0xEC65, + 0x99F1, 0xC064, 0x99F4, 0xEF5A, 0x99F6, 0xEF5E, 0x99F7, 0xEF5B, 0x99F8, 0xEF5D, 0x99F9, 0xEF5C, 0x99FA, 0xEF59, 0x99FB, 0xEF5F, + 0x99FC, 0xEF62, 0x99FD, 0xEF60, 0x99FE, 0xEF61, 0x99FF, 0xC240, 0x9A01, 0xC1FE, 0x9A02, 0xEF58, 0x9A03, 0xEF63, 0x9A04, 0xF1B3, + 0x9A05, 0xF1B6, 0x9A06, 0xF1B8, 0x9A07, 0xF1B7, 0x9A09, 0xF1B1, 0x9A0A, 0xF1B5, 0x9A0B, 0xF1B0, 0x9A0D, 0xF1B2, 0x9A0E, 0xC34D, + 0x9A0F, 0xF1AF, 0x9A11, 0xF1B4, 0x9A14, 0xF3C0, 0x9A15, 0xF3B5, 0x9A16, 0xC445, 0x9A19, 0xC446, 0x9A1A, 0xF3B4, 0x9A1B, 0xF3B9, + 0x9A1C, 0xF3BF, 0x9A1D, 0xF3B7, 0x9A1E, 0xF3BE, 0x9A20, 0xF3BB, 0x9A22, 0xF3BA, 0x9A23, 0xF3BD, 0x9A24, 0xF3B8, 0x9A25, 0xF3B6, + 0x9A27, 0xF3BC, 0x9A29, 0xF560, 0x9A2A, 0xF55E, 0x9A2B, 0xC4CA, 0x9A2C, 0xF55D, 0x9A2D, 0xF563, 0x9A2E, 0xF561, 0x9A30, 0xC4CB, + 0x9A31, 0xF55C, 0x9A32, 0xF55A, 0x9A34, 0xF55B, 0x9A35, 0xC4CD, 0x9A36, 0xF55F, 0x9A37, 0xC4CC, 0x9A38, 0xF562, 0x9A39, 0xF678, + 0x9A3A, 0xF67E, 0x9A3D, 0xF679, 0x9A3E, 0xC55B, 0x9A3F, 0xF6A1, 0x9A40, 0xC55A, 0x9A41, 0xF67D, 0x9A42, 0xF67C, 0x9A43, 0xC559, + 0x9A44, 0xF67B, 0x9A45, 0xC558, 0x9A46, 0xF67A, 0x9A48, 0xF77D, 0x9A49, 0xF7A1, 0x9A4A, 0xF77E, 0x9A4C, 0xF77B, 0x9A4D, 0xC5BB, + 0x9A4E, 0xF778, 0x9A4F, 0xF77C, 0x9A50, 0xF7A3, 0x9A52, 0xF7A2, 0x9A53, 0xF779, 0x9A54, 0xF77A, 0x9A55, 0xC5BA, 0x9A56, 0xF852, + 0x9A57, 0xC5E7, 0x9A59, 0xF853, 0x9A5A, 0xC5E5, 0x9A5B, 0xC5E6, 0x9A5E, 0xF8D3, 0x9A5F, 0xC64A, 0x9A60, 0xF976, 0x9A62, 0xC66A, + 0x9A64, 0xF9B3, 0x9A65, 0xC66B, 0x9A66, 0xF9B4, 0x9A67, 0xF9B5, 0x9A68, 0xF9C3, 0x9A69, 0xF9C2, 0x9A6A, 0xC67A, 0x9A6B, 0xF9CD, + 0x9AA8, 0xB0A9, 0x9AAB, 0xE0E9, 0x9AAD, 0xE0E8, 0x9AAF, 0xBBEA, 0x9AB0, 0xBBEB, 0x9AB1, 0xE4DA, 0x9AB3, 0xE8D2, 0x9AB4, 0xEC6C, + 0x9AB7, 0xBE75, 0x9AB8, 0xC065, 0x9AB9, 0xEC6A, 0x9ABB, 0xEC6D, 0x9ABC, 0xC066, 0x9ABE, 0xEF64, 0x9ABF, 0xEC6B, 0x9AC0, 0xF1B9, + 0x9AC1, 0xC34E, 0x9AC2, 0xF3C1, 0x9AC6, 0xF566, 0x9AC7, 0xF564, 0x9ACA, 0xF565, 0x9ACD, 0xF6A2, 0x9ACF, 0xC55C, 0x9AD0, 0xF7A4, + 0x9AD1, 0xC5EA, 0x9AD2, 0xC5BC, 0x9AD3, 0xC5E8, 0x9AD4, 0xC5E9, 0x9AD5, 0xF8D4, 0x9AD6, 0xC662, 0x9AD8, 0xB0AA, 0x9ADC, 0xF1BA, + 0x9ADF, 0xD449, 0x9AE1, 0xB9A6, 0x9AE3, 0xE4DB, 0x9AE6, 0xBBEC, 0x9AE7, 0xE4DC, 0x9AEB, 0xE8D4, 0x9AEC, 0xE8D3, 0x9AED, 0xC068, + 0x9AEE, 0xBE76, 0x9AEF, 0xBE77, 0x9AF1, 0xE8D7, 0x9AF2, 0xE8D6, 0x9AF3, 0xE8D5, 0x9AF6, 0xEC6E, 0x9AF7, 0xEC71, 0x9AF9, 0xEC70, + 0x9AFA, 0xEC6F, 0x9AFB, 0xC067, 0x9AFC, 0xEF68, 0x9AFD, 0xEF66, 0x9AFE, 0xEF65, 0x9B01, 0xEF67, 0x9B03, 0xC34F, 0x9B04, 0xF1BC, + 0x9B05, 0xF1BD, 0x9B06, 0xC350, 0x9B08, 0xF1BB, 0x9B0A, 0xF3C3, 0x9B0B, 0xF3C2, 0x9B0C, 0xF3C5, 0x9B0D, 0xC447, 0x9B0E, 0xF3C4, + 0x9B10, 0xF567, 0x9B11, 0xF569, 0x9B12, 0xF568, 0x9B15, 0xF6A3, 0x9B16, 0xF6A6, 0x9B17, 0xF6A4, 0x9B18, 0xF6A5, 0x9B19, 0xF7A5, + 0x9B1A, 0xC5BD, 0x9B1E, 0xF854, 0x9B1F, 0xF855, 0x9B20, 0xF856, 0x9B22, 0xC64B, 0x9B23, 0xC663, 0x9B24, 0xF9B6, 0x9B25, 0xB0AB, + 0x9B27, 0xBE78, 0x9B28, 0xC069, 0x9B29, 0xF1BE, 0x9B2B, 0xF7A6, 0x9B2E, 0xF9C4, 0x9B2F, 0xD44A, 0x9B31, 0xC67B, 0x9B32, 0xB0AC, + 0x9B33, 0xEC72, 0x9B35, 0xF1BF, 0x9B37, 0xF3C6, 0x9B3A, 0xF6A7, 0x9B3B, 0xF7A7, 0x9B3C, 0xB0AD, 0x9B3E, 0xE4DD, 0x9B3F, 0xE4DE, + 0x9B41, 0xBBED, 0x9B42, 0xBBEE, 0x9B43, 0xE8D9, 0x9B44, 0xBE7A, 0x9B45, 0xBE79, 0x9B46, 0xE8D8, 0x9B48, 0xEF69, 0x9B4A, 0xF1C0, + 0x9B4B, 0xF1C2, 0x9B4C, 0xF1C1, 0x9B4D, 0xC353, 0x9B4E, 0xC352, 0x9B4F, 0xC351, 0x9B51, 0xC55E, 0x9B52, 0xF6A8, 0x9B54, 0xC55D, + 0x9B55, 0xF7A9, 0x9B56, 0xF7A8, 0x9B58, 0xC64C, 0x9B59, 0xF8D5, 0x9B5A, 0xB3BD, 0x9B5B, 0xE0EA, 0x9B5F, 0xE4E1, 0x9B60, 0xE4DF, + 0x9B61, 0xE4E0, 0x9B64, 0xE8E2, 0x9B66, 0xE8DD, 0x9B67, 0xE8DA, 0x9B68, 0xE8E1, 0x9B6C, 0xE8E3, 0x9B6F, 0xBE7C, 0x9B70, 0xE8E0, + 0x9B71, 0xE8DC, 0x9B74, 0xE8DB, 0x9B75, 0xE8DF, 0x9B76, 0xE8DE, 0x9B77, 0xBE7B, 0x9B7A, 0xEC7D, 0x9B7B, 0xEC78, 0x9B7C, 0xEC76, + 0x9B7D, 0xECA1, 0x9B7E, 0xEC77, 0x9B80, 0xEC73, 0x9B82, 0xEC79, 0x9B85, 0xEC74, 0x9B86, 0xEF72, 0x9B87, 0xEC75, 0x9B88, 0xECA2, + 0x9B90, 0xEC7C, 0x9B91, 0xC06A, 0x9B92, 0xEC7B, 0x9B93, 0xEC7A, 0x9B95, 0xEC7E, 0x9B9A, 0xEF6A, 0x9B9B, 0xEF6D, 0x9B9E, 0xEF6C, + 0x9BA0, 0xEF74, 0x9BA1, 0xEF6F, 0x9BA2, 0xEF73, 0x9BA4, 0xEF71, 0x9BA5, 0xEF70, 0x9BA6, 0xEF6E, 0x9BA8, 0xEF6B, 0x9BAA, 0xC243, + 0x9BAB, 0xC242, 0x9BAD, 0xC244, 0x9BAE, 0xC241, 0x9BAF, 0xEF75, 0x9BB5, 0xF1C8, 0x9BB6, 0xF1CB, 0x9BB8, 0xF1C9, 0x9BB9, 0xF1CD, + 0x9BBD, 0xF1CE, 0x9BBF, 0xF1C6, 0x9BC0, 0xC358, 0x9BC1, 0xF1C7, 0x9BC3, 0xF1C5, 0x9BC4, 0xF1CC, 0x9BC6, 0xF1C4, 0x9BC7, 0xF1C3, + 0x9BC8, 0xC357, 0x9BC9, 0xC355, 0x9BCA, 0xC354, 0x9BD3, 0xF1CA, 0x9BD4, 0xF3CF, 0x9BD5, 0xF3D5, 0x9BD6, 0xC44A, 0x9BD7, 0xF3D0, + 0x9BD9, 0xF3D3, 0x9BDA, 0xF3D7, 0x9BDB, 0xC44B, 0x9BDC, 0xF3D2, 0x9BDE, 0xF3CA, 0x9BE0, 0xF3C9, 0x9BE1, 0xF3D6, 0x9BE2, 0xF3CD, + 0x9BE4, 0xF3CB, 0x9BE5, 0xF3D4, 0x9BE6, 0xF3CC, 0x9BE7, 0xC449, 0x9BE8, 0xC448, 0x9BEA, 0xF3C7, 0x9BEB, 0xF3C8, 0x9BEC, 0xF3D1, + 0x9BF0, 0xF3CE, 0x9BF7, 0xF56C, 0x9BF8, 0xF56F, 0x9BFD, 0xC356, 0x9C05, 0xF56D, 0x9C06, 0xF573, 0x9C07, 0xF571, 0x9C08, 0xF56B, + 0x9C09, 0xF576, 0x9C0B, 0xF56A, 0x9C0D, 0xC4CF, 0x9C0E, 0xF572, 0x9C12, 0xF56E, 0x9C13, 0xC4CE, 0x9C14, 0xF575, 0x9C17, 0xF574, + 0x9C1C, 0xF6AB, 0x9C1D, 0xF6AA, 0x9C21, 0xF6B1, 0x9C23, 0xF6AD, 0x9C24, 0xF6B0, 0x9C25, 0xC560, 0x9C28, 0xF6AE, 0x9C29, 0xF6AF, + 0x9C2B, 0xF6A9, 0x9C2C, 0xF6AC, 0x9C2D, 0xC55F, 0x9C31, 0xC5BF, 0x9C32, 0xF7B4, 0x9C33, 0xF7AF, 0x9C34, 0xF7B3, 0x9C36, 0xF7B6, + 0x9C37, 0xF7B2, 0x9C39, 0xF7AE, 0x9C3B, 0xC5C1, 0x9C3C, 0xF7B1, 0x9C3D, 0xF7B5, 0x9C3E, 0xC5C0, 0x9C3F, 0xF7AC, 0x9C40, 0xF570, + 0x9C41, 0xF7B0, 0x9C44, 0xF7AD, 0x9C46, 0xF7AA, 0x9C48, 0xF7AB, 0x9C49, 0xC5BE, 0x9C4A, 0xF85A, 0x9C4B, 0xF85C, 0x9C4C, 0xF85F, + 0x9C4D, 0xF85B, 0x9C4E, 0xF860, 0x9C50, 0xF859, 0x9C52, 0xF857, 0x9C54, 0xC5EB, 0x9C55, 0xF85D, 0x9C56, 0xC5ED, 0x9C57, 0xC5EC, + 0x9C58, 0xF858, 0x9C59, 0xF85E, 0x9C5E, 0xF8DA, 0x9C5F, 0xC64D, 0x9C60, 0xF8DB, 0x9C62, 0xF8D9, 0x9C63, 0xF8D6, 0x9C66, 0xF8D8, + 0x9C67, 0xF8D7, 0x9C68, 0xF95A, 0x9C6D, 0xF95C, 0x9C6E, 0xF95B, 0x9C71, 0xF979, 0x9C73, 0xF978, 0x9C74, 0xF977, 0x9C75, 0xF97A, + 0x9C77, 0xC673, 0x9C78, 0xC674, 0x9C79, 0xF9CA, 0x9C7A, 0xF9CE, 0x9CE5, 0xB3BE, 0x9CE6, 0xDCAF, 0x9CE7, 0xE0ED, 0x9CE9, 0xB9A7, + 0x9CEA, 0xE0EB, 0x9CED, 0xE0EC, 0x9CF1, 0xE4E2, 0x9CF2, 0xE4E3, 0x9CF3, 0xBBF1, 0x9CF4, 0xBBEF, 0x9CF5, 0xE4E4, 0x9CF6, 0xBBF0, + 0x9CF7, 0xE8E8, 0x9CF9, 0xE8EB, 0x9CFA, 0xE8E5, 0x9CFB, 0xE8EC, 0x9CFC, 0xE8E4, 0x9CFD, 0xE8E6, 0x9CFF, 0xE8E7, 0x9D00, 0xE8EA, + 0x9D03, 0xBEA1, 0x9D04, 0xE8EF, 0x9D05, 0xE8EE, 0x9D06, 0xBE7D, 0x9D07, 0xE8E9, 0x9D08, 0xE8ED, 0x9D09, 0xBE7E, 0x9D10, 0xECAC, + 0x9D12, 0xC06F, 0x9D14, 0xECA7, 0x9D15, 0xC06B, 0x9D17, 0xECA4, 0x9D18, 0xECAA, 0x9D19, 0xECAD, 0x9D1B, 0xC070, 0x9D1D, 0xECA9, + 0x9D1E, 0xECA6, 0x9D1F, 0xECAE, 0x9D20, 0xECA5, 0x9D22, 0xECAB, 0x9D23, 0xC06C, 0x9D25, 0xECA3, 0x9D26, 0xC06D, 0x9D28, 0xC06E, + 0x9D29, 0xECA8, 0x9D2D, 0xEFA9, 0x9D2E, 0xEF7A, 0x9D2F, 0xEF7B, 0x9D30, 0xEF7E, 0x9D31, 0xEF7C, 0x9D33, 0xEF76, 0x9D36, 0xEF79, + 0x9D37, 0xEFA5, 0x9D38, 0xEF7D, 0x9D3B, 0xC245, 0x9D3D, 0xEFA7, 0x9D3E, 0xEFA4, 0x9D3F, 0xC246, 0x9D40, 0xEFA6, 0x9D41, 0xEF77, + 0x9D42, 0xEFA2, 0x9D43, 0xEFA3, 0x9D45, 0xEFA1, 0x9D4A, 0xF1D2, 0x9D4B, 0xF1D4, 0x9D4C, 0xF1D7, 0x9D4F, 0xF1D1, 0x9D51, 0xC359, + 0x9D52, 0xF1D9, 0x9D53, 0xF1D0, 0x9D54, 0xF1DA, 0x9D56, 0xF1D6, 0x9D57, 0xF1D8, 0x9D58, 0xF1DC, 0x9D59, 0xF1D5, 0x9D5A, 0xF1DD, + 0x9D5B, 0xF1D3, 0x9D5C, 0xF1CF, 0x9D5D, 0xC35A, 0x9D5F, 0xF1DB, 0x9D60, 0xC35B, 0x9D61, 0xC44D, 0x9D67, 0xEF78, 0x9D68, 0xF3F1, + 0x9D69, 0xF3E8, 0x9D6A, 0xC44F, 0x9D6B, 0xF3E4, 0x9D6C, 0xC450, 0x9D6F, 0xF3ED, 0x9D70, 0xF3E7, 0x9D71, 0xF3DD, 0x9D72, 0xC44E, + 0x9D73, 0xF3EA, 0x9D74, 0xF3E5, 0x9D75, 0xF3E6, 0x9D77, 0xF3D8, 0x9D78, 0xF3DF, 0x9D79, 0xF3EE, 0x9D7B, 0xF3EB, 0x9D7D, 0xF3E3, + 0x9D7F, 0xF3EF, 0x9D80, 0xF3DE, 0x9D81, 0xF3D9, 0x9D82, 0xF3EC, 0x9D84, 0xF3DB, 0x9D85, 0xF3E9, 0x9D86, 0xF3E0, 0x9D87, 0xF3F0, + 0x9D88, 0xF3DC, 0x9D89, 0xC44C, 0x9D8A, 0xF3DA, 0x9D8B, 0xF3E1, 0x9D8C, 0xF3E2, 0x9D90, 0xF57D, 0x9D92, 0xF57B, 0x9D94, 0xF5A2, + 0x9D96, 0xF5AE, 0x9D97, 0xF5A5, 0x9D98, 0xF57C, 0x9D99, 0xF578, 0x9D9A, 0xF5A7, 0x9D9B, 0xF57E, 0x9D9C, 0xF5A3, 0x9D9D, 0xF57A, + 0x9D9E, 0xF5AA, 0x9D9F, 0xF577, 0x9DA0, 0xF5A1, 0x9DA1, 0xF5A6, 0x9DA2, 0xF5A8, 0x9DA3, 0xF5AB, 0x9DA4, 0xF579, 0x9DA6, 0xF5AF, + 0x9DA7, 0xF5B0, 0x9DA8, 0xF5A9, 0x9DA9, 0xF5AD, 0x9DAA, 0xF5A4, 0x9DAC, 0xF6C1, 0x9DAD, 0xF6C4, 0x9DAF, 0xC561, 0x9DB1, 0xF6C3, + 0x9DB2, 0xF6C8, 0x9DB3, 0xF6C6, 0x9DB4, 0xC562, 0x9DB5, 0xF6BD, 0x9DB6, 0xF6B3, 0x9DB7, 0xF6B2, 0x9DB8, 0xC564, 0x9DB9, 0xF6BF, + 0x9DBA, 0xF6C0, 0x9DBB, 0xF6BC, 0x9DBC, 0xF6B4, 0x9DBE, 0xF6B9, 0x9DBF, 0xF5AC, 0x9DC1, 0xF6B5, 0x9DC2, 0xC563, 0x9DC3, 0xF6BB, + 0x9DC5, 0xF6BA, 0x9DC7, 0xF6B6, 0x9DC8, 0xF6C2, 0x9DCA, 0xF6B7, 0x9DCB, 0xF7BB, 0x9DCC, 0xF6C5, 0x9DCD, 0xF6C7, 0x9DCE, 0xF6BE, + 0x9DCF, 0xF6B8, 0x9DD0, 0xF7BC, 0x9DD1, 0xF7BE, 0x9DD2, 0xF7B8, 0x9DD3, 0xC5C2, 0x9DD5, 0xF7C5, 0x9DD6, 0xF7C3, 0x9DD7, 0xC5C3, + 0x9DD8, 0xF7C2, 0x9DD9, 0xF7C1, 0x9DDA, 0xF7BA, 0x9DDB, 0xF7B7, 0x9DDC, 0xF7BD, 0x9DDD, 0xF7C6, 0x9DDE, 0xF7B9, 0x9DDF, 0xF7BF, + 0x9DE1, 0xF869, 0x9DE2, 0xF86E, 0x9DE3, 0xF864, 0x9DE4, 0xF867, 0x9DE5, 0xC5EE, 0x9DE6, 0xF86B, 0x9DE8, 0xF872, 0x9DE9, 0xF7C0, + 0x9DEB, 0xF865, 0x9DEC, 0xF86F, 0x9DED, 0xF873, 0x9DEE, 0xF86A, 0x9DEF, 0xF863, 0x9DF0, 0xF86D, 0x9DF2, 0xF86C, 0x9DF3, 0xF871, + 0x9DF4, 0xF870, 0x9DF5, 0xF7C4, 0x9DF6, 0xF868, 0x9DF7, 0xF862, 0x9DF8, 0xF866, 0x9DF9, 0xC64E, 0x9DFA, 0xC64F, 0x9DFB, 0xF861, + 0x9DFD, 0xF8E6, 0x9DFE, 0xF8DD, 0x9DFF, 0xF8E5, 0x9E00, 0xF8E2, 0x9E01, 0xF8E3, 0x9E02, 0xF8DC, 0x9E03, 0xF8DF, 0x9E04, 0xF8E7, + 0x9E05, 0xF8E1, 0x9E06, 0xF8E0, 0x9E07, 0xF8DE, 0x9E09, 0xF8E4, 0x9E0B, 0xF95D, 0x9E0D, 0xF95E, 0x9E0F, 0xF960, 0x9E10, 0xF95F, + 0x9E11, 0xF962, 0x9E12, 0xF961, 0x9E13, 0xF97C, 0x9E14, 0xF97B, 0x9E15, 0xF9B7, 0x9E17, 0xF9B8, 0x9E19, 0xF9C5, 0x9E1A, 0xC678, + 0x9E1B, 0xC67C, 0x9E1D, 0xF9CF, 0x9E1E, 0xC67D, 0x9E75, 0xB3BF, 0x9E79, 0xC4D0, 0x9E7A, 0xF6C9, 0x9E7C, 0xC650, 0x9E7D, 0xC651, + 0x9E7F, 0xB3C0, 0x9E80, 0xE0EE, 0x9E82, 0xB9A8, 0x9E83, 0xE8F0, 0x9E86, 0xECB0, 0x9E87, 0xECB1, 0x9E88, 0xECAF, 0x9E89, 0xEFAB, + 0x9E8A, 0xEFAA, 0x9E8B, 0xC247, 0x9E8C, 0xF1DF, 0x9E8D, 0xEFAC, 0x9E8E, 0xF1DE, 0x9E91, 0xF3F3, 0x9E92, 0xC451, 0x9E93, 0xC453, + 0x9E94, 0xF3F2, 0x9E97, 0xC452, 0x9E99, 0xF5B1, 0x9E9A, 0xF5B3, 0x9E9B, 0xF5B2, 0x9E9C, 0xF6CA, 0x9E9D, 0xC565, 0x9E9F, 0xC5EF, + 0x9EA0, 0xF8E8, 0x9EA1, 0xF963, 0x9EA4, 0xF9D2, 0x9EA5, 0xB3C1, 0x9EA7, 0xE4E5, 0x9EA9, 0xBEA2, 0x9EAD, 0xECB3, 0x9EAE, 0xECB2, + 0x9EB0, 0xEFAD, 0x9EB4, 0xC454, 0x9EB5, 0xC4D1, 0x9EB6, 0xF7C7, 0x9EB7, 0xF9CB, 0x9EBB, 0xB3C2, 0x9EBC, 0xBBF2, 0x9EBE, 0xBEA3, + 0x9EC0, 0xF3F4, 0x9EC2, 0xF874, 0x9EC3, 0xB6C0, 0x9EC8, 0xEFAE, 0x9ECC, 0xC664, 0x9ECD, 0xB6C1, 0x9ECE, 0xBEA4, 0x9ECF, 0xC248, + 0x9ED0, 0xF875, 0x9ED1, 0xB6C2, 0x9ED3, 0xE8F1, 0x9ED4, 0xC072, 0x9ED5, 0xECB4, 0x9ED6, 0xECB5, 0x9ED8, 0xC071, 0x9EDA, 0xEFAF, + 0x9EDB, 0xC24C, 0x9EDC, 0xC24A, 0x9EDD, 0xC24B, 0x9EDE, 0xC249, 0x9EDF, 0xF1E0, 0x9EE0, 0xC35C, 0x9EE4, 0xF5B5, 0x9EE5, 0xF5B4, + 0x9EE6, 0xF5B7, 0x9EE7, 0xF5B6, 0x9EE8, 0xC4D2, 0x9EEB, 0xF6CB, 0x9EED, 0xF6CD, 0x9EEE, 0xF6CC, 0x9EEF, 0xC566, 0x9EF0, 0xF7C8, + 0x9EF2, 0xF876, 0x9EF3, 0xF877, 0x9EF4, 0xC5F0, 0x9EF5, 0xF964, 0x9EF6, 0xF97D, 0x9EF7, 0xC675, 0x9EF9, 0xDCB0, 0x9EFA, 0xECB6, + 0x9EFB, 0xEFB0, 0x9EFC, 0xF3F5, 0x9EFD, 0xE0EF, 0x9EFF, 0xEFB1, 0x9F00, 0xF1E2, 0x9F01, 0xF1E1, 0x9F06, 0xF878, 0x9F07, 0xC652, + 0x9F09, 0xF965, 0x9F0A, 0xF97E, 0x9F0E, 0xB9A9, 0x9F0F, 0xE8F2, 0x9F10, 0xE8F3, 0x9F12, 0xECB7, 0x9F13, 0xB9AA, 0x9F15, 0xC35D, + 0x9F16, 0xF1E3, 0x9F18, 0xF6CF, 0x9F19, 0xC567, 0x9F1A, 0xF6D0, 0x9F1B, 0xF6CE, 0x9F1C, 0xF879, 0x9F1E, 0xF8E9, 0x9F20, 0xB9AB, + 0x9F22, 0xEFB4, 0x9F23, 0xEFB3, 0x9F24, 0xEFB2, 0x9F25, 0xF1E4, 0x9F28, 0xF1E8, 0x9F29, 0xF1E7, 0x9F2A, 0xF1E6, 0x9F2B, 0xF1E5, + 0x9F2C, 0xC35E, 0x9F2D, 0xF3F6, 0x9F2E, 0xF5B9, 0x9F2F, 0xC4D3, 0x9F30, 0xF5B8, 0x9F31, 0xF6D1, 0x9F32, 0xF7CB, 0x9F33, 0xF7CA, + 0x9F34, 0xC5C4, 0x9F35, 0xF7C9, 0x9F36, 0xF87C, 0x9F37, 0xF87B, 0x9F38, 0xF87A, 0x9F3B, 0xBBF3, 0x9F3D, 0xECB8, 0x9F3E, 0xC24D, + 0x9F40, 0xF3F7, 0x9F41, 0xF3F8, 0x9F42, 0xF7CC, 0x9F43, 0xF87D, 0x9F46, 0xF8EA, 0x9F47, 0xF966, 0x9F48, 0xF9B9, 0x9F49, 0xF9D4, + 0x9F4A, 0xBBF4, 0x9F4B, 0xC24E, 0x9F4C, 0xF1E9, 0x9F4D, 0xF3F9, 0x9F4E, 0xF6D2, 0x9F4F, 0xF87E, 0x9F52, 0xBEA6, 0x9F54, 0xEFB5, + 0x9F55, 0xF1EA, 0x9F56, 0xF3FA, 0x9F57, 0xF3FB, 0x9F58, 0xF3FC, 0x9F59, 0xF5BE, 0x9F5B, 0xF5BA, 0x9F5C, 0xC568, 0x9F5D, 0xF5BD, + 0x9F5E, 0xF5BC, 0x9F5F, 0xC4D4, 0x9F60, 0xF5BB, 0x9F61, 0xC4D6, 0x9F63, 0xC4D5, 0x9F64, 0xF6D4, 0x9F65, 0xF6D3, 0x9F66, 0xC569, + 0x9F67, 0xC56A, 0x9F6A, 0xC5C6, 0x9F6B, 0xF7CD, 0x9F6C, 0xC5C5, 0x9F6E, 0xF8A3, 0x9F6F, 0xF8A4, 0x9F70, 0xF8A2, 0x9F71, 0xF8A1, + 0x9F72, 0xC654, 0x9F74, 0xF8EB, 0x9F75, 0xF8EC, 0x9F76, 0xF8ED, 0x9F77, 0xC653, 0x9F78, 0xF967, 0x9F79, 0xF96A, 0x9F7A, 0xF969, + 0x9F7B, 0xF968, 0x9F7E, 0xF9D3, 0x9F8D, 0xC073, 0x9F90, 0xC365, 0x9F91, 0xF5BF, 0x9F92, 0xF6D5, 0x9F94, 0xC5C7, 0x9F95, 0xF7CE, + 0x9F98, 0xF9D5, 0x9F9C, 0xC074, 0x9FA0, 0xEFB6, 0x9FA2, 0xF7CF, 0x9FA4, 0xF9A1, 0xFA0C, 0xC94A, 0xFA0D, 0xDDFC, 0xFE30, 0xA14A, + 0xFE31, 0xA157, 0xFE33, 0xA159, 0xFE34, 0xA15B, 0xFE35, 0xA15F, 0xFE36, 0xA160, 0xFE37, 0xA163, 0xFE38, 0xA164, 0xFE39, 0xA167, + 0xFE3A, 0xA168, 0xFE3B, 0xA16B, 0xFE3C, 0xA16C, 0xFE3D, 0xA16F, 0xFE3E, 0xA170, 0xFE3F, 0xA173, 0xFE40, 0xA174, 0xFE41, 0xA177, + 0xFE42, 0xA178, 0xFE43, 0xA17B, 0xFE44, 0xA17C, 0xFE49, 0xA1C6, 0xFE4A, 0xA1C7, 0xFE4B, 0xA1CA, 0xFE4C, 0xA1CB, 0xFE4D, 0xA1C8, + 0xFE4E, 0xA1C9, 0xFE4F, 0xA15C, 0xFE50, 0xA14D, 0xFE51, 0xA14E, 0xFE52, 0xA14F, 0xFE54, 0xA151, 0xFE55, 0xA152, 0xFE56, 0xA153, + 0xFE57, 0xA154, 0xFE59, 0xA17D, 0xFE5A, 0xA17E, 0xFE5B, 0xA1A1, 0xFE5C, 0xA1A2, 0xFE5D, 0xA1A3, 0xFE5E, 0xA1A4, 0xFE5F, 0xA1CC, + 0xFE60, 0xA1CD, 0xFE61, 0xA1CE, 0xFE62, 0xA1DE, 0xFE63, 0xA1DF, 0xFE64, 0xA1E0, 0xFE65, 0xA1E1, 0xFE66, 0xA1E2, 0xFE68, 0xA242, + 0xFE69, 0xA24C, 0xFE6A, 0xA24D, 0xFE6B, 0xA24E, 0xFF01, 0xA149, 0xFF03, 0xA1AD, 0xFF04, 0xA243, 0xFF05, 0xA248, 0xFF06, 0xA1AE, + 0xFF08, 0xA15D, 0xFF09, 0xA15E, 0xFF0A, 0xA1AF, 0xFF0B, 0xA1CF, 0xFF0C, 0xA141, 0xFF0D, 0xA1D0, 0xFF0E, 0xA144, 0xFF0F, 0xA1FE, + 0xFF10, 0xA2AF, 0xFF11, 0xA2B0, 0xFF12, 0xA2B1, 0xFF13, 0xA2B2, 0xFF14, 0xA2B3, 0xFF15, 0xA2B4, 0xFF16, 0xA2B5, 0xFF17, 0xA2B6, + 0xFF18, 0xA2B7, 0xFF19, 0xA2B8, 0xFF1A, 0xA147, 0xFF1B, 0xA146, 0xFF1C, 0xA1D5, 0xFF1D, 0xA1D7, 0xFF1E, 0xA1D6, 0xFF1F, 0xA148, + 0xFF20, 0xA249, 0xFF21, 0xA2CF, 0xFF22, 0xA2D0, 0xFF23, 0xA2D1, 0xFF24, 0xA2D2, 0xFF25, 0xA2D3, 0xFF26, 0xA2D4, 0xFF27, 0xA2D5, + 0xFF28, 0xA2D6, 0xFF29, 0xA2D7, 0xFF2A, 0xA2D8, 0xFF2B, 0xA2D9, 0xFF2C, 0xA2DA, 0xFF2D, 0xA2DB, 0xFF2E, 0xA2DC, 0xFF2F, 0xA2DD, + 0xFF30, 0xA2DE, 0xFF31, 0xA2DF, 0xFF32, 0xA2E0, 0xFF33, 0xA2E1, 0xFF34, 0xA2E2, 0xFF35, 0xA2E3, 0xFF36, 0xA2E4, 0xFF37, 0xA2E5, + 0xFF38, 0xA2E6, 0xFF39, 0xA2E7, 0xFF3A, 0xA2E8, 0xFF3C, 0xA240, 0xFF3F, 0xA1C4, 0xFF41, 0xA2E9, 0xFF42, 0xA2EA, 0xFF43, 0xA2EB, + 0xFF44, 0xA2EC, 0xFF45, 0xA2ED, 0xFF46, 0xA2EE, 0xFF47, 0xA2EF, 0xFF48, 0xA2F0, 0xFF49, 0xA2F1, 0xFF4A, 0xA2F2, 0xFF4B, 0xA2F3, + 0xFF4C, 0xA2F4, 0xFF4D, 0xA2F5, 0xFF4E, 0xA2F6, 0xFF4F, 0xA2F7, 0xFF50, 0xA2F8, 0xFF51, 0xA2F9, 0xFF52, 0xA2FA, 0xFF53, 0xA2FB, + 0xFF54, 0xA2FC, 0xFF55, 0xA2FD, 0xFF56, 0xA2FE, 0xFF57, 0xA340, 0xFF58, 0xA341, 0xFF59, 0xA342, 0xFF5A, 0xA343, 0xFF5B, 0xA161, + 0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0 +}; + +static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ + 0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A, + 0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52, + 0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31, + 0xA158, 0x2014, 0xA159, 0xFE33, 0xA15A, 0x2574, 0xA15B, 0xFE34, 0xA15C, 0xFE4F, 0xA15D, 0xFF08, 0xA15E, 0xFF09, 0xA15F, 0xFE35, + 0xA160, 0xFE36, 0xA161, 0xFF5B, 0xA162, 0xFF5D, 0xA163, 0xFE37, 0xA164, 0xFE38, 0xA165, 0x3014, 0xA166, 0x3015, 0xA167, 0xFE39, + 0xA168, 0xFE3A, 0xA169, 0x3010, 0xA16A, 0x3011, 0xA16B, 0xFE3B, 0xA16C, 0xFE3C, 0xA16D, 0x300A, 0xA16E, 0x300B, 0xA16F, 0xFE3D, + 0xA170, 0xFE3E, 0xA171, 0x3008, 0xA172, 0x3009, 0xA173, 0xFE3F, 0xA174, 0xFE40, 0xA175, 0x300C, 0xA176, 0x300D, 0xA177, 0xFE41, + 0xA178, 0xFE42, 0xA179, 0x300E, 0xA17A, 0x300F, 0xA17B, 0xFE43, 0xA17C, 0xFE44, 0xA17D, 0xFE59, 0xA17E, 0xFE5A, 0xA1A1, 0xFE5B, + 0xA1A2, 0xFE5C, 0xA1A3, 0xFE5D, 0xA1A4, 0xFE5E, 0xA1A5, 0x2018, 0xA1A6, 0x2019, 0xA1A7, 0x201C, 0xA1A8, 0x201D, 0xA1A9, 0x301D, + 0xA1AA, 0x301E, 0xA1AB, 0x2035, 0xA1AC, 0x2032, 0xA1AD, 0xFF03, 0xA1AE, 0xFF06, 0xA1AF, 0xFF0A, 0xA1B0, 0x203B, 0xA1B1, 0x00A7, + 0xA1B2, 0x3003, 0xA1B3, 0x25CB, 0xA1B4, 0x25CF, 0xA1B5, 0x25B3, 0xA1B6, 0x25B2, 0xA1B7, 0x25CE, 0xA1B8, 0x2606, 0xA1B9, 0x2605, + 0xA1BA, 0x25C7, 0xA1BB, 0x25C6, 0xA1BC, 0x25A1, 0xA1BD, 0x25A0, 0xA1BE, 0x25BD, 0xA1BF, 0x25BC, 0xA1C0, 0x32A3, 0xA1C1, 0x2105, + 0xA1C2, 0x00AF, 0xA1C3, 0xFFE3, 0xA1C4, 0xFF3F, 0xA1C5, 0x02CD, 0xA1C6, 0xFE49, 0xA1C7, 0xFE4A, 0xA1C8, 0xFE4D, 0xA1C9, 0xFE4E, + 0xA1CA, 0xFE4B, 0xA1CB, 0xFE4C, 0xA1CC, 0xFE5F, 0xA1CD, 0xFE60, 0xA1CE, 0xFE61, 0xA1CF, 0xFF0B, 0xA1D0, 0xFF0D, 0xA1D1, 0x00D7, + 0xA1D2, 0x00F7, 0xA1D3, 0x00B1, 0xA1D4, 0x221A, 0xA1D5, 0xFF1C, 0xA1D6, 0xFF1E, 0xA1D7, 0xFF1D, 0xA1D8, 0x2266, 0xA1D9, 0x2267, + 0xA1DA, 0x2260, 0xA1DB, 0x221E, 0xA1DC, 0x2252, 0xA1DD, 0x2261, 0xA1DE, 0xFE62, 0xA1DF, 0xFE63, 0xA1E0, 0xFE64, 0xA1E1, 0xFE65, + 0xA1E2, 0xFE66, 0xA1E3, 0xFF5E, 0xA1E4, 0x2229, 0xA1E5, 0x222A, 0xA1E6, 0x22A5, 0xA1E7, 0x2220, 0xA1E8, 0x221F, 0xA1E9, 0x22BF, + 0xA1EA, 0x33D2, 0xA1EB, 0x33D1, 0xA1EC, 0x222B, 0xA1ED, 0x222E, 0xA1EE, 0x2235, 0xA1EF, 0x2234, 0xA1F0, 0x2640, 0xA1F1, 0x2642, + 0xA1F2, 0x2295, 0xA1F3, 0x2299, 0xA1F4, 0x2191, 0xA1F5, 0x2193, 0xA1F6, 0x2190, 0xA1F7, 0x2192, 0xA1F8, 0x2196, 0xA1F9, 0x2197, + 0xA1FA, 0x2199, 0xA1FB, 0x2198, 0xA1FC, 0x2225, 0xA1FD, 0x2223, 0xA1FE, 0xFF0F, 0xA240, 0xFF3C, 0xA241, 0x2215, 0xA242, 0xFE68, + 0xA243, 0xFF04, 0xA244, 0xFFE5, 0xA245, 0x3012, 0xA246, 0xFFE0, 0xA247, 0xFFE1, 0xA248, 0xFF05, 0xA249, 0xFF20, 0xA24A, 0x2103, + 0xA24B, 0x2109, 0xA24C, 0xFE69, 0xA24D, 0xFE6A, 0xA24E, 0xFE6B, 0xA24F, 0x33D5, 0xA250, 0x339C, 0xA251, 0x339D, 0xA252, 0x339E, + 0xA253, 0x33CE, 0xA254, 0x33A1, 0xA255, 0x338E, 0xA256, 0x338F, 0xA257, 0x33C4, 0xA258, 0x00B0, 0xA259, 0x5159, 0xA25A, 0x515B, + 0xA25B, 0x515E, 0xA25C, 0x515D, 0xA25D, 0x5161, 0xA25E, 0x5163, 0xA25F, 0x55E7, 0xA260, 0x74E9, 0xA261, 0x7CCE, 0xA262, 0x2581, + 0xA263, 0x2582, 0xA264, 0x2583, 0xA265, 0x2584, 0xA266, 0x2585, 0xA267, 0x2586, 0xA268, 0x2587, 0xA269, 0x2588, 0xA26A, 0x258F, + 0xA26B, 0x258E, 0xA26C, 0x258D, 0xA26D, 0x258C, 0xA26E, 0x258B, 0xA26F, 0x258A, 0xA270, 0x2589, 0xA271, 0x253C, 0xA272, 0x2534, + 0xA273, 0x252C, 0xA274, 0x2524, 0xA275, 0x251C, 0xA276, 0x2594, 0xA277, 0x2500, 0xA278, 0x2502, 0xA279, 0x2595, 0xA27A, 0x250C, + 0xA27B, 0x2510, 0xA27C, 0x2514, 0xA27D, 0x2518, 0xA27E, 0x256D, 0xA2A1, 0x256E, 0xA2A2, 0x2570, 0xA2A3, 0x256F, 0xA2A4, 0x2550, + 0xA2A5, 0x255E, 0xA2A6, 0x256A, 0xA2A7, 0x2561, 0xA2A8, 0x25E2, 0xA2A9, 0x25E3, 0xA2AA, 0x25E5, 0xA2AB, 0x25E4, 0xA2AC, 0x2571, + 0xA2AD, 0x2572, 0xA2AE, 0x2573, 0xA2AF, 0xFF10, 0xA2B0, 0xFF11, 0xA2B1, 0xFF12, 0xA2B2, 0xFF13, 0xA2B3, 0xFF14, 0xA2B4, 0xFF15, + 0xA2B5, 0xFF16, 0xA2B6, 0xFF17, 0xA2B7, 0xFF18, 0xA2B8, 0xFF19, 0xA2B9, 0x2160, 0xA2BA, 0x2161, 0xA2BB, 0x2162, 0xA2BC, 0x2163, + 0xA2BD, 0x2164, 0xA2BE, 0x2165, 0xA2BF, 0x2166, 0xA2C0, 0x2167, 0xA2C1, 0x2168, 0xA2C2, 0x2169, 0xA2C3, 0x3021, 0xA2C4, 0x3022, + 0xA2C5, 0x3023, 0xA2C6, 0x3024, 0xA2C7, 0x3025, 0xA2C8, 0x3026, 0xA2C9, 0x3027, 0xA2CA, 0x3028, 0xA2CB, 0x3029, 0xA2CC, 0x5341, + 0xA2CD, 0x5344, 0xA2CE, 0x5345, 0xA2CF, 0xFF21, 0xA2D0, 0xFF22, 0xA2D1, 0xFF23, 0xA2D2, 0xFF24, 0xA2D3, 0xFF25, 0xA2D4, 0xFF26, + 0xA2D5, 0xFF27, 0xA2D6, 0xFF28, 0xA2D7, 0xFF29, 0xA2D8, 0xFF2A, 0xA2D9, 0xFF2B, 0xA2DA, 0xFF2C, 0xA2DB, 0xFF2D, 0xA2DC, 0xFF2E, + 0xA2DD, 0xFF2F, 0xA2DE, 0xFF30, 0xA2DF, 0xFF31, 0xA2E0, 0xFF32, 0xA2E1, 0xFF33, 0xA2E2, 0xFF34, 0xA2E3, 0xFF35, 0xA2E4, 0xFF36, + 0xA2E5, 0xFF37, 0xA2E6, 0xFF38, 0xA2E7, 0xFF39, 0xA2E8, 0xFF3A, 0xA2E9, 0xFF41, 0xA2EA, 0xFF42, 0xA2EB, 0xFF43, 0xA2EC, 0xFF44, + 0xA2ED, 0xFF45, 0xA2EE, 0xFF46, 0xA2EF, 0xFF47, 0xA2F0, 0xFF48, 0xA2F1, 0xFF49, 0xA2F2, 0xFF4A, 0xA2F3, 0xFF4B, 0xA2F4, 0xFF4C, + 0xA2F5, 0xFF4D, 0xA2F6, 0xFF4E, 0xA2F7, 0xFF4F, 0xA2F8, 0xFF50, 0xA2F9, 0xFF51, 0xA2FA, 0xFF52, 0xA2FB, 0xFF53, 0xA2FC, 0xFF54, + 0xA2FD, 0xFF55, 0xA2FE, 0xFF56, 0xA340, 0xFF57, 0xA341, 0xFF58, 0xA342, 0xFF59, 0xA343, 0xFF5A, 0xA344, 0x0391, 0xA345, 0x0392, + 0xA346, 0x0393, 0xA347, 0x0394, 0xA348, 0x0395, 0xA349, 0x0396, 0xA34A, 0x0397, 0xA34B, 0x0398, 0xA34C, 0x0399, 0xA34D, 0x039A, + 0xA34E, 0x039B, 0xA34F, 0x039C, 0xA350, 0x039D, 0xA351, 0x039E, 0xA352, 0x039F, 0xA353, 0x03A0, 0xA354, 0x03A1, 0xA355, 0x03A3, + 0xA356, 0x03A4, 0xA357, 0x03A5, 0xA358, 0x03A6, 0xA359, 0x03A7, 0xA35A, 0x03A8, 0xA35B, 0x03A9, 0xA35C, 0x03B1, 0xA35D, 0x03B2, + 0xA35E, 0x03B3, 0xA35F, 0x03B4, 0xA360, 0x03B5, 0xA361, 0x03B6, 0xA362, 0x03B7, 0xA363, 0x03B8, 0xA364, 0x03B9, 0xA365, 0x03BA, + 0xA366, 0x03BB, 0xA367, 0x03BC, 0xA368, 0x03BD, 0xA369, 0x03BE, 0xA36A, 0x03BF, 0xA36B, 0x03C0, 0xA36C, 0x03C1, 0xA36D, 0x03C3, + 0xA36E, 0x03C4, 0xA36F, 0x03C5, 0xA370, 0x03C6, 0xA371, 0x03C7, 0xA372, 0x03C8, 0xA373, 0x03C9, 0xA374, 0x3105, 0xA375, 0x3106, + 0xA376, 0x3107, 0xA377, 0x3108, 0xA378, 0x3109, 0xA379, 0x310A, 0xA37A, 0x310B, 0xA37B, 0x310C, 0xA37C, 0x310D, 0xA37D, 0x310E, + 0xA37E, 0x310F, 0xA3A1, 0x3110, 0xA3A2, 0x3111, 0xA3A3, 0x3112, 0xA3A4, 0x3113, 0xA3A5, 0x3114, 0xA3A6, 0x3115, 0xA3A7, 0x3116, + 0xA3A8, 0x3117, 0xA3A9, 0x3118, 0xA3AA, 0x3119, 0xA3AB, 0x311A, 0xA3AC, 0x311B, 0xA3AD, 0x311C, 0xA3AE, 0x311D, 0xA3AF, 0x311E, + 0xA3B0, 0x311F, 0xA3B1, 0x3120, 0xA3B2, 0x3121, 0xA3B3, 0x3122, 0xA3B4, 0x3123, 0xA3B5, 0x3124, 0xA3B6, 0x3125, 0xA3B7, 0x3126, + 0xA3B8, 0x3127, 0xA3B9, 0x3128, 0xA3BA, 0x3129, 0xA3BB, 0x02D9, 0xA3BC, 0x02C9, 0xA3BD, 0x02CA, 0xA3BE, 0x02C7, 0xA3BF, 0x02CB, + 0xA3E1, 0x20AC, 0xA440, 0x4E00, 0xA441, 0x4E59, 0xA442, 0x4E01, 0xA443, 0x4E03, 0xA444, 0x4E43, 0xA445, 0x4E5D, 0xA446, 0x4E86, + 0xA447, 0x4E8C, 0xA448, 0x4EBA, 0xA449, 0x513F, 0xA44A, 0x5165, 0xA44B, 0x516B, 0xA44C, 0x51E0, 0xA44D, 0x5200, 0xA44E, 0x5201, + 0xA44F, 0x529B, 0xA450, 0x5315, 0xA451, 0x5341, 0xA452, 0x535C, 0xA453, 0x53C8, 0xA454, 0x4E09, 0xA455, 0x4E0B, 0xA456, 0x4E08, + 0xA457, 0x4E0A, 0xA458, 0x4E2B, 0xA459, 0x4E38, 0xA45A, 0x51E1, 0xA45B, 0x4E45, 0xA45C, 0x4E48, 0xA45D, 0x4E5F, 0xA45E, 0x4E5E, + 0xA45F, 0x4E8E, 0xA460, 0x4EA1, 0xA461, 0x5140, 0xA462, 0x5203, 0xA463, 0x52FA, 0xA464, 0x5343, 0xA465, 0x53C9, 0xA466, 0x53E3, + 0xA467, 0x571F, 0xA468, 0x58EB, 0xA469, 0x5915, 0xA46A, 0x5927, 0xA46B, 0x5973, 0xA46C, 0x5B50, 0xA46D, 0x5B51, 0xA46E, 0x5B53, + 0xA46F, 0x5BF8, 0xA470, 0x5C0F, 0xA471, 0x5C22, 0xA472, 0x5C38, 0xA473, 0x5C71, 0xA474, 0x5DDD, 0xA475, 0x5DE5, 0xA476, 0x5DF1, + 0xA477, 0x5DF2, 0xA478, 0x5DF3, 0xA479, 0x5DFE, 0xA47A, 0x5E72, 0xA47B, 0x5EFE, 0xA47C, 0x5F0B, 0xA47D, 0x5F13, 0xA47E, 0x624D, + 0xA4A1, 0x4E11, 0xA4A2, 0x4E10, 0xA4A3, 0x4E0D, 0xA4A4, 0x4E2D, 0xA4A5, 0x4E30, 0xA4A6, 0x4E39, 0xA4A7, 0x4E4B, 0xA4A8, 0x5C39, + 0xA4A9, 0x4E88, 0xA4AA, 0x4E91, 0xA4AB, 0x4E95, 0xA4AC, 0x4E92, 0xA4AD, 0x4E94, 0xA4AE, 0x4EA2, 0xA4AF, 0x4EC1, 0xA4B0, 0x4EC0, + 0xA4B1, 0x4EC3, 0xA4B2, 0x4EC6, 0xA4B3, 0x4EC7, 0xA4B4, 0x4ECD, 0xA4B5, 0x4ECA, 0xA4B6, 0x4ECB, 0xA4B7, 0x4EC4, 0xA4B8, 0x5143, + 0xA4B9, 0x5141, 0xA4BA, 0x5167, 0xA4BB, 0x516D, 0xA4BC, 0x516E, 0xA4BD, 0x516C, 0xA4BE, 0x5197, 0xA4BF, 0x51F6, 0xA4C0, 0x5206, + 0xA4C1, 0x5207, 0xA4C2, 0x5208, 0xA4C3, 0x52FB, 0xA4C4, 0x52FE, 0xA4C5, 0x52FF, 0xA4C6, 0x5316, 0xA4C7, 0x5339, 0xA4C8, 0x5348, + 0xA4C9, 0x5347, 0xA4CA, 0x5345, 0xA4CB, 0x535E, 0xA4CC, 0x5384, 0xA4CD, 0x53CB, 0xA4CE, 0x53CA, 0xA4CF, 0x53CD, 0xA4D0, 0x58EC, + 0xA4D1, 0x5929, 0xA4D2, 0x592B, 0xA4D3, 0x592A, 0xA4D4, 0x592D, 0xA4D5, 0x5B54, 0xA4D6, 0x5C11, 0xA4D7, 0x5C24, 0xA4D8, 0x5C3A, + 0xA4D9, 0x5C6F, 0xA4DA, 0x5DF4, 0xA4DB, 0x5E7B, 0xA4DC, 0x5EFF, 0xA4DD, 0x5F14, 0xA4DE, 0x5F15, 0xA4DF, 0x5FC3, 0xA4E0, 0x6208, + 0xA4E1, 0x6236, 0xA4E2, 0x624B, 0xA4E3, 0x624E, 0xA4E4, 0x652F, 0xA4E5, 0x6587, 0xA4E6, 0x6597, 0xA4E7, 0x65A4, 0xA4E8, 0x65B9, + 0xA4E9, 0x65E5, 0xA4EA, 0x66F0, 0xA4EB, 0x6708, 0xA4EC, 0x6728, 0xA4ED, 0x6B20, 0xA4EE, 0x6B62, 0xA4EF, 0x6B79, 0xA4F0, 0x6BCB, + 0xA4F1, 0x6BD4, 0xA4F2, 0x6BDB, 0xA4F3, 0x6C0F, 0xA4F4, 0x6C34, 0xA4F5, 0x706B, 0xA4F6, 0x722A, 0xA4F7, 0x7236, 0xA4F8, 0x723B, + 0xA4F9, 0x7247, 0xA4FA, 0x7259, 0xA4FB, 0x725B, 0xA4FC, 0x72AC, 0xA4FD, 0x738B, 0xA4FE, 0x4E19, 0xA540, 0x4E16, 0xA541, 0x4E15, + 0xA542, 0x4E14, 0xA543, 0x4E18, 0xA544, 0x4E3B, 0xA545, 0x4E4D, 0xA546, 0x4E4F, 0xA547, 0x4E4E, 0xA548, 0x4EE5, 0xA549, 0x4ED8, + 0xA54A, 0x4ED4, 0xA54B, 0x4ED5, 0xA54C, 0x4ED6, 0xA54D, 0x4ED7, 0xA54E, 0x4EE3, 0xA54F, 0x4EE4, 0xA550, 0x4ED9, 0xA551, 0x4EDE, + 0xA552, 0x5145, 0xA553, 0x5144, 0xA554, 0x5189, 0xA555, 0x518A, 0xA556, 0x51AC, 0xA557, 0x51F9, 0xA558, 0x51FA, 0xA559, 0x51F8, + 0xA55A, 0x520A, 0xA55B, 0x52A0, 0xA55C, 0x529F, 0xA55D, 0x5305, 0xA55E, 0x5306, 0xA55F, 0x5317, 0xA560, 0x531D, 0xA561, 0x4EDF, + 0xA562, 0x534A, 0xA563, 0x5349, 0xA564, 0x5361, 0xA565, 0x5360, 0xA566, 0x536F, 0xA567, 0x536E, 0xA568, 0x53BB, 0xA569, 0x53EF, + 0xA56A, 0x53E4, 0xA56B, 0x53F3, 0xA56C, 0x53EC, 0xA56D, 0x53EE, 0xA56E, 0x53E9, 0xA56F, 0x53E8, 0xA570, 0x53FC, 0xA571, 0x53F8, + 0xA572, 0x53F5, 0xA573, 0x53EB, 0xA574, 0x53E6, 0xA575, 0x53EA, 0xA576, 0x53F2, 0xA577, 0x53F1, 0xA578, 0x53F0, 0xA579, 0x53E5, + 0xA57A, 0x53ED, 0xA57B, 0x53FB, 0xA57C, 0x56DB, 0xA57D, 0x56DA, 0xA57E, 0x5916, 0xA5A1, 0x592E, 0xA5A2, 0x5931, 0xA5A3, 0x5974, + 0xA5A4, 0x5976, 0xA5A5, 0x5B55, 0xA5A6, 0x5B83, 0xA5A7, 0x5C3C, 0xA5A8, 0x5DE8, 0xA5A9, 0x5DE7, 0xA5AA, 0x5DE6, 0xA5AB, 0x5E02, + 0xA5AC, 0x5E03, 0xA5AD, 0x5E73, 0xA5AE, 0x5E7C, 0xA5AF, 0x5F01, 0xA5B0, 0x5F18, 0xA5B1, 0x5F17, 0xA5B2, 0x5FC5, 0xA5B3, 0x620A, + 0xA5B4, 0x6253, 0xA5B5, 0x6254, 0xA5B6, 0x6252, 0xA5B7, 0x6251, 0xA5B8, 0x65A5, 0xA5B9, 0x65E6, 0xA5BA, 0x672E, 0xA5BB, 0x672C, + 0xA5BC, 0x672A, 0xA5BD, 0x672B, 0xA5BE, 0x672D, 0xA5BF, 0x6B63, 0xA5C0, 0x6BCD, 0xA5C1, 0x6C11, 0xA5C2, 0x6C10, 0xA5C3, 0x6C38, + 0xA5C4, 0x6C41, 0xA5C5, 0x6C40, 0xA5C6, 0x6C3E, 0xA5C7, 0x72AF, 0xA5C8, 0x7384, 0xA5C9, 0x7389, 0xA5CA, 0x74DC, 0xA5CB, 0x74E6, + 0xA5CC, 0x7518, 0xA5CD, 0x751F, 0xA5CE, 0x7528, 0xA5CF, 0x7529, 0xA5D0, 0x7530, 0xA5D1, 0x7531, 0xA5D2, 0x7532, 0xA5D3, 0x7533, + 0xA5D4, 0x758B, 0xA5D5, 0x767D, 0xA5D6, 0x76AE, 0xA5D7, 0x76BF, 0xA5D8, 0x76EE, 0xA5D9, 0x77DB, 0xA5DA, 0x77E2, 0xA5DB, 0x77F3, + 0xA5DC, 0x793A, 0xA5DD, 0x79BE, 0xA5DE, 0x7A74, 0xA5DF, 0x7ACB, 0xA5E0, 0x4E1E, 0xA5E1, 0x4E1F, 0xA5E2, 0x4E52, 0xA5E3, 0x4E53, + 0xA5E4, 0x4E69, 0xA5E5, 0x4E99, 0xA5E6, 0x4EA4, 0xA5E7, 0x4EA6, 0xA5E8, 0x4EA5, 0xA5E9, 0x4EFF, 0xA5EA, 0x4F09, 0xA5EB, 0x4F19, + 0xA5EC, 0x4F0A, 0xA5ED, 0x4F15, 0xA5EE, 0x4F0D, 0xA5EF, 0x4F10, 0xA5F0, 0x4F11, 0xA5F1, 0x4F0F, 0xA5F2, 0x4EF2, 0xA5F3, 0x4EF6, + 0xA5F4, 0x4EFB, 0xA5F5, 0x4EF0, 0xA5F6, 0x4EF3, 0xA5F7, 0x4EFD, 0xA5F8, 0x4F01, 0xA5F9, 0x4F0B, 0xA5FA, 0x5149, 0xA5FB, 0x5147, + 0xA5FC, 0x5146, 0xA5FD, 0x5148, 0xA5FE, 0x5168, 0xA640, 0x5171, 0xA641, 0x518D, 0xA642, 0x51B0, 0xA643, 0x5217, 0xA644, 0x5211, + 0xA645, 0x5212, 0xA646, 0x520E, 0xA647, 0x5216, 0xA648, 0x52A3, 0xA649, 0x5308, 0xA64A, 0x5321, 0xA64B, 0x5320, 0xA64C, 0x5370, + 0xA64D, 0x5371, 0xA64E, 0x5409, 0xA64F, 0x540F, 0xA650, 0x540C, 0xA651, 0x540A, 0xA652, 0x5410, 0xA653, 0x5401, 0xA654, 0x540B, + 0xA655, 0x5404, 0xA656, 0x5411, 0xA657, 0x540D, 0xA658, 0x5408, 0xA659, 0x5403, 0xA65A, 0x540E, 0xA65B, 0x5406, 0xA65C, 0x5412, + 0xA65D, 0x56E0, 0xA65E, 0x56DE, 0xA65F, 0x56DD, 0xA660, 0x5733, 0xA661, 0x5730, 0xA662, 0x5728, 0xA663, 0x572D, 0xA664, 0x572C, + 0xA665, 0x572F, 0xA666, 0x5729, 0xA667, 0x5919, 0xA668, 0x591A, 0xA669, 0x5937, 0xA66A, 0x5938, 0xA66B, 0x5984, 0xA66C, 0x5978, + 0xA66D, 0x5983, 0xA66E, 0x597D, 0xA66F, 0x5979, 0xA670, 0x5982, 0xA671, 0x5981, 0xA672, 0x5B57, 0xA673, 0x5B58, 0xA674, 0x5B87, + 0xA675, 0x5B88, 0xA676, 0x5B85, 0xA677, 0x5B89, 0xA678, 0x5BFA, 0xA679, 0x5C16, 0xA67A, 0x5C79, 0xA67B, 0x5DDE, 0xA67C, 0x5E06, + 0xA67D, 0x5E76, 0xA67E, 0x5E74, 0xA6A1, 0x5F0F, 0xA6A2, 0x5F1B, 0xA6A3, 0x5FD9, 0xA6A4, 0x5FD6, 0xA6A5, 0x620E, 0xA6A6, 0x620C, + 0xA6A7, 0x620D, 0xA6A8, 0x6210, 0xA6A9, 0x6263, 0xA6AA, 0x625B, 0xA6AB, 0x6258, 0xA6AC, 0x6536, 0xA6AD, 0x65E9, 0xA6AE, 0x65E8, + 0xA6AF, 0x65EC, 0xA6B0, 0x65ED, 0xA6B1, 0x66F2, 0xA6B2, 0x66F3, 0xA6B3, 0x6709, 0xA6B4, 0x673D, 0xA6B5, 0x6734, 0xA6B6, 0x6731, + 0xA6B7, 0x6735, 0xA6B8, 0x6B21, 0xA6B9, 0x6B64, 0xA6BA, 0x6B7B, 0xA6BB, 0x6C16, 0xA6BC, 0x6C5D, 0xA6BD, 0x6C57, 0xA6BE, 0x6C59, + 0xA6BF, 0x6C5F, 0xA6C0, 0x6C60, 0xA6C1, 0x6C50, 0xA6C2, 0x6C55, 0xA6C3, 0x6C61, 0xA6C4, 0x6C5B, 0xA6C5, 0x6C4D, 0xA6C6, 0x6C4E, + 0xA6C7, 0x7070, 0xA6C8, 0x725F, 0xA6C9, 0x725D, 0xA6CA, 0x767E, 0xA6CB, 0x7AF9, 0xA6CC, 0x7C73, 0xA6CD, 0x7CF8, 0xA6CE, 0x7F36, + 0xA6CF, 0x7F8A, 0xA6D0, 0x7FBD, 0xA6D1, 0x8001, 0xA6D2, 0x8003, 0xA6D3, 0x800C, 0xA6D4, 0x8012, 0xA6D5, 0x8033, 0xA6D6, 0x807F, + 0xA6D7, 0x8089, 0xA6D8, 0x808B, 0xA6D9, 0x808C, 0xA6DA, 0x81E3, 0xA6DB, 0x81EA, 0xA6DC, 0x81F3, 0xA6DD, 0x81FC, 0xA6DE, 0x820C, + 0xA6DF, 0x821B, 0xA6E0, 0x821F, 0xA6E1, 0x826E, 0xA6E2, 0x8272, 0xA6E3, 0x827E, 0xA6E4, 0x866B, 0xA6E5, 0x8840, 0xA6E6, 0x884C, + 0xA6E7, 0x8863, 0xA6E8, 0x897F, 0xA6E9, 0x9621, 0xA6EA, 0x4E32, 0xA6EB, 0x4EA8, 0xA6EC, 0x4F4D, 0xA6ED, 0x4F4F, 0xA6EE, 0x4F47, + 0xA6EF, 0x4F57, 0xA6F0, 0x4F5E, 0xA6F1, 0x4F34, 0xA6F2, 0x4F5B, 0xA6F3, 0x4F55, 0xA6F4, 0x4F30, 0xA6F5, 0x4F50, 0xA6F6, 0x4F51, + 0xA6F7, 0x4F3D, 0xA6F8, 0x4F3A, 0xA6F9, 0x4F38, 0xA6FA, 0x4F43, 0xA6FB, 0x4F54, 0xA6FC, 0x4F3C, 0xA6FD, 0x4F46, 0xA6FE, 0x4F63, + 0xA740, 0x4F5C, 0xA741, 0x4F60, 0xA742, 0x4F2F, 0xA743, 0x4F4E, 0xA744, 0x4F36, 0xA745, 0x4F59, 0xA746, 0x4F5D, 0xA747, 0x4F48, + 0xA748, 0x4F5A, 0xA749, 0x514C, 0xA74A, 0x514B, 0xA74B, 0x514D, 0xA74C, 0x5175, 0xA74D, 0x51B6, 0xA74E, 0x51B7, 0xA74F, 0x5225, + 0xA750, 0x5224, 0xA751, 0x5229, 0xA752, 0x522A, 0xA753, 0x5228, 0xA754, 0x52AB, 0xA755, 0x52A9, 0xA756, 0x52AA, 0xA757, 0x52AC, + 0xA758, 0x5323, 0xA759, 0x5373, 0xA75A, 0x5375, 0xA75B, 0x541D, 0xA75C, 0x542D, 0xA75D, 0x541E, 0xA75E, 0x543E, 0xA75F, 0x5426, + 0xA760, 0x544E, 0xA761, 0x5427, 0xA762, 0x5446, 0xA763, 0x5443, 0xA764, 0x5433, 0xA765, 0x5448, 0xA766, 0x5442, 0xA767, 0x541B, + 0xA768, 0x5429, 0xA769, 0x544A, 0xA76A, 0x5439, 0xA76B, 0x543B, 0xA76C, 0x5438, 0xA76D, 0x542E, 0xA76E, 0x5435, 0xA76F, 0x5436, + 0xA770, 0x5420, 0xA771, 0x543C, 0xA772, 0x5440, 0xA773, 0x5431, 0xA774, 0x542B, 0xA775, 0x541F, 0xA776, 0x542C, 0xA777, 0x56EA, + 0xA778, 0x56F0, 0xA779, 0x56E4, 0xA77A, 0x56EB, 0xA77B, 0x574A, 0xA77C, 0x5751, 0xA77D, 0x5740, 0xA77E, 0x574D, 0xA7A1, 0x5747, + 0xA7A2, 0x574E, 0xA7A3, 0x573E, 0xA7A4, 0x5750, 0xA7A5, 0x574F, 0xA7A6, 0x573B, 0xA7A7, 0x58EF, 0xA7A8, 0x593E, 0xA7A9, 0x599D, + 0xA7AA, 0x5992, 0xA7AB, 0x59A8, 0xA7AC, 0x599E, 0xA7AD, 0x59A3, 0xA7AE, 0x5999, 0xA7AF, 0x5996, 0xA7B0, 0x598D, 0xA7B1, 0x59A4, + 0xA7B2, 0x5993, 0xA7B3, 0x598A, 0xA7B4, 0x59A5, 0xA7B5, 0x5B5D, 0xA7B6, 0x5B5C, 0xA7B7, 0x5B5A, 0xA7B8, 0x5B5B, 0xA7B9, 0x5B8C, + 0xA7BA, 0x5B8B, 0xA7BB, 0x5B8F, 0xA7BC, 0x5C2C, 0xA7BD, 0x5C40, 0xA7BE, 0x5C41, 0xA7BF, 0x5C3F, 0xA7C0, 0x5C3E, 0xA7C1, 0x5C90, + 0xA7C2, 0x5C91, 0xA7C3, 0x5C94, 0xA7C4, 0x5C8C, 0xA7C5, 0x5DEB, 0xA7C6, 0x5E0C, 0xA7C7, 0x5E8F, 0xA7C8, 0x5E87, 0xA7C9, 0x5E8A, + 0xA7CA, 0x5EF7, 0xA7CB, 0x5F04, 0xA7CC, 0x5F1F, 0xA7CD, 0x5F64, 0xA7CE, 0x5F62, 0xA7CF, 0x5F77, 0xA7D0, 0x5F79, 0xA7D1, 0x5FD8, + 0xA7D2, 0x5FCC, 0xA7D3, 0x5FD7, 0xA7D4, 0x5FCD, 0xA7D5, 0x5FF1, 0xA7D6, 0x5FEB, 0xA7D7, 0x5FF8, 0xA7D8, 0x5FEA, 0xA7D9, 0x6212, + 0xA7DA, 0x6211, 0xA7DB, 0x6284, 0xA7DC, 0x6297, 0xA7DD, 0x6296, 0xA7DE, 0x6280, 0xA7DF, 0x6276, 0xA7E0, 0x6289, 0xA7E1, 0x626D, + 0xA7E2, 0x628A, 0xA7E3, 0x627C, 0xA7E4, 0x627E, 0xA7E5, 0x6279, 0xA7E6, 0x6273, 0xA7E7, 0x6292, 0xA7E8, 0x626F, 0xA7E9, 0x6298, + 0xA7EA, 0x626E, 0xA7EB, 0x6295, 0xA7EC, 0x6293, 0xA7ED, 0x6291, 0xA7EE, 0x6286, 0xA7EF, 0x6539, 0xA7F0, 0x653B, 0xA7F1, 0x6538, + 0xA7F2, 0x65F1, 0xA7F3, 0x66F4, 0xA7F4, 0x675F, 0xA7F5, 0x674E, 0xA7F6, 0x674F, 0xA7F7, 0x6750, 0xA7F8, 0x6751, 0xA7F9, 0x675C, + 0xA7FA, 0x6756, 0xA7FB, 0x675E, 0xA7FC, 0x6749, 0xA7FD, 0x6746, 0xA7FE, 0x6760, 0xA840, 0x6753, 0xA841, 0x6757, 0xA842, 0x6B65, + 0xA843, 0x6BCF, 0xA844, 0x6C42, 0xA845, 0x6C5E, 0xA846, 0x6C99, 0xA847, 0x6C81, 0xA848, 0x6C88, 0xA849, 0x6C89, 0xA84A, 0x6C85, + 0xA84B, 0x6C9B, 0xA84C, 0x6C6A, 0xA84D, 0x6C7A, 0xA84E, 0x6C90, 0xA84F, 0x6C70, 0xA850, 0x6C8C, 0xA851, 0x6C68, 0xA852, 0x6C96, + 0xA853, 0x6C92, 0xA854, 0x6C7D, 0xA855, 0x6C83, 0xA856, 0x6C72, 0xA857, 0x6C7E, 0xA858, 0x6C74, 0xA859, 0x6C86, 0xA85A, 0x6C76, + 0xA85B, 0x6C8D, 0xA85C, 0x6C94, 0xA85D, 0x6C98, 0xA85E, 0x6C82, 0xA85F, 0x7076, 0xA860, 0x707C, 0xA861, 0x707D, 0xA862, 0x7078, + 0xA863, 0x7262, 0xA864, 0x7261, 0xA865, 0x7260, 0xA866, 0x72C4, 0xA867, 0x72C2, 0xA868, 0x7396, 0xA869, 0x752C, 0xA86A, 0x752B, + 0xA86B, 0x7537, 0xA86C, 0x7538, 0xA86D, 0x7682, 0xA86E, 0x76EF, 0xA86F, 0x77E3, 0xA870, 0x79C1, 0xA871, 0x79C0, 0xA872, 0x79BF, + 0xA873, 0x7A76, 0xA874, 0x7CFB, 0xA875, 0x7F55, 0xA876, 0x8096, 0xA877, 0x8093, 0xA878, 0x809D, 0xA879, 0x8098, 0xA87A, 0x809B, + 0xA87B, 0x809A, 0xA87C, 0x80B2, 0xA87D, 0x826F, 0xA87E, 0x8292, 0xA8A1, 0x828B, 0xA8A2, 0x828D, 0xA8A3, 0x898B, 0xA8A4, 0x89D2, + 0xA8A5, 0x8A00, 0xA8A6, 0x8C37, 0xA8A7, 0x8C46, 0xA8A8, 0x8C55, 0xA8A9, 0x8C9D, 0xA8AA, 0x8D64, 0xA8AB, 0x8D70, 0xA8AC, 0x8DB3, + 0xA8AD, 0x8EAB, 0xA8AE, 0x8ECA, 0xA8AF, 0x8F9B, 0xA8B0, 0x8FB0, 0xA8B1, 0x8FC2, 0xA8B2, 0x8FC6, 0xA8B3, 0x8FC5, 0xA8B4, 0x8FC4, + 0xA8B5, 0x5DE1, 0xA8B6, 0x9091, 0xA8B7, 0x90A2, 0xA8B8, 0x90AA, 0xA8B9, 0x90A6, 0xA8BA, 0x90A3, 0xA8BB, 0x9149, 0xA8BC, 0x91C6, + 0xA8BD, 0x91CC, 0xA8BE, 0x9632, 0xA8BF, 0x962E, 0xA8C0, 0x9631, 0xA8C1, 0x962A, 0xA8C2, 0x962C, 0xA8C3, 0x4E26, 0xA8C4, 0x4E56, + 0xA8C5, 0x4E73, 0xA8C6, 0x4E8B, 0xA8C7, 0x4E9B, 0xA8C8, 0x4E9E, 0xA8C9, 0x4EAB, 0xA8CA, 0x4EAC, 0xA8CB, 0x4F6F, 0xA8CC, 0x4F9D, + 0xA8CD, 0x4F8D, 0xA8CE, 0x4F73, 0xA8CF, 0x4F7F, 0xA8D0, 0x4F6C, 0xA8D1, 0x4F9B, 0xA8D2, 0x4F8B, 0xA8D3, 0x4F86, 0xA8D4, 0x4F83, + 0xA8D5, 0x4F70, 0xA8D6, 0x4F75, 0xA8D7, 0x4F88, 0xA8D8, 0x4F69, 0xA8D9, 0x4F7B, 0xA8DA, 0x4F96, 0xA8DB, 0x4F7E, 0xA8DC, 0x4F8F, + 0xA8DD, 0x4F91, 0xA8DE, 0x4F7A, 0xA8DF, 0x5154, 0xA8E0, 0x5152, 0xA8E1, 0x5155, 0xA8E2, 0x5169, 0xA8E3, 0x5177, 0xA8E4, 0x5176, + 0xA8E5, 0x5178, 0xA8E6, 0x51BD, 0xA8E7, 0x51FD, 0xA8E8, 0x523B, 0xA8E9, 0x5238, 0xA8EA, 0x5237, 0xA8EB, 0x523A, 0xA8EC, 0x5230, + 0xA8ED, 0x522E, 0xA8EE, 0x5236, 0xA8EF, 0x5241, 0xA8F0, 0x52BE, 0xA8F1, 0x52BB, 0xA8F2, 0x5352, 0xA8F3, 0x5354, 0xA8F4, 0x5353, + 0xA8F5, 0x5351, 0xA8F6, 0x5366, 0xA8F7, 0x5377, 0xA8F8, 0x5378, 0xA8F9, 0x5379, 0xA8FA, 0x53D6, 0xA8FB, 0x53D4, 0xA8FC, 0x53D7, + 0xA8FD, 0x5473, 0xA8FE, 0x5475, 0xA940, 0x5496, 0xA941, 0x5478, 0xA942, 0x5495, 0xA943, 0x5480, 0xA944, 0x547B, 0xA945, 0x5477, + 0xA946, 0x5484, 0xA947, 0x5492, 0xA948, 0x5486, 0xA949, 0x547C, 0xA94A, 0x5490, 0xA94B, 0x5471, 0xA94C, 0x5476, 0xA94D, 0x548C, + 0xA94E, 0x549A, 0xA94F, 0x5462, 0xA950, 0x5468, 0xA951, 0x548B, 0xA952, 0x547D, 0xA953, 0x548E, 0xA954, 0x56FA, 0xA955, 0x5783, + 0xA956, 0x5777, 0xA957, 0x576A, 0xA958, 0x5769, 0xA959, 0x5761, 0xA95A, 0x5766, 0xA95B, 0x5764, 0xA95C, 0x577C, 0xA95D, 0x591C, + 0xA95E, 0x5949, 0xA95F, 0x5947, 0xA960, 0x5948, 0xA961, 0x5944, 0xA962, 0x5954, 0xA963, 0x59BE, 0xA964, 0x59BB, 0xA965, 0x59D4, + 0xA966, 0x59B9, 0xA967, 0x59AE, 0xA968, 0x59D1, 0xA969, 0x59C6, 0xA96A, 0x59D0, 0xA96B, 0x59CD, 0xA96C, 0x59CB, 0xA96D, 0x59D3, + 0xA96E, 0x59CA, 0xA96F, 0x59AF, 0xA970, 0x59B3, 0xA971, 0x59D2, 0xA972, 0x59C5, 0xA973, 0x5B5F, 0xA974, 0x5B64, 0xA975, 0x5B63, + 0xA976, 0x5B97, 0xA977, 0x5B9A, 0xA978, 0x5B98, 0xA979, 0x5B9C, 0xA97A, 0x5B99, 0xA97B, 0x5B9B, 0xA97C, 0x5C1A, 0xA97D, 0x5C48, + 0xA97E, 0x5C45, 0xA9A1, 0x5C46, 0xA9A2, 0x5CB7, 0xA9A3, 0x5CA1, 0xA9A4, 0x5CB8, 0xA9A5, 0x5CA9, 0xA9A6, 0x5CAB, 0xA9A7, 0x5CB1, + 0xA9A8, 0x5CB3, 0xA9A9, 0x5E18, 0xA9AA, 0x5E1A, 0xA9AB, 0x5E16, 0xA9AC, 0x5E15, 0xA9AD, 0x5E1B, 0xA9AE, 0x5E11, 0xA9AF, 0x5E78, + 0xA9B0, 0x5E9A, 0xA9B1, 0x5E97, 0xA9B2, 0x5E9C, 0xA9B3, 0x5E95, 0xA9B4, 0x5E96, 0xA9B5, 0x5EF6, 0xA9B6, 0x5F26, 0xA9B7, 0x5F27, + 0xA9B8, 0x5F29, 0xA9B9, 0x5F80, 0xA9BA, 0x5F81, 0xA9BB, 0x5F7F, 0xA9BC, 0x5F7C, 0xA9BD, 0x5FDD, 0xA9BE, 0x5FE0, 0xA9BF, 0x5FFD, + 0xA9C0, 0x5FF5, 0xA9C1, 0x5FFF, 0xA9C2, 0x600F, 0xA9C3, 0x6014, 0xA9C4, 0x602F, 0xA9C5, 0x6035, 0xA9C6, 0x6016, 0xA9C7, 0x602A, + 0xA9C8, 0x6015, 0xA9C9, 0x6021, 0xA9CA, 0x6027, 0xA9CB, 0x6029, 0xA9CC, 0x602B, 0xA9CD, 0x601B, 0xA9CE, 0x6216, 0xA9CF, 0x6215, + 0xA9D0, 0x623F, 0xA9D1, 0x623E, 0xA9D2, 0x6240, 0xA9D3, 0x627F, 0xA9D4, 0x62C9, 0xA9D5, 0x62CC, 0xA9D6, 0x62C4, 0xA9D7, 0x62BF, + 0xA9D8, 0x62C2, 0xA9D9, 0x62B9, 0xA9DA, 0x62D2, 0xA9DB, 0x62DB, 0xA9DC, 0x62AB, 0xA9DD, 0x62D3, 0xA9DE, 0x62D4, 0xA9DF, 0x62CB, + 0xA9E0, 0x62C8, 0xA9E1, 0x62A8, 0xA9E2, 0x62BD, 0xA9E3, 0x62BC, 0xA9E4, 0x62D0, 0xA9E5, 0x62D9, 0xA9E6, 0x62C7, 0xA9E7, 0x62CD, + 0xA9E8, 0x62B5, 0xA9E9, 0x62DA, 0xA9EA, 0x62B1, 0xA9EB, 0x62D8, 0xA9EC, 0x62D6, 0xA9ED, 0x62D7, 0xA9EE, 0x62C6, 0xA9EF, 0x62AC, + 0xA9F0, 0x62CE, 0xA9F1, 0x653E, 0xA9F2, 0x65A7, 0xA9F3, 0x65BC, 0xA9F4, 0x65FA, 0xA9F5, 0x6614, 0xA9F6, 0x6613, 0xA9F7, 0x660C, + 0xA9F8, 0x6606, 0xA9F9, 0x6602, 0xA9FA, 0x660E, 0xA9FB, 0x6600, 0xA9FC, 0x660F, 0xA9FD, 0x6615, 0xA9FE, 0x660A, 0xAA40, 0x6607, + 0xAA41, 0x670D, 0xAA42, 0x670B, 0xAA43, 0x676D, 0xAA44, 0x678B, 0xAA45, 0x6795, 0xAA46, 0x6771, 0xAA47, 0x679C, 0xAA48, 0x6773, + 0xAA49, 0x6777, 0xAA4A, 0x6787, 0xAA4B, 0x679D, 0xAA4C, 0x6797, 0xAA4D, 0x676F, 0xAA4E, 0x6770, 0xAA4F, 0x677F, 0xAA50, 0x6789, + 0xAA51, 0x677E, 0xAA52, 0x6790, 0xAA53, 0x6775, 0xAA54, 0x679A, 0xAA55, 0x6793, 0xAA56, 0x677C, 0xAA57, 0x676A, 0xAA58, 0x6772, + 0xAA59, 0x6B23, 0xAA5A, 0x6B66, 0xAA5B, 0x6B67, 0xAA5C, 0x6B7F, 0xAA5D, 0x6C13, 0xAA5E, 0x6C1B, 0xAA5F, 0x6CE3, 0xAA60, 0x6CE8, + 0xAA61, 0x6CF3, 0xAA62, 0x6CB1, 0xAA63, 0x6CCC, 0xAA64, 0x6CE5, 0xAA65, 0x6CB3, 0xAA66, 0x6CBD, 0xAA67, 0x6CBE, 0xAA68, 0x6CBC, + 0xAA69, 0x6CE2, 0xAA6A, 0x6CAB, 0xAA6B, 0x6CD5, 0xAA6C, 0x6CD3, 0xAA6D, 0x6CB8, 0xAA6E, 0x6CC4, 0xAA6F, 0x6CB9, 0xAA70, 0x6CC1, + 0xAA71, 0x6CAE, 0xAA72, 0x6CD7, 0xAA73, 0x6CC5, 0xAA74, 0x6CF1, 0xAA75, 0x6CBF, 0xAA76, 0x6CBB, 0xAA77, 0x6CE1, 0xAA78, 0x6CDB, + 0xAA79, 0x6CCA, 0xAA7A, 0x6CAC, 0xAA7B, 0x6CEF, 0xAA7C, 0x6CDC, 0xAA7D, 0x6CD6, 0xAA7E, 0x6CE0, 0xAAA1, 0x7095, 0xAAA2, 0x708E, + 0xAAA3, 0x7092, 0xAAA4, 0x708A, 0xAAA5, 0x7099, 0xAAA6, 0x722C, 0xAAA7, 0x722D, 0xAAA8, 0x7238, 0xAAA9, 0x7248, 0xAAAA, 0x7267, + 0xAAAB, 0x7269, 0xAAAC, 0x72C0, 0xAAAD, 0x72CE, 0xAAAE, 0x72D9, 0xAAAF, 0x72D7, 0xAAB0, 0x72D0, 0xAAB1, 0x73A9, 0xAAB2, 0x73A8, + 0xAAB3, 0x739F, 0xAAB4, 0x73AB, 0xAAB5, 0x73A5, 0xAAB6, 0x753D, 0xAAB7, 0x759D, 0xAAB8, 0x7599, 0xAAB9, 0x759A, 0xAABA, 0x7684, + 0xAABB, 0x76C2, 0xAABC, 0x76F2, 0xAABD, 0x76F4, 0xAABE, 0x77E5, 0xAABF, 0x77FD, 0xAAC0, 0x793E, 0xAAC1, 0x7940, 0xAAC2, 0x7941, + 0xAAC3, 0x79C9, 0xAAC4, 0x79C8, 0xAAC5, 0x7A7A, 0xAAC6, 0x7A79, 0xAAC7, 0x7AFA, 0xAAC8, 0x7CFE, 0xAAC9, 0x7F54, 0xAACA, 0x7F8C, + 0xAACB, 0x7F8B, 0xAACC, 0x8005, 0xAACD, 0x80BA, 0xAACE, 0x80A5, 0xAACF, 0x80A2, 0xAAD0, 0x80B1, 0xAAD1, 0x80A1, 0xAAD2, 0x80AB, + 0xAAD3, 0x80A9, 0xAAD4, 0x80B4, 0xAAD5, 0x80AA, 0xAAD6, 0x80AF, 0xAAD7, 0x81E5, 0xAAD8, 0x81FE, 0xAAD9, 0x820D, 0xAADA, 0x82B3, + 0xAADB, 0x829D, 0xAADC, 0x8299, 0xAADD, 0x82AD, 0xAADE, 0x82BD, 0xAADF, 0x829F, 0xAAE0, 0x82B9, 0xAAE1, 0x82B1, 0xAAE2, 0x82AC, + 0xAAE3, 0x82A5, 0xAAE4, 0x82AF, 0xAAE5, 0x82B8, 0xAAE6, 0x82A3, 0xAAE7, 0x82B0, 0xAAE8, 0x82BE, 0xAAE9, 0x82B7, 0xAAEA, 0x864E, + 0xAAEB, 0x8671, 0xAAEC, 0x521D, 0xAAED, 0x8868, 0xAAEE, 0x8ECB, 0xAAEF, 0x8FCE, 0xAAF0, 0x8FD4, 0xAAF1, 0x8FD1, 0xAAF2, 0x90B5, + 0xAAF3, 0x90B8, 0xAAF4, 0x90B1, 0xAAF5, 0x90B6, 0xAAF6, 0x91C7, 0xAAF7, 0x91D1, 0xAAF8, 0x9577, 0xAAF9, 0x9580, 0xAAFA, 0x961C, + 0xAAFB, 0x9640, 0xAAFC, 0x963F, 0xAAFD, 0x963B, 0xAAFE, 0x9644, 0xAB40, 0x9642, 0xAB41, 0x96B9, 0xAB42, 0x96E8, 0xAB43, 0x9752, + 0xAB44, 0x975E, 0xAB45, 0x4E9F, 0xAB46, 0x4EAD, 0xAB47, 0x4EAE, 0xAB48, 0x4FE1, 0xAB49, 0x4FB5, 0xAB4A, 0x4FAF, 0xAB4B, 0x4FBF, + 0xAB4C, 0x4FE0, 0xAB4D, 0x4FD1, 0xAB4E, 0x4FCF, 0xAB4F, 0x4FDD, 0xAB50, 0x4FC3, 0xAB51, 0x4FB6, 0xAB52, 0x4FD8, 0xAB53, 0x4FDF, + 0xAB54, 0x4FCA, 0xAB55, 0x4FD7, 0xAB56, 0x4FAE, 0xAB57, 0x4FD0, 0xAB58, 0x4FC4, 0xAB59, 0x4FC2, 0xAB5A, 0x4FDA, 0xAB5B, 0x4FCE, + 0xAB5C, 0x4FDE, 0xAB5D, 0x4FB7, 0xAB5E, 0x5157, 0xAB5F, 0x5192, 0xAB60, 0x5191, 0xAB61, 0x51A0, 0xAB62, 0x524E, 0xAB63, 0x5243, + 0xAB64, 0x524A, 0xAB65, 0x524D, 0xAB66, 0x524C, 0xAB67, 0x524B, 0xAB68, 0x5247, 0xAB69, 0x52C7, 0xAB6A, 0x52C9, 0xAB6B, 0x52C3, + 0xAB6C, 0x52C1, 0xAB6D, 0x530D, 0xAB6E, 0x5357, 0xAB6F, 0x537B, 0xAB70, 0x539A, 0xAB71, 0x53DB, 0xAB72, 0x54AC, 0xAB73, 0x54C0, + 0xAB74, 0x54A8, 0xAB75, 0x54CE, 0xAB76, 0x54C9, 0xAB77, 0x54B8, 0xAB78, 0x54A6, 0xAB79, 0x54B3, 0xAB7A, 0x54C7, 0xAB7B, 0x54C2, + 0xAB7C, 0x54BD, 0xAB7D, 0x54AA, 0xAB7E, 0x54C1, 0xABA1, 0x54C4, 0xABA2, 0x54C8, 0xABA3, 0x54AF, 0xABA4, 0x54AB, 0xABA5, 0x54B1, + 0xABA6, 0x54BB, 0xABA7, 0x54A9, 0xABA8, 0x54A7, 0xABA9, 0x54BF, 0xABAA, 0x56FF, 0xABAB, 0x5782, 0xABAC, 0x578B, 0xABAD, 0x57A0, + 0xABAE, 0x57A3, 0xABAF, 0x57A2, 0xABB0, 0x57CE, 0xABB1, 0x57AE, 0xABB2, 0x5793, 0xABB3, 0x5955, 0xABB4, 0x5951, 0xABB5, 0x594F, + 0xABB6, 0x594E, 0xABB7, 0x5950, 0xABB8, 0x59DC, 0xABB9, 0x59D8, 0xABBA, 0x59FF, 0xABBB, 0x59E3, 0xABBC, 0x59E8, 0xABBD, 0x5A03, + 0xABBE, 0x59E5, 0xABBF, 0x59EA, 0xABC0, 0x59DA, 0xABC1, 0x59E6, 0xABC2, 0x5A01, 0xABC3, 0x59FB, 0xABC4, 0x5B69, 0xABC5, 0x5BA3, + 0xABC6, 0x5BA6, 0xABC7, 0x5BA4, 0xABC8, 0x5BA2, 0xABC9, 0x5BA5, 0xABCA, 0x5C01, 0xABCB, 0x5C4E, 0xABCC, 0x5C4F, 0xABCD, 0x5C4D, + 0xABCE, 0x5C4B, 0xABCF, 0x5CD9, 0xABD0, 0x5CD2, 0xABD1, 0x5DF7, 0xABD2, 0x5E1D, 0xABD3, 0x5E25, 0xABD4, 0x5E1F, 0xABD5, 0x5E7D, + 0xABD6, 0x5EA0, 0xABD7, 0x5EA6, 0xABD8, 0x5EFA, 0xABD9, 0x5F08, 0xABDA, 0x5F2D, 0xABDB, 0x5F65, 0xABDC, 0x5F88, 0xABDD, 0x5F85, + 0xABDE, 0x5F8A, 0xABDF, 0x5F8B, 0xABE0, 0x5F87, 0xABE1, 0x5F8C, 0xABE2, 0x5F89, 0xABE3, 0x6012, 0xABE4, 0x601D, 0xABE5, 0x6020, + 0xABE6, 0x6025, 0xABE7, 0x600E, 0xABE8, 0x6028, 0xABE9, 0x604D, 0xABEA, 0x6070, 0xABEB, 0x6068, 0xABEC, 0x6062, 0xABED, 0x6046, + 0xABEE, 0x6043, 0xABEF, 0x606C, 0xABF0, 0x606B, 0xABF1, 0x606A, 0xABF2, 0x6064, 0xABF3, 0x6241, 0xABF4, 0x62DC, 0xABF5, 0x6316, + 0xABF6, 0x6309, 0xABF7, 0x62FC, 0xABF8, 0x62ED, 0xABF9, 0x6301, 0xABFA, 0x62EE, 0xABFB, 0x62FD, 0xABFC, 0x6307, 0xABFD, 0x62F1, + 0xABFE, 0x62F7, 0xAC40, 0x62EF, 0xAC41, 0x62EC, 0xAC42, 0x62FE, 0xAC43, 0x62F4, 0xAC44, 0x6311, 0xAC45, 0x6302, 0xAC46, 0x653F, + 0xAC47, 0x6545, 0xAC48, 0x65AB, 0xAC49, 0x65BD, 0xAC4A, 0x65E2, 0xAC4B, 0x6625, 0xAC4C, 0x662D, 0xAC4D, 0x6620, 0xAC4E, 0x6627, + 0xAC4F, 0x662F, 0xAC50, 0x661F, 0xAC51, 0x6628, 0xAC52, 0x6631, 0xAC53, 0x6624, 0xAC54, 0x66F7, 0xAC55, 0x67FF, 0xAC56, 0x67D3, + 0xAC57, 0x67F1, 0xAC58, 0x67D4, 0xAC59, 0x67D0, 0xAC5A, 0x67EC, 0xAC5B, 0x67B6, 0xAC5C, 0x67AF, 0xAC5D, 0x67F5, 0xAC5E, 0x67E9, + 0xAC5F, 0x67EF, 0xAC60, 0x67C4, 0xAC61, 0x67D1, 0xAC62, 0x67B4, 0xAC63, 0x67DA, 0xAC64, 0x67E5, 0xAC65, 0x67B8, 0xAC66, 0x67CF, + 0xAC67, 0x67DE, 0xAC68, 0x67F3, 0xAC69, 0x67B0, 0xAC6A, 0x67D9, 0xAC6B, 0x67E2, 0xAC6C, 0x67DD, 0xAC6D, 0x67D2, 0xAC6E, 0x6B6A, + 0xAC6F, 0x6B83, 0xAC70, 0x6B86, 0xAC71, 0x6BB5, 0xAC72, 0x6BD2, 0xAC73, 0x6BD7, 0xAC74, 0x6C1F, 0xAC75, 0x6CC9, 0xAC76, 0x6D0B, + 0xAC77, 0x6D32, 0xAC78, 0x6D2A, 0xAC79, 0x6D41, 0xAC7A, 0x6D25, 0xAC7B, 0x6D0C, 0xAC7C, 0x6D31, 0xAC7D, 0x6D1E, 0xAC7E, 0x6D17, + 0xACA1, 0x6D3B, 0xACA2, 0x6D3D, 0xACA3, 0x6D3E, 0xACA4, 0x6D36, 0xACA5, 0x6D1B, 0xACA6, 0x6CF5, 0xACA7, 0x6D39, 0xACA8, 0x6D27, + 0xACA9, 0x6D38, 0xACAA, 0x6D29, 0xACAB, 0x6D2E, 0xACAC, 0x6D35, 0xACAD, 0x6D0E, 0xACAE, 0x6D2B, 0xACAF, 0x70AB, 0xACB0, 0x70BA, + 0xACB1, 0x70B3, 0xACB2, 0x70AC, 0xACB3, 0x70AF, 0xACB4, 0x70AD, 0xACB5, 0x70B8, 0xACB6, 0x70AE, 0xACB7, 0x70A4, 0xACB8, 0x7230, + 0xACB9, 0x7272, 0xACBA, 0x726F, 0xACBB, 0x7274, 0xACBC, 0x72E9, 0xACBD, 0x72E0, 0xACBE, 0x72E1, 0xACBF, 0x73B7, 0xACC0, 0x73CA, + 0xACC1, 0x73BB, 0xACC2, 0x73B2, 0xACC3, 0x73CD, 0xACC4, 0x73C0, 0xACC5, 0x73B3, 0xACC6, 0x751A, 0xACC7, 0x752D, 0xACC8, 0x754F, + 0xACC9, 0x754C, 0xACCA, 0x754E, 0xACCB, 0x754B, 0xACCC, 0x75AB, 0xACCD, 0x75A4, 0xACCE, 0x75A5, 0xACCF, 0x75A2, 0xACD0, 0x75A3, + 0xACD1, 0x7678, 0xACD2, 0x7686, 0xACD3, 0x7687, 0xACD4, 0x7688, 0xACD5, 0x76C8, 0xACD6, 0x76C6, 0xACD7, 0x76C3, 0xACD8, 0x76C5, + 0xACD9, 0x7701, 0xACDA, 0x76F9, 0xACDB, 0x76F8, 0xACDC, 0x7709, 0xACDD, 0x770B, 0xACDE, 0x76FE, 0xACDF, 0x76FC, 0xACE0, 0x7707, + 0xACE1, 0x77DC, 0xACE2, 0x7802, 0xACE3, 0x7814, 0xACE4, 0x780C, 0xACE5, 0x780D, 0xACE6, 0x7946, 0xACE7, 0x7949, 0xACE8, 0x7948, + 0xACE9, 0x7947, 0xACEA, 0x79B9, 0xACEB, 0x79BA, 0xACEC, 0x79D1, 0xACED, 0x79D2, 0xACEE, 0x79CB, 0xACEF, 0x7A7F, 0xACF0, 0x7A81, + 0xACF1, 0x7AFF, 0xACF2, 0x7AFD, 0xACF3, 0x7C7D, 0xACF4, 0x7D02, 0xACF5, 0x7D05, 0xACF6, 0x7D00, 0xACF7, 0x7D09, 0xACF8, 0x7D07, + 0xACF9, 0x7D04, 0xACFA, 0x7D06, 0xACFB, 0x7F38, 0xACFC, 0x7F8E, 0xACFD, 0x7FBF, 0xACFE, 0x8004, 0xAD40, 0x8010, 0xAD41, 0x800D, + 0xAD42, 0x8011, 0xAD43, 0x8036, 0xAD44, 0x80D6, 0xAD45, 0x80E5, 0xAD46, 0x80DA, 0xAD47, 0x80C3, 0xAD48, 0x80C4, 0xAD49, 0x80CC, + 0xAD4A, 0x80E1, 0xAD4B, 0x80DB, 0xAD4C, 0x80CE, 0xAD4D, 0x80DE, 0xAD4E, 0x80E4, 0xAD4F, 0x80DD, 0xAD50, 0x81F4, 0xAD51, 0x8222, + 0xAD52, 0x82E7, 0xAD53, 0x8303, 0xAD54, 0x8305, 0xAD55, 0x82E3, 0xAD56, 0x82DB, 0xAD57, 0x82E6, 0xAD58, 0x8304, 0xAD59, 0x82E5, + 0xAD5A, 0x8302, 0xAD5B, 0x8309, 0xAD5C, 0x82D2, 0xAD5D, 0x82D7, 0xAD5E, 0x82F1, 0xAD5F, 0x8301, 0xAD60, 0x82DC, 0xAD61, 0x82D4, + 0xAD62, 0x82D1, 0xAD63, 0x82DE, 0xAD64, 0x82D3, 0xAD65, 0x82DF, 0xAD66, 0x82EF, 0xAD67, 0x8306, 0xAD68, 0x8650, 0xAD69, 0x8679, + 0xAD6A, 0x867B, 0xAD6B, 0x867A, 0xAD6C, 0x884D, 0xAD6D, 0x886B, 0xAD6E, 0x8981, 0xAD6F, 0x89D4, 0xAD70, 0x8A08, 0xAD71, 0x8A02, + 0xAD72, 0x8A03, 0xAD73, 0x8C9E, 0xAD74, 0x8CA0, 0xAD75, 0x8D74, 0xAD76, 0x8D73, 0xAD77, 0x8DB4, 0xAD78, 0x8ECD, 0xAD79, 0x8ECC, + 0xAD7A, 0x8FF0, 0xAD7B, 0x8FE6, 0xAD7C, 0x8FE2, 0xAD7D, 0x8FEA, 0xAD7E, 0x8FE5, 0xADA1, 0x8FED, 0xADA2, 0x8FEB, 0xADA3, 0x8FE4, + 0xADA4, 0x8FE8, 0xADA5, 0x90CA, 0xADA6, 0x90CE, 0xADA7, 0x90C1, 0xADA8, 0x90C3, 0xADA9, 0x914B, 0xADAA, 0x914A, 0xADAB, 0x91CD, + 0xADAC, 0x9582, 0xADAD, 0x9650, 0xADAE, 0x964B, 0xADAF, 0x964C, 0xADB0, 0x964D, 0xADB1, 0x9762, 0xADB2, 0x9769, 0xADB3, 0x97CB, + 0xADB4, 0x97ED, 0xADB5, 0x97F3, 0xADB6, 0x9801, 0xADB7, 0x98A8, 0xADB8, 0x98DB, 0xADB9, 0x98DF, 0xADBA, 0x9996, 0xADBB, 0x9999, + 0xADBC, 0x4E58, 0xADBD, 0x4EB3, 0xADBE, 0x500C, 0xADBF, 0x500D, 0xADC0, 0x5023, 0xADC1, 0x4FEF, 0xADC2, 0x5026, 0xADC3, 0x5025, + 0xADC4, 0x4FF8, 0xADC5, 0x5029, 0xADC6, 0x5016, 0xADC7, 0x5006, 0xADC8, 0x503C, 0xADC9, 0x501F, 0xADCA, 0x501A, 0xADCB, 0x5012, + 0xADCC, 0x5011, 0xADCD, 0x4FFA, 0xADCE, 0x5000, 0xADCF, 0x5014, 0xADD0, 0x5028, 0xADD1, 0x4FF1, 0xADD2, 0x5021, 0xADD3, 0x500B, + 0xADD4, 0x5019, 0xADD5, 0x5018, 0xADD6, 0x4FF3, 0xADD7, 0x4FEE, 0xADD8, 0x502D, 0xADD9, 0x502A, 0xADDA, 0x4FFE, 0xADDB, 0x502B, + 0xADDC, 0x5009, 0xADDD, 0x517C, 0xADDE, 0x51A4, 0xADDF, 0x51A5, 0xADE0, 0x51A2, 0xADE1, 0x51CD, 0xADE2, 0x51CC, 0xADE3, 0x51C6, + 0xADE4, 0x51CB, 0xADE5, 0x5256, 0xADE6, 0x525C, 0xADE7, 0x5254, 0xADE8, 0x525B, 0xADE9, 0x525D, 0xADEA, 0x532A, 0xADEB, 0x537F, + 0xADEC, 0x539F, 0xADED, 0x539D, 0xADEE, 0x53DF, 0xADEF, 0x54E8, 0xADF0, 0x5510, 0xADF1, 0x5501, 0xADF2, 0x5537, 0xADF3, 0x54FC, + 0xADF4, 0x54E5, 0xADF5, 0x54F2, 0xADF6, 0x5506, 0xADF7, 0x54FA, 0xADF8, 0x5514, 0xADF9, 0x54E9, 0xADFA, 0x54ED, 0xADFB, 0x54E1, + 0xADFC, 0x5509, 0xADFD, 0x54EE, 0xADFE, 0x54EA, 0xAE40, 0x54E6, 0xAE41, 0x5527, 0xAE42, 0x5507, 0xAE43, 0x54FD, 0xAE44, 0x550F, + 0xAE45, 0x5703, 0xAE46, 0x5704, 0xAE47, 0x57C2, 0xAE48, 0x57D4, 0xAE49, 0x57CB, 0xAE4A, 0x57C3, 0xAE4B, 0x5809, 0xAE4C, 0x590F, + 0xAE4D, 0x5957, 0xAE4E, 0x5958, 0xAE4F, 0x595A, 0xAE50, 0x5A11, 0xAE51, 0x5A18, 0xAE52, 0x5A1C, 0xAE53, 0x5A1F, 0xAE54, 0x5A1B, + 0xAE55, 0x5A13, 0xAE56, 0x59EC, 0xAE57, 0x5A20, 0xAE58, 0x5A23, 0xAE59, 0x5A29, 0xAE5A, 0x5A25, 0xAE5B, 0x5A0C, 0xAE5C, 0x5A09, + 0xAE5D, 0x5B6B, 0xAE5E, 0x5C58, 0xAE5F, 0x5BB0, 0xAE60, 0x5BB3, 0xAE61, 0x5BB6, 0xAE62, 0x5BB4, 0xAE63, 0x5BAE, 0xAE64, 0x5BB5, + 0xAE65, 0x5BB9, 0xAE66, 0x5BB8, 0xAE67, 0x5C04, 0xAE68, 0x5C51, 0xAE69, 0x5C55, 0xAE6A, 0x5C50, 0xAE6B, 0x5CED, 0xAE6C, 0x5CFD, + 0xAE6D, 0x5CFB, 0xAE6E, 0x5CEA, 0xAE6F, 0x5CE8, 0xAE70, 0x5CF0, 0xAE71, 0x5CF6, 0xAE72, 0x5D01, 0xAE73, 0x5CF4, 0xAE74, 0x5DEE, + 0xAE75, 0x5E2D, 0xAE76, 0x5E2B, 0xAE77, 0x5EAB, 0xAE78, 0x5EAD, 0xAE79, 0x5EA7, 0xAE7A, 0x5F31, 0xAE7B, 0x5F92, 0xAE7C, 0x5F91, + 0xAE7D, 0x5F90, 0xAE7E, 0x6059, 0xAEA1, 0x6063, 0xAEA2, 0x6065, 0xAEA3, 0x6050, 0xAEA4, 0x6055, 0xAEA5, 0x606D, 0xAEA6, 0x6069, + 0xAEA7, 0x606F, 0xAEA8, 0x6084, 0xAEA9, 0x609F, 0xAEAA, 0x609A, 0xAEAB, 0x608D, 0xAEAC, 0x6094, 0xAEAD, 0x608C, 0xAEAE, 0x6085, + 0xAEAF, 0x6096, 0xAEB0, 0x6247, 0xAEB1, 0x62F3, 0xAEB2, 0x6308, 0xAEB3, 0x62FF, 0xAEB4, 0x634E, 0xAEB5, 0x633E, 0xAEB6, 0x632F, + 0xAEB7, 0x6355, 0xAEB8, 0x6342, 0xAEB9, 0x6346, 0xAEBA, 0x634F, 0xAEBB, 0x6349, 0xAEBC, 0x633A, 0xAEBD, 0x6350, 0xAEBE, 0x633D, + 0xAEBF, 0x632A, 0xAEC0, 0x632B, 0xAEC1, 0x6328, 0xAEC2, 0x634D, 0xAEC3, 0x634C, 0xAEC4, 0x6548, 0xAEC5, 0x6549, 0xAEC6, 0x6599, + 0xAEC7, 0x65C1, 0xAEC8, 0x65C5, 0xAEC9, 0x6642, 0xAECA, 0x6649, 0xAECB, 0x664F, 0xAECC, 0x6643, 0xAECD, 0x6652, 0xAECE, 0x664C, + 0xAECF, 0x6645, 0xAED0, 0x6641, 0xAED1, 0x66F8, 0xAED2, 0x6714, 0xAED3, 0x6715, 0xAED4, 0x6717, 0xAED5, 0x6821, 0xAED6, 0x6838, + 0xAED7, 0x6848, 0xAED8, 0x6846, 0xAED9, 0x6853, 0xAEDA, 0x6839, 0xAEDB, 0x6842, 0xAEDC, 0x6854, 0xAEDD, 0x6829, 0xAEDE, 0x68B3, + 0xAEDF, 0x6817, 0xAEE0, 0x684C, 0xAEE1, 0x6851, 0xAEE2, 0x683D, 0xAEE3, 0x67F4, 0xAEE4, 0x6850, 0xAEE5, 0x6840, 0xAEE6, 0x683C, + 0xAEE7, 0x6843, 0xAEE8, 0x682A, 0xAEE9, 0x6845, 0xAEEA, 0x6813, 0xAEEB, 0x6818, 0xAEEC, 0x6841, 0xAEED, 0x6B8A, 0xAEEE, 0x6B89, + 0xAEEF, 0x6BB7, 0xAEF0, 0x6C23, 0xAEF1, 0x6C27, 0xAEF2, 0x6C28, 0xAEF3, 0x6C26, 0xAEF4, 0x6C24, 0xAEF5, 0x6CF0, 0xAEF6, 0x6D6A, + 0xAEF7, 0x6D95, 0xAEF8, 0x6D88, 0xAEF9, 0x6D87, 0xAEFA, 0x6D66, 0xAEFB, 0x6D78, 0xAEFC, 0x6D77, 0xAEFD, 0x6D59, 0xAEFE, 0x6D93, + 0xAF40, 0x6D6C, 0xAF41, 0x6D89, 0xAF42, 0x6D6E, 0xAF43, 0x6D5A, 0xAF44, 0x6D74, 0xAF45, 0x6D69, 0xAF46, 0x6D8C, 0xAF47, 0x6D8A, + 0xAF48, 0x6D79, 0xAF49, 0x6D85, 0xAF4A, 0x6D65, 0xAF4B, 0x6D94, 0xAF4C, 0x70CA, 0xAF4D, 0x70D8, 0xAF4E, 0x70E4, 0xAF4F, 0x70D9, + 0xAF50, 0x70C8, 0xAF51, 0x70CF, 0xAF52, 0x7239, 0xAF53, 0x7279, 0xAF54, 0x72FC, 0xAF55, 0x72F9, 0xAF56, 0x72FD, 0xAF57, 0x72F8, + 0xAF58, 0x72F7, 0xAF59, 0x7386, 0xAF5A, 0x73ED, 0xAF5B, 0x7409, 0xAF5C, 0x73EE, 0xAF5D, 0x73E0, 0xAF5E, 0x73EA, 0xAF5F, 0x73DE, + 0xAF60, 0x7554, 0xAF61, 0x755D, 0xAF62, 0x755C, 0xAF63, 0x755A, 0xAF64, 0x7559, 0xAF65, 0x75BE, 0xAF66, 0x75C5, 0xAF67, 0x75C7, + 0xAF68, 0x75B2, 0xAF69, 0x75B3, 0xAF6A, 0x75BD, 0xAF6B, 0x75BC, 0xAF6C, 0x75B9, 0xAF6D, 0x75C2, 0xAF6E, 0x75B8, 0xAF6F, 0x768B, + 0xAF70, 0x76B0, 0xAF71, 0x76CA, 0xAF72, 0x76CD, 0xAF73, 0x76CE, 0xAF74, 0x7729, 0xAF75, 0x771F, 0xAF76, 0x7720, 0xAF77, 0x7728, + 0xAF78, 0x77E9, 0xAF79, 0x7830, 0xAF7A, 0x7827, 0xAF7B, 0x7838, 0xAF7C, 0x781D, 0xAF7D, 0x7834, 0xAF7E, 0x7837, 0xAFA1, 0x7825, + 0xAFA2, 0x782D, 0xAFA3, 0x7820, 0xAFA4, 0x781F, 0xAFA5, 0x7832, 0xAFA6, 0x7955, 0xAFA7, 0x7950, 0xAFA8, 0x7960, 0xAFA9, 0x795F, + 0xAFAA, 0x7956, 0xAFAB, 0x795E, 0xAFAC, 0x795D, 0xAFAD, 0x7957, 0xAFAE, 0x795A, 0xAFAF, 0x79E4, 0xAFB0, 0x79E3, 0xAFB1, 0x79E7, + 0xAFB2, 0x79DF, 0xAFB3, 0x79E6, 0xAFB4, 0x79E9, 0xAFB5, 0x79D8, 0xAFB6, 0x7A84, 0xAFB7, 0x7A88, 0xAFB8, 0x7AD9, 0xAFB9, 0x7B06, + 0xAFBA, 0x7B11, 0xAFBB, 0x7C89, 0xAFBC, 0x7D21, 0xAFBD, 0x7D17, 0xAFBE, 0x7D0B, 0xAFBF, 0x7D0A, 0xAFC0, 0x7D20, 0xAFC1, 0x7D22, + 0xAFC2, 0x7D14, 0xAFC3, 0x7D10, 0xAFC4, 0x7D15, 0xAFC5, 0x7D1A, 0xAFC6, 0x7D1C, 0xAFC7, 0x7D0D, 0xAFC8, 0x7D19, 0xAFC9, 0x7D1B, + 0xAFCA, 0x7F3A, 0xAFCB, 0x7F5F, 0xAFCC, 0x7F94, 0xAFCD, 0x7FC5, 0xAFCE, 0x7FC1, 0xAFCF, 0x8006, 0xAFD0, 0x8018, 0xAFD1, 0x8015, + 0xAFD2, 0x8019, 0xAFD3, 0x8017, 0xAFD4, 0x803D, 0xAFD5, 0x803F, 0xAFD6, 0x80F1, 0xAFD7, 0x8102, 0xAFD8, 0x80F0, 0xAFD9, 0x8105, + 0xAFDA, 0x80ED, 0xAFDB, 0x80F4, 0xAFDC, 0x8106, 0xAFDD, 0x80F8, 0xAFDE, 0x80F3, 0xAFDF, 0x8108, 0xAFE0, 0x80FD, 0xAFE1, 0x810A, + 0xAFE2, 0x80FC, 0xAFE3, 0x80EF, 0xAFE4, 0x81ED, 0xAFE5, 0x81EC, 0xAFE6, 0x8200, 0xAFE7, 0x8210, 0xAFE8, 0x822A, 0xAFE9, 0x822B, + 0xAFEA, 0x8228, 0xAFEB, 0x822C, 0xAFEC, 0x82BB, 0xAFED, 0x832B, 0xAFEE, 0x8352, 0xAFEF, 0x8354, 0xAFF0, 0x834A, 0xAFF1, 0x8338, + 0xAFF2, 0x8350, 0xAFF3, 0x8349, 0xAFF4, 0x8335, 0xAFF5, 0x8334, 0xAFF6, 0x834F, 0xAFF7, 0x8332, 0xAFF8, 0x8339, 0xAFF9, 0x8336, + 0xAFFA, 0x8317, 0xAFFB, 0x8340, 0xAFFC, 0x8331, 0xAFFD, 0x8328, 0xAFFE, 0x8343, 0xB040, 0x8654, 0xB041, 0x868A, 0xB042, 0x86AA, + 0xB043, 0x8693, 0xB044, 0x86A4, 0xB045, 0x86A9, 0xB046, 0x868C, 0xB047, 0x86A3, 0xB048, 0x869C, 0xB049, 0x8870, 0xB04A, 0x8877, + 0xB04B, 0x8881, 0xB04C, 0x8882, 0xB04D, 0x887D, 0xB04E, 0x8879, 0xB04F, 0x8A18, 0xB050, 0x8A10, 0xB051, 0x8A0E, 0xB052, 0x8A0C, + 0xB053, 0x8A15, 0xB054, 0x8A0A, 0xB055, 0x8A17, 0xB056, 0x8A13, 0xB057, 0x8A16, 0xB058, 0x8A0F, 0xB059, 0x8A11, 0xB05A, 0x8C48, + 0xB05B, 0x8C7A, 0xB05C, 0x8C79, 0xB05D, 0x8CA1, 0xB05E, 0x8CA2, 0xB05F, 0x8D77, 0xB060, 0x8EAC, 0xB061, 0x8ED2, 0xB062, 0x8ED4, + 0xB063, 0x8ECF, 0xB064, 0x8FB1, 0xB065, 0x9001, 0xB066, 0x9006, 0xB067, 0x8FF7, 0xB068, 0x9000, 0xB069, 0x8FFA, 0xB06A, 0x8FF4, + 0xB06B, 0x9003, 0xB06C, 0x8FFD, 0xB06D, 0x9005, 0xB06E, 0x8FF8, 0xB06F, 0x9095, 0xB070, 0x90E1, 0xB071, 0x90DD, 0xB072, 0x90E2, + 0xB073, 0x9152, 0xB074, 0x914D, 0xB075, 0x914C, 0xB076, 0x91D8, 0xB077, 0x91DD, 0xB078, 0x91D7, 0xB079, 0x91DC, 0xB07A, 0x91D9, + 0xB07B, 0x9583, 0xB07C, 0x9662, 0xB07D, 0x9663, 0xB07E, 0x9661, 0xB0A1, 0x965B, 0xB0A2, 0x965D, 0xB0A3, 0x9664, 0xB0A4, 0x9658, + 0xB0A5, 0x965E, 0xB0A6, 0x96BB, 0xB0A7, 0x98E2, 0xB0A8, 0x99AC, 0xB0A9, 0x9AA8, 0xB0AA, 0x9AD8, 0xB0AB, 0x9B25, 0xB0AC, 0x9B32, + 0xB0AD, 0x9B3C, 0xB0AE, 0x4E7E, 0xB0AF, 0x507A, 0xB0B0, 0x507D, 0xB0B1, 0x505C, 0xB0B2, 0x5047, 0xB0B3, 0x5043, 0xB0B4, 0x504C, + 0xB0B5, 0x505A, 0xB0B6, 0x5049, 0xB0B7, 0x5065, 0xB0B8, 0x5076, 0xB0B9, 0x504E, 0xB0BA, 0x5055, 0xB0BB, 0x5075, 0xB0BC, 0x5074, + 0xB0BD, 0x5077, 0xB0BE, 0x504F, 0xB0BF, 0x500F, 0xB0C0, 0x506F, 0xB0C1, 0x506D, 0xB0C2, 0x515C, 0xB0C3, 0x5195, 0xB0C4, 0x51F0, + 0xB0C5, 0x526A, 0xB0C6, 0x526F, 0xB0C7, 0x52D2, 0xB0C8, 0x52D9, 0xB0C9, 0x52D8, 0xB0CA, 0x52D5, 0xB0CB, 0x5310, 0xB0CC, 0x530F, + 0xB0CD, 0x5319, 0xB0CE, 0x533F, 0xB0CF, 0x5340, 0xB0D0, 0x533E, 0xB0D1, 0x53C3, 0xB0D2, 0x66FC, 0xB0D3, 0x5546, 0xB0D4, 0x556A, + 0xB0D5, 0x5566, 0xB0D6, 0x5544, 0xB0D7, 0x555E, 0xB0D8, 0x5561, 0xB0D9, 0x5543, 0xB0DA, 0x554A, 0xB0DB, 0x5531, 0xB0DC, 0x5556, + 0xB0DD, 0x554F, 0xB0DE, 0x5555, 0xB0DF, 0x552F, 0xB0E0, 0x5564, 0xB0E1, 0x5538, 0xB0E2, 0x552E, 0xB0E3, 0x555C, 0xB0E4, 0x552C, + 0xB0E5, 0x5563, 0xB0E6, 0x5533, 0xB0E7, 0x5541, 0xB0E8, 0x5557, 0xB0E9, 0x5708, 0xB0EA, 0x570B, 0xB0EB, 0x5709, 0xB0EC, 0x57DF, + 0xB0ED, 0x5805, 0xB0EE, 0x580A, 0xB0EF, 0x5806, 0xB0F0, 0x57E0, 0xB0F1, 0x57E4, 0xB0F2, 0x57FA, 0xB0F3, 0x5802, 0xB0F4, 0x5835, + 0xB0F5, 0x57F7, 0xB0F6, 0x57F9, 0xB0F7, 0x5920, 0xB0F8, 0x5962, 0xB0F9, 0x5A36, 0xB0FA, 0x5A41, 0xB0FB, 0x5A49, 0xB0FC, 0x5A66, + 0xB0FD, 0x5A6A, 0xB0FE, 0x5A40, 0xB140, 0x5A3C, 0xB141, 0x5A62, 0xB142, 0x5A5A, 0xB143, 0x5A46, 0xB144, 0x5A4A, 0xB145, 0x5B70, + 0xB146, 0x5BC7, 0xB147, 0x5BC5, 0xB148, 0x5BC4, 0xB149, 0x5BC2, 0xB14A, 0x5BBF, 0xB14B, 0x5BC6, 0xB14C, 0x5C09, 0xB14D, 0x5C08, + 0xB14E, 0x5C07, 0xB14F, 0x5C60, 0xB150, 0x5C5C, 0xB151, 0x5C5D, 0xB152, 0x5D07, 0xB153, 0x5D06, 0xB154, 0x5D0E, 0xB155, 0x5D1B, + 0xB156, 0x5D16, 0xB157, 0x5D22, 0xB158, 0x5D11, 0xB159, 0x5D29, 0xB15A, 0x5D14, 0xB15B, 0x5D19, 0xB15C, 0x5D24, 0xB15D, 0x5D27, + 0xB15E, 0x5D17, 0xB15F, 0x5DE2, 0xB160, 0x5E38, 0xB161, 0x5E36, 0xB162, 0x5E33, 0xB163, 0x5E37, 0xB164, 0x5EB7, 0xB165, 0x5EB8, + 0xB166, 0x5EB6, 0xB167, 0x5EB5, 0xB168, 0x5EBE, 0xB169, 0x5F35, 0xB16A, 0x5F37, 0xB16B, 0x5F57, 0xB16C, 0x5F6C, 0xB16D, 0x5F69, + 0xB16E, 0x5F6B, 0xB16F, 0x5F97, 0xB170, 0x5F99, 0xB171, 0x5F9E, 0xB172, 0x5F98, 0xB173, 0x5FA1, 0xB174, 0x5FA0, 0xB175, 0x5F9C, + 0xB176, 0x607F, 0xB177, 0x60A3, 0xB178, 0x6089, 0xB179, 0x60A0, 0xB17A, 0x60A8, 0xB17B, 0x60CB, 0xB17C, 0x60B4, 0xB17D, 0x60E6, + 0xB17E, 0x60BD, 0xB1A1, 0x60C5, 0xB1A2, 0x60BB, 0xB1A3, 0x60B5, 0xB1A4, 0x60DC, 0xB1A5, 0x60BC, 0xB1A6, 0x60D8, 0xB1A7, 0x60D5, + 0xB1A8, 0x60C6, 0xB1A9, 0x60DF, 0xB1AA, 0x60B8, 0xB1AB, 0x60DA, 0xB1AC, 0x60C7, 0xB1AD, 0x621A, 0xB1AE, 0x621B, 0xB1AF, 0x6248, + 0xB1B0, 0x63A0, 0xB1B1, 0x63A7, 0xB1B2, 0x6372, 0xB1B3, 0x6396, 0xB1B4, 0x63A2, 0xB1B5, 0x63A5, 0xB1B6, 0x6377, 0xB1B7, 0x6367, + 0xB1B8, 0x6398, 0xB1B9, 0x63AA, 0xB1BA, 0x6371, 0xB1BB, 0x63A9, 0xB1BC, 0x6389, 0xB1BD, 0x6383, 0xB1BE, 0x639B, 0xB1BF, 0x636B, + 0xB1C0, 0x63A8, 0xB1C1, 0x6384, 0xB1C2, 0x6388, 0xB1C3, 0x6399, 0xB1C4, 0x63A1, 0xB1C5, 0x63AC, 0xB1C6, 0x6392, 0xB1C7, 0x638F, + 0xB1C8, 0x6380, 0xB1C9, 0x637B, 0xB1CA, 0x6369, 0xB1CB, 0x6368, 0xB1CC, 0x637A, 0xB1CD, 0x655D, 0xB1CE, 0x6556, 0xB1CF, 0x6551, + 0xB1D0, 0x6559, 0xB1D1, 0x6557, 0xB1D2, 0x555F, 0xB1D3, 0x654F, 0xB1D4, 0x6558, 0xB1D5, 0x6555, 0xB1D6, 0x6554, 0xB1D7, 0x659C, + 0xB1D8, 0x659B, 0xB1D9, 0x65AC, 0xB1DA, 0x65CF, 0xB1DB, 0x65CB, 0xB1DC, 0x65CC, 0xB1DD, 0x65CE, 0xB1DE, 0x665D, 0xB1DF, 0x665A, + 0xB1E0, 0x6664, 0xB1E1, 0x6668, 0xB1E2, 0x6666, 0xB1E3, 0x665E, 0xB1E4, 0x66F9, 0xB1E5, 0x52D7, 0xB1E6, 0x671B, 0xB1E7, 0x6881, + 0xB1E8, 0x68AF, 0xB1E9, 0x68A2, 0xB1EA, 0x6893, 0xB1EB, 0x68B5, 0xB1EC, 0x687F, 0xB1ED, 0x6876, 0xB1EE, 0x68B1, 0xB1EF, 0x68A7, + 0xB1F0, 0x6897, 0xB1F1, 0x68B0, 0xB1F2, 0x6883, 0xB1F3, 0x68C4, 0xB1F4, 0x68AD, 0xB1F5, 0x6886, 0xB1F6, 0x6885, 0xB1F7, 0x6894, + 0xB1F8, 0x689D, 0xB1F9, 0x68A8, 0xB1FA, 0x689F, 0xB1FB, 0x68A1, 0xB1FC, 0x6882, 0xB1FD, 0x6B32, 0xB1FE, 0x6BBA, 0xB240, 0x6BEB, + 0xB241, 0x6BEC, 0xB242, 0x6C2B, 0xB243, 0x6D8E, 0xB244, 0x6DBC, 0xB245, 0x6DF3, 0xB246, 0x6DD9, 0xB247, 0x6DB2, 0xB248, 0x6DE1, + 0xB249, 0x6DCC, 0xB24A, 0x6DE4, 0xB24B, 0x6DFB, 0xB24C, 0x6DFA, 0xB24D, 0x6E05, 0xB24E, 0x6DC7, 0xB24F, 0x6DCB, 0xB250, 0x6DAF, + 0xB251, 0x6DD1, 0xB252, 0x6DAE, 0xB253, 0x6DDE, 0xB254, 0x6DF9, 0xB255, 0x6DB8, 0xB256, 0x6DF7, 0xB257, 0x6DF5, 0xB258, 0x6DC5, + 0xB259, 0x6DD2, 0xB25A, 0x6E1A, 0xB25B, 0x6DB5, 0xB25C, 0x6DDA, 0xB25D, 0x6DEB, 0xB25E, 0x6DD8, 0xB25F, 0x6DEA, 0xB260, 0x6DF1, + 0xB261, 0x6DEE, 0xB262, 0x6DE8, 0xB263, 0x6DC6, 0xB264, 0x6DC4, 0xB265, 0x6DAA, 0xB266, 0x6DEC, 0xB267, 0x6DBF, 0xB268, 0x6DE6, + 0xB269, 0x70F9, 0xB26A, 0x7109, 0xB26B, 0x710A, 0xB26C, 0x70FD, 0xB26D, 0x70EF, 0xB26E, 0x723D, 0xB26F, 0x727D, 0xB270, 0x7281, + 0xB271, 0x731C, 0xB272, 0x731B, 0xB273, 0x7316, 0xB274, 0x7313, 0xB275, 0x7319, 0xB276, 0x7387, 0xB277, 0x7405, 0xB278, 0x740A, + 0xB279, 0x7403, 0xB27A, 0x7406, 0xB27B, 0x73FE, 0xB27C, 0x740D, 0xB27D, 0x74E0, 0xB27E, 0x74F6, 0xB2A1, 0x74F7, 0xB2A2, 0x751C, + 0xB2A3, 0x7522, 0xB2A4, 0x7565, 0xB2A5, 0x7566, 0xB2A6, 0x7562, 0xB2A7, 0x7570, 0xB2A8, 0x758F, 0xB2A9, 0x75D4, 0xB2AA, 0x75D5, + 0xB2AB, 0x75B5, 0xB2AC, 0x75CA, 0xB2AD, 0x75CD, 0xB2AE, 0x768E, 0xB2AF, 0x76D4, 0xB2B0, 0x76D2, 0xB2B1, 0x76DB, 0xB2B2, 0x7737, + 0xB2B3, 0x773E, 0xB2B4, 0x773C, 0xB2B5, 0x7736, 0xB2B6, 0x7738, 0xB2B7, 0x773A, 0xB2B8, 0x786B, 0xB2B9, 0x7843, 0xB2BA, 0x784E, + 0xB2BB, 0x7965, 0xB2BC, 0x7968, 0xB2BD, 0x796D, 0xB2BE, 0x79FB, 0xB2BF, 0x7A92, 0xB2C0, 0x7A95, 0xB2C1, 0x7B20, 0xB2C2, 0x7B28, + 0xB2C3, 0x7B1B, 0xB2C4, 0x7B2C, 0xB2C5, 0x7B26, 0xB2C6, 0x7B19, 0xB2C7, 0x7B1E, 0xB2C8, 0x7B2E, 0xB2C9, 0x7C92, 0xB2CA, 0x7C97, + 0xB2CB, 0x7C95, 0xB2CC, 0x7D46, 0xB2CD, 0x7D43, 0xB2CE, 0x7D71, 0xB2CF, 0x7D2E, 0xB2D0, 0x7D39, 0xB2D1, 0x7D3C, 0xB2D2, 0x7D40, + 0xB2D3, 0x7D30, 0xB2D4, 0x7D33, 0xB2D5, 0x7D44, 0xB2D6, 0x7D2F, 0xB2D7, 0x7D42, 0xB2D8, 0x7D32, 0xB2D9, 0x7D31, 0xB2DA, 0x7F3D, + 0xB2DB, 0x7F9E, 0xB2DC, 0x7F9A, 0xB2DD, 0x7FCC, 0xB2DE, 0x7FCE, 0xB2DF, 0x7FD2, 0xB2E0, 0x801C, 0xB2E1, 0x804A, 0xB2E2, 0x8046, + 0xB2E3, 0x812F, 0xB2E4, 0x8116, 0xB2E5, 0x8123, 0xB2E6, 0x812B, 0xB2E7, 0x8129, 0xB2E8, 0x8130, 0xB2E9, 0x8124, 0xB2EA, 0x8202, + 0xB2EB, 0x8235, 0xB2EC, 0x8237, 0xB2ED, 0x8236, 0xB2EE, 0x8239, 0xB2EF, 0x838E, 0xB2F0, 0x839E, 0xB2F1, 0x8398, 0xB2F2, 0x8378, + 0xB2F3, 0x83A2, 0xB2F4, 0x8396, 0xB2F5, 0x83BD, 0xB2F6, 0x83AB, 0xB2F7, 0x8392, 0xB2F8, 0x838A, 0xB2F9, 0x8393, 0xB2FA, 0x8389, + 0xB2FB, 0x83A0, 0xB2FC, 0x8377, 0xB2FD, 0x837B, 0xB2FE, 0x837C, 0xB340, 0x8386, 0xB341, 0x83A7, 0xB342, 0x8655, 0xB343, 0x5F6A, + 0xB344, 0x86C7, 0xB345, 0x86C0, 0xB346, 0x86B6, 0xB347, 0x86C4, 0xB348, 0x86B5, 0xB349, 0x86C6, 0xB34A, 0x86CB, 0xB34B, 0x86B1, + 0xB34C, 0x86AF, 0xB34D, 0x86C9, 0xB34E, 0x8853, 0xB34F, 0x889E, 0xB350, 0x8888, 0xB351, 0x88AB, 0xB352, 0x8892, 0xB353, 0x8896, + 0xB354, 0x888D, 0xB355, 0x888B, 0xB356, 0x8993, 0xB357, 0x898F, 0xB358, 0x8A2A, 0xB359, 0x8A1D, 0xB35A, 0x8A23, 0xB35B, 0x8A25, + 0xB35C, 0x8A31, 0xB35D, 0x8A2D, 0xB35E, 0x8A1F, 0xB35F, 0x8A1B, 0xB360, 0x8A22, 0xB361, 0x8C49, 0xB362, 0x8C5A, 0xB363, 0x8CA9, + 0xB364, 0x8CAC, 0xB365, 0x8CAB, 0xB366, 0x8CA8, 0xB367, 0x8CAA, 0xB368, 0x8CA7, 0xB369, 0x8D67, 0xB36A, 0x8D66, 0xB36B, 0x8DBE, + 0xB36C, 0x8DBA, 0xB36D, 0x8EDB, 0xB36E, 0x8EDF, 0xB36F, 0x9019, 0xB370, 0x900D, 0xB371, 0x901A, 0xB372, 0x9017, 0xB373, 0x9023, + 0xB374, 0x901F, 0xB375, 0x901D, 0xB376, 0x9010, 0xB377, 0x9015, 0xB378, 0x901E, 0xB379, 0x9020, 0xB37A, 0x900F, 0xB37B, 0x9022, + 0xB37C, 0x9016, 0xB37D, 0x901B, 0xB37E, 0x9014, 0xB3A1, 0x90E8, 0xB3A2, 0x90ED, 0xB3A3, 0x90FD, 0xB3A4, 0x9157, 0xB3A5, 0x91CE, + 0xB3A6, 0x91F5, 0xB3A7, 0x91E6, 0xB3A8, 0x91E3, 0xB3A9, 0x91E7, 0xB3AA, 0x91ED, 0xB3AB, 0x91E9, 0xB3AC, 0x9589, 0xB3AD, 0x966A, + 0xB3AE, 0x9675, 0xB3AF, 0x9673, 0xB3B0, 0x9678, 0xB3B1, 0x9670, 0xB3B2, 0x9674, 0xB3B3, 0x9676, 0xB3B4, 0x9677, 0xB3B5, 0x966C, + 0xB3B6, 0x96C0, 0xB3B7, 0x96EA, 0xB3B8, 0x96E9, 0xB3B9, 0x7AE0, 0xB3BA, 0x7ADF, 0xB3BB, 0x9802, 0xB3BC, 0x9803, 0xB3BD, 0x9B5A, + 0xB3BE, 0x9CE5, 0xB3BF, 0x9E75, 0xB3C0, 0x9E7F, 0xB3C1, 0x9EA5, 0xB3C2, 0x9EBB, 0xB3C3, 0x50A2, 0xB3C4, 0x508D, 0xB3C5, 0x5085, + 0xB3C6, 0x5099, 0xB3C7, 0x5091, 0xB3C8, 0x5080, 0xB3C9, 0x5096, 0xB3CA, 0x5098, 0xB3CB, 0x509A, 0xB3CC, 0x6700, 0xB3CD, 0x51F1, + 0xB3CE, 0x5272, 0xB3CF, 0x5274, 0xB3D0, 0x5275, 0xB3D1, 0x5269, 0xB3D2, 0x52DE, 0xB3D3, 0x52DD, 0xB3D4, 0x52DB, 0xB3D5, 0x535A, + 0xB3D6, 0x53A5, 0xB3D7, 0x557B, 0xB3D8, 0x5580, 0xB3D9, 0x55A7, 0xB3DA, 0x557C, 0xB3DB, 0x558A, 0xB3DC, 0x559D, 0xB3DD, 0x5598, + 0xB3DE, 0x5582, 0xB3DF, 0x559C, 0xB3E0, 0x55AA, 0xB3E1, 0x5594, 0xB3E2, 0x5587, 0xB3E3, 0x558B, 0xB3E4, 0x5583, 0xB3E5, 0x55B3, + 0xB3E6, 0x55AE, 0xB3E7, 0x559F, 0xB3E8, 0x553E, 0xB3E9, 0x55B2, 0xB3EA, 0x559A, 0xB3EB, 0x55BB, 0xB3EC, 0x55AC, 0xB3ED, 0x55B1, + 0xB3EE, 0x557E, 0xB3EF, 0x5589, 0xB3F0, 0x55AB, 0xB3F1, 0x5599, 0xB3F2, 0x570D, 0xB3F3, 0x582F, 0xB3F4, 0x582A, 0xB3F5, 0x5834, + 0xB3F6, 0x5824, 0xB3F7, 0x5830, 0xB3F8, 0x5831, 0xB3F9, 0x5821, 0xB3FA, 0x581D, 0xB3FB, 0x5820, 0xB3FC, 0x58F9, 0xB3FD, 0x58FA, + 0xB3FE, 0x5960, 0xB440, 0x5A77, 0xB441, 0x5A9A, 0xB442, 0x5A7F, 0xB443, 0x5A92, 0xB444, 0x5A9B, 0xB445, 0x5AA7, 0xB446, 0x5B73, + 0xB447, 0x5B71, 0xB448, 0x5BD2, 0xB449, 0x5BCC, 0xB44A, 0x5BD3, 0xB44B, 0x5BD0, 0xB44C, 0x5C0A, 0xB44D, 0x5C0B, 0xB44E, 0x5C31, + 0xB44F, 0x5D4C, 0xB450, 0x5D50, 0xB451, 0x5D34, 0xB452, 0x5D47, 0xB453, 0x5DFD, 0xB454, 0x5E45, 0xB455, 0x5E3D, 0xB456, 0x5E40, + 0xB457, 0x5E43, 0xB458, 0x5E7E, 0xB459, 0x5ECA, 0xB45A, 0x5EC1, 0xB45B, 0x5EC2, 0xB45C, 0x5EC4, 0xB45D, 0x5F3C, 0xB45E, 0x5F6D, + 0xB45F, 0x5FA9, 0xB460, 0x5FAA, 0xB461, 0x5FA8, 0xB462, 0x60D1, 0xB463, 0x60E1, 0xB464, 0x60B2, 0xB465, 0x60B6, 0xB466, 0x60E0, + 0xB467, 0x611C, 0xB468, 0x6123, 0xB469, 0x60FA, 0xB46A, 0x6115, 0xB46B, 0x60F0, 0xB46C, 0x60FB, 0xB46D, 0x60F4, 0xB46E, 0x6168, + 0xB46F, 0x60F1, 0xB470, 0x610E, 0xB471, 0x60F6, 0xB472, 0x6109, 0xB473, 0x6100, 0xB474, 0x6112, 0xB475, 0x621F, 0xB476, 0x6249, + 0xB477, 0x63A3, 0xB478, 0x638C, 0xB479, 0x63CF, 0xB47A, 0x63C0, 0xB47B, 0x63E9, 0xB47C, 0x63C9, 0xB47D, 0x63C6, 0xB47E, 0x63CD, + 0xB4A1, 0x63D2, 0xB4A2, 0x63E3, 0xB4A3, 0x63D0, 0xB4A4, 0x63E1, 0xB4A5, 0x63D6, 0xB4A6, 0x63ED, 0xB4A7, 0x63EE, 0xB4A8, 0x6376, + 0xB4A9, 0x63F4, 0xB4AA, 0x63EA, 0xB4AB, 0x63DB, 0xB4AC, 0x6452, 0xB4AD, 0x63DA, 0xB4AE, 0x63F9, 0xB4AF, 0x655E, 0xB4B0, 0x6566, + 0xB4B1, 0x6562, 0xB4B2, 0x6563, 0xB4B3, 0x6591, 0xB4B4, 0x6590, 0xB4B5, 0x65AF, 0xB4B6, 0x666E, 0xB4B7, 0x6670, 0xB4B8, 0x6674, + 0xB4B9, 0x6676, 0xB4BA, 0x666F, 0xB4BB, 0x6691, 0xB4BC, 0x667A, 0xB4BD, 0x667E, 0xB4BE, 0x6677, 0xB4BF, 0x66FE, 0xB4C0, 0x66FF, + 0xB4C1, 0x671F, 0xB4C2, 0x671D, 0xB4C3, 0x68FA, 0xB4C4, 0x68D5, 0xB4C5, 0x68E0, 0xB4C6, 0x68D8, 0xB4C7, 0x68D7, 0xB4C8, 0x6905, + 0xB4C9, 0x68DF, 0xB4CA, 0x68F5, 0xB4CB, 0x68EE, 0xB4CC, 0x68E7, 0xB4CD, 0x68F9, 0xB4CE, 0x68D2, 0xB4CF, 0x68F2, 0xB4D0, 0x68E3, + 0xB4D1, 0x68CB, 0xB4D2, 0x68CD, 0xB4D3, 0x690D, 0xB4D4, 0x6912, 0xB4D5, 0x690E, 0xB4D6, 0x68C9, 0xB4D7, 0x68DA, 0xB4D8, 0x696E, + 0xB4D9, 0x68FB, 0xB4DA, 0x6B3E, 0xB4DB, 0x6B3A, 0xB4DC, 0x6B3D, 0xB4DD, 0x6B98, 0xB4DE, 0x6B96, 0xB4DF, 0x6BBC, 0xB4E0, 0x6BEF, + 0xB4E1, 0x6C2E, 0xB4E2, 0x6C2F, 0xB4E3, 0x6C2C, 0xB4E4, 0x6E2F, 0xB4E5, 0x6E38, 0xB4E6, 0x6E54, 0xB4E7, 0x6E21, 0xB4E8, 0x6E32, + 0xB4E9, 0x6E67, 0xB4EA, 0x6E4A, 0xB4EB, 0x6E20, 0xB4EC, 0x6E25, 0xB4ED, 0x6E23, 0xB4EE, 0x6E1B, 0xB4EF, 0x6E5B, 0xB4F0, 0x6E58, + 0xB4F1, 0x6E24, 0xB4F2, 0x6E56, 0xB4F3, 0x6E6E, 0xB4F4, 0x6E2D, 0xB4F5, 0x6E26, 0xB4F6, 0x6E6F, 0xB4F7, 0x6E34, 0xB4F8, 0x6E4D, + 0xB4F9, 0x6E3A, 0xB4FA, 0x6E2C, 0xB4FB, 0x6E43, 0xB4FC, 0x6E1D, 0xB4FD, 0x6E3E, 0xB4FE, 0x6ECB, 0xB540, 0x6E89, 0xB541, 0x6E19, + 0xB542, 0x6E4E, 0xB543, 0x6E63, 0xB544, 0x6E44, 0xB545, 0x6E72, 0xB546, 0x6E69, 0xB547, 0x6E5F, 0xB548, 0x7119, 0xB549, 0x711A, + 0xB54A, 0x7126, 0xB54B, 0x7130, 0xB54C, 0x7121, 0xB54D, 0x7136, 0xB54E, 0x716E, 0xB54F, 0x711C, 0xB550, 0x724C, 0xB551, 0x7284, + 0xB552, 0x7280, 0xB553, 0x7336, 0xB554, 0x7325, 0xB555, 0x7334, 0xB556, 0x7329, 0xB557, 0x743A, 0xB558, 0x742A, 0xB559, 0x7433, + 0xB55A, 0x7422, 0xB55B, 0x7425, 0xB55C, 0x7435, 0xB55D, 0x7436, 0xB55E, 0x7434, 0xB55F, 0x742F, 0xB560, 0x741B, 0xB561, 0x7426, + 0xB562, 0x7428, 0xB563, 0x7525, 0xB564, 0x7526, 0xB565, 0x756B, 0xB566, 0x756A, 0xB567, 0x75E2, 0xB568, 0x75DB, 0xB569, 0x75E3, + 0xB56A, 0x75D9, 0xB56B, 0x75D8, 0xB56C, 0x75DE, 0xB56D, 0x75E0, 0xB56E, 0x767B, 0xB56F, 0x767C, 0xB570, 0x7696, 0xB571, 0x7693, + 0xB572, 0x76B4, 0xB573, 0x76DC, 0xB574, 0x774F, 0xB575, 0x77ED, 0xB576, 0x785D, 0xB577, 0x786C, 0xB578, 0x786F, 0xB579, 0x7A0D, + 0xB57A, 0x7A08, 0xB57B, 0x7A0B, 0xB57C, 0x7A05, 0xB57D, 0x7A00, 0xB57E, 0x7A98, 0xB5A1, 0x7A97, 0xB5A2, 0x7A96, 0xB5A3, 0x7AE5, + 0xB5A4, 0x7AE3, 0xB5A5, 0x7B49, 0xB5A6, 0x7B56, 0xB5A7, 0x7B46, 0xB5A8, 0x7B50, 0xB5A9, 0x7B52, 0xB5AA, 0x7B54, 0xB5AB, 0x7B4D, + 0xB5AC, 0x7B4B, 0xB5AD, 0x7B4F, 0xB5AE, 0x7B51, 0xB5AF, 0x7C9F, 0xB5B0, 0x7CA5, 0xB5B1, 0x7D5E, 0xB5B2, 0x7D50, 0xB5B3, 0x7D68, + 0xB5B4, 0x7D55, 0xB5B5, 0x7D2B, 0xB5B6, 0x7D6E, 0xB5B7, 0x7D72, 0xB5B8, 0x7D61, 0xB5B9, 0x7D66, 0xB5BA, 0x7D62, 0xB5BB, 0x7D70, + 0xB5BC, 0x7D73, 0xB5BD, 0x5584, 0xB5BE, 0x7FD4, 0xB5BF, 0x7FD5, 0xB5C0, 0x800B, 0xB5C1, 0x8052, 0xB5C2, 0x8085, 0xB5C3, 0x8155, + 0xB5C4, 0x8154, 0xB5C5, 0x814B, 0xB5C6, 0x8151, 0xB5C7, 0x814E, 0xB5C8, 0x8139, 0xB5C9, 0x8146, 0xB5CA, 0x813E, 0xB5CB, 0x814C, + 0xB5CC, 0x8153, 0xB5CD, 0x8174, 0xB5CE, 0x8212, 0xB5CF, 0x821C, 0xB5D0, 0x83E9, 0xB5D1, 0x8403, 0xB5D2, 0x83F8, 0xB5D3, 0x840D, + 0xB5D4, 0x83E0, 0xB5D5, 0x83C5, 0xB5D6, 0x840B, 0xB5D7, 0x83C1, 0xB5D8, 0x83EF, 0xB5D9, 0x83F1, 0xB5DA, 0x83F4, 0xB5DB, 0x8457, + 0xB5DC, 0x840A, 0xB5DD, 0x83F0, 0xB5DE, 0x840C, 0xB5DF, 0x83CC, 0xB5E0, 0x83FD, 0xB5E1, 0x83F2, 0xB5E2, 0x83CA, 0xB5E3, 0x8438, + 0xB5E4, 0x840E, 0xB5E5, 0x8404, 0xB5E6, 0x83DC, 0xB5E7, 0x8407, 0xB5E8, 0x83D4, 0xB5E9, 0x83DF, 0xB5EA, 0x865B, 0xB5EB, 0x86DF, + 0xB5EC, 0x86D9, 0xB5ED, 0x86ED, 0xB5EE, 0x86D4, 0xB5EF, 0x86DB, 0xB5F0, 0x86E4, 0xB5F1, 0x86D0, 0xB5F2, 0x86DE, 0xB5F3, 0x8857, + 0xB5F4, 0x88C1, 0xB5F5, 0x88C2, 0xB5F6, 0x88B1, 0xB5F7, 0x8983, 0xB5F8, 0x8996, 0xB5F9, 0x8A3B, 0xB5FA, 0x8A60, 0xB5FB, 0x8A55, + 0xB5FC, 0x8A5E, 0xB5FD, 0x8A3C, 0xB5FE, 0x8A41, 0xB640, 0x8A54, 0xB641, 0x8A5B, 0xB642, 0x8A50, 0xB643, 0x8A46, 0xB644, 0x8A34, + 0xB645, 0x8A3A, 0xB646, 0x8A36, 0xB647, 0x8A56, 0xB648, 0x8C61, 0xB649, 0x8C82, 0xB64A, 0x8CAF, 0xB64B, 0x8CBC, 0xB64C, 0x8CB3, + 0xB64D, 0x8CBD, 0xB64E, 0x8CC1, 0xB64F, 0x8CBB, 0xB650, 0x8CC0, 0xB651, 0x8CB4, 0xB652, 0x8CB7, 0xB653, 0x8CB6, 0xB654, 0x8CBF, + 0xB655, 0x8CB8, 0xB656, 0x8D8A, 0xB657, 0x8D85, 0xB658, 0x8D81, 0xB659, 0x8DCE, 0xB65A, 0x8DDD, 0xB65B, 0x8DCB, 0xB65C, 0x8DDA, + 0xB65D, 0x8DD1, 0xB65E, 0x8DCC, 0xB65F, 0x8DDB, 0xB660, 0x8DC6, 0xB661, 0x8EFB, 0xB662, 0x8EF8, 0xB663, 0x8EFC, 0xB664, 0x8F9C, + 0xB665, 0x902E, 0xB666, 0x9035, 0xB667, 0x9031, 0xB668, 0x9038, 0xB669, 0x9032, 0xB66A, 0x9036, 0xB66B, 0x9102, 0xB66C, 0x90F5, + 0xB66D, 0x9109, 0xB66E, 0x90FE, 0xB66F, 0x9163, 0xB670, 0x9165, 0xB671, 0x91CF, 0xB672, 0x9214, 0xB673, 0x9215, 0xB674, 0x9223, + 0xB675, 0x9209, 0xB676, 0x921E, 0xB677, 0x920D, 0xB678, 0x9210, 0xB679, 0x9207, 0xB67A, 0x9211, 0xB67B, 0x9594, 0xB67C, 0x958F, + 0xB67D, 0x958B, 0xB67E, 0x9591, 0xB6A1, 0x9593, 0xB6A2, 0x9592, 0xB6A3, 0x958E, 0xB6A4, 0x968A, 0xB6A5, 0x968E, 0xB6A6, 0x968B, + 0xB6A7, 0x967D, 0xB6A8, 0x9685, 0xB6A9, 0x9686, 0xB6AA, 0x968D, 0xB6AB, 0x9672, 0xB6AC, 0x9684, 0xB6AD, 0x96C1, 0xB6AE, 0x96C5, + 0xB6AF, 0x96C4, 0xB6B0, 0x96C6, 0xB6B1, 0x96C7, 0xB6B2, 0x96EF, 0xB6B3, 0x96F2, 0xB6B4, 0x97CC, 0xB6B5, 0x9805, 0xB6B6, 0x9806, + 0xB6B7, 0x9808, 0xB6B8, 0x98E7, 0xB6B9, 0x98EA, 0xB6BA, 0x98EF, 0xB6BB, 0x98E9, 0xB6BC, 0x98F2, 0xB6BD, 0x98ED, 0xB6BE, 0x99AE, + 0xB6BF, 0x99AD, 0xB6C0, 0x9EC3, 0xB6C1, 0x9ECD, 0xB6C2, 0x9ED1, 0xB6C3, 0x4E82, 0xB6C4, 0x50AD, 0xB6C5, 0x50B5, 0xB6C6, 0x50B2, + 0xB6C7, 0x50B3, 0xB6C8, 0x50C5, 0xB6C9, 0x50BE, 0xB6CA, 0x50AC, 0xB6CB, 0x50B7, 0xB6CC, 0x50BB, 0xB6CD, 0x50AF, 0xB6CE, 0x50C7, + 0xB6CF, 0x527F, 0xB6D0, 0x5277, 0xB6D1, 0x527D, 0xB6D2, 0x52DF, 0xB6D3, 0x52E6, 0xB6D4, 0x52E4, 0xB6D5, 0x52E2, 0xB6D6, 0x52E3, + 0xB6D7, 0x532F, 0xB6D8, 0x55DF, 0xB6D9, 0x55E8, 0xB6DA, 0x55D3, 0xB6DB, 0x55E6, 0xB6DC, 0x55CE, 0xB6DD, 0x55DC, 0xB6DE, 0x55C7, + 0xB6DF, 0x55D1, 0xB6E0, 0x55E3, 0xB6E1, 0x55E4, 0xB6E2, 0x55EF, 0xB6E3, 0x55DA, 0xB6E4, 0x55E1, 0xB6E5, 0x55C5, 0xB6E6, 0x55C6, + 0xB6E7, 0x55E5, 0xB6E8, 0x55C9, 0xB6E9, 0x5712, 0xB6EA, 0x5713, 0xB6EB, 0x585E, 0xB6EC, 0x5851, 0xB6ED, 0x5858, 0xB6EE, 0x5857, + 0xB6EF, 0x585A, 0xB6F0, 0x5854, 0xB6F1, 0x586B, 0xB6F2, 0x584C, 0xB6F3, 0x586D, 0xB6F4, 0x584A, 0xB6F5, 0x5862, 0xB6F6, 0x5852, + 0xB6F7, 0x584B, 0xB6F8, 0x5967, 0xB6F9, 0x5AC1, 0xB6FA, 0x5AC9, 0xB6FB, 0x5ACC, 0xB6FC, 0x5ABE, 0xB6FD, 0x5ABD, 0xB6FE, 0x5ABC, + 0xB740, 0x5AB3, 0xB741, 0x5AC2, 0xB742, 0x5AB2, 0xB743, 0x5D69, 0xB744, 0x5D6F, 0xB745, 0x5E4C, 0xB746, 0x5E79, 0xB747, 0x5EC9, + 0xB748, 0x5EC8, 0xB749, 0x5F12, 0xB74A, 0x5F59, 0xB74B, 0x5FAC, 0xB74C, 0x5FAE, 0xB74D, 0x611A, 0xB74E, 0x610F, 0xB74F, 0x6148, + 0xB750, 0x611F, 0xB751, 0x60F3, 0xB752, 0x611B, 0xB753, 0x60F9, 0xB754, 0x6101, 0xB755, 0x6108, 0xB756, 0x614E, 0xB757, 0x614C, + 0xB758, 0x6144, 0xB759, 0x614D, 0xB75A, 0x613E, 0xB75B, 0x6134, 0xB75C, 0x6127, 0xB75D, 0x610D, 0xB75E, 0x6106, 0xB75F, 0x6137, + 0xB760, 0x6221, 0xB761, 0x6222, 0xB762, 0x6413, 0xB763, 0x643E, 0xB764, 0x641E, 0xB765, 0x642A, 0xB766, 0x642D, 0xB767, 0x643D, + 0xB768, 0x642C, 0xB769, 0x640F, 0xB76A, 0x641C, 0xB76B, 0x6414, 0xB76C, 0x640D, 0xB76D, 0x6436, 0xB76E, 0x6416, 0xB76F, 0x6417, + 0xB770, 0x6406, 0xB771, 0x656C, 0xB772, 0x659F, 0xB773, 0x65B0, 0xB774, 0x6697, 0xB775, 0x6689, 0xB776, 0x6687, 0xB777, 0x6688, + 0xB778, 0x6696, 0xB779, 0x6684, 0xB77A, 0x6698, 0xB77B, 0x668D, 0xB77C, 0x6703, 0xB77D, 0x6994, 0xB77E, 0x696D, 0xB7A1, 0x695A, + 0xB7A2, 0x6977, 0xB7A3, 0x6960, 0xB7A4, 0x6954, 0xB7A5, 0x6975, 0xB7A6, 0x6930, 0xB7A7, 0x6982, 0xB7A8, 0x694A, 0xB7A9, 0x6968, + 0xB7AA, 0x696B, 0xB7AB, 0x695E, 0xB7AC, 0x6953, 0xB7AD, 0x6979, 0xB7AE, 0x6986, 0xB7AF, 0x695D, 0xB7B0, 0x6963, 0xB7B1, 0x695B, + 0xB7B2, 0x6B47, 0xB7B3, 0x6B72, 0xB7B4, 0x6BC0, 0xB7B5, 0x6BBF, 0xB7B6, 0x6BD3, 0xB7B7, 0x6BFD, 0xB7B8, 0x6EA2, 0xB7B9, 0x6EAF, + 0xB7BA, 0x6ED3, 0xB7BB, 0x6EB6, 0xB7BC, 0x6EC2, 0xB7BD, 0x6E90, 0xB7BE, 0x6E9D, 0xB7BF, 0x6EC7, 0xB7C0, 0x6EC5, 0xB7C1, 0x6EA5, + 0xB7C2, 0x6E98, 0xB7C3, 0x6EBC, 0xB7C4, 0x6EBA, 0xB7C5, 0x6EAB, 0xB7C6, 0x6ED1, 0xB7C7, 0x6E96, 0xB7C8, 0x6E9C, 0xB7C9, 0x6EC4, + 0xB7CA, 0x6ED4, 0xB7CB, 0x6EAA, 0xB7CC, 0x6EA7, 0xB7CD, 0x6EB4, 0xB7CE, 0x714E, 0xB7CF, 0x7159, 0xB7D0, 0x7169, 0xB7D1, 0x7164, + 0xB7D2, 0x7149, 0xB7D3, 0x7167, 0xB7D4, 0x715C, 0xB7D5, 0x716C, 0xB7D6, 0x7166, 0xB7D7, 0x714C, 0xB7D8, 0x7165, 0xB7D9, 0x715E, + 0xB7DA, 0x7146, 0xB7DB, 0x7168, 0xB7DC, 0x7156, 0xB7DD, 0x723A, 0xB7DE, 0x7252, 0xB7DF, 0x7337, 0xB7E0, 0x7345, 0xB7E1, 0x733F, + 0xB7E2, 0x733E, 0xB7E3, 0x746F, 0xB7E4, 0x745A, 0xB7E5, 0x7455, 0xB7E6, 0x745F, 0xB7E7, 0x745E, 0xB7E8, 0x7441, 0xB7E9, 0x743F, + 0xB7EA, 0x7459, 0xB7EB, 0x745B, 0xB7EC, 0x745C, 0xB7ED, 0x7576, 0xB7EE, 0x7578, 0xB7EF, 0x7600, 0xB7F0, 0x75F0, 0xB7F1, 0x7601, + 0xB7F2, 0x75F2, 0xB7F3, 0x75F1, 0xB7F4, 0x75FA, 0xB7F5, 0x75FF, 0xB7F6, 0x75F4, 0xB7F7, 0x75F3, 0xB7F8, 0x76DE, 0xB7F9, 0x76DF, + 0xB7FA, 0x775B, 0xB7FB, 0x776B, 0xB7FC, 0x7766, 0xB7FD, 0x775E, 0xB7FE, 0x7763, 0xB840, 0x7779, 0xB841, 0x776A, 0xB842, 0x776C, + 0xB843, 0x775C, 0xB844, 0x7765, 0xB845, 0x7768, 0xB846, 0x7762, 0xB847, 0x77EE, 0xB848, 0x788E, 0xB849, 0x78B0, 0xB84A, 0x7897, + 0xB84B, 0x7898, 0xB84C, 0x788C, 0xB84D, 0x7889, 0xB84E, 0x787C, 0xB84F, 0x7891, 0xB850, 0x7893, 0xB851, 0x787F, 0xB852, 0x797A, + 0xB853, 0x797F, 0xB854, 0x7981, 0xB855, 0x842C, 0xB856, 0x79BD, 0xB857, 0x7A1C, 0xB858, 0x7A1A, 0xB859, 0x7A20, 0xB85A, 0x7A14, + 0xB85B, 0x7A1F, 0xB85C, 0x7A1E, 0xB85D, 0x7A9F, 0xB85E, 0x7AA0, 0xB85F, 0x7B77, 0xB860, 0x7BC0, 0xB861, 0x7B60, 0xB862, 0x7B6E, + 0xB863, 0x7B67, 0xB864, 0x7CB1, 0xB865, 0x7CB3, 0xB866, 0x7CB5, 0xB867, 0x7D93, 0xB868, 0x7D79, 0xB869, 0x7D91, 0xB86A, 0x7D81, + 0xB86B, 0x7D8F, 0xB86C, 0x7D5B, 0xB86D, 0x7F6E, 0xB86E, 0x7F69, 0xB86F, 0x7F6A, 0xB870, 0x7F72, 0xB871, 0x7FA9, 0xB872, 0x7FA8, + 0xB873, 0x7FA4, 0xB874, 0x8056, 0xB875, 0x8058, 0xB876, 0x8086, 0xB877, 0x8084, 0xB878, 0x8171, 0xB879, 0x8170, 0xB87A, 0x8178, + 0xB87B, 0x8165, 0xB87C, 0x816E, 0xB87D, 0x8173, 0xB87E, 0x816B, 0xB8A1, 0x8179, 0xB8A2, 0x817A, 0xB8A3, 0x8166, 0xB8A4, 0x8205, + 0xB8A5, 0x8247, 0xB8A6, 0x8482, 0xB8A7, 0x8477, 0xB8A8, 0x843D, 0xB8A9, 0x8431, 0xB8AA, 0x8475, 0xB8AB, 0x8466, 0xB8AC, 0x846B, + 0xB8AD, 0x8449, 0xB8AE, 0x846C, 0xB8AF, 0x845B, 0xB8B0, 0x843C, 0xB8B1, 0x8435, 0xB8B2, 0x8461, 0xB8B3, 0x8463, 0xB8B4, 0x8469, + 0xB8B5, 0x846D, 0xB8B6, 0x8446, 0xB8B7, 0x865E, 0xB8B8, 0x865C, 0xB8B9, 0x865F, 0xB8BA, 0x86F9, 0xB8BB, 0x8713, 0xB8BC, 0x8708, + 0xB8BD, 0x8707, 0xB8BE, 0x8700, 0xB8BF, 0x86FE, 0xB8C0, 0x86FB, 0xB8C1, 0x8702, 0xB8C2, 0x8703, 0xB8C3, 0x8706, 0xB8C4, 0x870A, + 0xB8C5, 0x8859, 0xB8C6, 0x88DF, 0xB8C7, 0x88D4, 0xB8C8, 0x88D9, 0xB8C9, 0x88DC, 0xB8CA, 0x88D8, 0xB8CB, 0x88DD, 0xB8CC, 0x88E1, + 0xB8CD, 0x88CA, 0xB8CE, 0x88D5, 0xB8CF, 0x88D2, 0xB8D0, 0x899C, 0xB8D1, 0x89E3, 0xB8D2, 0x8A6B, 0xB8D3, 0x8A72, 0xB8D4, 0x8A73, + 0xB8D5, 0x8A66, 0xB8D6, 0x8A69, 0xB8D7, 0x8A70, 0xB8D8, 0x8A87, 0xB8D9, 0x8A7C, 0xB8DA, 0x8A63, 0xB8DB, 0x8AA0, 0xB8DC, 0x8A71, + 0xB8DD, 0x8A85, 0xB8DE, 0x8A6D, 0xB8DF, 0x8A62, 0xB8E0, 0x8A6E, 0xB8E1, 0x8A6C, 0xB8E2, 0x8A79, 0xB8E3, 0x8A7B, 0xB8E4, 0x8A3E, + 0xB8E5, 0x8A68, 0xB8E6, 0x8C62, 0xB8E7, 0x8C8A, 0xB8E8, 0x8C89, 0xB8E9, 0x8CCA, 0xB8EA, 0x8CC7, 0xB8EB, 0x8CC8, 0xB8EC, 0x8CC4, + 0xB8ED, 0x8CB2, 0xB8EE, 0x8CC3, 0xB8EF, 0x8CC2, 0xB8F0, 0x8CC5, 0xB8F1, 0x8DE1, 0xB8F2, 0x8DDF, 0xB8F3, 0x8DE8, 0xB8F4, 0x8DEF, + 0xB8F5, 0x8DF3, 0xB8F6, 0x8DFA, 0xB8F7, 0x8DEA, 0xB8F8, 0x8DE4, 0xB8F9, 0x8DE6, 0xB8FA, 0x8EB2, 0xB8FB, 0x8F03, 0xB8FC, 0x8F09, + 0xB8FD, 0x8EFE, 0xB8FE, 0x8F0A, 0xB940, 0x8F9F, 0xB941, 0x8FB2, 0xB942, 0x904B, 0xB943, 0x904A, 0xB944, 0x9053, 0xB945, 0x9042, + 0xB946, 0x9054, 0xB947, 0x903C, 0xB948, 0x9055, 0xB949, 0x9050, 0xB94A, 0x9047, 0xB94B, 0x904F, 0xB94C, 0x904E, 0xB94D, 0x904D, + 0xB94E, 0x9051, 0xB94F, 0x903E, 0xB950, 0x9041, 0xB951, 0x9112, 0xB952, 0x9117, 0xB953, 0x916C, 0xB954, 0x916A, 0xB955, 0x9169, + 0xB956, 0x91C9, 0xB957, 0x9237, 0xB958, 0x9257, 0xB959, 0x9238, 0xB95A, 0x923D, 0xB95B, 0x9240, 0xB95C, 0x923E, 0xB95D, 0x925B, + 0xB95E, 0x924B, 0xB95F, 0x9264, 0xB960, 0x9251, 0xB961, 0x9234, 0xB962, 0x9249, 0xB963, 0x924D, 0xB964, 0x9245, 0xB965, 0x9239, + 0xB966, 0x923F, 0xB967, 0x925A, 0xB968, 0x9598, 0xB969, 0x9698, 0xB96A, 0x9694, 0xB96B, 0x9695, 0xB96C, 0x96CD, 0xB96D, 0x96CB, + 0xB96E, 0x96C9, 0xB96F, 0x96CA, 0xB970, 0x96F7, 0xB971, 0x96FB, 0xB972, 0x96F9, 0xB973, 0x96F6, 0xB974, 0x9756, 0xB975, 0x9774, + 0xB976, 0x9776, 0xB977, 0x9810, 0xB978, 0x9811, 0xB979, 0x9813, 0xB97A, 0x980A, 0xB97B, 0x9812, 0xB97C, 0x980C, 0xB97D, 0x98FC, + 0xB97E, 0x98F4, 0xB9A1, 0x98FD, 0xB9A2, 0x98FE, 0xB9A3, 0x99B3, 0xB9A4, 0x99B1, 0xB9A5, 0x99B4, 0xB9A6, 0x9AE1, 0xB9A7, 0x9CE9, + 0xB9A8, 0x9E82, 0xB9A9, 0x9F0E, 0xB9AA, 0x9F13, 0xB9AB, 0x9F20, 0xB9AC, 0x50E7, 0xB9AD, 0x50EE, 0xB9AE, 0x50E5, 0xB9AF, 0x50D6, + 0xB9B0, 0x50ED, 0xB9B1, 0x50DA, 0xB9B2, 0x50D5, 0xB9B3, 0x50CF, 0xB9B4, 0x50D1, 0xB9B5, 0x50F1, 0xB9B6, 0x50CE, 0xB9B7, 0x50E9, + 0xB9B8, 0x5162, 0xB9B9, 0x51F3, 0xB9BA, 0x5283, 0xB9BB, 0x5282, 0xB9BC, 0x5331, 0xB9BD, 0x53AD, 0xB9BE, 0x55FE, 0xB9BF, 0x5600, + 0xB9C0, 0x561B, 0xB9C1, 0x5617, 0xB9C2, 0x55FD, 0xB9C3, 0x5614, 0xB9C4, 0x5606, 0xB9C5, 0x5609, 0xB9C6, 0x560D, 0xB9C7, 0x560E, + 0xB9C8, 0x55F7, 0xB9C9, 0x5616, 0xB9CA, 0x561F, 0xB9CB, 0x5608, 0xB9CC, 0x5610, 0xB9CD, 0x55F6, 0xB9CE, 0x5718, 0xB9CF, 0x5716, + 0xB9D0, 0x5875, 0xB9D1, 0x587E, 0xB9D2, 0x5883, 0xB9D3, 0x5893, 0xB9D4, 0x588A, 0xB9D5, 0x5879, 0xB9D6, 0x5885, 0xB9D7, 0x587D, + 0xB9D8, 0x58FD, 0xB9D9, 0x5925, 0xB9DA, 0x5922, 0xB9DB, 0x5924, 0xB9DC, 0x596A, 0xB9DD, 0x5969, 0xB9DE, 0x5AE1, 0xB9DF, 0x5AE6, + 0xB9E0, 0x5AE9, 0xB9E1, 0x5AD7, 0xB9E2, 0x5AD6, 0xB9E3, 0x5AD8, 0xB9E4, 0x5AE3, 0xB9E5, 0x5B75, 0xB9E6, 0x5BDE, 0xB9E7, 0x5BE7, + 0xB9E8, 0x5BE1, 0xB9E9, 0x5BE5, 0xB9EA, 0x5BE6, 0xB9EB, 0x5BE8, 0xB9EC, 0x5BE2, 0xB9ED, 0x5BE4, 0xB9EE, 0x5BDF, 0xB9EF, 0x5C0D, + 0xB9F0, 0x5C62, 0xB9F1, 0x5D84, 0xB9F2, 0x5D87, 0xB9F3, 0x5E5B, 0xB9F4, 0x5E63, 0xB9F5, 0x5E55, 0xB9F6, 0x5E57, 0xB9F7, 0x5E54, + 0xB9F8, 0x5ED3, 0xB9F9, 0x5ED6, 0xB9FA, 0x5F0A, 0xB9FB, 0x5F46, 0xB9FC, 0x5F70, 0xB9FD, 0x5FB9, 0xB9FE, 0x6147, 0xBA40, 0x613F, + 0xBA41, 0x614B, 0xBA42, 0x6177, 0xBA43, 0x6162, 0xBA44, 0x6163, 0xBA45, 0x615F, 0xBA46, 0x615A, 0xBA47, 0x6158, 0xBA48, 0x6175, + 0xBA49, 0x622A, 0xBA4A, 0x6487, 0xBA4B, 0x6458, 0xBA4C, 0x6454, 0xBA4D, 0x64A4, 0xBA4E, 0x6478, 0xBA4F, 0x645F, 0xBA50, 0x647A, + 0xBA51, 0x6451, 0xBA52, 0x6467, 0xBA53, 0x6434, 0xBA54, 0x646D, 0xBA55, 0x647B, 0xBA56, 0x6572, 0xBA57, 0x65A1, 0xBA58, 0x65D7, + 0xBA59, 0x65D6, 0xBA5A, 0x66A2, 0xBA5B, 0x66A8, 0xBA5C, 0x669D, 0xBA5D, 0x699C, 0xBA5E, 0x69A8, 0xBA5F, 0x6995, 0xBA60, 0x69C1, + 0xBA61, 0x69AE, 0xBA62, 0x69D3, 0xBA63, 0x69CB, 0xBA64, 0x699B, 0xBA65, 0x69B7, 0xBA66, 0x69BB, 0xBA67, 0x69AB, 0xBA68, 0x69B4, + 0xBA69, 0x69D0, 0xBA6A, 0x69CD, 0xBA6B, 0x69AD, 0xBA6C, 0x69CC, 0xBA6D, 0x69A6, 0xBA6E, 0x69C3, 0xBA6F, 0x69A3, 0xBA70, 0x6B49, + 0xBA71, 0x6B4C, 0xBA72, 0x6C33, 0xBA73, 0x6F33, 0xBA74, 0x6F14, 0xBA75, 0x6EFE, 0xBA76, 0x6F13, 0xBA77, 0x6EF4, 0xBA78, 0x6F29, + 0xBA79, 0x6F3E, 0xBA7A, 0x6F20, 0xBA7B, 0x6F2C, 0xBA7C, 0x6F0F, 0xBA7D, 0x6F02, 0xBA7E, 0x6F22, 0xBAA1, 0x6EFF, 0xBAA2, 0x6EEF, + 0xBAA3, 0x6F06, 0xBAA4, 0x6F31, 0xBAA5, 0x6F38, 0xBAA6, 0x6F32, 0xBAA7, 0x6F23, 0xBAA8, 0x6F15, 0xBAA9, 0x6F2B, 0xBAAA, 0x6F2F, + 0xBAAB, 0x6F88, 0xBAAC, 0x6F2A, 0xBAAD, 0x6EEC, 0xBAAE, 0x6F01, 0xBAAF, 0x6EF2, 0xBAB0, 0x6ECC, 0xBAB1, 0x6EF7, 0xBAB2, 0x7194, + 0xBAB3, 0x7199, 0xBAB4, 0x717D, 0xBAB5, 0x718A, 0xBAB6, 0x7184, 0xBAB7, 0x7192, 0xBAB8, 0x723E, 0xBAB9, 0x7292, 0xBABA, 0x7296, + 0xBABB, 0x7344, 0xBABC, 0x7350, 0xBABD, 0x7464, 0xBABE, 0x7463, 0xBABF, 0x746A, 0xBAC0, 0x7470, 0xBAC1, 0x746D, 0xBAC2, 0x7504, + 0xBAC3, 0x7591, 0xBAC4, 0x7627, 0xBAC5, 0x760D, 0xBAC6, 0x760B, 0xBAC7, 0x7609, 0xBAC8, 0x7613, 0xBAC9, 0x76E1, 0xBACA, 0x76E3, + 0xBACB, 0x7784, 0xBACC, 0x777D, 0xBACD, 0x777F, 0xBACE, 0x7761, 0xBACF, 0x78C1, 0xBAD0, 0x789F, 0xBAD1, 0x78A7, 0xBAD2, 0x78B3, + 0xBAD3, 0x78A9, 0xBAD4, 0x78A3, 0xBAD5, 0x798E, 0xBAD6, 0x798F, 0xBAD7, 0x798D, 0xBAD8, 0x7A2E, 0xBAD9, 0x7A31, 0xBADA, 0x7AAA, + 0xBADB, 0x7AA9, 0xBADC, 0x7AED, 0xBADD, 0x7AEF, 0xBADE, 0x7BA1, 0xBADF, 0x7B95, 0xBAE0, 0x7B8B, 0xBAE1, 0x7B75, 0xBAE2, 0x7B97, + 0xBAE3, 0x7B9D, 0xBAE4, 0x7B94, 0xBAE5, 0x7B8F, 0xBAE6, 0x7BB8, 0xBAE7, 0x7B87, 0xBAE8, 0x7B84, 0xBAE9, 0x7CB9, 0xBAEA, 0x7CBD, + 0xBAEB, 0x7CBE, 0xBAEC, 0x7DBB, 0xBAED, 0x7DB0, 0xBAEE, 0x7D9C, 0xBAEF, 0x7DBD, 0xBAF0, 0x7DBE, 0xBAF1, 0x7DA0, 0xBAF2, 0x7DCA, + 0xBAF3, 0x7DB4, 0xBAF4, 0x7DB2, 0xBAF5, 0x7DB1, 0xBAF6, 0x7DBA, 0xBAF7, 0x7DA2, 0xBAF8, 0x7DBF, 0xBAF9, 0x7DB5, 0xBAFA, 0x7DB8, + 0xBAFB, 0x7DAD, 0xBAFC, 0x7DD2, 0xBAFD, 0x7DC7, 0xBAFE, 0x7DAC, 0xBB40, 0x7F70, 0xBB41, 0x7FE0, 0xBB42, 0x7FE1, 0xBB43, 0x7FDF, + 0xBB44, 0x805E, 0xBB45, 0x805A, 0xBB46, 0x8087, 0xBB47, 0x8150, 0xBB48, 0x8180, 0xBB49, 0x818F, 0xBB4A, 0x8188, 0xBB4B, 0x818A, + 0xBB4C, 0x817F, 0xBB4D, 0x8182, 0xBB4E, 0x81E7, 0xBB4F, 0x81FA, 0xBB50, 0x8207, 0xBB51, 0x8214, 0xBB52, 0x821E, 0xBB53, 0x824B, + 0xBB54, 0x84C9, 0xBB55, 0x84BF, 0xBB56, 0x84C6, 0xBB57, 0x84C4, 0xBB58, 0x8499, 0xBB59, 0x849E, 0xBB5A, 0x84B2, 0xBB5B, 0x849C, + 0xBB5C, 0x84CB, 0xBB5D, 0x84B8, 0xBB5E, 0x84C0, 0xBB5F, 0x84D3, 0xBB60, 0x8490, 0xBB61, 0x84BC, 0xBB62, 0x84D1, 0xBB63, 0x84CA, + 0xBB64, 0x873F, 0xBB65, 0x871C, 0xBB66, 0x873B, 0xBB67, 0x8722, 0xBB68, 0x8725, 0xBB69, 0x8734, 0xBB6A, 0x8718, 0xBB6B, 0x8755, + 0xBB6C, 0x8737, 0xBB6D, 0x8729, 0xBB6E, 0x88F3, 0xBB6F, 0x8902, 0xBB70, 0x88F4, 0xBB71, 0x88F9, 0xBB72, 0x88F8, 0xBB73, 0x88FD, + 0xBB74, 0x88E8, 0xBB75, 0x891A, 0xBB76, 0x88EF, 0xBB77, 0x8AA6, 0xBB78, 0x8A8C, 0xBB79, 0x8A9E, 0xBB7A, 0x8AA3, 0xBB7B, 0x8A8D, + 0xBB7C, 0x8AA1, 0xBB7D, 0x8A93, 0xBB7E, 0x8AA4, 0xBBA1, 0x8AAA, 0xBBA2, 0x8AA5, 0xBBA3, 0x8AA8, 0xBBA4, 0x8A98, 0xBBA5, 0x8A91, + 0xBBA6, 0x8A9A, 0xBBA7, 0x8AA7, 0xBBA8, 0x8C6A, 0xBBA9, 0x8C8D, 0xBBAA, 0x8C8C, 0xBBAB, 0x8CD3, 0xBBAC, 0x8CD1, 0xBBAD, 0x8CD2, + 0xBBAE, 0x8D6B, 0xBBAF, 0x8D99, 0xBBB0, 0x8D95, 0xBBB1, 0x8DFC, 0xBBB2, 0x8F14, 0xBBB3, 0x8F12, 0xBBB4, 0x8F15, 0xBBB5, 0x8F13, + 0xBBB6, 0x8FA3, 0xBBB7, 0x9060, 0xBBB8, 0x9058, 0xBBB9, 0x905C, 0xBBBA, 0x9063, 0xBBBB, 0x9059, 0xBBBC, 0x905E, 0xBBBD, 0x9062, + 0xBBBE, 0x905D, 0xBBBF, 0x905B, 0xBBC0, 0x9119, 0xBBC1, 0x9118, 0xBBC2, 0x911E, 0xBBC3, 0x9175, 0xBBC4, 0x9178, 0xBBC5, 0x9177, + 0xBBC6, 0x9174, 0xBBC7, 0x9278, 0xBBC8, 0x9280, 0xBBC9, 0x9285, 0xBBCA, 0x9298, 0xBBCB, 0x9296, 0xBBCC, 0x927B, 0xBBCD, 0x9293, + 0xBBCE, 0x929C, 0xBBCF, 0x92A8, 0xBBD0, 0x927C, 0xBBD1, 0x9291, 0xBBD2, 0x95A1, 0xBBD3, 0x95A8, 0xBBD4, 0x95A9, 0xBBD5, 0x95A3, + 0xBBD6, 0x95A5, 0xBBD7, 0x95A4, 0xBBD8, 0x9699, 0xBBD9, 0x969C, 0xBBDA, 0x969B, 0xBBDB, 0x96CC, 0xBBDC, 0x96D2, 0xBBDD, 0x9700, + 0xBBDE, 0x977C, 0xBBDF, 0x9785, 0xBBE0, 0x97F6, 0xBBE1, 0x9817, 0xBBE2, 0x9818, 0xBBE3, 0x98AF, 0xBBE4, 0x98B1, 0xBBE5, 0x9903, + 0xBBE6, 0x9905, 0xBBE7, 0x990C, 0xBBE8, 0x9909, 0xBBE9, 0x99C1, 0xBBEA, 0x9AAF, 0xBBEB, 0x9AB0, 0xBBEC, 0x9AE6, 0xBBED, 0x9B41, + 0xBBEE, 0x9B42, 0xBBEF, 0x9CF4, 0xBBF0, 0x9CF6, 0xBBF1, 0x9CF3, 0xBBF2, 0x9EBC, 0xBBF3, 0x9F3B, 0xBBF4, 0x9F4A, 0xBBF5, 0x5104, + 0xBBF6, 0x5100, 0xBBF7, 0x50FB, 0xBBF8, 0x50F5, 0xBBF9, 0x50F9, 0xBBFA, 0x5102, 0xBBFB, 0x5108, 0xBBFC, 0x5109, 0xBBFD, 0x5105, + 0xBBFE, 0x51DC, 0xBC40, 0x5287, 0xBC41, 0x5288, 0xBC42, 0x5289, 0xBC43, 0x528D, 0xBC44, 0x528A, 0xBC45, 0x52F0, 0xBC46, 0x53B2, + 0xBC47, 0x562E, 0xBC48, 0x563B, 0xBC49, 0x5639, 0xBC4A, 0x5632, 0xBC4B, 0x563F, 0xBC4C, 0x5634, 0xBC4D, 0x5629, 0xBC4E, 0x5653, + 0xBC4F, 0x564E, 0xBC50, 0x5657, 0xBC51, 0x5674, 0xBC52, 0x5636, 0xBC53, 0x562F, 0xBC54, 0x5630, 0xBC55, 0x5880, 0xBC56, 0x589F, + 0xBC57, 0x589E, 0xBC58, 0x58B3, 0xBC59, 0x589C, 0xBC5A, 0x58AE, 0xBC5B, 0x58A9, 0xBC5C, 0x58A6, 0xBC5D, 0x596D, 0xBC5E, 0x5B09, + 0xBC5F, 0x5AFB, 0xBC60, 0x5B0B, 0xBC61, 0x5AF5, 0xBC62, 0x5B0C, 0xBC63, 0x5B08, 0xBC64, 0x5BEE, 0xBC65, 0x5BEC, 0xBC66, 0x5BE9, + 0xBC67, 0x5BEB, 0xBC68, 0x5C64, 0xBC69, 0x5C65, 0xBC6A, 0x5D9D, 0xBC6B, 0x5D94, 0xBC6C, 0x5E62, 0xBC6D, 0x5E5F, 0xBC6E, 0x5E61, + 0xBC6F, 0x5EE2, 0xBC70, 0x5EDA, 0xBC71, 0x5EDF, 0xBC72, 0x5EDD, 0xBC73, 0x5EE3, 0xBC74, 0x5EE0, 0xBC75, 0x5F48, 0xBC76, 0x5F71, + 0xBC77, 0x5FB7, 0xBC78, 0x5FB5, 0xBC79, 0x6176, 0xBC7A, 0x6167, 0xBC7B, 0x616E, 0xBC7C, 0x615D, 0xBC7D, 0x6155, 0xBC7E, 0x6182, + 0xBCA1, 0x617C, 0xBCA2, 0x6170, 0xBCA3, 0x616B, 0xBCA4, 0x617E, 0xBCA5, 0x61A7, 0xBCA6, 0x6190, 0xBCA7, 0x61AB, 0xBCA8, 0x618E, + 0xBCA9, 0x61AC, 0xBCAA, 0x619A, 0xBCAB, 0x61A4, 0xBCAC, 0x6194, 0xBCAD, 0x61AE, 0xBCAE, 0x622E, 0xBCAF, 0x6469, 0xBCB0, 0x646F, + 0xBCB1, 0x6479, 0xBCB2, 0x649E, 0xBCB3, 0x64B2, 0xBCB4, 0x6488, 0xBCB5, 0x6490, 0xBCB6, 0x64B0, 0xBCB7, 0x64A5, 0xBCB8, 0x6493, + 0xBCB9, 0x6495, 0xBCBA, 0x64A9, 0xBCBB, 0x6492, 0xBCBC, 0x64AE, 0xBCBD, 0x64AD, 0xBCBE, 0x64AB, 0xBCBF, 0x649A, 0xBCC0, 0x64AC, + 0xBCC1, 0x6499, 0xBCC2, 0x64A2, 0xBCC3, 0x64B3, 0xBCC4, 0x6575, 0xBCC5, 0x6577, 0xBCC6, 0x6578, 0xBCC7, 0x66AE, 0xBCC8, 0x66AB, + 0xBCC9, 0x66B4, 0xBCCA, 0x66B1, 0xBCCB, 0x6A23, 0xBCCC, 0x6A1F, 0xBCCD, 0x69E8, 0xBCCE, 0x6A01, 0xBCCF, 0x6A1E, 0xBCD0, 0x6A19, + 0xBCD1, 0x69FD, 0xBCD2, 0x6A21, 0xBCD3, 0x6A13, 0xBCD4, 0x6A0A, 0xBCD5, 0x69F3, 0xBCD6, 0x6A02, 0xBCD7, 0x6A05, 0xBCD8, 0x69ED, + 0xBCD9, 0x6A11, 0xBCDA, 0x6B50, 0xBCDB, 0x6B4E, 0xBCDC, 0x6BA4, 0xBCDD, 0x6BC5, 0xBCDE, 0x6BC6, 0xBCDF, 0x6F3F, 0xBCE0, 0x6F7C, + 0xBCE1, 0x6F84, 0xBCE2, 0x6F51, 0xBCE3, 0x6F66, 0xBCE4, 0x6F54, 0xBCE5, 0x6F86, 0xBCE6, 0x6F6D, 0xBCE7, 0x6F5B, 0xBCE8, 0x6F78, + 0xBCE9, 0x6F6E, 0xBCEA, 0x6F8E, 0xBCEB, 0x6F7A, 0xBCEC, 0x6F70, 0xBCED, 0x6F64, 0xBCEE, 0x6F97, 0xBCEF, 0x6F58, 0xBCF0, 0x6ED5, + 0xBCF1, 0x6F6F, 0xBCF2, 0x6F60, 0xBCF3, 0x6F5F, 0xBCF4, 0x719F, 0xBCF5, 0x71AC, 0xBCF6, 0x71B1, 0xBCF7, 0x71A8, 0xBCF8, 0x7256, + 0xBCF9, 0x729B, 0xBCFA, 0x734E, 0xBCFB, 0x7357, 0xBCFC, 0x7469, 0xBCFD, 0x748B, 0xBCFE, 0x7483, 0xBD40, 0x747E, 0xBD41, 0x7480, + 0xBD42, 0x757F, 0xBD43, 0x7620, 0xBD44, 0x7629, 0xBD45, 0x761F, 0xBD46, 0x7624, 0xBD47, 0x7626, 0xBD48, 0x7621, 0xBD49, 0x7622, + 0xBD4A, 0x769A, 0xBD4B, 0x76BA, 0xBD4C, 0x76E4, 0xBD4D, 0x778E, 0xBD4E, 0x7787, 0xBD4F, 0x778C, 0xBD50, 0x7791, 0xBD51, 0x778B, + 0xBD52, 0x78CB, 0xBD53, 0x78C5, 0xBD54, 0x78BA, 0xBD55, 0x78CA, 0xBD56, 0x78BE, 0xBD57, 0x78D5, 0xBD58, 0x78BC, 0xBD59, 0x78D0, + 0xBD5A, 0x7A3F, 0xBD5B, 0x7A3C, 0xBD5C, 0x7A40, 0xBD5D, 0x7A3D, 0xBD5E, 0x7A37, 0xBD5F, 0x7A3B, 0xBD60, 0x7AAF, 0xBD61, 0x7AAE, + 0xBD62, 0x7BAD, 0xBD63, 0x7BB1, 0xBD64, 0x7BC4, 0xBD65, 0x7BB4, 0xBD66, 0x7BC6, 0xBD67, 0x7BC7, 0xBD68, 0x7BC1, 0xBD69, 0x7BA0, + 0xBD6A, 0x7BCC, 0xBD6B, 0x7CCA, 0xBD6C, 0x7DE0, 0xBD6D, 0x7DF4, 0xBD6E, 0x7DEF, 0xBD6F, 0x7DFB, 0xBD70, 0x7DD8, 0xBD71, 0x7DEC, + 0xBD72, 0x7DDD, 0xBD73, 0x7DE8, 0xBD74, 0x7DE3, 0xBD75, 0x7DDA, 0xBD76, 0x7DDE, 0xBD77, 0x7DE9, 0xBD78, 0x7D9E, 0xBD79, 0x7DD9, + 0xBD7A, 0x7DF2, 0xBD7B, 0x7DF9, 0xBD7C, 0x7F75, 0xBD7D, 0x7F77, 0xBD7E, 0x7FAF, 0xBDA1, 0x7FE9, 0xBDA2, 0x8026, 0xBDA3, 0x819B, + 0xBDA4, 0x819C, 0xBDA5, 0x819D, 0xBDA6, 0x81A0, 0xBDA7, 0x819A, 0xBDA8, 0x8198, 0xBDA9, 0x8517, 0xBDAA, 0x853D, 0xBDAB, 0x851A, + 0xBDAC, 0x84EE, 0xBDAD, 0x852C, 0xBDAE, 0x852D, 0xBDAF, 0x8513, 0xBDB0, 0x8511, 0xBDB1, 0x8523, 0xBDB2, 0x8521, 0xBDB3, 0x8514, + 0xBDB4, 0x84EC, 0xBDB5, 0x8525, 0xBDB6, 0x84FF, 0xBDB7, 0x8506, 0xBDB8, 0x8782, 0xBDB9, 0x8774, 0xBDBA, 0x8776, 0xBDBB, 0x8760, + 0xBDBC, 0x8766, 0xBDBD, 0x8778, 0xBDBE, 0x8768, 0xBDBF, 0x8759, 0xBDC0, 0x8757, 0xBDC1, 0x874C, 0xBDC2, 0x8753, 0xBDC3, 0x885B, + 0xBDC4, 0x885D, 0xBDC5, 0x8910, 0xBDC6, 0x8907, 0xBDC7, 0x8912, 0xBDC8, 0x8913, 0xBDC9, 0x8915, 0xBDCA, 0x890A, 0xBDCB, 0x8ABC, + 0xBDCC, 0x8AD2, 0xBDCD, 0x8AC7, 0xBDCE, 0x8AC4, 0xBDCF, 0x8A95, 0xBDD0, 0x8ACB, 0xBDD1, 0x8AF8, 0xBDD2, 0x8AB2, 0xBDD3, 0x8AC9, + 0xBDD4, 0x8AC2, 0xBDD5, 0x8ABF, 0xBDD6, 0x8AB0, 0xBDD7, 0x8AD6, 0xBDD8, 0x8ACD, 0xBDD9, 0x8AB6, 0xBDDA, 0x8AB9, 0xBDDB, 0x8ADB, + 0xBDDC, 0x8C4C, 0xBDDD, 0x8C4E, 0xBDDE, 0x8C6C, 0xBDDF, 0x8CE0, 0xBDE0, 0x8CDE, 0xBDE1, 0x8CE6, 0xBDE2, 0x8CE4, 0xBDE3, 0x8CEC, + 0xBDE4, 0x8CED, 0xBDE5, 0x8CE2, 0xBDE6, 0x8CE3, 0xBDE7, 0x8CDC, 0xBDE8, 0x8CEA, 0xBDE9, 0x8CE1, 0xBDEA, 0x8D6D, 0xBDEB, 0x8D9F, + 0xBDEC, 0x8DA3, 0xBDED, 0x8E2B, 0xBDEE, 0x8E10, 0xBDEF, 0x8E1D, 0xBDF0, 0x8E22, 0xBDF1, 0x8E0F, 0xBDF2, 0x8E29, 0xBDF3, 0x8E1F, + 0xBDF4, 0x8E21, 0xBDF5, 0x8E1E, 0xBDF6, 0x8EBA, 0xBDF7, 0x8F1D, 0xBDF8, 0x8F1B, 0xBDF9, 0x8F1F, 0xBDFA, 0x8F29, 0xBDFB, 0x8F26, + 0xBDFC, 0x8F2A, 0xBDFD, 0x8F1C, 0xBDFE, 0x8F1E, 0xBE40, 0x8F25, 0xBE41, 0x9069, 0xBE42, 0x906E, 0xBE43, 0x9068, 0xBE44, 0x906D, + 0xBE45, 0x9077, 0xBE46, 0x9130, 0xBE47, 0x912D, 0xBE48, 0x9127, 0xBE49, 0x9131, 0xBE4A, 0x9187, 0xBE4B, 0x9189, 0xBE4C, 0x918B, + 0xBE4D, 0x9183, 0xBE4E, 0x92C5, 0xBE4F, 0x92BB, 0xBE50, 0x92B7, 0xBE51, 0x92EA, 0xBE52, 0x92AC, 0xBE53, 0x92E4, 0xBE54, 0x92C1, + 0xBE55, 0x92B3, 0xBE56, 0x92BC, 0xBE57, 0x92D2, 0xBE58, 0x92C7, 0xBE59, 0x92F0, 0xBE5A, 0x92B2, 0xBE5B, 0x95AD, 0xBE5C, 0x95B1, + 0xBE5D, 0x9704, 0xBE5E, 0x9706, 0xBE5F, 0x9707, 0xBE60, 0x9709, 0xBE61, 0x9760, 0xBE62, 0x978D, 0xBE63, 0x978B, 0xBE64, 0x978F, + 0xBE65, 0x9821, 0xBE66, 0x982B, 0xBE67, 0x981C, 0xBE68, 0x98B3, 0xBE69, 0x990A, 0xBE6A, 0x9913, 0xBE6B, 0x9912, 0xBE6C, 0x9918, + 0xBE6D, 0x99DD, 0xBE6E, 0x99D0, 0xBE6F, 0x99DF, 0xBE70, 0x99DB, 0xBE71, 0x99D1, 0xBE72, 0x99D5, 0xBE73, 0x99D2, 0xBE74, 0x99D9, + 0xBE75, 0x9AB7, 0xBE76, 0x9AEE, 0xBE77, 0x9AEF, 0xBE78, 0x9B27, 0xBE79, 0x9B45, 0xBE7A, 0x9B44, 0xBE7B, 0x9B77, 0xBE7C, 0x9B6F, + 0xBE7D, 0x9D06, 0xBE7E, 0x9D09, 0xBEA1, 0x9D03, 0xBEA2, 0x9EA9, 0xBEA3, 0x9EBE, 0xBEA4, 0x9ECE, 0xBEA5, 0x58A8, 0xBEA6, 0x9F52, + 0xBEA7, 0x5112, 0xBEA8, 0x5118, 0xBEA9, 0x5114, 0xBEAA, 0x5110, 0xBEAB, 0x5115, 0xBEAC, 0x5180, 0xBEAD, 0x51AA, 0xBEAE, 0x51DD, + 0xBEAF, 0x5291, 0xBEB0, 0x5293, 0xBEB1, 0x52F3, 0xBEB2, 0x5659, 0xBEB3, 0x566B, 0xBEB4, 0x5679, 0xBEB5, 0x5669, 0xBEB6, 0x5664, + 0xBEB7, 0x5678, 0xBEB8, 0x566A, 0xBEB9, 0x5668, 0xBEBA, 0x5665, 0xBEBB, 0x5671, 0xBEBC, 0x566F, 0xBEBD, 0x566C, 0xBEBE, 0x5662, + 0xBEBF, 0x5676, 0xBEC0, 0x58C1, 0xBEC1, 0x58BE, 0xBEC2, 0x58C7, 0xBEC3, 0x58C5, 0xBEC4, 0x596E, 0xBEC5, 0x5B1D, 0xBEC6, 0x5B34, + 0xBEC7, 0x5B78, 0xBEC8, 0x5BF0, 0xBEC9, 0x5C0E, 0xBECA, 0x5F4A, 0xBECB, 0x61B2, 0xBECC, 0x6191, 0xBECD, 0x61A9, 0xBECE, 0x618A, + 0xBECF, 0x61CD, 0xBED0, 0x61B6, 0xBED1, 0x61BE, 0xBED2, 0x61CA, 0xBED3, 0x61C8, 0xBED4, 0x6230, 0xBED5, 0x64C5, 0xBED6, 0x64C1, + 0xBED7, 0x64CB, 0xBED8, 0x64BB, 0xBED9, 0x64BC, 0xBEDA, 0x64DA, 0xBEDB, 0x64C4, 0xBEDC, 0x64C7, 0xBEDD, 0x64C2, 0xBEDE, 0x64CD, + 0xBEDF, 0x64BF, 0xBEE0, 0x64D2, 0xBEE1, 0x64D4, 0xBEE2, 0x64BE, 0xBEE3, 0x6574, 0xBEE4, 0x66C6, 0xBEE5, 0x66C9, 0xBEE6, 0x66B9, + 0xBEE7, 0x66C4, 0xBEE8, 0x66C7, 0xBEE9, 0x66B8, 0xBEEA, 0x6A3D, 0xBEEB, 0x6A38, 0xBEEC, 0x6A3A, 0xBEED, 0x6A59, 0xBEEE, 0x6A6B, + 0xBEEF, 0x6A58, 0xBEF0, 0x6A39, 0xBEF1, 0x6A44, 0xBEF2, 0x6A62, 0xBEF3, 0x6A61, 0xBEF4, 0x6A4B, 0xBEF5, 0x6A47, 0xBEF6, 0x6A35, + 0xBEF7, 0x6A5F, 0xBEF8, 0x6A48, 0xBEF9, 0x6B59, 0xBEFA, 0x6B77, 0xBEFB, 0x6C05, 0xBEFC, 0x6FC2, 0xBEFD, 0x6FB1, 0xBEFE, 0x6FA1, + 0xBF40, 0x6FC3, 0xBF41, 0x6FA4, 0xBF42, 0x6FC1, 0xBF43, 0x6FA7, 0xBF44, 0x6FB3, 0xBF45, 0x6FC0, 0xBF46, 0x6FB9, 0xBF47, 0x6FB6, + 0xBF48, 0x6FA6, 0xBF49, 0x6FA0, 0xBF4A, 0x6FB4, 0xBF4B, 0x71BE, 0xBF4C, 0x71C9, 0xBF4D, 0x71D0, 0xBF4E, 0x71D2, 0xBF4F, 0x71C8, + 0xBF50, 0x71D5, 0xBF51, 0x71B9, 0xBF52, 0x71CE, 0xBF53, 0x71D9, 0xBF54, 0x71DC, 0xBF55, 0x71C3, 0xBF56, 0x71C4, 0xBF57, 0x7368, + 0xBF58, 0x749C, 0xBF59, 0x74A3, 0xBF5A, 0x7498, 0xBF5B, 0x749F, 0xBF5C, 0x749E, 0xBF5D, 0x74E2, 0xBF5E, 0x750C, 0xBF5F, 0x750D, + 0xBF60, 0x7634, 0xBF61, 0x7638, 0xBF62, 0x763A, 0xBF63, 0x76E7, 0xBF64, 0x76E5, 0xBF65, 0x77A0, 0xBF66, 0x779E, 0xBF67, 0x779F, + 0xBF68, 0x77A5, 0xBF69, 0x78E8, 0xBF6A, 0x78DA, 0xBF6B, 0x78EC, 0xBF6C, 0x78E7, 0xBF6D, 0x79A6, 0xBF6E, 0x7A4D, 0xBF6F, 0x7A4E, + 0xBF70, 0x7A46, 0xBF71, 0x7A4C, 0xBF72, 0x7A4B, 0xBF73, 0x7ABA, 0xBF74, 0x7BD9, 0xBF75, 0x7C11, 0xBF76, 0x7BC9, 0xBF77, 0x7BE4, + 0xBF78, 0x7BDB, 0xBF79, 0x7BE1, 0xBF7A, 0x7BE9, 0xBF7B, 0x7BE6, 0xBF7C, 0x7CD5, 0xBF7D, 0x7CD6, 0xBF7E, 0x7E0A, 0xBFA1, 0x7E11, + 0xBFA2, 0x7E08, 0xBFA3, 0x7E1B, 0xBFA4, 0x7E23, 0xBFA5, 0x7E1E, 0xBFA6, 0x7E1D, 0xBFA7, 0x7E09, 0xBFA8, 0x7E10, 0xBFA9, 0x7F79, + 0xBFAA, 0x7FB2, 0xBFAB, 0x7FF0, 0xBFAC, 0x7FF1, 0xBFAD, 0x7FEE, 0xBFAE, 0x8028, 0xBFAF, 0x81B3, 0xBFB0, 0x81A9, 0xBFB1, 0x81A8, + 0xBFB2, 0x81FB, 0xBFB3, 0x8208, 0xBFB4, 0x8258, 0xBFB5, 0x8259, 0xBFB6, 0x854A, 0xBFB7, 0x8559, 0xBFB8, 0x8548, 0xBFB9, 0x8568, + 0xBFBA, 0x8569, 0xBFBB, 0x8543, 0xBFBC, 0x8549, 0xBFBD, 0x856D, 0xBFBE, 0x856A, 0xBFBF, 0x855E, 0xBFC0, 0x8783, 0xBFC1, 0x879F, + 0xBFC2, 0x879E, 0xBFC3, 0x87A2, 0xBFC4, 0x878D, 0xBFC5, 0x8861, 0xBFC6, 0x892A, 0xBFC7, 0x8932, 0xBFC8, 0x8925, 0xBFC9, 0x892B, + 0xBFCA, 0x8921, 0xBFCB, 0x89AA, 0xBFCC, 0x89A6, 0xBFCD, 0x8AE6, 0xBFCE, 0x8AFA, 0xBFCF, 0x8AEB, 0xBFD0, 0x8AF1, 0xBFD1, 0x8B00, + 0xBFD2, 0x8ADC, 0xBFD3, 0x8AE7, 0xBFD4, 0x8AEE, 0xBFD5, 0x8AFE, 0xBFD6, 0x8B01, 0xBFD7, 0x8B02, 0xBFD8, 0x8AF7, 0xBFD9, 0x8AED, + 0xBFDA, 0x8AF3, 0xBFDB, 0x8AF6, 0xBFDC, 0x8AFC, 0xBFDD, 0x8C6B, 0xBFDE, 0x8C6D, 0xBFDF, 0x8C93, 0xBFE0, 0x8CF4, 0xBFE1, 0x8E44, + 0xBFE2, 0x8E31, 0xBFE3, 0x8E34, 0xBFE4, 0x8E42, 0xBFE5, 0x8E39, 0xBFE6, 0x8E35, 0xBFE7, 0x8F3B, 0xBFE8, 0x8F2F, 0xBFE9, 0x8F38, + 0xBFEA, 0x8F33, 0xBFEB, 0x8FA8, 0xBFEC, 0x8FA6, 0xBFED, 0x9075, 0xBFEE, 0x9074, 0xBFEF, 0x9078, 0xBFF0, 0x9072, 0xBFF1, 0x907C, + 0xBFF2, 0x907A, 0xBFF3, 0x9134, 0xBFF4, 0x9192, 0xBFF5, 0x9320, 0xBFF6, 0x9336, 0xBFF7, 0x92F8, 0xBFF8, 0x9333, 0xBFF9, 0x932F, + 0xBFFA, 0x9322, 0xBFFB, 0x92FC, 0xBFFC, 0x932B, 0xBFFD, 0x9304, 0xBFFE, 0x931A, 0xC040, 0x9310, 0xC041, 0x9326, 0xC042, 0x9321, + 0xC043, 0x9315, 0xC044, 0x932E, 0xC045, 0x9319, 0xC046, 0x95BB, 0xC047, 0x96A7, 0xC048, 0x96A8, 0xC049, 0x96AA, 0xC04A, 0x96D5, + 0xC04B, 0x970E, 0xC04C, 0x9711, 0xC04D, 0x9716, 0xC04E, 0x970D, 0xC04F, 0x9713, 0xC050, 0x970F, 0xC051, 0x975B, 0xC052, 0x975C, + 0xC053, 0x9766, 0xC054, 0x9798, 0xC055, 0x9830, 0xC056, 0x9838, 0xC057, 0x983B, 0xC058, 0x9837, 0xC059, 0x982D, 0xC05A, 0x9839, + 0xC05B, 0x9824, 0xC05C, 0x9910, 0xC05D, 0x9928, 0xC05E, 0x991E, 0xC05F, 0x991B, 0xC060, 0x9921, 0xC061, 0x991A, 0xC062, 0x99ED, + 0xC063, 0x99E2, 0xC064, 0x99F1, 0xC065, 0x9AB8, 0xC066, 0x9ABC, 0xC067, 0x9AFB, 0xC068, 0x9AED, 0xC069, 0x9B28, 0xC06A, 0x9B91, + 0xC06B, 0x9D15, 0xC06C, 0x9D23, 0xC06D, 0x9D26, 0xC06E, 0x9D28, 0xC06F, 0x9D12, 0xC070, 0x9D1B, 0xC071, 0x9ED8, 0xC072, 0x9ED4, + 0xC073, 0x9F8D, 0xC074, 0x9F9C, 0xC075, 0x512A, 0xC076, 0x511F, 0xC077, 0x5121, 0xC078, 0x5132, 0xC079, 0x52F5, 0xC07A, 0x568E, + 0xC07B, 0x5680, 0xC07C, 0x5690, 0xC07D, 0x5685, 0xC07E, 0x5687, 0xC0A1, 0x568F, 0xC0A2, 0x58D5, 0xC0A3, 0x58D3, 0xC0A4, 0x58D1, + 0xC0A5, 0x58CE, 0xC0A6, 0x5B30, 0xC0A7, 0x5B2A, 0xC0A8, 0x5B24, 0xC0A9, 0x5B7A, 0xC0AA, 0x5C37, 0xC0AB, 0x5C68, 0xC0AC, 0x5DBC, + 0xC0AD, 0x5DBA, 0xC0AE, 0x5DBD, 0xC0AF, 0x5DB8, 0xC0B0, 0x5E6B, 0xC0B1, 0x5F4C, 0xC0B2, 0x5FBD, 0xC0B3, 0x61C9, 0xC0B4, 0x61C2, + 0xC0B5, 0x61C7, 0xC0B6, 0x61E6, 0xC0B7, 0x61CB, 0xC0B8, 0x6232, 0xC0B9, 0x6234, 0xC0BA, 0x64CE, 0xC0BB, 0x64CA, 0xC0BC, 0x64D8, + 0xC0BD, 0x64E0, 0xC0BE, 0x64F0, 0xC0BF, 0x64E6, 0xC0C0, 0x64EC, 0xC0C1, 0x64F1, 0xC0C2, 0x64E2, 0xC0C3, 0x64ED, 0xC0C4, 0x6582, + 0xC0C5, 0x6583, 0xC0C6, 0x66D9, 0xC0C7, 0x66D6, 0xC0C8, 0x6A80, 0xC0C9, 0x6A94, 0xC0CA, 0x6A84, 0xC0CB, 0x6AA2, 0xC0CC, 0x6A9C, + 0xC0CD, 0x6ADB, 0xC0CE, 0x6AA3, 0xC0CF, 0x6A7E, 0xC0D0, 0x6A97, 0xC0D1, 0x6A90, 0xC0D2, 0x6AA0, 0xC0D3, 0x6B5C, 0xC0D4, 0x6BAE, + 0xC0D5, 0x6BDA, 0xC0D6, 0x6C08, 0xC0D7, 0x6FD8, 0xC0D8, 0x6FF1, 0xC0D9, 0x6FDF, 0xC0DA, 0x6FE0, 0xC0DB, 0x6FDB, 0xC0DC, 0x6FE4, + 0xC0DD, 0x6FEB, 0xC0DE, 0x6FEF, 0xC0DF, 0x6F80, 0xC0E0, 0x6FEC, 0xC0E1, 0x6FE1, 0xC0E2, 0x6FE9, 0xC0E3, 0x6FD5, 0xC0E4, 0x6FEE, + 0xC0E5, 0x6FF0, 0xC0E6, 0x71E7, 0xC0E7, 0x71DF, 0xC0E8, 0x71EE, 0xC0E9, 0x71E6, 0xC0EA, 0x71E5, 0xC0EB, 0x71ED, 0xC0EC, 0x71EC, + 0xC0ED, 0x71F4, 0xC0EE, 0x71E0, 0xC0EF, 0x7235, 0xC0F0, 0x7246, 0xC0F1, 0x7370, 0xC0F2, 0x7372, 0xC0F3, 0x74A9, 0xC0F4, 0x74B0, + 0xC0F5, 0x74A6, 0xC0F6, 0x74A8, 0xC0F7, 0x7646, 0xC0F8, 0x7642, 0xC0F9, 0x764C, 0xC0FA, 0x76EA, 0xC0FB, 0x77B3, 0xC0FC, 0x77AA, + 0xC0FD, 0x77B0, 0xC0FE, 0x77AC, 0xC140, 0x77A7, 0xC141, 0x77AD, 0xC142, 0x77EF, 0xC143, 0x78F7, 0xC144, 0x78FA, 0xC145, 0x78F4, + 0xC146, 0x78EF, 0xC147, 0x7901, 0xC148, 0x79A7, 0xC149, 0x79AA, 0xC14A, 0x7A57, 0xC14B, 0x7ABF, 0xC14C, 0x7C07, 0xC14D, 0x7C0D, + 0xC14E, 0x7BFE, 0xC14F, 0x7BF7, 0xC150, 0x7C0C, 0xC151, 0x7BE0, 0xC152, 0x7CE0, 0xC153, 0x7CDC, 0xC154, 0x7CDE, 0xC155, 0x7CE2, + 0xC156, 0x7CDF, 0xC157, 0x7CD9, 0xC158, 0x7CDD, 0xC159, 0x7E2E, 0xC15A, 0x7E3E, 0xC15B, 0x7E46, 0xC15C, 0x7E37, 0xC15D, 0x7E32, + 0xC15E, 0x7E43, 0xC15F, 0x7E2B, 0xC160, 0x7E3D, 0xC161, 0x7E31, 0xC162, 0x7E45, 0xC163, 0x7E41, 0xC164, 0x7E34, 0xC165, 0x7E39, + 0xC166, 0x7E48, 0xC167, 0x7E35, 0xC168, 0x7E3F, 0xC169, 0x7E2F, 0xC16A, 0x7F44, 0xC16B, 0x7FF3, 0xC16C, 0x7FFC, 0xC16D, 0x8071, + 0xC16E, 0x8072, 0xC16F, 0x8070, 0xC170, 0x806F, 0xC171, 0x8073, 0xC172, 0x81C6, 0xC173, 0x81C3, 0xC174, 0x81BA, 0xC175, 0x81C2, + 0xC176, 0x81C0, 0xC177, 0x81BF, 0xC178, 0x81BD, 0xC179, 0x81C9, 0xC17A, 0x81BE, 0xC17B, 0x81E8, 0xC17C, 0x8209, 0xC17D, 0x8271, + 0xC17E, 0x85AA, 0xC1A1, 0x8584, 0xC1A2, 0x857E, 0xC1A3, 0x859C, 0xC1A4, 0x8591, 0xC1A5, 0x8594, 0xC1A6, 0x85AF, 0xC1A7, 0x859B, + 0xC1A8, 0x8587, 0xC1A9, 0x85A8, 0xC1AA, 0x858A, 0xC1AB, 0x8667, 0xC1AC, 0x87C0, 0xC1AD, 0x87D1, 0xC1AE, 0x87B3, 0xC1AF, 0x87D2, + 0xC1B0, 0x87C6, 0xC1B1, 0x87AB, 0xC1B2, 0x87BB, 0xC1B3, 0x87BA, 0xC1B4, 0x87C8, 0xC1B5, 0x87CB, 0xC1B6, 0x893B, 0xC1B7, 0x8936, + 0xC1B8, 0x8944, 0xC1B9, 0x8938, 0xC1BA, 0x893D, 0xC1BB, 0x89AC, 0xC1BC, 0x8B0E, 0xC1BD, 0x8B17, 0xC1BE, 0x8B19, 0xC1BF, 0x8B1B, + 0xC1C0, 0x8B0A, 0xC1C1, 0x8B20, 0xC1C2, 0x8B1D, 0xC1C3, 0x8B04, 0xC1C4, 0x8B10, 0xC1C5, 0x8C41, 0xC1C6, 0x8C3F, 0xC1C7, 0x8C73, + 0xC1C8, 0x8CFA, 0xC1C9, 0x8CFD, 0xC1CA, 0x8CFC, 0xC1CB, 0x8CF8, 0xC1CC, 0x8CFB, 0xC1CD, 0x8DA8, 0xC1CE, 0x8E49, 0xC1CF, 0x8E4B, + 0xC1D0, 0x8E48, 0xC1D1, 0x8E4A, 0xC1D2, 0x8F44, 0xC1D3, 0x8F3E, 0xC1D4, 0x8F42, 0xC1D5, 0x8F45, 0xC1D6, 0x8F3F, 0xC1D7, 0x907F, + 0xC1D8, 0x907D, 0xC1D9, 0x9084, 0xC1DA, 0x9081, 0xC1DB, 0x9082, 0xC1DC, 0x9080, 0xC1DD, 0x9139, 0xC1DE, 0x91A3, 0xC1DF, 0x919E, + 0xC1E0, 0x919C, 0xC1E1, 0x934D, 0xC1E2, 0x9382, 0xC1E3, 0x9328, 0xC1E4, 0x9375, 0xC1E5, 0x934A, 0xC1E6, 0x9365, 0xC1E7, 0x934B, + 0xC1E8, 0x9318, 0xC1E9, 0x937E, 0xC1EA, 0x936C, 0xC1EB, 0x935B, 0xC1EC, 0x9370, 0xC1ED, 0x935A, 0xC1EE, 0x9354, 0xC1EF, 0x95CA, + 0xC1F0, 0x95CB, 0xC1F1, 0x95CC, 0xC1F2, 0x95C8, 0xC1F3, 0x95C6, 0xC1F4, 0x96B1, 0xC1F5, 0x96B8, 0xC1F6, 0x96D6, 0xC1F7, 0x971C, + 0xC1F8, 0x971E, 0xC1F9, 0x97A0, 0xC1FA, 0x97D3, 0xC1FB, 0x9846, 0xC1FC, 0x98B6, 0xC1FD, 0x9935, 0xC1FE, 0x9A01, 0xC240, 0x99FF, + 0xC241, 0x9BAE, 0xC242, 0x9BAB, 0xC243, 0x9BAA, 0xC244, 0x9BAD, 0xC245, 0x9D3B, 0xC246, 0x9D3F, 0xC247, 0x9E8B, 0xC248, 0x9ECF, + 0xC249, 0x9EDE, 0xC24A, 0x9EDC, 0xC24B, 0x9EDD, 0xC24C, 0x9EDB, 0xC24D, 0x9F3E, 0xC24E, 0x9F4B, 0xC24F, 0x53E2, 0xC250, 0x5695, + 0xC251, 0x56AE, 0xC252, 0x58D9, 0xC253, 0x58D8, 0xC254, 0x5B38, 0xC255, 0x5F5D, 0xC256, 0x61E3, 0xC257, 0x6233, 0xC258, 0x64F4, + 0xC259, 0x64F2, 0xC25A, 0x64FE, 0xC25B, 0x6506, 0xC25C, 0x64FA, 0xC25D, 0x64FB, 0xC25E, 0x64F7, 0xC25F, 0x65B7, 0xC260, 0x66DC, + 0xC261, 0x6726, 0xC262, 0x6AB3, 0xC263, 0x6AAC, 0xC264, 0x6AC3, 0xC265, 0x6ABB, 0xC266, 0x6AB8, 0xC267, 0x6AC2, 0xC268, 0x6AAE, + 0xC269, 0x6AAF, 0xC26A, 0x6B5F, 0xC26B, 0x6B78, 0xC26C, 0x6BAF, 0xC26D, 0x7009, 0xC26E, 0x700B, 0xC26F, 0x6FFE, 0xC270, 0x7006, + 0xC271, 0x6FFA, 0xC272, 0x7011, 0xC273, 0x700F, 0xC274, 0x71FB, 0xC275, 0x71FC, 0xC276, 0x71FE, 0xC277, 0x71F8, 0xC278, 0x7377, + 0xC279, 0x7375, 0xC27A, 0x74A7, 0xC27B, 0x74BF, 0xC27C, 0x7515, 0xC27D, 0x7656, 0xC27E, 0x7658, 0xC2A1, 0x7652, 0xC2A2, 0x77BD, + 0xC2A3, 0x77BF, 0xC2A4, 0x77BB, 0xC2A5, 0x77BC, 0xC2A6, 0x790E, 0xC2A7, 0x79AE, 0xC2A8, 0x7A61, 0xC2A9, 0x7A62, 0xC2AA, 0x7A60, + 0xC2AB, 0x7AC4, 0xC2AC, 0x7AC5, 0xC2AD, 0x7C2B, 0xC2AE, 0x7C27, 0xC2AF, 0x7C2A, 0xC2B0, 0x7C1E, 0xC2B1, 0x7C23, 0xC2B2, 0x7C21, + 0xC2B3, 0x7CE7, 0xC2B4, 0x7E54, 0xC2B5, 0x7E55, 0xC2B6, 0x7E5E, 0xC2B7, 0x7E5A, 0xC2B8, 0x7E61, 0xC2B9, 0x7E52, 0xC2BA, 0x7E59, + 0xC2BB, 0x7F48, 0xC2BC, 0x7FF9, 0xC2BD, 0x7FFB, 0xC2BE, 0x8077, 0xC2BF, 0x8076, 0xC2C0, 0x81CD, 0xC2C1, 0x81CF, 0xC2C2, 0x820A, + 0xC2C3, 0x85CF, 0xC2C4, 0x85A9, 0xC2C5, 0x85CD, 0xC2C6, 0x85D0, 0xC2C7, 0x85C9, 0xC2C8, 0x85B0, 0xC2C9, 0x85BA, 0xC2CA, 0x85B9, + 0xC2CB, 0x85A6, 0xC2CC, 0x87EF, 0xC2CD, 0x87EC, 0xC2CE, 0x87F2, 0xC2CF, 0x87E0, 0xC2D0, 0x8986, 0xC2D1, 0x89B2, 0xC2D2, 0x89F4, + 0xC2D3, 0x8B28, 0xC2D4, 0x8B39, 0xC2D5, 0x8B2C, 0xC2D6, 0x8B2B, 0xC2D7, 0x8C50, 0xC2D8, 0x8D05, 0xC2D9, 0x8E59, 0xC2DA, 0x8E63, + 0xC2DB, 0x8E66, 0xC2DC, 0x8E64, 0xC2DD, 0x8E5F, 0xC2DE, 0x8E55, 0xC2DF, 0x8EC0, 0xC2E0, 0x8F49, 0xC2E1, 0x8F4D, 0xC2E2, 0x9087, + 0xC2E3, 0x9083, 0xC2E4, 0x9088, 0xC2E5, 0x91AB, 0xC2E6, 0x91AC, 0xC2E7, 0x91D0, 0xC2E8, 0x9394, 0xC2E9, 0x938A, 0xC2EA, 0x9396, + 0xC2EB, 0x93A2, 0xC2EC, 0x93B3, 0xC2ED, 0x93AE, 0xC2EE, 0x93AC, 0xC2EF, 0x93B0, 0xC2F0, 0x9398, 0xC2F1, 0x939A, 0xC2F2, 0x9397, + 0xC2F3, 0x95D4, 0xC2F4, 0x95D6, 0xC2F5, 0x95D0, 0xC2F6, 0x95D5, 0xC2F7, 0x96E2, 0xC2F8, 0x96DC, 0xC2F9, 0x96D9, 0xC2FA, 0x96DB, + 0xC2FB, 0x96DE, 0xC2FC, 0x9724, 0xC2FD, 0x97A3, 0xC2FE, 0x97A6, 0xC340, 0x97AD, 0xC341, 0x97F9, 0xC342, 0x984D, 0xC343, 0x984F, + 0xC344, 0x984C, 0xC345, 0x984E, 0xC346, 0x9853, 0xC347, 0x98BA, 0xC348, 0x993E, 0xC349, 0x993F, 0xC34A, 0x993D, 0xC34B, 0x992E, + 0xC34C, 0x99A5, 0xC34D, 0x9A0E, 0xC34E, 0x9AC1, 0xC34F, 0x9B03, 0xC350, 0x9B06, 0xC351, 0x9B4F, 0xC352, 0x9B4E, 0xC353, 0x9B4D, + 0xC354, 0x9BCA, 0xC355, 0x9BC9, 0xC356, 0x9BFD, 0xC357, 0x9BC8, 0xC358, 0x9BC0, 0xC359, 0x9D51, 0xC35A, 0x9D5D, 0xC35B, 0x9D60, + 0xC35C, 0x9EE0, 0xC35D, 0x9F15, 0xC35E, 0x9F2C, 0xC35F, 0x5133, 0xC360, 0x56A5, 0xC361, 0x58DE, 0xC362, 0x58DF, 0xC363, 0x58E2, + 0xC364, 0x5BF5, 0xC365, 0x9F90, 0xC366, 0x5EEC, 0xC367, 0x61F2, 0xC368, 0x61F7, 0xC369, 0x61F6, 0xC36A, 0x61F5, 0xC36B, 0x6500, + 0xC36C, 0x650F, 0xC36D, 0x66E0, 0xC36E, 0x66DD, 0xC36F, 0x6AE5, 0xC370, 0x6ADD, 0xC371, 0x6ADA, 0xC372, 0x6AD3, 0xC373, 0x701B, + 0xC374, 0x701F, 0xC375, 0x7028, 0xC376, 0x701A, 0xC377, 0x701D, 0xC378, 0x7015, 0xC379, 0x7018, 0xC37A, 0x7206, 0xC37B, 0x720D, + 0xC37C, 0x7258, 0xC37D, 0x72A2, 0xC37E, 0x7378, 0xC3A1, 0x737A, 0xC3A2, 0x74BD, 0xC3A3, 0x74CA, 0xC3A4, 0x74E3, 0xC3A5, 0x7587, + 0xC3A6, 0x7586, 0xC3A7, 0x765F, 0xC3A8, 0x7661, 0xC3A9, 0x77C7, 0xC3AA, 0x7919, 0xC3AB, 0x79B1, 0xC3AC, 0x7A6B, 0xC3AD, 0x7A69, + 0xC3AE, 0x7C3E, 0xC3AF, 0x7C3F, 0xC3B0, 0x7C38, 0xC3B1, 0x7C3D, 0xC3B2, 0x7C37, 0xC3B3, 0x7C40, 0xC3B4, 0x7E6B, 0xC3B5, 0x7E6D, + 0xC3B6, 0x7E79, 0xC3B7, 0x7E69, 0xC3B8, 0x7E6A, 0xC3B9, 0x7F85, 0xC3BA, 0x7E73, 0xC3BB, 0x7FB6, 0xC3BC, 0x7FB9, 0xC3BD, 0x7FB8, + 0xC3BE, 0x81D8, 0xC3BF, 0x85E9, 0xC3C0, 0x85DD, 0xC3C1, 0x85EA, 0xC3C2, 0x85D5, 0xC3C3, 0x85E4, 0xC3C4, 0x85E5, 0xC3C5, 0x85F7, + 0xC3C6, 0x87FB, 0xC3C7, 0x8805, 0xC3C8, 0x880D, 0xC3C9, 0x87F9, 0xC3CA, 0x87FE, 0xC3CB, 0x8960, 0xC3CC, 0x895F, 0xC3CD, 0x8956, + 0xC3CE, 0x895E, 0xC3CF, 0x8B41, 0xC3D0, 0x8B5C, 0xC3D1, 0x8B58, 0xC3D2, 0x8B49, 0xC3D3, 0x8B5A, 0xC3D4, 0x8B4E, 0xC3D5, 0x8B4F, + 0xC3D6, 0x8B46, 0xC3D7, 0x8B59, 0xC3D8, 0x8D08, 0xC3D9, 0x8D0A, 0xC3DA, 0x8E7C, 0xC3DB, 0x8E72, 0xC3DC, 0x8E87, 0xC3DD, 0x8E76, + 0xC3DE, 0x8E6C, 0xC3DF, 0x8E7A, 0xC3E0, 0x8E74, 0xC3E1, 0x8F54, 0xC3E2, 0x8F4E, 0xC3E3, 0x8FAD, 0xC3E4, 0x908A, 0xC3E5, 0x908B, + 0xC3E6, 0x91B1, 0xC3E7, 0x91AE, 0xC3E8, 0x93E1, 0xC3E9, 0x93D1, 0xC3EA, 0x93DF, 0xC3EB, 0x93C3, 0xC3EC, 0x93C8, 0xC3ED, 0x93DC, + 0xC3EE, 0x93DD, 0xC3EF, 0x93D6, 0xC3F0, 0x93E2, 0xC3F1, 0x93CD, 0xC3F2, 0x93D8, 0xC3F3, 0x93E4, 0xC3F4, 0x93D7, 0xC3F5, 0x93E8, + 0xC3F6, 0x95DC, 0xC3F7, 0x96B4, 0xC3F8, 0x96E3, 0xC3F9, 0x972A, 0xC3FA, 0x9727, 0xC3FB, 0x9761, 0xC3FC, 0x97DC, 0xC3FD, 0x97FB, + 0xC3FE, 0x985E, 0xC440, 0x9858, 0xC441, 0x985B, 0xC442, 0x98BC, 0xC443, 0x9945, 0xC444, 0x9949, 0xC445, 0x9A16, 0xC446, 0x9A19, + 0xC447, 0x9B0D, 0xC448, 0x9BE8, 0xC449, 0x9BE7, 0xC44A, 0x9BD6, 0xC44B, 0x9BDB, 0xC44C, 0x9D89, 0xC44D, 0x9D61, 0xC44E, 0x9D72, + 0xC44F, 0x9D6A, 0xC450, 0x9D6C, 0xC451, 0x9E92, 0xC452, 0x9E97, 0xC453, 0x9E93, 0xC454, 0x9EB4, 0xC455, 0x52F8, 0xC456, 0x56A8, + 0xC457, 0x56B7, 0xC458, 0x56B6, 0xC459, 0x56B4, 0xC45A, 0x56BC, 0xC45B, 0x58E4, 0xC45C, 0x5B40, 0xC45D, 0x5B43, 0xC45E, 0x5B7D, + 0xC45F, 0x5BF6, 0xC460, 0x5DC9, 0xC461, 0x61F8, 0xC462, 0x61FA, 0xC463, 0x6518, 0xC464, 0x6514, 0xC465, 0x6519, 0xC466, 0x66E6, + 0xC467, 0x6727, 0xC468, 0x6AEC, 0xC469, 0x703E, 0xC46A, 0x7030, 0xC46B, 0x7032, 0xC46C, 0x7210, 0xC46D, 0x737B, 0xC46E, 0x74CF, + 0xC46F, 0x7662, 0xC470, 0x7665, 0xC471, 0x7926, 0xC472, 0x792A, 0xC473, 0x792C, 0xC474, 0x792B, 0xC475, 0x7AC7, 0xC476, 0x7AF6, + 0xC477, 0x7C4C, 0xC478, 0x7C43, 0xC479, 0x7C4D, 0xC47A, 0x7CEF, 0xC47B, 0x7CF0, 0xC47C, 0x8FAE, 0xC47D, 0x7E7D, 0xC47E, 0x7E7C, + 0xC4A1, 0x7E82, 0xC4A2, 0x7F4C, 0xC4A3, 0x8000, 0xC4A4, 0x81DA, 0xC4A5, 0x8266, 0xC4A6, 0x85FB, 0xC4A7, 0x85F9, 0xC4A8, 0x8611, + 0xC4A9, 0x85FA, 0xC4AA, 0x8606, 0xC4AB, 0x860B, 0xC4AC, 0x8607, 0xC4AD, 0x860A, 0xC4AE, 0x8814, 0xC4AF, 0x8815, 0xC4B0, 0x8964, + 0xC4B1, 0x89BA, 0xC4B2, 0x89F8, 0xC4B3, 0x8B70, 0xC4B4, 0x8B6C, 0xC4B5, 0x8B66, 0xC4B6, 0x8B6F, 0xC4B7, 0x8B5F, 0xC4B8, 0x8B6B, + 0xC4B9, 0x8D0F, 0xC4BA, 0x8D0D, 0xC4BB, 0x8E89, 0xC4BC, 0x8E81, 0xC4BD, 0x8E85, 0xC4BE, 0x8E82, 0xC4BF, 0x91B4, 0xC4C0, 0x91CB, + 0xC4C1, 0x9418, 0xC4C2, 0x9403, 0xC4C3, 0x93FD, 0xC4C4, 0x95E1, 0xC4C5, 0x9730, 0xC4C6, 0x98C4, 0xC4C7, 0x9952, 0xC4C8, 0x9951, + 0xC4C9, 0x99A8, 0xC4CA, 0x9A2B, 0xC4CB, 0x9A30, 0xC4CC, 0x9A37, 0xC4CD, 0x9A35, 0xC4CE, 0x9C13, 0xC4CF, 0x9C0D, 0xC4D0, 0x9E79, + 0xC4D1, 0x9EB5, 0xC4D2, 0x9EE8, 0xC4D3, 0x9F2F, 0xC4D4, 0x9F5F, 0xC4D5, 0x9F63, 0xC4D6, 0x9F61, 0xC4D7, 0x5137, 0xC4D8, 0x5138, + 0xC4D9, 0x56C1, 0xC4DA, 0x56C0, 0xC4DB, 0x56C2, 0xC4DC, 0x5914, 0xC4DD, 0x5C6C, 0xC4DE, 0x5DCD, 0xC4DF, 0x61FC, 0xC4E0, 0x61FE, + 0xC4E1, 0x651D, 0xC4E2, 0x651C, 0xC4E3, 0x6595, 0xC4E4, 0x66E9, 0xC4E5, 0x6AFB, 0xC4E6, 0x6B04, 0xC4E7, 0x6AFA, 0xC4E8, 0x6BB2, + 0xC4E9, 0x704C, 0xC4EA, 0x721B, 0xC4EB, 0x72A7, 0xC4EC, 0x74D6, 0xC4ED, 0x74D4, 0xC4EE, 0x7669, 0xC4EF, 0x77D3, 0xC4F0, 0x7C50, + 0xC4F1, 0x7E8F, 0xC4F2, 0x7E8C, 0xC4F3, 0x7FBC, 0xC4F4, 0x8617, 0xC4F5, 0x862D, 0xC4F6, 0x861A, 0xC4F7, 0x8823, 0xC4F8, 0x8822, + 0xC4F9, 0x8821, 0xC4FA, 0x881F, 0xC4FB, 0x896A, 0xC4FC, 0x896C, 0xC4FD, 0x89BD, 0xC4FE, 0x8B74, 0xC540, 0x8B77, 0xC541, 0x8B7D, + 0xC542, 0x8D13, 0xC543, 0x8E8A, 0xC544, 0x8E8D, 0xC545, 0x8E8B, 0xC546, 0x8F5F, 0xC547, 0x8FAF, 0xC548, 0x91BA, 0xC549, 0x942E, + 0xC54A, 0x9433, 0xC54B, 0x9435, 0xC54C, 0x943A, 0xC54D, 0x9438, 0xC54E, 0x9432, 0xC54F, 0x942B, 0xC550, 0x95E2, 0xC551, 0x9738, + 0xC552, 0x9739, 0xC553, 0x9732, 0xC554, 0x97FF, 0xC555, 0x9867, 0xC556, 0x9865, 0xC557, 0x9957, 0xC558, 0x9A45, 0xC559, 0x9A43, + 0xC55A, 0x9A40, 0xC55B, 0x9A3E, 0xC55C, 0x9ACF, 0xC55D, 0x9B54, 0xC55E, 0x9B51, 0xC55F, 0x9C2D, 0xC560, 0x9C25, 0xC561, 0x9DAF, + 0xC562, 0x9DB4, 0xC563, 0x9DC2, 0xC564, 0x9DB8, 0xC565, 0x9E9D, 0xC566, 0x9EEF, 0xC567, 0x9F19, 0xC568, 0x9F5C, 0xC569, 0x9F66, + 0xC56A, 0x9F67, 0xC56B, 0x513C, 0xC56C, 0x513B, 0xC56D, 0x56C8, 0xC56E, 0x56CA, 0xC56F, 0x56C9, 0xC570, 0x5B7F, 0xC571, 0x5DD4, + 0xC572, 0x5DD2, 0xC573, 0x5F4E, 0xC574, 0x61FF, 0xC575, 0x6524, 0xC576, 0x6B0A, 0xC577, 0x6B61, 0xC578, 0x7051, 0xC579, 0x7058, + 0xC57A, 0x7380, 0xC57B, 0x74E4, 0xC57C, 0x758A, 0xC57D, 0x766E, 0xC57E, 0x766C, 0xC5A1, 0x79B3, 0xC5A2, 0x7C60, 0xC5A3, 0x7C5F, + 0xC5A4, 0x807E, 0xC5A5, 0x807D, 0xC5A6, 0x81DF, 0xC5A7, 0x8972, 0xC5A8, 0x896F, 0xC5A9, 0x89FC, 0xC5AA, 0x8B80, 0xC5AB, 0x8D16, + 0xC5AC, 0x8D17, 0xC5AD, 0x8E91, 0xC5AE, 0x8E93, 0xC5AF, 0x8F61, 0xC5B0, 0x9148, 0xC5B1, 0x9444, 0xC5B2, 0x9451, 0xC5B3, 0x9452, + 0xC5B4, 0x973D, 0xC5B5, 0x973E, 0xC5B6, 0x97C3, 0xC5B7, 0x97C1, 0xC5B8, 0x986B, 0xC5B9, 0x9955, 0xC5BA, 0x9A55, 0xC5BB, 0x9A4D, + 0xC5BC, 0x9AD2, 0xC5BD, 0x9B1A, 0xC5BE, 0x9C49, 0xC5BF, 0x9C31, 0xC5C0, 0x9C3E, 0xC5C1, 0x9C3B, 0xC5C2, 0x9DD3, 0xC5C3, 0x9DD7, + 0xC5C4, 0x9F34, 0xC5C5, 0x9F6C, 0xC5C6, 0x9F6A, 0xC5C7, 0x9F94, 0xC5C8, 0x56CC, 0xC5C9, 0x5DD6, 0xC5CA, 0x6200, 0xC5CB, 0x6523, + 0xC5CC, 0x652B, 0xC5CD, 0x652A, 0xC5CE, 0x66EC, 0xC5CF, 0x6B10, 0xC5D0, 0x74DA, 0xC5D1, 0x7ACA, 0xC5D2, 0x7C64, 0xC5D3, 0x7C63, + 0xC5D4, 0x7C65, 0xC5D5, 0x7E93, 0xC5D6, 0x7E96, 0xC5D7, 0x7E94, 0xC5D8, 0x81E2, 0xC5D9, 0x8638, 0xC5DA, 0x863F, 0xC5DB, 0x8831, + 0xC5DC, 0x8B8A, 0xC5DD, 0x9090, 0xC5DE, 0x908F, 0xC5DF, 0x9463, 0xC5E0, 0x9460, 0xC5E1, 0x9464, 0xC5E2, 0x9768, 0xC5E3, 0x986F, + 0xC5E4, 0x995C, 0xC5E5, 0x9A5A, 0xC5E6, 0x9A5B, 0xC5E7, 0x9A57, 0xC5E8, 0x9AD3, 0xC5E9, 0x9AD4, 0xC5EA, 0x9AD1, 0xC5EB, 0x9C54, + 0xC5EC, 0x9C57, 0xC5ED, 0x9C56, 0xC5EE, 0x9DE5, 0xC5EF, 0x9E9F, 0xC5F0, 0x9EF4, 0xC5F1, 0x56D1, 0xC5F2, 0x58E9, 0xC5F3, 0x652C, + 0xC5F4, 0x705E, 0xC5F5, 0x7671, 0xC5F6, 0x7672, 0xC5F7, 0x77D7, 0xC5F8, 0x7F50, 0xC5F9, 0x7F88, 0xC5FA, 0x8836, 0xC5FB, 0x8839, + 0xC5FC, 0x8862, 0xC5FD, 0x8B93, 0xC5FE, 0x8B92, 0xC640, 0x8B96, 0xC641, 0x8277, 0xC642, 0x8D1B, 0xC643, 0x91C0, 0xC644, 0x946A, + 0xC645, 0x9742, 0xC646, 0x9748, 0xC647, 0x9744, 0xC648, 0x97C6, 0xC649, 0x9870, 0xC64A, 0x9A5F, 0xC64B, 0x9B22, 0xC64C, 0x9B58, + 0xC64D, 0x9C5F, 0xC64E, 0x9DF9, 0xC64F, 0x9DFA, 0xC650, 0x9E7C, 0xC651, 0x9E7D, 0xC652, 0x9F07, 0xC653, 0x9F77, 0xC654, 0x9F72, + 0xC655, 0x5EF3, 0xC656, 0x6B16, 0xC657, 0x7063, 0xC658, 0x7C6C, 0xC659, 0x7C6E, 0xC65A, 0x883B, 0xC65B, 0x89C0, 0xC65C, 0x8EA1, + 0xC65D, 0x91C1, 0xC65E, 0x9472, 0xC65F, 0x9470, 0xC660, 0x9871, 0xC661, 0x995E, 0xC662, 0x9AD6, 0xC663, 0x9B23, 0xC664, 0x9ECC, + 0xC665, 0x7064, 0xC666, 0x77DA, 0xC667, 0x8B9A, 0xC668, 0x9477, 0xC669, 0x97C9, 0xC66A, 0x9A62, 0xC66B, 0x9A65, 0xC66C, 0x7E9C, + 0xC66D, 0x8B9C, 0xC66E, 0x8EAA, 0xC66F, 0x91C5, 0xC670, 0x947D, 0xC671, 0x947E, 0xC672, 0x947C, 0xC673, 0x9C77, 0xC674, 0x9C78, + 0xC675, 0x9EF7, 0xC676, 0x8C54, 0xC677, 0x947F, 0xC678, 0x9E1A, 0xC679, 0x7228, 0xC67A, 0x9A6A, 0xC67B, 0x9B31, 0xC67C, 0x9E1B, + 0xC67D, 0x9E1E, 0xC67E, 0x7C72, 0xC940, 0x4E42, 0xC941, 0x4E5C, 0xC942, 0x51F5, 0xC943, 0x531A, 0xC944, 0x5382, 0xC945, 0x4E07, + 0xC946, 0x4E0C, 0xC947, 0x4E47, 0xC948, 0x4E8D, 0xC949, 0x56D7, 0xC94A, 0xFA0C, 0xC94B, 0x5C6E, 0xC94C, 0x5F73, 0xC94D, 0x4E0F, + 0xC94E, 0x5187, 0xC94F, 0x4E0E, 0xC950, 0x4E2E, 0xC951, 0x4E93, 0xC952, 0x4EC2, 0xC953, 0x4EC9, 0xC954, 0x4EC8, 0xC955, 0x5198, + 0xC956, 0x52FC, 0xC957, 0x536C, 0xC958, 0x53B9, 0xC959, 0x5720, 0xC95A, 0x5903, 0xC95B, 0x592C, 0xC95C, 0x5C10, 0xC95D, 0x5DFF, + 0xC95E, 0x65E1, 0xC95F, 0x6BB3, 0xC960, 0x6BCC, 0xC961, 0x6C14, 0xC962, 0x723F, 0xC963, 0x4E31, 0xC964, 0x4E3C, 0xC965, 0x4EE8, + 0xC966, 0x4EDC, 0xC967, 0x4EE9, 0xC968, 0x4EE1, 0xC969, 0x4EDD, 0xC96A, 0x4EDA, 0xC96B, 0x520C, 0xC96C, 0x531C, 0xC96D, 0x534C, + 0xC96E, 0x5722, 0xC96F, 0x5723, 0xC970, 0x5917, 0xC971, 0x592F, 0xC972, 0x5B81, 0xC973, 0x5B84, 0xC974, 0x5C12, 0xC975, 0x5C3B, + 0xC976, 0x5C74, 0xC977, 0x5C73, 0xC978, 0x5E04, 0xC979, 0x5E80, 0xC97A, 0x5E82, 0xC97B, 0x5FC9, 0xC97C, 0x6209, 0xC97D, 0x6250, + 0xC97E, 0x6C15, 0xC9A1, 0x6C36, 0xC9A2, 0x6C43, 0xC9A3, 0x6C3F, 0xC9A4, 0x6C3B, 0xC9A5, 0x72AE, 0xC9A6, 0x72B0, 0xC9A7, 0x738A, + 0xC9A8, 0x79B8, 0xC9A9, 0x808A, 0xC9AA, 0x961E, 0xC9AB, 0x4F0E, 0xC9AC, 0x4F18, 0xC9AD, 0x4F2C, 0xC9AE, 0x4EF5, 0xC9AF, 0x4F14, + 0xC9B0, 0x4EF1, 0xC9B1, 0x4F00, 0xC9B2, 0x4EF7, 0xC9B3, 0x4F08, 0xC9B4, 0x4F1D, 0xC9B5, 0x4F02, 0xC9B6, 0x4F05, 0xC9B7, 0x4F22, + 0xC9B8, 0x4F13, 0xC9B9, 0x4F04, 0xC9BA, 0x4EF4, 0xC9BB, 0x4F12, 0xC9BC, 0x51B1, 0xC9BD, 0x5213, 0xC9BE, 0x5209, 0xC9BF, 0x5210, + 0xC9C0, 0x52A6, 0xC9C1, 0x5322, 0xC9C2, 0x531F, 0xC9C3, 0x534D, 0xC9C4, 0x538A, 0xC9C5, 0x5407, 0xC9C6, 0x56E1, 0xC9C7, 0x56DF, + 0xC9C8, 0x572E, 0xC9C9, 0x572A, 0xC9CA, 0x5734, 0xC9CB, 0x593C, 0xC9CC, 0x5980, 0xC9CD, 0x597C, 0xC9CE, 0x5985, 0xC9CF, 0x597B, + 0xC9D0, 0x597E, 0xC9D1, 0x5977, 0xC9D2, 0x597F, 0xC9D3, 0x5B56, 0xC9D4, 0x5C15, 0xC9D5, 0x5C25, 0xC9D6, 0x5C7C, 0xC9D7, 0x5C7A, + 0xC9D8, 0x5C7B, 0xC9D9, 0x5C7E, 0xC9DA, 0x5DDF, 0xC9DB, 0x5E75, 0xC9DC, 0x5E84, 0xC9DD, 0x5F02, 0xC9DE, 0x5F1A, 0xC9DF, 0x5F74, + 0xC9E0, 0x5FD5, 0xC9E1, 0x5FD4, 0xC9E2, 0x5FCF, 0xC9E3, 0x625C, 0xC9E4, 0x625E, 0xC9E5, 0x6264, 0xC9E6, 0x6261, 0xC9E7, 0x6266, + 0xC9E8, 0x6262, 0xC9E9, 0x6259, 0xC9EA, 0x6260, 0xC9EB, 0x625A, 0xC9EC, 0x6265, 0xC9ED, 0x65EF, 0xC9EE, 0x65EE, 0xC9EF, 0x673E, + 0xC9F0, 0x6739, 0xC9F1, 0x6738, 0xC9F2, 0x673B, 0xC9F3, 0x673A, 0xC9F4, 0x673F, 0xC9F5, 0x673C, 0xC9F6, 0x6733, 0xC9F7, 0x6C18, + 0xC9F8, 0x6C46, 0xC9F9, 0x6C52, 0xC9FA, 0x6C5C, 0xC9FB, 0x6C4F, 0xC9FC, 0x6C4A, 0xC9FD, 0x6C54, 0xC9FE, 0x6C4B, 0xCA40, 0x6C4C, + 0xCA41, 0x7071, 0xCA42, 0x725E, 0xCA43, 0x72B4, 0xCA44, 0x72B5, 0xCA45, 0x738E, 0xCA46, 0x752A, 0xCA47, 0x767F, 0xCA48, 0x7A75, + 0xCA49, 0x7F51, 0xCA4A, 0x8278, 0xCA4B, 0x827C, 0xCA4C, 0x8280, 0xCA4D, 0x827D, 0xCA4E, 0x827F, 0xCA4F, 0x864D, 0xCA50, 0x897E, + 0xCA51, 0x9099, 0xCA52, 0x9097, 0xCA53, 0x9098, 0xCA54, 0x909B, 0xCA55, 0x9094, 0xCA56, 0x9622, 0xCA57, 0x9624, 0xCA58, 0x9620, + 0xCA59, 0x9623, 0xCA5A, 0x4F56, 0xCA5B, 0x4F3B, 0xCA5C, 0x4F62, 0xCA5D, 0x4F49, 0xCA5E, 0x4F53, 0xCA5F, 0x4F64, 0xCA60, 0x4F3E, + 0xCA61, 0x4F67, 0xCA62, 0x4F52, 0xCA63, 0x4F5F, 0xCA64, 0x4F41, 0xCA65, 0x4F58, 0xCA66, 0x4F2D, 0xCA67, 0x4F33, 0xCA68, 0x4F3F, + 0xCA69, 0x4F61, 0xCA6A, 0x518F, 0xCA6B, 0x51B9, 0xCA6C, 0x521C, 0xCA6D, 0x521E, 0xCA6E, 0x5221, 0xCA6F, 0x52AD, 0xCA70, 0x52AE, + 0xCA71, 0x5309, 0xCA72, 0x5363, 0xCA73, 0x5372, 0xCA74, 0x538E, 0xCA75, 0x538F, 0xCA76, 0x5430, 0xCA77, 0x5437, 0xCA78, 0x542A, + 0xCA79, 0x5454, 0xCA7A, 0x5445, 0xCA7B, 0x5419, 0xCA7C, 0x541C, 0xCA7D, 0x5425, 0xCA7E, 0x5418, 0xCAA1, 0x543D, 0xCAA2, 0x544F, + 0xCAA3, 0x5441, 0xCAA4, 0x5428, 0xCAA5, 0x5424, 0xCAA6, 0x5447, 0xCAA7, 0x56EE, 0xCAA8, 0x56E7, 0xCAA9, 0x56E5, 0xCAAA, 0x5741, + 0xCAAB, 0x5745, 0xCAAC, 0x574C, 0xCAAD, 0x5749, 0xCAAE, 0x574B, 0xCAAF, 0x5752, 0xCAB0, 0x5906, 0xCAB1, 0x5940, 0xCAB2, 0x59A6, + 0xCAB3, 0x5998, 0xCAB4, 0x59A0, 0xCAB5, 0x5997, 0xCAB6, 0x598E, 0xCAB7, 0x59A2, 0xCAB8, 0x5990, 0xCAB9, 0x598F, 0xCABA, 0x59A7, + 0xCABB, 0x59A1, 0xCABC, 0x5B8E, 0xCABD, 0x5B92, 0xCABE, 0x5C28, 0xCABF, 0x5C2A, 0xCAC0, 0x5C8D, 0xCAC1, 0x5C8F, 0xCAC2, 0x5C88, + 0xCAC3, 0x5C8B, 0xCAC4, 0x5C89, 0xCAC5, 0x5C92, 0xCAC6, 0x5C8A, 0xCAC7, 0x5C86, 0xCAC8, 0x5C93, 0xCAC9, 0x5C95, 0xCACA, 0x5DE0, + 0xCACB, 0x5E0A, 0xCACC, 0x5E0E, 0xCACD, 0x5E8B, 0xCACE, 0x5E89, 0xCACF, 0x5E8C, 0xCAD0, 0x5E88, 0xCAD1, 0x5E8D, 0xCAD2, 0x5F05, + 0xCAD3, 0x5F1D, 0xCAD4, 0x5F78, 0xCAD5, 0x5F76, 0xCAD6, 0x5FD2, 0xCAD7, 0x5FD1, 0xCAD8, 0x5FD0, 0xCAD9, 0x5FED, 0xCADA, 0x5FE8, + 0xCADB, 0x5FEE, 0xCADC, 0x5FF3, 0xCADD, 0x5FE1, 0xCADE, 0x5FE4, 0xCADF, 0x5FE3, 0xCAE0, 0x5FFA, 0xCAE1, 0x5FEF, 0xCAE2, 0x5FF7, + 0xCAE3, 0x5FFB, 0xCAE4, 0x6000, 0xCAE5, 0x5FF4, 0xCAE6, 0x623A, 0xCAE7, 0x6283, 0xCAE8, 0x628C, 0xCAE9, 0x628E, 0xCAEA, 0x628F, + 0xCAEB, 0x6294, 0xCAEC, 0x6287, 0xCAED, 0x6271, 0xCAEE, 0x627B, 0xCAEF, 0x627A, 0xCAF0, 0x6270, 0xCAF1, 0x6281, 0xCAF2, 0x6288, + 0xCAF3, 0x6277, 0xCAF4, 0x627D, 0xCAF5, 0x6272, 0xCAF6, 0x6274, 0xCAF7, 0x6537, 0xCAF8, 0x65F0, 0xCAF9, 0x65F4, 0xCAFA, 0x65F3, + 0xCAFB, 0x65F2, 0xCAFC, 0x65F5, 0xCAFD, 0x6745, 0xCAFE, 0x6747, 0xCB40, 0x6759, 0xCB41, 0x6755, 0xCB42, 0x674C, 0xCB43, 0x6748, + 0xCB44, 0x675D, 0xCB45, 0x674D, 0xCB46, 0x675A, 0xCB47, 0x674B, 0xCB48, 0x6BD0, 0xCB49, 0x6C19, 0xCB4A, 0x6C1A, 0xCB4B, 0x6C78, + 0xCB4C, 0x6C67, 0xCB4D, 0x6C6B, 0xCB4E, 0x6C84, 0xCB4F, 0x6C8B, 0xCB50, 0x6C8F, 0xCB51, 0x6C71, 0xCB52, 0x6C6F, 0xCB53, 0x6C69, + 0xCB54, 0x6C9A, 0xCB55, 0x6C6D, 0xCB56, 0x6C87, 0xCB57, 0x6C95, 0xCB58, 0x6C9C, 0xCB59, 0x6C66, 0xCB5A, 0x6C73, 0xCB5B, 0x6C65, + 0xCB5C, 0x6C7B, 0xCB5D, 0x6C8E, 0xCB5E, 0x7074, 0xCB5F, 0x707A, 0xCB60, 0x7263, 0xCB61, 0x72BF, 0xCB62, 0x72BD, 0xCB63, 0x72C3, + 0xCB64, 0x72C6, 0xCB65, 0x72C1, 0xCB66, 0x72BA, 0xCB67, 0x72C5, 0xCB68, 0x7395, 0xCB69, 0x7397, 0xCB6A, 0x7393, 0xCB6B, 0x7394, + 0xCB6C, 0x7392, 0xCB6D, 0x753A, 0xCB6E, 0x7539, 0xCB6F, 0x7594, 0xCB70, 0x7595, 0xCB71, 0x7681, 0xCB72, 0x793D, 0xCB73, 0x8034, + 0xCB74, 0x8095, 0xCB75, 0x8099, 0xCB76, 0x8090, 0xCB77, 0x8092, 0xCB78, 0x809C, 0xCB79, 0x8290, 0xCB7A, 0x828F, 0xCB7B, 0x8285, + 0xCB7C, 0x828E, 0xCB7D, 0x8291, 0xCB7E, 0x8293, 0xCBA1, 0x828A, 0xCBA2, 0x8283, 0xCBA3, 0x8284, 0xCBA4, 0x8C78, 0xCBA5, 0x8FC9, + 0xCBA6, 0x8FBF, 0xCBA7, 0x909F, 0xCBA8, 0x90A1, 0xCBA9, 0x90A5, 0xCBAA, 0x909E, 0xCBAB, 0x90A7, 0xCBAC, 0x90A0, 0xCBAD, 0x9630, + 0xCBAE, 0x9628, 0xCBAF, 0x962F, 0xCBB0, 0x962D, 0xCBB1, 0x4E33, 0xCBB2, 0x4F98, 0xCBB3, 0x4F7C, 0xCBB4, 0x4F85, 0xCBB5, 0x4F7D, + 0xCBB6, 0x4F80, 0xCBB7, 0x4F87, 0xCBB8, 0x4F76, 0xCBB9, 0x4F74, 0xCBBA, 0x4F89, 0xCBBB, 0x4F84, 0xCBBC, 0x4F77, 0xCBBD, 0x4F4C, + 0xCBBE, 0x4F97, 0xCBBF, 0x4F6A, 0xCBC0, 0x4F9A, 0xCBC1, 0x4F79, 0xCBC2, 0x4F81, 0xCBC3, 0x4F78, 0xCBC4, 0x4F90, 0xCBC5, 0x4F9C, + 0xCBC6, 0x4F94, 0xCBC7, 0x4F9E, 0xCBC8, 0x4F92, 0xCBC9, 0x4F82, 0xCBCA, 0x4F95, 0xCBCB, 0x4F6B, 0xCBCC, 0x4F6E, 0xCBCD, 0x519E, + 0xCBCE, 0x51BC, 0xCBCF, 0x51BE, 0xCBD0, 0x5235, 0xCBD1, 0x5232, 0xCBD2, 0x5233, 0xCBD3, 0x5246, 0xCBD4, 0x5231, 0xCBD5, 0x52BC, + 0xCBD6, 0x530A, 0xCBD7, 0x530B, 0xCBD8, 0x533C, 0xCBD9, 0x5392, 0xCBDA, 0x5394, 0xCBDB, 0x5487, 0xCBDC, 0x547F, 0xCBDD, 0x5481, + 0xCBDE, 0x5491, 0xCBDF, 0x5482, 0xCBE0, 0x5488, 0xCBE1, 0x546B, 0xCBE2, 0x547A, 0xCBE3, 0x547E, 0xCBE4, 0x5465, 0xCBE5, 0x546C, + 0xCBE6, 0x5474, 0xCBE7, 0x5466, 0xCBE8, 0x548D, 0xCBE9, 0x546F, 0xCBEA, 0x5461, 0xCBEB, 0x5460, 0xCBEC, 0x5498, 0xCBED, 0x5463, + 0xCBEE, 0x5467, 0xCBEF, 0x5464, 0xCBF0, 0x56F7, 0xCBF1, 0x56F9, 0xCBF2, 0x576F, 0xCBF3, 0x5772, 0xCBF4, 0x576D, 0xCBF5, 0x576B, + 0xCBF6, 0x5771, 0xCBF7, 0x5770, 0xCBF8, 0x5776, 0xCBF9, 0x5780, 0xCBFA, 0x5775, 0xCBFB, 0x577B, 0xCBFC, 0x5773, 0xCBFD, 0x5774, + 0xCBFE, 0x5762, 0xCC40, 0x5768, 0xCC41, 0x577D, 0xCC42, 0x590C, 0xCC43, 0x5945, 0xCC44, 0x59B5, 0xCC45, 0x59BA, 0xCC46, 0x59CF, + 0xCC47, 0x59CE, 0xCC48, 0x59B2, 0xCC49, 0x59CC, 0xCC4A, 0x59C1, 0xCC4B, 0x59B6, 0xCC4C, 0x59BC, 0xCC4D, 0x59C3, 0xCC4E, 0x59D6, + 0xCC4F, 0x59B1, 0xCC50, 0x59BD, 0xCC51, 0x59C0, 0xCC52, 0x59C8, 0xCC53, 0x59B4, 0xCC54, 0x59C7, 0xCC55, 0x5B62, 0xCC56, 0x5B65, + 0xCC57, 0x5B93, 0xCC58, 0x5B95, 0xCC59, 0x5C44, 0xCC5A, 0x5C47, 0xCC5B, 0x5CAE, 0xCC5C, 0x5CA4, 0xCC5D, 0x5CA0, 0xCC5E, 0x5CB5, + 0xCC5F, 0x5CAF, 0xCC60, 0x5CA8, 0xCC61, 0x5CAC, 0xCC62, 0x5C9F, 0xCC63, 0x5CA3, 0xCC64, 0x5CAD, 0xCC65, 0x5CA2, 0xCC66, 0x5CAA, + 0xCC67, 0x5CA7, 0xCC68, 0x5C9D, 0xCC69, 0x5CA5, 0xCC6A, 0x5CB6, 0xCC6B, 0x5CB0, 0xCC6C, 0x5CA6, 0xCC6D, 0x5E17, 0xCC6E, 0x5E14, + 0xCC6F, 0x5E19, 0xCC70, 0x5F28, 0xCC71, 0x5F22, 0xCC72, 0x5F23, 0xCC73, 0x5F24, 0xCC74, 0x5F54, 0xCC75, 0x5F82, 0xCC76, 0x5F7E, + 0xCC77, 0x5F7D, 0xCC78, 0x5FDE, 0xCC79, 0x5FE5, 0xCC7A, 0x602D, 0xCC7B, 0x6026, 0xCC7C, 0x6019, 0xCC7D, 0x6032, 0xCC7E, 0x600B, + 0xCCA1, 0x6034, 0xCCA2, 0x600A, 0xCCA3, 0x6017, 0xCCA4, 0x6033, 0xCCA5, 0x601A, 0xCCA6, 0x601E, 0xCCA7, 0x602C, 0xCCA8, 0x6022, + 0xCCA9, 0x600D, 0xCCAA, 0x6010, 0xCCAB, 0x602E, 0xCCAC, 0x6013, 0xCCAD, 0x6011, 0xCCAE, 0x600C, 0xCCAF, 0x6009, 0xCCB0, 0x601C, + 0xCCB1, 0x6214, 0xCCB2, 0x623D, 0xCCB3, 0x62AD, 0xCCB4, 0x62B4, 0xCCB5, 0x62D1, 0xCCB6, 0x62BE, 0xCCB7, 0x62AA, 0xCCB8, 0x62B6, + 0xCCB9, 0x62CA, 0xCCBA, 0x62AE, 0xCCBB, 0x62B3, 0xCCBC, 0x62AF, 0xCCBD, 0x62BB, 0xCCBE, 0x62A9, 0xCCBF, 0x62B0, 0xCCC0, 0x62B8, + 0xCCC1, 0x653D, 0xCCC2, 0x65A8, 0xCCC3, 0x65BB, 0xCCC4, 0x6609, 0xCCC5, 0x65FC, 0xCCC6, 0x6604, 0xCCC7, 0x6612, 0xCCC8, 0x6608, + 0xCCC9, 0x65FB, 0xCCCA, 0x6603, 0xCCCB, 0x660B, 0xCCCC, 0x660D, 0xCCCD, 0x6605, 0xCCCE, 0x65FD, 0xCCCF, 0x6611, 0xCCD0, 0x6610, + 0xCCD1, 0x66F6, 0xCCD2, 0x670A, 0xCCD3, 0x6785, 0xCCD4, 0x676C, 0xCCD5, 0x678E, 0xCCD6, 0x6792, 0xCCD7, 0x6776, 0xCCD8, 0x677B, + 0xCCD9, 0x6798, 0xCCDA, 0x6786, 0xCCDB, 0x6784, 0xCCDC, 0x6774, 0xCCDD, 0x678D, 0xCCDE, 0x678C, 0xCCDF, 0x677A, 0xCCE0, 0x679F, + 0xCCE1, 0x6791, 0xCCE2, 0x6799, 0xCCE3, 0x6783, 0xCCE4, 0x677D, 0xCCE5, 0x6781, 0xCCE6, 0x6778, 0xCCE7, 0x6779, 0xCCE8, 0x6794, + 0xCCE9, 0x6B25, 0xCCEA, 0x6B80, 0xCCEB, 0x6B7E, 0xCCEC, 0x6BDE, 0xCCED, 0x6C1D, 0xCCEE, 0x6C93, 0xCCEF, 0x6CEC, 0xCCF0, 0x6CEB, + 0xCCF1, 0x6CEE, 0xCCF2, 0x6CD9, 0xCCF3, 0x6CB6, 0xCCF4, 0x6CD4, 0xCCF5, 0x6CAD, 0xCCF6, 0x6CE7, 0xCCF7, 0x6CB7, 0xCCF8, 0x6CD0, + 0xCCF9, 0x6CC2, 0xCCFA, 0x6CBA, 0xCCFB, 0x6CC3, 0xCCFC, 0x6CC6, 0xCCFD, 0x6CED, 0xCCFE, 0x6CF2, 0xCD40, 0x6CD2, 0xCD41, 0x6CDD, + 0xCD42, 0x6CB4, 0xCD43, 0x6C8A, 0xCD44, 0x6C9D, 0xCD45, 0x6C80, 0xCD46, 0x6CDE, 0xCD47, 0x6CC0, 0xCD48, 0x6D30, 0xCD49, 0x6CCD, + 0xCD4A, 0x6CC7, 0xCD4B, 0x6CB0, 0xCD4C, 0x6CF9, 0xCD4D, 0x6CCF, 0xCD4E, 0x6CE9, 0xCD4F, 0x6CD1, 0xCD50, 0x7094, 0xCD51, 0x7098, + 0xCD52, 0x7085, 0xCD53, 0x7093, 0xCD54, 0x7086, 0xCD55, 0x7084, 0xCD56, 0x7091, 0xCD57, 0x7096, 0xCD58, 0x7082, 0xCD59, 0x709A, + 0xCD5A, 0x7083, 0xCD5B, 0x726A, 0xCD5C, 0x72D6, 0xCD5D, 0x72CB, 0xCD5E, 0x72D8, 0xCD5F, 0x72C9, 0xCD60, 0x72DC, 0xCD61, 0x72D2, + 0xCD62, 0x72D4, 0xCD63, 0x72DA, 0xCD64, 0x72CC, 0xCD65, 0x72D1, 0xCD66, 0x73A4, 0xCD67, 0x73A1, 0xCD68, 0x73AD, 0xCD69, 0x73A6, + 0xCD6A, 0x73A2, 0xCD6B, 0x73A0, 0xCD6C, 0x73AC, 0xCD6D, 0x739D, 0xCD6E, 0x74DD, 0xCD6F, 0x74E8, 0xCD70, 0x753F, 0xCD71, 0x7540, + 0xCD72, 0x753E, 0xCD73, 0x758C, 0xCD74, 0x7598, 0xCD75, 0x76AF, 0xCD76, 0x76F3, 0xCD77, 0x76F1, 0xCD78, 0x76F0, 0xCD79, 0x76F5, + 0xCD7A, 0x77F8, 0xCD7B, 0x77FC, 0xCD7C, 0x77F9, 0xCD7D, 0x77FB, 0xCD7E, 0x77FA, 0xCDA1, 0x77F7, 0xCDA2, 0x7942, 0xCDA3, 0x793F, + 0xCDA4, 0x79C5, 0xCDA5, 0x7A78, 0xCDA6, 0x7A7B, 0xCDA7, 0x7AFB, 0xCDA8, 0x7C75, 0xCDA9, 0x7CFD, 0xCDAA, 0x8035, 0xCDAB, 0x808F, + 0xCDAC, 0x80AE, 0xCDAD, 0x80A3, 0xCDAE, 0x80B8, 0xCDAF, 0x80B5, 0xCDB0, 0x80AD, 0xCDB1, 0x8220, 0xCDB2, 0x82A0, 0xCDB3, 0x82C0, + 0xCDB4, 0x82AB, 0xCDB5, 0x829A, 0xCDB6, 0x8298, 0xCDB7, 0x829B, 0xCDB8, 0x82B5, 0xCDB9, 0x82A7, 0xCDBA, 0x82AE, 0xCDBB, 0x82BC, + 0xCDBC, 0x829E, 0xCDBD, 0x82BA, 0xCDBE, 0x82B4, 0xCDBF, 0x82A8, 0xCDC0, 0x82A1, 0xCDC1, 0x82A9, 0xCDC2, 0x82C2, 0xCDC3, 0x82A4, + 0xCDC4, 0x82C3, 0xCDC5, 0x82B6, 0xCDC6, 0x82A2, 0xCDC7, 0x8670, 0xCDC8, 0x866F, 0xCDC9, 0x866D, 0xCDCA, 0x866E, 0xCDCB, 0x8C56, + 0xCDCC, 0x8FD2, 0xCDCD, 0x8FCB, 0xCDCE, 0x8FD3, 0xCDCF, 0x8FCD, 0xCDD0, 0x8FD6, 0xCDD1, 0x8FD5, 0xCDD2, 0x8FD7, 0xCDD3, 0x90B2, + 0xCDD4, 0x90B4, 0xCDD5, 0x90AF, 0xCDD6, 0x90B3, 0xCDD7, 0x90B0, 0xCDD8, 0x9639, 0xCDD9, 0x963D, 0xCDDA, 0x963C, 0xCDDB, 0x963A, + 0xCDDC, 0x9643, 0xCDDD, 0x4FCD, 0xCDDE, 0x4FC5, 0xCDDF, 0x4FD3, 0xCDE0, 0x4FB2, 0xCDE1, 0x4FC9, 0xCDE2, 0x4FCB, 0xCDE3, 0x4FC1, + 0xCDE4, 0x4FD4, 0xCDE5, 0x4FDC, 0xCDE6, 0x4FD9, 0xCDE7, 0x4FBB, 0xCDE8, 0x4FB3, 0xCDE9, 0x4FDB, 0xCDEA, 0x4FC7, 0xCDEB, 0x4FD6, + 0xCDEC, 0x4FBA, 0xCDED, 0x4FC0, 0xCDEE, 0x4FB9, 0xCDEF, 0x4FEC, 0xCDF0, 0x5244, 0xCDF1, 0x5249, 0xCDF2, 0x52C0, 0xCDF3, 0x52C2, + 0xCDF4, 0x533D, 0xCDF5, 0x537C, 0xCDF6, 0x5397, 0xCDF7, 0x5396, 0xCDF8, 0x5399, 0xCDF9, 0x5398, 0xCDFA, 0x54BA, 0xCDFB, 0x54A1, + 0xCDFC, 0x54AD, 0xCDFD, 0x54A5, 0xCDFE, 0x54CF, 0xCE40, 0x54C3, 0xCE41, 0x830D, 0xCE42, 0x54B7, 0xCE43, 0x54AE, 0xCE44, 0x54D6, + 0xCE45, 0x54B6, 0xCE46, 0x54C5, 0xCE47, 0x54C6, 0xCE48, 0x54A0, 0xCE49, 0x5470, 0xCE4A, 0x54BC, 0xCE4B, 0x54A2, 0xCE4C, 0x54BE, + 0xCE4D, 0x5472, 0xCE4E, 0x54DE, 0xCE4F, 0x54B0, 0xCE50, 0x57B5, 0xCE51, 0x579E, 0xCE52, 0x579F, 0xCE53, 0x57A4, 0xCE54, 0x578C, + 0xCE55, 0x5797, 0xCE56, 0x579D, 0xCE57, 0x579B, 0xCE58, 0x5794, 0xCE59, 0x5798, 0xCE5A, 0x578F, 0xCE5B, 0x5799, 0xCE5C, 0x57A5, + 0xCE5D, 0x579A, 0xCE5E, 0x5795, 0xCE5F, 0x58F4, 0xCE60, 0x590D, 0xCE61, 0x5953, 0xCE62, 0x59E1, 0xCE63, 0x59DE, 0xCE64, 0x59EE, + 0xCE65, 0x5A00, 0xCE66, 0x59F1, 0xCE67, 0x59DD, 0xCE68, 0x59FA, 0xCE69, 0x59FD, 0xCE6A, 0x59FC, 0xCE6B, 0x59F6, 0xCE6C, 0x59E4, + 0xCE6D, 0x59F2, 0xCE6E, 0x59F7, 0xCE6F, 0x59DB, 0xCE70, 0x59E9, 0xCE71, 0x59F3, 0xCE72, 0x59F5, 0xCE73, 0x59E0, 0xCE74, 0x59FE, + 0xCE75, 0x59F4, 0xCE76, 0x59ED, 0xCE77, 0x5BA8, 0xCE78, 0x5C4C, 0xCE79, 0x5CD0, 0xCE7A, 0x5CD8, 0xCE7B, 0x5CCC, 0xCE7C, 0x5CD7, + 0xCE7D, 0x5CCB, 0xCE7E, 0x5CDB, 0xCEA1, 0x5CDE, 0xCEA2, 0x5CDA, 0xCEA3, 0x5CC9, 0xCEA4, 0x5CC7, 0xCEA5, 0x5CCA, 0xCEA6, 0x5CD6, + 0xCEA7, 0x5CD3, 0xCEA8, 0x5CD4, 0xCEA9, 0x5CCF, 0xCEAA, 0x5CC8, 0xCEAB, 0x5CC6, 0xCEAC, 0x5CCE, 0xCEAD, 0x5CDF, 0xCEAE, 0x5CF8, + 0xCEAF, 0x5DF9, 0xCEB0, 0x5E21, 0xCEB1, 0x5E22, 0xCEB2, 0x5E23, 0xCEB3, 0x5E20, 0xCEB4, 0x5E24, 0xCEB5, 0x5EB0, 0xCEB6, 0x5EA4, + 0xCEB7, 0x5EA2, 0xCEB8, 0x5E9B, 0xCEB9, 0x5EA3, 0xCEBA, 0x5EA5, 0xCEBB, 0x5F07, 0xCEBC, 0x5F2E, 0xCEBD, 0x5F56, 0xCEBE, 0x5F86, + 0xCEBF, 0x6037, 0xCEC0, 0x6039, 0xCEC1, 0x6054, 0xCEC2, 0x6072, 0xCEC3, 0x605E, 0xCEC4, 0x6045, 0xCEC5, 0x6053, 0xCEC6, 0x6047, + 0xCEC7, 0x6049, 0xCEC8, 0x605B, 0xCEC9, 0x604C, 0xCECA, 0x6040, 0xCECB, 0x6042, 0xCECC, 0x605F, 0xCECD, 0x6024, 0xCECE, 0x6044, + 0xCECF, 0x6058, 0xCED0, 0x6066, 0xCED1, 0x606E, 0xCED2, 0x6242, 0xCED3, 0x6243, 0xCED4, 0x62CF, 0xCED5, 0x630D, 0xCED6, 0x630B, + 0xCED7, 0x62F5, 0xCED8, 0x630E, 0xCED9, 0x6303, 0xCEDA, 0x62EB, 0xCEDB, 0x62F9, 0xCEDC, 0x630F, 0xCEDD, 0x630C, 0xCEDE, 0x62F8, + 0xCEDF, 0x62F6, 0xCEE0, 0x6300, 0xCEE1, 0x6313, 0xCEE2, 0x6314, 0xCEE3, 0x62FA, 0xCEE4, 0x6315, 0xCEE5, 0x62FB, 0xCEE6, 0x62F0, + 0xCEE7, 0x6541, 0xCEE8, 0x6543, 0xCEE9, 0x65AA, 0xCEEA, 0x65BF, 0xCEEB, 0x6636, 0xCEEC, 0x6621, 0xCEED, 0x6632, 0xCEEE, 0x6635, + 0xCEEF, 0x661C, 0xCEF0, 0x6626, 0xCEF1, 0x6622, 0xCEF2, 0x6633, 0xCEF3, 0x662B, 0xCEF4, 0x663A, 0xCEF5, 0x661D, 0xCEF6, 0x6634, + 0xCEF7, 0x6639, 0xCEF8, 0x662E, 0xCEF9, 0x670F, 0xCEFA, 0x6710, 0xCEFB, 0x67C1, 0xCEFC, 0x67F2, 0xCEFD, 0x67C8, 0xCEFE, 0x67BA, + 0xCF40, 0x67DC, 0xCF41, 0x67BB, 0xCF42, 0x67F8, 0xCF43, 0x67D8, 0xCF44, 0x67C0, 0xCF45, 0x67B7, 0xCF46, 0x67C5, 0xCF47, 0x67EB, + 0xCF48, 0x67E4, 0xCF49, 0x67DF, 0xCF4A, 0x67B5, 0xCF4B, 0x67CD, 0xCF4C, 0x67B3, 0xCF4D, 0x67F7, 0xCF4E, 0x67F6, 0xCF4F, 0x67EE, + 0xCF50, 0x67E3, 0xCF51, 0x67C2, 0xCF52, 0x67B9, 0xCF53, 0x67CE, 0xCF54, 0x67E7, 0xCF55, 0x67F0, 0xCF56, 0x67B2, 0xCF57, 0x67FC, + 0xCF58, 0x67C6, 0xCF59, 0x67ED, 0xCF5A, 0x67CC, 0xCF5B, 0x67AE, 0xCF5C, 0x67E6, 0xCF5D, 0x67DB, 0xCF5E, 0x67FA, 0xCF5F, 0x67C9, + 0xCF60, 0x67CA, 0xCF61, 0x67C3, 0xCF62, 0x67EA, 0xCF63, 0x67CB, 0xCF64, 0x6B28, 0xCF65, 0x6B82, 0xCF66, 0x6B84, 0xCF67, 0x6BB6, + 0xCF68, 0x6BD6, 0xCF69, 0x6BD8, 0xCF6A, 0x6BE0, 0xCF6B, 0x6C20, 0xCF6C, 0x6C21, 0xCF6D, 0x6D28, 0xCF6E, 0x6D34, 0xCF6F, 0x6D2D, + 0xCF70, 0x6D1F, 0xCF71, 0x6D3C, 0xCF72, 0x6D3F, 0xCF73, 0x6D12, 0xCF74, 0x6D0A, 0xCF75, 0x6CDA, 0xCF76, 0x6D33, 0xCF77, 0x6D04, + 0xCF78, 0x6D19, 0xCF79, 0x6D3A, 0xCF7A, 0x6D1A, 0xCF7B, 0x6D11, 0xCF7C, 0x6D00, 0xCF7D, 0x6D1D, 0xCF7E, 0x6D42, 0xCFA1, 0x6D01, + 0xCFA2, 0x6D18, 0xCFA3, 0x6D37, 0xCFA4, 0x6D03, 0xCFA5, 0x6D0F, 0xCFA6, 0x6D40, 0xCFA7, 0x6D07, 0xCFA8, 0x6D20, 0xCFA9, 0x6D2C, + 0xCFAA, 0x6D08, 0xCFAB, 0x6D22, 0xCFAC, 0x6D09, 0xCFAD, 0x6D10, 0xCFAE, 0x70B7, 0xCFAF, 0x709F, 0xCFB0, 0x70BE, 0xCFB1, 0x70B1, + 0xCFB2, 0x70B0, 0xCFB3, 0x70A1, 0xCFB4, 0x70B4, 0xCFB5, 0x70B5, 0xCFB6, 0x70A9, 0xCFB7, 0x7241, 0xCFB8, 0x7249, 0xCFB9, 0x724A, + 0xCFBA, 0x726C, 0xCFBB, 0x7270, 0xCFBC, 0x7273, 0xCFBD, 0x726E, 0xCFBE, 0x72CA, 0xCFBF, 0x72E4, 0xCFC0, 0x72E8, 0xCFC1, 0x72EB, + 0xCFC2, 0x72DF, 0xCFC3, 0x72EA, 0xCFC4, 0x72E6, 0xCFC5, 0x72E3, 0xCFC6, 0x7385, 0xCFC7, 0x73CC, 0xCFC8, 0x73C2, 0xCFC9, 0x73C8, + 0xCFCA, 0x73C5, 0xCFCB, 0x73B9, 0xCFCC, 0x73B6, 0xCFCD, 0x73B5, 0xCFCE, 0x73B4, 0xCFCF, 0x73EB, 0xCFD0, 0x73BF, 0xCFD1, 0x73C7, + 0xCFD2, 0x73BE, 0xCFD3, 0x73C3, 0xCFD4, 0x73C6, 0xCFD5, 0x73B8, 0xCFD6, 0x73CB, 0xCFD7, 0x74EC, 0xCFD8, 0x74EE, 0xCFD9, 0x752E, + 0xCFDA, 0x7547, 0xCFDB, 0x7548, 0xCFDC, 0x75A7, 0xCFDD, 0x75AA, 0xCFDE, 0x7679, 0xCFDF, 0x76C4, 0xCFE0, 0x7708, 0xCFE1, 0x7703, + 0xCFE2, 0x7704, 0xCFE3, 0x7705, 0xCFE4, 0x770A, 0xCFE5, 0x76F7, 0xCFE6, 0x76FB, 0xCFE7, 0x76FA, 0xCFE8, 0x77E7, 0xCFE9, 0x77E8, + 0xCFEA, 0x7806, 0xCFEB, 0x7811, 0xCFEC, 0x7812, 0xCFED, 0x7805, 0xCFEE, 0x7810, 0xCFEF, 0x780F, 0xCFF0, 0x780E, 0xCFF1, 0x7809, + 0xCFF2, 0x7803, 0xCFF3, 0x7813, 0xCFF4, 0x794A, 0xCFF5, 0x794C, 0xCFF6, 0x794B, 0xCFF7, 0x7945, 0xCFF8, 0x7944, 0xCFF9, 0x79D5, + 0xCFFA, 0x79CD, 0xCFFB, 0x79CF, 0xCFFC, 0x79D6, 0xCFFD, 0x79CE, 0xCFFE, 0x7A80, 0xD040, 0x7A7E, 0xD041, 0x7AD1, 0xD042, 0x7B00, + 0xD043, 0x7B01, 0xD044, 0x7C7A, 0xD045, 0x7C78, 0xD046, 0x7C79, 0xD047, 0x7C7F, 0xD048, 0x7C80, 0xD049, 0x7C81, 0xD04A, 0x7D03, + 0xD04B, 0x7D08, 0xD04C, 0x7D01, 0xD04D, 0x7F58, 0xD04E, 0x7F91, 0xD04F, 0x7F8D, 0xD050, 0x7FBE, 0xD051, 0x8007, 0xD052, 0x800E, + 0xD053, 0x800F, 0xD054, 0x8014, 0xD055, 0x8037, 0xD056, 0x80D8, 0xD057, 0x80C7, 0xD058, 0x80E0, 0xD059, 0x80D1, 0xD05A, 0x80C8, + 0xD05B, 0x80C2, 0xD05C, 0x80D0, 0xD05D, 0x80C5, 0xD05E, 0x80E3, 0xD05F, 0x80D9, 0xD060, 0x80DC, 0xD061, 0x80CA, 0xD062, 0x80D5, + 0xD063, 0x80C9, 0xD064, 0x80CF, 0xD065, 0x80D7, 0xD066, 0x80E6, 0xD067, 0x80CD, 0xD068, 0x81FF, 0xD069, 0x8221, 0xD06A, 0x8294, + 0xD06B, 0x82D9, 0xD06C, 0x82FE, 0xD06D, 0x82F9, 0xD06E, 0x8307, 0xD06F, 0x82E8, 0xD070, 0x8300, 0xD071, 0x82D5, 0xD072, 0x833A, + 0xD073, 0x82EB, 0xD074, 0x82D6, 0xD075, 0x82F4, 0xD076, 0x82EC, 0xD077, 0x82E1, 0xD078, 0x82F2, 0xD079, 0x82F5, 0xD07A, 0x830C, + 0xD07B, 0x82FB, 0xD07C, 0x82F6, 0xD07D, 0x82F0, 0xD07E, 0x82EA, 0xD0A1, 0x82E4, 0xD0A2, 0x82E0, 0xD0A3, 0x82FA, 0xD0A4, 0x82F3, + 0xD0A5, 0x82ED, 0xD0A6, 0x8677, 0xD0A7, 0x8674, 0xD0A8, 0x867C, 0xD0A9, 0x8673, 0xD0AA, 0x8841, 0xD0AB, 0x884E, 0xD0AC, 0x8867, + 0xD0AD, 0x886A, 0xD0AE, 0x8869, 0xD0AF, 0x89D3, 0xD0B0, 0x8A04, 0xD0B1, 0x8A07, 0xD0B2, 0x8D72, 0xD0B3, 0x8FE3, 0xD0B4, 0x8FE1, + 0xD0B5, 0x8FEE, 0xD0B6, 0x8FE0, 0xD0B7, 0x90F1, 0xD0B8, 0x90BD, 0xD0B9, 0x90BF, 0xD0BA, 0x90D5, 0xD0BB, 0x90C5, 0xD0BC, 0x90BE, + 0xD0BD, 0x90C7, 0xD0BE, 0x90CB, 0xD0BF, 0x90C8, 0xD0C0, 0x91D4, 0xD0C1, 0x91D3, 0xD0C2, 0x9654, 0xD0C3, 0x964F, 0xD0C4, 0x9651, + 0xD0C5, 0x9653, 0xD0C6, 0x964A, 0xD0C7, 0x964E, 0xD0C8, 0x501E, 0xD0C9, 0x5005, 0xD0CA, 0x5007, 0xD0CB, 0x5013, 0xD0CC, 0x5022, + 0xD0CD, 0x5030, 0xD0CE, 0x501B, 0xD0CF, 0x4FF5, 0xD0D0, 0x4FF4, 0xD0D1, 0x5033, 0xD0D2, 0x5037, 0xD0D3, 0x502C, 0xD0D4, 0x4FF6, + 0xD0D5, 0x4FF7, 0xD0D6, 0x5017, 0xD0D7, 0x501C, 0xD0D8, 0x5020, 0xD0D9, 0x5027, 0xD0DA, 0x5035, 0xD0DB, 0x502F, 0xD0DC, 0x5031, + 0xD0DD, 0x500E, 0xD0DE, 0x515A, 0xD0DF, 0x5194, 0xD0E0, 0x5193, 0xD0E1, 0x51CA, 0xD0E2, 0x51C4, 0xD0E3, 0x51C5, 0xD0E4, 0x51C8, + 0xD0E5, 0x51CE, 0xD0E6, 0x5261, 0xD0E7, 0x525A, 0xD0E8, 0x5252, 0xD0E9, 0x525E, 0xD0EA, 0x525F, 0xD0EB, 0x5255, 0xD0EC, 0x5262, + 0xD0ED, 0x52CD, 0xD0EE, 0x530E, 0xD0EF, 0x539E, 0xD0F0, 0x5526, 0xD0F1, 0x54E2, 0xD0F2, 0x5517, 0xD0F3, 0x5512, 0xD0F4, 0x54E7, + 0xD0F5, 0x54F3, 0xD0F6, 0x54E4, 0xD0F7, 0x551A, 0xD0F8, 0x54FF, 0xD0F9, 0x5504, 0xD0FA, 0x5508, 0xD0FB, 0x54EB, 0xD0FC, 0x5511, + 0xD0FD, 0x5505, 0xD0FE, 0x54F1, 0xD140, 0x550A, 0xD141, 0x54FB, 0xD142, 0x54F7, 0xD143, 0x54F8, 0xD144, 0x54E0, 0xD145, 0x550E, + 0xD146, 0x5503, 0xD147, 0x550B, 0xD148, 0x5701, 0xD149, 0x5702, 0xD14A, 0x57CC, 0xD14B, 0x5832, 0xD14C, 0x57D5, 0xD14D, 0x57D2, + 0xD14E, 0x57BA, 0xD14F, 0x57C6, 0xD150, 0x57BD, 0xD151, 0x57BC, 0xD152, 0x57B8, 0xD153, 0x57B6, 0xD154, 0x57BF, 0xD155, 0x57C7, + 0xD156, 0x57D0, 0xD157, 0x57B9, 0xD158, 0x57C1, 0xD159, 0x590E, 0xD15A, 0x594A, 0xD15B, 0x5A19, 0xD15C, 0x5A16, 0xD15D, 0x5A2D, + 0xD15E, 0x5A2E, 0xD15F, 0x5A15, 0xD160, 0x5A0F, 0xD161, 0x5A17, 0xD162, 0x5A0A, 0xD163, 0x5A1E, 0xD164, 0x5A33, 0xD165, 0x5B6C, + 0xD166, 0x5BA7, 0xD167, 0x5BAD, 0xD168, 0x5BAC, 0xD169, 0x5C03, 0xD16A, 0x5C56, 0xD16B, 0x5C54, 0xD16C, 0x5CEC, 0xD16D, 0x5CFF, + 0xD16E, 0x5CEE, 0xD16F, 0x5CF1, 0xD170, 0x5CF7, 0xD171, 0x5D00, 0xD172, 0x5CF9, 0xD173, 0x5E29, 0xD174, 0x5E28, 0xD175, 0x5EA8, + 0xD176, 0x5EAE, 0xD177, 0x5EAA, 0xD178, 0x5EAC, 0xD179, 0x5F33, 0xD17A, 0x5F30, 0xD17B, 0x5F67, 0xD17C, 0x605D, 0xD17D, 0x605A, + 0xD17E, 0x6067, 0xD1A1, 0x6041, 0xD1A2, 0x60A2, 0xD1A3, 0x6088, 0xD1A4, 0x6080, 0xD1A5, 0x6092, 0xD1A6, 0x6081, 0xD1A7, 0x609D, + 0xD1A8, 0x6083, 0xD1A9, 0x6095, 0xD1AA, 0x609B, 0xD1AB, 0x6097, 0xD1AC, 0x6087, 0xD1AD, 0x609C, 0xD1AE, 0x608E, 0xD1AF, 0x6219, + 0xD1B0, 0x6246, 0xD1B1, 0x62F2, 0xD1B2, 0x6310, 0xD1B3, 0x6356, 0xD1B4, 0x632C, 0xD1B5, 0x6344, 0xD1B6, 0x6345, 0xD1B7, 0x6336, + 0xD1B8, 0x6343, 0xD1B9, 0x63E4, 0xD1BA, 0x6339, 0xD1BB, 0x634B, 0xD1BC, 0x634A, 0xD1BD, 0x633C, 0xD1BE, 0x6329, 0xD1BF, 0x6341, + 0xD1C0, 0x6334, 0xD1C1, 0x6358, 0xD1C2, 0x6354, 0xD1C3, 0x6359, 0xD1C4, 0x632D, 0xD1C5, 0x6347, 0xD1C6, 0x6333, 0xD1C7, 0x635A, + 0xD1C8, 0x6351, 0xD1C9, 0x6338, 0xD1CA, 0x6357, 0xD1CB, 0x6340, 0xD1CC, 0x6348, 0xD1CD, 0x654A, 0xD1CE, 0x6546, 0xD1CF, 0x65C6, + 0xD1D0, 0x65C3, 0xD1D1, 0x65C4, 0xD1D2, 0x65C2, 0xD1D3, 0x664A, 0xD1D4, 0x665F, 0xD1D5, 0x6647, 0xD1D6, 0x6651, 0xD1D7, 0x6712, + 0xD1D8, 0x6713, 0xD1D9, 0x681F, 0xD1DA, 0x681A, 0xD1DB, 0x6849, 0xD1DC, 0x6832, 0xD1DD, 0x6833, 0xD1DE, 0x683B, 0xD1DF, 0x684B, + 0xD1E0, 0x684F, 0xD1E1, 0x6816, 0xD1E2, 0x6831, 0xD1E3, 0x681C, 0xD1E4, 0x6835, 0xD1E5, 0x682B, 0xD1E6, 0x682D, 0xD1E7, 0x682F, + 0xD1E8, 0x684E, 0xD1E9, 0x6844, 0xD1EA, 0x6834, 0xD1EB, 0x681D, 0xD1EC, 0x6812, 0xD1ED, 0x6814, 0xD1EE, 0x6826, 0xD1EF, 0x6828, + 0xD1F0, 0x682E, 0xD1F1, 0x684D, 0xD1F2, 0x683A, 0xD1F3, 0x6825, 0xD1F4, 0x6820, 0xD1F5, 0x6B2C, 0xD1F6, 0x6B2F, 0xD1F7, 0x6B2D, + 0xD1F8, 0x6B31, 0xD1F9, 0x6B34, 0xD1FA, 0x6B6D, 0xD1FB, 0x8082, 0xD1FC, 0x6B88, 0xD1FD, 0x6BE6, 0xD1FE, 0x6BE4, 0xD240, 0x6BE8, + 0xD241, 0x6BE3, 0xD242, 0x6BE2, 0xD243, 0x6BE7, 0xD244, 0x6C25, 0xD245, 0x6D7A, 0xD246, 0x6D63, 0xD247, 0x6D64, 0xD248, 0x6D76, + 0xD249, 0x6D0D, 0xD24A, 0x6D61, 0xD24B, 0x6D92, 0xD24C, 0x6D58, 0xD24D, 0x6D62, 0xD24E, 0x6D6D, 0xD24F, 0x6D6F, 0xD250, 0x6D91, + 0xD251, 0x6D8D, 0xD252, 0x6DEF, 0xD253, 0x6D7F, 0xD254, 0x6D86, 0xD255, 0x6D5E, 0xD256, 0x6D67, 0xD257, 0x6D60, 0xD258, 0x6D97, + 0xD259, 0x6D70, 0xD25A, 0x6D7C, 0xD25B, 0x6D5F, 0xD25C, 0x6D82, 0xD25D, 0x6D98, 0xD25E, 0x6D2F, 0xD25F, 0x6D68, 0xD260, 0x6D8B, + 0xD261, 0x6D7E, 0xD262, 0x6D80, 0xD263, 0x6D84, 0xD264, 0x6D16, 0xD265, 0x6D83, 0xD266, 0x6D7B, 0xD267, 0x6D7D, 0xD268, 0x6D75, + 0xD269, 0x6D90, 0xD26A, 0x70DC, 0xD26B, 0x70D3, 0xD26C, 0x70D1, 0xD26D, 0x70DD, 0xD26E, 0x70CB, 0xD26F, 0x7F39, 0xD270, 0x70E2, + 0xD271, 0x70D7, 0xD272, 0x70D2, 0xD273, 0x70DE, 0xD274, 0x70E0, 0xD275, 0x70D4, 0xD276, 0x70CD, 0xD277, 0x70C5, 0xD278, 0x70C6, + 0xD279, 0x70C7, 0xD27A, 0x70DA, 0xD27B, 0x70CE, 0xD27C, 0x70E1, 0xD27D, 0x7242, 0xD27E, 0x7278, 0xD2A1, 0x7277, 0xD2A2, 0x7276, + 0xD2A3, 0x7300, 0xD2A4, 0x72FA, 0xD2A5, 0x72F4, 0xD2A6, 0x72FE, 0xD2A7, 0x72F6, 0xD2A8, 0x72F3, 0xD2A9, 0x72FB, 0xD2AA, 0x7301, + 0xD2AB, 0x73D3, 0xD2AC, 0x73D9, 0xD2AD, 0x73E5, 0xD2AE, 0x73D6, 0xD2AF, 0x73BC, 0xD2B0, 0x73E7, 0xD2B1, 0x73E3, 0xD2B2, 0x73E9, + 0xD2B3, 0x73DC, 0xD2B4, 0x73D2, 0xD2B5, 0x73DB, 0xD2B6, 0x73D4, 0xD2B7, 0x73DD, 0xD2B8, 0x73DA, 0xD2B9, 0x73D7, 0xD2BA, 0x73D8, + 0xD2BB, 0x73E8, 0xD2BC, 0x74DE, 0xD2BD, 0x74DF, 0xD2BE, 0x74F4, 0xD2BF, 0x74F5, 0xD2C0, 0x7521, 0xD2C1, 0x755B, 0xD2C2, 0x755F, + 0xD2C3, 0x75B0, 0xD2C4, 0x75C1, 0xD2C5, 0x75BB, 0xD2C6, 0x75C4, 0xD2C7, 0x75C0, 0xD2C8, 0x75BF, 0xD2C9, 0x75B6, 0xD2CA, 0x75BA, + 0xD2CB, 0x768A, 0xD2CC, 0x76C9, 0xD2CD, 0x771D, 0xD2CE, 0x771B, 0xD2CF, 0x7710, 0xD2D0, 0x7713, 0xD2D1, 0x7712, 0xD2D2, 0x7723, + 0xD2D3, 0x7711, 0xD2D4, 0x7715, 0xD2D5, 0x7719, 0xD2D6, 0x771A, 0xD2D7, 0x7722, 0xD2D8, 0x7727, 0xD2D9, 0x7823, 0xD2DA, 0x782C, + 0xD2DB, 0x7822, 0xD2DC, 0x7835, 0xD2DD, 0x782F, 0xD2DE, 0x7828, 0xD2DF, 0x782E, 0xD2E0, 0x782B, 0xD2E1, 0x7821, 0xD2E2, 0x7829, + 0xD2E3, 0x7833, 0xD2E4, 0x782A, 0xD2E5, 0x7831, 0xD2E6, 0x7954, 0xD2E7, 0x795B, 0xD2E8, 0x794F, 0xD2E9, 0x795C, 0xD2EA, 0x7953, + 0xD2EB, 0x7952, 0xD2EC, 0x7951, 0xD2ED, 0x79EB, 0xD2EE, 0x79EC, 0xD2EF, 0x79E0, 0xD2F0, 0x79EE, 0xD2F1, 0x79ED, 0xD2F2, 0x79EA, + 0xD2F3, 0x79DC, 0xD2F4, 0x79DE, 0xD2F5, 0x79DD, 0xD2F6, 0x7A86, 0xD2F7, 0x7A89, 0xD2F8, 0x7A85, 0xD2F9, 0x7A8B, 0xD2FA, 0x7A8C, + 0xD2FB, 0x7A8A, 0xD2FC, 0x7A87, 0xD2FD, 0x7AD8, 0xD2FE, 0x7B10, 0xD340, 0x7B04, 0xD341, 0x7B13, 0xD342, 0x7B05, 0xD343, 0x7B0F, + 0xD344, 0x7B08, 0xD345, 0x7B0A, 0xD346, 0x7B0E, 0xD347, 0x7B09, 0xD348, 0x7B12, 0xD349, 0x7C84, 0xD34A, 0x7C91, 0xD34B, 0x7C8A, + 0xD34C, 0x7C8C, 0xD34D, 0x7C88, 0xD34E, 0x7C8D, 0xD34F, 0x7C85, 0xD350, 0x7D1E, 0xD351, 0x7D1D, 0xD352, 0x7D11, 0xD353, 0x7D0E, + 0xD354, 0x7D18, 0xD355, 0x7D16, 0xD356, 0x7D13, 0xD357, 0x7D1F, 0xD358, 0x7D12, 0xD359, 0x7D0F, 0xD35A, 0x7D0C, 0xD35B, 0x7F5C, + 0xD35C, 0x7F61, 0xD35D, 0x7F5E, 0xD35E, 0x7F60, 0xD35F, 0x7F5D, 0xD360, 0x7F5B, 0xD361, 0x7F96, 0xD362, 0x7F92, 0xD363, 0x7FC3, + 0xD364, 0x7FC2, 0xD365, 0x7FC0, 0xD366, 0x8016, 0xD367, 0x803E, 0xD368, 0x8039, 0xD369, 0x80FA, 0xD36A, 0x80F2, 0xD36B, 0x80F9, + 0xD36C, 0x80F5, 0xD36D, 0x8101, 0xD36E, 0x80FB, 0xD36F, 0x8100, 0xD370, 0x8201, 0xD371, 0x822F, 0xD372, 0x8225, 0xD373, 0x8333, + 0xD374, 0x832D, 0xD375, 0x8344, 0xD376, 0x8319, 0xD377, 0x8351, 0xD378, 0x8325, 0xD379, 0x8356, 0xD37A, 0x833F, 0xD37B, 0x8341, + 0xD37C, 0x8326, 0xD37D, 0x831C, 0xD37E, 0x8322, 0xD3A1, 0x8342, 0xD3A2, 0x834E, 0xD3A3, 0x831B, 0xD3A4, 0x832A, 0xD3A5, 0x8308, + 0xD3A6, 0x833C, 0xD3A7, 0x834D, 0xD3A8, 0x8316, 0xD3A9, 0x8324, 0xD3AA, 0x8320, 0xD3AB, 0x8337, 0xD3AC, 0x832F, 0xD3AD, 0x8329, + 0xD3AE, 0x8347, 0xD3AF, 0x8345, 0xD3B0, 0x834C, 0xD3B1, 0x8353, 0xD3B2, 0x831E, 0xD3B3, 0x832C, 0xD3B4, 0x834B, 0xD3B5, 0x8327, + 0xD3B6, 0x8348, 0xD3B7, 0x8653, 0xD3B8, 0x8652, 0xD3B9, 0x86A2, 0xD3BA, 0x86A8, 0xD3BB, 0x8696, 0xD3BC, 0x868D, 0xD3BD, 0x8691, + 0xD3BE, 0x869E, 0xD3BF, 0x8687, 0xD3C0, 0x8697, 0xD3C1, 0x8686, 0xD3C2, 0x868B, 0xD3C3, 0x869A, 0xD3C4, 0x8685, 0xD3C5, 0x86A5, + 0xD3C6, 0x8699, 0xD3C7, 0x86A1, 0xD3C8, 0x86A7, 0xD3C9, 0x8695, 0xD3CA, 0x8698, 0xD3CB, 0x868E, 0xD3CC, 0x869D, 0xD3CD, 0x8690, + 0xD3CE, 0x8694, 0xD3CF, 0x8843, 0xD3D0, 0x8844, 0xD3D1, 0x886D, 0xD3D2, 0x8875, 0xD3D3, 0x8876, 0xD3D4, 0x8872, 0xD3D5, 0x8880, + 0xD3D6, 0x8871, 0xD3D7, 0x887F, 0xD3D8, 0x886F, 0xD3D9, 0x8883, 0xD3DA, 0x887E, 0xD3DB, 0x8874, 0xD3DC, 0x887C, 0xD3DD, 0x8A12, + 0xD3DE, 0x8C47, 0xD3DF, 0x8C57, 0xD3E0, 0x8C7B, 0xD3E1, 0x8CA4, 0xD3E2, 0x8CA3, 0xD3E3, 0x8D76, 0xD3E4, 0x8D78, 0xD3E5, 0x8DB5, + 0xD3E6, 0x8DB7, 0xD3E7, 0x8DB6, 0xD3E8, 0x8ED1, 0xD3E9, 0x8ED3, 0xD3EA, 0x8FFE, 0xD3EB, 0x8FF5, 0xD3EC, 0x9002, 0xD3ED, 0x8FFF, + 0xD3EE, 0x8FFB, 0xD3EF, 0x9004, 0xD3F0, 0x8FFC, 0xD3F1, 0x8FF6, 0xD3F2, 0x90D6, 0xD3F3, 0x90E0, 0xD3F4, 0x90D9, 0xD3F5, 0x90DA, + 0xD3F6, 0x90E3, 0xD3F7, 0x90DF, 0xD3F8, 0x90E5, 0xD3F9, 0x90D8, 0xD3FA, 0x90DB, 0xD3FB, 0x90D7, 0xD3FC, 0x90DC, 0xD3FD, 0x90E4, + 0xD3FE, 0x9150, 0xD440, 0x914E, 0xD441, 0x914F, 0xD442, 0x91D5, 0xD443, 0x91E2, 0xD444, 0x91DA, 0xD445, 0x965C, 0xD446, 0x965F, + 0xD447, 0x96BC, 0xD448, 0x98E3, 0xD449, 0x9ADF, 0xD44A, 0x9B2F, 0xD44B, 0x4E7F, 0xD44C, 0x5070, 0xD44D, 0x506A, 0xD44E, 0x5061, + 0xD44F, 0x505E, 0xD450, 0x5060, 0xD451, 0x5053, 0xD452, 0x504B, 0xD453, 0x505D, 0xD454, 0x5072, 0xD455, 0x5048, 0xD456, 0x504D, + 0xD457, 0x5041, 0xD458, 0x505B, 0xD459, 0x504A, 0xD45A, 0x5062, 0xD45B, 0x5015, 0xD45C, 0x5045, 0xD45D, 0x505F, 0xD45E, 0x5069, + 0xD45F, 0x506B, 0xD460, 0x5063, 0xD461, 0x5064, 0xD462, 0x5046, 0xD463, 0x5040, 0xD464, 0x506E, 0xD465, 0x5073, 0xD466, 0x5057, + 0xD467, 0x5051, 0xD468, 0x51D0, 0xD469, 0x526B, 0xD46A, 0x526D, 0xD46B, 0x526C, 0xD46C, 0x526E, 0xD46D, 0x52D6, 0xD46E, 0x52D3, + 0xD46F, 0x532D, 0xD470, 0x539C, 0xD471, 0x5575, 0xD472, 0x5576, 0xD473, 0x553C, 0xD474, 0x554D, 0xD475, 0x5550, 0xD476, 0x5534, + 0xD477, 0x552A, 0xD478, 0x5551, 0xD479, 0x5562, 0xD47A, 0x5536, 0xD47B, 0x5535, 0xD47C, 0x5530, 0xD47D, 0x5552, 0xD47E, 0x5545, + 0xD4A1, 0x550C, 0xD4A2, 0x5532, 0xD4A3, 0x5565, 0xD4A4, 0x554E, 0xD4A5, 0x5539, 0xD4A6, 0x5548, 0xD4A7, 0x552D, 0xD4A8, 0x553B, + 0xD4A9, 0x5540, 0xD4AA, 0x554B, 0xD4AB, 0x570A, 0xD4AC, 0x5707, 0xD4AD, 0x57FB, 0xD4AE, 0x5814, 0xD4AF, 0x57E2, 0xD4B0, 0x57F6, + 0xD4B1, 0x57DC, 0xD4B2, 0x57F4, 0xD4B3, 0x5800, 0xD4B4, 0x57ED, 0xD4B5, 0x57FD, 0xD4B6, 0x5808, 0xD4B7, 0x57F8, 0xD4B8, 0x580B, + 0xD4B9, 0x57F3, 0xD4BA, 0x57CF, 0xD4BB, 0x5807, 0xD4BC, 0x57EE, 0xD4BD, 0x57E3, 0xD4BE, 0x57F2, 0xD4BF, 0x57E5, 0xD4C0, 0x57EC, + 0xD4C1, 0x57E1, 0xD4C2, 0x580E, 0xD4C3, 0x57FC, 0xD4C4, 0x5810, 0xD4C5, 0x57E7, 0xD4C6, 0x5801, 0xD4C7, 0x580C, 0xD4C8, 0x57F1, + 0xD4C9, 0x57E9, 0xD4CA, 0x57F0, 0xD4CB, 0x580D, 0xD4CC, 0x5804, 0xD4CD, 0x595C, 0xD4CE, 0x5A60, 0xD4CF, 0x5A58, 0xD4D0, 0x5A55, + 0xD4D1, 0x5A67, 0xD4D2, 0x5A5E, 0xD4D3, 0x5A38, 0xD4D4, 0x5A35, 0xD4D5, 0x5A6D, 0xD4D6, 0x5A50, 0xD4D7, 0x5A5F, 0xD4D8, 0x5A65, + 0xD4D9, 0x5A6C, 0xD4DA, 0x5A53, 0xD4DB, 0x5A64, 0xD4DC, 0x5A57, 0xD4DD, 0x5A43, 0xD4DE, 0x5A5D, 0xD4DF, 0x5A52, 0xD4E0, 0x5A44, + 0xD4E1, 0x5A5B, 0xD4E2, 0x5A48, 0xD4E3, 0x5A8E, 0xD4E4, 0x5A3E, 0xD4E5, 0x5A4D, 0xD4E6, 0x5A39, 0xD4E7, 0x5A4C, 0xD4E8, 0x5A70, + 0xD4E9, 0x5A69, 0xD4EA, 0x5A47, 0xD4EB, 0x5A51, 0xD4EC, 0x5A56, 0xD4ED, 0x5A42, 0xD4EE, 0x5A5C, 0xD4EF, 0x5B72, 0xD4F0, 0x5B6E, + 0xD4F1, 0x5BC1, 0xD4F2, 0x5BC0, 0xD4F3, 0x5C59, 0xD4F4, 0x5D1E, 0xD4F5, 0x5D0B, 0xD4F6, 0x5D1D, 0xD4F7, 0x5D1A, 0xD4F8, 0x5D20, + 0xD4F9, 0x5D0C, 0xD4FA, 0x5D28, 0xD4FB, 0x5D0D, 0xD4FC, 0x5D26, 0xD4FD, 0x5D25, 0xD4FE, 0x5D0F, 0xD540, 0x5D30, 0xD541, 0x5D12, + 0xD542, 0x5D23, 0xD543, 0x5D1F, 0xD544, 0x5D2E, 0xD545, 0x5E3E, 0xD546, 0x5E34, 0xD547, 0x5EB1, 0xD548, 0x5EB4, 0xD549, 0x5EB9, + 0xD54A, 0x5EB2, 0xD54B, 0x5EB3, 0xD54C, 0x5F36, 0xD54D, 0x5F38, 0xD54E, 0x5F9B, 0xD54F, 0x5F96, 0xD550, 0x5F9F, 0xD551, 0x608A, + 0xD552, 0x6090, 0xD553, 0x6086, 0xD554, 0x60BE, 0xD555, 0x60B0, 0xD556, 0x60BA, 0xD557, 0x60D3, 0xD558, 0x60D4, 0xD559, 0x60CF, + 0xD55A, 0x60E4, 0xD55B, 0x60D9, 0xD55C, 0x60DD, 0xD55D, 0x60C8, 0xD55E, 0x60B1, 0xD55F, 0x60DB, 0xD560, 0x60B7, 0xD561, 0x60CA, + 0xD562, 0x60BF, 0xD563, 0x60C3, 0xD564, 0x60CD, 0xD565, 0x60C0, 0xD566, 0x6332, 0xD567, 0x6365, 0xD568, 0x638A, 0xD569, 0x6382, + 0xD56A, 0x637D, 0xD56B, 0x63BD, 0xD56C, 0x639E, 0xD56D, 0x63AD, 0xD56E, 0x639D, 0xD56F, 0x6397, 0xD570, 0x63AB, 0xD571, 0x638E, + 0xD572, 0x636F, 0xD573, 0x6387, 0xD574, 0x6390, 0xD575, 0x636E, 0xD576, 0x63AF, 0xD577, 0x6375, 0xD578, 0x639C, 0xD579, 0x636D, + 0xD57A, 0x63AE, 0xD57B, 0x637C, 0xD57C, 0x63A4, 0xD57D, 0x633B, 0xD57E, 0x639F, 0xD5A1, 0x6378, 0xD5A2, 0x6385, 0xD5A3, 0x6381, + 0xD5A4, 0x6391, 0xD5A5, 0x638D, 0xD5A6, 0x6370, 0xD5A7, 0x6553, 0xD5A8, 0x65CD, 0xD5A9, 0x6665, 0xD5AA, 0x6661, 0xD5AB, 0x665B, + 0xD5AC, 0x6659, 0xD5AD, 0x665C, 0xD5AE, 0x6662, 0xD5AF, 0x6718, 0xD5B0, 0x6879, 0xD5B1, 0x6887, 0xD5B2, 0x6890, 0xD5B3, 0x689C, + 0xD5B4, 0x686D, 0xD5B5, 0x686E, 0xD5B6, 0x68AE, 0xD5B7, 0x68AB, 0xD5B8, 0x6956, 0xD5B9, 0x686F, 0xD5BA, 0x68A3, 0xD5BB, 0x68AC, + 0xD5BC, 0x68A9, 0xD5BD, 0x6875, 0xD5BE, 0x6874, 0xD5BF, 0x68B2, 0xD5C0, 0x688F, 0xD5C1, 0x6877, 0xD5C2, 0x6892, 0xD5C3, 0x687C, + 0xD5C4, 0x686B, 0xD5C5, 0x6872, 0xD5C6, 0x68AA, 0xD5C7, 0x6880, 0xD5C8, 0x6871, 0xD5C9, 0x687E, 0xD5CA, 0x689B, 0xD5CB, 0x6896, + 0xD5CC, 0x688B, 0xD5CD, 0x68A0, 0xD5CE, 0x6889, 0xD5CF, 0x68A4, 0xD5D0, 0x6878, 0xD5D1, 0x687B, 0xD5D2, 0x6891, 0xD5D3, 0x688C, + 0xD5D4, 0x688A, 0xD5D5, 0x687D, 0xD5D6, 0x6B36, 0xD5D7, 0x6B33, 0xD5D8, 0x6B37, 0xD5D9, 0x6B38, 0xD5DA, 0x6B91, 0xD5DB, 0x6B8F, + 0xD5DC, 0x6B8D, 0xD5DD, 0x6B8E, 0xD5DE, 0x6B8C, 0xD5DF, 0x6C2A, 0xD5E0, 0x6DC0, 0xD5E1, 0x6DAB, 0xD5E2, 0x6DB4, 0xD5E3, 0x6DB3, + 0xD5E4, 0x6E74, 0xD5E5, 0x6DAC, 0xD5E6, 0x6DE9, 0xD5E7, 0x6DE2, 0xD5E8, 0x6DB7, 0xD5E9, 0x6DF6, 0xD5EA, 0x6DD4, 0xD5EB, 0x6E00, + 0xD5EC, 0x6DC8, 0xD5ED, 0x6DE0, 0xD5EE, 0x6DDF, 0xD5EF, 0x6DD6, 0xD5F0, 0x6DBE, 0xD5F1, 0x6DE5, 0xD5F2, 0x6DDC, 0xD5F3, 0x6DDD, + 0xD5F4, 0x6DDB, 0xD5F5, 0x6DF4, 0xD5F6, 0x6DCA, 0xD5F7, 0x6DBD, 0xD5F8, 0x6DED, 0xD5F9, 0x6DF0, 0xD5FA, 0x6DBA, 0xD5FB, 0x6DD5, + 0xD5FC, 0x6DC2, 0xD5FD, 0x6DCF, 0xD5FE, 0x6DC9, 0xD640, 0x6DD0, 0xD641, 0x6DF2, 0xD642, 0x6DD3, 0xD643, 0x6DFD, 0xD644, 0x6DD7, + 0xD645, 0x6DCD, 0xD646, 0x6DE3, 0xD647, 0x6DBB, 0xD648, 0x70FA, 0xD649, 0x710D, 0xD64A, 0x70F7, 0xD64B, 0x7117, 0xD64C, 0x70F4, + 0xD64D, 0x710C, 0xD64E, 0x70F0, 0xD64F, 0x7104, 0xD650, 0x70F3, 0xD651, 0x7110, 0xD652, 0x70FC, 0xD653, 0x70FF, 0xD654, 0x7106, + 0xD655, 0x7113, 0xD656, 0x7100, 0xD657, 0x70F8, 0xD658, 0x70F6, 0xD659, 0x710B, 0xD65A, 0x7102, 0xD65B, 0x710E, 0xD65C, 0x727E, + 0xD65D, 0x727B, 0xD65E, 0x727C, 0xD65F, 0x727F, 0xD660, 0x731D, 0xD661, 0x7317, 0xD662, 0x7307, 0xD663, 0x7311, 0xD664, 0x7318, + 0xD665, 0x730A, 0xD666, 0x7308, 0xD667, 0x72FF, 0xD668, 0x730F, 0xD669, 0x731E, 0xD66A, 0x7388, 0xD66B, 0x73F6, 0xD66C, 0x73F8, + 0xD66D, 0x73F5, 0xD66E, 0x7404, 0xD66F, 0x7401, 0xD670, 0x73FD, 0xD671, 0x7407, 0xD672, 0x7400, 0xD673, 0x73FA, 0xD674, 0x73FC, + 0xD675, 0x73FF, 0xD676, 0x740C, 0xD677, 0x740B, 0xD678, 0x73F4, 0xD679, 0x7408, 0xD67A, 0x7564, 0xD67B, 0x7563, 0xD67C, 0x75CE, + 0xD67D, 0x75D2, 0xD67E, 0x75CF, 0xD6A1, 0x75CB, 0xD6A2, 0x75CC, 0xD6A3, 0x75D1, 0xD6A4, 0x75D0, 0xD6A5, 0x768F, 0xD6A6, 0x7689, + 0xD6A7, 0x76D3, 0xD6A8, 0x7739, 0xD6A9, 0x772F, 0xD6AA, 0x772D, 0xD6AB, 0x7731, 0xD6AC, 0x7732, 0xD6AD, 0x7734, 0xD6AE, 0x7733, + 0xD6AF, 0x773D, 0xD6B0, 0x7725, 0xD6B1, 0x773B, 0xD6B2, 0x7735, 0xD6B3, 0x7848, 0xD6B4, 0x7852, 0xD6B5, 0x7849, 0xD6B6, 0x784D, + 0xD6B7, 0x784A, 0xD6B8, 0x784C, 0xD6B9, 0x7826, 0xD6BA, 0x7845, 0xD6BB, 0x7850, 0xD6BC, 0x7964, 0xD6BD, 0x7967, 0xD6BE, 0x7969, + 0xD6BF, 0x796A, 0xD6C0, 0x7963, 0xD6C1, 0x796B, 0xD6C2, 0x7961, 0xD6C3, 0x79BB, 0xD6C4, 0x79FA, 0xD6C5, 0x79F8, 0xD6C6, 0x79F6, + 0xD6C7, 0x79F7, 0xD6C8, 0x7A8F, 0xD6C9, 0x7A94, 0xD6CA, 0x7A90, 0xD6CB, 0x7B35, 0xD6CC, 0x7B47, 0xD6CD, 0x7B34, 0xD6CE, 0x7B25, + 0xD6CF, 0x7B30, 0xD6D0, 0x7B22, 0xD6D1, 0x7B24, 0xD6D2, 0x7B33, 0xD6D3, 0x7B18, 0xD6D4, 0x7B2A, 0xD6D5, 0x7B1D, 0xD6D6, 0x7B31, + 0xD6D7, 0x7B2B, 0xD6D8, 0x7B2D, 0xD6D9, 0x7B2F, 0xD6DA, 0x7B32, 0xD6DB, 0x7B38, 0xD6DC, 0x7B1A, 0xD6DD, 0x7B23, 0xD6DE, 0x7C94, + 0xD6DF, 0x7C98, 0xD6E0, 0x7C96, 0xD6E1, 0x7CA3, 0xD6E2, 0x7D35, 0xD6E3, 0x7D3D, 0xD6E4, 0x7D38, 0xD6E5, 0x7D36, 0xD6E6, 0x7D3A, + 0xD6E7, 0x7D45, 0xD6E8, 0x7D2C, 0xD6E9, 0x7D29, 0xD6EA, 0x7D41, 0xD6EB, 0x7D47, 0xD6EC, 0x7D3E, 0xD6ED, 0x7D3F, 0xD6EE, 0x7D4A, + 0xD6EF, 0x7D3B, 0xD6F0, 0x7D28, 0xD6F1, 0x7F63, 0xD6F2, 0x7F95, 0xD6F3, 0x7F9C, 0xD6F4, 0x7F9D, 0xD6F5, 0x7F9B, 0xD6F6, 0x7FCA, + 0xD6F7, 0x7FCB, 0xD6F8, 0x7FCD, 0xD6F9, 0x7FD0, 0xD6FA, 0x7FD1, 0xD6FB, 0x7FC7, 0xD6FC, 0x7FCF, 0xD6FD, 0x7FC9, 0xD6FE, 0x801F, + 0xD740, 0x801E, 0xD741, 0x801B, 0xD742, 0x8047, 0xD743, 0x8043, 0xD744, 0x8048, 0xD745, 0x8118, 0xD746, 0x8125, 0xD747, 0x8119, + 0xD748, 0x811B, 0xD749, 0x812D, 0xD74A, 0x811F, 0xD74B, 0x812C, 0xD74C, 0x811E, 0xD74D, 0x8121, 0xD74E, 0x8115, 0xD74F, 0x8127, + 0xD750, 0x811D, 0xD751, 0x8122, 0xD752, 0x8211, 0xD753, 0x8238, 0xD754, 0x8233, 0xD755, 0x823A, 0xD756, 0x8234, 0xD757, 0x8232, + 0xD758, 0x8274, 0xD759, 0x8390, 0xD75A, 0x83A3, 0xD75B, 0x83A8, 0xD75C, 0x838D, 0xD75D, 0x837A, 0xD75E, 0x8373, 0xD75F, 0x83A4, + 0xD760, 0x8374, 0xD761, 0x838F, 0xD762, 0x8381, 0xD763, 0x8395, 0xD764, 0x8399, 0xD765, 0x8375, 0xD766, 0x8394, 0xD767, 0x83A9, + 0xD768, 0x837D, 0xD769, 0x8383, 0xD76A, 0x838C, 0xD76B, 0x839D, 0xD76C, 0x839B, 0xD76D, 0x83AA, 0xD76E, 0x838B, 0xD76F, 0x837E, + 0xD770, 0x83A5, 0xD771, 0x83AF, 0xD772, 0x8388, 0xD773, 0x8397, 0xD774, 0x83B0, 0xD775, 0x837F, 0xD776, 0x83A6, 0xD777, 0x8387, + 0xD778, 0x83AE, 0xD779, 0x8376, 0xD77A, 0x839A, 0xD77B, 0x8659, 0xD77C, 0x8656, 0xD77D, 0x86BF, 0xD77E, 0x86B7, 0xD7A1, 0x86C2, + 0xD7A2, 0x86C1, 0xD7A3, 0x86C5, 0xD7A4, 0x86BA, 0xD7A5, 0x86B0, 0xD7A6, 0x86C8, 0xD7A7, 0x86B9, 0xD7A8, 0x86B3, 0xD7A9, 0x86B8, + 0xD7AA, 0x86CC, 0xD7AB, 0x86B4, 0xD7AC, 0x86BB, 0xD7AD, 0x86BC, 0xD7AE, 0x86C3, 0xD7AF, 0x86BD, 0xD7B0, 0x86BE, 0xD7B1, 0x8852, + 0xD7B2, 0x8889, 0xD7B3, 0x8895, 0xD7B4, 0x88A8, 0xD7B5, 0x88A2, 0xD7B6, 0x88AA, 0xD7B7, 0x889A, 0xD7B8, 0x8891, 0xD7B9, 0x88A1, + 0xD7BA, 0x889F, 0xD7BB, 0x8898, 0xD7BC, 0x88A7, 0xD7BD, 0x8899, 0xD7BE, 0x889B, 0xD7BF, 0x8897, 0xD7C0, 0x88A4, 0xD7C1, 0x88AC, + 0xD7C2, 0x888C, 0xD7C3, 0x8893, 0xD7C4, 0x888E, 0xD7C5, 0x8982, 0xD7C6, 0x89D6, 0xD7C7, 0x89D9, 0xD7C8, 0x89D5, 0xD7C9, 0x8A30, + 0xD7CA, 0x8A27, 0xD7CB, 0x8A2C, 0xD7CC, 0x8A1E, 0xD7CD, 0x8C39, 0xD7CE, 0x8C3B, 0xD7CF, 0x8C5C, 0xD7D0, 0x8C5D, 0xD7D1, 0x8C7D, + 0xD7D2, 0x8CA5, 0xD7D3, 0x8D7D, 0xD7D4, 0x8D7B, 0xD7D5, 0x8D79, 0xD7D6, 0x8DBC, 0xD7D7, 0x8DC2, 0xD7D8, 0x8DB9, 0xD7D9, 0x8DBF, + 0xD7DA, 0x8DC1, 0xD7DB, 0x8ED8, 0xD7DC, 0x8EDE, 0xD7DD, 0x8EDD, 0xD7DE, 0x8EDC, 0xD7DF, 0x8ED7, 0xD7E0, 0x8EE0, 0xD7E1, 0x8EE1, + 0xD7E2, 0x9024, 0xD7E3, 0x900B, 0xD7E4, 0x9011, 0xD7E5, 0x901C, 0xD7E6, 0x900C, 0xD7E7, 0x9021, 0xD7E8, 0x90EF, 0xD7E9, 0x90EA, + 0xD7EA, 0x90F0, 0xD7EB, 0x90F4, 0xD7EC, 0x90F2, 0xD7ED, 0x90F3, 0xD7EE, 0x90D4, 0xD7EF, 0x90EB, 0xD7F0, 0x90EC, 0xD7F1, 0x90E9, + 0xD7F2, 0x9156, 0xD7F3, 0x9158, 0xD7F4, 0x915A, 0xD7F5, 0x9153, 0xD7F6, 0x9155, 0xD7F7, 0x91EC, 0xD7F8, 0x91F4, 0xD7F9, 0x91F1, + 0xD7FA, 0x91F3, 0xD7FB, 0x91F8, 0xD7FC, 0x91E4, 0xD7FD, 0x91F9, 0xD7FE, 0x91EA, 0xD840, 0x91EB, 0xD841, 0x91F7, 0xD842, 0x91E8, + 0xD843, 0x91EE, 0xD844, 0x957A, 0xD845, 0x9586, 0xD846, 0x9588, 0xD847, 0x967C, 0xD848, 0x966D, 0xD849, 0x966B, 0xD84A, 0x9671, + 0xD84B, 0x966F, 0xD84C, 0x96BF, 0xD84D, 0x976A, 0xD84E, 0x9804, 0xD84F, 0x98E5, 0xD850, 0x9997, 0xD851, 0x509B, 0xD852, 0x5095, + 0xD853, 0x5094, 0xD854, 0x509E, 0xD855, 0x508B, 0xD856, 0x50A3, 0xD857, 0x5083, 0xD858, 0x508C, 0xD859, 0x508E, 0xD85A, 0x509D, + 0xD85B, 0x5068, 0xD85C, 0x509C, 0xD85D, 0x5092, 0xD85E, 0x5082, 0xD85F, 0x5087, 0xD860, 0x515F, 0xD861, 0x51D4, 0xD862, 0x5312, + 0xD863, 0x5311, 0xD864, 0x53A4, 0xD865, 0x53A7, 0xD866, 0x5591, 0xD867, 0x55A8, 0xD868, 0x55A5, 0xD869, 0x55AD, 0xD86A, 0x5577, + 0xD86B, 0x5645, 0xD86C, 0x55A2, 0xD86D, 0x5593, 0xD86E, 0x5588, 0xD86F, 0x558F, 0xD870, 0x55B5, 0xD871, 0x5581, 0xD872, 0x55A3, + 0xD873, 0x5592, 0xD874, 0x55A4, 0xD875, 0x557D, 0xD876, 0x558C, 0xD877, 0x55A6, 0xD878, 0x557F, 0xD879, 0x5595, 0xD87A, 0x55A1, + 0xD87B, 0x558E, 0xD87C, 0x570C, 0xD87D, 0x5829, 0xD87E, 0x5837, 0xD8A1, 0x5819, 0xD8A2, 0x581E, 0xD8A3, 0x5827, 0xD8A4, 0x5823, + 0xD8A5, 0x5828, 0xD8A6, 0x57F5, 0xD8A7, 0x5848, 0xD8A8, 0x5825, 0xD8A9, 0x581C, 0xD8AA, 0x581B, 0xD8AB, 0x5833, 0xD8AC, 0x583F, + 0xD8AD, 0x5836, 0xD8AE, 0x582E, 0xD8AF, 0x5839, 0xD8B0, 0x5838, 0xD8B1, 0x582D, 0xD8B2, 0x582C, 0xD8B3, 0x583B, 0xD8B4, 0x5961, + 0xD8B5, 0x5AAF, 0xD8B6, 0x5A94, 0xD8B7, 0x5A9F, 0xD8B8, 0x5A7A, 0xD8B9, 0x5AA2, 0xD8BA, 0x5A9E, 0xD8BB, 0x5A78, 0xD8BC, 0x5AA6, + 0xD8BD, 0x5A7C, 0xD8BE, 0x5AA5, 0xD8BF, 0x5AAC, 0xD8C0, 0x5A95, 0xD8C1, 0x5AAE, 0xD8C2, 0x5A37, 0xD8C3, 0x5A84, 0xD8C4, 0x5A8A, + 0xD8C5, 0x5A97, 0xD8C6, 0x5A83, 0xD8C7, 0x5A8B, 0xD8C8, 0x5AA9, 0xD8C9, 0x5A7B, 0xD8CA, 0x5A7D, 0xD8CB, 0x5A8C, 0xD8CC, 0x5A9C, + 0xD8CD, 0x5A8F, 0xD8CE, 0x5A93, 0xD8CF, 0x5A9D, 0xD8D0, 0x5BEA, 0xD8D1, 0x5BCD, 0xD8D2, 0x5BCB, 0xD8D3, 0x5BD4, 0xD8D4, 0x5BD1, + 0xD8D5, 0x5BCA, 0xD8D6, 0x5BCE, 0xD8D7, 0x5C0C, 0xD8D8, 0x5C30, 0xD8D9, 0x5D37, 0xD8DA, 0x5D43, 0xD8DB, 0x5D6B, 0xD8DC, 0x5D41, + 0xD8DD, 0x5D4B, 0xD8DE, 0x5D3F, 0xD8DF, 0x5D35, 0xD8E0, 0x5D51, 0xD8E1, 0x5D4E, 0xD8E2, 0x5D55, 0xD8E3, 0x5D33, 0xD8E4, 0x5D3A, + 0xD8E5, 0x5D52, 0xD8E6, 0x5D3D, 0xD8E7, 0x5D31, 0xD8E8, 0x5D59, 0xD8E9, 0x5D42, 0xD8EA, 0x5D39, 0xD8EB, 0x5D49, 0xD8EC, 0x5D38, + 0xD8ED, 0x5D3C, 0xD8EE, 0x5D32, 0xD8EF, 0x5D36, 0xD8F0, 0x5D40, 0xD8F1, 0x5D45, 0xD8F2, 0x5E44, 0xD8F3, 0x5E41, 0xD8F4, 0x5F58, + 0xD8F5, 0x5FA6, 0xD8F6, 0x5FA5, 0xD8F7, 0x5FAB, 0xD8F8, 0x60C9, 0xD8F9, 0x60B9, 0xD8FA, 0x60CC, 0xD8FB, 0x60E2, 0xD8FC, 0x60CE, + 0xD8FD, 0x60C4, 0xD8FE, 0x6114, 0xD940, 0x60F2, 0xD941, 0x610A, 0xD942, 0x6116, 0xD943, 0x6105, 0xD944, 0x60F5, 0xD945, 0x6113, + 0xD946, 0x60F8, 0xD947, 0x60FC, 0xD948, 0x60FE, 0xD949, 0x60C1, 0xD94A, 0x6103, 0xD94B, 0x6118, 0xD94C, 0x611D, 0xD94D, 0x6110, + 0xD94E, 0x60FF, 0xD94F, 0x6104, 0xD950, 0x610B, 0xD951, 0x624A, 0xD952, 0x6394, 0xD953, 0x63B1, 0xD954, 0x63B0, 0xD955, 0x63CE, + 0xD956, 0x63E5, 0xD957, 0x63E8, 0xD958, 0x63EF, 0xD959, 0x63C3, 0xD95A, 0x649D, 0xD95B, 0x63F3, 0xD95C, 0x63CA, 0xD95D, 0x63E0, + 0xD95E, 0x63F6, 0xD95F, 0x63D5, 0xD960, 0x63F2, 0xD961, 0x63F5, 0xD962, 0x6461, 0xD963, 0x63DF, 0xD964, 0x63BE, 0xD965, 0x63DD, + 0xD966, 0x63DC, 0xD967, 0x63C4, 0xD968, 0x63D8, 0xD969, 0x63D3, 0xD96A, 0x63C2, 0xD96B, 0x63C7, 0xD96C, 0x63CC, 0xD96D, 0x63CB, + 0xD96E, 0x63C8, 0xD96F, 0x63F0, 0xD970, 0x63D7, 0xD971, 0x63D9, 0xD972, 0x6532, 0xD973, 0x6567, 0xD974, 0x656A, 0xD975, 0x6564, + 0xD976, 0x655C, 0xD977, 0x6568, 0xD978, 0x6565, 0xD979, 0x658C, 0xD97A, 0x659D, 0xD97B, 0x659E, 0xD97C, 0x65AE, 0xD97D, 0x65D0, + 0xD97E, 0x65D2, 0xD9A1, 0x667C, 0xD9A2, 0x666C, 0xD9A3, 0x667B, 0xD9A4, 0x6680, 0xD9A5, 0x6671, 0xD9A6, 0x6679, 0xD9A7, 0x666A, + 0xD9A8, 0x6672, 0xD9A9, 0x6701, 0xD9AA, 0x690C, 0xD9AB, 0x68D3, 0xD9AC, 0x6904, 0xD9AD, 0x68DC, 0xD9AE, 0x692A, 0xD9AF, 0x68EC, + 0xD9B0, 0x68EA, 0xD9B1, 0x68F1, 0xD9B2, 0x690F, 0xD9B3, 0x68D6, 0xD9B4, 0x68F7, 0xD9B5, 0x68EB, 0xD9B6, 0x68E4, 0xD9B7, 0x68F6, + 0xD9B8, 0x6913, 0xD9B9, 0x6910, 0xD9BA, 0x68F3, 0xD9BB, 0x68E1, 0xD9BC, 0x6907, 0xD9BD, 0x68CC, 0xD9BE, 0x6908, 0xD9BF, 0x6970, + 0xD9C0, 0x68B4, 0xD9C1, 0x6911, 0xD9C2, 0x68EF, 0xD9C3, 0x68C6, 0xD9C4, 0x6914, 0xD9C5, 0x68F8, 0xD9C6, 0x68D0, 0xD9C7, 0x68FD, + 0xD9C8, 0x68FC, 0xD9C9, 0x68E8, 0xD9CA, 0x690B, 0xD9CB, 0x690A, 0xD9CC, 0x6917, 0xD9CD, 0x68CE, 0xD9CE, 0x68C8, 0xD9CF, 0x68DD, + 0xD9D0, 0x68DE, 0xD9D1, 0x68E6, 0xD9D2, 0x68F4, 0xD9D3, 0x68D1, 0xD9D4, 0x6906, 0xD9D5, 0x68D4, 0xD9D6, 0x68E9, 0xD9D7, 0x6915, + 0xD9D8, 0x6925, 0xD9D9, 0x68C7, 0xD9DA, 0x6B39, 0xD9DB, 0x6B3B, 0xD9DC, 0x6B3F, 0xD9DD, 0x6B3C, 0xD9DE, 0x6B94, 0xD9DF, 0x6B97, + 0xD9E0, 0x6B99, 0xD9E1, 0x6B95, 0xD9E2, 0x6BBD, 0xD9E3, 0x6BF0, 0xD9E4, 0x6BF2, 0xD9E5, 0x6BF3, 0xD9E6, 0x6C30, 0xD9E7, 0x6DFC, + 0xD9E8, 0x6E46, 0xD9E9, 0x6E47, 0xD9EA, 0x6E1F, 0xD9EB, 0x6E49, 0xD9EC, 0x6E88, 0xD9ED, 0x6E3C, 0xD9EE, 0x6E3D, 0xD9EF, 0x6E45, + 0xD9F0, 0x6E62, 0xD9F1, 0x6E2B, 0xD9F2, 0x6E3F, 0xD9F3, 0x6E41, 0xD9F4, 0x6E5D, 0xD9F5, 0x6E73, 0xD9F6, 0x6E1C, 0xD9F7, 0x6E33, + 0xD9F8, 0x6E4B, 0xD9F9, 0x6E40, 0xD9FA, 0x6E51, 0xD9FB, 0x6E3B, 0xD9FC, 0x6E03, 0xD9FD, 0x6E2E, 0xD9FE, 0x6E5E, 0xDA40, 0x6E68, + 0xDA41, 0x6E5C, 0xDA42, 0x6E61, 0xDA43, 0x6E31, 0xDA44, 0x6E28, 0xDA45, 0x6E60, 0xDA46, 0x6E71, 0xDA47, 0x6E6B, 0xDA48, 0x6E39, + 0xDA49, 0x6E22, 0xDA4A, 0x6E30, 0xDA4B, 0x6E53, 0xDA4C, 0x6E65, 0xDA4D, 0x6E27, 0xDA4E, 0x6E78, 0xDA4F, 0x6E64, 0xDA50, 0x6E77, + 0xDA51, 0x6E55, 0xDA52, 0x6E79, 0xDA53, 0x6E52, 0xDA54, 0x6E66, 0xDA55, 0x6E35, 0xDA56, 0x6E36, 0xDA57, 0x6E5A, 0xDA58, 0x7120, + 0xDA59, 0x711E, 0xDA5A, 0x712F, 0xDA5B, 0x70FB, 0xDA5C, 0x712E, 0xDA5D, 0x7131, 0xDA5E, 0x7123, 0xDA5F, 0x7125, 0xDA60, 0x7122, + 0xDA61, 0x7132, 0xDA62, 0x711F, 0xDA63, 0x7128, 0xDA64, 0x713A, 0xDA65, 0x711B, 0xDA66, 0x724B, 0xDA67, 0x725A, 0xDA68, 0x7288, + 0xDA69, 0x7289, 0xDA6A, 0x7286, 0xDA6B, 0x7285, 0xDA6C, 0x728B, 0xDA6D, 0x7312, 0xDA6E, 0x730B, 0xDA6F, 0x7330, 0xDA70, 0x7322, + 0xDA71, 0x7331, 0xDA72, 0x7333, 0xDA73, 0x7327, 0xDA74, 0x7332, 0xDA75, 0x732D, 0xDA76, 0x7326, 0xDA77, 0x7323, 0xDA78, 0x7335, + 0xDA79, 0x730C, 0xDA7A, 0x742E, 0xDA7B, 0x742C, 0xDA7C, 0x7430, 0xDA7D, 0x742B, 0xDA7E, 0x7416, 0xDAA1, 0x741A, 0xDAA2, 0x7421, + 0xDAA3, 0x742D, 0xDAA4, 0x7431, 0xDAA5, 0x7424, 0xDAA6, 0x7423, 0xDAA7, 0x741D, 0xDAA8, 0x7429, 0xDAA9, 0x7420, 0xDAAA, 0x7432, + 0xDAAB, 0x74FB, 0xDAAC, 0x752F, 0xDAAD, 0x756F, 0xDAAE, 0x756C, 0xDAAF, 0x75E7, 0xDAB0, 0x75DA, 0xDAB1, 0x75E1, 0xDAB2, 0x75E6, + 0xDAB3, 0x75DD, 0xDAB4, 0x75DF, 0xDAB5, 0x75E4, 0xDAB6, 0x75D7, 0xDAB7, 0x7695, 0xDAB8, 0x7692, 0xDAB9, 0x76DA, 0xDABA, 0x7746, + 0xDABB, 0x7747, 0xDABC, 0x7744, 0xDABD, 0x774D, 0xDABE, 0x7745, 0xDABF, 0x774A, 0xDAC0, 0x774E, 0xDAC1, 0x774B, 0xDAC2, 0x774C, + 0xDAC3, 0x77DE, 0xDAC4, 0x77EC, 0xDAC5, 0x7860, 0xDAC6, 0x7864, 0xDAC7, 0x7865, 0xDAC8, 0x785C, 0xDAC9, 0x786D, 0xDACA, 0x7871, + 0xDACB, 0x786A, 0xDACC, 0x786E, 0xDACD, 0x7870, 0xDACE, 0x7869, 0xDACF, 0x7868, 0xDAD0, 0x785E, 0xDAD1, 0x7862, 0xDAD2, 0x7974, + 0xDAD3, 0x7973, 0xDAD4, 0x7972, 0xDAD5, 0x7970, 0xDAD6, 0x7A02, 0xDAD7, 0x7A0A, 0xDAD8, 0x7A03, 0xDAD9, 0x7A0C, 0xDADA, 0x7A04, + 0xDADB, 0x7A99, 0xDADC, 0x7AE6, 0xDADD, 0x7AE4, 0xDADE, 0x7B4A, 0xDADF, 0x7B3B, 0xDAE0, 0x7B44, 0xDAE1, 0x7B48, 0xDAE2, 0x7B4C, + 0xDAE3, 0x7B4E, 0xDAE4, 0x7B40, 0xDAE5, 0x7B58, 0xDAE6, 0x7B45, 0xDAE7, 0x7CA2, 0xDAE8, 0x7C9E, 0xDAE9, 0x7CA8, 0xDAEA, 0x7CA1, + 0xDAEB, 0x7D58, 0xDAEC, 0x7D6F, 0xDAED, 0x7D63, 0xDAEE, 0x7D53, 0xDAEF, 0x7D56, 0xDAF0, 0x7D67, 0xDAF1, 0x7D6A, 0xDAF2, 0x7D4F, + 0xDAF3, 0x7D6D, 0xDAF4, 0x7D5C, 0xDAF5, 0x7D6B, 0xDAF6, 0x7D52, 0xDAF7, 0x7D54, 0xDAF8, 0x7D69, 0xDAF9, 0x7D51, 0xDAFA, 0x7D5F, + 0xDAFB, 0x7D4E, 0xDAFC, 0x7F3E, 0xDAFD, 0x7F3F, 0xDAFE, 0x7F65, 0xDB40, 0x7F66, 0xDB41, 0x7FA2, 0xDB42, 0x7FA0, 0xDB43, 0x7FA1, + 0xDB44, 0x7FD7, 0xDB45, 0x8051, 0xDB46, 0x804F, 0xDB47, 0x8050, 0xDB48, 0x80FE, 0xDB49, 0x80D4, 0xDB4A, 0x8143, 0xDB4B, 0x814A, + 0xDB4C, 0x8152, 0xDB4D, 0x814F, 0xDB4E, 0x8147, 0xDB4F, 0x813D, 0xDB50, 0x814D, 0xDB51, 0x813A, 0xDB52, 0x81E6, 0xDB53, 0x81EE, + 0xDB54, 0x81F7, 0xDB55, 0x81F8, 0xDB56, 0x81F9, 0xDB57, 0x8204, 0xDB58, 0x823C, 0xDB59, 0x823D, 0xDB5A, 0x823F, 0xDB5B, 0x8275, + 0xDB5C, 0x833B, 0xDB5D, 0x83CF, 0xDB5E, 0x83F9, 0xDB5F, 0x8423, 0xDB60, 0x83C0, 0xDB61, 0x83E8, 0xDB62, 0x8412, 0xDB63, 0x83E7, + 0xDB64, 0x83E4, 0xDB65, 0x83FC, 0xDB66, 0x83F6, 0xDB67, 0x8410, 0xDB68, 0x83C6, 0xDB69, 0x83C8, 0xDB6A, 0x83EB, 0xDB6B, 0x83E3, + 0xDB6C, 0x83BF, 0xDB6D, 0x8401, 0xDB6E, 0x83DD, 0xDB6F, 0x83E5, 0xDB70, 0x83D8, 0xDB71, 0x83FF, 0xDB72, 0x83E1, 0xDB73, 0x83CB, + 0xDB74, 0x83CE, 0xDB75, 0x83D6, 0xDB76, 0x83F5, 0xDB77, 0x83C9, 0xDB78, 0x8409, 0xDB79, 0x840F, 0xDB7A, 0x83DE, 0xDB7B, 0x8411, + 0xDB7C, 0x8406, 0xDB7D, 0x83C2, 0xDB7E, 0x83F3, 0xDBA1, 0x83D5, 0xDBA2, 0x83FA, 0xDBA3, 0x83C7, 0xDBA4, 0x83D1, 0xDBA5, 0x83EA, + 0xDBA6, 0x8413, 0xDBA7, 0x83C3, 0xDBA8, 0x83EC, 0xDBA9, 0x83EE, 0xDBAA, 0x83C4, 0xDBAB, 0x83FB, 0xDBAC, 0x83D7, 0xDBAD, 0x83E2, + 0xDBAE, 0x841B, 0xDBAF, 0x83DB, 0xDBB0, 0x83FE, 0xDBB1, 0x86D8, 0xDBB2, 0x86E2, 0xDBB3, 0x86E6, 0xDBB4, 0x86D3, 0xDBB5, 0x86E3, + 0xDBB6, 0x86DA, 0xDBB7, 0x86EA, 0xDBB8, 0x86DD, 0xDBB9, 0x86EB, 0xDBBA, 0x86DC, 0xDBBB, 0x86EC, 0xDBBC, 0x86E9, 0xDBBD, 0x86D7, + 0xDBBE, 0x86E8, 0xDBBF, 0x86D1, 0xDBC0, 0x8848, 0xDBC1, 0x8856, 0xDBC2, 0x8855, 0xDBC3, 0x88BA, 0xDBC4, 0x88D7, 0xDBC5, 0x88B9, + 0xDBC6, 0x88B8, 0xDBC7, 0x88C0, 0xDBC8, 0x88BE, 0xDBC9, 0x88B6, 0xDBCA, 0x88BC, 0xDBCB, 0x88B7, 0xDBCC, 0x88BD, 0xDBCD, 0x88B2, + 0xDBCE, 0x8901, 0xDBCF, 0x88C9, 0xDBD0, 0x8995, 0xDBD1, 0x8998, 0xDBD2, 0x8997, 0xDBD3, 0x89DD, 0xDBD4, 0x89DA, 0xDBD5, 0x89DB, + 0xDBD6, 0x8A4E, 0xDBD7, 0x8A4D, 0xDBD8, 0x8A39, 0xDBD9, 0x8A59, 0xDBDA, 0x8A40, 0xDBDB, 0x8A57, 0xDBDC, 0x8A58, 0xDBDD, 0x8A44, + 0xDBDE, 0x8A45, 0xDBDF, 0x8A52, 0xDBE0, 0x8A48, 0xDBE1, 0x8A51, 0xDBE2, 0x8A4A, 0xDBE3, 0x8A4C, 0xDBE4, 0x8A4F, 0xDBE5, 0x8C5F, + 0xDBE6, 0x8C81, 0xDBE7, 0x8C80, 0xDBE8, 0x8CBA, 0xDBE9, 0x8CBE, 0xDBEA, 0x8CB0, 0xDBEB, 0x8CB9, 0xDBEC, 0x8CB5, 0xDBED, 0x8D84, + 0xDBEE, 0x8D80, 0xDBEF, 0x8D89, 0xDBF0, 0x8DD8, 0xDBF1, 0x8DD3, 0xDBF2, 0x8DCD, 0xDBF3, 0x8DC7, 0xDBF4, 0x8DD6, 0xDBF5, 0x8DDC, + 0xDBF6, 0x8DCF, 0xDBF7, 0x8DD5, 0xDBF8, 0x8DD9, 0xDBF9, 0x8DC8, 0xDBFA, 0x8DD7, 0xDBFB, 0x8DC5, 0xDBFC, 0x8EEF, 0xDBFD, 0x8EF7, + 0xDBFE, 0x8EFA, 0xDC40, 0x8EF9, 0xDC41, 0x8EE6, 0xDC42, 0x8EEE, 0xDC43, 0x8EE5, 0xDC44, 0x8EF5, 0xDC45, 0x8EE7, 0xDC46, 0x8EE8, + 0xDC47, 0x8EF6, 0xDC48, 0x8EEB, 0xDC49, 0x8EF1, 0xDC4A, 0x8EEC, 0xDC4B, 0x8EF4, 0xDC4C, 0x8EE9, 0xDC4D, 0x902D, 0xDC4E, 0x9034, + 0xDC4F, 0x902F, 0xDC50, 0x9106, 0xDC51, 0x912C, 0xDC52, 0x9104, 0xDC53, 0x90FF, 0xDC54, 0x90FC, 0xDC55, 0x9108, 0xDC56, 0x90F9, + 0xDC57, 0x90FB, 0xDC58, 0x9101, 0xDC59, 0x9100, 0xDC5A, 0x9107, 0xDC5B, 0x9105, 0xDC5C, 0x9103, 0xDC5D, 0x9161, 0xDC5E, 0x9164, + 0xDC5F, 0x915F, 0xDC60, 0x9162, 0xDC61, 0x9160, 0xDC62, 0x9201, 0xDC63, 0x920A, 0xDC64, 0x9225, 0xDC65, 0x9203, 0xDC66, 0x921A, + 0xDC67, 0x9226, 0xDC68, 0x920F, 0xDC69, 0x920C, 0xDC6A, 0x9200, 0xDC6B, 0x9212, 0xDC6C, 0x91FF, 0xDC6D, 0x91FD, 0xDC6E, 0x9206, + 0xDC6F, 0x9204, 0xDC70, 0x9227, 0xDC71, 0x9202, 0xDC72, 0x921C, 0xDC73, 0x9224, 0xDC74, 0x9219, 0xDC75, 0x9217, 0xDC76, 0x9205, + 0xDC77, 0x9216, 0xDC78, 0x957B, 0xDC79, 0x958D, 0xDC7A, 0x958C, 0xDC7B, 0x9590, 0xDC7C, 0x9687, 0xDC7D, 0x967E, 0xDC7E, 0x9688, + 0xDCA1, 0x9689, 0xDCA2, 0x9683, 0xDCA3, 0x9680, 0xDCA4, 0x96C2, 0xDCA5, 0x96C8, 0xDCA6, 0x96C3, 0xDCA7, 0x96F1, 0xDCA8, 0x96F0, + 0xDCA9, 0x976C, 0xDCAA, 0x9770, 0xDCAB, 0x976E, 0xDCAC, 0x9807, 0xDCAD, 0x98A9, 0xDCAE, 0x98EB, 0xDCAF, 0x9CE6, 0xDCB0, 0x9EF9, + 0xDCB1, 0x4E83, 0xDCB2, 0x4E84, 0xDCB3, 0x4EB6, 0xDCB4, 0x50BD, 0xDCB5, 0x50BF, 0xDCB6, 0x50C6, 0xDCB7, 0x50AE, 0xDCB8, 0x50C4, + 0xDCB9, 0x50CA, 0xDCBA, 0x50B4, 0xDCBB, 0x50C8, 0xDCBC, 0x50C2, 0xDCBD, 0x50B0, 0xDCBE, 0x50C1, 0xDCBF, 0x50BA, 0xDCC0, 0x50B1, + 0xDCC1, 0x50CB, 0xDCC2, 0x50C9, 0xDCC3, 0x50B6, 0xDCC4, 0x50B8, 0xDCC5, 0x51D7, 0xDCC6, 0x527A, 0xDCC7, 0x5278, 0xDCC8, 0x527B, + 0xDCC9, 0x527C, 0xDCCA, 0x55C3, 0xDCCB, 0x55DB, 0xDCCC, 0x55CC, 0xDCCD, 0x55D0, 0xDCCE, 0x55CB, 0xDCCF, 0x55CA, 0xDCD0, 0x55DD, + 0xDCD1, 0x55C0, 0xDCD2, 0x55D4, 0xDCD3, 0x55C4, 0xDCD4, 0x55E9, 0xDCD5, 0x55BF, 0xDCD6, 0x55D2, 0xDCD7, 0x558D, 0xDCD8, 0x55CF, + 0xDCD9, 0x55D5, 0xDCDA, 0x55E2, 0xDCDB, 0x55D6, 0xDCDC, 0x55C8, 0xDCDD, 0x55F2, 0xDCDE, 0x55CD, 0xDCDF, 0x55D9, 0xDCE0, 0x55C2, + 0xDCE1, 0x5714, 0xDCE2, 0x5853, 0xDCE3, 0x5868, 0xDCE4, 0x5864, 0xDCE5, 0x584F, 0xDCE6, 0x584D, 0xDCE7, 0x5849, 0xDCE8, 0x586F, + 0xDCE9, 0x5855, 0xDCEA, 0x584E, 0xDCEB, 0x585D, 0xDCEC, 0x5859, 0xDCED, 0x5865, 0xDCEE, 0x585B, 0xDCEF, 0x583D, 0xDCF0, 0x5863, + 0xDCF1, 0x5871, 0xDCF2, 0x58FC, 0xDCF3, 0x5AC7, 0xDCF4, 0x5AC4, 0xDCF5, 0x5ACB, 0xDCF6, 0x5ABA, 0xDCF7, 0x5AB8, 0xDCF8, 0x5AB1, + 0xDCF9, 0x5AB5, 0xDCFA, 0x5AB0, 0xDCFB, 0x5ABF, 0xDCFC, 0x5AC8, 0xDCFD, 0x5ABB, 0xDCFE, 0x5AC6, 0xDD40, 0x5AB7, 0xDD41, 0x5AC0, + 0xDD42, 0x5ACA, 0xDD43, 0x5AB4, 0xDD44, 0x5AB6, 0xDD45, 0x5ACD, 0xDD46, 0x5AB9, 0xDD47, 0x5A90, 0xDD48, 0x5BD6, 0xDD49, 0x5BD8, + 0xDD4A, 0x5BD9, 0xDD4B, 0x5C1F, 0xDD4C, 0x5C33, 0xDD4D, 0x5D71, 0xDD4E, 0x5D63, 0xDD4F, 0x5D4A, 0xDD50, 0x5D65, 0xDD51, 0x5D72, + 0xDD52, 0x5D6C, 0xDD53, 0x5D5E, 0xDD54, 0x5D68, 0xDD55, 0x5D67, 0xDD56, 0x5D62, 0xDD57, 0x5DF0, 0xDD58, 0x5E4F, 0xDD59, 0x5E4E, + 0xDD5A, 0x5E4A, 0xDD5B, 0x5E4D, 0xDD5C, 0x5E4B, 0xDD5D, 0x5EC5, 0xDD5E, 0x5ECC, 0xDD5F, 0x5EC6, 0xDD60, 0x5ECB, 0xDD61, 0x5EC7, + 0xDD62, 0x5F40, 0xDD63, 0x5FAF, 0xDD64, 0x5FAD, 0xDD65, 0x60F7, 0xDD66, 0x6149, 0xDD67, 0x614A, 0xDD68, 0x612B, 0xDD69, 0x6145, + 0xDD6A, 0x6136, 0xDD6B, 0x6132, 0xDD6C, 0x612E, 0xDD6D, 0x6146, 0xDD6E, 0x612F, 0xDD6F, 0x614F, 0xDD70, 0x6129, 0xDD71, 0x6140, + 0xDD72, 0x6220, 0xDD73, 0x9168, 0xDD74, 0x6223, 0xDD75, 0x6225, 0xDD76, 0x6224, 0xDD77, 0x63C5, 0xDD78, 0x63F1, 0xDD79, 0x63EB, + 0xDD7A, 0x6410, 0xDD7B, 0x6412, 0xDD7C, 0x6409, 0xDD7D, 0x6420, 0xDD7E, 0x6424, 0xDDA1, 0x6433, 0xDDA2, 0x6443, 0xDDA3, 0x641F, + 0xDDA4, 0x6415, 0xDDA5, 0x6418, 0xDDA6, 0x6439, 0xDDA7, 0x6437, 0xDDA8, 0x6422, 0xDDA9, 0x6423, 0xDDAA, 0x640C, 0xDDAB, 0x6426, + 0xDDAC, 0x6430, 0xDDAD, 0x6428, 0xDDAE, 0x6441, 0xDDAF, 0x6435, 0xDDB0, 0x642F, 0xDDB1, 0x640A, 0xDDB2, 0x641A, 0xDDB3, 0x6440, + 0xDDB4, 0x6425, 0xDDB5, 0x6427, 0xDDB6, 0x640B, 0xDDB7, 0x63E7, 0xDDB8, 0x641B, 0xDDB9, 0x642E, 0xDDBA, 0x6421, 0xDDBB, 0x640E, + 0xDDBC, 0x656F, 0xDDBD, 0x6592, 0xDDBE, 0x65D3, 0xDDBF, 0x6686, 0xDDC0, 0x668C, 0xDDC1, 0x6695, 0xDDC2, 0x6690, 0xDDC3, 0x668B, + 0xDDC4, 0x668A, 0xDDC5, 0x6699, 0xDDC6, 0x6694, 0xDDC7, 0x6678, 0xDDC8, 0x6720, 0xDDC9, 0x6966, 0xDDCA, 0x695F, 0xDDCB, 0x6938, + 0xDDCC, 0x694E, 0xDDCD, 0x6962, 0xDDCE, 0x6971, 0xDDCF, 0x693F, 0xDDD0, 0x6945, 0xDDD1, 0x696A, 0xDDD2, 0x6939, 0xDDD3, 0x6942, + 0xDDD4, 0x6957, 0xDDD5, 0x6959, 0xDDD6, 0x697A, 0xDDD7, 0x6948, 0xDDD8, 0x6949, 0xDDD9, 0x6935, 0xDDDA, 0x696C, 0xDDDB, 0x6933, + 0xDDDC, 0x693D, 0xDDDD, 0x6965, 0xDDDE, 0x68F0, 0xDDDF, 0x6978, 0xDDE0, 0x6934, 0xDDE1, 0x6969, 0xDDE2, 0x6940, 0xDDE3, 0x696F, + 0xDDE4, 0x6944, 0xDDE5, 0x6976, 0xDDE6, 0x6958, 0xDDE7, 0x6941, 0xDDE8, 0x6974, 0xDDE9, 0x694C, 0xDDEA, 0x693B, 0xDDEB, 0x694B, + 0xDDEC, 0x6937, 0xDDED, 0x695C, 0xDDEE, 0x694F, 0xDDEF, 0x6951, 0xDDF0, 0x6932, 0xDDF1, 0x6952, 0xDDF2, 0x692F, 0xDDF3, 0x697B, + 0xDDF4, 0x693C, 0xDDF5, 0x6B46, 0xDDF6, 0x6B45, 0xDDF7, 0x6B43, 0xDDF8, 0x6B42, 0xDDF9, 0x6B48, 0xDDFA, 0x6B41, 0xDDFB, 0x6B9B, + 0xDDFC, 0xFA0D, 0xDDFD, 0x6BFB, 0xDDFE, 0x6BFC, 0xDE40, 0x6BF9, 0xDE41, 0x6BF7, 0xDE42, 0x6BF8, 0xDE43, 0x6E9B, 0xDE44, 0x6ED6, + 0xDE45, 0x6EC8, 0xDE46, 0x6E8F, 0xDE47, 0x6EC0, 0xDE48, 0x6E9F, 0xDE49, 0x6E93, 0xDE4A, 0x6E94, 0xDE4B, 0x6EA0, 0xDE4C, 0x6EB1, + 0xDE4D, 0x6EB9, 0xDE4E, 0x6EC6, 0xDE4F, 0x6ED2, 0xDE50, 0x6EBD, 0xDE51, 0x6EC1, 0xDE52, 0x6E9E, 0xDE53, 0x6EC9, 0xDE54, 0x6EB7, + 0xDE55, 0x6EB0, 0xDE56, 0x6ECD, 0xDE57, 0x6EA6, 0xDE58, 0x6ECF, 0xDE59, 0x6EB2, 0xDE5A, 0x6EBE, 0xDE5B, 0x6EC3, 0xDE5C, 0x6EDC, + 0xDE5D, 0x6ED8, 0xDE5E, 0x6E99, 0xDE5F, 0x6E92, 0xDE60, 0x6E8E, 0xDE61, 0x6E8D, 0xDE62, 0x6EA4, 0xDE63, 0x6EA1, 0xDE64, 0x6EBF, + 0xDE65, 0x6EB3, 0xDE66, 0x6ED0, 0xDE67, 0x6ECA, 0xDE68, 0x6E97, 0xDE69, 0x6EAE, 0xDE6A, 0x6EA3, 0xDE6B, 0x7147, 0xDE6C, 0x7154, + 0xDE6D, 0x7152, 0xDE6E, 0x7163, 0xDE6F, 0x7160, 0xDE70, 0x7141, 0xDE71, 0x715D, 0xDE72, 0x7162, 0xDE73, 0x7172, 0xDE74, 0x7178, + 0xDE75, 0x716A, 0xDE76, 0x7161, 0xDE77, 0x7142, 0xDE78, 0x7158, 0xDE79, 0x7143, 0xDE7A, 0x714B, 0xDE7B, 0x7170, 0xDE7C, 0x715F, + 0xDE7D, 0x7150, 0xDE7E, 0x7153, 0xDEA1, 0x7144, 0xDEA2, 0x714D, 0xDEA3, 0x715A, 0xDEA4, 0x724F, 0xDEA5, 0x728D, 0xDEA6, 0x728C, + 0xDEA7, 0x7291, 0xDEA8, 0x7290, 0xDEA9, 0x728E, 0xDEAA, 0x733C, 0xDEAB, 0x7342, 0xDEAC, 0x733B, 0xDEAD, 0x733A, 0xDEAE, 0x7340, + 0xDEAF, 0x734A, 0xDEB0, 0x7349, 0xDEB1, 0x7444, 0xDEB2, 0x744A, 0xDEB3, 0x744B, 0xDEB4, 0x7452, 0xDEB5, 0x7451, 0xDEB6, 0x7457, + 0xDEB7, 0x7440, 0xDEB8, 0x744F, 0xDEB9, 0x7450, 0xDEBA, 0x744E, 0xDEBB, 0x7442, 0xDEBC, 0x7446, 0xDEBD, 0x744D, 0xDEBE, 0x7454, + 0xDEBF, 0x74E1, 0xDEC0, 0x74FF, 0xDEC1, 0x74FE, 0xDEC2, 0x74FD, 0xDEC3, 0x751D, 0xDEC4, 0x7579, 0xDEC5, 0x7577, 0xDEC6, 0x6983, + 0xDEC7, 0x75EF, 0xDEC8, 0x760F, 0xDEC9, 0x7603, 0xDECA, 0x75F7, 0xDECB, 0x75FE, 0xDECC, 0x75FC, 0xDECD, 0x75F9, 0xDECE, 0x75F8, + 0xDECF, 0x7610, 0xDED0, 0x75FB, 0xDED1, 0x75F6, 0xDED2, 0x75ED, 0xDED3, 0x75F5, 0xDED4, 0x75FD, 0xDED5, 0x7699, 0xDED6, 0x76B5, + 0xDED7, 0x76DD, 0xDED8, 0x7755, 0xDED9, 0x775F, 0xDEDA, 0x7760, 0xDEDB, 0x7752, 0xDEDC, 0x7756, 0xDEDD, 0x775A, 0xDEDE, 0x7769, + 0xDEDF, 0x7767, 0xDEE0, 0x7754, 0xDEE1, 0x7759, 0xDEE2, 0x776D, 0xDEE3, 0x77E0, 0xDEE4, 0x7887, 0xDEE5, 0x789A, 0xDEE6, 0x7894, + 0xDEE7, 0x788F, 0xDEE8, 0x7884, 0xDEE9, 0x7895, 0xDEEA, 0x7885, 0xDEEB, 0x7886, 0xDEEC, 0x78A1, 0xDEED, 0x7883, 0xDEEE, 0x7879, + 0xDEEF, 0x7899, 0xDEF0, 0x7880, 0xDEF1, 0x7896, 0xDEF2, 0x787B, 0xDEF3, 0x797C, 0xDEF4, 0x7982, 0xDEF5, 0x797D, 0xDEF6, 0x7979, + 0xDEF7, 0x7A11, 0xDEF8, 0x7A18, 0xDEF9, 0x7A19, 0xDEFA, 0x7A12, 0xDEFB, 0x7A17, 0xDEFC, 0x7A15, 0xDEFD, 0x7A22, 0xDEFE, 0x7A13, + 0xDF40, 0x7A1B, 0xDF41, 0x7A10, 0xDF42, 0x7AA3, 0xDF43, 0x7AA2, 0xDF44, 0x7A9E, 0xDF45, 0x7AEB, 0xDF46, 0x7B66, 0xDF47, 0x7B64, + 0xDF48, 0x7B6D, 0xDF49, 0x7B74, 0xDF4A, 0x7B69, 0xDF4B, 0x7B72, 0xDF4C, 0x7B65, 0xDF4D, 0x7B73, 0xDF4E, 0x7B71, 0xDF4F, 0x7B70, + 0xDF50, 0x7B61, 0xDF51, 0x7B78, 0xDF52, 0x7B76, 0xDF53, 0x7B63, 0xDF54, 0x7CB2, 0xDF55, 0x7CB4, 0xDF56, 0x7CAF, 0xDF57, 0x7D88, + 0xDF58, 0x7D86, 0xDF59, 0x7D80, 0xDF5A, 0x7D8D, 0xDF5B, 0x7D7F, 0xDF5C, 0x7D85, 0xDF5D, 0x7D7A, 0xDF5E, 0x7D8E, 0xDF5F, 0x7D7B, + 0xDF60, 0x7D83, 0xDF61, 0x7D7C, 0xDF62, 0x7D8C, 0xDF63, 0x7D94, 0xDF64, 0x7D84, 0xDF65, 0x7D7D, 0xDF66, 0x7D92, 0xDF67, 0x7F6D, + 0xDF68, 0x7F6B, 0xDF69, 0x7F67, 0xDF6A, 0x7F68, 0xDF6B, 0x7F6C, 0xDF6C, 0x7FA6, 0xDF6D, 0x7FA5, 0xDF6E, 0x7FA7, 0xDF6F, 0x7FDB, + 0xDF70, 0x7FDC, 0xDF71, 0x8021, 0xDF72, 0x8164, 0xDF73, 0x8160, 0xDF74, 0x8177, 0xDF75, 0x815C, 0xDF76, 0x8169, 0xDF77, 0x815B, + 0xDF78, 0x8162, 0xDF79, 0x8172, 0xDF7A, 0x6721, 0xDF7B, 0x815E, 0xDF7C, 0x8176, 0xDF7D, 0x8167, 0xDF7E, 0x816F, 0xDFA1, 0x8144, + 0xDFA2, 0x8161, 0xDFA3, 0x821D, 0xDFA4, 0x8249, 0xDFA5, 0x8244, 0xDFA6, 0x8240, 0xDFA7, 0x8242, 0xDFA8, 0x8245, 0xDFA9, 0x84F1, + 0xDFAA, 0x843F, 0xDFAB, 0x8456, 0xDFAC, 0x8476, 0xDFAD, 0x8479, 0xDFAE, 0x848F, 0xDFAF, 0x848D, 0xDFB0, 0x8465, 0xDFB1, 0x8451, + 0xDFB2, 0x8440, 0xDFB3, 0x8486, 0xDFB4, 0x8467, 0xDFB5, 0x8430, 0xDFB6, 0x844D, 0xDFB7, 0x847D, 0xDFB8, 0x845A, 0xDFB9, 0x8459, + 0xDFBA, 0x8474, 0xDFBB, 0x8473, 0xDFBC, 0x845D, 0xDFBD, 0x8507, 0xDFBE, 0x845E, 0xDFBF, 0x8437, 0xDFC0, 0x843A, 0xDFC1, 0x8434, + 0xDFC2, 0x847A, 0xDFC3, 0x8443, 0xDFC4, 0x8478, 0xDFC5, 0x8432, 0xDFC6, 0x8445, 0xDFC7, 0x8429, 0xDFC8, 0x83D9, 0xDFC9, 0x844B, + 0xDFCA, 0x842F, 0xDFCB, 0x8442, 0xDFCC, 0x842D, 0xDFCD, 0x845F, 0xDFCE, 0x8470, 0xDFCF, 0x8439, 0xDFD0, 0x844E, 0xDFD1, 0x844C, + 0xDFD2, 0x8452, 0xDFD3, 0x846F, 0xDFD4, 0x84C5, 0xDFD5, 0x848E, 0xDFD6, 0x843B, 0xDFD7, 0x8447, 0xDFD8, 0x8436, 0xDFD9, 0x8433, + 0xDFDA, 0x8468, 0xDFDB, 0x847E, 0xDFDC, 0x8444, 0xDFDD, 0x842B, 0xDFDE, 0x8460, 0xDFDF, 0x8454, 0xDFE0, 0x846E, 0xDFE1, 0x8450, + 0xDFE2, 0x870B, 0xDFE3, 0x8704, 0xDFE4, 0x86F7, 0xDFE5, 0x870C, 0xDFE6, 0x86FA, 0xDFE7, 0x86D6, 0xDFE8, 0x86F5, 0xDFE9, 0x874D, + 0xDFEA, 0x86F8, 0xDFEB, 0x870E, 0xDFEC, 0x8709, 0xDFED, 0x8701, 0xDFEE, 0x86F6, 0xDFEF, 0x870D, 0xDFF0, 0x8705, 0xDFF1, 0x88D6, + 0xDFF2, 0x88CB, 0xDFF3, 0x88CD, 0xDFF4, 0x88CE, 0xDFF5, 0x88DE, 0xDFF6, 0x88DB, 0xDFF7, 0x88DA, 0xDFF8, 0x88CC, 0xDFF9, 0x88D0, + 0xDFFA, 0x8985, 0xDFFB, 0x899B, 0xDFFC, 0x89DF, 0xDFFD, 0x89E5, 0xDFFE, 0x89E4, 0xE040, 0x89E1, 0xE041, 0x89E0, 0xE042, 0x89E2, + 0xE043, 0x89DC, 0xE044, 0x89E6, 0xE045, 0x8A76, 0xE046, 0x8A86, 0xE047, 0x8A7F, 0xE048, 0x8A61, 0xE049, 0x8A3F, 0xE04A, 0x8A77, + 0xE04B, 0x8A82, 0xE04C, 0x8A84, 0xE04D, 0x8A75, 0xE04E, 0x8A83, 0xE04F, 0x8A81, 0xE050, 0x8A74, 0xE051, 0x8A7A, 0xE052, 0x8C3C, + 0xE053, 0x8C4B, 0xE054, 0x8C4A, 0xE055, 0x8C65, 0xE056, 0x8C64, 0xE057, 0x8C66, 0xE058, 0x8C86, 0xE059, 0x8C84, 0xE05A, 0x8C85, + 0xE05B, 0x8CCC, 0xE05C, 0x8D68, 0xE05D, 0x8D69, 0xE05E, 0x8D91, 0xE05F, 0x8D8C, 0xE060, 0x8D8E, 0xE061, 0x8D8F, 0xE062, 0x8D8D, + 0xE063, 0x8D93, 0xE064, 0x8D94, 0xE065, 0x8D90, 0xE066, 0x8D92, 0xE067, 0x8DF0, 0xE068, 0x8DE0, 0xE069, 0x8DEC, 0xE06A, 0x8DF1, + 0xE06B, 0x8DEE, 0xE06C, 0x8DD0, 0xE06D, 0x8DE9, 0xE06E, 0x8DE3, 0xE06F, 0x8DE2, 0xE070, 0x8DE7, 0xE071, 0x8DF2, 0xE072, 0x8DEB, + 0xE073, 0x8DF4, 0xE074, 0x8F06, 0xE075, 0x8EFF, 0xE076, 0x8F01, 0xE077, 0x8F00, 0xE078, 0x8F05, 0xE079, 0x8F07, 0xE07A, 0x8F08, + 0xE07B, 0x8F02, 0xE07C, 0x8F0B, 0xE07D, 0x9052, 0xE07E, 0x903F, 0xE0A1, 0x9044, 0xE0A2, 0x9049, 0xE0A3, 0x903D, 0xE0A4, 0x9110, + 0xE0A5, 0x910D, 0xE0A6, 0x910F, 0xE0A7, 0x9111, 0xE0A8, 0x9116, 0xE0A9, 0x9114, 0xE0AA, 0x910B, 0xE0AB, 0x910E, 0xE0AC, 0x916E, + 0xE0AD, 0x916F, 0xE0AE, 0x9248, 0xE0AF, 0x9252, 0xE0B0, 0x9230, 0xE0B1, 0x923A, 0xE0B2, 0x9266, 0xE0B3, 0x9233, 0xE0B4, 0x9265, + 0xE0B5, 0x925E, 0xE0B6, 0x9283, 0xE0B7, 0x922E, 0xE0B8, 0x924A, 0xE0B9, 0x9246, 0xE0BA, 0x926D, 0xE0BB, 0x926C, 0xE0BC, 0x924F, + 0xE0BD, 0x9260, 0xE0BE, 0x9267, 0xE0BF, 0x926F, 0xE0C0, 0x9236, 0xE0C1, 0x9261, 0xE0C2, 0x9270, 0xE0C3, 0x9231, 0xE0C4, 0x9254, + 0xE0C5, 0x9263, 0xE0C6, 0x9250, 0xE0C7, 0x9272, 0xE0C8, 0x924E, 0xE0C9, 0x9253, 0xE0CA, 0x924C, 0xE0CB, 0x9256, 0xE0CC, 0x9232, + 0xE0CD, 0x959F, 0xE0CE, 0x959C, 0xE0CF, 0x959E, 0xE0D0, 0x959B, 0xE0D1, 0x9692, 0xE0D2, 0x9693, 0xE0D3, 0x9691, 0xE0D4, 0x9697, + 0xE0D5, 0x96CE, 0xE0D6, 0x96FA, 0xE0D7, 0x96FD, 0xE0D8, 0x96F8, 0xE0D9, 0x96F5, 0xE0DA, 0x9773, 0xE0DB, 0x9777, 0xE0DC, 0x9778, + 0xE0DD, 0x9772, 0xE0DE, 0x980F, 0xE0DF, 0x980D, 0xE0E0, 0x980E, 0xE0E1, 0x98AC, 0xE0E2, 0x98F6, 0xE0E3, 0x98F9, 0xE0E4, 0x99AF, + 0xE0E5, 0x99B2, 0xE0E6, 0x99B0, 0xE0E7, 0x99B5, 0xE0E8, 0x9AAD, 0xE0E9, 0x9AAB, 0xE0EA, 0x9B5B, 0xE0EB, 0x9CEA, 0xE0EC, 0x9CED, + 0xE0ED, 0x9CE7, 0xE0EE, 0x9E80, 0xE0EF, 0x9EFD, 0xE0F0, 0x50E6, 0xE0F1, 0x50D4, 0xE0F2, 0x50D7, 0xE0F3, 0x50E8, 0xE0F4, 0x50F3, + 0xE0F5, 0x50DB, 0xE0F6, 0x50EA, 0xE0F7, 0x50DD, 0xE0F8, 0x50E4, 0xE0F9, 0x50D3, 0xE0FA, 0x50EC, 0xE0FB, 0x50F0, 0xE0FC, 0x50EF, + 0xE0FD, 0x50E3, 0xE0FE, 0x50E0, 0xE140, 0x51D8, 0xE141, 0x5280, 0xE142, 0x5281, 0xE143, 0x52E9, 0xE144, 0x52EB, 0xE145, 0x5330, + 0xE146, 0x53AC, 0xE147, 0x5627, 0xE148, 0x5615, 0xE149, 0x560C, 0xE14A, 0x5612, 0xE14B, 0x55FC, 0xE14C, 0x560F, 0xE14D, 0x561C, + 0xE14E, 0x5601, 0xE14F, 0x5613, 0xE150, 0x5602, 0xE151, 0x55FA, 0xE152, 0x561D, 0xE153, 0x5604, 0xE154, 0x55FF, 0xE155, 0x55F9, + 0xE156, 0x5889, 0xE157, 0x587C, 0xE158, 0x5890, 0xE159, 0x5898, 0xE15A, 0x5886, 0xE15B, 0x5881, 0xE15C, 0x587F, 0xE15D, 0x5874, + 0xE15E, 0x588B, 0xE15F, 0x587A, 0xE160, 0x5887, 0xE161, 0x5891, 0xE162, 0x588E, 0xE163, 0x5876, 0xE164, 0x5882, 0xE165, 0x5888, + 0xE166, 0x587B, 0xE167, 0x5894, 0xE168, 0x588F, 0xE169, 0x58FE, 0xE16A, 0x596B, 0xE16B, 0x5ADC, 0xE16C, 0x5AEE, 0xE16D, 0x5AE5, + 0xE16E, 0x5AD5, 0xE16F, 0x5AEA, 0xE170, 0x5ADA, 0xE171, 0x5AED, 0xE172, 0x5AEB, 0xE173, 0x5AF3, 0xE174, 0x5AE2, 0xE175, 0x5AE0, + 0xE176, 0x5ADB, 0xE177, 0x5AEC, 0xE178, 0x5ADE, 0xE179, 0x5ADD, 0xE17A, 0x5AD9, 0xE17B, 0x5AE8, 0xE17C, 0x5ADF, 0xE17D, 0x5B77, + 0xE17E, 0x5BE0, 0xE1A1, 0x5BE3, 0xE1A2, 0x5C63, 0xE1A3, 0x5D82, 0xE1A4, 0x5D80, 0xE1A5, 0x5D7D, 0xE1A6, 0x5D86, 0xE1A7, 0x5D7A, + 0xE1A8, 0x5D81, 0xE1A9, 0x5D77, 0xE1AA, 0x5D8A, 0xE1AB, 0x5D89, 0xE1AC, 0x5D88, 0xE1AD, 0x5D7E, 0xE1AE, 0x5D7C, 0xE1AF, 0x5D8D, + 0xE1B0, 0x5D79, 0xE1B1, 0x5D7F, 0xE1B2, 0x5E58, 0xE1B3, 0x5E59, 0xE1B4, 0x5E53, 0xE1B5, 0x5ED8, 0xE1B6, 0x5ED1, 0xE1B7, 0x5ED7, + 0xE1B8, 0x5ECE, 0xE1B9, 0x5EDC, 0xE1BA, 0x5ED5, 0xE1BB, 0x5ED9, 0xE1BC, 0x5ED2, 0xE1BD, 0x5ED4, 0xE1BE, 0x5F44, 0xE1BF, 0x5F43, + 0xE1C0, 0x5F6F, 0xE1C1, 0x5FB6, 0xE1C2, 0x612C, 0xE1C3, 0x6128, 0xE1C4, 0x6141, 0xE1C5, 0x615E, 0xE1C6, 0x6171, 0xE1C7, 0x6173, + 0xE1C8, 0x6152, 0xE1C9, 0x6153, 0xE1CA, 0x6172, 0xE1CB, 0x616C, 0xE1CC, 0x6180, 0xE1CD, 0x6174, 0xE1CE, 0x6154, 0xE1CF, 0x617A, + 0xE1D0, 0x615B, 0xE1D1, 0x6165, 0xE1D2, 0x613B, 0xE1D3, 0x616A, 0xE1D4, 0x6161, 0xE1D5, 0x6156, 0xE1D6, 0x6229, 0xE1D7, 0x6227, + 0xE1D8, 0x622B, 0xE1D9, 0x642B, 0xE1DA, 0x644D, 0xE1DB, 0x645B, 0xE1DC, 0x645D, 0xE1DD, 0x6474, 0xE1DE, 0x6476, 0xE1DF, 0x6472, + 0xE1E0, 0x6473, 0xE1E1, 0x647D, 0xE1E2, 0x6475, 0xE1E3, 0x6466, 0xE1E4, 0x64A6, 0xE1E5, 0x644E, 0xE1E6, 0x6482, 0xE1E7, 0x645E, + 0xE1E8, 0x645C, 0xE1E9, 0x644B, 0xE1EA, 0x6453, 0xE1EB, 0x6460, 0xE1EC, 0x6450, 0xE1ED, 0x647F, 0xE1EE, 0x643F, 0xE1EF, 0x646C, + 0xE1F0, 0x646B, 0xE1F1, 0x6459, 0xE1F2, 0x6465, 0xE1F3, 0x6477, 0xE1F4, 0x6573, 0xE1F5, 0x65A0, 0xE1F6, 0x66A1, 0xE1F7, 0x66A0, + 0xE1F8, 0x669F, 0xE1F9, 0x6705, 0xE1FA, 0x6704, 0xE1FB, 0x6722, 0xE1FC, 0x69B1, 0xE1FD, 0x69B6, 0xE1FE, 0x69C9, 0xE240, 0x69A0, + 0xE241, 0x69CE, 0xE242, 0x6996, 0xE243, 0x69B0, 0xE244, 0x69AC, 0xE245, 0x69BC, 0xE246, 0x6991, 0xE247, 0x6999, 0xE248, 0x698E, + 0xE249, 0x69A7, 0xE24A, 0x698D, 0xE24B, 0x69A9, 0xE24C, 0x69BE, 0xE24D, 0x69AF, 0xE24E, 0x69BF, 0xE24F, 0x69C4, 0xE250, 0x69BD, + 0xE251, 0x69A4, 0xE252, 0x69D4, 0xE253, 0x69B9, 0xE254, 0x69CA, 0xE255, 0x699A, 0xE256, 0x69CF, 0xE257, 0x69B3, 0xE258, 0x6993, + 0xE259, 0x69AA, 0xE25A, 0x69A1, 0xE25B, 0x699E, 0xE25C, 0x69D9, 0xE25D, 0x6997, 0xE25E, 0x6990, 0xE25F, 0x69C2, 0xE260, 0x69B5, + 0xE261, 0x69A5, 0xE262, 0x69C6, 0xE263, 0x6B4A, 0xE264, 0x6B4D, 0xE265, 0x6B4B, 0xE266, 0x6B9E, 0xE267, 0x6B9F, 0xE268, 0x6BA0, + 0xE269, 0x6BC3, 0xE26A, 0x6BC4, 0xE26B, 0x6BFE, 0xE26C, 0x6ECE, 0xE26D, 0x6EF5, 0xE26E, 0x6EF1, 0xE26F, 0x6F03, 0xE270, 0x6F25, + 0xE271, 0x6EF8, 0xE272, 0x6F37, 0xE273, 0x6EFB, 0xE274, 0x6F2E, 0xE275, 0x6F09, 0xE276, 0x6F4E, 0xE277, 0x6F19, 0xE278, 0x6F1A, + 0xE279, 0x6F27, 0xE27A, 0x6F18, 0xE27B, 0x6F3B, 0xE27C, 0x6F12, 0xE27D, 0x6EED, 0xE27E, 0x6F0A, 0xE2A1, 0x6F36, 0xE2A2, 0x6F73, + 0xE2A3, 0x6EF9, 0xE2A4, 0x6EEE, 0xE2A5, 0x6F2D, 0xE2A6, 0x6F40, 0xE2A7, 0x6F30, 0xE2A8, 0x6F3C, 0xE2A9, 0x6F35, 0xE2AA, 0x6EEB, + 0xE2AB, 0x6F07, 0xE2AC, 0x6F0E, 0xE2AD, 0x6F43, 0xE2AE, 0x6F05, 0xE2AF, 0x6EFD, 0xE2B0, 0x6EF6, 0xE2B1, 0x6F39, 0xE2B2, 0x6F1C, + 0xE2B3, 0x6EFC, 0xE2B4, 0x6F3A, 0xE2B5, 0x6F1F, 0xE2B6, 0x6F0D, 0xE2B7, 0x6F1E, 0xE2B8, 0x6F08, 0xE2B9, 0x6F21, 0xE2BA, 0x7187, + 0xE2BB, 0x7190, 0xE2BC, 0x7189, 0xE2BD, 0x7180, 0xE2BE, 0x7185, 0xE2BF, 0x7182, 0xE2C0, 0x718F, 0xE2C1, 0x717B, 0xE2C2, 0x7186, + 0xE2C3, 0x7181, 0xE2C4, 0x7197, 0xE2C5, 0x7244, 0xE2C6, 0x7253, 0xE2C7, 0x7297, 0xE2C8, 0x7295, 0xE2C9, 0x7293, 0xE2CA, 0x7343, + 0xE2CB, 0x734D, 0xE2CC, 0x7351, 0xE2CD, 0x734C, 0xE2CE, 0x7462, 0xE2CF, 0x7473, 0xE2D0, 0x7471, 0xE2D1, 0x7475, 0xE2D2, 0x7472, + 0xE2D3, 0x7467, 0xE2D4, 0x746E, 0xE2D5, 0x7500, 0xE2D6, 0x7502, 0xE2D7, 0x7503, 0xE2D8, 0x757D, 0xE2D9, 0x7590, 0xE2DA, 0x7616, + 0xE2DB, 0x7608, 0xE2DC, 0x760C, 0xE2DD, 0x7615, 0xE2DE, 0x7611, 0xE2DF, 0x760A, 0xE2E0, 0x7614, 0xE2E1, 0x76B8, 0xE2E2, 0x7781, + 0xE2E3, 0x777C, 0xE2E4, 0x7785, 0xE2E5, 0x7782, 0xE2E6, 0x776E, 0xE2E7, 0x7780, 0xE2E8, 0x776F, 0xE2E9, 0x777E, 0xE2EA, 0x7783, + 0xE2EB, 0x78B2, 0xE2EC, 0x78AA, 0xE2ED, 0x78B4, 0xE2EE, 0x78AD, 0xE2EF, 0x78A8, 0xE2F0, 0x787E, 0xE2F1, 0x78AB, 0xE2F2, 0x789E, + 0xE2F3, 0x78A5, 0xE2F4, 0x78A0, 0xE2F5, 0x78AC, 0xE2F6, 0x78A2, 0xE2F7, 0x78A4, 0xE2F8, 0x7998, 0xE2F9, 0x798A, 0xE2FA, 0x798B, + 0xE2FB, 0x7996, 0xE2FC, 0x7995, 0xE2FD, 0x7994, 0xE2FE, 0x7993, 0xE340, 0x7997, 0xE341, 0x7988, 0xE342, 0x7992, 0xE343, 0x7990, + 0xE344, 0x7A2B, 0xE345, 0x7A4A, 0xE346, 0x7A30, 0xE347, 0x7A2F, 0xE348, 0x7A28, 0xE349, 0x7A26, 0xE34A, 0x7AA8, 0xE34B, 0x7AAB, + 0xE34C, 0x7AAC, 0xE34D, 0x7AEE, 0xE34E, 0x7B88, 0xE34F, 0x7B9C, 0xE350, 0x7B8A, 0xE351, 0x7B91, 0xE352, 0x7B90, 0xE353, 0x7B96, + 0xE354, 0x7B8D, 0xE355, 0x7B8C, 0xE356, 0x7B9B, 0xE357, 0x7B8E, 0xE358, 0x7B85, 0xE359, 0x7B98, 0xE35A, 0x5284, 0xE35B, 0x7B99, + 0xE35C, 0x7BA4, 0xE35D, 0x7B82, 0xE35E, 0x7CBB, 0xE35F, 0x7CBF, 0xE360, 0x7CBC, 0xE361, 0x7CBA, 0xE362, 0x7DA7, 0xE363, 0x7DB7, + 0xE364, 0x7DC2, 0xE365, 0x7DA3, 0xE366, 0x7DAA, 0xE367, 0x7DC1, 0xE368, 0x7DC0, 0xE369, 0x7DC5, 0xE36A, 0x7D9D, 0xE36B, 0x7DCE, + 0xE36C, 0x7DC4, 0xE36D, 0x7DC6, 0xE36E, 0x7DCB, 0xE36F, 0x7DCC, 0xE370, 0x7DAF, 0xE371, 0x7DB9, 0xE372, 0x7D96, 0xE373, 0x7DBC, + 0xE374, 0x7D9F, 0xE375, 0x7DA6, 0xE376, 0x7DAE, 0xE377, 0x7DA9, 0xE378, 0x7DA1, 0xE379, 0x7DC9, 0xE37A, 0x7F73, 0xE37B, 0x7FE2, + 0xE37C, 0x7FE3, 0xE37D, 0x7FE5, 0xE37E, 0x7FDE, 0xE3A1, 0x8024, 0xE3A2, 0x805D, 0xE3A3, 0x805C, 0xE3A4, 0x8189, 0xE3A5, 0x8186, + 0xE3A6, 0x8183, 0xE3A7, 0x8187, 0xE3A8, 0x818D, 0xE3A9, 0x818C, 0xE3AA, 0x818B, 0xE3AB, 0x8215, 0xE3AC, 0x8497, 0xE3AD, 0x84A4, + 0xE3AE, 0x84A1, 0xE3AF, 0x849F, 0xE3B0, 0x84BA, 0xE3B1, 0x84CE, 0xE3B2, 0x84C2, 0xE3B3, 0x84AC, 0xE3B4, 0x84AE, 0xE3B5, 0x84AB, + 0xE3B6, 0x84B9, 0xE3B7, 0x84B4, 0xE3B8, 0x84C1, 0xE3B9, 0x84CD, 0xE3BA, 0x84AA, 0xE3BB, 0x849A, 0xE3BC, 0x84B1, 0xE3BD, 0x84D0, + 0xE3BE, 0x849D, 0xE3BF, 0x84A7, 0xE3C0, 0x84BB, 0xE3C1, 0x84A2, 0xE3C2, 0x8494, 0xE3C3, 0x84C7, 0xE3C4, 0x84CC, 0xE3C5, 0x849B, + 0xE3C6, 0x84A9, 0xE3C7, 0x84AF, 0xE3C8, 0x84A8, 0xE3C9, 0x84D6, 0xE3CA, 0x8498, 0xE3CB, 0x84B6, 0xE3CC, 0x84CF, 0xE3CD, 0x84A0, + 0xE3CE, 0x84D7, 0xE3CF, 0x84D4, 0xE3D0, 0x84D2, 0xE3D1, 0x84DB, 0xE3D2, 0x84B0, 0xE3D3, 0x8491, 0xE3D4, 0x8661, 0xE3D5, 0x8733, + 0xE3D6, 0x8723, 0xE3D7, 0x8728, 0xE3D8, 0x876B, 0xE3D9, 0x8740, 0xE3DA, 0x872E, 0xE3DB, 0x871E, 0xE3DC, 0x8721, 0xE3DD, 0x8719, + 0xE3DE, 0x871B, 0xE3DF, 0x8743, 0xE3E0, 0x872C, 0xE3E1, 0x8741, 0xE3E2, 0x873E, 0xE3E3, 0x8746, 0xE3E4, 0x8720, 0xE3E5, 0x8732, + 0xE3E6, 0x872A, 0xE3E7, 0x872D, 0xE3E8, 0x873C, 0xE3E9, 0x8712, 0xE3EA, 0x873A, 0xE3EB, 0x8731, 0xE3EC, 0x8735, 0xE3ED, 0x8742, + 0xE3EE, 0x8726, 0xE3EF, 0x8727, 0xE3F0, 0x8738, 0xE3F1, 0x8724, 0xE3F2, 0x871A, 0xE3F3, 0x8730, 0xE3F4, 0x8711, 0xE3F5, 0x88F7, + 0xE3F6, 0x88E7, 0xE3F7, 0x88F1, 0xE3F8, 0x88F2, 0xE3F9, 0x88FA, 0xE3FA, 0x88FE, 0xE3FB, 0x88EE, 0xE3FC, 0x88FC, 0xE3FD, 0x88F6, + 0xE3FE, 0x88FB, 0xE440, 0x88F0, 0xE441, 0x88EC, 0xE442, 0x88EB, 0xE443, 0x899D, 0xE444, 0x89A1, 0xE445, 0x899F, 0xE446, 0x899E, + 0xE447, 0x89E9, 0xE448, 0x89EB, 0xE449, 0x89E8, 0xE44A, 0x8AAB, 0xE44B, 0x8A99, 0xE44C, 0x8A8B, 0xE44D, 0x8A92, 0xE44E, 0x8A8F, + 0xE44F, 0x8A96, 0xE450, 0x8C3D, 0xE451, 0x8C68, 0xE452, 0x8C69, 0xE453, 0x8CD5, 0xE454, 0x8CCF, 0xE455, 0x8CD7, 0xE456, 0x8D96, + 0xE457, 0x8E09, 0xE458, 0x8E02, 0xE459, 0x8DFF, 0xE45A, 0x8E0D, 0xE45B, 0x8DFD, 0xE45C, 0x8E0A, 0xE45D, 0x8E03, 0xE45E, 0x8E07, + 0xE45F, 0x8E06, 0xE460, 0x8E05, 0xE461, 0x8DFE, 0xE462, 0x8E00, 0xE463, 0x8E04, 0xE464, 0x8F10, 0xE465, 0x8F11, 0xE466, 0x8F0E, + 0xE467, 0x8F0D, 0xE468, 0x9123, 0xE469, 0x911C, 0xE46A, 0x9120, 0xE46B, 0x9122, 0xE46C, 0x911F, 0xE46D, 0x911D, 0xE46E, 0x911A, + 0xE46F, 0x9124, 0xE470, 0x9121, 0xE471, 0x911B, 0xE472, 0x917A, 0xE473, 0x9172, 0xE474, 0x9179, 0xE475, 0x9173, 0xE476, 0x92A5, + 0xE477, 0x92A4, 0xE478, 0x9276, 0xE479, 0x929B, 0xE47A, 0x927A, 0xE47B, 0x92A0, 0xE47C, 0x9294, 0xE47D, 0x92AA, 0xE47E, 0x928D, + 0xE4A1, 0x92A6, 0xE4A2, 0x929A, 0xE4A3, 0x92AB, 0xE4A4, 0x9279, 0xE4A5, 0x9297, 0xE4A6, 0x927F, 0xE4A7, 0x92A3, 0xE4A8, 0x92EE, + 0xE4A9, 0x928E, 0xE4AA, 0x9282, 0xE4AB, 0x9295, 0xE4AC, 0x92A2, 0xE4AD, 0x927D, 0xE4AE, 0x9288, 0xE4AF, 0x92A1, 0xE4B0, 0x928A, + 0xE4B1, 0x9286, 0xE4B2, 0x928C, 0xE4B3, 0x9299, 0xE4B4, 0x92A7, 0xE4B5, 0x927E, 0xE4B6, 0x9287, 0xE4B7, 0x92A9, 0xE4B8, 0x929D, + 0xE4B9, 0x928B, 0xE4BA, 0x922D, 0xE4BB, 0x969E, 0xE4BC, 0x96A1, 0xE4BD, 0x96FF, 0xE4BE, 0x9758, 0xE4BF, 0x977D, 0xE4C0, 0x977A, + 0xE4C1, 0x977E, 0xE4C2, 0x9783, 0xE4C3, 0x9780, 0xE4C4, 0x9782, 0xE4C5, 0x977B, 0xE4C6, 0x9784, 0xE4C7, 0x9781, 0xE4C8, 0x977F, + 0xE4C9, 0x97CE, 0xE4CA, 0x97CD, 0xE4CB, 0x9816, 0xE4CC, 0x98AD, 0xE4CD, 0x98AE, 0xE4CE, 0x9902, 0xE4CF, 0x9900, 0xE4D0, 0x9907, + 0xE4D1, 0x999D, 0xE4D2, 0x999C, 0xE4D3, 0x99C3, 0xE4D4, 0x99B9, 0xE4D5, 0x99BB, 0xE4D6, 0x99BA, 0xE4D7, 0x99C2, 0xE4D8, 0x99BD, + 0xE4D9, 0x99C7, 0xE4DA, 0x9AB1, 0xE4DB, 0x9AE3, 0xE4DC, 0x9AE7, 0xE4DD, 0x9B3E, 0xE4DE, 0x9B3F, 0xE4DF, 0x9B60, 0xE4E0, 0x9B61, + 0xE4E1, 0x9B5F, 0xE4E2, 0x9CF1, 0xE4E3, 0x9CF2, 0xE4E4, 0x9CF5, 0xE4E5, 0x9EA7, 0xE4E6, 0x50FF, 0xE4E7, 0x5103, 0xE4E8, 0x5130, + 0xE4E9, 0x50F8, 0xE4EA, 0x5106, 0xE4EB, 0x5107, 0xE4EC, 0x50F6, 0xE4ED, 0x50FE, 0xE4EE, 0x510B, 0xE4EF, 0x510C, 0xE4F0, 0x50FD, + 0xE4F1, 0x510A, 0xE4F2, 0x528B, 0xE4F3, 0x528C, 0xE4F4, 0x52F1, 0xE4F5, 0x52EF, 0xE4F6, 0x5648, 0xE4F7, 0x5642, 0xE4F8, 0x564C, + 0xE4F9, 0x5635, 0xE4FA, 0x5641, 0xE4FB, 0x564A, 0xE4FC, 0x5649, 0xE4FD, 0x5646, 0xE4FE, 0x5658, 0xE540, 0x565A, 0xE541, 0x5640, + 0xE542, 0x5633, 0xE543, 0x563D, 0xE544, 0x562C, 0xE545, 0x563E, 0xE546, 0x5638, 0xE547, 0x562A, 0xE548, 0x563A, 0xE549, 0x571A, + 0xE54A, 0x58AB, 0xE54B, 0x589D, 0xE54C, 0x58B1, 0xE54D, 0x58A0, 0xE54E, 0x58A3, 0xE54F, 0x58AF, 0xE550, 0x58AC, 0xE551, 0x58A5, + 0xE552, 0x58A1, 0xE553, 0x58FF, 0xE554, 0x5AFF, 0xE555, 0x5AF4, 0xE556, 0x5AFD, 0xE557, 0x5AF7, 0xE558, 0x5AF6, 0xE559, 0x5B03, + 0xE55A, 0x5AF8, 0xE55B, 0x5B02, 0xE55C, 0x5AF9, 0xE55D, 0x5B01, 0xE55E, 0x5B07, 0xE55F, 0x5B05, 0xE560, 0x5B0F, 0xE561, 0x5C67, + 0xE562, 0x5D99, 0xE563, 0x5D97, 0xE564, 0x5D9F, 0xE565, 0x5D92, 0xE566, 0x5DA2, 0xE567, 0x5D93, 0xE568, 0x5D95, 0xE569, 0x5DA0, + 0xE56A, 0x5D9C, 0xE56B, 0x5DA1, 0xE56C, 0x5D9A, 0xE56D, 0x5D9E, 0xE56E, 0x5E69, 0xE56F, 0x5E5D, 0xE570, 0x5E60, 0xE571, 0x5E5C, + 0xE572, 0x7DF3, 0xE573, 0x5EDB, 0xE574, 0x5EDE, 0xE575, 0x5EE1, 0xE576, 0x5F49, 0xE577, 0x5FB2, 0xE578, 0x618B, 0xE579, 0x6183, + 0xE57A, 0x6179, 0xE57B, 0x61B1, 0xE57C, 0x61B0, 0xE57D, 0x61A2, 0xE57E, 0x6189, 0xE5A1, 0x619B, 0xE5A2, 0x6193, 0xE5A3, 0x61AF, + 0xE5A4, 0x61AD, 0xE5A5, 0x619F, 0xE5A6, 0x6192, 0xE5A7, 0x61AA, 0xE5A8, 0x61A1, 0xE5A9, 0x618D, 0xE5AA, 0x6166, 0xE5AB, 0x61B3, + 0xE5AC, 0x622D, 0xE5AD, 0x646E, 0xE5AE, 0x6470, 0xE5AF, 0x6496, 0xE5B0, 0x64A0, 0xE5B1, 0x6485, 0xE5B2, 0x6497, 0xE5B3, 0x649C, + 0xE5B4, 0x648F, 0xE5B5, 0x648B, 0xE5B6, 0x648A, 0xE5B7, 0x648C, 0xE5B8, 0x64A3, 0xE5B9, 0x649F, 0xE5BA, 0x6468, 0xE5BB, 0x64B1, + 0xE5BC, 0x6498, 0xE5BD, 0x6576, 0xE5BE, 0x657A, 0xE5BF, 0x6579, 0xE5C0, 0x657B, 0xE5C1, 0x65B2, 0xE5C2, 0x65B3, 0xE5C3, 0x66B5, + 0xE5C4, 0x66B0, 0xE5C5, 0x66A9, 0xE5C6, 0x66B2, 0xE5C7, 0x66B7, 0xE5C8, 0x66AA, 0xE5C9, 0x66AF, 0xE5CA, 0x6A00, 0xE5CB, 0x6A06, + 0xE5CC, 0x6A17, 0xE5CD, 0x69E5, 0xE5CE, 0x69F8, 0xE5CF, 0x6A15, 0xE5D0, 0x69F1, 0xE5D1, 0x69E4, 0xE5D2, 0x6A20, 0xE5D3, 0x69FF, + 0xE5D4, 0x69EC, 0xE5D5, 0x69E2, 0xE5D6, 0x6A1B, 0xE5D7, 0x6A1D, 0xE5D8, 0x69FE, 0xE5D9, 0x6A27, 0xE5DA, 0x69F2, 0xE5DB, 0x69EE, + 0xE5DC, 0x6A14, 0xE5DD, 0x69F7, 0xE5DE, 0x69E7, 0xE5DF, 0x6A40, 0xE5E0, 0x6A08, 0xE5E1, 0x69E6, 0xE5E2, 0x69FB, 0xE5E3, 0x6A0D, + 0xE5E4, 0x69FC, 0xE5E5, 0x69EB, 0xE5E6, 0x6A09, 0xE5E7, 0x6A04, 0xE5E8, 0x6A18, 0xE5E9, 0x6A25, 0xE5EA, 0x6A0F, 0xE5EB, 0x69F6, + 0xE5EC, 0x6A26, 0xE5ED, 0x6A07, 0xE5EE, 0x69F4, 0xE5EF, 0x6A16, 0xE5F0, 0x6B51, 0xE5F1, 0x6BA5, 0xE5F2, 0x6BA3, 0xE5F3, 0x6BA2, + 0xE5F4, 0x6BA6, 0xE5F5, 0x6C01, 0xE5F6, 0x6C00, 0xE5F7, 0x6BFF, 0xE5F8, 0x6C02, 0xE5F9, 0x6F41, 0xE5FA, 0x6F26, 0xE5FB, 0x6F7E, + 0xE5FC, 0x6F87, 0xE5FD, 0x6FC6, 0xE5FE, 0x6F92, 0xE640, 0x6F8D, 0xE641, 0x6F89, 0xE642, 0x6F8C, 0xE643, 0x6F62, 0xE644, 0x6F4F, + 0xE645, 0x6F85, 0xE646, 0x6F5A, 0xE647, 0x6F96, 0xE648, 0x6F76, 0xE649, 0x6F6C, 0xE64A, 0x6F82, 0xE64B, 0x6F55, 0xE64C, 0x6F72, + 0xE64D, 0x6F52, 0xE64E, 0x6F50, 0xE64F, 0x6F57, 0xE650, 0x6F94, 0xE651, 0x6F93, 0xE652, 0x6F5D, 0xE653, 0x6F00, 0xE654, 0x6F61, + 0xE655, 0x6F6B, 0xE656, 0x6F7D, 0xE657, 0x6F67, 0xE658, 0x6F90, 0xE659, 0x6F53, 0xE65A, 0x6F8B, 0xE65B, 0x6F69, 0xE65C, 0x6F7F, + 0xE65D, 0x6F95, 0xE65E, 0x6F63, 0xE65F, 0x6F77, 0xE660, 0x6F6A, 0xE661, 0x6F7B, 0xE662, 0x71B2, 0xE663, 0x71AF, 0xE664, 0x719B, + 0xE665, 0x71B0, 0xE666, 0x71A0, 0xE667, 0x719A, 0xE668, 0x71A9, 0xE669, 0x71B5, 0xE66A, 0x719D, 0xE66B, 0x71A5, 0xE66C, 0x719E, + 0xE66D, 0x71A4, 0xE66E, 0x71A1, 0xE66F, 0x71AA, 0xE670, 0x719C, 0xE671, 0x71A7, 0xE672, 0x71B3, 0xE673, 0x7298, 0xE674, 0x729A, + 0xE675, 0x7358, 0xE676, 0x7352, 0xE677, 0x735E, 0xE678, 0x735F, 0xE679, 0x7360, 0xE67A, 0x735D, 0xE67B, 0x735B, 0xE67C, 0x7361, + 0xE67D, 0x735A, 0xE67E, 0x7359, 0xE6A1, 0x7362, 0xE6A2, 0x7487, 0xE6A3, 0x7489, 0xE6A4, 0x748A, 0xE6A5, 0x7486, 0xE6A6, 0x7481, + 0xE6A7, 0x747D, 0xE6A8, 0x7485, 0xE6A9, 0x7488, 0xE6AA, 0x747C, 0xE6AB, 0x7479, 0xE6AC, 0x7508, 0xE6AD, 0x7507, 0xE6AE, 0x757E, + 0xE6AF, 0x7625, 0xE6B0, 0x761E, 0xE6B1, 0x7619, 0xE6B2, 0x761D, 0xE6B3, 0x761C, 0xE6B4, 0x7623, 0xE6B5, 0x761A, 0xE6B6, 0x7628, + 0xE6B7, 0x761B, 0xE6B8, 0x769C, 0xE6B9, 0x769D, 0xE6BA, 0x769E, 0xE6BB, 0x769B, 0xE6BC, 0x778D, 0xE6BD, 0x778F, 0xE6BE, 0x7789, + 0xE6BF, 0x7788, 0xE6C0, 0x78CD, 0xE6C1, 0x78BB, 0xE6C2, 0x78CF, 0xE6C3, 0x78CC, 0xE6C4, 0x78D1, 0xE6C5, 0x78CE, 0xE6C6, 0x78D4, + 0xE6C7, 0x78C8, 0xE6C8, 0x78C3, 0xE6C9, 0x78C4, 0xE6CA, 0x78C9, 0xE6CB, 0x799A, 0xE6CC, 0x79A1, 0xE6CD, 0x79A0, 0xE6CE, 0x799C, + 0xE6CF, 0x79A2, 0xE6D0, 0x799B, 0xE6D1, 0x6B76, 0xE6D2, 0x7A39, 0xE6D3, 0x7AB2, 0xE6D4, 0x7AB4, 0xE6D5, 0x7AB3, 0xE6D6, 0x7BB7, + 0xE6D7, 0x7BCB, 0xE6D8, 0x7BBE, 0xE6D9, 0x7BAC, 0xE6DA, 0x7BCE, 0xE6DB, 0x7BAF, 0xE6DC, 0x7BB9, 0xE6DD, 0x7BCA, 0xE6DE, 0x7BB5, + 0xE6DF, 0x7CC5, 0xE6E0, 0x7CC8, 0xE6E1, 0x7CCC, 0xE6E2, 0x7CCB, 0xE6E3, 0x7DF7, 0xE6E4, 0x7DDB, 0xE6E5, 0x7DEA, 0xE6E6, 0x7DE7, + 0xE6E7, 0x7DD7, 0xE6E8, 0x7DE1, 0xE6E9, 0x7E03, 0xE6EA, 0x7DFA, 0xE6EB, 0x7DE6, 0xE6EC, 0x7DF6, 0xE6ED, 0x7DF1, 0xE6EE, 0x7DF0, + 0xE6EF, 0x7DEE, 0xE6F0, 0x7DDF, 0xE6F1, 0x7F76, 0xE6F2, 0x7FAC, 0xE6F3, 0x7FB0, 0xE6F4, 0x7FAD, 0xE6F5, 0x7FED, 0xE6F6, 0x7FEB, + 0xE6F7, 0x7FEA, 0xE6F8, 0x7FEC, 0xE6F9, 0x7FE6, 0xE6FA, 0x7FE8, 0xE6FB, 0x8064, 0xE6FC, 0x8067, 0xE6FD, 0x81A3, 0xE6FE, 0x819F, + 0xE740, 0x819E, 0xE741, 0x8195, 0xE742, 0x81A2, 0xE743, 0x8199, 0xE744, 0x8197, 0xE745, 0x8216, 0xE746, 0x824F, 0xE747, 0x8253, + 0xE748, 0x8252, 0xE749, 0x8250, 0xE74A, 0x824E, 0xE74B, 0x8251, 0xE74C, 0x8524, 0xE74D, 0x853B, 0xE74E, 0x850F, 0xE74F, 0x8500, + 0xE750, 0x8529, 0xE751, 0x850E, 0xE752, 0x8509, 0xE753, 0x850D, 0xE754, 0x851F, 0xE755, 0x850A, 0xE756, 0x8527, 0xE757, 0x851C, + 0xE758, 0x84FB, 0xE759, 0x852B, 0xE75A, 0x84FA, 0xE75B, 0x8508, 0xE75C, 0x850C, 0xE75D, 0x84F4, 0xE75E, 0x852A, 0xE75F, 0x84F2, + 0xE760, 0x8515, 0xE761, 0x84F7, 0xE762, 0x84EB, 0xE763, 0x84F3, 0xE764, 0x84FC, 0xE765, 0x8512, 0xE766, 0x84EA, 0xE767, 0x84E9, + 0xE768, 0x8516, 0xE769, 0x84FE, 0xE76A, 0x8528, 0xE76B, 0x851D, 0xE76C, 0x852E, 0xE76D, 0x8502, 0xE76E, 0x84FD, 0xE76F, 0x851E, + 0xE770, 0x84F6, 0xE771, 0x8531, 0xE772, 0x8526, 0xE773, 0x84E7, 0xE774, 0x84E8, 0xE775, 0x84F0, 0xE776, 0x84EF, 0xE777, 0x84F9, + 0xE778, 0x8518, 0xE779, 0x8520, 0xE77A, 0x8530, 0xE77B, 0x850B, 0xE77C, 0x8519, 0xE77D, 0x852F, 0xE77E, 0x8662, 0xE7A1, 0x8756, + 0xE7A2, 0x8763, 0xE7A3, 0x8764, 0xE7A4, 0x8777, 0xE7A5, 0x87E1, 0xE7A6, 0x8773, 0xE7A7, 0x8758, 0xE7A8, 0x8754, 0xE7A9, 0x875B, + 0xE7AA, 0x8752, 0xE7AB, 0x8761, 0xE7AC, 0x875A, 0xE7AD, 0x8751, 0xE7AE, 0x875E, 0xE7AF, 0x876D, 0xE7B0, 0x876A, 0xE7B1, 0x8750, + 0xE7B2, 0x874E, 0xE7B3, 0x875F, 0xE7B4, 0x875D, 0xE7B5, 0x876F, 0xE7B6, 0x876C, 0xE7B7, 0x877A, 0xE7B8, 0x876E, 0xE7B9, 0x875C, + 0xE7BA, 0x8765, 0xE7BB, 0x874F, 0xE7BC, 0x877B, 0xE7BD, 0x8775, 0xE7BE, 0x8762, 0xE7BF, 0x8767, 0xE7C0, 0x8769, 0xE7C1, 0x885A, + 0xE7C2, 0x8905, 0xE7C3, 0x890C, 0xE7C4, 0x8914, 0xE7C5, 0x890B, 0xE7C6, 0x8917, 0xE7C7, 0x8918, 0xE7C8, 0x8919, 0xE7C9, 0x8906, + 0xE7CA, 0x8916, 0xE7CB, 0x8911, 0xE7CC, 0x890E, 0xE7CD, 0x8909, 0xE7CE, 0x89A2, 0xE7CF, 0x89A4, 0xE7D0, 0x89A3, 0xE7D1, 0x89ED, + 0xE7D2, 0x89F0, 0xE7D3, 0x89EC, 0xE7D4, 0x8ACF, 0xE7D5, 0x8AC6, 0xE7D6, 0x8AB8, 0xE7D7, 0x8AD3, 0xE7D8, 0x8AD1, 0xE7D9, 0x8AD4, + 0xE7DA, 0x8AD5, 0xE7DB, 0x8ABB, 0xE7DC, 0x8AD7, 0xE7DD, 0x8ABE, 0xE7DE, 0x8AC0, 0xE7DF, 0x8AC5, 0xE7E0, 0x8AD8, 0xE7E1, 0x8AC3, + 0xE7E2, 0x8ABA, 0xE7E3, 0x8ABD, 0xE7E4, 0x8AD9, 0xE7E5, 0x8C3E, 0xE7E6, 0x8C4D, 0xE7E7, 0x8C8F, 0xE7E8, 0x8CE5, 0xE7E9, 0x8CDF, + 0xE7EA, 0x8CD9, 0xE7EB, 0x8CE8, 0xE7EC, 0x8CDA, 0xE7ED, 0x8CDD, 0xE7EE, 0x8CE7, 0xE7EF, 0x8DA0, 0xE7F0, 0x8D9C, 0xE7F1, 0x8DA1, + 0xE7F2, 0x8D9B, 0xE7F3, 0x8E20, 0xE7F4, 0x8E23, 0xE7F5, 0x8E25, 0xE7F6, 0x8E24, 0xE7F7, 0x8E2E, 0xE7F8, 0x8E15, 0xE7F9, 0x8E1B, + 0xE7FA, 0x8E16, 0xE7FB, 0x8E11, 0xE7FC, 0x8E19, 0xE7FD, 0x8E26, 0xE7FE, 0x8E27, 0xE840, 0x8E14, 0xE841, 0x8E12, 0xE842, 0x8E18, + 0xE843, 0x8E13, 0xE844, 0x8E1C, 0xE845, 0x8E17, 0xE846, 0x8E1A, 0xE847, 0x8F2C, 0xE848, 0x8F24, 0xE849, 0x8F18, 0xE84A, 0x8F1A, + 0xE84B, 0x8F20, 0xE84C, 0x8F23, 0xE84D, 0x8F16, 0xE84E, 0x8F17, 0xE84F, 0x9073, 0xE850, 0x9070, 0xE851, 0x906F, 0xE852, 0x9067, + 0xE853, 0x906B, 0xE854, 0x912F, 0xE855, 0x912B, 0xE856, 0x9129, 0xE857, 0x912A, 0xE858, 0x9132, 0xE859, 0x9126, 0xE85A, 0x912E, + 0xE85B, 0x9185, 0xE85C, 0x9186, 0xE85D, 0x918A, 0xE85E, 0x9181, 0xE85F, 0x9182, 0xE860, 0x9184, 0xE861, 0x9180, 0xE862, 0x92D0, + 0xE863, 0x92C3, 0xE864, 0x92C4, 0xE865, 0x92C0, 0xE866, 0x92D9, 0xE867, 0x92B6, 0xE868, 0x92CF, 0xE869, 0x92F1, 0xE86A, 0x92DF, + 0xE86B, 0x92D8, 0xE86C, 0x92E9, 0xE86D, 0x92D7, 0xE86E, 0x92DD, 0xE86F, 0x92CC, 0xE870, 0x92EF, 0xE871, 0x92C2, 0xE872, 0x92E8, + 0xE873, 0x92CA, 0xE874, 0x92C8, 0xE875, 0x92CE, 0xE876, 0x92E6, 0xE877, 0x92CD, 0xE878, 0x92D5, 0xE879, 0x92C9, 0xE87A, 0x92E0, + 0xE87B, 0x92DE, 0xE87C, 0x92E7, 0xE87D, 0x92D1, 0xE87E, 0x92D3, 0xE8A1, 0x92B5, 0xE8A2, 0x92E1, 0xE8A3, 0x92C6, 0xE8A4, 0x92B4, + 0xE8A5, 0x957C, 0xE8A6, 0x95AC, 0xE8A7, 0x95AB, 0xE8A8, 0x95AE, 0xE8A9, 0x95B0, 0xE8AA, 0x96A4, 0xE8AB, 0x96A2, 0xE8AC, 0x96D3, + 0xE8AD, 0x9705, 0xE8AE, 0x9708, 0xE8AF, 0x9702, 0xE8B0, 0x975A, 0xE8B1, 0x978A, 0xE8B2, 0x978E, 0xE8B3, 0x9788, 0xE8B4, 0x97D0, + 0xE8B5, 0x97CF, 0xE8B6, 0x981E, 0xE8B7, 0x981D, 0xE8B8, 0x9826, 0xE8B9, 0x9829, 0xE8BA, 0x9828, 0xE8BB, 0x9820, 0xE8BC, 0x981B, + 0xE8BD, 0x9827, 0xE8BE, 0x98B2, 0xE8BF, 0x9908, 0xE8C0, 0x98FA, 0xE8C1, 0x9911, 0xE8C2, 0x9914, 0xE8C3, 0x9916, 0xE8C4, 0x9917, + 0xE8C5, 0x9915, 0xE8C6, 0x99DC, 0xE8C7, 0x99CD, 0xE8C8, 0x99CF, 0xE8C9, 0x99D3, 0xE8CA, 0x99D4, 0xE8CB, 0x99CE, 0xE8CC, 0x99C9, + 0xE8CD, 0x99D6, 0xE8CE, 0x99D8, 0xE8CF, 0x99CB, 0xE8D0, 0x99D7, 0xE8D1, 0x99CC, 0xE8D2, 0x9AB3, 0xE8D3, 0x9AEC, 0xE8D4, 0x9AEB, + 0xE8D5, 0x9AF3, 0xE8D6, 0x9AF2, 0xE8D7, 0x9AF1, 0xE8D8, 0x9B46, 0xE8D9, 0x9B43, 0xE8DA, 0x9B67, 0xE8DB, 0x9B74, 0xE8DC, 0x9B71, + 0xE8DD, 0x9B66, 0xE8DE, 0x9B76, 0xE8DF, 0x9B75, 0xE8E0, 0x9B70, 0xE8E1, 0x9B68, 0xE8E2, 0x9B64, 0xE8E3, 0x9B6C, 0xE8E4, 0x9CFC, + 0xE8E5, 0x9CFA, 0xE8E6, 0x9CFD, 0xE8E7, 0x9CFF, 0xE8E8, 0x9CF7, 0xE8E9, 0x9D07, 0xE8EA, 0x9D00, 0xE8EB, 0x9CF9, 0xE8EC, 0x9CFB, + 0xE8ED, 0x9D08, 0xE8EE, 0x9D05, 0xE8EF, 0x9D04, 0xE8F0, 0x9E83, 0xE8F1, 0x9ED3, 0xE8F2, 0x9F0F, 0xE8F3, 0x9F10, 0xE8F4, 0x511C, + 0xE8F5, 0x5113, 0xE8F6, 0x5117, 0xE8F7, 0x511A, 0xE8F8, 0x5111, 0xE8F9, 0x51DE, 0xE8FA, 0x5334, 0xE8FB, 0x53E1, 0xE8FC, 0x5670, + 0xE8FD, 0x5660, 0xE8FE, 0x566E, 0xE940, 0x5673, 0xE941, 0x5666, 0xE942, 0x5663, 0xE943, 0x566D, 0xE944, 0x5672, 0xE945, 0x565E, + 0xE946, 0x5677, 0xE947, 0x571C, 0xE948, 0x571B, 0xE949, 0x58C8, 0xE94A, 0x58BD, 0xE94B, 0x58C9, 0xE94C, 0x58BF, 0xE94D, 0x58BA, + 0xE94E, 0x58C2, 0xE94F, 0x58BC, 0xE950, 0x58C6, 0xE951, 0x5B17, 0xE952, 0x5B19, 0xE953, 0x5B1B, 0xE954, 0x5B21, 0xE955, 0x5B14, + 0xE956, 0x5B13, 0xE957, 0x5B10, 0xE958, 0x5B16, 0xE959, 0x5B28, 0xE95A, 0x5B1A, 0xE95B, 0x5B20, 0xE95C, 0x5B1E, 0xE95D, 0x5BEF, + 0xE95E, 0x5DAC, 0xE95F, 0x5DB1, 0xE960, 0x5DA9, 0xE961, 0x5DA7, 0xE962, 0x5DB5, 0xE963, 0x5DB0, 0xE964, 0x5DAE, 0xE965, 0x5DAA, + 0xE966, 0x5DA8, 0xE967, 0x5DB2, 0xE968, 0x5DAD, 0xE969, 0x5DAF, 0xE96A, 0x5DB4, 0xE96B, 0x5E67, 0xE96C, 0x5E68, 0xE96D, 0x5E66, + 0xE96E, 0x5E6F, 0xE96F, 0x5EE9, 0xE970, 0x5EE7, 0xE971, 0x5EE6, 0xE972, 0x5EE8, 0xE973, 0x5EE5, 0xE974, 0x5F4B, 0xE975, 0x5FBC, + 0xE976, 0x619D, 0xE977, 0x61A8, 0xE978, 0x6196, 0xE979, 0x61C5, 0xE97A, 0x61B4, 0xE97B, 0x61C6, 0xE97C, 0x61C1, 0xE97D, 0x61CC, + 0xE97E, 0x61BA, 0xE9A1, 0x61BF, 0xE9A2, 0x61B8, 0xE9A3, 0x618C, 0xE9A4, 0x64D7, 0xE9A5, 0x64D6, 0xE9A6, 0x64D0, 0xE9A7, 0x64CF, + 0xE9A8, 0x64C9, 0xE9A9, 0x64BD, 0xE9AA, 0x6489, 0xE9AB, 0x64C3, 0xE9AC, 0x64DB, 0xE9AD, 0x64F3, 0xE9AE, 0x64D9, 0xE9AF, 0x6533, + 0xE9B0, 0x657F, 0xE9B1, 0x657C, 0xE9B2, 0x65A2, 0xE9B3, 0x66C8, 0xE9B4, 0x66BE, 0xE9B5, 0x66C0, 0xE9B6, 0x66CA, 0xE9B7, 0x66CB, + 0xE9B8, 0x66CF, 0xE9B9, 0x66BD, 0xE9BA, 0x66BB, 0xE9BB, 0x66BA, 0xE9BC, 0x66CC, 0xE9BD, 0x6723, 0xE9BE, 0x6A34, 0xE9BF, 0x6A66, + 0xE9C0, 0x6A49, 0xE9C1, 0x6A67, 0xE9C2, 0x6A32, 0xE9C3, 0x6A68, 0xE9C4, 0x6A3E, 0xE9C5, 0x6A5D, 0xE9C6, 0x6A6D, 0xE9C7, 0x6A76, + 0xE9C8, 0x6A5B, 0xE9C9, 0x6A51, 0xE9CA, 0x6A28, 0xE9CB, 0x6A5A, 0xE9CC, 0x6A3B, 0xE9CD, 0x6A3F, 0xE9CE, 0x6A41, 0xE9CF, 0x6A6A, + 0xE9D0, 0x6A64, 0xE9D1, 0x6A50, 0xE9D2, 0x6A4F, 0xE9D3, 0x6A54, 0xE9D4, 0x6A6F, 0xE9D5, 0x6A69, 0xE9D6, 0x6A60, 0xE9D7, 0x6A3C, + 0xE9D8, 0x6A5E, 0xE9D9, 0x6A56, 0xE9DA, 0x6A55, 0xE9DB, 0x6A4D, 0xE9DC, 0x6A4E, 0xE9DD, 0x6A46, 0xE9DE, 0x6B55, 0xE9DF, 0x6B54, + 0xE9E0, 0x6B56, 0xE9E1, 0x6BA7, 0xE9E2, 0x6BAA, 0xE9E3, 0x6BAB, 0xE9E4, 0x6BC8, 0xE9E5, 0x6BC7, 0xE9E6, 0x6C04, 0xE9E7, 0x6C03, + 0xE9E8, 0x6C06, 0xE9E9, 0x6FAD, 0xE9EA, 0x6FCB, 0xE9EB, 0x6FA3, 0xE9EC, 0x6FC7, 0xE9ED, 0x6FBC, 0xE9EE, 0x6FCE, 0xE9EF, 0x6FC8, + 0xE9F0, 0x6F5E, 0xE9F1, 0x6FC4, 0xE9F2, 0x6FBD, 0xE9F3, 0x6F9E, 0xE9F4, 0x6FCA, 0xE9F5, 0x6FA8, 0xE9F6, 0x7004, 0xE9F7, 0x6FA5, + 0xE9F8, 0x6FAE, 0xE9F9, 0x6FBA, 0xE9FA, 0x6FAC, 0xE9FB, 0x6FAA, 0xE9FC, 0x6FCF, 0xE9FD, 0x6FBF, 0xE9FE, 0x6FB8, 0xEA40, 0x6FA2, + 0xEA41, 0x6FC9, 0xEA42, 0x6FAB, 0xEA43, 0x6FCD, 0xEA44, 0x6FAF, 0xEA45, 0x6FB2, 0xEA46, 0x6FB0, 0xEA47, 0x71C5, 0xEA48, 0x71C2, + 0xEA49, 0x71BF, 0xEA4A, 0x71B8, 0xEA4B, 0x71D6, 0xEA4C, 0x71C0, 0xEA4D, 0x71C1, 0xEA4E, 0x71CB, 0xEA4F, 0x71D4, 0xEA50, 0x71CA, + 0xEA51, 0x71C7, 0xEA52, 0x71CF, 0xEA53, 0x71BD, 0xEA54, 0x71D8, 0xEA55, 0x71BC, 0xEA56, 0x71C6, 0xEA57, 0x71DA, 0xEA58, 0x71DB, + 0xEA59, 0x729D, 0xEA5A, 0x729E, 0xEA5B, 0x7369, 0xEA5C, 0x7366, 0xEA5D, 0x7367, 0xEA5E, 0x736C, 0xEA5F, 0x7365, 0xEA60, 0x736B, + 0xEA61, 0x736A, 0xEA62, 0x747F, 0xEA63, 0x749A, 0xEA64, 0x74A0, 0xEA65, 0x7494, 0xEA66, 0x7492, 0xEA67, 0x7495, 0xEA68, 0x74A1, + 0xEA69, 0x750B, 0xEA6A, 0x7580, 0xEA6B, 0x762F, 0xEA6C, 0x762D, 0xEA6D, 0x7631, 0xEA6E, 0x763D, 0xEA6F, 0x7633, 0xEA70, 0x763C, + 0xEA71, 0x7635, 0xEA72, 0x7632, 0xEA73, 0x7630, 0xEA74, 0x76BB, 0xEA75, 0x76E6, 0xEA76, 0x779A, 0xEA77, 0x779D, 0xEA78, 0x77A1, + 0xEA79, 0x779C, 0xEA7A, 0x779B, 0xEA7B, 0x77A2, 0xEA7C, 0x77A3, 0xEA7D, 0x7795, 0xEA7E, 0x7799, 0xEAA1, 0x7797, 0xEAA2, 0x78DD, + 0xEAA3, 0x78E9, 0xEAA4, 0x78E5, 0xEAA5, 0x78EA, 0xEAA6, 0x78DE, 0xEAA7, 0x78E3, 0xEAA8, 0x78DB, 0xEAA9, 0x78E1, 0xEAAA, 0x78E2, + 0xEAAB, 0x78ED, 0xEAAC, 0x78DF, 0xEAAD, 0x78E0, 0xEAAE, 0x79A4, 0xEAAF, 0x7A44, 0xEAB0, 0x7A48, 0xEAB1, 0x7A47, 0xEAB2, 0x7AB6, + 0xEAB3, 0x7AB8, 0xEAB4, 0x7AB5, 0xEAB5, 0x7AB1, 0xEAB6, 0x7AB7, 0xEAB7, 0x7BDE, 0xEAB8, 0x7BE3, 0xEAB9, 0x7BE7, 0xEABA, 0x7BDD, + 0xEABB, 0x7BD5, 0xEABC, 0x7BE5, 0xEABD, 0x7BDA, 0xEABE, 0x7BE8, 0xEABF, 0x7BF9, 0xEAC0, 0x7BD4, 0xEAC1, 0x7BEA, 0xEAC2, 0x7BE2, + 0xEAC3, 0x7BDC, 0xEAC4, 0x7BEB, 0xEAC5, 0x7BD8, 0xEAC6, 0x7BDF, 0xEAC7, 0x7CD2, 0xEAC8, 0x7CD4, 0xEAC9, 0x7CD7, 0xEACA, 0x7CD0, + 0xEACB, 0x7CD1, 0xEACC, 0x7E12, 0xEACD, 0x7E21, 0xEACE, 0x7E17, 0xEACF, 0x7E0C, 0xEAD0, 0x7E1F, 0xEAD1, 0x7E20, 0xEAD2, 0x7E13, + 0xEAD3, 0x7E0E, 0xEAD4, 0x7E1C, 0xEAD5, 0x7E15, 0xEAD6, 0x7E1A, 0xEAD7, 0x7E22, 0xEAD8, 0x7E0B, 0xEAD9, 0x7E0F, 0xEADA, 0x7E16, + 0xEADB, 0x7E0D, 0xEADC, 0x7E14, 0xEADD, 0x7E25, 0xEADE, 0x7E24, 0xEADF, 0x7F43, 0xEAE0, 0x7F7B, 0xEAE1, 0x7F7C, 0xEAE2, 0x7F7A, + 0xEAE3, 0x7FB1, 0xEAE4, 0x7FEF, 0xEAE5, 0x802A, 0xEAE6, 0x8029, 0xEAE7, 0x806C, 0xEAE8, 0x81B1, 0xEAE9, 0x81A6, 0xEAEA, 0x81AE, + 0xEAEB, 0x81B9, 0xEAEC, 0x81B5, 0xEAED, 0x81AB, 0xEAEE, 0x81B0, 0xEAEF, 0x81AC, 0xEAF0, 0x81B4, 0xEAF1, 0x81B2, 0xEAF2, 0x81B7, + 0xEAF3, 0x81A7, 0xEAF4, 0x81F2, 0xEAF5, 0x8255, 0xEAF6, 0x8256, 0xEAF7, 0x8257, 0xEAF8, 0x8556, 0xEAF9, 0x8545, 0xEAFA, 0x856B, + 0xEAFB, 0x854D, 0xEAFC, 0x8553, 0xEAFD, 0x8561, 0xEAFE, 0x8558, 0xEB40, 0x8540, 0xEB41, 0x8546, 0xEB42, 0x8564, 0xEB43, 0x8541, + 0xEB44, 0x8562, 0xEB45, 0x8544, 0xEB46, 0x8551, 0xEB47, 0x8547, 0xEB48, 0x8563, 0xEB49, 0x853E, 0xEB4A, 0x855B, 0xEB4B, 0x8571, + 0xEB4C, 0x854E, 0xEB4D, 0x856E, 0xEB4E, 0x8575, 0xEB4F, 0x8555, 0xEB50, 0x8567, 0xEB51, 0x8560, 0xEB52, 0x858C, 0xEB53, 0x8566, + 0xEB54, 0x855D, 0xEB55, 0x8554, 0xEB56, 0x8565, 0xEB57, 0x856C, 0xEB58, 0x8663, 0xEB59, 0x8665, 0xEB5A, 0x8664, 0xEB5B, 0x879B, + 0xEB5C, 0x878F, 0xEB5D, 0x8797, 0xEB5E, 0x8793, 0xEB5F, 0x8792, 0xEB60, 0x8788, 0xEB61, 0x8781, 0xEB62, 0x8796, 0xEB63, 0x8798, + 0xEB64, 0x8779, 0xEB65, 0x8787, 0xEB66, 0x87A3, 0xEB67, 0x8785, 0xEB68, 0x8790, 0xEB69, 0x8791, 0xEB6A, 0x879D, 0xEB6B, 0x8784, + 0xEB6C, 0x8794, 0xEB6D, 0x879C, 0xEB6E, 0x879A, 0xEB6F, 0x8789, 0xEB70, 0x891E, 0xEB71, 0x8926, 0xEB72, 0x8930, 0xEB73, 0x892D, + 0xEB74, 0x892E, 0xEB75, 0x8927, 0xEB76, 0x8931, 0xEB77, 0x8922, 0xEB78, 0x8929, 0xEB79, 0x8923, 0xEB7A, 0x892F, 0xEB7B, 0x892C, + 0xEB7C, 0x891F, 0xEB7D, 0x89F1, 0xEB7E, 0x8AE0, 0xEBA1, 0x8AE2, 0xEBA2, 0x8AF2, 0xEBA3, 0x8AF4, 0xEBA4, 0x8AF5, 0xEBA5, 0x8ADD, + 0xEBA6, 0x8B14, 0xEBA7, 0x8AE4, 0xEBA8, 0x8ADF, 0xEBA9, 0x8AF0, 0xEBAA, 0x8AC8, 0xEBAB, 0x8ADE, 0xEBAC, 0x8AE1, 0xEBAD, 0x8AE8, + 0xEBAE, 0x8AFF, 0xEBAF, 0x8AEF, 0xEBB0, 0x8AFB, 0xEBB1, 0x8C91, 0xEBB2, 0x8C92, 0xEBB3, 0x8C90, 0xEBB4, 0x8CF5, 0xEBB5, 0x8CEE, + 0xEBB6, 0x8CF1, 0xEBB7, 0x8CF0, 0xEBB8, 0x8CF3, 0xEBB9, 0x8D6C, 0xEBBA, 0x8D6E, 0xEBBB, 0x8DA5, 0xEBBC, 0x8DA7, 0xEBBD, 0x8E33, + 0xEBBE, 0x8E3E, 0xEBBF, 0x8E38, 0xEBC0, 0x8E40, 0xEBC1, 0x8E45, 0xEBC2, 0x8E36, 0xEBC3, 0x8E3C, 0xEBC4, 0x8E3D, 0xEBC5, 0x8E41, + 0xEBC6, 0x8E30, 0xEBC7, 0x8E3F, 0xEBC8, 0x8EBD, 0xEBC9, 0x8F36, 0xEBCA, 0x8F2E, 0xEBCB, 0x8F35, 0xEBCC, 0x8F32, 0xEBCD, 0x8F39, + 0xEBCE, 0x8F37, 0xEBCF, 0x8F34, 0xEBD0, 0x9076, 0xEBD1, 0x9079, 0xEBD2, 0x907B, 0xEBD3, 0x9086, 0xEBD4, 0x90FA, 0xEBD5, 0x9133, + 0xEBD6, 0x9135, 0xEBD7, 0x9136, 0xEBD8, 0x9193, 0xEBD9, 0x9190, 0xEBDA, 0x9191, 0xEBDB, 0x918D, 0xEBDC, 0x918F, 0xEBDD, 0x9327, + 0xEBDE, 0x931E, 0xEBDF, 0x9308, 0xEBE0, 0x931F, 0xEBE1, 0x9306, 0xEBE2, 0x930F, 0xEBE3, 0x937A, 0xEBE4, 0x9338, 0xEBE5, 0x933C, + 0xEBE6, 0x931B, 0xEBE7, 0x9323, 0xEBE8, 0x9312, 0xEBE9, 0x9301, 0xEBEA, 0x9346, 0xEBEB, 0x932D, 0xEBEC, 0x930E, 0xEBED, 0x930D, + 0xEBEE, 0x92CB, 0xEBEF, 0x931D, 0xEBF0, 0x92FA, 0xEBF1, 0x9325, 0xEBF2, 0x9313, 0xEBF3, 0x92F9, 0xEBF4, 0x92F7, 0xEBF5, 0x9334, + 0xEBF6, 0x9302, 0xEBF7, 0x9324, 0xEBF8, 0x92FF, 0xEBF9, 0x9329, 0xEBFA, 0x9339, 0xEBFB, 0x9335, 0xEBFC, 0x932A, 0xEBFD, 0x9314, + 0xEBFE, 0x930C, 0xEC40, 0x930B, 0xEC41, 0x92FE, 0xEC42, 0x9309, 0xEC43, 0x9300, 0xEC44, 0x92FB, 0xEC45, 0x9316, 0xEC46, 0x95BC, + 0xEC47, 0x95CD, 0xEC48, 0x95BE, 0xEC49, 0x95B9, 0xEC4A, 0x95BA, 0xEC4B, 0x95B6, 0xEC4C, 0x95BF, 0xEC4D, 0x95B5, 0xEC4E, 0x95BD, + 0xEC4F, 0x96A9, 0xEC50, 0x96D4, 0xEC51, 0x970B, 0xEC52, 0x9712, 0xEC53, 0x9710, 0xEC54, 0x9799, 0xEC55, 0x9797, 0xEC56, 0x9794, + 0xEC57, 0x97F0, 0xEC58, 0x97F8, 0xEC59, 0x9835, 0xEC5A, 0x982F, 0xEC5B, 0x9832, 0xEC5C, 0x9924, 0xEC5D, 0x991F, 0xEC5E, 0x9927, + 0xEC5F, 0x9929, 0xEC60, 0x999E, 0xEC61, 0x99EE, 0xEC62, 0x99EC, 0xEC63, 0x99E5, 0xEC64, 0x99E4, 0xEC65, 0x99F0, 0xEC66, 0x99E3, + 0xEC67, 0x99EA, 0xEC68, 0x99E9, 0xEC69, 0x99E7, 0xEC6A, 0x9AB9, 0xEC6B, 0x9ABF, 0xEC6C, 0x9AB4, 0xEC6D, 0x9ABB, 0xEC6E, 0x9AF6, + 0xEC6F, 0x9AFA, 0xEC70, 0x9AF9, 0xEC71, 0x9AF7, 0xEC72, 0x9B33, 0xEC73, 0x9B80, 0xEC74, 0x9B85, 0xEC75, 0x9B87, 0xEC76, 0x9B7C, + 0xEC77, 0x9B7E, 0xEC78, 0x9B7B, 0xEC79, 0x9B82, 0xEC7A, 0x9B93, 0xEC7B, 0x9B92, 0xEC7C, 0x9B90, 0xEC7D, 0x9B7A, 0xEC7E, 0x9B95, + 0xECA1, 0x9B7D, 0xECA2, 0x9B88, 0xECA3, 0x9D25, 0xECA4, 0x9D17, 0xECA5, 0x9D20, 0xECA6, 0x9D1E, 0xECA7, 0x9D14, 0xECA8, 0x9D29, + 0xECA9, 0x9D1D, 0xECAA, 0x9D18, 0xECAB, 0x9D22, 0xECAC, 0x9D10, 0xECAD, 0x9D19, 0xECAE, 0x9D1F, 0xECAF, 0x9E88, 0xECB0, 0x9E86, + 0xECB1, 0x9E87, 0xECB2, 0x9EAE, 0xECB3, 0x9EAD, 0xECB4, 0x9ED5, 0xECB5, 0x9ED6, 0xECB6, 0x9EFA, 0xECB7, 0x9F12, 0xECB8, 0x9F3D, + 0xECB9, 0x5126, 0xECBA, 0x5125, 0xECBB, 0x5122, 0xECBC, 0x5124, 0xECBD, 0x5120, 0xECBE, 0x5129, 0xECBF, 0x52F4, 0xECC0, 0x5693, + 0xECC1, 0x568C, 0xECC2, 0x568D, 0xECC3, 0x5686, 0xECC4, 0x5684, 0xECC5, 0x5683, 0xECC6, 0x567E, 0xECC7, 0x5682, 0xECC8, 0x567F, + 0xECC9, 0x5681, 0xECCA, 0x58D6, 0xECCB, 0x58D4, 0xECCC, 0x58CF, 0xECCD, 0x58D2, 0xECCE, 0x5B2D, 0xECCF, 0x5B25, 0xECD0, 0x5B32, + 0xECD1, 0x5B23, 0xECD2, 0x5B2C, 0xECD3, 0x5B27, 0xECD4, 0x5B26, 0xECD5, 0x5B2F, 0xECD6, 0x5B2E, 0xECD7, 0x5B7B, 0xECD8, 0x5BF1, + 0xECD9, 0x5BF2, 0xECDA, 0x5DB7, 0xECDB, 0x5E6C, 0xECDC, 0x5E6A, 0xECDD, 0x5FBE, 0xECDE, 0x5FBB, 0xECDF, 0x61C3, 0xECE0, 0x61B5, + 0xECE1, 0x61BC, 0xECE2, 0x61E7, 0xECE3, 0x61E0, 0xECE4, 0x61E5, 0xECE5, 0x61E4, 0xECE6, 0x61E8, 0xECE7, 0x61DE, 0xECE8, 0x64EF, + 0xECE9, 0x64E9, 0xECEA, 0x64E3, 0xECEB, 0x64EB, 0xECEC, 0x64E4, 0xECED, 0x64E8, 0xECEE, 0x6581, 0xECEF, 0x6580, 0xECF0, 0x65B6, + 0xECF1, 0x65DA, 0xECF2, 0x66D2, 0xECF3, 0x6A8D, 0xECF4, 0x6A96, 0xECF5, 0x6A81, 0xECF6, 0x6AA5, 0xECF7, 0x6A89, 0xECF8, 0x6A9F, + 0xECF9, 0x6A9B, 0xECFA, 0x6AA1, 0xECFB, 0x6A9E, 0xECFC, 0x6A87, 0xECFD, 0x6A93, 0xECFE, 0x6A8E, 0xED40, 0x6A95, 0xED41, 0x6A83, + 0xED42, 0x6AA8, 0xED43, 0x6AA4, 0xED44, 0x6A91, 0xED45, 0x6A7F, 0xED46, 0x6AA6, 0xED47, 0x6A9A, 0xED48, 0x6A85, 0xED49, 0x6A8C, + 0xED4A, 0x6A92, 0xED4B, 0x6B5B, 0xED4C, 0x6BAD, 0xED4D, 0x6C09, 0xED4E, 0x6FCC, 0xED4F, 0x6FA9, 0xED50, 0x6FF4, 0xED51, 0x6FD4, + 0xED52, 0x6FE3, 0xED53, 0x6FDC, 0xED54, 0x6FED, 0xED55, 0x6FE7, 0xED56, 0x6FE6, 0xED57, 0x6FDE, 0xED58, 0x6FF2, 0xED59, 0x6FDD, + 0xED5A, 0x6FE2, 0xED5B, 0x6FE8, 0xED5C, 0x71E1, 0xED5D, 0x71F1, 0xED5E, 0x71E8, 0xED5F, 0x71F2, 0xED60, 0x71E4, 0xED61, 0x71F0, + 0xED62, 0x71E2, 0xED63, 0x7373, 0xED64, 0x736E, 0xED65, 0x736F, 0xED66, 0x7497, 0xED67, 0x74B2, 0xED68, 0x74AB, 0xED69, 0x7490, + 0xED6A, 0x74AA, 0xED6B, 0x74AD, 0xED6C, 0x74B1, 0xED6D, 0x74A5, 0xED6E, 0x74AF, 0xED6F, 0x7510, 0xED70, 0x7511, 0xED71, 0x7512, + 0xED72, 0x750F, 0xED73, 0x7584, 0xED74, 0x7643, 0xED75, 0x7648, 0xED76, 0x7649, 0xED77, 0x7647, 0xED78, 0x76A4, 0xED79, 0x76E9, + 0xED7A, 0x77B5, 0xED7B, 0x77AB, 0xED7C, 0x77B2, 0xED7D, 0x77B7, 0xED7E, 0x77B6, 0xEDA1, 0x77B4, 0xEDA2, 0x77B1, 0xEDA3, 0x77A8, + 0xEDA4, 0x77F0, 0xEDA5, 0x78F3, 0xEDA6, 0x78FD, 0xEDA7, 0x7902, 0xEDA8, 0x78FB, 0xEDA9, 0x78FC, 0xEDAA, 0x78F2, 0xEDAB, 0x7905, + 0xEDAC, 0x78F9, 0xEDAD, 0x78FE, 0xEDAE, 0x7904, 0xEDAF, 0x79AB, 0xEDB0, 0x79A8, 0xEDB1, 0x7A5C, 0xEDB2, 0x7A5B, 0xEDB3, 0x7A56, + 0xEDB4, 0x7A58, 0xEDB5, 0x7A54, 0xEDB6, 0x7A5A, 0xEDB7, 0x7ABE, 0xEDB8, 0x7AC0, 0xEDB9, 0x7AC1, 0xEDBA, 0x7C05, 0xEDBB, 0x7C0F, + 0xEDBC, 0x7BF2, 0xEDBD, 0x7C00, 0xEDBE, 0x7BFF, 0xEDBF, 0x7BFB, 0xEDC0, 0x7C0E, 0xEDC1, 0x7BF4, 0xEDC2, 0x7C0B, 0xEDC3, 0x7BF3, + 0xEDC4, 0x7C02, 0xEDC5, 0x7C09, 0xEDC6, 0x7C03, 0xEDC7, 0x7C01, 0xEDC8, 0x7BF8, 0xEDC9, 0x7BFD, 0xEDCA, 0x7C06, 0xEDCB, 0x7BF0, + 0xEDCC, 0x7BF1, 0xEDCD, 0x7C10, 0xEDCE, 0x7C0A, 0xEDCF, 0x7CE8, 0xEDD0, 0x7E2D, 0xEDD1, 0x7E3C, 0xEDD2, 0x7E42, 0xEDD3, 0x7E33, + 0xEDD4, 0x9848, 0xEDD5, 0x7E38, 0xEDD6, 0x7E2A, 0xEDD7, 0x7E49, 0xEDD8, 0x7E40, 0xEDD9, 0x7E47, 0xEDDA, 0x7E29, 0xEDDB, 0x7E4C, + 0xEDDC, 0x7E30, 0xEDDD, 0x7E3B, 0xEDDE, 0x7E36, 0xEDDF, 0x7E44, 0xEDE0, 0x7E3A, 0xEDE1, 0x7F45, 0xEDE2, 0x7F7F, 0xEDE3, 0x7F7E, + 0xEDE4, 0x7F7D, 0xEDE5, 0x7FF4, 0xEDE6, 0x7FF2, 0xEDE7, 0x802C, 0xEDE8, 0x81BB, 0xEDE9, 0x81C4, 0xEDEA, 0x81CC, 0xEDEB, 0x81CA, + 0xEDEC, 0x81C5, 0xEDED, 0x81C7, 0xEDEE, 0x81BC, 0xEDEF, 0x81E9, 0xEDF0, 0x825B, 0xEDF1, 0x825A, 0xEDF2, 0x825C, 0xEDF3, 0x8583, + 0xEDF4, 0x8580, 0xEDF5, 0x858F, 0xEDF6, 0x85A7, 0xEDF7, 0x8595, 0xEDF8, 0x85A0, 0xEDF9, 0x858B, 0xEDFA, 0x85A3, 0xEDFB, 0x857B, + 0xEDFC, 0x85A4, 0xEDFD, 0x859A, 0xEDFE, 0x859E, 0xEE40, 0x8577, 0xEE41, 0x857C, 0xEE42, 0x8589, 0xEE43, 0x85A1, 0xEE44, 0x857A, + 0xEE45, 0x8578, 0xEE46, 0x8557, 0xEE47, 0x858E, 0xEE48, 0x8596, 0xEE49, 0x8586, 0xEE4A, 0x858D, 0xEE4B, 0x8599, 0xEE4C, 0x859D, + 0xEE4D, 0x8581, 0xEE4E, 0x85A2, 0xEE4F, 0x8582, 0xEE50, 0x8588, 0xEE51, 0x8585, 0xEE52, 0x8579, 0xEE53, 0x8576, 0xEE54, 0x8598, + 0xEE55, 0x8590, 0xEE56, 0x859F, 0xEE57, 0x8668, 0xEE58, 0x87BE, 0xEE59, 0x87AA, 0xEE5A, 0x87AD, 0xEE5B, 0x87C5, 0xEE5C, 0x87B0, + 0xEE5D, 0x87AC, 0xEE5E, 0x87B9, 0xEE5F, 0x87B5, 0xEE60, 0x87BC, 0xEE61, 0x87AE, 0xEE62, 0x87C9, 0xEE63, 0x87C3, 0xEE64, 0x87C2, + 0xEE65, 0x87CC, 0xEE66, 0x87B7, 0xEE67, 0x87AF, 0xEE68, 0x87C4, 0xEE69, 0x87CA, 0xEE6A, 0x87B4, 0xEE6B, 0x87B6, 0xEE6C, 0x87BF, + 0xEE6D, 0x87B8, 0xEE6E, 0x87BD, 0xEE6F, 0x87DE, 0xEE70, 0x87B2, 0xEE71, 0x8935, 0xEE72, 0x8933, 0xEE73, 0x893C, 0xEE74, 0x893E, + 0xEE75, 0x8941, 0xEE76, 0x8952, 0xEE77, 0x8937, 0xEE78, 0x8942, 0xEE79, 0x89AD, 0xEE7A, 0x89AF, 0xEE7B, 0x89AE, 0xEE7C, 0x89F2, + 0xEE7D, 0x89F3, 0xEE7E, 0x8B1E, 0xEEA1, 0x8B18, 0xEEA2, 0x8B16, 0xEEA3, 0x8B11, 0xEEA4, 0x8B05, 0xEEA5, 0x8B0B, 0xEEA6, 0x8B22, + 0xEEA7, 0x8B0F, 0xEEA8, 0x8B12, 0xEEA9, 0x8B15, 0xEEAA, 0x8B07, 0xEEAB, 0x8B0D, 0xEEAC, 0x8B08, 0xEEAD, 0x8B06, 0xEEAE, 0x8B1C, + 0xEEAF, 0x8B13, 0xEEB0, 0x8B1A, 0xEEB1, 0x8C4F, 0xEEB2, 0x8C70, 0xEEB3, 0x8C72, 0xEEB4, 0x8C71, 0xEEB5, 0x8C6F, 0xEEB6, 0x8C95, + 0xEEB7, 0x8C94, 0xEEB8, 0x8CF9, 0xEEB9, 0x8D6F, 0xEEBA, 0x8E4E, 0xEEBB, 0x8E4D, 0xEEBC, 0x8E53, 0xEEBD, 0x8E50, 0xEEBE, 0x8E4C, + 0xEEBF, 0x8E47, 0xEEC0, 0x8F43, 0xEEC1, 0x8F40, 0xEEC2, 0x9085, 0xEEC3, 0x907E, 0xEEC4, 0x9138, 0xEEC5, 0x919A, 0xEEC6, 0x91A2, + 0xEEC7, 0x919B, 0xEEC8, 0x9199, 0xEEC9, 0x919F, 0xEECA, 0x91A1, 0xEECB, 0x919D, 0xEECC, 0x91A0, 0xEECD, 0x93A1, 0xEECE, 0x9383, + 0xEECF, 0x93AF, 0xEED0, 0x9364, 0xEED1, 0x9356, 0xEED2, 0x9347, 0xEED3, 0x937C, 0xEED4, 0x9358, 0xEED5, 0x935C, 0xEED6, 0x9376, + 0xEED7, 0x9349, 0xEED8, 0x9350, 0xEED9, 0x9351, 0xEEDA, 0x9360, 0xEEDB, 0x936D, 0xEEDC, 0x938F, 0xEEDD, 0x934C, 0xEEDE, 0x936A, + 0xEEDF, 0x9379, 0xEEE0, 0x9357, 0xEEE1, 0x9355, 0xEEE2, 0x9352, 0xEEE3, 0x934F, 0xEEE4, 0x9371, 0xEEE5, 0x9377, 0xEEE6, 0x937B, + 0xEEE7, 0x9361, 0xEEE8, 0x935E, 0xEEE9, 0x9363, 0xEEEA, 0x9367, 0xEEEB, 0x9380, 0xEEEC, 0x934E, 0xEEED, 0x9359, 0xEEEE, 0x95C7, + 0xEEEF, 0x95C0, 0xEEF0, 0x95C9, 0xEEF1, 0x95C3, 0xEEF2, 0x95C5, 0xEEF3, 0x95B7, 0xEEF4, 0x96AE, 0xEEF5, 0x96B0, 0xEEF6, 0x96AC, + 0xEEF7, 0x9720, 0xEEF8, 0x971F, 0xEEF9, 0x9718, 0xEEFA, 0x971D, 0xEEFB, 0x9719, 0xEEFC, 0x979A, 0xEEFD, 0x97A1, 0xEEFE, 0x979C, + 0xEF40, 0x979E, 0xEF41, 0x979D, 0xEF42, 0x97D5, 0xEF43, 0x97D4, 0xEF44, 0x97F1, 0xEF45, 0x9841, 0xEF46, 0x9844, 0xEF47, 0x984A, + 0xEF48, 0x9849, 0xEF49, 0x9845, 0xEF4A, 0x9843, 0xEF4B, 0x9925, 0xEF4C, 0x992B, 0xEF4D, 0x992C, 0xEF4E, 0x992A, 0xEF4F, 0x9933, + 0xEF50, 0x9932, 0xEF51, 0x992F, 0xEF52, 0x992D, 0xEF53, 0x9931, 0xEF54, 0x9930, 0xEF55, 0x9998, 0xEF56, 0x99A3, 0xEF57, 0x99A1, + 0xEF58, 0x9A02, 0xEF59, 0x99FA, 0xEF5A, 0x99F4, 0xEF5B, 0x99F7, 0xEF5C, 0x99F9, 0xEF5D, 0x99F8, 0xEF5E, 0x99F6, 0xEF5F, 0x99FB, + 0xEF60, 0x99FD, 0xEF61, 0x99FE, 0xEF62, 0x99FC, 0xEF63, 0x9A03, 0xEF64, 0x9ABE, 0xEF65, 0x9AFE, 0xEF66, 0x9AFD, 0xEF67, 0x9B01, + 0xEF68, 0x9AFC, 0xEF69, 0x9B48, 0xEF6A, 0x9B9A, 0xEF6B, 0x9BA8, 0xEF6C, 0x9B9E, 0xEF6D, 0x9B9B, 0xEF6E, 0x9BA6, 0xEF6F, 0x9BA1, + 0xEF70, 0x9BA5, 0xEF71, 0x9BA4, 0xEF72, 0x9B86, 0xEF73, 0x9BA2, 0xEF74, 0x9BA0, 0xEF75, 0x9BAF, 0xEF76, 0x9D33, 0xEF77, 0x9D41, + 0xEF78, 0x9D67, 0xEF79, 0x9D36, 0xEF7A, 0x9D2E, 0xEF7B, 0x9D2F, 0xEF7C, 0x9D31, 0xEF7D, 0x9D38, 0xEF7E, 0x9D30, 0xEFA1, 0x9D45, + 0xEFA2, 0x9D42, 0xEFA3, 0x9D43, 0xEFA4, 0x9D3E, 0xEFA5, 0x9D37, 0xEFA6, 0x9D40, 0xEFA7, 0x9D3D, 0xEFA8, 0x7FF5, 0xEFA9, 0x9D2D, + 0xEFAA, 0x9E8A, 0xEFAB, 0x9E89, 0xEFAC, 0x9E8D, 0xEFAD, 0x9EB0, 0xEFAE, 0x9EC8, 0xEFAF, 0x9EDA, 0xEFB0, 0x9EFB, 0xEFB1, 0x9EFF, + 0xEFB2, 0x9F24, 0xEFB3, 0x9F23, 0xEFB4, 0x9F22, 0xEFB5, 0x9F54, 0xEFB6, 0x9FA0, 0xEFB7, 0x5131, 0xEFB8, 0x512D, 0xEFB9, 0x512E, + 0xEFBA, 0x5698, 0xEFBB, 0x569C, 0xEFBC, 0x5697, 0xEFBD, 0x569A, 0xEFBE, 0x569D, 0xEFBF, 0x5699, 0xEFC0, 0x5970, 0xEFC1, 0x5B3C, + 0xEFC2, 0x5C69, 0xEFC3, 0x5C6A, 0xEFC4, 0x5DC0, 0xEFC5, 0x5E6D, 0xEFC6, 0x5E6E, 0xEFC7, 0x61D8, 0xEFC8, 0x61DF, 0xEFC9, 0x61ED, + 0xEFCA, 0x61EE, 0xEFCB, 0x61F1, 0xEFCC, 0x61EA, 0xEFCD, 0x61F0, 0xEFCE, 0x61EB, 0xEFCF, 0x61D6, 0xEFD0, 0x61E9, 0xEFD1, 0x64FF, + 0xEFD2, 0x6504, 0xEFD3, 0x64FD, 0xEFD4, 0x64F8, 0xEFD5, 0x6501, 0xEFD6, 0x6503, 0xEFD7, 0x64FC, 0xEFD8, 0x6594, 0xEFD9, 0x65DB, + 0xEFDA, 0x66DA, 0xEFDB, 0x66DB, 0xEFDC, 0x66D8, 0xEFDD, 0x6AC5, 0xEFDE, 0x6AB9, 0xEFDF, 0x6ABD, 0xEFE0, 0x6AE1, 0xEFE1, 0x6AC6, + 0xEFE2, 0x6ABA, 0xEFE3, 0x6AB6, 0xEFE4, 0x6AB7, 0xEFE5, 0x6AC7, 0xEFE6, 0x6AB4, 0xEFE7, 0x6AAD, 0xEFE8, 0x6B5E, 0xEFE9, 0x6BC9, + 0xEFEA, 0x6C0B, 0xEFEB, 0x7007, 0xEFEC, 0x700C, 0xEFED, 0x700D, 0xEFEE, 0x7001, 0xEFEF, 0x7005, 0xEFF0, 0x7014, 0xEFF1, 0x700E, + 0xEFF2, 0x6FFF, 0xEFF3, 0x7000, 0xEFF4, 0x6FFB, 0xEFF5, 0x7026, 0xEFF6, 0x6FFC, 0xEFF7, 0x6FF7, 0xEFF8, 0x700A, 0xEFF9, 0x7201, + 0xEFFA, 0x71FF, 0xEFFB, 0x71F9, 0xEFFC, 0x7203, 0xEFFD, 0x71FD, 0xEFFE, 0x7376, 0xF040, 0x74B8, 0xF041, 0x74C0, 0xF042, 0x74B5, + 0xF043, 0x74C1, 0xF044, 0x74BE, 0xF045, 0x74B6, 0xF046, 0x74BB, 0xF047, 0x74C2, 0xF048, 0x7514, 0xF049, 0x7513, 0xF04A, 0x765C, + 0xF04B, 0x7664, 0xF04C, 0x7659, 0xF04D, 0x7650, 0xF04E, 0x7653, 0xF04F, 0x7657, 0xF050, 0x765A, 0xF051, 0x76A6, 0xF052, 0x76BD, + 0xF053, 0x76EC, 0xF054, 0x77C2, 0xF055, 0x77BA, 0xF056, 0x78FF, 0xF057, 0x790C, 0xF058, 0x7913, 0xF059, 0x7914, 0xF05A, 0x7909, + 0xF05B, 0x7910, 0xF05C, 0x7912, 0xF05D, 0x7911, 0xF05E, 0x79AD, 0xF05F, 0x79AC, 0xF060, 0x7A5F, 0xF061, 0x7C1C, 0xF062, 0x7C29, + 0xF063, 0x7C19, 0xF064, 0x7C20, 0xF065, 0x7C1F, 0xF066, 0x7C2D, 0xF067, 0x7C1D, 0xF068, 0x7C26, 0xF069, 0x7C28, 0xF06A, 0x7C22, + 0xF06B, 0x7C25, 0xF06C, 0x7C30, 0xF06D, 0x7E5C, 0xF06E, 0x7E50, 0xF06F, 0x7E56, 0xF070, 0x7E63, 0xF071, 0x7E58, 0xF072, 0x7E62, + 0xF073, 0x7E5F, 0xF074, 0x7E51, 0xF075, 0x7E60, 0xF076, 0x7E57, 0xF077, 0x7E53, 0xF078, 0x7FB5, 0xF079, 0x7FB3, 0xF07A, 0x7FF7, + 0xF07B, 0x7FF8, 0xF07C, 0x8075, 0xF07D, 0x81D1, 0xF07E, 0x81D2, 0xF0A1, 0x81D0, 0xF0A2, 0x825F, 0xF0A3, 0x825E, 0xF0A4, 0x85B4, + 0xF0A5, 0x85C6, 0xF0A6, 0x85C0, 0xF0A7, 0x85C3, 0xF0A8, 0x85C2, 0xF0A9, 0x85B3, 0xF0AA, 0x85B5, 0xF0AB, 0x85BD, 0xF0AC, 0x85C7, + 0xF0AD, 0x85C4, 0xF0AE, 0x85BF, 0xF0AF, 0x85CB, 0xF0B0, 0x85CE, 0xF0B1, 0x85C8, 0xF0B2, 0x85C5, 0xF0B3, 0x85B1, 0xF0B4, 0x85B6, + 0xF0B5, 0x85D2, 0xF0B6, 0x8624, 0xF0B7, 0x85B8, 0xF0B8, 0x85B7, 0xF0B9, 0x85BE, 0xF0BA, 0x8669, 0xF0BB, 0x87E7, 0xF0BC, 0x87E6, + 0xF0BD, 0x87E2, 0xF0BE, 0x87DB, 0xF0BF, 0x87EB, 0xF0C0, 0x87EA, 0xF0C1, 0x87E5, 0xF0C2, 0x87DF, 0xF0C3, 0x87F3, 0xF0C4, 0x87E4, + 0xF0C5, 0x87D4, 0xF0C6, 0x87DC, 0xF0C7, 0x87D3, 0xF0C8, 0x87ED, 0xF0C9, 0x87D8, 0xF0CA, 0x87E3, 0xF0CB, 0x87A4, 0xF0CC, 0x87D7, + 0xF0CD, 0x87D9, 0xF0CE, 0x8801, 0xF0CF, 0x87F4, 0xF0D0, 0x87E8, 0xF0D1, 0x87DD, 0xF0D2, 0x8953, 0xF0D3, 0x894B, 0xF0D4, 0x894F, + 0xF0D5, 0x894C, 0xF0D6, 0x8946, 0xF0D7, 0x8950, 0xF0D8, 0x8951, 0xF0D9, 0x8949, 0xF0DA, 0x8B2A, 0xF0DB, 0x8B27, 0xF0DC, 0x8B23, + 0xF0DD, 0x8B33, 0xF0DE, 0x8B30, 0xF0DF, 0x8B35, 0xF0E0, 0x8B47, 0xF0E1, 0x8B2F, 0xF0E2, 0x8B3C, 0xF0E3, 0x8B3E, 0xF0E4, 0x8B31, + 0xF0E5, 0x8B25, 0xF0E6, 0x8B37, 0xF0E7, 0x8B26, 0xF0E8, 0x8B36, 0xF0E9, 0x8B2E, 0xF0EA, 0x8B24, 0xF0EB, 0x8B3B, 0xF0EC, 0x8B3D, + 0xF0ED, 0x8B3A, 0xF0EE, 0x8C42, 0xF0EF, 0x8C75, 0xF0F0, 0x8C99, 0xF0F1, 0x8C98, 0xF0F2, 0x8C97, 0xF0F3, 0x8CFE, 0xF0F4, 0x8D04, + 0xF0F5, 0x8D02, 0xF0F6, 0x8D00, 0xF0F7, 0x8E5C, 0xF0F8, 0x8E62, 0xF0F9, 0x8E60, 0xF0FA, 0x8E57, 0xF0FB, 0x8E56, 0xF0FC, 0x8E5E, + 0xF0FD, 0x8E65, 0xF0FE, 0x8E67, 0xF140, 0x8E5B, 0xF141, 0x8E5A, 0xF142, 0x8E61, 0xF143, 0x8E5D, 0xF144, 0x8E69, 0xF145, 0x8E54, + 0xF146, 0x8F46, 0xF147, 0x8F47, 0xF148, 0x8F48, 0xF149, 0x8F4B, 0xF14A, 0x9128, 0xF14B, 0x913A, 0xF14C, 0x913B, 0xF14D, 0x913E, + 0xF14E, 0x91A8, 0xF14F, 0x91A5, 0xF150, 0x91A7, 0xF151, 0x91AF, 0xF152, 0x91AA, 0xF153, 0x93B5, 0xF154, 0x938C, 0xF155, 0x9392, + 0xF156, 0x93B7, 0xF157, 0x939B, 0xF158, 0x939D, 0xF159, 0x9389, 0xF15A, 0x93A7, 0xF15B, 0x938E, 0xF15C, 0x93AA, 0xF15D, 0x939E, + 0xF15E, 0x93A6, 0xF15F, 0x9395, 0xF160, 0x9388, 0xF161, 0x9399, 0xF162, 0x939F, 0xF163, 0x938D, 0xF164, 0x93B1, 0xF165, 0x9391, + 0xF166, 0x93B2, 0xF167, 0x93A4, 0xF168, 0x93A8, 0xF169, 0x93B4, 0xF16A, 0x93A3, 0xF16B, 0x93A5, 0xF16C, 0x95D2, 0xF16D, 0x95D3, + 0xF16E, 0x95D1, 0xF16F, 0x96B3, 0xF170, 0x96D7, 0xF171, 0x96DA, 0xF172, 0x5DC2, 0xF173, 0x96DF, 0xF174, 0x96D8, 0xF175, 0x96DD, + 0xF176, 0x9723, 0xF177, 0x9722, 0xF178, 0x9725, 0xF179, 0x97AC, 0xF17A, 0x97AE, 0xF17B, 0x97A8, 0xF17C, 0x97AB, 0xF17D, 0x97A4, + 0xF17E, 0x97AA, 0xF1A1, 0x97A2, 0xF1A2, 0x97A5, 0xF1A3, 0x97D7, 0xF1A4, 0x97D9, 0xF1A5, 0x97D6, 0xF1A6, 0x97D8, 0xF1A7, 0x97FA, + 0xF1A8, 0x9850, 0xF1A9, 0x9851, 0xF1AA, 0x9852, 0xF1AB, 0x98B8, 0xF1AC, 0x9941, 0xF1AD, 0x993C, 0xF1AE, 0x993A, 0xF1AF, 0x9A0F, + 0xF1B0, 0x9A0B, 0xF1B1, 0x9A09, 0xF1B2, 0x9A0D, 0xF1B3, 0x9A04, 0xF1B4, 0x9A11, 0xF1B5, 0x9A0A, 0xF1B6, 0x9A05, 0xF1B7, 0x9A07, + 0xF1B8, 0x9A06, 0xF1B9, 0x9AC0, 0xF1BA, 0x9ADC, 0xF1BB, 0x9B08, 0xF1BC, 0x9B04, 0xF1BD, 0x9B05, 0xF1BE, 0x9B29, 0xF1BF, 0x9B35, + 0xF1C0, 0x9B4A, 0xF1C1, 0x9B4C, 0xF1C2, 0x9B4B, 0xF1C3, 0x9BC7, 0xF1C4, 0x9BC6, 0xF1C5, 0x9BC3, 0xF1C6, 0x9BBF, 0xF1C7, 0x9BC1, + 0xF1C8, 0x9BB5, 0xF1C9, 0x9BB8, 0xF1CA, 0x9BD3, 0xF1CB, 0x9BB6, 0xF1CC, 0x9BC4, 0xF1CD, 0x9BB9, 0xF1CE, 0x9BBD, 0xF1CF, 0x9D5C, + 0xF1D0, 0x9D53, 0xF1D1, 0x9D4F, 0xF1D2, 0x9D4A, 0xF1D3, 0x9D5B, 0xF1D4, 0x9D4B, 0xF1D5, 0x9D59, 0xF1D6, 0x9D56, 0xF1D7, 0x9D4C, + 0xF1D8, 0x9D57, 0xF1D9, 0x9D52, 0xF1DA, 0x9D54, 0xF1DB, 0x9D5F, 0xF1DC, 0x9D58, 0xF1DD, 0x9D5A, 0xF1DE, 0x9E8E, 0xF1DF, 0x9E8C, + 0xF1E0, 0x9EDF, 0xF1E1, 0x9F01, 0xF1E2, 0x9F00, 0xF1E3, 0x9F16, 0xF1E4, 0x9F25, 0xF1E5, 0x9F2B, 0xF1E6, 0x9F2A, 0xF1E7, 0x9F29, + 0xF1E8, 0x9F28, 0xF1E9, 0x9F4C, 0xF1EA, 0x9F55, 0xF1EB, 0x5134, 0xF1EC, 0x5135, 0xF1ED, 0x5296, 0xF1EE, 0x52F7, 0xF1EF, 0x53B4, + 0xF1F0, 0x56AB, 0xF1F1, 0x56AD, 0xF1F2, 0x56A6, 0xF1F3, 0x56A7, 0xF1F4, 0x56AA, 0xF1F5, 0x56AC, 0xF1F6, 0x58DA, 0xF1F7, 0x58DD, + 0xF1F8, 0x58DB, 0xF1F9, 0x5912, 0xF1FA, 0x5B3D, 0xF1FB, 0x5B3E, 0xF1FC, 0x5B3F, 0xF1FD, 0x5DC3, 0xF1FE, 0x5E70, 0xF240, 0x5FBF, + 0xF241, 0x61FB, 0xF242, 0x6507, 0xF243, 0x6510, 0xF244, 0x650D, 0xF245, 0x6509, 0xF246, 0x650C, 0xF247, 0x650E, 0xF248, 0x6584, + 0xF249, 0x65DE, 0xF24A, 0x65DD, 0xF24B, 0x66DE, 0xF24C, 0x6AE7, 0xF24D, 0x6AE0, 0xF24E, 0x6ACC, 0xF24F, 0x6AD1, 0xF250, 0x6AD9, + 0xF251, 0x6ACB, 0xF252, 0x6ADF, 0xF253, 0x6ADC, 0xF254, 0x6AD0, 0xF255, 0x6AEB, 0xF256, 0x6ACF, 0xF257, 0x6ACD, 0xF258, 0x6ADE, + 0xF259, 0x6B60, 0xF25A, 0x6BB0, 0xF25B, 0x6C0C, 0xF25C, 0x7019, 0xF25D, 0x7027, 0xF25E, 0x7020, 0xF25F, 0x7016, 0xF260, 0x702B, + 0xF261, 0x7021, 0xF262, 0x7022, 0xF263, 0x7023, 0xF264, 0x7029, 0xF265, 0x7017, 0xF266, 0x7024, 0xF267, 0x701C, 0xF268, 0x702A, + 0xF269, 0x720C, 0xF26A, 0x720A, 0xF26B, 0x7207, 0xF26C, 0x7202, 0xF26D, 0x7205, 0xF26E, 0x72A5, 0xF26F, 0x72A6, 0xF270, 0x72A4, + 0xF271, 0x72A3, 0xF272, 0x72A1, 0xF273, 0x74CB, 0xF274, 0x74C5, 0xF275, 0x74B7, 0xF276, 0x74C3, 0xF277, 0x7516, 0xF278, 0x7660, + 0xF279, 0x77C9, 0xF27A, 0x77CA, 0xF27B, 0x77C4, 0xF27C, 0x77F1, 0xF27D, 0x791D, 0xF27E, 0x791B, 0xF2A1, 0x7921, 0xF2A2, 0x791C, + 0xF2A3, 0x7917, 0xF2A4, 0x791E, 0xF2A5, 0x79B0, 0xF2A6, 0x7A67, 0xF2A7, 0x7A68, 0xF2A8, 0x7C33, 0xF2A9, 0x7C3C, 0xF2AA, 0x7C39, + 0xF2AB, 0x7C2C, 0xF2AC, 0x7C3B, 0xF2AD, 0x7CEC, 0xF2AE, 0x7CEA, 0xF2AF, 0x7E76, 0xF2B0, 0x7E75, 0xF2B1, 0x7E78, 0xF2B2, 0x7E70, + 0xF2B3, 0x7E77, 0xF2B4, 0x7E6F, 0xF2B5, 0x7E7A, 0xF2B6, 0x7E72, 0xF2B7, 0x7E74, 0xF2B8, 0x7E68, 0xF2B9, 0x7F4B, 0xF2BA, 0x7F4A, + 0xF2BB, 0x7F83, 0xF2BC, 0x7F86, 0xF2BD, 0x7FB7, 0xF2BE, 0x7FFD, 0xF2BF, 0x7FFE, 0xF2C0, 0x8078, 0xF2C1, 0x81D7, 0xF2C2, 0x81D5, + 0xF2C3, 0x8264, 0xF2C4, 0x8261, 0xF2C5, 0x8263, 0xF2C6, 0x85EB, 0xF2C7, 0x85F1, 0xF2C8, 0x85ED, 0xF2C9, 0x85D9, 0xF2CA, 0x85E1, + 0xF2CB, 0x85E8, 0xF2CC, 0x85DA, 0xF2CD, 0x85D7, 0xF2CE, 0x85EC, 0xF2CF, 0x85F2, 0xF2D0, 0x85F8, 0xF2D1, 0x85D8, 0xF2D2, 0x85DF, + 0xF2D3, 0x85E3, 0xF2D4, 0x85DC, 0xF2D5, 0x85D1, 0xF2D6, 0x85F0, 0xF2D7, 0x85E6, 0xF2D8, 0x85EF, 0xF2D9, 0x85DE, 0xF2DA, 0x85E2, + 0xF2DB, 0x8800, 0xF2DC, 0x87FA, 0xF2DD, 0x8803, 0xF2DE, 0x87F6, 0xF2DF, 0x87F7, 0xF2E0, 0x8809, 0xF2E1, 0x880C, 0xF2E2, 0x880B, + 0xF2E3, 0x8806, 0xF2E4, 0x87FC, 0xF2E5, 0x8808, 0xF2E6, 0x87FF, 0xF2E7, 0x880A, 0xF2E8, 0x8802, 0xF2E9, 0x8962, 0xF2EA, 0x895A, + 0xF2EB, 0x895B, 0xF2EC, 0x8957, 0xF2ED, 0x8961, 0xF2EE, 0x895C, 0xF2EF, 0x8958, 0xF2F0, 0x895D, 0xF2F1, 0x8959, 0xF2F2, 0x8988, + 0xF2F3, 0x89B7, 0xF2F4, 0x89B6, 0xF2F5, 0x89F6, 0xF2F6, 0x8B50, 0xF2F7, 0x8B48, 0xF2F8, 0x8B4A, 0xF2F9, 0x8B40, 0xF2FA, 0x8B53, + 0xF2FB, 0x8B56, 0xF2FC, 0x8B54, 0xF2FD, 0x8B4B, 0xF2FE, 0x8B55, 0xF340, 0x8B51, 0xF341, 0x8B42, 0xF342, 0x8B52, 0xF343, 0x8B57, + 0xF344, 0x8C43, 0xF345, 0x8C77, 0xF346, 0x8C76, 0xF347, 0x8C9A, 0xF348, 0x8D06, 0xF349, 0x8D07, 0xF34A, 0x8D09, 0xF34B, 0x8DAC, + 0xF34C, 0x8DAA, 0xF34D, 0x8DAD, 0xF34E, 0x8DAB, 0xF34F, 0x8E6D, 0xF350, 0x8E78, 0xF351, 0x8E73, 0xF352, 0x8E6A, 0xF353, 0x8E6F, + 0xF354, 0x8E7B, 0xF355, 0x8EC2, 0xF356, 0x8F52, 0xF357, 0x8F51, 0xF358, 0x8F4F, 0xF359, 0x8F50, 0xF35A, 0x8F53, 0xF35B, 0x8FB4, + 0xF35C, 0x9140, 0xF35D, 0x913F, 0xF35E, 0x91B0, 0xF35F, 0x91AD, 0xF360, 0x93DE, 0xF361, 0x93C7, 0xF362, 0x93CF, 0xF363, 0x93C2, + 0xF364, 0x93DA, 0xF365, 0x93D0, 0xF366, 0x93F9, 0xF367, 0x93EC, 0xF368, 0x93CC, 0xF369, 0x93D9, 0xF36A, 0x93A9, 0xF36B, 0x93E6, + 0xF36C, 0x93CA, 0xF36D, 0x93D4, 0xF36E, 0x93EE, 0xF36F, 0x93E3, 0xF370, 0x93D5, 0xF371, 0x93C4, 0xF372, 0x93CE, 0xF373, 0x93C0, + 0xF374, 0x93D2, 0xF375, 0x93E7, 0xF376, 0x957D, 0xF377, 0x95DA, 0xF378, 0x95DB, 0xF379, 0x96E1, 0xF37A, 0x9729, 0xF37B, 0x972B, + 0xF37C, 0x972C, 0xF37D, 0x9728, 0xF37E, 0x9726, 0xF3A1, 0x97B3, 0xF3A2, 0x97B7, 0xF3A3, 0x97B6, 0xF3A4, 0x97DD, 0xF3A5, 0x97DE, + 0xF3A6, 0x97DF, 0xF3A7, 0x985C, 0xF3A8, 0x9859, 0xF3A9, 0x985D, 0xF3AA, 0x9857, 0xF3AB, 0x98BF, 0xF3AC, 0x98BD, 0xF3AD, 0x98BB, + 0xF3AE, 0x98BE, 0xF3AF, 0x9948, 0xF3B0, 0x9947, 0xF3B1, 0x9943, 0xF3B2, 0x99A6, 0xF3B3, 0x99A7, 0xF3B4, 0x9A1A, 0xF3B5, 0x9A15, + 0xF3B6, 0x9A25, 0xF3B7, 0x9A1D, 0xF3B8, 0x9A24, 0xF3B9, 0x9A1B, 0xF3BA, 0x9A22, 0xF3BB, 0x9A20, 0xF3BC, 0x9A27, 0xF3BD, 0x9A23, + 0xF3BE, 0x9A1E, 0xF3BF, 0x9A1C, 0xF3C0, 0x9A14, 0xF3C1, 0x9AC2, 0xF3C2, 0x9B0B, 0xF3C3, 0x9B0A, 0xF3C4, 0x9B0E, 0xF3C5, 0x9B0C, + 0xF3C6, 0x9B37, 0xF3C7, 0x9BEA, 0xF3C8, 0x9BEB, 0xF3C9, 0x9BE0, 0xF3CA, 0x9BDE, 0xF3CB, 0x9BE4, 0xF3CC, 0x9BE6, 0xF3CD, 0x9BE2, + 0xF3CE, 0x9BF0, 0xF3CF, 0x9BD4, 0xF3D0, 0x9BD7, 0xF3D1, 0x9BEC, 0xF3D2, 0x9BDC, 0xF3D3, 0x9BD9, 0xF3D4, 0x9BE5, 0xF3D5, 0x9BD5, + 0xF3D6, 0x9BE1, 0xF3D7, 0x9BDA, 0xF3D8, 0x9D77, 0xF3D9, 0x9D81, 0xF3DA, 0x9D8A, 0xF3DB, 0x9D84, 0xF3DC, 0x9D88, 0xF3DD, 0x9D71, + 0xF3DE, 0x9D80, 0xF3DF, 0x9D78, 0xF3E0, 0x9D86, 0xF3E1, 0x9D8B, 0xF3E2, 0x9D8C, 0xF3E3, 0x9D7D, 0xF3E4, 0x9D6B, 0xF3E5, 0x9D74, + 0xF3E6, 0x9D75, 0xF3E7, 0x9D70, 0xF3E8, 0x9D69, 0xF3E9, 0x9D85, 0xF3EA, 0x9D73, 0xF3EB, 0x9D7B, 0xF3EC, 0x9D82, 0xF3ED, 0x9D6F, + 0xF3EE, 0x9D79, 0xF3EF, 0x9D7F, 0xF3F0, 0x9D87, 0xF3F1, 0x9D68, 0xF3F2, 0x9E94, 0xF3F3, 0x9E91, 0xF3F4, 0x9EC0, 0xF3F5, 0x9EFC, + 0xF3F6, 0x9F2D, 0xF3F7, 0x9F40, 0xF3F8, 0x9F41, 0xF3F9, 0x9F4D, 0xF3FA, 0x9F56, 0xF3FB, 0x9F57, 0xF3FC, 0x9F58, 0xF3FD, 0x5337, + 0xF3FE, 0x56B2, 0xF440, 0x56B5, 0xF441, 0x56B3, 0xF442, 0x58E3, 0xF443, 0x5B45, 0xF444, 0x5DC6, 0xF445, 0x5DC7, 0xF446, 0x5EEE, + 0xF447, 0x5EEF, 0xF448, 0x5FC0, 0xF449, 0x5FC1, 0xF44A, 0x61F9, 0xF44B, 0x6517, 0xF44C, 0x6516, 0xF44D, 0x6515, 0xF44E, 0x6513, + 0xF44F, 0x65DF, 0xF450, 0x66E8, 0xF451, 0x66E3, 0xF452, 0x66E4, 0xF453, 0x6AF3, 0xF454, 0x6AF0, 0xF455, 0x6AEA, 0xF456, 0x6AE8, + 0xF457, 0x6AF9, 0xF458, 0x6AF1, 0xF459, 0x6AEE, 0xF45A, 0x6AEF, 0xF45B, 0x703C, 0xF45C, 0x7035, 0xF45D, 0x702F, 0xF45E, 0x7037, + 0xF45F, 0x7034, 0xF460, 0x7031, 0xF461, 0x7042, 0xF462, 0x7038, 0xF463, 0x703F, 0xF464, 0x703A, 0xF465, 0x7039, 0xF466, 0x7040, + 0xF467, 0x703B, 0xF468, 0x7033, 0xF469, 0x7041, 0xF46A, 0x7213, 0xF46B, 0x7214, 0xF46C, 0x72A8, 0xF46D, 0x737D, 0xF46E, 0x737C, + 0xF46F, 0x74BA, 0xF470, 0x76AB, 0xF471, 0x76AA, 0xF472, 0x76BE, 0xF473, 0x76ED, 0xF474, 0x77CC, 0xF475, 0x77CE, 0xF476, 0x77CF, + 0xF477, 0x77CD, 0xF478, 0x77F2, 0xF479, 0x7925, 0xF47A, 0x7923, 0xF47B, 0x7927, 0xF47C, 0x7928, 0xF47D, 0x7924, 0xF47E, 0x7929, + 0xF4A1, 0x79B2, 0xF4A2, 0x7A6E, 0xF4A3, 0x7A6C, 0xF4A4, 0x7A6D, 0xF4A5, 0x7AF7, 0xF4A6, 0x7C49, 0xF4A7, 0x7C48, 0xF4A8, 0x7C4A, + 0xF4A9, 0x7C47, 0xF4AA, 0x7C45, 0xF4AB, 0x7CEE, 0xF4AC, 0x7E7B, 0xF4AD, 0x7E7E, 0xF4AE, 0x7E81, 0xF4AF, 0x7E80, 0xF4B0, 0x7FBA, + 0xF4B1, 0x7FFF, 0xF4B2, 0x8079, 0xF4B3, 0x81DB, 0xF4B4, 0x81D9, 0xF4B5, 0x820B, 0xF4B6, 0x8268, 0xF4B7, 0x8269, 0xF4B8, 0x8622, + 0xF4B9, 0x85FF, 0xF4BA, 0x8601, 0xF4BB, 0x85FE, 0xF4BC, 0x861B, 0xF4BD, 0x8600, 0xF4BE, 0x85F6, 0xF4BF, 0x8604, 0xF4C0, 0x8609, + 0xF4C1, 0x8605, 0xF4C2, 0x860C, 0xF4C3, 0x85FD, 0xF4C4, 0x8819, 0xF4C5, 0x8810, 0xF4C6, 0x8811, 0xF4C7, 0x8817, 0xF4C8, 0x8813, + 0xF4C9, 0x8816, 0xF4CA, 0x8963, 0xF4CB, 0x8966, 0xF4CC, 0x89B9, 0xF4CD, 0x89F7, 0xF4CE, 0x8B60, 0xF4CF, 0x8B6A, 0xF4D0, 0x8B5D, + 0xF4D1, 0x8B68, 0xF4D2, 0x8B63, 0xF4D3, 0x8B65, 0xF4D4, 0x8B67, 0xF4D5, 0x8B6D, 0xF4D6, 0x8DAE, 0xF4D7, 0x8E86, 0xF4D8, 0x8E88, + 0xF4D9, 0x8E84, 0xF4DA, 0x8F59, 0xF4DB, 0x8F56, 0xF4DC, 0x8F57, 0xF4DD, 0x8F55, 0xF4DE, 0x8F58, 0xF4DF, 0x8F5A, 0xF4E0, 0x908D, + 0xF4E1, 0x9143, 0xF4E2, 0x9141, 0xF4E3, 0x91B7, 0xF4E4, 0x91B5, 0xF4E5, 0x91B2, 0xF4E6, 0x91B3, 0xF4E7, 0x940B, 0xF4E8, 0x9413, + 0xF4E9, 0x93FB, 0xF4EA, 0x9420, 0xF4EB, 0x940F, 0xF4EC, 0x9414, 0xF4ED, 0x93FE, 0xF4EE, 0x9415, 0xF4EF, 0x9410, 0xF4F0, 0x9428, + 0xF4F1, 0x9419, 0xF4F2, 0x940D, 0xF4F3, 0x93F5, 0xF4F4, 0x9400, 0xF4F5, 0x93F7, 0xF4F6, 0x9407, 0xF4F7, 0x940E, 0xF4F8, 0x9416, + 0xF4F9, 0x9412, 0xF4FA, 0x93FA, 0xF4FB, 0x9409, 0xF4FC, 0x93F8, 0xF4FD, 0x940A, 0xF4FE, 0x93FF, 0xF540, 0x93FC, 0xF541, 0x940C, + 0xF542, 0x93F6, 0xF543, 0x9411, 0xF544, 0x9406, 0xF545, 0x95DE, 0xF546, 0x95E0, 0xF547, 0x95DF, 0xF548, 0x972E, 0xF549, 0x972F, + 0xF54A, 0x97B9, 0xF54B, 0x97BB, 0xF54C, 0x97FD, 0xF54D, 0x97FE, 0xF54E, 0x9860, 0xF54F, 0x9862, 0xF550, 0x9863, 0xF551, 0x985F, + 0xF552, 0x98C1, 0xF553, 0x98C2, 0xF554, 0x9950, 0xF555, 0x994E, 0xF556, 0x9959, 0xF557, 0x994C, 0xF558, 0x994B, 0xF559, 0x9953, + 0xF55A, 0x9A32, 0xF55B, 0x9A34, 0xF55C, 0x9A31, 0xF55D, 0x9A2C, 0xF55E, 0x9A2A, 0xF55F, 0x9A36, 0xF560, 0x9A29, 0xF561, 0x9A2E, + 0xF562, 0x9A38, 0xF563, 0x9A2D, 0xF564, 0x9AC7, 0xF565, 0x9ACA, 0xF566, 0x9AC6, 0xF567, 0x9B10, 0xF568, 0x9B12, 0xF569, 0x9B11, + 0xF56A, 0x9C0B, 0xF56B, 0x9C08, 0xF56C, 0x9BF7, 0xF56D, 0x9C05, 0xF56E, 0x9C12, 0xF56F, 0x9BF8, 0xF570, 0x9C40, 0xF571, 0x9C07, + 0xF572, 0x9C0E, 0xF573, 0x9C06, 0xF574, 0x9C17, 0xF575, 0x9C14, 0xF576, 0x9C09, 0xF577, 0x9D9F, 0xF578, 0x9D99, 0xF579, 0x9DA4, + 0xF57A, 0x9D9D, 0xF57B, 0x9D92, 0xF57C, 0x9D98, 0xF57D, 0x9D90, 0xF57E, 0x9D9B, 0xF5A1, 0x9DA0, 0xF5A2, 0x9D94, 0xF5A3, 0x9D9C, + 0xF5A4, 0x9DAA, 0xF5A5, 0x9D97, 0xF5A6, 0x9DA1, 0xF5A7, 0x9D9A, 0xF5A8, 0x9DA2, 0xF5A9, 0x9DA8, 0xF5AA, 0x9D9E, 0xF5AB, 0x9DA3, + 0xF5AC, 0x9DBF, 0xF5AD, 0x9DA9, 0xF5AE, 0x9D96, 0xF5AF, 0x9DA6, 0xF5B0, 0x9DA7, 0xF5B1, 0x9E99, 0xF5B2, 0x9E9B, 0xF5B3, 0x9E9A, + 0xF5B4, 0x9EE5, 0xF5B5, 0x9EE4, 0xF5B6, 0x9EE7, 0xF5B7, 0x9EE6, 0xF5B8, 0x9F30, 0xF5B9, 0x9F2E, 0xF5BA, 0x9F5B, 0xF5BB, 0x9F60, + 0xF5BC, 0x9F5E, 0xF5BD, 0x9F5D, 0xF5BE, 0x9F59, 0xF5BF, 0x9F91, 0xF5C0, 0x513A, 0xF5C1, 0x5139, 0xF5C2, 0x5298, 0xF5C3, 0x5297, + 0xF5C4, 0x56C3, 0xF5C5, 0x56BD, 0xF5C6, 0x56BE, 0xF5C7, 0x5B48, 0xF5C8, 0x5B47, 0xF5C9, 0x5DCB, 0xF5CA, 0x5DCF, 0xF5CB, 0x5EF1, + 0xF5CC, 0x61FD, 0xF5CD, 0x651B, 0xF5CE, 0x6B02, 0xF5CF, 0x6AFC, 0xF5D0, 0x6B03, 0xF5D1, 0x6AF8, 0xF5D2, 0x6B00, 0xF5D3, 0x7043, + 0xF5D4, 0x7044, 0xF5D5, 0x704A, 0xF5D6, 0x7048, 0xF5D7, 0x7049, 0xF5D8, 0x7045, 0xF5D9, 0x7046, 0xF5DA, 0x721D, 0xF5DB, 0x721A, + 0xF5DC, 0x7219, 0xF5DD, 0x737E, 0xF5DE, 0x7517, 0xF5DF, 0x766A, 0xF5E0, 0x77D0, 0xF5E1, 0x792D, 0xF5E2, 0x7931, 0xF5E3, 0x792F, + 0xF5E4, 0x7C54, 0xF5E5, 0x7C53, 0xF5E6, 0x7CF2, 0xF5E7, 0x7E8A, 0xF5E8, 0x7E87, 0xF5E9, 0x7E88, 0xF5EA, 0x7E8B, 0xF5EB, 0x7E86, + 0xF5EC, 0x7E8D, 0xF5ED, 0x7F4D, 0xF5EE, 0x7FBB, 0xF5EF, 0x8030, 0xF5F0, 0x81DD, 0xF5F1, 0x8618, 0xF5F2, 0x862A, 0xF5F3, 0x8626, + 0xF5F4, 0x861F, 0xF5F5, 0x8623, 0xF5F6, 0x861C, 0xF5F7, 0x8619, 0xF5F8, 0x8627, 0xF5F9, 0x862E, 0xF5FA, 0x8621, 0xF5FB, 0x8620, + 0xF5FC, 0x8629, 0xF5FD, 0x861E, 0xF5FE, 0x8625, 0xF640, 0x8829, 0xF641, 0x881D, 0xF642, 0x881B, 0xF643, 0x8820, 0xF644, 0x8824, + 0xF645, 0x881C, 0xF646, 0x882B, 0xF647, 0x884A, 0xF648, 0x896D, 0xF649, 0x8969, 0xF64A, 0x896E, 0xF64B, 0x896B, 0xF64C, 0x89FA, + 0xF64D, 0x8B79, 0xF64E, 0x8B78, 0xF64F, 0x8B45, 0xF650, 0x8B7A, 0xF651, 0x8B7B, 0xF652, 0x8D10, 0xF653, 0x8D14, 0xF654, 0x8DAF, + 0xF655, 0x8E8E, 0xF656, 0x8E8C, 0xF657, 0x8F5E, 0xF658, 0x8F5B, 0xF659, 0x8F5D, 0xF65A, 0x9146, 0xF65B, 0x9144, 0xF65C, 0x9145, + 0xF65D, 0x91B9, 0xF65E, 0x943F, 0xF65F, 0x943B, 0xF660, 0x9436, 0xF661, 0x9429, 0xF662, 0x943D, 0xF663, 0x943C, 0xF664, 0x9430, + 0xF665, 0x9439, 0xF666, 0x942A, 0xF667, 0x9437, 0xF668, 0x942C, 0xF669, 0x9440, 0xF66A, 0x9431, 0xF66B, 0x95E5, 0xF66C, 0x95E4, + 0xF66D, 0x95E3, 0xF66E, 0x9735, 0xF66F, 0x973A, 0xF670, 0x97BF, 0xF671, 0x97E1, 0xF672, 0x9864, 0xF673, 0x98C9, 0xF674, 0x98C6, + 0xF675, 0x98C0, 0xF676, 0x9958, 0xF677, 0x9956, 0xF678, 0x9A39, 0xF679, 0x9A3D, 0xF67A, 0x9A46, 0xF67B, 0x9A44, 0xF67C, 0x9A42, + 0xF67D, 0x9A41, 0xF67E, 0x9A3A, 0xF6A1, 0x9A3F, 0xF6A2, 0x9ACD, 0xF6A3, 0x9B15, 0xF6A4, 0x9B17, 0xF6A5, 0x9B18, 0xF6A6, 0x9B16, + 0xF6A7, 0x9B3A, 0xF6A8, 0x9B52, 0xF6A9, 0x9C2B, 0xF6AA, 0x9C1D, 0xF6AB, 0x9C1C, 0xF6AC, 0x9C2C, 0xF6AD, 0x9C23, 0xF6AE, 0x9C28, + 0xF6AF, 0x9C29, 0xF6B0, 0x9C24, 0xF6B1, 0x9C21, 0xF6B2, 0x9DB7, 0xF6B3, 0x9DB6, 0xF6B4, 0x9DBC, 0xF6B5, 0x9DC1, 0xF6B6, 0x9DC7, + 0xF6B7, 0x9DCA, 0xF6B8, 0x9DCF, 0xF6B9, 0x9DBE, 0xF6BA, 0x9DC5, 0xF6BB, 0x9DC3, 0xF6BC, 0x9DBB, 0xF6BD, 0x9DB5, 0xF6BE, 0x9DCE, + 0xF6BF, 0x9DB9, 0xF6C0, 0x9DBA, 0xF6C1, 0x9DAC, 0xF6C2, 0x9DC8, 0xF6C3, 0x9DB1, 0xF6C4, 0x9DAD, 0xF6C5, 0x9DCC, 0xF6C6, 0x9DB3, + 0xF6C7, 0x9DCD, 0xF6C8, 0x9DB2, 0xF6C9, 0x9E7A, 0xF6CA, 0x9E9C, 0xF6CB, 0x9EEB, 0xF6CC, 0x9EEE, 0xF6CD, 0x9EED, 0xF6CE, 0x9F1B, + 0xF6CF, 0x9F18, 0xF6D0, 0x9F1A, 0xF6D1, 0x9F31, 0xF6D2, 0x9F4E, 0xF6D3, 0x9F65, 0xF6D4, 0x9F64, 0xF6D5, 0x9F92, 0xF6D6, 0x4EB9, + 0xF6D7, 0x56C6, 0xF6D8, 0x56C5, 0xF6D9, 0x56CB, 0xF6DA, 0x5971, 0xF6DB, 0x5B4B, 0xF6DC, 0x5B4C, 0xF6DD, 0x5DD5, 0xF6DE, 0x5DD1, + 0xF6DF, 0x5EF2, 0xF6E0, 0x6521, 0xF6E1, 0x6520, 0xF6E2, 0x6526, 0xF6E3, 0x6522, 0xF6E4, 0x6B0B, 0xF6E5, 0x6B08, 0xF6E6, 0x6B09, + 0xF6E7, 0x6C0D, 0xF6E8, 0x7055, 0xF6E9, 0x7056, 0xF6EA, 0x7057, 0xF6EB, 0x7052, 0xF6EC, 0x721E, 0xF6ED, 0x721F, 0xF6EE, 0x72A9, + 0xF6EF, 0x737F, 0xF6F0, 0x74D8, 0xF6F1, 0x74D5, 0xF6F2, 0x74D9, 0xF6F3, 0x74D7, 0xF6F4, 0x766D, 0xF6F5, 0x76AD, 0xF6F6, 0x7935, + 0xF6F7, 0x79B4, 0xF6F8, 0x7A70, 0xF6F9, 0x7A71, 0xF6FA, 0x7C57, 0xF6FB, 0x7C5C, 0xF6FC, 0x7C59, 0xF6FD, 0x7C5B, 0xF6FE, 0x7C5A, + 0xF740, 0x7CF4, 0xF741, 0x7CF1, 0xF742, 0x7E91, 0xF743, 0x7F4F, 0xF744, 0x7F87, 0xF745, 0x81DE, 0xF746, 0x826B, 0xF747, 0x8634, + 0xF748, 0x8635, 0xF749, 0x8633, 0xF74A, 0x862C, 0xF74B, 0x8632, 0xF74C, 0x8636, 0xF74D, 0x882C, 0xF74E, 0x8828, 0xF74F, 0x8826, + 0xF750, 0x882A, 0xF751, 0x8825, 0xF752, 0x8971, 0xF753, 0x89BF, 0xF754, 0x89BE, 0xF755, 0x89FB, 0xF756, 0x8B7E, 0xF757, 0x8B84, + 0xF758, 0x8B82, 0xF759, 0x8B86, 0xF75A, 0x8B85, 0xF75B, 0x8B7F, 0xF75C, 0x8D15, 0xF75D, 0x8E95, 0xF75E, 0x8E94, 0xF75F, 0x8E9A, + 0xF760, 0x8E92, 0xF761, 0x8E90, 0xF762, 0x8E96, 0xF763, 0x8E97, 0xF764, 0x8F60, 0xF765, 0x8F62, 0xF766, 0x9147, 0xF767, 0x944C, + 0xF768, 0x9450, 0xF769, 0x944A, 0xF76A, 0x944B, 0xF76B, 0x944F, 0xF76C, 0x9447, 0xF76D, 0x9445, 0xF76E, 0x9448, 0xF76F, 0x9449, + 0xF770, 0x9446, 0xF771, 0x973F, 0xF772, 0x97E3, 0xF773, 0x986A, 0xF774, 0x9869, 0xF775, 0x98CB, 0xF776, 0x9954, 0xF777, 0x995B, + 0xF778, 0x9A4E, 0xF779, 0x9A53, 0xF77A, 0x9A54, 0xF77B, 0x9A4C, 0xF77C, 0x9A4F, 0xF77D, 0x9A48, 0xF77E, 0x9A4A, 0xF7A1, 0x9A49, + 0xF7A2, 0x9A52, 0xF7A3, 0x9A50, 0xF7A4, 0x9AD0, 0xF7A5, 0x9B19, 0xF7A6, 0x9B2B, 0xF7A7, 0x9B3B, 0xF7A8, 0x9B56, 0xF7A9, 0x9B55, + 0xF7AA, 0x9C46, 0xF7AB, 0x9C48, 0xF7AC, 0x9C3F, 0xF7AD, 0x9C44, 0xF7AE, 0x9C39, 0xF7AF, 0x9C33, 0xF7B0, 0x9C41, 0xF7B1, 0x9C3C, + 0xF7B2, 0x9C37, 0xF7B3, 0x9C34, 0xF7B4, 0x9C32, 0xF7B5, 0x9C3D, 0xF7B6, 0x9C36, 0xF7B7, 0x9DDB, 0xF7B8, 0x9DD2, 0xF7B9, 0x9DDE, + 0xF7BA, 0x9DDA, 0xF7BB, 0x9DCB, 0xF7BC, 0x9DD0, 0xF7BD, 0x9DDC, 0xF7BE, 0x9DD1, 0xF7BF, 0x9DDF, 0xF7C0, 0x9DE9, 0xF7C1, 0x9DD9, + 0xF7C2, 0x9DD8, 0xF7C3, 0x9DD6, 0xF7C4, 0x9DF5, 0xF7C5, 0x9DD5, 0xF7C6, 0x9DDD, 0xF7C7, 0x9EB6, 0xF7C8, 0x9EF0, 0xF7C9, 0x9F35, + 0xF7CA, 0x9F33, 0xF7CB, 0x9F32, 0xF7CC, 0x9F42, 0xF7CD, 0x9F6B, 0xF7CE, 0x9F95, 0xF7CF, 0x9FA2, 0xF7D0, 0x513D, 0xF7D1, 0x5299, + 0xF7D2, 0x58E8, 0xF7D3, 0x58E7, 0xF7D4, 0x5972, 0xF7D5, 0x5B4D, 0xF7D6, 0x5DD8, 0xF7D7, 0x882F, 0xF7D8, 0x5F4F, 0xF7D9, 0x6201, + 0xF7DA, 0x6203, 0xF7DB, 0x6204, 0xF7DC, 0x6529, 0xF7DD, 0x6525, 0xF7DE, 0x6596, 0xF7DF, 0x66EB, 0xF7E0, 0x6B11, 0xF7E1, 0x6B12, + 0xF7E2, 0x6B0F, 0xF7E3, 0x6BCA, 0xF7E4, 0x705B, 0xF7E5, 0x705A, 0xF7E6, 0x7222, 0xF7E7, 0x7382, 0xF7E8, 0x7381, 0xF7E9, 0x7383, + 0xF7EA, 0x7670, 0xF7EB, 0x77D4, 0xF7EC, 0x7C67, 0xF7ED, 0x7C66, 0xF7EE, 0x7E95, 0xF7EF, 0x826C, 0xF7F0, 0x863A, 0xF7F1, 0x8640, + 0xF7F2, 0x8639, 0xF7F3, 0x863C, 0xF7F4, 0x8631, 0xF7F5, 0x863B, 0xF7F6, 0x863E, 0xF7F7, 0x8830, 0xF7F8, 0x8832, 0xF7F9, 0x882E, + 0xF7FA, 0x8833, 0xF7FB, 0x8976, 0xF7FC, 0x8974, 0xF7FD, 0x8973, 0xF7FE, 0x89FE, 0xF840, 0x8B8C, 0xF841, 0x8B8E, 0xF842, 0x8B8B, + 0xF843, 0x8B88, 0xF844, 0x8C45, 0xF845, 0x8D19, 0xF846, 0x8E98, 0xF847, 0x8F64, 0xF848, 0x8F63, 0xF849, 0x91BC, 0xF84A, 0x9462, + 0xF84B, 0x9455, 0xF84C, 0x945D, 0xF84D, 0x9457, 0xF84E, 0x945E, 0xF84F, 0x97C4, 0xF850, 0x97C5, 0xF851, 0x9800, 0xF852, 0x9A56, + 0xF853, 0x9A59, 0xF854, 0x9B1E, 0xF855, 0x9B1F, 0xF856, 0x9B20, 0xF857, 0x9C52, 0xF858, 0x9C58, 0xF859, 0x9C50, 0xF85A, 0x9C4A, + 0xF85B, 0x9C4D, 0xF85C, 0x9C4B, 0xF85D, 0x9C55, 0xF85E, 0x9C59, 0xF85F, 0x9C4C, 0xF860, 0x9C4E, 0xF861, 0x9DFB, 0xF862, 0x9DF7, + 0xF863, 0x9DEF, 0xF864, 0x9DE3, 0xF865, 0x9DEB, 0xF866, 0x9DF8, 0xF867, 0x9DE4, 0xF868, 0x9DF6, 0xF869, 0x9DE1, 0xF86A, 0x9DEE, + 0xF86B, 0x9DE6, 0xF86C, 0x9DF2, 0xF86D, 0x9DF0, 0xF86E, 0x9DE2, 0xF86F, 0x9DEC, 0xF870, 0x9DF4, 0xF871, 0x9DF3, 0xF872, 0x9DE8, + 0xF873, 0x9DED, 0xF874, 0x9EC2, 0xF875, 0x9ED0, 0xF876, 0x9EF2, 0xF877, 0x9EF3, 0xF878, 0x9F06, 0xF879, 0x9F1C, 0xF87A, 0x9F38, + 0xF87B, 0x9F37, 0xF87C, 0x9F36, 0xF87D, 0x9F43, 0xF87E, 0x9F4F, 0xF8A1, 0x9F71, 0xF8A2, 0x9F70, 0xF8A3, 0x9F6E, 0xF8A4, 0x9F6F, + 0xF8A5, 0x56D3, 0xF8A6, 0x56CD, 0xF8A7, 0x5B4E, 0xF8A8, 0x5C6D, 0xF8A9, 0x652D, 0xF8AA, 0x66ED, 0xF8AB, 0x66EE, 0xF8AC, 0x6B13, + 0xF8AD, 0x705F, 0xF8AE, 0x7061, 0xF8AF, 0x705D, 0xF8B0, 0x7060, 0xF8B1, 0x7223, 0xF8B2, 0x74DB, 0xF8B3, 0x74E5, 0xF8B4, 0x77D5, + 0xF8B5, 0x7938, 0xF8B6, 0x79B7, 0xF8B7, 0x79B6, 0xF8B8, 0x7C6A, 0xF8B9, 0x7E97, 0xF8BA, 0x7F89, 0xF8BB, 0x826D, 0xF8BC, 0x8643, + 0xF8BD, 0x8838, 0xF8BE, 0x8837, 0xF8BF, 0x8835, 0xF8C0, 0x884B, 0xF8C1, 0x8B94, 0xF8C2, 0x8B95, 0xF8C3, 0x8E9E, 0xF8C4, 0x8E9F, + 0xF8C5, 0x8EA0, 0xF8C6, 0x8E9D, 0xF8C7, 0x91BE, 0xF8C8, 0x91BD, 0xF8C9, 0x91C2, 0xF8CA, 0x946B, 0xF8CB, 0x9468, 0xF8CC, 0x9469, + 0xF8CD, 0x96E5, 0xF8CE, 0x9746, 0xF8CF, 0x9743, 0xF8D0, 0x9747, 0xF8D1, 0x97C7, 0xF8D2, 0x97E5, 0xF8D3, 0x9A5E, 0xF8D4, 0x9AD5, + 0xF8D5, 0x9B59, 0xF8D6, 0x9C63, 0xF8D7, 0x9C67, 0xF8D8, 0x9C66, 0xF8D9, 0x9C62, 0xF8DA, 0x9C5E, 0xF8DB, 0x9C60, 0xF8DC, 0x9E02, + 0xF8DD, 0x9DFE, 0xF8DE, 0x9E07, 0xF8DF, 0x9E03, 0xF8E0, 0x9E06, 0xF8E1, 0x9E05, 0xF8E2, 0x9E00, 0xF8E3, 0x9E01, 0xF8E4, 0x9E09, + 0xF8E5, 0x9DFF, 0xF8E6, 0x9DFD, 0xF8E7, 0x9E04, 0xF8E8, 0x9EA0, 0xF8E9, 0x9F1E, 0xF8EA, 0x9F46, 0xF8EB, 0x9F74, 0xF8EC, 0x9F75, + 0xF8ED, 0x9F76, 0xF8EE, 0x56D4, 0xF8EF, 0x652E, 0xF8F0, 0x65B8, 0xF8F1, 0x6B18, 0xF8F2, 0x6B19, 0xF8F3, 0x6B17, 0xF8F4, 0x6B1A, + 0xF8F5, 0x7062, 0xF8F6, 0x7226, 0xF8F7, 0x72AA, 0xF8F8, 0x77D8, 0xF8F9, 0x77D9, 0xF8FA, 0x7939, 0xF8FB, 0x7C69, 0xF8FC, 0x7C6B, + 0xF8FD, 0x7CF6, 0xF8FE, 0x7E9A, 0xF940, 0x7E98, 0xF941, 0x7E9B, 0xF942, 0x7E99, 0xF943, 0x81E0, 0xF944, 0x81E1, 0xF945, 0x8646, + 0xF946, 0x8647, 0xF947, 0x8648, 0xF948, 0x8979, 0xF949, 0x897A, 0xF94A, 0x897C, 0xF94B, 0x897B, 0xF94C, 0x89FF, 0xF94D, 0x8B98, + 0xF94E, 0x8B99, 0xF94F, 0x8EA5, 0xF950, 0x8EA4, 0xF951, 0x8EA3, 0xF952, 0x946E, 0xF953, 0x946D, 0xF954, 0x946F, 0xF955, 0x9471, + 0xF956, 0x9473, 0xF957, 0x9749, 0xF958, 0x9872, 0xF959, 0x995F, 0xF95A, 0x9C68, 0xF95B, 0x9C6E, 0xF95C, 0x9C6D, 0xF95D, 0x9E0B, + 0xF95E, 0x9E0D, 0xF95F, 0x9E10, 0xF960, 0x9E0F, 0xF961, 0x9E12, 0xF962, 0x9E11, 0xF963, 0x9EA1, 0xF964, 0x9EF5, 0xF965, 0x9F09, + 0xF966, 0x9F47, 0xF967, 0x9F78, 0xF968, 0x9F7B, 0xF969, 0x9F7A, 0xF96A, 0x9F79, 0xF96B, 0x571E, 0xF96C, 0x7066, 0xF96D, 0x7C6F, + 0xF96E, 0x883C, 0xF96F, 0x8DB2, 0xF970, 0x8EA6, 0xF971, 0x91C3, 0xF972, 0x9474, 0xF973, 0x9478, 0xF974, 0x9476, 0xF975, 0x9475, + 0xF976, 0x9A60, 0xF977, 0x9C74, 0xF978, 0x9C73, 0xF979, 0x9C71, 0xF97A, 0x9C75, 0xF97B, 0x9E14, 0xF97C, 0x9E13, 0xF97D, 0x9EF6, + 0xF97E, 0x9F0A, 0xF9A1, 0x9FA4, 0xF9A2, 0x7068, 0xF9A3, 0x7065, 0xF9A4, 0x7CF7, 0xF9A5, 0x866A, 0xF9A6, 0x883E, 0xF9A7, 0x883D, + 0xF9A8, 0x883F, 0xF9A9, 0x8B9E, 0xF9AA, 0x8C9C, 0xF9AB, 0x8EA9, 0xF9AC, 0x8EC9, 0xF9AD, 0x974B, 0xF9AE, 0x9873, 0xF9AF, 0x9874, + 0xF9B0, 0x98CC, 0xF9B1, 0x9961, 0xF9B2, 0x99AB, 0xF9B3, 0x9A64, 0xF9B4, 0x9A66, 0xF9B5, 0x9A67, 0xF9B6, 0x9B24, 0xF9B7, 0x9E15, + 0xF9B8, 0x9E17, 0xF9B9, 0x9F48, 0xF9BA, 0x6207, 0xF9BB, 0x6B1E, 0xF9BC, 0x7227, 0xF9BD, 0x864C, 0xF9BE, 0x8EA8, 0xF9BF, 0x9482, + 0xF9C0, 0x9480, 0xF9C1, 0x9481, 0xF9C2, 0x9A69, 0xF9C3, 0x9A68, 0xF9C4, 0x9B2E, 0xF9C5, 0x9E19, 0xF9C6, 0x7229, 0xF9C7, 0x864B, + 0xF9C8, 0x8B9F, 0xF9C9, 0x9483, 0xF9CA, 0x9C79, 0xF9CB, 0x9EB7, 0xF9CC, 0x7675, 0xF9CD, 0x9A6B, 0xF9CE, 0x9C7A, 0xF9CF, 0x9E1D, + 0xF9D0, 0x7069, 0xF9D1, 0x706A, 0xF9D2, 0x9EA4, 0xF9D3, 0x9F7E, 0xF9D4, 0x9F49, 0xF9D5, 0x9F98, 0xF9D6, 0x7881, 0xF9D7, 0x92B9, + 0xF9D8, 0x88CF, 0xF9D9, 0x58BB, 0xF9DA, 0x6052, 0xF9DB, 0x7CA7, 0xF9DC, 0x5AFA, 0xF9DD, 0x2554, 0xF9DE, 0x2566, 0xF9DF, 0x2557, + 0xF9E0, 0x2560, 0xF9E1, 0x256C, 0xF9E2, 0x2563, 0xF9E3, 0x255A, 0xF9E4, 0x2569, 0xF9E5, 0x255D, 0xF9E6, 0x2552, 0xF9E7, 0x2564, + 0xF9E8, 0x2555, 0xF9E9, 0x255E, 0xF9EA, 0x256A, 0xF9EB, 0x2561, 0xF9EC, 0x2558, 0xF9ED, 0x2567, 0xF9EE, 0x255B, 0xF9EF, 0x2553, + 0xF9F0, 0x2565, 0xF9F1, 0x2556, 0xF9F2, 0x255F, 0xF9F3, 0x256B, 0xF9F4, 0x2562, 0xF9F5, 0x2559, 0xF9F6, 0x2568, 0xF9F7, 0x255C, + 0xF9F8, 0x2551, 0xF9F9, 0x2550, 0xF9FA, 0x256D, 0xF9FB, 0x256E, 0xF9FC, 0x2570, 0xF9FD, 0x256F, 0xF9FE, 0x2593, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 +static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 +static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 +static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 +static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 +static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 +static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 +static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 +static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 +static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 +static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, + 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 +static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 +static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 +static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, + 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, + 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 +static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ + 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, + 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, + 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, + 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, + 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 +}; +#endif +#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 +static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 +static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 +static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ + 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, + 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, + 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, + 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, + 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, + 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 +}; +#endif + + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* SBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + for (c = 0; c < 0x80 && uni != p[c]; c++) ; + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } + + return c; +} + +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* DBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE >= 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i = 0, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + uc = (WCHAR)uni; + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i = 0, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ + p = CVTBL(oem2uni, FF_CODE_PAGE); + hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for dynamic code page configuration */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 0 + +static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; +static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; + + +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WCHAR)uni; + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ + p = cp_table[i]; + if (p) { /* Is it valid code page ? */ + for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ + c = (c + 0x80) & 0xFF; + } + } else { /* DBCS */ + switch (cp) { /* Get conversion table */ + case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; + case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; + case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; + case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; + } + if (p) { /* Is it valid code page? */ + li = 0; + for (n = 16; n; n--) { /* Find OEM code */ + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + p = cp_table[i]; + if (p) { /* Is it a valid CP ? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } else { /* DBCS */ + switch (cp) { + case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; + case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; + case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; + case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; + } + if (p) { + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* Unicode up-case conversion */ +/*------------------------------------------------------------------------*/ + +DWORD ff_wtoupper ( /* Returns up-converted code point */ + DWORD uni /* Unicode code point to be up-converted */ +) +{ + const WORD *p; + WORD uc, bc, nc, cmd; + static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ + /* Basic Latin */ + 0x0061,0x031A, + /* Latin-1 Supplement */ + 0x00E0,0x0317, + 0x00F8,0x0307, + 0x00FF,0x0001,0x0178, + /* Latin Extended-A */ + 0x0100,0x0130, + 0x0132,0x0106, + 0x0139,0x0110, + 0x014A,0x012E, + 0x0179,0x0106, + /* Latin Extended-B */ + 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, + 0x01CD,0x0110, + 0x01DD,0x0001,0x018E, + 0x01DE,0x0112, + 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, + 0x01F8,0x0128, + 0x0222,0x0112, + 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, + 0x0246,0x010A, + /* IPA Extensions */ + 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, + /* Greek, Coptic */ + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, + 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, + 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, + 0x03C4,0x0308, + 0x03CC,0x0003,0x038C,0x038E,0x038F, + 0x03D8,0x0118, + 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, + /* Cyrillic */ + 0x0430,0x0320, + 0x0450,0x0710, + 0x0460,0x0122, + 0x048A,0x0136, + 0x04C1,0x010E, + 0x04CF,0x0001,0x04C0, + 0x04D0,0x0144, + /* Armenian */ + 0x0561,0x0426, + + 0x0000 /* EOT */ + }; + static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ + /* Phonetic Extensions */ + 0x1D7D,0x0001,0x2C63, + /* Latin Extended Additional */ + 0x1E00,0x0196, + 0x1EA0,0x015A, + /* Greek Extended */ + 0x1F00,0x0608, + 0x1F10,0x0606, + 0x1F20,0x0608, + 0x1F30,0x0608, + 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, + 0x1F60,0x0608, + 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, + 0x1F80,0x0608, + 0x1F90,0x0608, + 0x1FA0,0x0608, + 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, + 0x1FD0,0x0602, + 0x1FE0,0x0602, + 0x1FE5,0x0001,0x1FEC, + 0x1FF3,0x0001,0x1FFC, + /* Letterlike Symbols */ + 0x214E,0x0001,0x2132, + /* Number forms */ + 0x2170,0x0210, + 0x2184,0x0001,0x2183, + /* Enclosed Alphanumerics */ + 0x24D0,0x051A, + 0x2C30,0x042F, + /* Latin Extended-C */ + 0x2C60,0x0102, + 0x2C67,0x0106, 0x2C75,0x0102, + /* Coptic */ + 0x2C80,0x0164, + /* Georgian Supplement */ + 0x2D00,0x0826, + /* Full-width */ + 0xFF41,0x031A, + + 0x0000 /* EOT */ + }; + + + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WORD)uni; + p = uc < 0x1000 ? cvt1 : cvt2; + for (;;) { + bc = *p++; /* Get the block base */ + if (bc == 0 || uc < bc) break; /* Not matched? */ + nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ + if (uc < bc + nc) { /* In the block? */ + switch (cmd) { + case 0: uc = p[uc - bc]; break; /* Table conversion */ + case 1: uc -= (uc - bc) & 1; break; /* Case pairs */ + case 2: uc -= 16; break; /* Shift -16 */ + case 3: uc -= 32; break; /* Shift -32 */ + case 4: uc -= 48; break; /* Shift -48 */ + case 5: uc -= 26; break; /* Shift -26 */ + case 6: uc += 8; break; /* Shift +8 */ + case 7: uc -= 80; break; /* Shift -80 */ + case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */ + } + break; + } + if (cmd == 0) p += nc; /* Skip table if needed */ + } + uni = uc; + } + + return uni; +} + + +#endif /* #if FF_USE_LFN */ diff --git a/components/fatfs/test/CMakeLists.txt b/components/fatfs/test/CMakeLists.txt new file mode 100644 index 000000000..bb32fd2d9 --- /dev/null +++ b/components/fatfs/test/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRC_DIRS . + INCLUDE_DIRS . + REQUIRES unity test_utils vfs fatfs + EMBED_TXTFILES fatfs.img + ) \ No newline at end of file diff --git a/components/fatfs/test/component.mk b/components/fatfs/test/component.mk new file mode 100644 index 000000000..c7e058220 --- /dev/null +++ b/components/fatfs/test/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +COMPONENT_EMBED_TXTFILES := fatfs.img diff --git a/components/fatfs/test/fatfs.img b/components/fatfs/test/fatfs.img new file mode 100644 index 000000000..d602cc782 Binary files /dev/null and b/components/fatfs/test/fatfs.img differ diff --git a/components/fatfs/test/test_fatfs_common.c b/components/fatfs/test/test_fatfs_common.c new file mode 100644 index 000000000..41ae0d229 --- /dev/null +++ b/components/fatfs/test/test_fatfs_common.c @@ -0,0 +1,812 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ff.h" +#include "test_fatfs_common.h" + +const char* fatfs_test_hello_str = "Hello, World!\n"; +const char* fatfs_test_hello_str_utf = "世界,你好!\n"; + +void test_fatfs_create_file_with_text(const char* name, const char* text) +{ + FILE* f = fopen(name, "wb"); + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_TRUE(fputs(text, f) != EOF); + TEST_ASSERT_EQUAL(0, fclose(f)); +} + +void test_fatfs_overwrite_append(const char* filename) +{ + /* Create new file with 'aaaa' */ + test_fatfs_create_file_with_text(filename, "aaaa"); + + /* Append 'bbbb' to file */ + FILE *f_a = fopen(filename, "a"); + TEST_ASSERT_NOT_NULL(f_a); + TEST_ASSERT_NOT_EQUAL(EOF, fputs("bbbb", f_a)); + TEST_ASSERT_EQUAL(0, fclose(f_a)); + + /* Read back 8 bytes from file, verify it's 'aaaabbbb' */ + char buf[10] = { 0 }; + FILE *f_r = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL(f_r); + TEST_ASSERT_EQUAL(8, fread(buf, 1, 8, f_r)); + TEST_ASSERT_EQUAL_STRING_LEN("aaaabbbb", buf, 8); + + /* Be sure we're at end of file */ + TEST_ASSERT_EQUAL(0, fread(buf, 1, 8, f_r)); + + TEST_ASSERT_EQUAL(0, fclose(f_r)); + + /* Overwrite file with 'cccc' */ + test_fatfs_create_file_with_text(filename, "cccc"); + + /* Verify file now only contains 'cccc' */ + f_r = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL(f_r); + bzero(buf, sizeof(buf)); + TEST_ASSERT_EQUAL(4, fread(buf, 1, 8, f_r)); // trying to read 8 bytes, only expecting 4 + TEST_ASSERT_EQUAL_STRING_LEN("cccc", buf, 4); + TEST_ASSERT_EQUAL(0, fclose(f_r)); +} + +void test_fatfs_read_file(const char* filename) +{ + FILE* f = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL(f); + char buf[32] = { 0 }; + int cb = fread(buf, 1, sizeof(buf), f); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str), cb); + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str, buf)); + TEST_ASSERT_EQUAL(0, fclose(f)); +} + +void test_fatfs_read_file_utf_8(const char* filename) +{ + FILE* f = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL(f); + char buf[64] = { 0 }; //Doubled buffer size to allow for longer UTF-8 strings + int cb = fread(buf, 1, sizeof(buf), f); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str_utf), cb); + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str_utf, buf)); + TEST_ASSERT_EQUAL(0, fclose(f)); +} + +void test_fatfs_pread_file(const char* filename) +{ + char buf[32] = { 0 }; + const int fd = open(filename, O_RDONLY); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + int r = pread(fd, buf, sizeof(buf), 0); // it is a regular read() with offset==0 + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str, buf)); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str), r); + + memset(buf, 0, sizeof(buf)); + r = pread(fd, buf, sizeof(buf), 1); // offset==1 + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str + 1, buf)); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str) - 1, r); + + memset(buf, 0, sizeof(buf)); + r = pread(fd, buf, sizeof(buf), 5); // offset==5 + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str + 5, buf)); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str) - 5, r); + + // regular read() should work now because pread() should not affect the current position in file + + memset(buf, 0, sizeof(buf)); + r = read(fd, buf, sizeof(buf)); // note that this is read() and not pread() + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str, buf)); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str), r); + + memset(buf, 0, sizeof(buf)); + r = pread(fd, buf, sizeof(buf), 10); // offset==10 + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str + 10, buf)); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str) - 10, r); + + memset(buf, 0, sizeof(buf)); + r = pread(fd, buf, sizeof(buf), strlen(fatfs_test_hello_str) + 1); // offset to EOF + TEST_ASSERT_EQUAL(0, r); + + TEST_ASSERT_EQUAL(0, close(fd)); +} + +static void test_pwrite(const char *filename, off_t offset, const char *msg) +{ + const int fd = open(filename, O_WRONLY); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + const off_t current_pos = lseek(fd, 0, SEEK_END); // O_APPEND is not the same - jumps to the end only before write() + + const int r = pwrite(fd, msg, strlen(msg), offset); + TEST_ASSERT_EQUAL(strlen(msg), r); + + TEST_ASSERT_EQUAL(current_pos, lseek(fd, 0, SEEK_CUR)); // pwrite should not move the pointer + + TEST_ASSERT_EQUAL(0, close(fd)); +} + +static void test_file_content(const char *filename, const char *msg) +{ + char buf[32] = { 0 }; + const int fd = open(filename, O_RDONLY); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + int r = read(fd, buf, sizeof(buf)); + TEST_ASSERT_NOT_EQUAL(-1, r); + TEST_ASSERT_EQUAL(0, strcmp(msg, buf)); + + TEST_ASSERT_EQUAL(0, close(fd)); +} + +void test_fatfs_pwrite_file(const char *filename) +{ + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC); + TEST_ASSERT_NOT_EQUAL(-1, fd); + TEST_ASSERT_EQUAL(0, close(fd)); + + test_pwrite(filename, 0, "Hello"); + test_file_content(filename, "Hello"); + + test_pwrite(filename, strlen("Hello"), ", world!"); + test_file_content(filename, "Hello, world!"); + test_pwrite(filename, strlen("Hello, "), "Dolly"); + test_file_content(filename, "Hello, Dolly!"); +} + +void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count) +{ + FILE** files = calloc(files_count, sizeof(FILE*)); + for (size_t i = 0; i < files_count; ++i) { + char name[32]; + snprintf(name, sizeof(name), "%s_%d.txt", filename_prefix, i); + files[i] = fopen(name, "w"); + TEST_ASSERT_NOT_NULL(files[i]); + } + /* close everything and clean up */ + for (size_t i = 0; i < files_count; ++i) { + fclose(files[i]); + } + free(files); +} + +void test_fatfs_lseek(const char* filename) +{ + FILE* f = fopen(filename, "wb+"); + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_EQUAL(11, fprintf(f, "0123456789\n")); + TEST_ASSERT_EQUAL(0, fseek(f, -2, SEEK_CUR)); + TEST_ASSERT_EQUAL('9', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 3, SEEK_SET)); + TEST_ASSERT_EQUAL('3', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, -3, SEEK_END)); + TEST_ASSERT_EQUAL('8', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 3, SEEK_END)); + TEST_ASSERT_EQUAL(14, ftell(f)); + TEST_ASSERT_EQUAL(4, fprintf(f, "abc\n")); + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_END)); + TEST_ASSERT_EQUAL(18, ftell(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_SET)); + char buf[20]; + TEST_ASSERT_EQUAL(18, fread(buf, 1, sizeof(buf), f)); + const char ref_buf[] = "0123456789\n\0\0\0abc\n"; + TEST_ASSERT_EQUAL_INT8_ARRAY(ref_buf, buf, sizeof(ref_buf) - 1); + + TEST_ASSERT_EQUAL(0, fclose(f)); +} + +void test_fatfs_truncate_file(const char* filename) +{ + int read = 0; + int truncated_len = 0; + + const char input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char output[sizeof(input)]; + + FILE* f = fopen(filename, "wb"); + + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_EQUAL(strlen(input), fprintf(f, input)); + + TEST_ASSERT_EQUAL(0, fclose(f)); + + + // Extending file beyond size is not supported + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + + // Truncating should succeed + const char truncated_1[] = "ABCDEFGHIJ"; + truncated_len = strlen(truncated_1); + + TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + + f = fopen(filename, "rb"); + TEST_ASSERT_NOT_NULL(f); + + memset(output, 0, sizeof(output)); + read = fread(output, 1, sizeof(output), f); + + TEST_ASSERT_EQUAL(truncated_len, read); + TEST_ASSERT_EQUAL_STRING_LEN(truncated_1, output, truncated_len); + + TEST_ASSERT_EQUAL(0, fclose(f)); + + + // Once truncated, the new file size should be the basis + // whether truncation should succeed or not + TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input))); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + + // Truncating a truncated file should succeed + const char truncated_2[] = "ABCDE"; + truncated_len = strlen(truncated_2); + + TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + + f = fopen(filename, "rb"); + TEST_ASSERT_NOT_NULL(f); + + memset(output, 0, sizeof(output)); + read = fread(output, 1, sizeof(output), f); + + TEST_ASSERT_EQUAL(truncated_len, read); + TEST_ASSERT_EQUAL_STRING_LEN(truncated_2, output, truncated_len); + + TEST_ASSERT_EQUAL(0, fclose(f)); +} + +void test_fatfs_stat(const char* filename, const char* root_dir) +{ + struct tm tm; + tm.tm_year = 2017 - 1900; + tm.tm_mon = 11; + tm.tm_mday = 8; + tm.tm_hour = 19; + tm.tm_min = 51; + tm.tm_sec = 10; + time_t t = mktime(&tm); + printf("Setting time: %s", asctime(&tm)); + struct timeval now = { .tv_sec = t }; + settimeofday(&now, NULL); + + test_fatfs_create_file_with_text(filename, "foo\n"); + + struct stat st; + TEST_ASSERT_EQUAL(0, stat(filename, &st)); + time_t mtime = st.st_mtime; + struct tm mtm; + localtime_r(&mtime, &mtm); + printf("File time: %s", asctime(&mtm)); + TEST_ASSERT(abs(mtime - t) < 2); // fatfs library stores time with 2 second precision + + TEST_ASSERT(st.st_mode & S_IFREG); + TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + + memset(&st, 0, sizeof(st)); + TEST_ASSERT_EQUAL(0, stat(root_dir, &st)); + TEST_ASSERT(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); +} + +void test_fatfs_utime(const char* filename, const char* root_dir) +{ + struct stat achieved_stat; + struct tm desired_tm; + struct utimbuf desired_time = { + .actime = 0, // access time is not supported + .modtime = 0, + }; + time_t false_now = 0; + memset(&desired_tm, 0, sizeof(struct tm)); + + { + // Setting up a false actual time - used when the file is created and for modification with the current time + desired_tm.tm_mon = 10 - 1; + desired_tm.tm_mday = 31; + desired_tm.tm_year = 2018 - 1900; + desired_tm.tm_hour = 10; + desired_tm.tm_min = 35; + desired_tm.tm_sec = 23; + + false_now = mktime(&desired_tm); + + struct timeval now = { .tv_sec = false_now }; + settimeofday(&now, NULL); + } + test_fatfs_create_file_with_text(filename, ""); + + // 00:00:00. January 1st, 1980 - FATFS cannot handle earlier dates + desired_tm.tm_mon = 1 - 1; + desired_tm.tm_mday = 1; + desired_tm.tm_year = 1980 - 1900; + desired_tm.tm_hour = 0; + desired_tm.tm_min = 0; + desired_tm.tm_sec = 0; + printf("Testing mod. time: %s", asctime(&desired_tm)); + desired_time.modtime = mktime(&desired_tm); + TEST_ASSERT_EQUAL(0, utime(filename, &desired_time)); + TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat)); + TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime); + + // current time + TEST_ASSERT_EQUAL(0, utime(filename, NULL)); + TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat)); + printf("Mod. time changed to (false actual time): %s", ctime(&achieved_stat.st_mtime)); + TEST_ASSERT_NOT_EQUAL(desired_time.modtime, achieved_stat.st_mtime); + TEST_ASSERT(false_now - achieved_stat.st_mtime <= 2); // two seconds of tolerance are given + + // 23:59:08. December 31st, 2037 + desired_tm.tm_mon = 12 - 1; + desired_tm.tm_mday = 31; + desired_tm.tm_year = 2037 - 1900; + desired_tm.tm_hour = 23; + desired_tm.tm_min = 59; + desired_tm.tm_sec = 8; + printf("Testing mod. time: %s", asctime(&desired_tm)); + desired_time.modtime = mktime(&desired_tm); + TEST_ASSERT_EQUAL(0, utime(filename, &desired_time)); + TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat)); + TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime); + + //WARNING: it has the Unix Millenium bug (Y2K38) + + // 00:00:00. January 1st, 1970 - FATFS cannot handle years before 1980 + desired_tm.tm_mon = 1 - 1; + desired_tm.tm_mday = 1; + desired_tm.tm_year = 1970 - 1900; + desired_tm.tm_hour = 0; + desired_tm.tm_min = 0; + desired_tm.tm_sec = 0; + printf("Testing mod. time: %s", asctime(&desired_tm)); + desired_time.modtime = mktime(&desired_tm); + TEST_ASSERT_EQUAL(-1, utime(filename, &desired_time)); + TEST_ASSERT_EQUAL(EINVAL, errno); +} + +void test_fatfs_unlink(const char* filename) +{ + test_fatfs_create_file_with_text(filename, "unlink\n"); + + TEST_ASSERT_EQUAL(0, unlink(filename)); + + TEST_ASSERT_NULL(fopen(filename, "r")); +} + +void test_fatfs_link_rename(const char* filename_prefix) +{ + char name_copy[64]; + char name_dst[64]; + char name_src[64]; + snprintf(name_copy, sizeof(name_copy), "%s_cpy.txt", filename_prefix); + snprintf(name_dst, sizeof(name_dst), "%s_dst.txt", filename_prefix); + snprintf(name_src, sizeof(name_src), "%s_src.txt", filename_prefix); + + unlink(name_copy); + unlink(name_dst); + unlink(name_src); + + FILE* f = fopen(name_src, "w+"); + TEST_ASSERT_NOT_NULL(f); + const char* str = "0123456789"; + for (int i = 0; i < 4000; ++i) { + TEST_ASSERT_NOT_EQUAL(EOF, fputs(str, f)); + } + TEST_ASSERT_EQUAL(0, fclose(f)); + TEST_ASSERT_EQUAL(0, link(name_src, name_copy)); + FILE* fcopy = fopen(name_copy, "r"); + TEST_ASSERT_NOT_NULL(fcopy); + TEST_ASSERT_EQUAL(0, fseek(fcopy, 0, SEEK_END)); + TEST_ASSERT_EQUAL(40000, ftell(fcopy)); + TEST_ASSERT_EQUAL(0, fclose(fcopy)); + TEST_ASSERT_EQUAL(0, rename(name_copy, name_dst)); + TEST_ASSERT_NULL(fopen(name_copy, "r")); + FILE* fdst = fopen(name_dst, "r"); + TEST_ASSERT_NOT_NULL(fdst); + TEST_ASSERT_EQUAL(0, fseek(fdst, 0, SEEK_END)); + TEST_ASSERT_EQUAL(40000, ftell(fdst)); + TEST_ASSERT_EQUAL(0, fclose(fdst)); +} + +void test_fatfs_mkdir_rmdir(const char* filename_prefix) +{ + char name_dir1[64]; + char name_dir2[64]; + char name_dir2_file[64]; + snprintf(name_dir1, sizeof(name_dir1), "%s1", filename_prefix); + snprintf(name_dir2, sizeof(name_dir2), "%s2", filename_prefix); + snprintf(name_dir2_file, sizeof(name_dir2_file), "%s2/1.txt", filename_prefix); + + TEST_ASSERT_EQUAL(0, mkdir(name_dir1, 0755)); + struct stat st; + TEST_ASSERT_EQUAL(0, stat(name_dir1, &st)); + TEST_ASSERT_TRUE(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); + TEST_ASSERT_EQUAL(0, rmdir(name_dir1)); + TEST_ASSERT_EQUAL(-1, stat(name_dir1, &st)); + + TEST_ASSERT_EQUAL(0, mkdir(name_dir2, 0755)); + test_fatfs_create_file_with_text(name_dir2_file, "foo\n"); + TEST_ASSERT_EQUAL(0, stat(name_dir2, &st)); + TEST_ASSERT_TRUE(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); + TEST_ASSERT_EQUAL(0, stat(name_dir2_file, &st)); + TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + TEST_ASSERT_TRUE(st.st_mode & S_IFREG); + TEST_ASSERT_EQUAL(-1, rmdir(name_dir2)); + TEST_ASSERT_EQUAL(0, unlink(name_dir2_file)); + TEST_ASSERT_EQUAL(0, rmdir(name_dir2)); +} + +void test_fatfs_can_opendir(const char* path) +{ + char name_dir_file[64]; + const char * file_name = "test_opd.txt"; + snprintf(name_dir_file, sizeof(name_dir_file), "%s/%s", path, file_name); + unlink(name_dir_file); + test_fatfs_create_file_with_text(name_dir_file, "test_opendir\n"); + DIR* dir = opendir(path); + TEST_ASSERT_NOT_NULL(dir); + bool found = false; + while (true) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + if (strcasecmp(de->d_name, file_name) == 0) { + found = true; + break; + } + } + TEST_ASSERT_TRUE(found); + TEST_ASSERT_EQUAL(0, closedir(dir)); + unlink(name_dir_file); +} + +void test_fatfs_opendir_readdir_rewinddir(const char* dir_prefix) +{ + char name_dir_inner_file[64]; + char name_dir_inner[64]; + char name_dir_file3[64]; + char name_dir_file2[64]; + char name_dir_file1[64]; + + snprintf(name_dir_inner_file, sizeof(name_dir_inner_file), "%s/inner/3.txt", dir_prefix); + snprintf(name_dir_inner, sizeof(name_dir_inner), "%s/inner", dir_prefix); + snprintf(name_dir_file3, sizeof(name_dir_file2), "%s/boo.bin", dir_prefix); + snprintf(name_dir_file2, sizeof(name_dir_file2), "%s/2.txt", dir_prefix); + snprintf(name_dir_file1, sizeof(name_dir_file1), "%s/1.txt", dir_prefix); + + unlink(name_dir_inner_file); + rmdir(name_dir_inner); + unlink(name_dir_file1); + unlink(name_dir_file2); + unlink(name_dir_file3); + rmdir(dir_prefix); + + TEST_ASSERT_EQUAL(0, mkdir(dir_prefix, 0755)); + test_fatfs_create_file_with_text(name_dir_file1, "1\n"); + test_fatfs_create_file_with_text(name_dir_file2, "2\n"); + test_fatfs_create_file_with_text(name_dir_file3, "\01\02\03"); + TEST_ASSERT_EQUAL(0, mkdir(name_dir_inner, 0755)); + test_fatfs_create_file_with_text(name_dir_inner_file, "3\n"); + + DIR* dir = opendir(dir_prefix); + TEST_ASSERT_NOT_NULL(dir); + int count = 0; + const char* names[4]; + while(count < 4) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + printf("found '%s'\n", de->d_name); + if (strcasecmp(de->d_name, "1.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "1.txt"; + ++count; + } else if (strcasecmp(de->d_name, "2.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "2.txt"; + ++count; + } else if (strcasecmp(de->d_name, "inner") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_DIR); + names[count] = "inner"; + ++count; + } else if (strcasecmp(de->d_name, "boo.bin") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "boo.bin"; + ++count; + } else { + TEST_FAIL_MESSAGE("unexpected directory entry"); + } + } + TEST_ASSERT_EQUAL(count, 4); + + rewinddir(dir); + struct dirent* de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[0])); + seekdir(dir, 3); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[3])); + seekdir(dir, 1); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[1])); + seekdir(dir, 2); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[2])); + + TEST_ASSERT_EQUAL(0, closedir(dir)); +} + +void test_fatfs_opendir_readdir_rewinddir_utf_8(const char* dir_prefix) +{ + char name_dir_inner_file[64]; + char name_dir_inner[64]; + char name_dir_file3[64]; + char name_dir_file2[64]; + char name_dir_file1[64]; + + snprintf(name_dir_inner_file, sizeof(name_dir_inner_file), "%s/内部目录/内部文件.txt", dir_prefix); + snprintf(name_dir_inner, sizeof(name_dir_inner), "%s/内部目录", dir_prefix); + snprintf(name_dir_file3, sizeof(name_dir_file3), "%s/文件三.bin", dir_prefix); + snprintf(name_dir_file2, sizeof(name_dir_file2), "%s/文件二.txt", dir_prefix); + snprintf(name_dir_file1, sizeof(name_dir_file1), "%s/文件一.txt", dir_prefix); + + unlink(name_dir_inner_file); + rmdir(name_dir_inner); + unlink(name_dir_file1); + unlink(name_dir_file2); + unlink(name_dir_file3); + rmdir(dir_prefix); + + TEST_ASSERT_EQUAL(0, mkdir(dir_prefix, 0755)); + test_fatfs_create_file_with_text(name_dir_file1, "一号\n"); + test_fatfs_create_file_with_text(name_dir_file2, "二号\n"); + test_fatfs_create_file_with_text(name_dir_file3, "\0一\0二\0三"); + TEST_ASSERT_EQUAL(0, mkdir(name_dir_inner, 0755)); + test_fatfs_create_file_with_text(name_dir_inner_file, "三号\n"); + + DIR* dir = opendir(dir_prefix); + TEST_ASSERT_NOT_NULL(dir); + int count = 0; + const char* names[4]; + while(count < 4) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + printf("found '%s'\n", de->d_name); + if (strcasecmp(de->d_name, "文件一.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "文件一.txt"; + ++count; + } else if (strcasecmp(de->d_name, "文件二.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "文件二.txt"; + ++count; + } else if (strcasecmp(de->d_name, "内部目录") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_DIR); + names[count] = "内部目录"; + ++count; + } else if (strcasecmp(de->d_name, "文件三.bin") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "文件三.bin"; + ++count; + } else { + TEST_FAIL_MESSAGE("unexpected directory entry"); + } + } + TEST_ASSERT_EQUAL(count, 4); + + rewinddir(dir); + struct dirent* de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[0])); + seekdir(dir, 3); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[3])); + seekdir(dir, 1); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[1])); + seekdir(dir, 2); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[2])); + + TEST_ASSERT_EQUAL(0, closedir(dir)); +} + +typedef struct { + const char* filename; + bool write; + size_t word_count; + int seed; + SemaphoreHandle_t done; + int result; +} read_write_test_arg_t; + +#define READ_WRITE_TEST_ARG_INIT(name, seed_) \ + { \ + .filename = name, \ + .seed = seed_, \ + .word_count = 8192, \ + .write = true, \ + .done = xSemaphoreCreateBinary() \ + } + +static void read_write_task(void* param) +{ + read_write_test_arg_t* args = (read_write_test_arg_t*) param; + FILE* f = fopen(args->filename, args->write ? "wb" : "rb"); + if (f == NULL) { + args->result = ESP_ERR_NOT_FOUND; + goto done; + } + + srand(args->seed); + for (size_t i = 0; i < args->word_count; ++i) { + uint32_t val = i * 77; + if (args->write) { + int cnt = fwrite(&val, sizeof(val), 1, f); + if (cnt != 1) { + ets_printf("E(w): i=%d, cnt=%d val=%d\n\n", i, cnt, val); + args->result = ESP_FAIL; + goto close; + } + } else { + uint32_t rval; + int cnt = fread(&rval, sizeof(rval), 1, f); + if (cnt != 1 || rval != val) { + ets_printf("E(r): i=%d, cnt=%d rval=%d val=%d\n\n", i, cnt, rval, val); + args->result = ESP_FAIL; + goto close; + } + } + } + args->result = ESP_OK; + +close: + fclose(f); + +done: + xSemaphoreGive(args->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +void test_fatfs_concurrent(const char* filename_prefix) +{ + char names[4][64]; + for (size_t i = 0; i < 4; ++i) { + snprintf(names[i], sizeof(names[i]), "%s%d", filename_prefix, i + 1); + unlink(names[i]); + } + + read_write_test_arg_t args1 = READ_WRITE_TEST_ARG_INIT(names[0], 1); + read_write_test_arg_t args2 = READ_WRITE_TEST_ARG_INIT(names[1], 2); + + printf("writing f1 and f2\n"); + + const int cpuid_0 = 0; + const int cpuid_1 = portNUM_PROCESSORS - 1; + const int stack_size = 4096; + xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, cpuid_1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("f1 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("f2 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + + args1.write = false; + args2.write = false; + read_write_test_arg_t args3 = READ_WRITE_TEST_ARG_INIT(names[2], 3); + read_write_test_arg_t args4 = READ_WRITE_TEST_ARG_INIT(names[3], 4); + + printf("reading f1 and f2, writing f3 and f4\n"); + + xTaskCreatePinnedToCore(&read_write_task, "rw3", stack_size, &args3, 3, NULL, cpuid_1); + xTaskCreatePinnedToCore(&read_write_task, "rw4", stack_size, &args4, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, cpuid_1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("f1 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("f2 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + xSemaphoreTake(args3.done, portMAX_DELAY); + printf("f3 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args3.result); + xSemaphoreTake(args4.done, portMAX_DELAY); + printf("f4 done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args4.result); + + vSemaphoreDelete(args1.done); + vSemaphoreDelete(args2.done); + vSemaphoreDelete(args3.done); + vSemaphoreDelete(args4.done); +} + +void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_t file_size, bool is_write) +{ + const size_t buf_count = file_size / buf_size; + + FILE* f = fopen(filename, (is_write) ? "wb" : "rb"); + TEST_ASSERT_NOT_NULL(f); + + struct timeval tv_start; + gettimeofday(&tv_start, NULL); + for (size_t n = 0; n < buf_count; ++n) { + if (is_write) { + TEST_ASSERT_EQUAL(buf_size, write(fileno(f), buf, buf_size)); + } else { + if (read(fileno(f), buf, buf_size) != buf_size) { + printf("reading at n=%d, eof=%d", n, feof(f)); + TEST_FAIL(); + } + } + } + + struct timeval tv_end; + gettimeofday(&tv_end, NULL); + + TEST_ASSERT_EQUAL(0, fclose(f)); + + float t_s = tv_end.tv_sec - tv_start.tv_sec + 1e-6f * (tv_end.tv_usec - tv_start.tv_usec); + printf("%s %d bytes (block size %d) in %.3fms (%.3f MB/s)\n", + (is_write)?"Wrote":"Read", file_size, buf_size, t_s * 1e3, + file_size / (1024.0f * 1024.0f * t_s)); +} diff --git a/components/fatfs/test/test_fatfs_common.h b/components/fatfs/test/test_fatfs_common.h new file mode 100644 index 000000000..0a792434b --- /dev/null +++ b/components/fatfs/test/test_fatfs_common.h @@ -0,0 +1,73 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file test_fatfs_common.h + * @brief Common routines for FAT-on-SDMMC and FAT-on-WL tests + */ + +#define HEAP_SIZE_CAPTURE(heap_size) \ + heap_size = esp_get_free_heap_size(); + +#define HEAP_SIZE_CHECK(heap_size, tolerance) \ + do {\ + size_t final_heap_size = esp_get_free_heap_size(); \ + if (final_heap_size < heap_size - tolerance) { \ + printf("Initial heap size: %d, final: %d, diff=%d\n", heap_size, final_heap_size, heap_size - final_heap_size); \ + } \ + } while(0) + +const char* fatfs_test_hello_str; +const char* fatfs_test_hello_str_utf; + +void test_fatfs_create_file_with_text(const char* name, const char* text); + +void test_fatfs_overwrite_append(const char* filename); + +void test_fatfs_read_file(const char* filename); + +void test_fatfs_read_file_utf_8(const char* filename); + +void test_fatfs_pread_file(const char* filename); + +void test_fatfs_pwrite_file(const char* filename); + +void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count); + +void test_fatfs_lseek(const char* filename); + +void test_fatfs_truncate_file(const char* path); + +void test_fatfs_stat(const char* filename, const char* root_dir); + +void test_fatfs_utime(const char* filename, const char* root_dir); + +void test_fatfs_unlink(const char* filename); + +void test_fatfs_link_rename(const char* filename_prefix); + +void test_fatfs_concurrent(const char* filename_prefix); + +void test_fatfs_mkdir_rmdir(const char* filename_prefix); + +void test_fatfs_can_opendir(const char* path); + +void test_fatfs_opendir_readdir_rewinddir(const char* dir_prefix); + +void test_fatfs_opendir_readdir_rewinddir_utf_8(const char* dir_prefix); + +void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_t file_size, bool write); + diff --git a/components/fatfs/test/test_fatfs_rawflash.c b/components/fatfs/test/test_fatfs_rawflash.c new file mode 100644 index 000000000..9f34d3c0e --- /dev/null +++ b/components/fatfs/test/test_fatfs_rawflash.c @@ -0,0 +1,363 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "test_utils.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "test_fatfs_common.h" +#include "esp_partition.h" +#include "ff.h" + + +static void test_setup(size_t max_files) +{ + extern const char fatfs_start[] asm("_binary_fatfs_img_start"); + extern const char fatfs_end[] asm("_binary_fatfs_img_end"); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = max_files + }; + const esp_partition_t* part = get_test_data_partition(); + + TEST_ASSERT(part->size >= (fatfs_end - fatfs_start - 1)); + + // spi_flash_mmap_handle_t mmap_handle; + // const void* mmap_ptr; + // TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, SPI_FLASH_MMAP_DATA, &mmap_ptr, &mmap_handle)); + // bool content_valid = memcmp(fatfs_start, mmap_ptr, part->size) == 0; + // spi_flash_munmap(mmap_handle); + + size_t max_space_size = MIN(part->size, fatfs_end - fatfs_start - 1); + bool content_valid = true; + char *buf = malloc(4096); + TEST_ASSERT_NOT_NULL(buf); + + for (size_t i = 0; i < max_space_size; i += 4096) { + size_t bytes = MIN(4096, max_space_size - i); + + TEST_ESP_OK(esp_partition_read(part, i, buf, bytes)); + if (memcmp(fatfs_start + i, buf, bytes)) { + content_valid = false; + break; + } + } + + free(buf); + + if (!content_valid) { + printf("Copying fatfs.img into test partition...\n"); + esp_partition_erase_range(part, 0, part->size); + for (int i = 0; i < part->size; i+= SPI_FLASH_SEC_SIZE) { + ESP_ERROR_CHECK( esp_partition_write(part, i, fatfs_start + i, SPI_FLASH_SEC_SIZE) ); + } + } + + TEST_ESP_OK(esp_vfs_fat_rawflash_mount("/spiflash", "flash_test", &mount_config)); +} + +static void test_teardown(void) +{ + TEST_ESP_OK(esp_vfs_fat_rawflash_unmount("/spiflash","flash_test")); +} + +TEST_CASE("(raw) can read file", "[fatfs]") +{ + test_setup(5); + FILE* f = fopen("/spiflash/hello.txt", "r"); + TEST_ASSERT_NOT_NULL(f); + char buf[32] = { 0 }; + int cb = fread(buf, 1, sizeof(buf), f); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str), cb); + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str, buf)); + TEST_ASSERT_EQUAL(0, fclose(f)); + test_teardown(); +} + +TEST_CASE("(raw) can open maximum number of files", "[fatfs]") +{ + size_t max_files = FOPEN_MAX - 3; /* account for stdin, stdout, stderr */ + test_setup(max_files); + + FILE** files = calloc(max_files, sizeof(FILE*)); + for (size_t i = 0; i < max_files; ++i) { + char name[32]; + snprintf(name, sizeof(name), "/spiflash/f/%d.txt", i + 1); + files[i] = fopen(name, "r"); + TEST_ASSERT_NOT_NULL(files[i]); + } + /* close everything and clean up */ + for (size_t i = 0; i < max_files; ++i) { + fclose(files[i]); + } + free(files); + test_teardown(); + +} + + +TEST_CASE("(raw) can lseek", "[fatfs]") +{ + test_setup(5); + FILE* f = fopen("/spiflash/hello.txt", "r"); + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_EQUAL(0, fseek(f, 2, SEEK_CUR)); + TEST_ASSERT_EQUAL('l', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 4, SEEK_SET)); + TEST_ASSERT_EQUAL('o', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, -5, SEEK_END)); + TEST_ASSERT_EQUAL('r', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 3, SEEK_END)); + TEST_ASSERT_EQUAL(17, ftell(f)); + + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_END)); + TEST_ASSERT_EQUAL(14, ftell(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_SET)); + test_teardown(); +} + +TEST_CASE("(raw) stat returns correct values", "[fatfs]") +{ + test_setup(5); + struct tm tm; + tm.tm_year = 2018 - 1900; + tm.tm_mon = 5; // Note: month can be 0-11 & not 1-12 + tm.tm_mday = 13; + tm.tm_hour = 11; + tm.tm_min = 2; + tm.tm_sec = 10; + time_t t = mktime(&tm); + printf("Reference time: %s", asctime(&tm)); + + struct stat st; + TEST_ASSERT_EQUAL(0, stat("/spiflash/stat.txt", &st)); + + time_t mtime = st.st_mtime; + struct tm mtm; + localtime_r(&mtime, &mtm); + printf("File time: %s", asctime(&mtm)); + TEST_ASSERT(mtime > t); // Modification time should be in future wrt ref time + + TEST_ASSERT(st.st_mode & S_IFREG); + TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + + memset(&st, 0, sizeof(st)); + TEST_ASSERT_EQUAL(0, stat("/spiflash", &st)); + TEST_ASSERT(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); + + test_teardown(); +} + + + +TEST_CASE("(raw) can opendir root directory of FS", "[fatfs]") +{ + test_setup(5); + DIR* dir = opendir("/spiflash"); + TEST_ASSERT_NOT_NULL(dir); + bool found = false; + while (true) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + if (strcasecmp(de->d_name, "test_opd.txt") == 0) { + found = true; + break; + } + } + TEST_ASSERT_TRUE(found); + TEST_ASSERT_EQUAL(0, closedir(dir)); + + test_teardown(); +} +TEST_CASE("(raw) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs]") +{ + test_setup(5); + + DIR* dir = opendir("/spiflash/dir"); + TEST_ASSERT_NOT_NULL(dir); + int count = 0; + const char* names[4]; + while(count < 4) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + printf("found '%s'\n", de->d_name); + if (strcasecmp(de->d_name, "1.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "1.txt"; + ++count; + } else if (strcasecmp(de->d_name, "2.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "2.txt"; + ++count; + } else if (strcasecmp(de->d_name, "inner") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_DIR); + names[count] = "inner"; + ++count; + } else if (strcasecmp(de->d_name, "boo.bin") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "boo.bin"; + ++count; + } else { + TEST_FAIL_MESSAGE("unexpected directory entry"); + } + } + TEST_ASSERT_EQUAL(count, 4); + + rewinddir(dir); + struct dirent* de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[0])); + seekdir(dir, 3); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[3])); + seekdir(dir, 1); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[1])); + seekdir(dir, 2); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[2])); + + TEST_ASSERT_EQUAL(0, closedir(dir)); + + test_teardown(); +} + + +typedef struct { + const char* filename; + size_t word_count; + int seed; + int val; + SemaphoreHandle_t done; + int result; +} read_test_arg_t; + +#define READ_TEST_ARG_INIT(name, seed_, val_) \ + { \ + .filename = name, \ + .seed = seed_, \ + .word_count = 8000, \ + .val = val_, \ + .done = xSemaphoreCreateBinary() \ + } + +static void read_task(void* param) +{ + read_test_arg_t* args = (read_test_arg_t*) param; + FILE* f = fopen(args->filename, "rb"); + if (f == NULL) { + args->result = ESP_ERR_NOT_FOUND; + goto done; + } + + srand(args->seed); + for (size_t i = 0; i < args->word_count; ++i) { + uint32_t rval; + int cnt = fread(&rval, sizeof(rval), 1, f); + if (cnt != 1 || rval != args->val) { + ets_printf("E(r): i=%d, cnt=%d rval=%d val=%d\n\n", i, cnt, rval, args->val); + args->result = ESP_FAIL; + goto close; + } + } + args->result = ESP_OK; + +close: + fclose(f); + +done: + xSemaphoreGive(args->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + + +TEST_CASE("(raw) multiple tasks can use same volume", "[fatfs]") +{ + test_setup(5); + char names[4][64]; + for (size_t i = 0; i < 4; ++i) { + snprintf(names[i], sizeof(names[i]), "/spiflash/ccrnt/%d.txt", i + 1); + } + + read_test_arg_t args1 = READ_TEST_ARG_INIT(names[0], 1, 0x31313131); + read_test_arg_t args2 = READ_TEST_ARG_INIT(names[1], 2, 0x32323232); + read_test_arg_t args3 = READ_TEST_ARG_INIT(names[2], 3, 0x33333333); + read_test_arg_t args4 = READ_TEST_ARG_INIT(names[3], 4, 0x34343434); + + const int cpuid_0 = 0; + const int cpuid_1 = portNUM_PROCESSORS - 1; + const int stack_size = 4096; + + printf("reading files 1.txt 2.txt 3.txt 4.txt \n"); + + xTaskCreatePinnedToCore(&read_task, "r1", stack_size, &args1, 3, NULL, cpuid_1); + xTaskCreatePinnedToCore(&read_task, "r2", stack_size, &args2, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_task, "r3", stack_size, &args3, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_task, "r4", stack_size, &args4, 3, NULL, cpuid_1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("1.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("2.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + xSemaphoreTake(args3.done, portMAX_DELAY); + printf("3.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args3.result); + xSemaphoreTake(args4.done, portMAX_DELAY); + printf("4.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args4.result); + + vSemaphoreDelete(args1.done); + vSemaphoreDelete(args2.done); + vSemaphoreDelete(args3.done); + vSemaphoreDelete(args4.done); + test_teardown(); +} + +TEST_CASE("(raw) read speed test", "[fatfs][timeout=60]") +{ + test_setup(5); + + const size_t buf_size = 16 * 1024; + uint32_t* buf = (uint32_t*) calloc(1, buf_size); + const size_t file_size = 256 * 1024; + const char* file = "/spiflash/256k.bin"; + + test_fatfs_rw_speed(file, buf, 4 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 8 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 16 * 1024, file_size, false); + + free(buf); + test_teardown(); +} diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c new file mode 100644 index 000000000..a484c7b89 --- /dev/null +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -0,0 +1,304 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if 0 + +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/sdmmc_defs.h" +#include "sdmmc_cmd.h" +#include "ff.h" +#include "test_fatfs_common.h" +#include "soc/soc_caps.h" + +#ifdef SOC_SDMMC_HOST_SUPPORTED +#include "driver/sdmmc_host.h" + +static void test_setup(void) +{ + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 16 * 1024 + }; + TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL)); +} + +static void test_teardown(void) +{ + TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount()); +} + +static const char* test_filename = "/sdcard/hello.txt"; + +TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][sd][ignore]") +{ + size_t heap_size; + HEAP_SIZE_CAPTURE(heap_size); + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = 5 + }; + + for (int i = 0; i < 3; ++i) { + printf("Initializing card, attempt %d\n", i); + esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL); + printf("err=%d\n", err); + TEST_ESP_ERR(ESP_ERR_TIMEOUT, err); + } + HEAP_SIZE_CHECK(heap_size, 0); +} + +TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); + test_teardown(); +} + +TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); + test_fatfs_read_file(test_filename); + test_teardown(); +} + +TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); + test_fatfs_pread_file(test_filename); + test_teardown(); +} + +TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_pwrite_file(test_filename); + test_teardown(); +} + +TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_overwrite_append(test_filename); + test_teardown(); +} + +TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_lseek("/sdcard/seek.txt"); + test_teardown(); +} + +TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_truncate_file("/sdcard/truncate.txt"); + test_teardown(); +} + +TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_stat("/sdcard/stat.txt", "/sdcard"); + test_teardown(); +} + +TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_utime("/sdcard/utime.txt", "/sdcard"); + test_teardown(); +} + +TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_unlink("/sdcard/unlink.txt"); + test_teardown(); +} + +TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_link_rename("/sdcard/link"); + test_teardown(); +} + +TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_mkdir_rmdir("/sdcard/dir"); + test_teardown(); +} + +TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_can_opendir("/sdcard"); + test_teardown(); +} + +TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_opendir_readdir_rewinddir("/sdcard/dir"); + test_teardown(); +} + +TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_concurrent("/sdcard/f"); + test_teardown(); +} + +static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write); + +TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") +{ + size_t heap_size; + HEAP_SIZE_CAPTURE(heap_size); + + const size_t buf_size = 16 * 1024; + uint32_t* buf = (uint32_t*) calloc(1, buf_size); + esp_fill_random(buf, buf_size); + const size_t file_size = 1 * 1024 * 1024; + + speed_test(buf, 4 * 1024, file_size, true); + speed_test(buf, 8 * 1024, file_size, true); + speed_test(buf, 16 * 1024, file_size, true); + + speed_test(buf, 4 * 1024, file_size, false); + speed_test(buf, 8 * 1024, file_size, false); + speed_test(buf, 16 * 1024, file_size, false); + + free(buf); + + HEAP_SIZE_CHECK(heap_size, 0); +} + +static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write) +{ + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = write, + .max_files = 5, + .allocation_unit_size = 64 * 1024 + }; + TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL)); + + test_fatfs_rw_speed("/sdcard/4mb.bin", buf, buf_size, file_size, write); + + TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount()); +} + +TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5 + }; + + const char* filename_sd = "/sdcard/sd.txt"; + const char* filename_wl = "/spiflash/wl.txt"; + const char* str_sd = "this is sd\n"; + const char* str_wl = "this is spiflash\n"; + + /* Erase flash before the firs use */ + const esp_partition_t *test_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "flash_test"); + esp_partition_erase_range(test_partition, 0, test_partition->size); + printf("Partition erased: addr- 0x%08x, size- 0x%08x\n", test_partition->address, test_partition->size); + + /* Mount FATFS in SD can WL at the same time. Create a file on each FS */ + wl_handle_t wl_handle = WL_INVALID_HANDLE; + test_setup(); + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &wl_handle)); + unlink(filename_sd); + unlink(filename_wl); + test_fatfs_create_file_with_text(filename_sd, str_sd); + test_fatfs_create_file_with_text(filename_wl, str_wl); + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", wl_handle)); + test_teardown(); + + /* Check that the file "sd.txt" was created on FS in SD, and has the right data */ + test_setup(); + TEST_ASSERT_NULL(fopen(filename_wl, "r")); + FILE* f = fopen(filename_sd, "r"); + TEST_ASSERT_NOT_NULL(f); + char buf[64]; + TEST_ASSERT_NOT_NULL(fgets(buf, sizeof(buf) - 1, f)); + TEST_ASSERT_EQUAL(0, strcmp(buf, str_sd)); + fclose(f); + test_teardown(); + + /* Check that the file "wl.txt" was created on FS in WL, and has the right data */ + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &wl_handle)); + TEST_ASSERT_NULL(fopen(filename_sd, "r")); + f = fopen(filename_wl, "r"); + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_NOT_NULL(fgets(buf, sizeof(buf) - 1, f)); + TEST_ASSERT_EQUAL(0, strcmp(buf, str_wl)); + fclose(f); + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", wl_handle)); +} + +/* + * In FatFs menuconfig, set CONFIG_FATFS_API_ENCODING to UTF-8 and set the + * Codepage to CP936 (Simplified Chinese) in order to run the following tests. + * Ensure that the text editor is UTF-8 compatible when compiling these tests. + */ +#if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936) + +static const char* test_filename_utf_8 = "/sdcard/测试文件.txt"; + +TEST_CASE("(SD) can read file using UTF-8 encoded strings", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + test_setup(); + test_fatfs_create_file_with_text(test_filename_utf_8, fatfs_test_hello_str_utf); + test_fatfs_read_file_utf_8(test_filename_utf_8); + test_teardown(); +} + +TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected using UTF-8 encoded strings", "[fatfs][ignore]") +{ + test_setup(); + test_fatfs_opendir_readdir_rewinddir_utf_8("/sdcard/目录"); + test_teardown(); +} +#endif // CONFIG_FATFS_API_ENCODING_UTF_8 && CONFIG_FATFS_CODEPAGE == 936 + +#endif + +#endif diff --git a/components/fatfs/test/test_fatfs_spiflash.c b/components/fatfs/test/test_fatfs_spiflash.c new file mode 100644 index 000000000..64dbe4ff0 --- /dev/null +++ b/components/fatfs/test/test_fatfs_spiflash.c @@ -0,0 +1,225 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "test_utils.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "test_fatfs_common.h" +#include "wear_levelling.h" +#include "esp_partition.h" + + +static wl_handle_t s_test_wl_handle; +static void test_setup(void) +{ + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5 + }; + + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &s_test_wl_handle)); +} + +static void test_teardown(void) +{ + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", s_test_wl_handle)); +} + +TEST_CASE("(WL) can format partition", "[fatfs][wear_levelling]") +{ + const esp_partition_t* part = get_test_data_partition(); + esp_partition_erase_range(part, 0, part->size); + test_setup(); + test_teardown(); +} + +TEST_CASE("(WL) can create and write file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_create_file_with_text("/spiflash/hello.txt", fatfs_test_hello_str); + test_teardown(); +} + +TEST_CASE("(WL) can read file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_create_file_with_text("/spiflash/hello.txt", fatfs_test_hello_str); + test_fatfs_read_file("/spiflash/hello.txt"); + test_teardown(); +} + +TEST_CASE("(WL) can read file with pread", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_create_file_with_text("/spiflash/hello.txt", fatfs_test_hello_str); + test_fatfs_pread_file("/spiflash/hello.txt"); + test_teardown(); +} + +TEST_CASE("(WL) pwrite() works well", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_pwrite_file("/spiflash/hello.txt"); + test_teardown(); +} + +TEST_CASE("(WL) can open maximum number of files", "[fatfs][wear_levelling]") +{ + size_t max_files = FOPEN_MAX - 3; /* account for stdin, stdout, stderr */ + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = max_files + }; + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &s_test_wl_handle)); + test_fatfs_open_max_files("/spiflash/f", max_files); + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", s_test_wl_handle)); +} + +TEST_CASE("(WL) overwrite and append file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_overwrite_append("/spiflash/hello.txt"); + test_teardown(); +} + +TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_lseek("/spiflash/seek.txt"); + test_teardown(); +} + +TEST_CASE("(WL) can truncate", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_truncate_file("/spiflash/truncate.txt"); + test_teardown(); +} + +TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_stat("/spiflash/stat.txt", "/spiflash"); + test_teardown(); +} + +TEST_CASE("(WL) utime sets modification time", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_utime("/spiflash/utime.txt", "/spiflash"); + test_teardown(); +} + +TEST_CASE("(WL) unlink removes a file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_unlink("/spiflash/unlink.txt"); + test_teardown(); +} + +TEST_CASE("(WL) link copies a file, rename moves a file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_link_rename("/spiflash/link"); + test_teardown(); +} + +TEST_CASE("(WL) can create and remove directories", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_mkdir_rmdir("/spiflash/dir"); + test_teardown(); +} + +TEST_CASE("(WL) can opendir root directory of FS", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_can_opendir("/spiflash"); + test_teardown(); +} + +TEST_CASE("(WL) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_opendir_readdir_rewinddir("/spiflash/dir"); + test_teardown(); +} + +TEST_CASE("(WL) multiple tasks can use same volume", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_concurrent("/spiflash/f"); + test_teardown(); +} + +TEST_CASE("(WL) write/read speed test", "[fatfs][wear_levelling][timeout=60]") +{ + /* Erase partition before running the test to get consistent results */ + const esp_partition_t* part = get_test_data_partition(); + esp_partition_erase_range(part, 0, part->size); + + test_setup(); + + const size_t buf_size = 16 * 1024; + uint32_t* buf = (uint32_t*) calloc(1, buf_size); + esp_fill_random(buf, buf_size); + const size_t file_size = 256 * 1024; + const char* file = "/spiflash/256k.bin"; + + test_fatfs_rw_speed(file, buf, 4 * 1024, file_size, true); + test_fatfs_rw_speed(file, buf, 8 * 1024, file_size, true); + test_fatfs_rw_speed(file, buf, 16 * 1024, file_size, true); + + test_fatfs_rw_speed(file, buf, 4 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 8 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 16 * 1024, file_size, false); + + unlink(file); + + free(buf); + test_teardown(); +} + +/* + * In FatFs menuconfig, set CONFIG_FATFS_API_ENCODING to UTF-8 and set the + * Codepage to CP936 (Simplified Chinese) in order to run the following tests. + * Ensure that the text editor is UTF-8 compatible when compiling these tests. + */ +#if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936) +TEST_CASE("(WL) can read file with UTF-8 encoded strings", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_create_file_with_text("/spiflash/测试文件.txt", fatfs_test_hello_str_utf); + test_fatfs_read_file_utf_8("/spiflash/测试文件.txt"); + test_teardown(); +} + +TEST_CASE("(WL) opendir, readdir, rewinddir, seekdir work as expected using UTF-8 encoded strings", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_opendir_readdir_rewinddir_utf_8("/spiflash/目录"); + test_teardown(); +} +#endif diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile new file mode 100644 index 000000000..2e63322c0 --- /dev/null +++ b/components/fatfs/test_fatfs_host/Makefile @@ -0,0 +1,106 @@ +ifndef COMPONENT +COMPONENT := fatfs +endif + +COMPONENT_LIB := lib$(COMPONENT).a +TEST_PROGRAM := test_$(COMPONENT) + +STUBS_LIB_DIR := ../../../components/spi_flash/sim/stubs +STUBS_LIB_BUILD_DIR := $(STUBS_LIB_DIR)/build +STUBS_LIB := libstubs.a + +SPI_FLASH_SIM_DIR := ../../../components/spi_flash/sim +SPI_FLASH_SIM_BUILD_DIR := $(SPI_FLASH_SIM_DIR)/build +SPI_FLASH_SIM_LIB := libspi_flash.a + +WEAR_LEVELLING_DIR := ../../../components/wear_levelling/test_wl_host +WEAR_LEVELLING_BUILD_DIR := $(WEAR_LEVELLING_DIR)/build +WEAR_LEVELLING_LIB := libwl.a + +include Makefile.files + +all: test + +ifndef SDKCONFIG +SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h)) +SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h +else +SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG))) +endif + +INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR) ../../../tools/catch) + +CPPFLAGS += $(INCLUDE_FLAGS) -g -m32 +CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32 + +# Build libraries that this component is dependent on +$(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB): force + $(MAKE) -C $(STUBS_LIB_DIR) lib SDKCONFIG=$(SDKCONFIG) + +$(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib SDKCONFIG=$(SDKCONFIG) + +$(WEAR_LEVELLING_BUILD_DIR)/$(WEAR_LEVELLING_LIB): force + $(MAKE) -C $(WEAR_LEVELLING_DIR) lib SDKCONFIG=$(SDKCONFIG) + +# Create target for building this component as a library +CFILES := $(filter %.c, $(SOURCE_FILES)) +CPPFILES := $(filter %.cpp, $(SOURCE_FILES)) + +CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1})) +CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1})) + +ifndef BUILD_DIR +BUILD_DIR := build +endif + +OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)))) + +define COMPILE_C +$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG) + mkdir -p $(BUILD_DIR) + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1} +endef + +define COMPILE_CPP +$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG) + mkdir -p $(BUILD_DIR) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1} +endef + +$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG) + mkdir -p $(BUILD_DIR) + $(AR) rcs $@ $^ + +lib: $(BUILD_DIR)/$(COMPONENT_LIB) + +$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile)))) +$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile)))) + +# Create target for building this component as a test +TEST_SOURCE_FILES = \ + test_fatfs.cpp \ + main.cpp \ + +TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o)) + +$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(WEAR_LEVELLING_BUILD_DIR)/$(WEAR_LEVELLING_LIB) $(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB) $(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB) partition_table.bin $(SDKCONFIG) + g++ $(LDFLAGS) $(CXXFLAGS) -o $@ $(TEST_OBJ_FILES) -L$(BUILD_DIR) -l:$(COMPONENT_LIB) -L$(WEAR_LEVELLING_BUILD_DIR) -l:$(WEAR_LEVELLING_LIB) -L$(SPI_FLASH_SIM_BUILD_DIR) -l:$(SPI_FLASH_SIM_LIB) -L$(STUBS_LIB_BUILD_DIR) -l:$(STUBS_LIB) + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +# Create other necessary targets +partition_table.bin: partition_table.csv + python ../../../components/partition_table/gen_esp32part.py --verify $< $@ + +force: + +# Create target to cleanup files +clean: + $(MAKE) -C $(STUBS_LIB_DIR) clean + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean + $(MAKE) -C $(WEAR_LEVELLING_DIR) clean + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin + +.PHONY: all lib test clean force diff --git a/components/fatfs/test_fatfs_host/Makefile.files b/components/fatfs/test_fatfs_host/Makefile.files new file mode 100644 index 000000000..ab77bc40c --- /dev/null +++ b/components/fatfs/test_fatfs_host/Makefile.files @@ -0,0 +1,38 @@ +SOURCE_FILES := \ + $(addprefix ../src/, \ + ff.c \ + ffunicode.c \ + ) \ + $(addprefix ../diskio/,\ + diskio.c \ + diskio_wl.c \ + ) \ + ../port/linux/ffsystem.c + +INCLUDE_DIRS := \ + . \ + ../diskio \ + ../src \ + $(addprefix ../../spi_flash/sim/stubs/, \ + app_update/include \ + driver/include \ + esp32/include \ + freertos/include \ + log/include \ + newlib/include \ + sdmmc/include \ + vfs/include \ + ) \ + $(addprefix ../../../components/, \ + esp_rom/include \ + xtensa/include \ + xtensa/esp32/include \ + soc/esp32/include \ + soc/include \ + esp32/include \ + esp_common/include \ + bootloader_support/include \ + app_update/include \ + spi_flash/include \ + wear_levelling/include \ + ) diff --git a/components/fatfs/test_fatfs_host/component.mk b/components/fatfs/test_fatfs_host/component.mk new file mode 100644 index 000000000..82dea0b0c --- /dev/null +++ b/components/fatfs/test_fatfs_host/component.mk @@ -0,0 +1,17 @@ +include $(COMPONENT_PATH)/Makefile.files + +COMPONENT_OWNBUILDTARGET := 1 +COMPONENT_OWNCLEANTARGET := 1 + +COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS) + +.PHONY: build +build: $(SDKCONFIG_HEADER) + $(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME) + +CLEAN_FILES := component_project_vars.mk +.PHONY: clean +clean: + $(summary) RM $(CLEAN_FILES) + rm -f $(CLEAN_FILES) + $(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME) \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/main.cpp b/components/fatfs/test_fatfs_host/main.cpp new file mode 100644 index 000000000..0c7c351f4 --- /dev/null +++ b/components/fatfs/test_fatfs_host/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/components/fatfs/test_fatfs_host/partition_table.csv b/components/fatfs/test_fatfs_host/partition_table.csv new file mode 100644 index 000000000..9b4dbd1ba --- /dev/null +++ b/components/fatfs/test_fatfs_host/partition_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/sdkconfig/sdkconfig.h b/components/fatfs/test_fatfs_host/sdkconfig/sdkconfig.h new file mode 100644 index 000000000..1c08df4ae --- /dev/null +++ b/components/fatfs/test_fatfs_host/sdkconfig/sdkconfig.h @@ -0,0 +1,8 @@ +# pragma once +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_ESPTOOLPY_FLASHSIZE "8MB" +//currently use the legacy implementation, since the stubs for new HAL are not done yet +#define CONFIG_SPI_FLASH_USE_LEGACY_IMPL diff --git a/components/fatfs/test_fatfs_host/test_fatfs.cpp b/components/fatfs/test_fatfs_host/test_fatfs.cpp new file mode 100644 index 000000000..d1f7119e6 --- /dev/null +++ b/components/fatfs/test_fatfs_host/test_fatfs.cpp @@ -0,0 +1,93 @@ +#include +#include + +#include "ff.h" +#include "esp_partition.h" +#include "wear_levelling.h" +#include "diskio_impl.h" +#include "diskio_wl.h" + +#include "catch.hpp" + +extern "C" void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); + +TEST_CASE("create volume, open file, write and read back data", "[fatfs]") +{ + _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin"); + + FRESULT fr_result; + BYTE pdrv; + FATFS fs; + FIL file; + UINT bw; + + esp_err_t esp_result; + + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); + + // Mount wear-levelled partition + wl_handle_t wl_handle; + esp_result = wl_mount(partition, &wl_handle); + REQUIRE(esp_result == ESP_OK); + + // Get a physical drive + esp_result = ff_diskio_get_drive(&pdrv); + REQUIRE(esp_result == ESP_OK); + + // Register physical drive as wear-levelled partition + esp_result = ff_diskio_register_wl_partition(pdrv, wl_handle); + + // Create FAT volume on the entire disk + DWORD part_list[] = {100, 0, 0, 0}; + BYTE work_area[FF_MAX_SS]; + + fr_result = f_fdisk(pdrv, part_list, work_area); + REQUIRE(fr_result == FR_OK); + fr_result = f_mkfs("", FM_ANY, 0, work_area, sizeof(work_area)); // Use default volume + + // Mount the volume + fr_result = f_mount(&fs, "", 0); + REQUIRE(fr_result == FR_OK); + + // Open, write and read data + fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); + REQUIRE(fr_result == FR_OK); + + // Generate data + uint32_t data_size = 100000; + + char *data = (char*) malloc(data_size); + char *read = (char*) malloc(data_size); + + for(uint32_t i = 0; i < data_size; i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + + // Write generated data + fr_result = f_write(&file, data, data_size, &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == data_size); + + // Move to beginning of file + fr_result = f_lseek(&file, 0); + REQUIRE(fr_result == FR_OK); + + // Read written data + fr_result = f_read(&file, read, data_size, &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == data_size); + + REQUIRE(memcmp(data, read, data_size) == 0); + + // Close file + fr_result = f_close(&file); + REQUIRE(fr_result == FR_OK); + + // Unmount default volume + fr_result = f_mount(0, "", 0); + REQUIRE(fr_result == FR_OK); + + free(read); + free(data); +} diff --git a/components/fatfs/vfs/esp_vfs_fat.h b/components/fatfs/vfs/esp_vfs_fat.h new file mode 100644 index 000000000..01a4c70d1 --- /dev/null +++ b/components/fatfs/vfs/esp_vfs_fat.h @@ -0,0 +1,236 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include "esp_err.h" +#include "driver/gpio.h" +#include "driver/sdmmc_types.h" +#include "driver/sdspi_host.h" +#include "ff.h" +#include "wear_levelling.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Register FATFS with VFS component + * + * This function registers given FAT drive in VFS, at the specified base path. + * If only one drive is used, fat_drive argument can be an empty string. + * Refer to FATFS library documentation on how to specify FAT drive. + * This function also allocates FATFS structure which should be used for f_mount + * call. + * + * @note This function doesn't mount the drive into FATFS, it just connects + * POSIX and C standard library IO function with FATFS. You need to mount + * desired drive into FATFS separately. + * + * @param base_path path prefix where FATFS should be registered + * @param fat_drive FATFS drive specification; if only one drive is used, can be an empty string + * @param max_files maximum number of files which can be open at the same time + * @param[out] out_fs pointer to FATFS structure which can be used for FATFS f_mount call is returned via this argument. + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_register was already called + * - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered + */ +esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, + size_t max_files, FATFS** out_fs); + +/** + * @brief Un-register FATFS from VFS + * + * @note FATFS structure returned by esp_vfs_fat_register is destroyed after + * this call. Make sure to call f_mount function to unmount it before + * calling esp_vfs_fat_unregister_ctx. + * Difference between this function and the one above is that this one + * will release the correct drive, while the one above will release + * the last registered one + * + * @param base_path path prefix where FATFS is registered. This is the same + * used when esp_vfs_fat_register was called + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS + */ +esp_err_t esp_vfs_fat_unregister_path(const char* base_path); + + +/** + * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions + */ +typedef struct { + /** + * If FAT partition can not be mounted, and this parameter is true, + * create partition table and format the filesystem. + */ + bool format_if_mount_failed; + int max_files; ///< Max number of open files + /** + * If format_if_mount_failed is set, and mount fails, format the card + * with given allocation unit size. Must be a power of 2, between sector + * size and 128 * sector size. + * For SD cards, sector size is always 512 bytes. For wear_levelling, + * sector size is determined by CONFIG_WL_SECTOR_SIZE option. + * + * Using larger allocation unit size will result in higher read/write + * performance and higher overhead when storing small files. + * + * Setting this field to 0 will result in allocation unit set to the + * sector size. + */ + size_t allocation_unit_size; +} esp_vfs_fat_mount_config_t; + +// Compatibility definition +typedef esp_vfs_fat_mount_config_t esp_vfs_fat_sdmmc_mount_config_t; + +/** + * @brief Convenience function to get FAT filesystem on SD card registered in VFS + * + * This is an all-in-one function which does the following: + * - initializes SDMMC driver or SPI driver with configuration in host_config + * - initializes SD card with configuration in slot_config + * - mounts FAT partition on SD card using FATFS library, with configuration in mount_config + * - registers FATFS library with VFS, with prefix given by base_prefix variable + * + * This function is intended to make example code more compact. + * For real world applications, developers should implement the logic of + * probing SD card, locating and mounting partition, and registering FATFS in VFS, + * with proper error checking and handling of exceptional conditions. + * + * @param base_path path where partition should be registered (e.g. "/sdcard") + * @param host_config Pointer to structure describing SDMMC host. When using + * SDMMC peripheral, this structure can be initialized using + * SDMMC_HOST_DEFAULT() macro. When using SPI peripheral, + * this structure can be initialized using SDSPI_HOST_DEFAULT() + * macro. + * @param slot_config Pointer to structure with slot configuration. + * For SDMMC peripheral, pass a pointer to sdmmc_slot_config_t + * structure initialized using SDMMC_SLOT_CONFIG_DEFAULT. + * For SPI peripheral, pass a pointer to sdspi_slot_config_t + * structure initialized using SDSPI_SLOT_CONFIG_DEFAULT. + * @param mount_config pointer to structure with extra parameters for mounting FATFS + * @param[out] out_card if not NULL, pointer to the card information structure will be returned via this argument + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers + */ +esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, + const sdmmc_host_t* host_config, + const void* slot_config, + const esp_vfs_fat_mount_config_t* mount_config, + sdmmc_card_t** out_card); + +/** + * @brief Unmount FAT filesystem and release resources acquired using esp_vfs_fat_sdmmc_mount + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount hasn't been called + */ +esp_err_t esp_vfs_fat_sdmmc_unmount(void); + +/** + * @brief Convenience function to initialize FAT filesystem in SPI flash and register it in VFS + * + * This is an all-in-one function which does the following: + * + * - finds the partition with defined partition_label. Partition label should be + * configured in the partition table. + * - initializes flash wear levelling library on top of the given partition + * - mounts FAT partition using FATFS library on top of flash wear levelling + * library + * - registers FATFS library with VFS, with prefix given by base_prefix variable + * + * This function is intended to make example code more compact. + * + * @param base_path path where FATFS partition should be mounted (e.g. "/spiflash") + * @param partition_label label of the partition which should be used + * @param mount_config pointer to structure with extra parameters for mounting FATFS + * @param[out] wl_handle wear levelling driver handle + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from wear levelling library, SPI flash driver, or FATFS drivers + */ +esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config, + wl_handle_t* wl_handle); + +/** + * @brief Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount + * + * @param base_path path where partition should be registered (e.g. "/spiflash") + * @param wl_handle wear levelling driver handle returned by esp_vfs_fat_spiflash_mount + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn't been called + */ + esp_err_t esp_vfs_fat_spiflash_unmount(const char* base_path, wl_handle_t wl_handle); + + +/** + * @brief Convenience function to initialize read-only FAT filesystem and register it in VFS + * + * This is an all-in-one function which does the following: + * + * - finds the partition with defined partition_label. Partition label should be + * configured in the partition table. + * - mounts FAT partition using FATFS library + * - registers FATFS library with VFS, with prefix given by base_prefix variable + * + * @note Wear levelling is not used when FAT is mounted in read-only mode using this function. + * + * @param base_path path where FATFS partition should be mounted (e.g. "/spiflash") + * @param partition_label label of the partition which should be used + * @param mount_config pointer to structure with extra parameters for mounting FATFS + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_rawflash_mount was already called for the same partition + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from SPI flash driver, or FATFS drivers + */ +esp_err_t esp_vfs_fat_rawflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config); + +/** + * @brief Unmount FAT filesystem and release resources acquired using esp_vfs_fat_rawflash_mount + * + * @param base_path path where partition should be registered (e.g. "/spiflash") + * @param partition_label label of partition to be unmounted + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn't been called + */ + esp_err_t esp_vfs_fat_rawflash_unmount(const char* base_path, const char* partition_label); + + +#ifdef __cplusplus +} +#endif diff --git a/components/fatfs/vfs/vfs_fat.c b/components/fatfs/vfs/vfs_fat.c new file mode 100644 index 000000000..5506b1158 --- /dev/null +++ b/components/fatfs/vfs/vfs_fat.c @@ -0,0 +1,956 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include "esp_vfs.h" +#include "esp_log.h" +#include "ff.h" +#include "diskio_impl.h" + +typedef struct { + char fat_drive[8]; /* FAT drive name */ + char base_path[ESP_VFS_PATH_MAX]; /* base path in VFS where partition is registered */ + size_t max_files; /* max number of simultaneously open files; size of files[] array */ + _lock_t lock; /* guard for access to this structure */ + FATFS fs; /* fatfs library FS structure */ + char tmp_path_buf[FILENAME_MAX+3]; /* temporary buffer used to prepend drive name to the path */ + char tmp_path_buf2[FILENAME_MAX+3]; /* as above; used in functions which take two path arguments */ + bool *o_append; /* O_APPEND is stored here for each max_files entries (because O_APPEND is not compatible with FA_OPEN_APPEND) */ + FIL files[0]; /* array with max_files entries; must be the final member of the structure */ +} vfs_fat_ctx_t; + +typedef struct { + DIR dir; + long offset; + FF_DIR ffdir; + FILINFO filinfo; + struct dirent cur_dirent; +} vfs_fat_dir_t; + +/* Date and time storage formats in FAT */ +typedef union { + struct { + uint16_t mday : 5; /* Day of month, 1 - 31 */ + uint16_t mon : 4; /* Month, 1 - 12 */ + uint16_t year : 7; /* Year, counting from 1980. E.g. 37 for 2017 */ + }; + uint16_t as_int; +} fat_date_t; + +typedef union { + struct { + uint16_t sec : 5; /* Seconds divided by 2. E.g. 21 for 42 seconds */ + uint16_t min : 6; /* Minutes, 0 - 59 */ + uint16_t hour : 5; /* Hour, 0 - 23 */ + }; + uint16_t as_int; +} fat_time_t; + +static const char* TAG = "vfs_fat"; + +static ssize_t vfs_fat_write(void* p, int fd, const void * data, size_t size); +static off_t vfs_fat_lseek(void* p, int fd, off_t size, int mode); +static ssize_t vfs_fat_read(void* ctx, int fd, void * dst, size_t size); +static ssize_t vfs_fat_pread(void *ctx, int fd, void *dst, size_t size, off_t offset); +static ssize_t vfs_fat_pwrite(void *ctx, int fd, const void *src, size_t size, off_t offset); +static int vfs_fat_open(void* ctx, const char * path, int flags, int mode); +static int vfs_fat_close(void* ctx, int fd); +static int vfs_fat_fstat(void* ctx, int fd, struct stat * st); +static int vfs_fat_stat(void* ctx, const char * path, struct stat * st); +static int vfs_fat_fsync(void* ctx, int fd); +static int vfs_fat_link(void* ctx, const char* n1, const char* n2); +static int vfs_fat_unlink(void* ctx, const char *path); +static int vfs_fat_rename(void* ctx, const char *src, const char *dst); +static DIR* vfs_fat_opendir(void* ctx, const char* name); +static struct dirent* vfs_fat_readdir(void* ctx, DIR* pdir); +static int vfs_fat_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent); +static long vfs_fat_telldir(void* ctx, DIR* pdir); +static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset); +static int vfs_fat_closedir(void* ctx, DIR* pdir); +static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode); +static int vfs_fat_rmdir(void* ctx, const char* name); +static int vfs_fat_access(void* ctx, const char *path, int amode); +static int vfs_fat_truncate(void* ctx, const char *path, off_t length); +static int vfs_fat_utime(void* ctx, const char *path, const struct utimbuf *times); + +static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL }; +//backwards-compatibility with esp_vfs_fat_unregister() +static vfs_fat_ctx_t* s_fat_ctx = NULL; + +static size_t find_context_index_by_path(const char* base_path) +{ + for(size_t i=0; ibase_path, base_path)) { + return i; + } + } + return FF_VOLUMES; +} + +static size_t find_unused_context_index(void) +{ + for(size_t i=0; io_append = ff_memalloc(max_files * sizeof(bool)); + if (fat_ctx->o_append == NULL) { + free(fat_ctx); + return ESP_ERR_NO_MEM; + } + memset(fat_ctx->o_append, 0, max_files * sizeof(bool)); + fat_ctx->max_files = max_files; + strlcpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); + strlcpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); + + esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx); + if (err != ESP_OK) { + free(fat_ctx->o_append); + free(fat_ctx); + return err; + } + + _lock_init(&fat_ctx->lock); + s_fat_ctxs[ctx] = fat_ctx; + + //compatibility + s_fat_ctx = fat_ctx; + + *out_fs = &fat_ctx->fs; + + return ESP_OK; +} + +esp_err_t esp_vfs_fat_unregister_path(const char* base_path) +{ + size_t ctx = find_context_index_by_path(base_path); + if (ctx == FF_VOLUMES) { + return ESP_ERR_INVALID_STATE; + } + vfs_fat_ctx_t* fat_ctx = s_fat_ctxs[ctx]; + esp_err_t err = esp_vfs_unregister(fat_ctx->base_path); + if (err != ESP_OK) { + return err; + } + _lock_close(&fat_ctx->lock); + free(fat_ctx->o_append); + free(fat_ctx); + s_fat_ctxs[ctx] = NULL; + return ESP_OK; +} + +static int get_next_fd(vfs_fat_ctx_t* fat_ctx) +{ + for (size_t i = 0; i < fat_ctx->max_files; ++i) { + if (fat_ctx->files[i].obj.fs == NULL) { + return (int) i; + } + } + return -1; +} + +static int fat_mode_conv(int m) +{ + int res = 0; + int acc_mode = m & O_ACCMODE; + if (acc_mode == O_RDONLY) { + res |= FA_READ; + } else if (acc_mode == O_WRONLY) { + res |= FA_WRITE; + } else if (acc_mode == O_RDWR) { + res |= FA_READ | FA_WRITE; + } + if ((m & O_CREAT) && (m & O_EXCL)) { + res |= FA_CREATE_NEW; + } else if ((m & O_CREAT) && (m & O_TRUNC)) { + res |= FA_CREATE_ALWAYS; + } else if (m & O_APPEND) { + res |= FA_OPEN_ALWAYS; + } else { + res |= FA_OPEN_EXISTING; + } + return res; +} + +static int fresult_to_errno(FRESULT fr) +{ + switch(fr) { + case FR_DISK_ERR: return EIO; + case FR_INT_ERR: return EIO; + case FR_NOT_READY: return ENODEV; + case FR_NO_FILE: return ENOENT; + case FR_NO_PATH: return ENOENT; + case FR_INVALID_NAME: return EINVAL; + case FR_DENIED: return EACCES; + case FR_EXIST: return EEXIST; + case FR_INVALID_OBJECT: return EBADF; + case FR_WRITE_PROTECTED: return EACCES; + case FR_INVALID_DRIVE: return ENXIO; + case FR_NOT_ENABLED: return ENODEV; + case FR_NO_FILESYSTEM: return ENODEV; + case FR_MKFS_ABORTED: return EINTR; + case FR_TIMEOUT: return ETIMEDOUT; + case FR_LOCKED: return EACCES; + case FR_NOT_ENOUGH_CORE: return ENOMEM; + case FR_TOO_MANY_OPEN_FILES: return ENFILE; + case FR_INVALID_PARAMETER: return EINVAL; + case FR_OK: return 0; + } + assert(0 && "unhandled FRESULT"); + return ENOTSUP; +} + +static void file_cleanup(vfs_fat_ctx_t* ctx, int fd) +{ + memset(&ctx->files[fd], 0, sizeof(FIL)); +} + +/** + * @brief Prepend drive letters to path names + * This function returns new path path pointers, pointing to a temporary buffer + * inside ctx. + * @note Call this function with ctx->lock acquired. Paths are valid while the + * lock is held. + * @param ctx vfs_fat_ctx_t context + * @param[inout] path as input, pointer to the path; as output, pointer to the new path + * @param[inout] path2 as input, pointer to the path; as output, pointer to the new path + */ +static void prepend_drive_to_path(vfs_fat_ctx_t * ctx, const char ** path, const char ** path2){ + snprintf(ctx->tmp_path_buf, sizeof(ctx->tmp_path_buf), "%s%s", ctx->fat_drive, *path); + *path = ctx->tmp_path_buf; + if(path2){ + snprintf(ctx->tmp_path_buf2, sizeof(ctx->tmp_path_buf2), "%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, *path2); + *path2 = ctx->tmp_path_buf2; + } +} + +static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) +{ + ESP_LOGV(TAG, "%s: path=\"%s\", flags=%x, mode=%x", __func__, path, flags, mode); + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + int fd = get_next_fd(fat_ctx); + if (fd < 0) { + _lock_release(&fat_ctx->lock); + ESP_LOGE(TAG, "open: no free file descriptors"); + errno = ENFILE; + return -1; + } + FRESULT res = f_open(&fat_ctx->files[fd], path, fat_mode_conv(flags)); + if (res != FR_OK) { + file_cleanup(fat_ctx, fd); + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + // O_APPEND need to be stored because it is not compatible with FA_OPEN_APPEND: + // - FA_OPEN_APPEND means to jump to the end of file only after open() + // - O_APPEND means to jump to the end only before each write() + // Other VFS drivers handles O_APPEND well (to the best of my knowledge), + // therefore this flag is stored here (at this VFS level) in order to save + // memory. + fat_ctx->o_append[fd] = (flags & O_APPEND) == O_APPEND; + _lock_release(&fat_ctx->lock); + return fd; +} + +static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + FIL* file = &fat_ctx->files[fd]; + FRESULT res; + if (fat_ctx->o_append[fd]) { + if ((res = f_lseek(file, f_size(file))) != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + } + unsigned written = 0; + res = f_write(file, data, size, &written); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + if (written == 0) { + return -1; + } + } + return written; +} + +static ssize_t vfs_fat_read(void* ctx, int fd, void * dst, size_t size) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + FIL* file = &fat_ctx->files[fd]; + unsigned read = 0; + FRESULT res = f_read(file, dst, size, &read); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + if (read == 0) { + return -1; + } + } + return read; +} + +static ssize_t vfs_fat_pread(void *ctx, int fd, void *dst, size_t size, off_t offset) +{ + ssize_t ret = -1; + vfs_fat_ctx_t *fat_ctx = (vfs_fat_ctx_t *) ctx; + _lock_acquire(&fat_ctx->lock); + FIL *file = &fat_ctx->files[fd]; + const off_t prev_pos = f_tell(file); + + FRESULT f_res = f_lseek(file, offset); + if (f_res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + errno = fresult_to_errno(f_res); + goto pread_release; + } + + unsigned read = 0; + f_res = f_read(file, dst, size, &read); + if (f_res == FR_OK) { + ret = read; + } else { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + errno = fresult_to_errno(f_res); + // No return yet - need to restore previous position + } + + f_res = f_lseek(file, prev_pos); + if (f_res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + if (ret >= 0) { + errno = fresult_to_errno(f_res); + } // else f_read failed so errno shouldn't be overwritten + ret = -1; // in case the read was successful but the seek wasn't + } + +pread_release: + _lock_release(&fat_ctx->lock); + return ret; +} + +static ssize_t vfs_fat_pwrite(void *ctx, int fd, const void *src, size_t size, off_t offset) +{ + ssize_t ret = -1; + vfs_fat_ctx_t *fat_ctx = (vfs_fat_ctx_t *) ctx; + _lock_acquire(&fat_ctx->lock); + FIL *file = &fat_ctx->files[fd]; + const off_t prev_pos = f_tell(file); + + FRESULT f_res = f_lseek(file, offset); + if (f_res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + errno = fresult_to_errno(f_res); + goto pwrite_release; + } + + unsigned wr = 0; + f_res = f_write(file, src, size, &wr); + if (f_res == FR_OK) { + ret = wr; + } else { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + errno = fresult_to_errno(f_res); + // No return yet - need to restore previous position + } + + f_res = f_lseek(file, prev_pos); + if (f_res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res); + if (ret >= 0) { + errno = fresult_to_errno(f_res); + } // else f_write failed so errno shouldn't be overwritten + ret = -1; // in case the write was successful but the seek wasn't + } + +pwrite_release: + _lock_release(&fat_ctx->lock); + return ret; +} + +static int vfs_fat_fsync(void* ctx, int fd) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + FIL* file = &fat_ctx->files[fd]; + FRESULT res = f_sync(file); + _lock_release(&fat_ctx->lock); + int rc = 0; + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + rc = -1; + } + return rc; +} + +static int vfs_fat_close(void* ctx, int fd) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + FIL* file = &fat_ctx->files[fd]; + FRESULT res = f_close(file); + file_cleanup(fat_ctx, fd); + _lock_release(&fat_ctx->lock); + int rc = 0; + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + rc = -1; + } + return rc; +} + +static off_t vfs_fat_lseek(void* ctx, int fd, off_t offset, int mode) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + FIL* file = &fat_ctx->files[fd]; + off_t new_pos; + if (mode == SEEK_SET) { + new_pos = offset; + } else if (mode == SEEK_CUR) { + off_t cur_pos = f_tell(file); + new_pos = cur_pos + offset; + } else if (mode == SEEK_END) { + off_t size = f_size(file); + new_pos = size + offset; + } else { + errno = EINVAL; + return -1; + } + FRESULT res = f_lseek(file, new_pos); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return new_pos; +} + +static int vfs_fat_fstat(void* ctx, int fd, struct stat * st) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + FIL* file = &fat_ctx->files[fd]; + st->st_size = f_size(file); + st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFREG; + st->st_mtime = 0; + st->st_atime = 0; + st->st_ctime = 0; + return 0; +} + +static inline mode_t get_stat_mode(bool is_dir) +{ + return S_IRWXU | S_IRWXG | S_IRWXO | + ((is_dir) ? S_IFDIR : S_IFREG); +} + +static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) +{ + if (strcmp(path, "/") == 0) { + /* FatFS f_stat function does not work for the drive root. + * Just pretend that this is a directory. + */ + memset(st, 0, sizeof(*st)); + st->st_mode = get_stat_mode(true); + return 0; + } + + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + FILINFO info; + FRESULT res = f_stat(path, &info); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + + memset(st, 0, sizeof(*st)); + st->st_size = info.fsize; + st->st_mode = get_stat_mode((info.fattrib & AM_DIR) != 0); + fat_date_t fdate = { .as_int = info.fdate }; + fat_time_t ftime = { .as_int = info.ftime }; + struct tm tm = { + .tm_mday = fdate.mday, + .tm_mon = fdate.mon - 1, /* unlike tm_mday, tm_mon is zero-based */ + .tm_year = fdate.year + 80, + .tm_sec = ftime.sec * 2, + .tm_min = ftime.min, + .tm_hour = ftime.hour + }; + st->st_mtime = mktime(&tm); + st->st_atime = 0; + st->st_ctime = 0; + return 0; +} + +static int vfs_fat_unlink(void* ctx, const char *path) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + FRESULT res = f_unlink(path); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static int vfs_fat_link(void* ctx, const char* n1, const char* n2) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &n1, &n2); + const size_t copy_buf_size = fat_ctx->fs.csize; + FRESULT res; + FIL* pf1 = (FIL*) ff_memalloc(sizeof(FIL)); + FIL* pf2 = (FIL*) ff_memalloc(sizeof(FIL)); + void* buf = ff_memalloc(copy_buf_size); + if (buf == NULL || pf1 == NULL || pf2 == NULL) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "alloc failed, pf1=%p, pf2=%p, buf=%p", pf1, pf2, buf); + free(pf1); + free(pf2); + free(buf); + errno = ENOMEM; + return -1; + } + memset(pf1, 0, sizeof(*pf1)); + memset(pf2, 0, sizeof(*pf2)); + res = f_open(pf1, n1, FA_READ | FA_OPEN_EXISTING); + if (res != FR_OK) { + _lock_release(&fat_ctx->lock); + goto fail1; + } + res = f_open(pf2, n2, FA_WRITE | FA_CREATE_NEW); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + goto fail2; + } + size_t size_left = f_size(pf1); + while (size_left > 0) { + size_t will_copy = (size_left < copy_buf_size) ? size_left : copy_buf_size; + size_t read; + res = f_read(pf1, buf, will_copy, &read); + if (res != FR_OK) { + goto fail3; + } else if (read != will_copy) { + res = FR_DISK_ERR; + goto fail3; + } + size_t written; + res = f_write(pf2, buf, will_copy, &written); + if (res != FR_OK) { + goto fail3; + } else if (written != will_copy) { + res = FR_DISK_ERR; + goto fail3; + } + size_left -= will_copy; + } +fail3: + f_close(pf2); + free(pf2); +fail2: + f_close(pf1); + free(pf1); +fail1: + free(buf); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static int vfs_fat_rename(void* ctx, const char *src, const char *dst) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &src, &dst); + FRESULT res = f_rename(src, dst); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static DIR* vfs_fat_opendir(void* ctx, const char* name) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &name, NULL); + vfs_fat_dir_t* fat_dir = ff_memalloc(sizeof(vfs_fat_dir_t)); + if (!fat_dir) { + _lock_release(&fat_ctx->lock); + errno = ENOMEM; + return NULL; + } + memset(fat_dir, 0, sizeof(*fat_dir)); + + FRESULT res = f_opendir(&fat_dir->ffdir, name); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + free(fat_dir); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return NULL; + } + return (DIR*) fat_dir; +} + +static int vfs_fat_closedir(void* ctx, DIR* pdir) +{ + assert(pdir); + vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; + FRESULT res = f_closedir(&fat_dir->ffdir); + free(pdir); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static struct dirent* vfs_fat_readdir(void* ctx, DIR* pdir) +{ + vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; + struct dirent* out_dirent; + int err = vfs_fat_readdir_r(ctx, pdir, &fat_dir->cur_dirent, &out_dirent); + if (err != 0) { + errno = err; + return NULL; + } + return out_dirent; +} + +static int vfs_fat_readdir_r(void* ctx, DIR* pdir, + struct dirent* entry, struct dirent** out_dirent) +{ + assert(pdir); + vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; + FRESULT res = f_readdir(&fat_dir->ffdir, &fat_dir->filinfo); + if (res != FR_OK) { + *out_dirent = NULL; + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + return fresult_to_errno(res); + } + if (fat_dir->filinfo.fname[0] == 0) { + // end of directory + *out_dirent = NULL; + return 0; + } + entry->d_ino = 0; + if (fat_dir->filinfo.fattrib & AM_DIR) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + strlcpy(entry->d_name, fat_dir->filinfo.fname, + sizeof(entry->d_name)); + fat_dir->offset++; + *out_dirent = entry; + return 0; +} + +static long vfs_fat_telldir(void* ctx, DIR* pdir) +{ + assert(pdir); + vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; + return fat_dir->offset; +} + +static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset) +{ + assert(pdir); + vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; + FRESULT res; + if (offset < fat_dir->offset) { + res = f_rewinddir(&fat_dir->ffdir); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: rewinddir fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return; + } + fat_dir->offset = 0; + } + while (fat_dir->offset < offset) { + res = f_readdir(&fat_dir->ffdir, &fat_dir->filinfo); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: f_readdir fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return; + } + fat_dir->offset++; + } +} + +static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) +{ + (void) mode; + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &name, NULL); + FRESULT res = f_mkdir(name); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static int vfs_fat_rmdir(void* ctx, const char* name) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &name, NULL); + FRESULT res = f_unlink(name); + _lock_release(&fat_ctx->lock); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + return 0; +} + +static int vfs_fat_access(void* ctx, const char *path, int amode) +{ + FILINFO info; + int ret = 0; + FRESULT res; + + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + res = f_stat(path, &info); + _lock_release(&fat_ctx->lock); + + if (res == FR_OK) { + if (((amode & W_OK) == W_OK) && ((info.fattrib & AM_RDO) == AM_RDO)) { + ret = -1; + errno = EACCES; + } + // There is no flag to test readable or executable: we assume that if + // it exists then it is readable and executable + } else { + ret = -1; + errno = ENOENT; + } + + return ret; +} + +static int vfs_fat_truncate(void* ctx, const char *path, off_t length) +{ + FRESULT res; + FIL* file; + + int ret = 0; + + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + + file = (FIL*) ff_memalloc(sizeof(FIL)); + if (file == NULL) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "truncate alloc failed"); + errno = ENOMEM; + ret = -1; + goto out; + } + memset(file, 0, sizeof(*file)); + + res = f_open(file, path, FA_WRITE); + + if (res != FR_OK) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto out; + } + + res = f_size(file); + + if (res < length) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "truncate does not support extending size"); + errno = EPERM; + ret = -1; + goto close; + } + + res = f_lseek(file, length); + if (res != FR_OK) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto close; + } + + res = f_truncate(file); + _lock_release(&fat_ctx->lock); + + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + } + +close: + res = f_close(file); + + if (res != FR_OK) { + ESP_LOGE(TAG, "closing file opened for truncate failed"); + // Overwrite previous errors, since not being able to close + // an opened file is a more critical issue. + errno = fresult_to_errno(res); + ret = -1; + } + +out: + free(file); + return ret; +} + +static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *times) +{ + FILINFO filinfo_time; + + { + struct tm tm_time; + + if (times) { + localtime_r(×->modtime, &tm_time); + } else { + // use current time + struct timeval tv; + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &tm_time); + } + + if (tm_time.tm_year < 80) { + // FATFS cannot handle years before 1980 + errno = EINVAL; + return -1; + } + + fat_date_t fdate; + fat_time_t ftime; + + // this time transformation is esentially the reverse of the one in vfs_fat_stat() + fdate.mday = tm_time.tm_mday; + fdate.mon = tm_time.tm_mon + 1; // January in fdate.mon is 1, and 0 in tm_time.tm_mon + fdate.year = tm_time.tm_year - 80; // tm_time.tm_year=0 is 1900, tm_time.tm_year=0 is 1980 + ftime.sec = tm_time.tm_sec / 2, // ftime.sec counts seconds by 2 + ftime.min = tm_time.tm_min; + ftime.hour = tm_time.tm_hour; + + filinfo_time.fdate = fdate.as_int; + filinfo_time.ftime = ftime.as_int; + } + + vfs_fat_ctx_t *fat_ctx = (vfs_fat_ctx_t *) ctx; + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + FRESULT res = f_utime(path, &filinfo_time); + _lock_release(&fat_ctx->lock); + + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + + return 0; +} diff --git a/components/fatfs/vfs/vfs_fat_internal.h b/components/fatfs/vfs/vfs_fat_internal.h new file mode 100644 index 000000000..dc3bae271 --- /dev/null +++ b/components/fatfs/vfs/vfs_fat_internal.h @@ -0,0 +1,30 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_vfs_fat.h" +#include +#include + +static inline size_t esp_vfs_fat_get_allocation_unit_size( + size_t sector_size, size_t requested_size) +{ + size_t alloc_unit_size = requested_size; + const size_t max_sectors_per_cylinder = 128; + const size_t max_size = sector_size * max_sectors_per_cylinder; + alloc_unit_size = MAX(alloc_unit_size, sector_size); + alloc_unit_size = MIN(alloc_unit_size, max_size); + return alloc_unit_size; +} diff --git a/components/fatfs/vfs/vfs_fat_sdmmc.c b/components/fatfs/vfs/vfs_fat_sdmmc.c new file mode 100644 index 000000000..6b26970e2 --- /dev/null +++ b/components/fatfs/vfs/vfs_fat_sdmmc.c @@ -0,0 +1,186 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "vfs_fat_internal.h" +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +#include "sdmmc_cmd.h" +#include "diskio_impl.h" +#include "diskio_sdmmc.h" + +static const char* TAG = "vfs_fat_sdmmc"; +static sdmmc_card_t* s_card = NULL; +static uint8_t s_pdrv = 0; +static char * s_base_path = NULL; + +esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, + const sdmmc_host_t* host_config, + const void* slot_config, + const esp_vfs_fat_mount_config_t* mount_config, + sdmmc_card_t** out_card) +{ + const size_t workbuf_size = 4096; + void* workbuf = NULL; + FATFS* fs = NULL; + + if (s_card != NULL) { + return ESP_ERR_INVALID_STATE; + } + + // connect SDMMC driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + + s_base_path = strdup(base_path); + if(!s_base_path){ + ESP_LOGD(TAG, "could not copy base_path"); + return ESP_ERR_NO_MEM; + } + esp_err_t err = ESP_OK; + // not using ff_memalloc here, as allocation in internal RAM is preferred + s_card = malloc(sizeof(sdmmc_card_t)); + if (s_card == NULL) { + err = ESP_ERR_NO_MEM; + goto fail; + } + + err = (*host_config->init)(); + if (err != ESP_OK) { + ESP_LOGD(TAG, "host init returned rc=0x%x", err); + goto fail; + } + + // configure SD slot + if (host_config->flags == SDMMC_HOST_FLAG_SPI) { + err = sdspi_host_init_slot(host_config->slot, + (const sdspi_slot_config_t*) slot_config); + } else { + err = sdmmc_host_init_slot(host_config->slot, + (const sdmmc_slot_config_t*) slot_config); + } + if (err != ESP_OK) { + ESP_LOGD(TAG, "slot_config returned rc=0x%x", err); + goto fail; + } + + // probe and initialize card + err = sdmmc_card_init(host_config, s_card); + if (err != ESP_OK) { + ESP_LOGD(TAG, "sdmmc_card_init failed 0x(%x)", err); + goto fail; + } + if (out_card != NULL) { + *out_card = s_card; + } + + ff_diskio_register_sdmmc(pdrv, s_card); + s_pdrv = pdrv; + ESP_LOGD(TAG, "using pdrv=%i", pdrv); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + // connect FATFS to VFS + err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + if (err == ESP_ERR_INVALID_STATE) { + // it's okay, already registered with VFS + } else if (err != ESP_OK) { + ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", err); + goto fail; + } + + // Try to mount partition + FRESULT res = f_mount(fs, drv, 1); + if (res != FR_OK) { + err = ESP_FAIL; + ESP_LOGW(TAG, "failed to mount card (%d)", res); + if (!((res == FR_NO_FILESYSTEM || res == FR_INT_ERR) + && mount_config->format_if_mount_failed)) { + goto fail; + } + ESP_LOGW(TAG, "partitioning card"); + workbuf = ff_memalloc(workbuf_size); + if (workbuf == NULL) { + err = ESP_ERR_NO_MEM; + goto fail; + } + DWORD plist[] = {100, 0, 0, 0}; + res = f_fdisk(s_pdrv, plist, workbuf); + if (res != FR_OK) { + err = ESP_FAIL; + ESP_LOGD(TAG, "f_fdisk failed (%d)", res); + goto fail; + } + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + s_card->csd.sector_size, + mount_config->allocation_unit_size); + ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); + res = f_mkfs(drv, FM_ANY, alloc_unit_size, workbuf, workbuf_size); + if (res != FR_OK) { + err = ESP_FAIL; + ESP_LOGD(TAG, "f_mkfs failed (%d)", res); + goto fail; + } + free(workbuf); + workbuf = NULL; + ESP_LOGW(TAG, "mounting again"); + res = f_mount(fs, drv, 0); + if (res != FR_OK) { + err = ESP_FAIL; + ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res); + goto fail; + } + } + return ESP_OK; + +fail: + host_config->deinit(); + free(workbuf); + if (fs) { + f_mount(NULL, drv, 0); + } + esp_vfs_fat_unregister_path(base_path); + ff_diskio_unregister(pdrv); + free(s_card); + s_card = NULL; + free(s_base_path); + s_base_path = NULL; + return err; +} + +esp_err_t esp_vfs_fat_sdmmc_unmount(void) +{ + if (s_card == NULL) { + return ESP_ERR_INVALID_STATE; + } + // unmount + char drv[3] = {(char)('0' + s_pdrv), ':', 0}; + f_mount(0, drv, 0); + // release SD driver + esp_err_t (*host_deinit)(void) = s_card->host.deinit; + ff_diskio_unregister(s_pdrv); + free(s_card); + s_card = NULL; + (*host_deinit)(); + esp_err_t err = esp_vfs_fat_unregister_path(s_base_path); + free(s_base_path); + s_base_path = NULL; + return err; +} diff --git a/components/fatfs/vfs/vfs_fat_spiflash.c b/components/fatfs/vfs/vfs_fat_spiflash.c new file mode 100644 index 000000000..3110d2e2d --- /dev/null +++ b/components/fatfs/vfs/vfs_fat_spiflash.c @@ -0,0 +1,209 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "vfs_fat_internal.h" +#include "diskio_impl.h" + +#include "diskio_rawflash.h" + +#include "wear_levelling.h" +#include "diskio_wl.h" + +static const char *TAG = "vfs_fat_spiflash"; +esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config, + wl_handle_t* wl_handle) +{ + esp_err_t result = ESP_OK; + const size_t workbuf_size = 4096; + void *workbuf = NULL; + + esp_partition_subtype_t subtype = partition_label ? + ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_FAT; + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + subtype, partition_label); + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + result = wl_mount(data_partition, wl_handle); + if (result != ESP_OK) { + ESP_LOGE(TAG, "failed to mount wear levelling layer. result = %i", result); + return result; + } + // connect driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "using pdrv=%i", pdrv); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + result = ff_diskio_register_wl_partition(pdrv, *wl_handle); + if (result != ESP_OK) { + ESP_LOGE(TAG, "ff_diskio_register_wl_partition failed pdrv=%i, error - 0x(%x)", pdrv, result); + goto fail; + } + FATFS *fs; + result = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + if (result == ESP_ERR_INVALID_STATE) { + // it's okay, already registered with VFS + } else if (result != ESP_OK) { + ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", result); + goto fail; + } + + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + if (!((fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR) + && mount_config->format_if_mount_failed)) { + result = ESP_FAIL; + goto fail; + } + workbuf = ff_memalloc(workbuf_size); + if (workbuf == NULL) { + result = ESP_ERR_NO_MEM; + goto fail; + } + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + CONFIG_WL_SECTOR_SIZE, + mount_config->allocation_unit_size); + ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); + fresult = f_mkfs(drv, FM_ANY | FM_SFD, alloc_unit_size, workbuf, workbuf_size); + if (fresult != FR_OK) { + result = ESP_FAIL; + ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); + goto fail; + } + free(workbuf); + workbuf = NULL; + ESP_LOGI(TAG, "Mounting again"); + fresult = f_mount(fs, drv, 0); + if (fresult != FR_OK) { + result = ESP_FAIL; + ESP_LOGE(TAG, "f_mount failed after formatting (%d)", fresult); + goto fail; + } + } + return ESP_OK; + +fail: + free(workbuf); + esp_vfs_fat_unregister_path(base_path); + ff_diskio_unregister(pdrv); + return result; +} + +esp_err_t esp_vfs_fat_spiflash_unmount(const char *base_path, wl_handle_t wl_handle) +{ + BYTE pdrv = ff_diskio_get_pdrv_wl(wl_handle); + if (pdrv == 0xff) { + return ESP_ERR_INVALID_STATE; + } + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + ff_diskio_clear_pdrv_wl(wl_handle); + // release partition driver + esp_err_t err_drv = wl_unmount(wl_handle); + esp_err_t err = esp_vfs_fat_unregister_path(base_path); + if (err == ESP_OK) err = err_drv; + return err; +} + +esp_err_t esp_vfs_fat_rawflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config) +{ + esp_err_t result = ESP_OK; + + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, partition_label); + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + // connect driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "using pdrv=%i", pdrv); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + result = ff_diskio_register_raw_partition(pdrv, data_partition); + if (result != ESP_OK) { + ESP_LOGE(TAG, "ff_diskio_register_raw_partition failed pdrv=%i, error - 0x(%x)", pdrv, result); + goto fail; + } + + FATFS *fs; + result = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + if (result == ESP_ERR_INVALID_STATE) { + // it's okay, already registered with VFS + } else if (result != ESP_OK) { + ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", result); + goto fail; + } + + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + result = ESP_FAIL; + goto fail; + } + return ESP_OK; + +fail: + esp_vfs_fat_unregister_path(base_path); + ff_diskio_unregister(pdrv); + return result; +} + + +esp_err_t esp_vfs_fat_rawflash_unmount(const char *base_path, const char* partition_label) +{ + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, partition_label); + + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + BYTE pdrv = ff_diskio_get_pdrv_raw(data_partition); + if (pdrv == 0xff) { + return ESP_ERR_INVALID_STATE; + } + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + esp_err_t err = esp_vfs_fat_unregister_path(base_path); + return err; +} diff --git a/components/freemodbus/CMakeLists.txt b/components/freemodbus/CMakeLists.txt new file mode 100644 index 000000000..395fdc00c --- /dev/null +++ b/components/freemodbus/CMakeLists.txt @@ -0,0 +1,45 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +set(srcs + "common/esp_modbus_master.c" + "common/esp_modbus_slave.c" + "modbus/mb.c" + "modbus/mb_m.c" + "modbus/tcp/mbtcp.c" + "modbus/tcp/mbtcp_m.c" + "port/port.c" + "port/portevent.c" + "port/portevent_m.c" + "port/portother.c" + "port/portother_m.c" + "port/porttimer.c" + "port/porttimer_m.c" + "modbus/functions/mbfunccoils.c" + "modbus/functions/mbfunccoils_m.c" + "modbus/functions/mbfuncdiag.c" + "modbus/functions/mbfuncdisc.c" + "modbus/functions/mbfuncdisc_m.c" + "modbus/functions/mbfuncholding.c" + "modbus/functions/mbfuncholding_m.c" + "modbus/functions/mbfuncinput.c" + "modbus/functions/mbfuncinput_m.c" + "modbus/functions/mbfuncother.c" + "modbus/functions/mbutils.c" + "tcp_slave/port/port_tcp_slave.c" + "tcp_slave/modbus_controller/mbc_tcp_slave.c" + "tcp_master/modbus_controller/mbc_tcp_master.c" + "tcp_master/port/port_tcp_master.c" + "common/esp_modbus_master_tcp.c" + "common/esp_modbus_slave_tcp.c") + +set(include_dirs common/include) + +set(priv_include_dirs common port modbus modbus/ascii modbus/functions + modbus/rtu modbus/tcp modbus/include) + +list(APPEND priv_include_dirs tcp_slave/port tcp_slave/modbus_controller + tcp_master/port tcp_master/modbus_controller) + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + PRIV_INCLUDE_DIRS "${priv_include_dirs}") diff --git a/components/freemodbus/Kconfig b/components/freemodbus/Kconfig new file mode 100644 index 000000000..d2dfb37c3 --- /dev/null +++ b/components/freemodbus/Kconfig @@ -0,0 +1,163 @@ +menu "Modbus configuration" + + config FMB_COMM_MODE_TCP_EN + bool "Enable Modbus stack support for TCP communication mode" + default y + help + Enable Modbus TCP option for stack. + + config FMB_TCP_PORT_DEFAULT + int "Modbus TCP port number" + range 0 65535 + default 502 + depends on FMB_COMM_MODE_TCP_EN + help + Modbus default port number used by Modbus TCP stack + + config FMB_TCP_PORT_MAX_CONN + int "Maximum allowed connections for TCP stack" + range 1 6 + default 5 + depends on FMB_COMM_MODE_TCP_EN + help + Maximum allowed connections number for Modbus TCP stack. + This is used by Modbus master and slave port layer to establish connections. + This parameter may decrease performance of Modbus stack and can cause + increasing of processing time (increase only if absolutely necessary). + + config FMB_TCP_CONNECTION_TOUT_SEC + int "Modbus TCP connection timeout" + range 1 3600 + default 20 + depends on FMB_COMM_MODE_TCP_EN + help + Modbus TCP connection timeout in seconds. + Once expired the current connection with the client will be closed + and Modbus slave will be waiting for new connection to accept. + + config FMB_MASTER_TIMEOUT_MS_RESPOND + int "Slave respond timeout (Milliseconds)" + default 150 + range 50 3000 + help + If master sends a frame which is not broadcast, it has to wait sometime for slave response. + if slave is not respond in this time, the master will process timeout error. + + config FMB_MASTER_DELAY_MS_CONVERT + int "Slave conversion delay (Milliseconds)" + default 200 + range 50 400 + help + If master sends a broadcast frame, it has to wait conversion time to delay, + then master can send next frame. + + config FMB_QUEUE_LENGTH + int "Modbus serial task queue length" + range 0 200 + default 20 + help + Modbus serial driver queue length. It is used by event queue task. + See the serial driver API for more information. + + config FMB_PORT_TASK_STACK_SIZE + int "Modbus port task stack size" + range 2048 8192 + default 4096 + help + Modbus port task stack size for rx/tx event processing. + It may be adjusted when debugging is enabled (for example). + + config FMB_SERIAL_BUF_SIZE + int "Modbus serial task RX/TX buffer size" + range 0 2048 + default 256 + help + Modbus serial task RX and TX buffer size for UART driver initialization. + This buffer is used for modbus frame transfer. The Modbus protocol maximum + frame size is 256 bytes. Bigger size can be used for non standard implementations. + + config FMB_PORT_TASK_PRIO + int "Modbus port task priority" + range 3 10 + default 10 + help + Modbus port data processing task priority. + The priority of Modbus controller task is equal to (CONFIG_FMB_PORT_TASK_PRIO - 1). + + config FMB_CONTROLLER_SLAVE_ID_SUPPORT + bool "Modbus controller slave ID support" + default y + help + Modbus slave ID support enable. + When enabled the Modbus command is supported by stack. + + config FMB_CONTROLLER_SLAVE_ID + hex "Modbus controller slave ID" + range 0 4294967295 + default 0x00112233 + depends on FMB_CONTROLLER_SLAVE_ID_SUPPORT + help + Modbus slave ID value to identify modbus device + in the network using command. + Most significant byte of ID is used as short device ID and + other three bytes used as long ID. + + config FMB_CONTROLLER_NOTIFY_TIMEOUT + int "Modbus controller notification timeout (ms)" + range 0 200 + default 20 + help + Modbus controller notification timeout in milliseconds. + This timeout is used to send notification about accessed parameters. + + config FMB_CONTROLLER_NOTIFY_QUEUE_SIZE + int "Modbus controller notification queue size" + range 0 200 + default 20 + help + Modbus controller notification queue size. + The notification queue is used to get information about accessed parameters. + + config FMB_CONTROLLER_STACK_SIZE + int "Modbus controller stack size" + range 0 8192 + default 4096 + help + Modbus controller task stack size. The Stack size may be adjusted when + debug mode is used which requires more stack size (for example). + + config FMB_EVENT_QUEUE_TIMEOUT + int "Modbus stack event queue timeout (ms)" + range 0 500 + default 20 + help + Modbus stack event queue timeout in milliseconds. This may help to optimize + Modbus stack event processing time. + + config FMB_TIMER_GROUP + int "Modbus Timer group number" + range 0 1 + default 0 + help + Modbus Timer group number that is used for timeout measurement. + + config FMB_TIMER_INDEX + int "Modbus Timer index in the group" + range 0 1 + default 0 + help + Modbus Timer Index in the group that is used for timeout measurement. + + config FMB_TIMER_ISR_IN_IRAM + bool "Place timer interrupt handler into IRAM" + default n + select UART_ISR_IN_IRAM + help + This option places Modbus timer IRQ handler into IRAM. + This allows to avoid delays related to processing of non-IRAM-safe interrupts + during a flash write operation (NVS updating a value, or some other + flash API which has to perform an read/write operation and disable CPU cache). + This option has dependency with the UART_ISR_IN_IRAM option which places UART interrupt + handler into IRAM to prevent delays related to processing of UART events. + +endmenu diff --git a/components/freemodbus/common/esp_modbus_callbacks.h b/components/freemodbus/common/esp_modbus_callbacks.h new file mode 100644 index 000000000..d9875a626 --- /dev/null +++ b/components/freemodbus/common/esp_modbus_callbacks.h @@ -0,0 +1,29 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// Stack callback functions prototypes + +#ifndef _ESP_MODBUS_CALLBACKS_H_ +#define _ESP_MODBUS_CALLBACKS_H_ + +#include "mb.h" +#include "mb_m.h" + +typedef eMBErrorCode (*reg_input_cb)(UCHAR*, USHORT, USHORT); +typedef eMBErrorCode (*reg_holding_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode); +typedef eMBErrorCode (*reg_coils_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode); +typedef eMBErrorCode (*reg_discrete_cb)(UCHAR*, USHORT, USHORT); + +#endif /* _ESP_MODBUS_CALLBACKS_H_ */ diff --git a/components/freemodbus/common/esp_modbus_master.c b/components/freemodbus/common/esp_modbus_master.c new file mode 100644 index 000000000..eee360820 --- /dev/null +++ b/components/freemodbus/common/esp_modbus_master.c @@ -0,0 +1,244 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "esp_err.h" // for esp_err_t +#include "mbc_master.h" // for master interface define +#include "esp_modbus_master.h" // for public interface defines +#include "esp_modbus_callbacks.h" // for callback functions + +// This file implements public API for Modbus master controller. +// These functions are wrappers for interface functions of the controller +static mb_master_interface_t* master_interface_ptr = NULL; + +void mbc_master_init_iface(void* handler) +{ + master_interface_ptr = (mb_master_interface_t*) handler; +} + +/** + * Modbus controller destroy function + */ +esp_err_t mbc_master_destroy(void) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->destroy != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->destroy(); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master destroy failure, error=(0x%x).", + error); + return error; +} + +esp_err_t mbc_master_get_cid_info(uint16_t cid, const mb_parameter_descriptor_t** param_info) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->get_cid_info != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->get_cid_info(cid, param_info); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master get cid info failure, error=(0x%x).", + error); + return error; +} + +/** + * Get parameter data for corresponding characteristic + */ +esp_err_t mbc_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t* type) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->get_parameter != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->get_parameter(cid, name, value, type); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master get parameter failure, error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return error; +} + +/** + * Send custom Modbus request defined as mb_param_request_t structure + */ +esp_err_t mbc_master_send_request(mb_param_request_t* request, void* data_ptr) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->send_request != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->send_request(request, data_ptr); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master send request failure error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return ESP_OK; +} + +/** + * Set Modbus parameter description table + */ +esp_err_t mbc_master_set_descriptor(const mb_parameter_descriptor_t* descriptor, + const uint16_t num_elements) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->set_descriptor != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->set_descriptor(descriptor, num_elements); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master set descriptor failure, error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return ESP_OK; +} + +/** + * Set parameter value for characteristic selected by name and cid + */ +esp_err_t mbc_master_set_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t* type) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->set_parameter != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->set_parameter(cid, name, value, type); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master set parameter failure, error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return ESP_OK; +} + +/** + * Setup Modbus controller parameters + */ +esp_err_t mbc_master_setup(void* comm_info) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->setup != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->setup(comm_info); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master setup failure, error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return ESP_OK; +} + +/** + * Modbus controller stack start function + */ +esp_err_t mbc_master_start(void) +{ + esp_err_t error = ESP_OK; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->start != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->start(); + MB_MASTER_CHECK((error == ESP_OK), + error, + "Master start failure, error=(0x%x) (%s).", + error, esp_err_to_name(error)); + return ESP_OK; +} + +eMBErrorCode eMBMasterRegDiscreteCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete) +{ + eMBErrorCode error = MB_ENOERR; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->master_reg_cb_discrete != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->master_reg_cb_discrete(pucRegBuffer, usAddress, usNDiscrete); + return error; +} + +eMBErrorCode eMBMasterRegCoilsCB(UCHAR* pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode error = MB_ENOERR; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->master_reg_cb_coils != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->master_reg_cb_coils(pucRegBuffer, usAddress, + usNCoils, eMode); + return error; +} + +eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode error = MB_ENOERR; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->master_reg_cb_holding != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->master_reg_cb_holding(pucRegBuffer, usAddress, + usNRegs, eMode); + return error; +} + +eMBErrorCode eMBMasterRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs) +{ + eMBErrorCode error = MB_ENOERR; + MB_MASTER_CHECK((master_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + MB_MASTER_CHECK((master_interface_ptr->master_reg_cb_input != NULL), + ESP_ERR_INVALID_STATE, + "Master interface is not correctly initialized."); + error = master_interface_ptr->master_reg_cb_input(pucRegBuffer, usAddress, usNRegs); + return error; +} diff --git a/components/freemodbus/common/esp_modbus_master_tcp.c b/components/freemodbus/common/esp_modbus_master_tcp.c new file mode 100644 index 000000000..4bedfe84d --- /dev/null +++ b/components/freemodbus/common/esp_modbus_master_tcp.c @@ -0,0 +1,33 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "esp_err.h" // for esp_err_t +#include "esp_modbus_master.h" // for public interface defines +#include "mbc_tcp_master.h" // for public interface defines + +/** + * Initialization of Modbus TCP Master controller interface + */ +esp_err_t mbc_master_init_tcp(void** handler) +{ + void* port_handler = NULL; + esp_err_t error = mbc_tcp_master_create(&port_handler); + + if ((port_handler != NULL) && (error == ESP_OK)) { + mbc_master_init_iface(port_handler); + *handler = port_handler; + } + return error; +} diff --git a/components/freemodbus/common/esp_modbus_slave.c b/components/freemodbus/common/esp_modbus_slave.c new file mode 100644 index 000000000..57a54efe3 --- /dev/null +++ b/components/freemodbus/common/esp_modbus_slave.c @@ -0,0 +1,231 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "esp_err.h" // for esp_err_t +#include "sdkconfig.h" // for KConfig defines +#include "mbc_slave.h" // for slave private type definitions +#include "esp_modbus_common.h" // for common defines +#include "esp_modbus_slave.h" // for public slave defines +#include "esp_modbus_callbacks.h" // for modbus callbacks function pointers declaration + +#ifdef CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT + +#define MB_ID_BYTE0(id) ((uint8_t)(id)) +#define MB_ID_BYTE1(id) ((uint8_t)(((uint16_t)(id) >> 8) & 0xFF)) +#define MB_ID_BYTE2(id) ((uint8_t)(((uint32_t)(id) >> 16) & 0xFF)) +#define MB_ID_BYTE3(id) ((uint8_t)(((uint32_t)(id) >> 24) & 0xFF)) + +#define MB_CONTROLLER_SLAVE_ID (CONFIG_FMB_CONTROLLER_SLAVE_ID) +#define MB_SLAVE_ID_SHORT (MB_ID_BYTE3(MB_CONTROLLER_SLAVE_ID)) + +// Slave ID constant +static uint8_t mb_slave_id[] = { MB_ID_BYTE0(MB_CONTROLLER_SLAVE_ID), + MB_ID_BYTE1(MB_CONTROLLER_SLAVE_ID), + MB_ID_BYTE2(MB_CONTROLLER_SLAVE_ID) }; + +#endif + +// Common interface pointer for slave port +static mb_slave_interface_t* slave_interface_ptr = NULL; + +void mbc_slave_init_iface(void* handler) +{ + slave_interface_ptr = (mb_slave_interface_t*) handler; +} + +/** + * Modbus controller destroy function + */ +esp_err_t mbc_slave_destroy(void) +{ + esp_err_t error = ESP_OK; + // Is initialization done? + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + // Check if interface has been initialized + MB_SLAVE_CHECK((slave_interface_ptr->destroy != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + // Call the slave port destroy function + error = slave_interface_ptr->destroy(); + MB_SLAVE_CHECK((error == ESP_OK), + ESP_ERR_INVALID_STATE, + "Slave destroy failure error=(0x%x).", + error); + return error; +} + +/** + * Setup Modbus controller parameters + */ +esp_err_t mbc_slave_setup(void* comm_info) +{ + esp_err_t error = ESP_OK; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->setup != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->setup(comm_info); + MB_SLAVE_CHECK((error == ESP_OK), + ESP_ERR_INVALID_STATE, + "Slave setup failure error=(0x%x).", + error); + return error; +} + +/** + * Start Modbus controller start function + */ +esp_err_t mbc_slave_start(void) +{ + esp_err_t error = ESP_OK; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->start != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); +#ifdef CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT + // Set the slave ID if the KConfig option is selected + eMBErrorCode status = eMBSetSlaveID(MB_SLAVE_ID_SHORT, TRUE, (UCHAR*)mb_slave_id, sizeof(mb_slave_id)); + MB_SLAVE_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack set slave ID failure."); +#endif + error = slave_interface_ptr->start(); + MB_SLAVE_CHECK((error == ESP_OK), + ESP_ERR_INVALID_STATE, + "Slave start failure error=(0x%x).", + error); + return error; +} + +/** + * Blocking function to get event on parameter group change for application task + */ +mb_event_group_t mbc_slave_check_event(mb_event_group_t group) +{ + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + MB_EVENT_NO_EVENTS, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->check_event != NULL), + MB_EVENT_NO_EVENTS, + "Slave interface is not correctly initialized."); + mb_event_group_t event = slave_interface_ptr->check_event(group); + return event; +} + +/** + * Function to get notification about parameter change from application task + */ +esp_err_t mbc_slave_get_param_info(mb_param_info_t* reg_info, uint32_t timeout) +{ + esp_err_t error = ESP_OK; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->get_param_info != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->get_param_info(reg_info, timeout); + MB_SLAVE_CHECK((error == ESP_OK), + ESP_ERR_INVALID_STATE, + "Slave get parameter info failure error=(0x%x).", + error); + return error; +} + +/** + * Function to set area descriptors for modbus parameters + */ +esp_err_t mbc_slave_set_descriptor(mb_register_area_descriptor_t descr_data) +{ + esp_err_t error = ESP_OK; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->set_descriptor != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->set_descriptor(descr_data); + MB_SLAVE_CHECK((error == ESP_OK), + ESP_ERR_INVALID_STATE, + "Slave set descriptor failure error=(0x%x).", + (uint16_t)error); + return error; +} + +/** + * Below are stack callback functions to read/write registers + */ +eMBErrorCode eMBRegDiscreteCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete) +{ + eMBErrorCode error = MB_ENOERR; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_discrete != NULL), + error, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->slave_reg_cb_discrete(pucRegBuffer, usAddress, usNDiscrete); + + return error; +} + +eMBErrorCode eMBRegCoilsCB(UCHAR* pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode error = MB_ENOERR; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_coils != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->slave_reg_cb_coils(pucRegBuffer, usAddress, + usNCoils, eMode); + return error; +} + +eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode error = MB_ENOERR; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_holding != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->slave_reg_cb_holding(pucRegBuffer, usAddress, + usNRegs, eMode); + return error; +} + +eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs) +{ + eMBErrorCode error = MB_ENOERR; + MB_SLAVE_CHECK((slave_interface_ptr != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_input != NULL), + ESP_ERR_INVALID_STATE, + "Slave interface is not correctly initialized."); + error = slave_interface_ptr->slave_reg_cb_input(pucRegBuffer, usAddress, usNRegs); + return error; +} diff --git a/components/freemodbus/common/esp_modbus_slave_tcp.c b/components/freemodbus/common/esp_modbus_slave_tcp.c new file mode 100644 index 000000000..238469045 --- /dev/null +++ b/components/freemodbus/common/esp_modbus_slave_tcp.c @@ -0,0 +1,33 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "esp_err.h" // for esp_err_t +#include "esp_modbus_slave.h" // for public slave defines +#include "mbc_tcp_slave.h" // for public interface defines + +/** + * Initialization of Modbus TCP Slave controller + */ +esp_err_t mbc_slave_init_tcp(void** handler) +{ + void* port_handler = NULL; + esp_err_t error = mbc_tcp_slave_create(&port_handler); + + if ((port_handler != NULL) && (error == ESP_OK)) { + mbc_slave_init_iface(port_handler); + *handler = port_handler; + } + return error; +} diff --git a/components/freemodbus/common/include/esp_modbus_common.h b/components/freemodbus/common/include/esp_modbus_common.h new file mode 100644 index 000000000..058f88dc9 --- /dev/null +++ b/components/freemodbus/common/include/esp_modbus_common.h @@ -0,0 +1,156 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MB_IFACE_COMMON_H +#define _MB_IFACE_COMMON_H +#include "freertos/FreeRTOS.h" +#include "driver/uart.h" // for UART types + +#ifdef __cplusplus +extern "C" { +#endif + +#define MB_CONTROLLER_STACK_SIZE (CONFIG_FMB_CONTROLLER_STACK_SIZE) // Stack size for Modbus controller +#define MB_CONTROLLER_PRIORITY (CONFIG_FMB_PORT_TASK_PRIO - 1) // priority of MB controller task + +// Default port defines +#define MB_DEVICE_ADDRESS (1) // Default slave device address in Modbus +#define MB_DEVICE_SPEED (115200) // Default Modbus speed for now hard defined +#define MB_UART_PORT (UART_NUM_MAX - 1) // Default UART port number +#define MB_PAR_INFO_TOUT (10) // Timeout for get parameter info +#define MB_PARITY_NONE (UART_PARITY_DISABLE) + +// The Macros below handle the endianness while transfer N byte data into buffer +#define _XFER_4_RD(dst, src) { \ + *(uint8_t *)(dst)++ = *(uint8_t*)(src + 1); \ + *(uint8_t *)(dst)++ = *(uint8_t*)(src + 0); \ + *(uint8_t *)(dst)++ = *(uint8_t*)(src + 3); \ + *(uint8_t *)(dst)++ = *(uint8_t*)(src + 2); \ + (src) += 4; \ +} + +#define _XFER_2_RD(dst, src) { \ + *(uint8_t *)(dst)++ = *(uint8_t *)(src + 1); \ + *(uint8_t *)(dst)++ = *(uint8_t *)(src + 0); \ + (src) += 2; \ +} + +#define _XFER_4_WR(dst, src) { \ + *(uint8_t *)(dst + 1) = *(uint8_t *)(src)++; \ + *(uint8_t *)(dst + 0) = *(uint8_t *)(src)++; \ + *(uint8_t *)(dst + 3) = *(uint8_t *)(src)++; \ + *(uint8_t *)(dst + 2) = *(uint8_t *)(src)++ ; \ +} + +#define _XFER_2_WR(dst, src) { \ + *(uint8_t *)(dst + 1) = *(uint8_t *)(src)++; \ + *(uint8_t *)(dst + 0) = *(uint8_t *)(src)++; \ +} + +/** + * @brief Types of actual Modbus implementation + */ +typedef enum +{ + MB_PORT_SERIAL_MASTER = 0x00, /*!< Modbus port type serial master. */ + MB_PORT_SERIAL_SLAVE, /*!< Modbus port type serial slave. */ + MB_PORT_TCP_MASTER, /*!< Modbus port type TCP master. */ + MB_PORT_TCP_SLAVE, /*!< Modbus port type TCP slave. */ + MB_PORT_COUNT, /*!< Modbus port count. */ + MB_PORT_INACTIVE = 0xFF +} mb_port_type_t; + +/** + * @brief Event group for parameters notification + */ +typedef enum +{ + MB_EVENT_NO_EVENTS = 0x00, + MB_EVENT_HOLDING_REG_WR = BIT0, /*!< Modbus Event Write Holding registers. */ + MB_EVENT_HOLDING_REG_RD = BIT1, /*!< Modbus Event Read Holding registers. */ + MB_EVENT_INPUT_REG_RD = BIT3, /*!< Modbus Event Read Input registers. */ + MB_EVENT_COILS_WR = BIT4, /*!< Modbus Event Write Coils. */ + MB_EVENT_COILS_RD = BIT5, /*!< Modbus Event Read Coils. */ + MB_EVENT_DISCRETE_RD = BIT6, /*!< Modbus Event Read Discrete bits. */ + MB_EVENT_STACK_STARTED = BIT7 /*!< Modbus Event Stack started */ +} mb_event_group_t; + +/** + * @brief Type of Modbus parameter + */ +typedef enum { + MB_PARAM_HOLDING = 0x00, /*!< Modbus Holding register. */ + MB_PARAM_INPUT, /*!< Modbus Input register. */ + MB_PARAM_COIL, /*!< Modbus Coils. */ + MB_PARAM_DISCRETE, /*!< Modbus Discrete bits. */ + MB_PARAM_COUNT, + MB_PARAM_UNKNOWN = 0xFF +} mb_param_type_t; + +/*! + * \brief Modbus serial transmission modes (RTU/ASCII). + */ +typedef enum { + MB_MODE_RTU, /*!< RTU transmission mode. */ + MB_MODE_ASCII, /*!< ASCII transmission mode. */ + MB_MODE_TCP, /*!< TCP communication mode. */ + MB_MODE_UDP /*!< UDP communication mode. */ +} mb_mode_type_t; + +/*! + * \brief Modbus TCP type of address. + */ +typedef enum { + MB_IPV4 = 0, /*!< TCP IPV4 addressing */ + MB_IPV6 = 1 /*!< TCP IPV6 addressing */ +} mb_tcp_addr_type_t; + +/** + * @brief Device communication structure to setup Modbus controller + */ +typedef union { + // Serial communication structure + struct { + mb_mode_type_t mode; /*!< Modbus communication mode */ + uint8_t slave_addr; /*!< Modbus slave address field (dummy for master) */ + uart_port_t port; /*!< Modbus communication port (UART) number */ + uint32_t baudrate; /*!< Modbus baudrate */ + uart_parity_t parity; /*!< Modbus UART parity settings */ + uint16_t dummy_port; /*!< Dummy field, unused */ + }; + // TCP/UDP communication structure + struct { + mb_mode_type_t ip_mode; /*!< Modbus communication mode */ + uint16_t ip_port; /*!< Modbus port */ + mb_tcp_addr_type_t ip_addr_type; /*!< Modbus address type */ + void* ip_addr; /*!< Modbus address table for connection */ + void* ip_netif_ptr; /*!< Modbus network interface */ + }; +} mb_communication_info_t; + +/** + * common interface method types + */ +typedef esp_err_t (*iface_init)(void**); /*!< Interface method init */ +typedef esp_err_t (*iface_destroy)(void); /*!< Interface method destroy */ +typedef esp_err_t (*iface_setup)(void*); /*!< Interface method setup */ +typedef esp_err_t (*iface_start)(void); /*!< Interface method start */ + +#ifdef __cplusplus +} +#endif + +#endif // _MB_IFACE_COMMON_H + diff --git a/components/freemodbus/common/include/esp_modbus_master.h b/components/freemodbus/common/include/esp_modbus_master.h new file mode 100644 index 000000000..74adabafe --- /dev/null +++ b/components/freemodbus/common/include/esp_modbus_master.h @@ -0,0 +1,269 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ESP_MB_MASTER_INTERFACE_H +#define _ESP_MB_MASTER_INTERFACE_H + +#include // for standard int types definition +#include // for NULL and std defines +#include "esp_modbus_common.h" // for common types + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief Modbus descriptor table parameter type defines. + */ +typedef enum { + PARAM_TYPE_U8 = 0x00, /*!< Unsigned 8 */ + PARAM_TYPE_U16 = 0x01, /*!< Unsigned 16 */ + PARAM_TYPE_U32 = 0x02, /*!< Unsigned 32 */ + PARAM_TYPE_FLOAT = 0x03, /*!< Float type */ + PARAM_TYPE_ASCII = 0x04 /*!< ASCII type */ +} mb_descr_type_t; + +/*! + * \brief Modbus descriptor table parameter size in bytes. + */ +typedef enum { + PARAM_SIZE_U8 = 0x01, /*!< Unsigned 8 */ + PARAM_SIZE_U16 = 0x02, /*!< Unsigned 16 */ + PARAM_SIZE_U32 = 0x04, /*!< Unsigned 32 */ + PARAM_SIZE_FLOAT = 0x04, /*!< Float size */ + PARAM_SIZE_ASCII = 0x08, /*!< ASCII size */ + PARAM_SIZE_ASCII24 = 0x18, /*!< ASCII24 size */ + PARAM_MAX_SIZE +} mb_descr_size_t; + +/*! + * \brief Modbus parameter options for description table + */ +typedef union { + struct { + int opt1; /*!< Parameter option1 */ + int opt2; /*!< Parameter option2 */ + int opt3; /*!< Parameter option3 */ + }; + struct { + int min; /*!< Parameter minimum value */ + int max; /*!< Parameter maximum value */ + int step; /*!< Step of parameter change tracking */ + }; +} mb_parameter_opt_t; + +/** + * @brief Permissions for the characteristics + */ +typedef enum { + PAR_PERMS_READ = 1 << BIT0, /**< the characteristic of the device are readable */ + PAR_PERMS_WRITE = 1 << BIT1, /**< the characteristic of the device are writable*/ + PAR_PERMS_TRIGGER = 1 << BIT2, /**< the characteristic of the device are triggerable */ + PAR_PERMS_READ_WRITE = PAR_PERMS_READ | PAR_PERMS_WRITE, /**< the characteristic of the device are readable & writable */ + PAR_PERMS_READ_TRIGGER = PAR_PERMS_READ | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & triggerable */ + PAR_PERMS_WRITE_TRIGGER = PAR_PERMS_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are writable & triggerable */ + PAR_PERMS_READ_WRITE_TRIGGER = PAR_PERMS_READ_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & writable & triggerable */ +} mb_param_perms_t; + +/** + * @brief Characteristics descriptor type is used to describe characteristic and + * link it with Modbus parameters that reflect its data. + */ +typedef struct { + uint16_t cid; /*!< Characteristic cid */ + const char* param_key; /*!< The key (name) of the parameter */ + const char* param_units; /*!< The physical units of the parameter */ + uint8_t mb_slave_addr; /*!< Slave address of device in the Modbus segment */ + mb_param_type_t mb_param_type; /*!< Type of modbus parameter */ + uint16_t mb_reg_start; /*!< This is the Modbus register address. This is the 0 based value. */ + uint16_t mb_size; /*!< Size of mb parameter in registers */ + uint16_t param_offset; /*!< Parameter name (OFFSET in the parameter structure) */ + mb_descr_type_t param_type; /*!< Float, U8, U16, U32, ASCII, etc. */ + mb_descr_size_t param_size; /*!< Number of bytes in the parameter. */ + mb_parameter_opt_t param_opts; /*!< Parameter options used to check limits and etc. */ + mb_param_perms_t access; /*!< Access permissions based on mode */ +} mb_parameter_descriptor_t; + +/** + * @brief Modbus register request type structure + */ +typedef struct { + uint8_t slave_addr; /*!< Modbus slave address */ + uint8_t command; /*!< Modbus command to send */ + uint16_t reg_start; /*!< Modbus start register */ + uint16_t reg_size; /*!< Modbus number of registers */ +} mb_param_request_t; + +/** + * @brief Initialize Modbus controller and stack for TCP port + * + * @param[out] handler handler(pointer) to master data structure + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + * - ESP_ERR_NOT_SUPPORTED Port type not supported + * - ESP_ERR_INVALID_STATE Initialization failure + */ +esp_err_t mbc_master_init_tcp(void** handler); + +/** + * @brief Initialize Modbus Master controller and stack for Serial port + * + * @param[out] handler handler(pointer) to master data structure + * @param[in] port_type type of stack + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + * - ESP_ERR_NOT_SUPPORTED Port type not supported + * - ESP_ERR_INVALID_STATE Initialization failure + */ +esp_err_t mbc_master_init(mb_port_type_t port_type, void** handler); + +/** + * @brief Initialize Modbus Master controller interface handle + * + * @param[in] handler - pointer to master data structure + * @return None + */ +void mbc_master_init_iface(void* handler); + +/** + * @brief Destroy Modbus controller and stack + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Parameter error + */ +esp_err_t mbc_master_destroy(void); + +/** + * @brief Start Modbus communication stack + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Modbus stack start error + */ +esp_err_t mbc_master_start(void); + +/** + * @brief Set Modbus communication parameters for the controller + * + * @param comm_info Communication parameters structure. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Incorrect parameter data + */ +esp_err_t mbc_master_setup(void* comm_info); + +/***************************** Specific interface functions ******************************************** + * Interface functions below provide basic methods to read/write access to slave devices in Modbus + * segment as well as API to read specific supported characteristics linked to Modbus parameters + * of devices in Modbus network. +*******************************************************************************************************/ + +/** + * @brief Assign parameter description table for Modbus controller interface. + * + * @param[in] descriptor pointer to parameter description table + * @param num_elements number of elements in the table + * + * @return + * - esp_err_t ESP_OK - set descriptor successfully + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument in function call + */ +esp_err_t mbc_master_set_descriptor(const mb_parameter_descriptor_t* descriptor, const uint16_t num_elements); + +/** + * @brief Send data request as defined in parameter request, waits response + * from slave and returns status of command execution. This function provides standard way + * for read/write access to Modbus devices in the network. + * + * @param[in] request pointer to request structure of type mb_param_request_t + * @param[in] data_ptr pointer to data buffer to send or received data (dependent of command field in request) + * + * @return + * - esp_err_t ESP_OK - request was successful + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave + * - esp_err_t ESP_ERR_TIMEOUT - operation timeout or no response from slave + * - esp_err_t ESP_ERR_NOT_SUPPORTED - the request command is not supported by slave + * - esp_err_t ESP_FAIL - slave returned an exception or other failure + */ +esp_err_t mbc_master_send_request(mb_param_request_t* request, void* data_ptr); + +/** + * @brief Get information about supported characteristic defined as cid. Uses parameter description table to get + * this information. The function will check if characteristic defined as a cid parameter is supported + * and returns its description in param_info. Returns ESP_ERR_NOT_FOUND if characteristic is not supported. + * + * @param[in] cid characteristic id + * @param param_info pointer to pointer of characteristic data. + * + * @return + * - esp_err_t ESP_OK - request was successful and buffer contains the supported characteristic name + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_NOT_FOUND - the characteristic (cid) not found + * - esp_err_t ESP_FAIL - unknown error during lookup table processing +*/ +esp_err_t mbc_master_get_cid_info(uint16_t cid, const mb_parameter_descriptor_t** param_info); + +/** + * @brief Read parameter from modbus slave device whose name is defined by name and has cid. + * The additional data for request is taken from parameter description (lookup) table. + * + * @param[in] cid id of the characteristic for parameter + * @param[in] name pointer into string name (key) of parameter (null terminated) + * @param[out] value pointer to data buffer of parameter + * @param[out] type parameter type associated with the name returned from parameter description table. + * + * @return + * - esp_err_t ESP_OK - request was successful and value buffer contains + * representation of actual parameter data from slave + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave + * - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure + * - esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave + * - esp_err_t ESP_ERR_NOT_SUPPORTED - the request command is not supported by slave + * - esp_err_t ESP_ERR_NOT_FOUND - the parameter is not found in the parameter description table + * - esp_err_t ESP_FAIL - slave returned an exception or other failure +*/ +esp_err_t mbc_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t *type); + +/** + * @brief Set characteristic's value defined as a name and cid parameter. + * The additional data for cid parameter request is taken from master parameter lookup table. + * + * @param[in] cid id of the characteristic for parameter + * @param[in] name pointer into string name (key) of parameter (null terminated) + * @param[out] value pointer to data buffer of parameter (actual representation of json value field in binary form) + * @param[out] type pointer to parameter type associated with the name returned from parameter lookup table. + * + * @return + * - esp_err_t ESP_OK - request was successful and value was saved in the slave device registers + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave during processing of parameter + * - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure + * - esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave + * - esp_err_t ESP_ERR_NOT_SUPPORTED - the request command is not supported by slave + * - esp_err_t ESP_FAIL - slave returned an exception or other failure +*/ +esp_err_t mbc_master_set_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t *type); + +#ifdef __cplusplus +} +#endif + +#endif // _ESP_MB_MASTER_INTERFACE_H diff --git a/components/freemodbus/common/include/esp_modbus_slave.h b/components/freemodbus/common/include/esp_modbus_slave.h new file mode 100644 index 000000000..50d306d54 --- /dev/null +++ b/components/freemodbus/common/include/esp_modbus_slave.h @@ -0,0 +1,151 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ESP_MB_SLAVE_INTERFACE_H +#define _ESP_MB_SLAVE_INTERFACE_H + +// Public interface header for slave +#include // for standard int types definition +#include // for NULL and std defines +#include "freertos/FreeRTOS.h" // for task creation and queues access +#include "freertos/event_groups.h" // for event groups +#include "esp_modbus_common.h" // for common types + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Parameter access event information type + */ +typedef struct { + uint32_t time_stamp; /*!< Timestamp of Modbus Event (uS)*/ + uint16_t mb_offset; /*!< Modbus register offset */ + mb_event_group_t type; /*!< Modbus event type */ + uint8_t* address; /*!< Modbus data storage address */ + size_t size; /*!< Modbus event register size (number of registers)*/ +} mb_param_info_t; + +/** + * @brief Parameter storage area descriptor + */ +typedef struct { + uint16_t start_offset; /*!< Modbus start address for area descriptor */ + mb_param_type_t type; /*!< Type of storage area descriptor */ + void* address; /*!< Instance address for storage area descriptor */ + size_t size; /*!< Instance size for area descriptor (bytes) */ +} mb_register_area_descriptor_t; + +/** + * @brief Initialize Modbus Slave controller and stack for TCP port + * + * @param[out] handler handler(pointer) to master data structure + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + * - ESP_ERR_NOT_SUPPORTED Port type not supported + * - ESP_ERR_INVALID_STATE Initialization failure + */ +esp_err_t mbc_slave_init_tcp(void** handler); + +/** + * @brief Initialize Modbus Slave controller and stack for Serial port + * + * @param[out] handler handler(pointer) to master data structure + * @param[in] port_type the type of port + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + * - ESP_ERR_NOT_SUPPORTED Port type not supported + * - ESP_ERR_INVALID_STATE Initialization failure + */ +esp_err_t mbc_slave_init(mb_port_type_t port_type, void** handler); + +/** + * @brief Initialize Modbus Slave controller interface handle + * + * @param[in] handler - pointer to slave interface data structure + * @return None + */ +void mbc_slave_init_iface(void* handler); + +/** + * @brief Destroy Modbus controller and stack + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Parameter error + */ +esp_err_t mbc_slave_destroy(void); + +/** + * @brief Start Modbus communication stack + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Modbus stack start error + */ +esp_err_t mbc_slave_start(void); + +/** + * @brief Set Modbus communication parameters for the controller + * + * @param comm_info Communication parameters structure. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Incorrect parameter data + */ +esp_err_t mbc_slave_setup(void* comm_info); + +/** + * @brief Wait for specific event on parameter change. + * + * @param group Group event bit mask to wait for change + * + * @return + * - mb_event_group_t event bits triggered + */ +mb_event_group_t mbc_slave_check_event(mb_event_group_t group); + +/** + * @brief Get parameter information + * + * @param[out] reg_info parameter info structure + * @param timeout Timeout in milliseconds to read information from + * parameter queue + * @return + * - ESP_OK Success + * - ESP_ERR_TIMEOUT Can not get data from parameter queue + * or queue overflow + */ +esp_err_t mbc_slave_get_param_info(mb_param_info_t* reg_info, uint32_t timeout); + +/** + * @brief Set Modbus area descriptor + * + * @param descr_data Modbus registers area descriptor structure + * + * @return + * - ESP_OK: The appropriate descriptor is set + * - ESP_ERR_INVALID_ARG: The argument is incorrect + */ +esp_err_t mbc_slave_set_descriptor(mb_register_area_descriptor_t descr_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/freemodbus/common/include/mbcontroller.h b/components/freemodbus/common/include/mbcontroller.h new file mode 100644 index 000000000..08b3c183c --- /dev/null +++ b/components/freemodbus/common/include/mbcontroller.h @@ -0,0 +1,32 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +// mbcontroller.h +// mbcontroller - common Modbus controller header file + +#ifndef _MODBUS_CONTROLLER_COMMON +#define _MODBUS_CONTROLLER_COMMON + +#include // for standard int types definition +#include // for NULL and std defines +#include "string.h" // for strerror() +#include "errno.h" // for errno +#include "esp_err.h" // for error handling +#include "driver/uart.h" // for uart port number defines +#include "sdkconfig.h" // for KConfig options + +#include "esp_modbus_master.h" +#include "esp_modbus_slave.h" + +#endif diff --git a/components/freemodbus/common/mbc_master.h b/components/freemodbus/common/mbc_master.h new file mode 100644 index 000000000..67e5f556c --- /dev/null +++ b/components/freemodbus/common/mbc_master.h @@ -0,0 +1,106 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _MB_CONTROLLER_MASTER_H +#define _MB_CONTROLLER_MASTER_H + +#include "freertos/FreeRTOS.h" // for task creation and queue access +#include "freertos/task.h" // for task api access +#include "freertos/event_groups.h" // for event groups +#include "driver/uart.h" // for UART types +#include "errno.h" // for errno +#include "esp_log.h" // for log write +#include "string.h" // for strerror() +#include "esp_modbus_common.h" // for common types +#include "esp_modbus_master.h" // for public master types +#include "esp_modbus_callbacks.h" + +/* ----------------------- Defines ------------------------------------------*/ + +#define MB_MASTER_TAG "MB_CONTROLLER_MASTER" + +#define MB_MASTER_CHECK(a, ret_val, str, ...) \ + if (!(a)) { \ + ESP_LOGE(MB_MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return (ret_val); \ + } + +#define MB_MASTER_ASSERT(con) do { \ + if (!(con)) { ESP_LOGE(MB_MASTER_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ + } while (0) + +/** + * @brief Request mode for parameter to use in data dictionary + */ +typedef enum { + MB_PARAM_READ, /*!< Read parameter values. */ + MB_PARAM_WRITE /*!< Write parameter values. */ +} mb_param_mode_t; + +/** + * @brief Device communication parameters for master + */ +typedef struct { + mb_mode_type_t mode; /*!< Modbus communication mode */ + uint8_t dummy; /*!< Dummy field */ + uart_port_t port; /*!< Modbus communication port (UART) number */ + uint32_t baudrate; /*!< Modbus baudrate */ + uart_parity_t parity; /*!< Modbus UART parity settings */ +} mb_master_comm_info_t; + +/** + * @brief Modbus controller handler structure + */ +typedef struct { + mb_port_type_t port_type; /*!< Modbus port type */ + mb_communication_info_t mbm_comm; /*!< Modbus communication info */ + uint8_t* mbm_reg_buffer_ptr; /*!< Modbus data buffer pointer */ + uint16_t mbm_reg_buffer_size; /*!< Modbus data buffer size */ + TaskHandle_t mbm_task_handle; /*!< Modbus task handle */ + EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */ + const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */ + size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/ +} mb_master_options_t; + +typedef esp_err_t (*iface_get_cid_info)(uint16_t, const mb_parameter_descriptor_t**); /*!< Interface get_cid_info method */ +typedef esp_err_t (*iface_get_parameter)(uint16_t, char*, uint8_t*, uint8_t*); /*!< Interface get_parameter method */ +typedef esp_err_t (*iface_send_request)(mb_param_request_t*, void*); /*!< Interface send_request method */ +typedef esp_err_t (*iface_set_descriptor)(const mb_parameter_descriptor_t*, const uint16_t); /*!< Interface set_descriptor method */ +typedef esp_err_t (*iface_set_parameter)(uint16_t, char*, uint8_t*, uint8_t*); /*!< Interface set_parameter method */ + +/** + * @brief Modbus controller interface structure + */ +typedef struct { + // Master object interface options + mb_master_options_t opts; + + // Public interface methods + iface_init init; /*!< Interface method init */ + iface_destroy destroy; /*!< Interface method destroy */ + iface_setup setup; /*!< Interface method setup */ + iface_start start; /*!< Interface method start */ + iface_get_cid_info get_cid_info; /*!< Interface get_cid_info method */ + iface_get_parameter get_parameter; /*!< Interface get_parameter method */ + iface_send_request send_request; /*!< Interface send_request method */ + iface_set_descriptor set_descriptor; /*!< Interface set_descriptor method */ + iface_set_parameter set_parameter; /*!< Interface set_parameter method */ + // Modbus register calback function pointers + reg_discrete_cb master_reg_cb_discrete; /*!< Stack callback discrete rw method */ + reg_input_cb master_reg_cb_input; /*!< Stack callback input rw method */ + reg_holding_cb master_reg_cb_holding; /*!< Stack callback holding rw method */ + reg_coils_cb master_reg_cb_coils; /*!< Stack callback coils rw method */ +} mb_master_interface_t; + +#endif //_MB_CONTROLLER_MASTER_H diff --git a/components/freemodbus/common/mbc_slave.h b/components/freemodbus/common/mbc_slave.h new file mode 100644 index 000000000..a3d42fd17 --- /dev/null +++ b/components/freemodbus/common/mbc_slave.h @@ -0,0 +1,94 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _MB_CONTROLLER_SLAVE_H +#define _MB_CONTROLLER_SLAVE_H +#include "freertos/FreeRTOS.h" +#include "driver/uart.h" // for uart defines +#include "errno.h" // for errno +#include "esp_log.h" // for log write +#include "string.h" // for strerror() +#include "esp_modbus_slave.h" // for public type defines +#include "esp_modbus_callbacks.h" // for callback functions + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_INST_MIN_SIZE (2) // The minimal size of Modbus registers area in bytes +#define MB_INST_MAX_SIZE (65535 * 2) // The maximum size of Modbus area in bytes + +#define MB_CONTROLLER_NOTIFY_QUEUE_SIZE (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue +#define MB_CONTROLLER_NOTIFY_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout + +#define MB_SLAVE_TAG "MB_CONTROLLER_SLAVE" + +#define MB_SLAVE_CHECK(a, ret_val, str, ...) \ + if (!(a)) { \ + ESP_LOGE(MB_SLAVE_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return (ret_val); \ + } + +#define MB_SLAVE_ASSERT(con) do { \ + if (!(con)) { ESP_LOGE(MB_SLAVE_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ + } while (0) + +/** + * @brief Device communication parameters for master + */ +typedef struct { + mb_mode_type_t mode; /*!< Modbus communication mode */ + uint8_t slave_addr; /*!< Slave address field */ + uart_port_t port; /*!< Modbus communication port (UART) number */ + uint32_t baudrate; /*!< Modbus baudrate */ + uart_parity_t parity; /*!< Modbus UART parity settings */ +} mb_slave_comm_info_t; + +/** + * @brief Modbus controller handler structure + */ +typedef struct { + mb_port_type_t port_type; /*!< port type */ + mb_communication_info_t mbs_comm; /*!< communication info */ + TaskHandle_t mbs_task_handle; /*!< task handle */ + EventGroupHandle_t mbs_event_group; /*!< controller event group */ + QueueHandle_t mbs_notification_queue_handle; /*!< controller notification queue */ + mb_register_area_descriptor_t mbs_area_descriptors[MB_PARAM_COUNT]; /*!< register area descriptors */ +} mb_slave_options_t; + +typedef mb_event_group_t (*iface_check_event)(mb_event_group_t); /*!< Interface method check_event */ +typedef esp_err_t (*iface_get_param_info)(mb_param_info_t*, uint32_t); /*!< Interface method get_param_info */ +typedef esp_err_t (*iface_set_descriptor)(mb_register_area_descriptor_t); /*!< Interface method set_descriptor */ + +/** + * @brief Request mode for parameter to use in data dictionary + */ +typedef struct +{ + mb_slave_options_t opts; /*!< Modbus slave options */ + + // Functional pointers to internal static functions of the implementation (public interface methods) + iface_init init; /*!< Interface method init */ + iface_destroy destroy; /*!< Interface method destroy */ + iface_setup setup; /*!< Interface method setup */ + iface_start start; /*!< Interface method start */ + iface_check_event check_event; /*!< Interface method check_event */ + iface_get_param_info get_param_info; /*!< Interface method get_param_info */ + iface_set_descriptor set_descriptor; /*!< Interface method set_descriptor */ + + // Modbus register calback function pointers + reg_discrete_cb slave_reg_cb_discrete; /*!< Stack callback discrete rw method */ + reg_input_cb slave_reg_cb_input; /*!< Stack callback input rw method */ + reg_holding_cb slave_reg_cb_holding; /*!< Stack callback holding rw method */ + reg_coils_cb slave_reg_cb_coils; /*!< Stack callback coils rw method */ +} mb_slave_interface_t; + +#endif diff --git a/components/freemodbus/component.mk b/components/freemodbus/component.mk new file mode 100644 index 000000000..e19a2428d --- /dev/null +++ b/components/freemodbus/component.mk @@ -0,0 +1,14 @@ +COMPONENT_ADD_INCLUDEDIRS := common/include +COMPONENT_PRIV_INCLUDEDIRS := common port modbus modbus/ascii modbus/functions +COMPONENT_PRIV_INCLUDEDIRS += modbus/rtu modbus/tcp modbus/include +COMPONENT_PRIV_INCLUDEDIRS += serial_slave/port serial_slave/modbus_controller +COMPONENT_PRIV_INCLUDEDIRS += serial_master/port serial_master/modbus_controller +COMPONENT_PRIV_INCLUDEDIRS += tcp_slave/port tcp_slave/modbus_controller +COMPONENT_PRIV_INCLUDEDIRS += tcp_master/port tcp_master/modbus_controller +COMPONENT_SRCDIRS := common +COMPONENT_SRCDIRS += modbus modbus/ascii modbus/functions modbus/rtu modbus/tcp +COMPONENT_SRCDIRS += serial_slave/port serial_slave/modbus_controller +COMPONENT_SRCDIRS += serial_master/port serial_master/modbus_controller +COMPONENT_SRCDIRS += tcp_slave/port tcp_slave/modbus_controller +COMPONENT_SRCDIRS += tcp_master/port tcp_master/modbus_controller +COMPONENT_SRCDIRS += port diff --git a/components/freemodbus/modbus/ascii/mbascii.c b/components/freemodbus/modbus/ascii/mbascii.c new file mode 100644 index 000000000..bbe1994b2 --- /dev/null +++ b/components/freemodbus/modbus/ascii/mbascii.c @@ -0,0 +1,473 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbascii.c,v 1.17 2010/06/06 13:47:07 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbconfig.h" +#include "mbascii.h" +#include "mbframe.h" + +#include "mbcrc.h" +#include "mbport.h" + +#if MB_SLAVE_ASCII_ENABLED > 0 + +/* ----------------------- Type definitions ---------------------------------*/ +typedef enum +{ + STATE_RX_IDLE, /*!< Receiver is in idle state. */ + STATE_RX_RCV, /*!< Frame is beeing received. */ + STATE_RX_WAIT_EOF /*!< Wait for End of Frame. */ +} eMBRcvState; + +typedef enum +{ + STATE_TX_IDLE, /*!< Transmitter is in idle state. */ + STATE_TX_START, /*!< Starting transmission (':' sent). */ + STATE_TX_DATA, /*!< Sending of data (Address, Data, LRC). */ + STATE_TX_END, /*!< End of transmission. */ + STATE_TX_NOTIFY /*!< Notify sender that the frame has been sent. */ +} eMBSndState; + +typedef enum +{ + BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */ + BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */ +} eMBBytePos; + +/* ----------------------- Shared variables ---------------------------------*/ +/* We reuse the Modbus RTU buffer because only one driver is active */ +extern volatile UCHAR ucMbSlaveBuf[]; + +/* ----------------------- Static functions ---------------------------------*/ +static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter ); + +static UCHAR prvucMBBIN2CHAR( UCHAR ucByte ); + +static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen ); + +/* ----------------------- Static variables ---------------------------------*/ +static volatile eMBSndState eSndState; +static volatile eMBRcvState eRcvState; + +static volatile UCHAR *ucASCIIBuf = ucMbSlaveBuf; + +static volatile USHORT usRcvBufferPos; +static volatile eMBBytePos eBytePos; + +static volatile UCHAR *pucSndBufferCur; +static volatile USHORT usSndBufferCount; + +static volatile UCHAR ucLRC; +static volatile UCHAR ucMBLFCharacter; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + ( void )ucSlaveAddress; + + ENTER_CRITICAL_SECTION( ); + ucMBLFCharacter = MB_ASCII_DEFAULT_LF; + + if( xMBPortSerialInit( ucPort, ulBaudRate, MB_ASCII_BITS_PER_SYMB, eParity ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + else if( xMBPortTimersInit( MB_ASCII_TIMEOUT_MS * 20UL ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + + EXIT_CRITICAL_SECTION( ); + + return eStatus; +} + +void +eMBASCIIStart( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBPortSerialEnable( TRUE, FALSE ); + eRcvState = STATE_RX_IDLE; + EXIT_CRITICAL_SECTION( ); + + /* No special startup required for ASCII. */ + ( void )xMBPortEventPost( EV_READY ); +} + +void +eMBASCIIStop( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBPortSerialEnable( FALSE, FALSE ); + vMBPortTimersDisable( ); + EXIT_CRITICAL_SECTION( ); +} + +eMBErrorCode +eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); + assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ); + + /* Length and CRC check */ + if( ( usRcvBufferPos >= MB_ASCII_SER_PDU_SIZE_MIN ) + && ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) ) + { + /* Save the address field. All frames are passed to the upper layed + * and the decision if a frame is used is done there. + */ + *pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF]; + + /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus + * size of address field and CRC checksum. + */ + *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC ); + + /* Return the start of the Modbus PDU to the caller. */ + *pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF]; + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +eMBErrorCode +eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + UCHAR usLRC; + + ENTER_CRITICAL_SECTION( ); + /* Check if the receiver is still in idle state. If not we where too + * slow with processing the received frame and the master sent another + * frame on the network. We have to abort sending the frame. + */ + if( eRcvState == STATE_RX_IDLE ) + { + /* First byte before the Modbus-PDU is the slave address. */ + pucSndBufferCur = ( UCHAR * ) pucFrame - 1; + usSndBufferCount = 1; + + /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ + pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; + usSndBufferCount += usLength; + + /* Calculate LRC checksum for Modbus-Serial-Line-PDU. */ + usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); + ucASCIIBuf[usSndBufferCount++] = usLRC; + + /* Activate the transmitter. */ + eSndState = STATE_TX_START; + vMBPortSerialEnable( FALSE, TRUE ); + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +BOOL +xMBASCIIReceiveFSM( void ) +{ + BOOL xNeedPoll = FALSE; + UCHAR ucByte; + UCHAR ucResult; + + assert( eSndState == STATE_TX_IDLE ); + + xNeedPoll = xMBPortSerialGetByte( ( CHAR * ) & ucByte ); + switch ( eRcvState ) + { + /* A new character is received. If the character is a ':' the input + * buffer is cleared. A CR-character signals the end of the data + * block. Other characters are part of the data block and their + * ASCII value is converted back to a binary representation. + */ + case STATE_RX_RCV: + /* Enable timer for character timeout. */ + vMBPortTimersEnable( ); + if( ucByte == ':' ) + { + /* Empty receive buffer. */ + eBytePos = BYTE_HIGH_NIBBLE; + usRcvBufferPos = 0; + } + else if( ucByte == MB_ASCII_DEFAULT_CR ) + { + eRcvState = STATE_RX_WAIT_EOF; + } + else + { + ucResult = prvucMBCHAR2BIN( ucByte ); + switch ( eBytePos ) + { + /* High nibble of the byte comes first. We check for + * a buffer overflow here. */ + case BYTE_HIGH_NIBBLE: + if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) + { + ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 ); + eBytePos = BYTE_LOW_NIBBLE; + break; + } + else + { + /* not handled in Modbus specification but seems + * a resonable implementation. */ + eRcvState = STATE_RX_IDLE; + /* Disable previously activated timer because of error state. */ + vMBPortTimersDisable( ); + } + break; + + case BYTE_LOW_NIBBLE: + ucASCIIBuf[usRcvBufferPos] |= ucResult; + usRcvBufferPos++; + eBytePos = BYTE_HIGH_NIBBLE; + break; + } + } + break; + + case STATE_RX_WAIT_EOF: + if( ucByte == ucMBLFCharacter ) + { + /* Disable character timeout timer because all characters are + * received. */ + vMBPortTimersDisable( ); + /* Receiver is again in idle state. */ + eRcvState = STATE_RX_IDLE; + + /* Notify the caller of eMBASCIIReceive that a new frame + * was received. */ + (void)xMBPortEventPost( EV_FRAME_RECEIVED ); + } + else if( ucByte == ':' ) + { + /* Empty receive buffer and back to receive state. */ + eBytePos = BYTE_HIGH_NIBBLE; + usRcvBufferPos = 0; + eRcvState = STATE_RX_RCV; + + /* Enable timer for character timeout. */ + vMBPortTimersEnable( ); + } + else + { + /* Frame is not okay. Delete entire frame. */ + eRcvState = STATE_RX_IDLE; + } + break; + + case STATE_RX_IDLE: + if( ucByte == ':' ) + { + /* Enable timer for character timeout. */ + vMBPortTimersEnable( ); + /* Reset the input buffers to store the frame. */ + usRcvBufferPos = 0; + eBytePos = BYTE_HIGH_NIBBLE; + eRcvState = STATE_RX_RCV; + } + break; + } + + return xNeedPoll; +} + +BOOL +xMBASCIITransmitFSM( void ) +{ + BOOL xNeedPoll = TRUE; + UCHAR ucByte; + + assert( eRcvState == STATE_RX_IDLE ); + switch ( eSndState ) + { + /* Start of transmission. The start of a frame is defined by sending + * the character ':'. */ + case STATE_TX_START: + ucByte = ':'; + xMBPortSerialPutByte( ( CHAR )ucByte ); + eSndState = STATE_TX_DATA; + eBytePos = BYTE_HIGH_NIBBLE; + break; + + /* Send the data block. Each data byte is encoded as a character hex + * stream with the high nibble sent first and the low nibble sent + * last. If all data bytes are exhausted we send a '\r' character + * to end the transmission. */ + case STATE_TX_DATA: + if( usSndBufferCount > 0 ) + { + switch ( eBytePos ) + { + case BYTE_HIGH_NIBBLE: + ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) ); + xMBPortSerialPutByte( ( CHAR ) ucByte ); + eBytePos = BYTE_LOW_NIBBLE; + break; + + case BYTE_LOW_NIBBLE: + ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) ); + xMBPortSerialPutByte( ( CHAR )ucByte ); + pucSndBufferCur++; + eBytePos = BYTE_HIGH_NIBBLE; + usSndBufferCount--; + break; + } + } + else + { + xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR ); + eSndState = STATE_TX_END; + } + break; + + /* Finish the frame by sending a LF character. */ + case STATE_TX_END: + xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter ); + /* We need another state to make sure that the CR character has + * been sent. */ + eSndState = STATE_TX_NOTIFY; + break; + + /* Notify the task which called eMBASCIISend that the frame has + * been sent. */ + case STATE_TX_NOTIFY: + eSndState = STATE_TX_IDLE; + xMBPortEventPost( EV_FRAME_TRANSMIT ); + xNeedPoll = FALSE; + break; + + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_TX_IDLE: + break; + } + + return xNeedPoll; +} + +BOOL MB_PORT_ISR_ATTR +xMBASCIITimerT1SExpired( void ) +{ + switch ( eRcvState ) + { + /* If we have a timeout we go back to the idle state and wait for + * the next frame. + */ + case STATE_RX_RCV: + case STATE_RX_WAIT_EOF: + eRcvState = STATE_RX_IDLE; + break; + + default: + assert( ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_WAIT_EOF ) + || (eRcvState == STATE_RX_IDLE )); + break; + } + vMBPortTimersDisable( ); + + /* no context switch required. */ + return FALSE; +} + + +static UCHAR +prvucMBCHAR2BIN( UCHAR ucCharacter ) +{ + if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) ) + { + return ( UCHAR )( ucCharacter - '0' ); + } + else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) ) + { + return ( UCHAR )( ucCharacter - 'A' + 0x0A ); + } + else + { + return 0xFF; + } +} + +static UCHAR +prvucMBBIN2CHAR( UCHAR ucByte ) +{ + if( ucByte <= 0x09 ) + { + return ( UCHAR )( '0' + ucByte ); + } + else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) ) + { + return ( UCHAR )( ucByte - 0x0A + 'A' ); + } + else + { + /* Programming error. */ + assert( 0 ); + } + return '0'; +} + + +static UCHAR +prvucMBLRC( UCHAR * pucFrame, USHORT usLen ) +{ + UCHAR ucLRC = 0; /* LRC char initialized */ + + while( usLen-- ) + { + ucLRC += *pucFrame++; /* Add buffer byte without carry */ + } + + /* Return twos complement */ + ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) ); + return ucLRC; +} + +#endif diff --git a/components/freemodbus/modbus/ascii/mbascii.h b/components/freemodbus/modbus/ascii/mbascii.h new file mode 100644 index 000000000..535701b6d --- /dev/null +++ b/components/freemodbus/modbus/ascii/mbascii.h @@ -0,0 +1,78 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbascii.h,v 1.8 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_ASCII_H +#define _MB_ASCII_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */ +#define MB_ASCII_DEFAULT_LF '\n' /*!< Default LF character for Modbus ASCII. */ +#define MB_ASCII_SER_PDU_SIZE_MIN 3 /*!< Minimum size of a Modbus ASCII frame. */ + +/* ----------------------- Function declaration -----------------------------*/ + +#if MB_SLAVE_ASCII_ENABLED > 0 +eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort, + ULONG ulBaudRate, eMBParity eParity ); +void eMBASCIIStart( void ); +void eMBASCIIStop( void ); + +eMBErrorCode eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, + USHORT * pusLength ); +eMBErrorCode eMBASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame, + USHORT usLength ); +BOOL xMBASCIIReceiveFSM( void ); +BOOL xMBASCIITransmitFSM( void ); +BOOL xMBASCIITimerT1SExpired( void ); +#endif + +#if MB_MASTER_ASCII_ENABLED > 0 +eMBErrorCode eMBMasterASCIIInit( UCHAR ucPort, + ULONG ulBaudRate, eMBParity eParity ); +void eMBMasterASCIIStart( void ); +void eMBMasterASCIIStop( void ); + +eMBErrorCode eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, + USHORT * pusLength ); +eMBErrorCode eMBMasterASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame, + USHORT usLength ); +BOOL xMBMasterASCIIReceiveFSM( void ); +BOOL xMBMasterASCIITransmitFSM( void ); +BOOL xMBMasterASCIITimerT1SExpired( void ); +#endif + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/ascii/mbascii_m.c b/components/freemodbus/modbus/ascii/mbascii_m.c new file mode 100644 index 000000000..b6327c2aa --- /dev/null +++ b/components/freemodbus/modbus/ascii/mbascii_m.c @@ -0,0 +1,573 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbascii.c,v 1.17 2010/06/06 13:47:07 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbconfig.h" +#include "mbascii.h" +#include "mbframe.h" + +#include "mbcrc.h" +#include "mbport.h" + +#if MB_MASTER_ASCII_ENABLED > 0 + +/* ----------------------- Defines ------------------------------------------*/ + +/* ----------------------- Type definitions ---------------------------------*/ +typedef enum +{ + STATE_M_RX_INIT, /*!< Receiver is in initial state. */ + STATE_M_RX_IDLE, /*!< Receiver is in idle state. */ + STATE_M_RX_RCV, /*!< Frame is beeing received. */ + STATE_M_RX_WAIT_EOF, /*!< Wait for End of Frame. */ + STATE_M_RX_ERROR, /*!< If the frame is invalid. */ +} eMBMasterAsciiRcvState; + +typedef enum +{ + STATE_M_TX_IDLE, /*!< Transmitter is in idle state. */ + STATE_M_TX_START, /*!< Starting transmission (':' sent). */ + STATE_M_TX_DATA, /*!< Sending of data (Address, Data, LRC). */ + STATE_M_TX_END, /*!< End of transmission. */ + STATE_M_TX_NOTIFY, /*!< Notify sender that the frame has been sent. */ + STATE_M_TX_XFWR, /*!< Transmitter is in transfer finish and wait receive state. */ +} eMBMasterAsciiSndState; + +typedef enum +{ + BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */ + BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */ +} eMBBytePos; + +/* ----------------------- Shared values -----------------------------------*/ +/* These Modbus values are shared in ASCII mode*/ +extern volatile UCHAR ucMasterRcvBuf[]; +extern volatile UCHAR ucMasterSndBuf[]; +extern volatile eMBMasterTimerMode eMasterCurTimerMode; + +/* ----------------------- Static functions ---------------------------------*/ +static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter ); + +static UCHAR prvucMBBIN2CHAR( UCHAR ucByte ); + +static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen ); + +/* ----------------------- Static variables ---------------------------------*/ +static volatile eMBMasterAsciiSndState eSndState; +static volatile eMBMasterAsciiRcvState eRcvState; + +static volatile UCHAR *ucMasterASCIIRcvBuf = ucMasterRcvBuf; +static volatile UCHAR *ucMasterASCIISndBuf = ucMasterSndBuf; + +static volatile USHORT usMasterRcvBufferPos; +static volatile eMBBytePos eBytePos; + +static volatile UCHAR *pucMasterSndBufferCur; +static volatile USHORT usMasterSndBufferCount; + +static volatile UCHAR ucLRC; +static volatile UCHAR ucMBLFCharacter; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBMasterASCIIInit( UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); + ucMBLFCharacter = MB_ASCII_DEFAULT_LF; + + if( xMBMasterPortSerialInit( ucPort, ulBaudRate, MB_ASCII_BITS_PER_SYMB, eParity ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + else if( xMBMasterPortTimersInit( MB_ASCII_TIMEOUT_MS * MB_TIMER_TICS_PER_MS ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + + EXIT_CRITICAL_SECTION( ); + + return eStatus; +} + +void +eMBMasterASCIIStart( void ) +{ + ENTER_CRITICAL_SECTION( ); + eRcvState = STATE_M_RX_IDLE; + vMBMasterPortSerialEnable( TRUE, FALSE ); + vMBMasterPortTimersT35Enable( ); + EXIT_CRITICAL_SECTION( ); +} + +void +eMBMasterASCIIStop( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBMasterPortSerialEnable( FALSE, FALSE ); + vMBMasterPortTimersDisable( ); + EXIT_CRITICAL_SECTION( ); +} + +eMBErrorCode +eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); + assert( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); + + /* Length and CRC check */ + if( ( usMasterRcvBufferPos >= MB_ASCII_SER_PDU_SIZE_MIN ) + && ( prvucMBLRC( ( UCHAR * ) ucMasterASCIIRcvBuf, usMasterRcvBufferPos ) == 0 ) ) + { + /* Save the address field. All frames are passed to the upper layed + * and the decision if a frame is used is done there. + */ + *pucRcvAddress = ucMasterASCIIRcvBuf[MB_SER_PDU_ADDR_OFF]; + + /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus + * size of address field and CRC checksum. + */ + *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC ); + + /* Return the start of the Modbus PDU to the caller. */ + *pucFrame = ( UCHAR * ) & ucMasterASCIIRcvBuf[MB_SER_PDU_PDU_OFF]; + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +eMBErrorCode +eMBMasterASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + UCHAR usLRC; + + if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL; + + ENTER_CRITICAL_SECTION( ); + /* Check if the receiver is still in idle state. If not we where too + * slow with processing the received frame and the master sent another + * frame on the network. We have to abort sending the frame. + */ + if(eRcvState == STATE_M_RX_IDLE) + { + /* First byte before the Modbus-PDU is the slave address. */ + pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1; + usMasterSndBufferCount = 1; + + /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ + pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; + usMasterSndBufferCount += usLength; + + /* Calculate LRC checksum for Modbus-Serial-Line-PDU. */ + usLRC = prvucMBLRC( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ); + ucMasterASCIISndBuf[usMasterSndBufferCount++] = usLRC; + + /* Activate the transmitter. */ + eSndState = STATE_M_TX_START; + vMBMasterPortSerialEnable( FALSE, TRUE ); + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +BOOL +xMBMasterASCIIReceiveFSM( void ) +{ + BOOL xNeedPoll = FALSE; + UCHAR ucByte; + UCHAR ucResult; + + assert(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); + + /* Always read the character. */ + xNeedPoll = xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte ); + + switch ( eRcvState ) + { + /* If we have received a character in the init state we have to + * wait until the frame is finished. + */ + case STATE_M_RX_INIT: + vMBMasterPortTimersT35Enable( ); + break; + + /* In the error state we wait until all characters in the + * damaged frame are transmitted. + */ + case STATE_M_RX_ERROR: + vMBMasterPortTimersRespondTimeoutEnable( ); + break; + + /* In the idle state we wait for a new character. If a character + * is received the t1.5 and t3.5 timers are started and the + * receiver is in the state STATE_RX_RECEIVE and disable early + * the timer of respond timeout . + */ + case STATE_M_RX_IDLE: + /* Waiting for the start of frame character during respond timeout */ + vMBMasterPortTimersRespondTimeoutEnable( ); + if( ucByte == ':' ) + { + /* Reset the input buffers to store the frame in receive state. */ + usMasterRcvBufferPos = 0; + eBytePos = BYTE_HIGH_NIBBLE; + eRcvState = STATE_M_RX_RCV; + } + eSndState = STATE_M_TX_IDLE; + break; + + /* A new character is received. If the character is a ':' the input + * buffer is cleared. A CR-character signals the end of the data + * block. Other characters are part of the data block and their + * ASCII value is converted back to a binary representation. + */ + case STATE_M_RX_RCV: + /* Enable timer timeout. */ + vMBMasterPortTimersT35Enable( ); + if( ucByte == ':' ) + { + /* Empty receive buffer. */ + eBytePos = BYTE_HIGH_NIBBLE; + usMasterRcvBufferPos = 0; + } + else if( ucByte == MB_ASCII_DEFAULT_CR ) + { + eRcvState = STATE_M_RX_WAIT_EOF; + } + else + { + ucResult = prvucMBCHAR2BIN( ucByte ); + switch ( eBytePos ) + { + /* High nibble of the byte comes first. We check for + * a buffer overflow here. */ + case BYTE_HIGH_NIBBLE: + if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ) + { + ucMasterASCIIRcvBuf[usMasterRcvBufferPos] = ( UCHAR )( ucResult << 4 ); + eBytePos = BYTE_LOW_NIBBLE; + break; + } + else + { + /* not handled in Modbus specification but seems + * a resonable implementation. */ + eRcvState = STATE_M_RX_ERROR; + /* Disable previously activated timer because of error state. */ + vMBPortTimersDisable( ); + } + break; + + case BYTE_LOW_NIBBLE: + ucMasterASCIIRcvBuf[usMasterRcvBufferPos] |= ucResult; + usMasterRcvBufferPos++; + eBytePos = BYTE_HIGH_NIBBLE; + break; + } + } + break; + + case STATE_M_RX_WAIT_EOF: + if( ucByte == ucMBLFCharacter ) + { + /* Disable character timeout timer because all characters are + * received. */ + vMBMasterPortTimersDisable( ); + /* Receiver is again in idle state. */ + eRcvState = STATE_M_RX_IDLE; + + /* Notify the caller of eMBMasterASCIIReceive that a new frame + * was received. */ + (void)xMBMasterPortEventPost( EV_MASTER_FRAME_RECEIVED ); + xNeedPoll = FALSE; + } + else if( ucByte == ':' ) + { + /* Start of frame character received but last message is not completed. + * Empty receive buffer and back to receive state. */ + eBytePos = BYTE_HIGH_NIBBLE; + usMasterRcvBufferPos = 0; + eRcvState = STATE_M_RX_IDLE; + + /* Enable timer for respond timeout and wait for next frame. */ + vMBMasterPortTimersRespondTimeoutEnable( ); + } + else + { + /* Frame is not okay. Delete entire frame. */ + eRcvState = STATE_M_RX_IDLE; + } + break; + } + + return xNeedPoll; +} + +BOOL +xMBMasterASCIITransmitFSM( void ) +{ + BOOL xNeedPoll = TRUE; + UCHAR ucByte; + BOOL xFrameIsBroadcast = FALSE; + + assert( eRcvState == STATE_M_RX_IDLE ); + + switch ( eSndState ) + { + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_M_TX_XFWR: + break; + + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_M_TX_IDLE: + break; + + /* Start of transmission. The start of a frame is defined by sending + * the character ':'. */ + case STATE_M_TX_START: + ucByte = ':'; + xMBMasterPortSerialPutByte( ( CHAR )ucByte ); + eSndState = STATE_M_TX_DATA; + eBytePos = BYTE_HIGH_NIBBLE; + break; + + /* Send the data block. Each data byte is encoded as a character hex + * stream with the high nibble sent first and the low nibble sent + * last. If all data bytes are exhausted we send a '\r' character + * to end the transmission. */ + case STATE_M_TX_DATA: + if( usMasterSndBufferCount > 0 ) + { + switch ( eBytePos ) + { + case BYTE_HIGH_NIBBLE: + ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucMasterSndBufferCur >> 4 ) ); + xMBMasterPortSerialPutByte( ( CHAR ) ucByte ); + eBytePos = BYTE_LOW_NIBBLE; + break; + + case BYTE_LOW_NIBBLE: + ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucMasterSndBufferCur & 0x0F ) ); + xMBMasterPortSerialPutByte( ( CHAR )ucByte ); + pucMasterSndBufferCur++; + eBytePos = BYTE_HIGH_NIBBLE; + usMasterSndBufferCount--; + break; + } + } + else + { + xMBMasterPortSerialPutByte( MB_ASCII_DEFAULT_CR ); + eSndState = STATE_M_TX_END; + } + break; + + /* Finish the frame by sending a LF character. */ + case STATE_M_TX_END: + xMBMasterPortSerialPutByte( ( CHAR )ucMBLFCharacter ); + /* We need another state to make sure that the CR character has + * been sent. */ + eSndState = STATE_M_TX_NOTIFY; + break; + + /* Notify the task which called eMBMasterASCIISend that the frame has + * been sent. */ + case STATE_M_TX_NOTIFY: + xFrameIsBroadcast = ( ucMasterASCIISndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; + vMBMasterRequestSetType( xFrameIsBroadcast ); + eSndState = STATE_M_TX_XFWR; + /* If the frame is broadcast ,master will enable timer of convert delay, + * else master will enable timer of respond timeout. */ + if ( xFrameIsBroadcast == TRUE ) + { + vMBMasterPortTimersConvertDelayEnable( ); + } + else + { + vMBMasterPortTimersRespondTimeoutEnable( ); + } + xNeedPoll = FALSE; + break; + } + + return xNeedPoll; +} + +BOOL +xMBMasterASCIITimerT1SExpired( void ) +{ + BOOL xNeedPoll = FALSE; + + switch ( eRcvState ) + { + /* Timer t35 expired. Startup phase is finished. */ + case STATE_M_RX_INIT: + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY); + ESP_EARLY_LOGI("xMBMasterASCIITimerT1SExpired", "RX_INIT_EXPIRED"); + break; + + /* Start of message is not received during respond timeout. + * Process error. */ + case STATE_M_RX_IDLE: + eRcvState = STATE_M_RX_ERROR; + break; + + /* A recieve timeout expired and no any new character received. + * Wait for respond time and go to error state to inform listener about error */ + case STATE_M_RX_RCV: + eRcvState = STATE_M_RX_ERROR; + break; + + /* An error occured while receiving the frame. */ + case STATE_M_RX_ERROR: + vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); + xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + break; + + /* If we have a timeout we go back to the idle state and wait for + * the next frame. + */ + case STATE_M_RX_WAIT_EOF: + eRcvState = STATE_M_RX_IDLE; + break; + + default: + assert( 0 ); + break; + } + eRcvState = STATE_M_RX_IDLE; + + switch (eSndState) + { + /* A frame was send finish and convert delay or respond timeout expired. + * If the frame is broadcast,The master will idle,and if the frame is not + * broadcast.*/ + case STATE_M_TX_XFWR: + if ( xMBMasterRequestIsBroadcast( ) == FALSE ) { + vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT); + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + } + break; + + /* Function called in an illegal state. */ + default: + assert( ( eSndState == STATE_M_TX_START ) || ( eSndState == STATE_M_TX_IDLE ) + || ( eSndState == STATE_M_TX_DATA ) || ( eSndState == STATE_M_TX_END ) + || ( eSndState == STATE_M_TX_NOTIFY ) ); + break; + } + eSndState = STATE_M_TX_IDLE; + + vMBMasterPortTimersDisable( ); + /* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */ + if (xMBMasterGetCurTimerMode() == MB_TMODE_CONVERT_DELAY) { + xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE ); + } + + vMBMasterPortTimersDisable( ); + + /* no context switch required. */ + return xNeedPoll; +} + +static UCHAR +prvucMBCHAR2BIN( UCHAR ucCharacter ) +{ + if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) ) + { + return ( UCHAR )( ucCharacter - '0' ); + } + else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) ) + { + return ( UCHAR )( ucCharacter - 'A' + 0x0A ); + } + else + { + return 0xFF; + } +} + +static UCHAR +prvucMBBIN2CHAR( UCHAR ucByte ) +{ + if( ucByte <= 0x09 ) + { + return ( UCHAR )( '0' + ucByte ); + } + else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) ) + { + return ( UCHAR )( ucByte - 0x0A + 'A' ); + } + else + { + /* Programming error. */ + assert( 0 ); + } + return '0'; +} + +static UCHAR +prvucMBLRC( UCHAR * pucFrame, USHORT usLen ) +{ + UCHAR ucLRC = 0; /* LRC char initialized */ + + while( usLen-- ) + { + ucLRC += *pucFrame++; /* Add buffer byte without carry */ + } + + /* Return twos complement */ + ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) ); + return ucLRC; +} + +#endif diff --git a/components/freemodbus/modbus/functions/mbfunccoils.c b/components/freemodbus/modbus/functions/mbfunccoils.c new file mode 100644 index 000000000..458ff5ca2 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfunccoils.c @@ -0,0 +1,273 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_COILCNT_MAX ( 0x07D0 ) + +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ( 0x07B0 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED || MB_TCP_ENABLED + +#if MB_FUNC_READ_COILS_ENABLED + +eMBException +eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usCoilCount; + UCHAR ucNBytes; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8 ); + usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usCoilCount >= 1 ) && + ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READ_COILS; + *usLen += 1; + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usCoilCount & 0x0007 ) != 0 ) + { + ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 ); + } + else + { + ucNBytes = ( UCHAR )( usCoilCount / 8 ); + } + *pucFrameCur++ = ucNBytes; + *usLen += 1; + + eRegStatus = + eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount, + MB_REG_READ ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + /* The response contains the function code, the starting address + * and the quantity of registers. We reuse the old values in the + * buffer because they are still valid. */ + *usLen += ucNBytes;; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#if MB_FUNC_WRITE_COIL_ENABLED > 0 +eMBException +eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + UCHAR ucBuf[2]; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) && + ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) || + ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) ) + { + ucBuf[1] = 0; + if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) + { + ucBuf[0] = 1; + } + else + { + ucBuf[0] = 0; + } + eRegStatus = + eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 +eMBException +eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usCoilCnt; + UCHAR ucByteCount; + UCHAR ucByteCountVerify; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); + usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); + + ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; + + /* Compute the number of expected bytes in the request. */ + if( ( usCoilCnt & 0x0007 ) != 0 ) + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); + } + else + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); + } + + if( ( usCoilCnt >= 1 ) && + ( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) && + ( ucByteCountVerify == ucByteCount ) ) + { + eRegStatus = + eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], + usRegAddress, usCoilCnt, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + /* The response contains the function code, the starting address + * and the quantity of registers. We reuse the old values in the + * buffer because they are still valid. */ + *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#endif + +#endif diff --git a/components/freemodbus/modbus/functions/mbfunccoils_m.c b/components/freemodbus/modbus/functions/mbfunccoils_m.c new file mode 100644 index 000000000..036808c7b --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfunccoils_m.c @@ -0,0 +1,391 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfunccoils_m.c,v 1.60 2013/10/12 15:10:12 Armink Add Master Functions + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" +#include "mbutils.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_SIZE ( 4 ) +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_REQ_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ( 0x07B0 ) +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 5 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED + +#if MB_FUNC_READ_COILS_ENABLED + +/** + * This function will request read coil. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usNCoils coil total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_COILS; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8; + ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usCoilCount; + UCHAR ucByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF] << 8 ); + usCoilCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] ); + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usCoilCount & 0x0007 ) != 0 ) + { + ucByteCount = ( UCHAR )( usCoilCount / 8 + 1 ); + } + else + { + ucByteCount = ( UCHAR )( usCoilCount / 8 ); + } + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usCoilCount >= 1 ) && + ( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ ); + + /* If an error occurred convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_WRITE_COIL_ENABLED > 0 + +/** + * This function will request write one coil. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usCoilData data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + * + * @see eMBMasterReqWriteMultipleCoils + */ +eMBMasterReqErrCode +eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_SINGLE_COIL; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + UCHAR ucBuf[2]; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) && + ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) || + ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) ) + { + ucBuf[1] = 0; + if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) + { + ucBuf[0] = 1; + } + else + { + ucBuf[0] = 0; + } + eRegStatus = + eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif // #if MB_FUNC_WRITE_COIL_ENABLED > 0 + +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 + +/** + * This function will request write multiple coils. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usNCoils coil total number + * @param usCoilData data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + * + * @see eMBMasterReqWriteCoil + */ +eMBMasterReqErrCode +eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + UCHAR ucByteCount; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_COILS; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF] = usNCoils >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF + 1] = usNCoils ; + if( ( usNCoils & 0x0007 ) != 0 ) + { + ucByteCount = ( UCHAR )( usNCoils / 8 + 1 ); + } + else + { + ucByteCount = ( UCHAR )( usNCoils / 8 ); + } + ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = ucByteCount; + ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; + while( ucByteCount > usRegIndex) + { + *ucMBFrame++ = pucDataBuffer[usRegIndex++]; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usCoilCnt; + UCHAR ucByteCount; + UCHAR ucByteCountVerify; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, the *usLen is not need check. */ + if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); + usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); + + ucByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; + + /* Compute the number of expected bytes in the request. */ + if( ( usCoilCnt & 0x0007 ) != 0 ) + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); + } + else + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); + } + + if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) ) + { + eRegStatus = + eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], + usRegAddress, usCoilCnt, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif // #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 +#endif // #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 diff --git a/components/freemodbus/modbus/functions/mbfuncdiag.c b/components/freemodbus/modbus/functions/mbfuncdiag.c new file mode 100644 index 000000000..d75ffc0f7 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncdiag.c @@ -0,0 +1,29 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncdiag.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ + */ diff --git a/components/freemodbus/modbus/functions/mbfuncdisc.c b/components/freemodbus/modbus/functions/mbfuncdisc.c new file mode 100644 index 000000000..87667ac2f --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncdisc.c @@ -0,0 +1,126 @@ + /* + * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS + * Copyright (C) 2006 Christian Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED || MB_TCP_ENABLED + +#if MB_FUNC_READ_COILS_ENABLED + +eMBException +eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usDiscreteCnt; + UCHAR ucNBytes; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 ); + usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usDiscreteCnt >= 1 ) && + ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS; + *usLen += 1; + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usDiscreteCnt & 0x0007 ) != 0 ) + { + ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 ); + } + else + { + ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 ); + } + *pucFrameCur++ = ucNBytes; + *usLen += 1; + + eRegStatus = + eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + /* The response contains the function code, the starting address + * and the quantity of registers. We reuse the old values in the + * buffer because they are still valid. */ + *usLen += ucNBytes;; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#endif diff --git a/components/freemodbus/modbus/functions/mbfuncdisc_m.c b/components/freemodbus/modbus/functions/mbfuncdisc_m.c new file mode 100644 index 000000000..1a69647d8 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncdisc_m.c @@ -0,0 +1,162 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $ + */ + + + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED + +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED + +/** + * This function will request read discrete inputs. + * + * @param ucSndAddr salve address + * @param usDiscreteAddr discrete start address + * @param usNDiscreteIn discrete total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_DISCRETE_INPUTS; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usDiscreteAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usDiscreteAddr; + ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8; + ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usDiscreteCnt; + UCHAR ucNBytes; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usDiscreteCnt = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF] << 8 ); + usDiscreteCnt |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] ); + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usDiscreteCnt & 0x0007 ) != 0 ) + { + ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 ); + } + else + { + ucNBytes = ( UCHAR )( usDiscreteCnt / 8 ); + } + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF]) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif +#endif // #if MB_SERIAL_MASTER_RTU_ENABLED || MB_SERIAL_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED diff --git a/components/freemodbus/modbus/functions/mbfuncholding.c b/components/freemodbus/modbus/functions/mbfuncholding.c new file mode 100644 index 000000000..1a37866c5 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncholding.c @@ -0,0 +1,311 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) + +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 ) + +#define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) +#define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) +#define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) +#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED || MB_TCP_ENABLED + +#if MB_FUNC_WRITE_HOLDING_ENABLED + +eMBException +eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + /* Make callback to update the value. */ + eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], + usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 +eMBException +eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usRegCount; + UCHAR ucRegByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] ); + + ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; + + if( ( usRegCount >= 1 ) && + ( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) && + ( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) ) + { + /* Make callback to update the register values. */ + eRegStatus = + eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], + usRegAddress, usRegCount, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + /* The response contains the function code, the starting + * address and the quantity of registers. We reuse the + * old values in the buffer because they are still valid. + */ + *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + +eMBException +eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usRegCount; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER; + *usLen += 1; + + /* Second byte in the response contain the number of bytes. */ + *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 ); + *usLen += 1; + + /* Make callback to fill the buffer. */ + eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + *usLen += usRegCount * 2; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + +eMBException +eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegReadAddress; + USHORT usRegReadCount; + USHORT usRegWriteAddress; + USHORT usRegWriteCount; + UCHAR ucRegWriteByteCount; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) ) + { + usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U ); + usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] ); + usRegReadAddress++; + + usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U ); + usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] ); + + usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U ); + usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] ); + usRegWriteAddress++; + + usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U ); + usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] ); + + ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF]; + + if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) && + ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) && + ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) ) + { + /* Make callback to update the register values. */ + eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF], + usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); + + if( eRegStatus == MB_ENOERR ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; + *usLen += 1; + + /* Second byte in the response contain the number of bytes. */ + *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 ); + *usLen += 1; + + /* Make the read callback. */ + eRegStatus = + eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ ); + if( eRegStatus == MB_ENOERR ) + { + *usLen += 2 * usRegReadCount; + } + } + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + return eStatus; +} + +#endif + +#endif diff --git a/components/freemodbus/modbus/functions/mbfuncholding_m.c b/components/freemodbus/modbus/functions/mbfuncholding_m.c new file mode 100644 index 000000000..9b4c07711 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncholding_m.c @@ -0,0 +1,455 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +//#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) +#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_SIZE ( 4 ) +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX ( 0x0078 ) +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 4 ) + +#define MB_PDU_REQ_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) +#define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) +#define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) +#define MB_PDU_REQ_READWRITE_SIZE_MIN ( 9 ) +#define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 1 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED + +#if MB_FUNC_WRITE_HOLDING_ENABLED + +/** + * This function will request write holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usRegData register data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + /* Make callback to update the value. */ + eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], + usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 + +/** + * This function will request write multiple holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param pusDataBuffer data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2; + ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; + while( usNRegs > usRegIndex) + { + *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; + *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + UCHAR ucRegByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, the *usLen is not need check. */ + if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] ); + + ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; + + if( ucRegByteCount == 2 * usRegCount ) + { + /* Make callback to update the register values. */ + eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], + usRegAddress, usRegCount, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + +/** + * This function will request read holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + +/** + * This function will request read and write holding register. + * + * @param ucSndAddr salve address + * @param usReadRegAddr read register start address + * @param usNReadRegs read register total number + * @param pusDataBuffer data to be written + * @param usWriteRegAddr write register start address + * @param usNWriteRegs write register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, + USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs ; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2; + ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF; + while( usNWriteRegs > usRegIndex) + { + *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; + *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegReadAddress; + USHORT usRegReadCount; + USHORT usRegWriteAddress; + USHORT usRegWriteCount; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U ); + usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] ); + usRegReadAddress++; + + usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U ); + usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] ); + + usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U ); + usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] ); + usRegWriteAddress++; + + usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U ); + usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] ); + + if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] ) + { + /* Make callback to update the register values. */ + eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF], + usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); + + if( eRegStatus == MB_ENOERR ) + { + /* Make the read callback. */ + eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF], + usRegReadAddress, usRegReadCount, MB_REG_READ); + } + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + return eStatus; +} + +#endif +#endif // #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED + diff --git a/components/freemodbus/modbus/functions/mbfuncinput.c b/components/freemodbus/modbus/functions/mbfuncinput.c new file mode 100644 index 000000000..97aeac4db --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncinput.c @@ -0,0 +1,126 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncinput.c,v 1.10 2007/09/12 10:15:56 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) + +#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED || MB_TCP_ENABLED + +#if MB_FUNC_READ_INPUT_ENABLED + +eMBException +eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usRegCount; + UCHAR *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) + && ( usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX ) ) + { + /* Set the current PDU data pointer to the beginning. */ + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + /* First byte contains the function code. */ + *pucFrameCur++ = MB_FUNC_READ_INPUT_REGISTER; + *usLen += 1; + + /* Second byte in the response contain the number of bytes. */ + *pucFrameCur++ = ( UCHAR )( usRegCount * 2 ); + *usLen += 1; + + eRegStatus = + eMBRegInputCB( pucFrameCur, usRegAddress, usRegCount ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + else + { + *usLen += usRegCount * 2; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read input register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#endif diff --git a/components/freemodbus/modbus/functions/mbfuncinput_m.c b/components/freemodbus/modbus/functions/mbfuncinput_m.c new file mode 100644 index 000000000..3a6869552 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncinput_m.c @@ -0,0 +1,147 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncinput_m.c,v 1.60 2013/10/12 14:23:40 Armink Add Master Functions Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +#if MB_FUNC_READ_INPUT_ENABLED + +/** + * This function will request read input register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_INPUT_REGISTER; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif +#endif // #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED diff --git a/components/freemodbus/modbus/functions/mbfuncother.c b/components/freemodbus/modbus/functions/mbfuncother.c new file mode 100644 index 000000000..a488a5b77 --- /dev/null +++ b/components/freemodbus/modbus/functions/mbfuncother.c @@ -0,0 +1,92 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncother.c,v 1.8 2006/12/07 22:10:34 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED || MB_TCP_ENABLED + +#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED + +/* ----------------------- Static variables ---------------------------------*/ +static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF]; +static USHORT usMBSlaveIDLen; + +/* ----------------------- Start implementation -----------------------------*/ + +eMBErrorCode +eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, + UCHAR const *pucAdditional, USHORT usAdditionalLen ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + /* the first byte and second byte in the buffer is reserved for + * the parameter ucSlaveID and the running flag. The rest of + * the buffer is available for additional data. */ + if( usAdditionalLen + 2 < MB_FUNC_OTHER_REP_SLAVEID_BUF ) + { + usMBSlaveIDLen = 0; + ucMBSlaveID[usMBSlaveIDLen++] = ucSlaveID; + ucMBSlaveID[usMBSlaveIDLen++] = ( UCHAR )( xIsRunning ? 0xFF : 0x00 ); + if( usAdditionalLen > 0 ) + { + memcpy( &ucMBSlaveID[usMBSlaveIDLen], pucAdditional, + ( size_t )usAdditionalLen ); + usMBSlaveIDLen += usAdditionalLen; + } + } + else + { + eStatus = MB_ENORES; + } + return eStatus; +} + +eMBException +eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ) +{ + memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen ); + *usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen ); + return MB_EX_NONE; +} + +#endif + +#endif diff --git a/components/freemodbus/modbus/functions/mbutils.c b/components/freemodbus/modbus/functions/mbutils.c new file mode 100644 index 000000000..6a725703e --- /dev/null +++ b/components/freemodbus/modbus/functions/mbutils.c @@ -0,0 +1,141 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbutils.c,v 1.6 2007/02/18 23:49:07 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbproto.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define BITS_UCHAR 8U + +/* ----------------------- Start implementation -----------------------------*/ +void +xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits, + UCHAR ucValue ) +{ + USHORT usWordBuf; + USHORT usMask; + USHORT usByteOffset; + USHORT usNPreBits; + USHORT usValue = ucValue; + + assert( ucNBits <= 8 ); + assert( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 ); + + /* Calculate byte offset for first byte containing the bit values starting + * at usBitOffset. */ + usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR ); + + /* How many bits precede our bits to set. */ + usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR ); + + /* Move bit field into position over bits to set */ + usValue <<= usNPreBits; + + /* Prepare a mask for setting the new bits. */ + usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 ); + usMask <<= usBitOffset - usByteOffset * BITS_UCHAR; + + /* copy bits into temporary storage. */ + usWordBuf = ucByteBuf[usByteOffset]; + usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR; + + /* Zero out bit field bits and then or value bits into them. */ + usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue ); + + /* move bits back into storage */ + ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF ); + ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR ); +} + +UCHAR +xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits ) +{ + USHORT usWordBuf; + USHORT usMask; + USHORT usByteOffset; + USHORT usNPreBits; + + /* Calculate byte offset for first byte containing the bit values starting + * at usBitOffset. */ + usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR ); + + /* How many bits precede our bits to set. */ + usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR ); + + /* Prepare a mask for setting the new bits. */ + usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 ); + + /* copy bits into temporary storage. */ + usWordBuf = ucByteBuf[usByteOffset]; + usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR; + + /* throw away unneeded bits. */ + usWordBuf >>= usNPreBits; + + /* mask away bits above the requested bitfield. */ + usWordBuf &= usMask; + + return ( UCHAR ) usWordBuf; +} + +eMBException +prveMBError2Exception( eMBErrorCode eErrorCode ) +{ + eMBException eStatus; + + switch ( eErrorCode ) + { + case MB_ENOERR: + eStatus = MB_EX_NONE; + break; + + case MB_ENOREG: + eStatus = MB_EX_ILLEGAL_DATA_ADDRESS; + break; + + case MB_ETIMEDOUT: + eStatus = MB_EX_SLAVE_BUSY; + break; + + default: + eStatus = MB_EX_SLAVE_DEVICE_FAILURE; + break; + } + + return eStatus; +} diff --git a/components/freemodbus/modbus/include/mb.h b/components/freemodbus/modbus/include/mb.h new file mode 100644 index 000000000..abfa92bd4 --- /dev/null +++ b/components/freemodbus/modbus/include/mb.h @@ -0,0 +1,417 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mb.h,v 1.17 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_H +#define _MB_H + +#include "port.h" + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +#include "mbport.h" +#include "mbproto.h" + +/*! \defgroup modbus Modbus + * \code #include "mb.h" \endcode + * + * This module defines the interface for the application. It contains + * the basic functions and types required to use the Modbus protocol stack. + * A typical application will want to call eMBInit() first. If the device + * is ready to answer network requests it must then call eMBEnable() to activate + * the protocol stack. In the main loop the function eMBPoll() must be called + * periodically. The time interval between pooling depends on the configured + * Modbus timeout. If an RTOS is available a separate task should be created + * and the task should always call the function eMBPoll(). + * + * \code + * // Initialize protocol stack in RTU mode for a slave with address 10 = 0x0A + * eMBInit( MB_RTU, 0x0A, 38400, MB_PAR_EVEN ); + * // Enable the Modbus Protocol Stack. + * eMBEnable( ); + * for( ;; ) + * { + * // Call the main polling loop of the Modbus protocol stack. + * eMBPoll( ); + * ... + * } + * \endcode + */ + +/* ----------------------- Defines ------------------------------------------*/ + +/*! \ingroup modbus + * \brief Use the default Modbus TCP port (502) + */ +#define MB_TCP_PORT_USE_DEFAULT 0 + +#define MB_FUNC_CODE_MAX 127 + +/* ----------------------- Type definitions ---------------------------------*/ +/*! \ingroup modbus + * \brief Modbus serial transmission modes (RTU/ASCII). + * + * Modbus serial supports two transmission modes. Either ASCII or RTU. RTU + * is faster but has more hardware requirements and requires a network with + * a low jitter. ASCII is slower and more reliable on slower links (E.g. modems) + */ +typedef enum +{ + MB_RTU, /*!< RTU transmission mode. */ + MB_ASCII, /*!< ASCII transmission mode. */ + MB_TCP /*!< TCP mode. */ +} eMBMode; + +/*! \ingroup modbus + * \brief If register should be written or read. + * + * This value is passed to the callback functions which support either + * reading or writing register values. Writing means that the application + * registers should be updated and reading means that the modbus protocol + * stack needs to know the current register values. + * + * \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and + * eMBRegInputCB( ). + */ +typedef enum +{ + MB_REG_READ, /*!< Read register values and pass to protocol stack. */ + MB_REG_WRITE /*!< Update register values. */ +} eMBRegisterMode; + +/*! \ingroup modbus + * \brief Errorcodes used by all function in the protocol stack. + */ +typedef enum +{ + MB_ENOERR, /*!< no error. */ + MB_ENOREG, /*!< illegal register address. */ + MB_EINVAL, /*!< illegal argument. */ + MB_EPORTERR, /*!< porting layer error. */ + MB_ENORES, /*!< insufficient resources. */ + MB_EIO, /*!< I/O error. */ + MB_EILLSTATE, /*!< protocol stack in illegal state. */ + MB_ETIMEDOUT /*!< timeout error occurred. */ +} eMBErrorCode; + +/* ----------------------- Function prototypes ------------------------------*/ +/*! \ingroup modbus + * \brief Initialize the Modbus protocol stack. + * + * This functions initializes the ASCII or RTU module and calls the + * init functions of the porting layer to prepare the hardware. Please + * note that the receiver is still disabled and no Modbus frames are + * processed until eMBEnable( ) has been called. + * + * \param eMode If ASCII or RTU mode should be used. + * \param ucSlaveAddress The slave address. Only frames sent to this + * address or to the broadcast address are processed. + * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value + * is platform dependent and some ports simply choose to ignore it. + * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend + * on the porting layer. + * \param eParity Parity used for serial transmission. + * + * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. + * The protocol is then in the disabled state and ready for activation + * by calling eMBEnable( ). Otherwise one of the following error codes + * is returned: + * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid + * slave addresses are in the range 1 - 247. + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, + UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ); + +/*! \ingroup modbus + * \brief Initialize the Modbus protocol stack for Modbus TCP. + * + * This function initializes the Modbus TCP Module. Please note that + * frame processing is still disabled until eMBEnable( ) is called. + * + * \param usTCPPort The TCP port to listen on. + * \return If the protocol stack has been initialized correctly the function + * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error + * codes is returned: + * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid + * slave addresses are in the range 1 - 247. + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBTCPInit( USHORT usTCPPort ); + +/*! \ingroup modbus + * \brief Release resources used by the protocol stack. + * + * This function disables the Modbus protocol stack and release all + * hardware resources. It must only be called when the protocol stack + * is disabled. + * + * \note Note all ports implement this function. A port which wants to + * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. + * + * \return If the resources where released it return eMBErrorCode::MB_ENOERR. + * If the protocol stack is not in the disabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBClose( void ); + +/*! \ingroup modbus + * \brief Enable the Modbus protocol stack. + * + * This function enables processing of Modbus frames. Enabling the protocol + * stack is only possible if it is in the disabled state. + * + * \return If the protocol stack is now in the state enabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it + * return eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBEnable( void ); + +/*! \ingroup modbus + * \brief Disable the Modbus protocol stack. + * + * This function disables processing of Modbus frames. + * + * \return If the protocol stack has been disabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBDisable( void ); + +/*! \ingroup modbus + * \brief The main pooling loop of the Modbus protocol stack. + * + * This function must be called periodically. The timer interval required + * is given by the application dependent Modbus slave timeout. Internally the + * function calls xMBPortEventGet() and waits for an event from the receiver or + * transmitter state machines. + * + * \return If the protocol stack is not in the enabled state the function + * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns + * eMBErrorCode::MB_ENOERR. + */ +eMBErrorCode eMBPoll( void ); + +/*! \ingroup modbus + * \brief Configure the slave id of the device. + * + * This function should be called when the Modbus function Report Slave ID + * is enabled ( By defining MB_FUNC_OTHER_REP_SLAVEID_ENABLED in mbconfig.h ). + * + * \param ucSlaveID Values is returned in the Slave ID byte of the + * Report Slave ID response. + * \param xIsRunning If TRUE the Run Indicator Status byte is set to 0xFF. + * otherwise the Run Indicator Status is 0x00. + * \param pucAdditional Values which should be returned in the Additional + * bytes of the Report Slave ID response. + * \param usAdditionalLen Length of the buffer pucAdditonal. + * + * \return If the static buffer defined by MB_FUNC_OTHER_REP_SLAVEID_BUF in + * mbconfig.h is to small it returns eMBErrorCode::MB_ENORES. Otherwise + * it returns eMBErrorCode::MB_ENOERR. + */ +eMBErrorCode eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, + UCHAR const *pucAdditional, + USHORT usAdditionalLen ); + +/*! \ingroup modbus + * \brief Registers a callback handler for a given function code. + * + * This function registers a new callback handler for a given function code. + * The callback handler supplied is responsible for interpreting the Modbus PDU and + * the creation of an appropriate response. In case of an error it should return + * one of the possible Modbus exceptions which results in a Modbus exception frame + * sent by the protocol stack. + * + * \param ucFunctionCode The Modbus function code for which this handler should + * be registers. Valid function codes are in the range 1 to 127. + * \param pxHandler The function handler which should be called in case + * such a frame is received. If \c NULL a previously registered function handler + * for this function code is removed. + * + * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no + * more resources are available it returns eMBErrorCode::MB_ENORES. In this + * case the values in mbconfig.h should be adjusted. If the argument was not + * valid it returns eMBErrorCode::MB_EINVAL. + */ +eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode, + pxMBFunctionHandler pxHandler ); + +/* ----------------------- Callback -----------------------------------------*/ + +/*! \defgroup modbus_registers Modbus Registers + * \code #include "mb.h" \endcode + * The protocol stack does not internally allocate any memory for the + * registers. This makes the protocol stack very small and also usable on + * low end targets. In addition the values don't have to be in the memory + * and could for example be stored in a flash.
+ * Whenever the protocol stack requires a value it calls one of the callback + * function with the register address and the number of registers to read + * as an argument. The application should then read the actual register values + * (for example the ADC voltage) and should store the result in the supplied + * buffer.
+ * If the protocol stack wants to update a register value because a write + * register function was received a buffer with the new register values is + * passed to the callback function. The function should then use these values + * to update the application register values. + */ + +/*! \ingroup modbus_registers + * \brief Callback function used if the value of a Input Register + * is required by the protocol stack. The starting register address is given + * by \c usAddress and the last register is given by usAddress + + * usNRegs - 1. + * + * \param pucRegBuffer A buffer where the callback function should write + * the current value of the modbus registers to. + * \param usAddress The starting address of the register. Input registers + * are in the range 1 - 65535. + * \param usNRegs Number of registers the callback function must supply. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application can not supply values + * for registers within this range. In this case a + * ILLEGAL DATA ADDRESS exception frame is sent as a response. + * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is + * currently not available and the application dependent response + * timeout would be violated. In this case a SLAVE DEVICE BUSY + * exception is sent as a response. + * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case + * a SLAVE DEVICE FAILURE exception is sent as a response. + */ +eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Holding Register value is + * read or written by the protocol stack. The starting register address + * is given by \c usAddress and the last register is given by + * usAddress + usNRegs - 1. + * + * \param pucRegBuffer If the application registers values should be updated the + * buffer points to the new registers values. If the protocol stack needs + * to now the current values the callback function should write them into + * this buffer. + * \param usAddress The starting address of the register. + * \param usNRegs Number of registers to read or write. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register + * values should be updated from the values in the buffer. For example + * this would be the case when the Modbus master has issued an + * WRITE SINGLE REGISTER command. + * If the value eMBRegisterMode::MB_REG_READ the application should copy + * the current values into the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application can not supply values + * for registers within this range. In this case a + * ILLEGAL DATA ADDRESS exception frame is sent as a response. + * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is + * currently not available and the application dependent response + * timeout would be violated. In this case a SLAVE DEVICE BUSY + * exception is sent as a response. + * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case + * a SLAVE DEVICE FAILURE exception is sent as a response. + */ +eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Coil Register value is + * read or written by the protocol stack. If you are going to use + * this function you might use the functions xMBUtilSetBits( ) and + * xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The bits are packed in bytes where the first coil + * starting at address \c usAddress is stored in the LSB of the + * first byte in the buffer pucRegBuffer. + * If the buffer should be written by the callback function unused + * coil values (I.e. if not a multiple of eight coils is used) should be set + * to zero. + * \param usAddress The first coil number. + * \param usNCoils Number of coil values requested. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should + * be updated from the values supplied in the buffer \c pucRegBuffer. + * If eMBRegisterMode::MB_REG_READ the application should store the current + * values in the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is + * currently not available and the application dependent response + * timeout would be violated. In this case a SLAVE DEVICE BUSY + * exception is sent as a response. + * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case + * a SLAVE DEVICE FAILURE exception is sent as a response. + */ +eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Input Discrete Register value is + * read by the protocol stack. + * + * If you are going to use his function you might use the functions + * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The buffer should be updated with the current + * coil values. The first discrete input starting at \c usAddress must be + * stored at the LSB of the first byte in the buffer. If the requested number + * is not a multiple of eight the remaining bits should be set to zero. + * \param usAddress The starting address of the first discrete input. + * \param usNDiscrete Number of discrete input values. + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If no such discrete inputs exists. + * In this case a ILLEGAL DATA ADDRESS exception frame is sent + * as a response. + * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is + * currently not available and the application dependent response + * timeout would be violated. In this case a SLAVE DEVICE BUSY + * exception is sent as a response. + * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case + * a SLAVE DEVICE FAILURE exception is sent as a response. + */ +eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete ); + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mb_m.h b/components/freemodbus/modbus/include/mb_m.h new file mode 100644 index 000000000..f17867e1c --- /dev/null +++ b/components/freemodbus/modbus/include/mb_m.h @@ -0,0 +1,410 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mb_m.h,v 1.60 2013/09/03 10:20:05 Armink Add Master Functions $ + */ + +#ifndef _MB_M_H +#define _MB_M_H + +#include "mbconfig.h" +#include "port.h" +#include "mb.h" + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +#include "mbport.h" +#include "mbproto.h" +/*! \defgroup modbus Modbus + * \code #include "mb.h" \endcode + * + * This module defines the interface for the application. It contains + * the basic functions and types required to use the Modbus Master protocol stack. + * A typical application will want to call eMBMasterInit() first. If the device + * is ready to answer network requests it must then call eMBEnable() to activate + * the protocol stack. In the main loop the function eMBMasterPoll() must be called + * periodically. The time interval between pooling depends on the configured + * Modbus timeout. If an RTOS is available a separate task should be created + * and the task should always call the function eMBMasterPoll(). + * + * \code + * // Initialize protocol stack in RTU mode for a Master + * eMBMasterInit( MB_RTU, 38400, MB_PAR_EVEN ); + * // Enable the Modbus Protocol Stack. + * eMBMasterEnable( ); + * for( ;; ) + * { + * // Call the main polling loop of the Modbus Master protocol stack. + * eMBMasterPoll( ); + * ... + * } + * \endcode + */ + +/* ----------------------- Defines ------------------------------------------*/ + +/*! \ingroup modbus + * \brief Use the default Modbus Master TCP port (502) + */ +#define MB_MASTER_TCP_PORT_USE_DEFAULT 0 + +/*! \ingroup modbus + * \brief Errorcodes used by all function in the Master request. + */ +typedef enum +{ + MB_MRE_NO_ERR, /*!< no error. */ + MB_MRE_NO_REG, /*!< illegal register address. */ + MB_MRE_ILL_ARG, /*!< illegal argument. */ + MB_MRE_REV_DATA, /*!< receive data error. */ + MB_MRE_TIMEDOUT, /*!< timeout error occurred. */ + MB_MRE_MASTER_BUSY, /*!< master is busy now. */ + MB_MRE_EXE_FUN /*!< execute function error. */ +} eMBMasterReqErrCode; + +/*! \ingroup modbus + * \brief TimerMode is Master 3 kind of Timer modes. + */ +typedef enum +{ + MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */ + MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */ + MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/ +}eMBMasterTimerMode; + +/* ----------------------- Function prototypes ------------------------------*/ +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack. + * + * This functions initializes the ASCII or RTU module and calls the + * init functions of the porting layer to prepare the hardware. Please + * note that the receiver is still disabled and no Modbus frames are + * processed until eMBMasterEnable( ) has been called. + * + * \param eMode If ASCII or RTU mode should be used. + * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value + * is platform dependent and some ports simply choose to ignore it. + * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend + * on the porting layer. + * \param eParity Parity used for serial transmission. + * + * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. + * The protocol is then in the disabled state and ready for activation + * by calling eMBMasterEnable( ). Otherwise one of the following error codes + * is returned: + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterSerialInit( eMBMode eMode, UCHAR ucPort, + ULONG ulBaudRate, eMBParity eParity ); + +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack for Modbus TCP. + * + * This function initializes the Modbus TCP Module. Please note that + * frame processing is still disabled until eMBEnable( ) is called. + * + * \param usTCPPort The TCP port to listen on. + * \return If the protocol stack has been initialized correctly the function + * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error + * codes is returned: + * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid + * slave addresses are in the range 1 - 247. + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterTCPInit( USHORT usTCPPort ); + +/*! \ingroup modbus + * \brief Release resources used by the protocol stack. + * + * This function disables the Modbus Master protocol stack and release all + * hardware resources. It must only be called when the protocol stack + * is disabled. + * + * \note Note all ports implement this function. A port which wants to + * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. + * + * \return If the resources where released it return eMBErrorCode::MB_ENOERR. + * If the protocol stack is not in the disabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterClose( void ); + +/*! \ingroup modbus + * \brief Enable the Modbus Master protocol stack. + * + * This function enables processing of Modbus Master frames. Enabling the protocol + * stack is only possible if it is in the disabled state. + * + * \return If the protocol stack is now in the state enabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it + * return eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterEnable( void ); + +/*! \ingroup modbus + * \brief Disable the Modbus Master protocol stack. + * + * This function disables processing of Modbus frames. + * + * \return If the protocol stack has been disabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterDisable( void ); + +/*! \ingroup modbus + * \brief The main pooling loop of the Modbus Master protocol stack. + * + * This function must be called periodically. The timer interval required + * is given by the application dependent Modbus slave timeout. Internally the + * function calls xMBMasterPortEventGet() and waits for an event from the receiver or + * transmitter state machines. + * + * \return If the protocol stack is not in the enabled state the function + * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns + * eMBErrorCode::MB_ENOERR. + */ +eMBErrorCode eMBMasterPoll( void ); + +/*! \ingroup modbus + * \brief Registers a callback handler for a given function code. + * + * This function registers a new callback handler for a given function code. + * The callback handler supplied is responsible for interpreting the Modbus PDU and + * the creation of an appropriate response. In case of an error it should return + * one of the possible Modbus exceptions which results in a Modbus exception frame + * sent by the protocol stack. + * + * \param ucFunctionCode The Modbus function code for which this handler should + * be registers. Valid function codes are in the range 1 to 127. + * \param pxHandler The function handler which should be called in case + * such a frame is received. If \c NULL a previously registered function handler + * for this function code is removed. + * + * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no + * more resources are available it returns eMBErrorCode::MB_ENORES. In this + * case the values in mbconfig.h should be adjusted. If the argument was not + * valid it returns eMBErrorCode::MB_EINVAL. + */ +eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode, + pxMBFunctionHandler pxHandler ); + +/* ----------------------- Callback -----------------------------------------*/ + +/*! \defgroup modbus_master registers Modbus Registers + * \code #include "mb_m.h" \endcode + * The protocol stack does not internally allocate any memory for the + * registers. This makes the protocol stack very small and also usable on + * low end targets. In addition the values don't have to be in the memory + * and could for example be stored in a flash.
+ * Whenever the protocol stack requires a value it calls one of the callback + * function with the register address and the number of registers to read + * as an argument. The application should then read the actual register values + * (for example the ADC voltage) and should store the result in the supplied + * buffer.
+ * If the protocol stack wants to update a register value because a write + * register function was received a buffer with the new register values is + * passed to the callback function. The function should then use these values + * to update the application register values. + */ + +/*! \ingroup modbus_registers + * \brief Callback function used if the value of a Input Register + * is required by the protocol stack. The starting register address is given + * by \c usAddress and the last register is given by usAddress + + * usNRegs - 1. + * + * \param pucRegBuffer A buffer where the callback function should write + * the current value of the modbus registers to. + * \param usAddress The starting address of the register. Input registers + * are in the range 1 - 65535. + * \param usNRegs Number of registers the callback function must supply. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Holding Register value is + * read or written by the protocol stack. The starting register address + * is given by \c usAddress and the last register is given by + * usAddress + usNRegs - 1. + * + * \param pucRegBuffer If the application registers values should be updated the + * buffer points to the new registers values. If the protocol stack needs + * to now the current values the callback function should write them into + * this buffer. + * \param usAddress The starting address of the register. + * \param usNRegs Number of registers to read or write. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register + * values should be updated from the values in the buffer. For example + * this would be the case when the Modbus master has issued an + * WRITE SINGLE REGISTER command. + * If the value eMBRegisterMode::MB_REG_READ the application should copy + * the current values into the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Coil Register value is + * read or written by the protocol stack. If you are going to use + * this function you might use the functions xMBUtilSetBits( ) and + * xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The bits are packed in bytes where the first coil + * starting at address \c usAddress is stored in the LSB of the + * first byte in the buffer pucRegBuffer. + * If the buffer should be written by the callback function unused + * coil values (I.e. if not a multiple of eight coils is used) should be set + * to zero. + * \param usAddress The first coil number. + * \param usNCoils Number of coil values requested. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should + * be updated from the values supplied in the buffer \c pucRegBuffer. + * If eMBRegisterMode::MB_REG_READ the application should store the current + * values in the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Input Discrete Register value is + * read by the protocol stack. + * + * If you are going to use his function you might use the functions + * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The buffer should be updated with the current + * coil values. The first discrete input starting at \c usAddress must be + * stored at the LSB of the first byte in the buffer. If the requested number + * is not a multiple of eight the remaining bits should be set to zero. + * \param usAddress The starting address of the first discrete input. + * \param usNDiscrete Number of discrete input values. + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete ); + +/*! \ingroup modbus + *\brief These Modbus functions are called for user when Modbus run in Master Mode. + */ +eMBMasterReqErrCode +eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, + USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, + USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ); + +eMBException +eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); + +/* \ingroup modbus + * \brief These functions are interface for Modbus Master + */ +void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ); +UCHAR ucMBMasterGetDestAddress( void ); +void vMBMasterSetDestAddress( UCHAR Address ); +BOOL xMBMasterGetCBRunInMasterMode( void ); +void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ); +USHORT usMBMasterGetPDUSndLength( void ); +void vMBMasterSetPDUSndLength( USHORT SendPDULength ); +void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ); +void vMBMasterRequestSetType( BOOL xIsBroadcast ); +eMBMasterTimerMode xMBMasterGetCurTimerMode( void ); +BOOL xMBMasterRequestIsBroadcast( void ); +eMBMasterErrorEventType eMBMasterGetErrorType( void ); +void vMBMasterSetErrorType( eMBMasterErrorEventType errorType ); +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ); + +/* ----------------------- Callback -----------------------------------------*/ + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mbconfig.h b/components/freemodbus/modbus/include/mbconfig.h new file mode 100644 index 000000000..f32be6c23 --- /dev/null +++ b/components/freemodbus/modbus/include/mbconfig.h @@ -0,0 +1,170 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbconfig.h,v 1.15 2010/06/06 13:54:40 wolti Exp $ + * $Id: mbconfig.h,v 1.60 2013/08/13 21:19:55 Armink Add Master Functions $ + */ + +#ifndef _MB_CONFIG_H +#define _MB_CONFIG_H + +#include "sdkconfig.h" // for KConfig options + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif +/* ----------------------- Defines ------------------------------------------*/ +/*! \defgroup modbus_cfg Modbus Configuration + * + * Most modules in the protocol stack are completly optional and can be + * excluded. This is specially important if target resources are very small + * and program memory space should be saved.
+ * + * All of these settings are available in the file mbconfig.h + */ +/*! \addtogroup modbus_cfg + * @{ + */ +/*! \brief If Modbus Master ASCII support is enabled. */ +#define MB_MASTER_ASCII_ENABLED ( CONFIG_FMB_COMM_MODE_ASCII_EN ) +/*! \brief If Modbus Master RTU support is enabled. */ +#define MB_MASTER_RTU_ENABLED ( CONFIG_FMB_COMM_MODE_RTU_EN ) +/*! \brief If Modbus Master TCP support is enabled. */ +#define MB_MASTER_TCP_ENABLED ( CONFIG_FMB_COMM_MODE_TCP_EN ) +/*! \brief If Modbus Slave ASCII support is enabled. */ +#define MB_SLAVE_ASCII_ENABLED ( CONFIG_FMB_COMM_MODE_ASCII_EN ) +/*! \brief If Modbus Slave RTU support is enabled. */ +#define MB_SLAVE_RTU_ENABLED ( CONFIG_FMB_COMM_MODE_RTU_EN ) +/*! \brief If Modbus Slave TCP support is enabled. */ +#define MB_TCP_ENABLED ( CONFIG_FMB_COMM_MODE_TCP_EN ) + +#if !CONFIG_FMB_COMM_MODE_ASCII_EN && !CONFIG_FMB_COMM_MODE_RTU_EN && !MB_MASTER_TCP_ENABLED && !MB_TCP_ENABLED +#error "None of Modbus communication mode is enabled. Please enable one of (ASCII, RTU, TCP) mode in Kconfig." +#endif + +/*! \brief This option defines the number of data bits per ASCII character. + * + * A parity bit is added before the stop bit which keeps the actual byte size at 10 bits. + */ +#ifdef CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB +#define MB_ASCII_BITS_PER_SYMB ( CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB ) +#endif + +/*! \brief The character timeout value for Modbus ASCII. + * + * The character timeout value is not fixed for Modbus ASCII and is therefore + * a configuration option. It should be set to the maximum expected delay + * time of the network. + */ +#ifdef CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS +#define MB_ASCII_TIMEOUT_MS ( CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS ) +#endif + +/*! \brief Timeout to wait in ASCII prior to enabling transmitter. + * + * If defined the function calls vMBPortSerialDelay with the argument + * MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS to allow for a delay before + * the serial transmitter is enabled. This is required because some + * targets are so fast that there is no time between receiving and + * transmitting the frame. If the master is to slow with enabling its + * receiver then he will not receive the response correctly. + */ +#ifndef MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS +#define MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ( 0 ) +#endif + +/*! \brief Maximum number of Modbus functions codes the protocol stack + * should support. + * + * The maximum number of supported Modbus functions must be greater than + * the sum of all enabled functions in this file and custom function + * handlers. If set to small adding more functions will fail. + */ +#define MB_FUNC_HANDLERS_MAX ( 16 ) + +/*! \brief Number of bytes which should be allocated for the Report Slave ID + * command. + * + * This number limits the maximum size of the additional segment in the + * report slave id function. See eMBSetSlaveID( ) for more information on + * how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED + * is set to 1. + */ +#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 ) + +/*! \brief If the Report Slave ID function should be enabled. */ +#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT ) + +/*! \brief If the Read Input Registers function should be enabled. */ +#define MB_FUNC_READ_INPUT_ENABLED ( 1 ) + +/*! \brief If the Read Holding Registers function should be enabled. */ +#define MB_FUNC_READ_HOLDING_ENABLED ( 1 ) + +/*! \brief If the Write Single Register function should be enabled. */ +#define MB_FUNC_WRITE_HOLDING_ENABLED ( 1 ) + +/*! \brief If the Write Multiple registers function should be enabled. */ +#define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 ) + +/*! \brief If the Read Coils function should be enabled. */ +#define MB_FUNC_READ_COILS_ENABLED ( 1 ) + +/*! \brief If the Write Coils function should be enabled. */ +#define MB_FUNC_WRITE_COIL_ENABLED ( 1 ) + +/*! \brief If the Write Multiple Coils function should be enabled. */ +#define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED ( 1 ) + +/*! \brief If the Read Discrete Inputs function should be enabled. */ +#define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED ( 1 ) + +/*! \brief If the Read/Write Multiple Registers function should be enabled. */ +#define MB_FUNC_READWRITE_HOLDING_ENABLED ( 1 ) + +/*! \brief Check the option to place timer handler into IRAM */ +#define MB_PORT_TIMER_ISR_IN_IRAM ( CONFIG_FMB_TIMER_ISR_IN_IRAM ) + +/*! @} */ +#ifdef __cplusplus + PR_END_EXTERN_C +#endif + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +/*! \brief If master send a broadcast frame, the master will wait time of convert to delay, + * then master can send other frame */ +#define MB_MASTER_DELAY_MS_CONVERT ( CONFIG_FMB_MASTER_DELAY_MS_CONVERT ) +/*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave. + * And if slave is not respond in this time,the master will process this timeout error. + * Then master can send other frame */ +#define MB_MASTER_TIMEOUT_MS_RESPOND ( CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND ) +/*! \brief The total slaves in Modbus Master system. + * \note : The slave ID must be continuous from 1.*/ +#define MB_MASTER_TOTAL_SLAVE_NUM ( 247 ) +#endif + +#endif diff --git a/components/freemodbus/modbus/include/mbframe.h b/components/freemodbus/modbus/include/mbframe.h new file mode 100644 index 000000000..9dbfc394a --- /dev/null +++ b/components/freemodbus/modbus/include/mbframe.h @@ -0,0 +1,103 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbframe.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_FRAME_H +#define _MB_FRAME_H + +#include "port.h" + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/*! + * Constants which defines the format of a modbus frame. The example is + * shown for a Modbus RTU/ASCII frame. Note that the Modbus PDU is not + * dependent on the underlying transport. + * + * + * <------------------------ MODBUS SERIAL LINE PDU (1) -------------------> + * <----------- MODBUS PDU (1') ----------------> + * +-----------+---------------+----------------------------+-------------+ + * | Address | Function Code | Data | CRC/LRC | + * +-----------+---------------+----------------------------+-------------+ + * | | | | + * (2) (3/2') (3') (4) + * + * (1) ... MB_SER_PDU_SIZE_MAX = 256 + * (2) ... MB_SER_PDU_ADDR_OFF = 0 + * (3) ... MB_SER_PDU_PDU_OFF = 1 + * (4) ... MB_SER_PDU_SIZE_CRC = 2 + * + * (1') ... MB_PDU_SIZE_MAX = 253 + * (2') ... MB_PDU_FUNC_OFF = 0 + * (3') ... MB_PDU_DATA_OFF = 1 + * + */ + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_SIZE_MAX 253 /*!< Maximum size of a PDU. */ +#define MB_PDU_SIZE_MIN 1 /*!< Function Code */ +#define MB_PDU_FUNC_OFF 0 /*!< Offset of function code in PDU. */ +#define MB_PDU_DATA_OFF 1 /*!< Offset for response data in PDU. */ + +#define MB_SER_PDU_SIZE_MAX MB_SERIAL_BUF_SIZE /*!< Maximum size of a Modbus frame. */ +#define MB_SER_PDU_SIZE_LRC 1 /*!< Size of LRC field in PDU. */ +#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */ +#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */ +#define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */ + +#define MB_TCP_TID 0 +#define MB_TCP_PID 2 +#define MB_TCP_LEN 4 +#define MB_TCP_UID 6 +#define MB_TCP_FUNC 7 + +#define MB_TCP_PSEUDO_ADDRESS 255 + +/* ----------------------- Prototypes 0-------------------------------------*/ +typedef void ( *pvMBFrameStart ) ( void ); + +typedef void ( *pvMBFrameStop ) ( void ); + +typedef eMBErrorCode( *peMBFrameReceive ) ( UCHAR * pucRcvAddress, + UCHAR ** pucFrame, + USHORT * pusLength ); + +typedef eMBErrorCode( *peMBFrameSend ) ( UCHAR slaveAddress, + const UCHAR * pucFrame, + USHORT usLength ); + +typedef void( *pvMBFrameClose ) ( void ); + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mbfunc.h b/components/freemodbus/modbus/include/mbfunc.h new file mode 100644 index 000000000..aea14f759 --- /dev/null +++ b/components/freemodbus/modbus/include/mbfunc.h @@ -0,0 +1,80 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfunc.h,v 1.12 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_FUNC_H +#define _MB_FUNC_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif +#if MB_FUNC_OTHER_REP_SLAVEID_BUF > 0 + eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_READ_INPUT_ENABLED > 0 +eMBException eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_READ_HOLDING_ENABLED > 0 +eMBException eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 +eMBException eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 +eMBException eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_READ_COILS_ENABLED > 0 +eMBException eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_WRITE_COIL_ENABLED > 0 +eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 +eMBException eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 +eMBException eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 +eMBException eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +#endif + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mbport.h b/components/freemodbus/modbus/include/mbport.h new file mode 100644 index 000000000..8dfe8b7ca --- /dev/null +++ b/components/freemodbus/modbus/include/mbport.h @@ -0,0 +1,247 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbport.h,v 1.19 2010/06/06 13:54:40 wolti Exp $ + */ + +#ifndef _MB_PORT_H +#define _MB_PORT_H + +#include "mbconfig.h" // for options + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +#if CONFIG_UART_ISR_IN_IRAM +#define MB_PORT_SERIAL_ISR_FLAG ESP_INTR_FLAG_IRAM +#else +#define MB_PORT_SERIAL_ISR_FLAG ESP_INTR_FLAG_LOWMED +#endif + +#if MB_PORT_TIMER_ISR_IN_IRAM +#define MB_PORT_ISR_ATTR IRAM_ATTR +#define MB_PORT_TIMER_ISR_FLAG ESP_INTR_FLAG_IRAM +#else +#define MB_PORT_ISR_ATTR +#define MB_PORT_TIMER_ISR_FLAG ESP_INTR_FLAG_LOWMED +#endif + +/* ----------------------- Type definitions ---------------------------------*/ + +typedef enum +{ + EV_READY = 0x01, /*!< Startup finished. */ + EV_FRAME_RECEIVED = 0x02, /*!< Frame received. */ + EV_EXECUTE = 0x04, /*!< Execute function. */ + EV_FRAME_SENT = 0x08, /*!< Frame sent. */ + EV_FRAME_TRANSMIT = 0x10 /*!< Frame transmit. */ +} eMBEventType; + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +typedef enum { + EV_MASTER_NO_EVENT = 0x0000, + EV_MASTER_READY = 0x0001, /*!< Startup finished. */ + EV_MASTER_FRAME_RECEIVED = 0x0002, /*!< Frame received. */ + EV_MASTER_EXECUTE = 0x0004, /*!< Execute function. */ + EV_MASTER_FRAME_SENT = 0x0008, /*!< Frame sent. */ + EV_MASTER_FRAME_TRANSMIT = 0x0010, /*!< Frame transmission. */ + EV_MASTER_ERROR_PROCESS = 0x0020, /*!< Frame error process. */ + EV_MASTER_PROCESS_SUCCESS = 0x0040, /*!< Request process success. */ + EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0080, /*!< Request respond timeout. */ + EV_MASTER_ERROR_RECEIVE_DATA = 0x0100, /*!< Request receive data error. */ + EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0200 /*!< Request execute function error. */ +} eMBMasterEventType; + +typedef enum { + EV_ERROR_INIT, /*!< No error, initial state. */ + EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */ + EV_ERROR_RECEIVE_DATA, /*!< Receive frame data error. */ + EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */ + EV_ERROR_OK /*!< No error, processing completed. */ +} eMBMasterErrorEventType; +#endif + +/*! \ingroup modbus + * \brief Parity used for characters in serial mode. + * + * The parity which should be applied to the characters sent over the serial + * link. Please note that this values are actually passed to the porting + * layer and therefore not all parity modes might be available. + */ +typedef enum +{ + MB_PAR_NONE, /*!< No parity. */ + MB_PAR_ODD, /*!< Odd parity. */ + MB_PAR_EVEN /*!< Even parity. */ +} eMBParity; + +/* ----------------------- Supporting functions -----------------------------*/ +BOOL xMBPortEventInit( void ); + +BOOL xMBPortEventPost( eMBEventType eEvent ); + +BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent ); + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +BOOL xMBMasterPortEventInit( void ); + +BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent ); + +BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent ); + +eMBMasterEventType + xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout); + +void vMBMasterOsResInit( void ); + +BOOL xMBMasterRunResTake( LONG time ); + +void vMBMasterRunResRelease( void ); +#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +/* ----------------------- Serial port functions ----------------------------*/ + +BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, + UCHAR ucDataBits, eMBParity eParity ); + +void vMBPortClose( void ); + +void xMBPortSerialClose( void ); + +void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); + +BOOL xMBPortSerialGetByte( CHAR * pucByte ); + +BOOL xMBPortSerialPutByte( CHAR ucByte ); + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED +BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, + UCHAR ucDataBits, eMBParity eParity ); + +void vMBMasterPortClose( void ); + +void xMBMasterPortSerialClose( void ); + +void vMBMasterPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); + +BOOL xMBMasterPortSerialGetByte( CHAR * pucByte ); + +BOOL xMBMasterPortSerialPutByte( CHAR ucByte ); +#endif + +/* ----------------------- Timers functions ---------------------------------*/ +BOOL xMBPortTimersInit( USHORT usTimeOut50us ); + +void xMBPortTimersClose( void ); + +void vMBPortTimersEnable( void ); + +void vMBPortTimersDisable( void ); + +void vMBPortTimersDelay( USHORT usTimeOutMS ); + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +BOOL xMBMasterPortTimersInit( USHORT usTimeOut50us ); + +void xMBMasterPortTimersClose( void ); + +void vMBMasterPortTimersT35Enable( void ); + +void vMBMasterPortTimersConvertDelayEnable( void ); + +void vMBMasterPortTimersRespondTimeoutEnable( void ); + +void vMBMasterPortTimersDisable( void ); + + +/* ----------------- Callback for the master error process ------------------*/ +void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterCBRequestSuccess( void ); +#endif +/* ----------------------- Callback for the protocol stack ------------------*/ +/*! + * \brief Callback function for the porting layer when a new byte is + * available. + * + * Depending upon the mode this callback function is used by the RTU or + * ASCII transmission layers. In any case a call to xMBPortSerialGetByte() + * must immediately return a new character. + * + * \return TRUE if a event was posted to the queue because + * a new byte was received. The port implementation should wake up the + * tasks which are currently blocked on the eventqueue. + */ +extern BOOL( *pxMBFrameCBByteReceived ) ( void ); + +extern BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); + +extern BOOL( *pxMBPortCBTimerExpired ) ( void ); + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +extern BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); + +extern BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); + +extern BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); +#endif +/* ----------------------- TCP port functions -------------------------------*/ +#if MB_TCP_ENABLED +BOOL xMBTCPPortInit( USHORT usTCPPort ); + +void vMBTCPPortClose( void ); + +void vMBTCPPortDisable( void ); + +BOOL xMBTCPPortGetRequest( UCHAR **ppucMBTCPFrame, USHORT * usTCPLength ); + +BOOL xMBTCPPortSendResponse( UCHAR *pucMBTCPFrame, USHORT usTCPLength ); + +#endif + +#if MB_MASTER_TCP_ENABLED +BOOL xMBMasterTCPPortInit( USHORT usTCPPort ); + +void vMBMasterTCPPortClose( void ); + +void vMBMasterTCPPortDisable( void ); + +BOOL xMBMasterTCPPortGetRequest( UCHAR **ppucMBTCPFrame, USHORT * usTCPLength ); + +BOOL xMBMasterTCPPortSendResponse( UCHAR *pucMBTCPFrame, USHORT usTCPLength ); +#endif +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mbproto.h b/components/freemodbus/modbus/include/mbproto.h new file mode 100644 index 000000000..f84cb3edc --- /dev/null +++ b/components/freemodbus/modbus/include/mbproto.h @@ -0,0 +1,83 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbproto.h,v 1.14 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_PROTO_H +#define _MB_PROTO_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif +/* ----------------------- Defines ------------------------------------------*/ +#define MB_ADDRESS_BROADCAST ( 0 ) /*! Modbus broadcast address. */ +#define MB_ADDRESS_MIN ( 1 ) /*! Smallest possible slave address. */ +#define MB_ADDRESS_MAX ( 247 ) /*! Biggest possible slave address. */ +#define MB_FUNC_NONE ( 0 ) +#define MB_FUNC_READ_COILS ( 1 ) +#define MB_FUNC_READ_DISCRETE_INPUTS ( 2 ) +#define MB_FUNC_WRITE_SINGLE_COIL ( 5 ) +#define MB_FUNC_WRITE_MULTIPLE_COILS ( 15 ) +#define MB_FUNC_READ_HOLDING_REGISTER ( 3 ) +#define MB_FUNC_READ_INPUT_REGISTER ( 4 ) +#define MB_FUNC_WRITE_REGISTER ( 6 ) +#define MB_FUNC_WRITE_MULTIPLE_REGISTERS ( 16 ) +#define MB_FUNC_READWRITE_MULTIPLE_REGISTERS ( 23 ) +#define MB_FUNC_DIAG_READ_EXCEPTION ( 7 ) +#define MB_FUNC_DIAG_DIAGNOSTIC ( 8 ) +#define MB_FUNC_DIAG_GET_COM_EVENT_CNT ( 11 ) +#define MB_FUNC_DIAG_GET_COM_EVENT_LOG ( 12 ) +#define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 ) +#define MB_FUNC_ERROR ( 128u ) +/* ----------------------- Type definitions ---------------------------------*/ + typedef enum +{ + MB_EX_NONE = 0x00, + MB_EX_ILLEGAL_FUNCTION = 0x01, + MB_EX_ILLEGAL_DATA_ADDRESS = 0x02, + MB_EX_ILLEGAL_DATA_VALUE = 0x03, + MB_EX_SLAVE_DEVICE_FAILURE = 0x04, + MB_EX_ACKNOWLEDGE = 0x05, + MB_EX_SLAVE_BUSY = 0x06, + MB_EX_MEMORY_PARITY_ERROR = 0x08, + MB_EX_GATEWAY_PATH_FAILED = 0x0A, + MB_EX_GATEWAY_TGT_FAILED = 0x0B +} eMBException; + +typedef eMBException( *pxMBFunctionHandler ) ( UCHAR * pucFrame, USHORT * pusLength ); + +typedef struct +{ + UCHAR ucFunctionCode; + pxMBFunctionHandler pxHandler; +} xMBFunctionHandler; + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/include/mbutils.h b/components/freemodbus/modbus/include/mbutils.h new file mode 100644 index 000000000..61495751d --- /dev/null +++ b/components/freemodbus/modbus/include/mbutils.h @@ -0,0 +1,108 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbutils.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_UTILS_H +#define _MB_UTILS_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif +/*! \defgroup modbus_utils Utilities + * + * This module contains some utility functions which can be used by + * the application. It includes some special functions for working with + * bitfields backed by a character array buffer. + * + */ +/*! \addtogroup modbus_utils + * @{ + */ +/*! \brief Function to set bits in a byte buffer. + * + * This function allows the efficient use of an array to implement bitfields. + * The array used for storing the bits must always be a multiple of two + * bytes. Up to eight bits can be set or cleared in one operation. + * + * \param ucByteBuf A buffer where the bit values are stored. Must be a + * multiple of 2 bytes. No length checking is performed and if + * usBitOffset / 8 is greater than the size of the buffer memory contents + * is overwritten. + * \param usBitOffset The starting address of the bits to set. The first + * bit has the offset 0. + * \param ucNBits Number of bits to modify. The value must always be smaller + * than 8. + * \param ucValues Thew new values for the bits. The value for the first bit + * starting at usBitOffset is the LSB of the value + * ucValues + * + * \code + * ucBits[2] = {0, 0}; + * + * // Set bit 4 to 1 (read: set 1 bit starting at bit offset 4 to value 1) + * xMBUtilSetBits( ucBits, 4, 1, 1 ); + * + * // Set bit 7 to 1 and bit 8 to 0. + * xMBUtilSetBits( ucBits, 7, 2, 0x01 ); + * + * // Set bits 8 - 11 to 0x05 and bits 12 - 15 to 0x0A; + * xMBUtilSetBits( ucBits, 8, 8, 0x5A); + * \endcode + */ +void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, + UCHAR ucNBits, UCHAR ucValues ); + +/*! \brief Function to read bits in a byte buffer. + * + * This function is used to extract up bit values from an array. Up to eight + * bit values can be extracted in one step. + * + * \param ucByteBuf A buffer where the bit values are stored. + * \param usBitOffset The starting address of the bits to set. The first + * bit has the offset 0. + * \param ucNBits Number of bits to modify. The value must always be smaller + * than 8. + * + * \code + * UCHAR ucBits[2] = {0, 0}; + * UCHAR ucResult; + * + * // Extract the bits 3 - 10. + * ucResult = xMBUtilGetBits( ucBits, 3, 8 ); + * \endcode + */ +UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, + UCHAR ucNBits ); + +/*! @} */ + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/mb.c b/components/freemodbus/modbus/mb.c new file mode 100644 index 000000000..90fef6522 --- /dev/null +++ b/components/freemodbus/modbus/mb.c @@ -0,0 +1,428 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mb.c,v 1.28 2010/06/06 13:54:40 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbconfig.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbfunc.h" +#include "mbport.h" + +#if MB_SLAVE_RTU_ENABLED +#include "mbrtu.h" +#endif +#if MB_SLAVE_ASCII_ENABLED +#include "mbascii.h" +#endif +#if MB_TCP_ENABLED +#include "mbtcp.h" +#endif + +#ifndef MB_PORT_HAS_CLOSE +#define MB_PORT_HAS_CLOSE 0 +#endif + +/* ----------------------- Static variables ---------------------------------*/ + +static UCHAR ucMBAddress; +static eMBMode eMBCurrentMode; + +volatile UCHAR ucMbSlaveBuf[MB_SERIAL_BUF_SIZE]; + +static enum +{ + STATE_ENABLED, + STATE_DISABLED, + STATE_NOT_INITIALIZED +} eMBState = STATE_NOT_INITIALIZED; + +/* Functions pointer which are initialized in eMBInit( ). Depending on the + * mode (RTU or ASCII) the are set to the correct implementations. + */ +static peMBFrameSend peMBFrameSendCur; +static pvMBFrameStart pvMBFrameStartCur; +static pvMBFrameStop pvMBFrameStopCur; +static peMBFrameReceive peMBFrameReceiveCur; +static pvMBFrameClose pvMBFrameCloseCur; + +/* Callback functions required by the porting layer. They are called when + * an external event has happend which includes a timeout or the reception + * or transmission of a character. + */ +BOOL( *pxMBFrameCBByteReceived ) ( void ); +BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); +BOOL( *pxMBPortCBTimerExpired ) ( void ); +BOOL( *pxMBFrameCBReceiveFSMCur ) ( void ); +BOOL( *pxMBFrameCBTransmitFSMCur ) ( void ); + +/* An array of Modbus functions handlers which associates Modbus function + * codes with implementing functions. + */ +static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = { +#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 + {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, +#endif +#if MB_FUNC_READ_INPUT_ENABLED > 0 + {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister}, +#endif +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister}, +#endif +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_READ_COILS_ENABLED > 0 + {MB_FUNC_READ_COILS, eMBFuncReadCoils}, +#endif +#if MB_FUNC_WRITE_COIL_ENABLED > 0 + {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils}, +#endif +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 + {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs}, +#endif +}; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + /* check preconditions */ + if( ( ucSlaveAddress == MB_ADDRESS_BROADCAST ) || + ( ucSlaveAddress < MB_ADDRESS_MIN ) || ( ucSlaveAddress > MB_ADDRESS_MAX ) ) + { + eStatus = MB_EINVAL; + } + else + { + ucMBAddress = ucSlaveAddress; + + switch ( eMode ) + { +#if MB_SLAVE_RTU_ENABLED > 0 + case MB_RTU: + pvMBFrameStartCur = eMBRTUStart; + pvMBFrameStopCur = eMBRTUStop; + peMBFrameSendCur = eMBRTUSend; + peMBFrameReceiveCur = eMBRTUReceive; + pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; + pxMBFrameCBByteReceived = xMBRTUReceiveFSM; + pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM; + pxMBPortCBTimerExpired = xMBRTUTimerT35Expired; + + eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity ); + break; +#endif +#if MB_SLAVE_ASCII_ENABLED > 0 + case MB_ASCII: + pvMBFrameStartCur = eMBASCIIStart; + pvMBFrameStopCur = eMBASCIIStop; + peMBFrameSendCur = eMBASCIISend; + peMBFrameReceiveCur = eMBASCIIReceive; + pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; + pxMBFrameCBByteReceived = xMBASCIIReceiveFSM; + pxMBFrameCBTransmitterEmpty = xMBASCIITransmitFSM; + pxMBPortCBTimerExpired = xMBASCIITimerT1SExpired; + + eStatus = eMBASCIIInit( ucMBAddress, ucPort, ulBaudRate, eParity ); + break; +#endif + default: + eStatus = MB_EINVAL; + } + + if( eStatus == MB_ENOERR ) + { + if( !xMBPortEventInit( ) ) + { + /* port dependent event module initalization failed. */ + eStatus = MB_EPORTERR; + } + else + { + eMBCurrentMode = eMode; + eMBState = STATE_DISABLED; + } + } + } + return eStatus; +} + +#if MB_TCP_ENABLED > 0 +eMBErrorCode +eMBTCPInit( USHORT ucTCPPort ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) + { + eMBState = STATE_DISABLED; + } + else if( !xMBPortEventInit( ) ) + { + /* Port dependent event module initalization failed. */ + eStatus = MB_EPORTERR; + } + else + { + pvMBFrameStartCur = eMBTCPStart; + pvMBFrameStopCur = eMBTCPStop; + peMBFrameReceiveCur = eMBTCPReceive; + peMBFrameSendCur = eMBTCPSend; + pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL; + ucMBAddress = MB_TCP_PSEUDO_ADDRESS; + eMBCurrentMode = MB_TCP; + eMBState = STATE_DISABLED; + } + return eStatus; +} +#endif + +eMBErrorCode +eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler ) +{ + int i; + eMBErrorCode eStatus; + + if( ( 0 < ucFunctionCode ) && ( ucFunctionCode <= MB_FUNC_CODE_MAX ) ) + { + ENTER_CRITICAL_SECTION( ); + if( pxHandler != NULL ) + { + for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) + { + if( ( xFuncHandlers[i].pxHandler == NULL ) || + ( xFuncHandlers[i].pxHandler == pxHandler ) ) + { + xFuncHandlers[i].ucFunctionCode = ucFunctionCode; + xFuncHandlers[i].pxHandler = pxHandler; + break; + } + } + eStatus = ( i != MB_FUNC_HANDLERS_MAX ) ? MB_ENOERR : MB_ENORES; + } + else + { + for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) + { + if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) + { + xFuncHandlers[i].ucFunctionCode = 0; + xFuncHandlers[i].pxHandler = NULL; + break; + } + } + /* Remove can't fail. */ + eStatus = MB_ENOERR; + } + EXIT_CRITICAL_SECTION( ); + } + else + { + eStatus = MB_EINVAL; + } + return eStatus; +} + + +eMBErrorCode +eMBClose( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + if( pvMBFrameCloseCur != NULL ) + { + pvMBFrameCloseCur( ); + } + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBEnable( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + /* Activate the protocol stack. */ + pvMBFrameStartCur( ); + eMBState = STATE_ENABLED; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBDisable( void ) +{ + eMBErrorCode eStatus; + + if( eMBState == STATE_ENABLED ) + { + pvMBFrameStopCur( ); + eMBState = STATE_DISABLED; + eStatus = MB_ENOERR; + } + else if( eMBState == STATE_DISABLED ) + { + eStatus = MB_ENOERR; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBPoll( void ) +{ + static UCHAR *ucMBFrame = NULL; + static UCHAR ucRcvAddress; + static UCHAR ucFunctionCode; + static USHORT usLength; + static eMBException eException; + + int i; + eMBErrorCode eStatus = MB_ENOERR; + eMBEventType eEvent; + + /* Check if the protocol stack is ready. */ + if( eMBState != STATE_ENABLED ) + { + return MB_EILLSTATE; + } + + /* Check if there is a event available. If not return control to caller. + * Otherwise we will handle the event. */ + if( xMBPortEventGet( &eEvent ) == TRUE ) + { + switch ( eEvent ) + { + case EV_READY: + ESP_LOGD(MB_PORT_TAG, "%s:EV_READY", __func__); + break; + + case EV_FRAME_RECEIVED: + ESP_LOGD(MB_PORT_TAG, "EV_FRAME_RECEIVED"); + eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); + if( eStatus == MB_ENOERR ) + { + /* Check if the frame is for us. If not ignore the frame. */ + if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) ) + { + ( void )xMBPortEventPost( EV_EXECUTE ); + ESP_LOG_BUFFER_HEX_LEVEL(MB_PORT_TAG, &ucMBFrame[MB_PDU_FUNC_OFF], usLength, ESP_LOG_DEBUG); + } + } + break; + + case EV_EXECUTE: + if ( !ucMBFrame ) { + return MB_EILLSTATE; + } + ESP_LOGD(MB_PORT_TAG, "%s:EV_EXECUTE", __func__); + ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; + eException = MB_EX_ILLEGAL_FUNCTION; + for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) + { + /* No more function handlers registered. Abort. */ + if( xFuncHandlers[i].ucFunctionCode == 0 ) + { + break; + } + if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) + { + eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); + break; + } + } + + /* If the request was not sent to the broadcast address we + * return a reply. */ + if( ucRcvAddress != MB_ADDRESS_BROADCAST ) + { + if( eException != MB_EX_NONE ) + { + /* An exception occurred. Build an error frame. */ + usLength = 0; + ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR ); + ucMBFrame[usLength++] = eException; + } + if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ) + { + vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ); + } + eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength ); + } + break; + + case EV_FRAME_TRANSMIT: + ESP_LOGD(MB_PORT_TAG, "%s:EV_FRAME_TRANSMIT", __func__); + break; + + case EV_FRAME_SENT: + ESP_LOGD(MB_PORT_TAG, "%s:EV_FRAME_SENT", __func__); + break; + + default: + break; + } + } + return eStatus; +} diff --git a/components/freemodbus/modbus/mb_m.c b/components/freemodbus/modbus/mb_m.c new file mode 100644 index 000000000..5dc3a7968 --- /dev/null +++ b/components/freemodbus/modbus/mb_m.c @@ -0,0 +1,546 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ + +#include "mb_m.h" +#include "mbconfig.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbfunc.h" + +#include "mbport.h" +#if MB_MASTER_RTU_ENABLED +#include "mbrtu.h" +#endif +#if MB_MASTER_ASCII_ENABLED +#include "mbascii.h" +#endif +#if MB_MASTER_TCP_ENABLED +#include "mbtcp.h" +#include "mbtcp_m.h" +#endif + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED + +#ifndef MB_PORT_HAS_CLOSE +#define MB_PORT_HAS_CLOSE 1 +#endif + +/* ----------------------- Static variables ---------------------------------*/ + +static UCHAR ucMBMasterDestAddress; +static BOOL xMBRunInMasterMode = FALSE; +static volatile eMBMasterErrorEventType eMBMasterCurErrorType; +static volatile USHORT usMasterSendPDULength; +static volatile eMBMode eMBMasterCurrentMode; + +/*------------------------ Shared variables ---------------------------------*/ + +volatile UCHAR ucMasterSndBuf[MB_SERIAL_BUF_SIZE]; +volatile UCHAR ucMasterRcvBuf[MB_SERIAL_BUF_SIZE]; +volatile eMBMasterTimerMode eMasterCurTimerMode; +volatile BOOL xFrameIsBroadcast = FALSE; + +static enum +{ + STATE_ENABLED, + STATE_DISABLED, + STATE_NOT_INITIALIZED +} eMBState = STATE_NOT_INITIALIZED; + +/* Functions pointer which are initialized in eMBInit( ). Depending on the + * mode (RTU or ASCII) the are set to the correct implementations. + * Using for Modbus Master,Add by Armink 20130813 + */ +static peMBFrameSend peMBMasterFrameSendCur; +static pvMBFrameStart pvMBMasterFrameStartCur; +static pvMBFrameStop pvMBMasterFrameStopCur; +static peMBFrameReceive peMBMasterFrameReceiveCur; +static pvMBFrameClose pvMBMasterFrameCloseCur; + +/* Callback functions required by the porting layer. They are called when + * an external event has happend which includes a timeout or the reception + * or transmission of a character. + * Using for Modbus Master,Add by Armink 20130813 + */ +BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); + +BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); + +BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); + +BOOL( *pxMBMasterFrameCBReceiveFSMCur ) ( void ); + +BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void ); + +/* An array of Modbus functions handlers which associates Modbus function + * codes with implementing functions. + */ +static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = { +#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 + {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, +#endif +#if MB_FUNC_READ_INPUT_ENABLED > 0 + {MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister}, +#endif +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + {MB_FUNC_READ_HOLDING_REGISTER, eMBMasterFuncReadHoldingRegister}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBMasterFuncWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_REGISTER, eMBMasterFuncWriteHoldingRegister}, +#endif +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBMasterFuncReadWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_READ_COILS_ENABLED > 0 + {MB_FUNC_READ_COILS, eMBMasterFuncReadCoils}, +#endif +#if MB_FUNC_WRITE_COIL_ENABLED > 0 + {MB_FUNC_WRITE_SINGLE_COIL, eMBMasterFuncWriteCoil}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_COILS, eMBMasterFuncWriteMultipleCoils}, +#endif +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 + {MB_FUNC_READ_DISCRETE_INPUTS, eMBMasterFuncReadDiscreteInputs}, +#endif +}; + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_TCP_ENABLED > 0 +eMBErrorCode +eMBMasterTCPInit( USHORT ucTCPPort ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( ( eStatus = eMBMasterTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) { + eMBState = STATE_DISABLED; + } + else if( !xMBMasterPortEventInit( ) ) { + /* Port dependent event module initialization failed. */ + eStatus = MB_EPORTERR; + } else { + pvMBMasterFrameStartCur = eMBMasterTCPStart; + pvMBMasterFrameStopCur = eMBMasterTCPStop; + peMBMasterFrameReceiveCur = eMBMasterTCPReceive; + peMBMasterFrameSendCur = eMBMasterTCPSend; + pxMBMasterPortCBTimerExpired = xMBMasterTCPTimerExpired; + pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterTCPPortClose : NULL; + ucMBMasterDestAddress = MB_TCP_PSEUDO_ADDRESS; + eMBMasterCurrentMode = MB_TCP; + eMBState = STATE_DISABLED; + + // initialize the OS resource for modbus master. + vMBMasterOsResInit(); + if( xMBMasterPortTimersInit( MB_MASTER_TIMEOUT_MS_RESPOND * MB_TIMER_TICS_PER_MS ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + + } + return eStatus; +} +#endif + +eMBErrorCode +eMBMasterSerialInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + switch (eMode) + { +#if MB_MASTER_RTU_ENABLED > 0 + case MB_RTU: + pvMBMasterFrameStartCur = eMBMasterRTUStart; + pvMBMasterFrameStopCur = eMBMasterRTUStop; + peMBMasterFrameSendCur = eMBMasterRTUSend; + peMBMasterFrameReceiveCur = eMBMasterRTUReceive; + pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; + pxMBMasterFrameCBByteReceived = xMBMasterRTUReceiveFSM; + pxMBMasterFrameCBTransmitterEmpty = xMBMasterRTUTransmitFSM; + pxMBMasterPortCBTimerExpired = xMBMasterRTUTimerExpired; + eMBMasterCurrentMode = MB_ASCII; + + eStatus = eMBMasterRTUInit(ucPort, ulBaudRate, eParity); + break; +#endif +#if MB_MASTER_ASCII_ENABLED > 0 + case MB_ASCII: + pvMBMasterFrameStartCur = eMBMasterASCIIStart; + pvMBMasterFrameStopCur = eMBMasterASCIIStop; + peMBMasterFrameSendCur = eMBMasterASCIISend; + peMBMasterFrameReceiveCur = eMBMasterASCIIReceive; + pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; + pxMBMasterFrameCBByteReceived = xMBMasterASCIIReceiveFSM; + pxMBMasterFrameCBTransmitterEmpty = xMBMasterASCIITransmitFSM; + pxMBMasterPortCBTimerExpired = xMBMasterASCIITimerT1SExpired; + eMBMasterCurrentMode = MB_RTU; + + eStatus = eMBMasterASCIIInit(ucPort, ulBaudRate, eParity ); + break; +#endif + default: + eStatus = MB_EINVAL; + break; + } + + if (eStatus == MB_ENOERR) + { + if (!xMBMasterPortEventInit()) + { + /* port dependent event module initalization failed. */ + eStatus = MB_EPORTERR; + } + else + { + eMBState = STATE_DISABLED; + } + /* initialize the OS resource for modbus master. */ + vMBMasterOsResInit(); + } + return eStatus; +} + +eMBErrorCode +eMBMasterClose( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + if( pvMBMasterFrameCloseCur != NULL ) + { + pvMBMasterFrameCloseCur( ); + } + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBMasterEnable( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + /* Activate the protocol stack. */ + pvMBMasterFrameStartCur( ); + /* Release the resource, because it created in busy state */ + //vMBMasterRunResRelease( ); + eMBState = STATE_ENABLED; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBMasterDisable( void ) +{ + eMBErrorCode eStatus; + + if( eMBState == STATE_ENABLED ) + { + pvMBMasterFrameStopCur( ); + eMBState = STATE_DISABLED; + eStatus = MB_ENOERR; + } + else if( eMBState == STATE_DISABLED ) + { + eStatus = MB_ENOERR; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBMasterPoll( void ) +{ + static UCHAR *ucMBFrame = NULL; + static UCHAR ucRcvAddress; + static UCHAR ucFunctionCode; + static USHORT usLength; + static eMBException eException; + int i; + int j; + eMBErrorCode eStatus = MB_ENOERR; + eMBMasterEventType eEvent; + eMBMasterErrorEventType errorType; + + /* Check if the protocol stack is ready. */ + if( eMBState != STATE_ENABLED ) + { + return MB_EILLSTATE; + } + + /* Check if there is a event available. If not return control to caller. + * Otherwise we will handle the event. */ + if ( xMBMasterPortEventGet( &eEvent ) == TRUE ) + { + // In some cases it is possible that more than one event set + // together (even from one subset mask) than process them consistently + if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_READY ) ) { + ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__); + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_READY ); + } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) { + ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__); + /* Master is busy now. */ + vMBMasterGetPDUSndBuf( &ucMBFrame ); + ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); + eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() ); + if (eStatus != MB_ENOERR) + { + ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus ); + } + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ); + } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) { + ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ ); + ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT ); + } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) { + eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength); + + // Check if the frame is for us. If not ,send an error process event. + if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() ) + || ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) ) ) + { + ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus); + ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG); + ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); + } + else + { + vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); + ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).", + __func__, ucRcvAddress, eStatus); + } + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ); + } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) { + if ( !ucMBFrame ) + { + return MB_EILLSTATE; + } + ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__); + ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; + eException = MB_EX_ILLEGAL_FUNCTION; + /* If receive frame has exception. The receive function code highest bit is 1.*/ + if (ucFunctionCode & MB_FUNC_ERROR) + { + eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; + } else { + for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) + { + /* No more function handlers registered. Abort. */ + if (xMasterFuncHandlers[i].ucFunctionCode == 0) + { + break; + } + if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) + { + vMBMasterSetCBRunInMasterMode(TRUE); + /* If master request is broadcast, + * the master need execute function for all slave. + */ + if ( xMBMasterRequestIsBroadcast() ) + { + usLength = usMBMasterGetPDUSndLength(); + for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++) + { + vMBMasterSetDestAddress(j); + eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); + } + } + else + { + eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); + } + vMBMasterSetCBRunInMasterMode( FALSE ); + break; + } + } + } + /* If master has exception, will send error process event. Otherwise the master is idle.*/ + if ( eException != MB_EX_NONE ) + { + vMBMasterSetErrorType( EV_ERROR_EXECUTE_FUNCTION ); + ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + } + else + { + if ( eMBMasterGetErrorType( ) == EV_ERROR_INIT ) { + vMBMasterSetErrorType(EV_ERROR_OK); + ESP_LOGD( MB_PORT_TAG, "%s: set event EV_ERROR_OK", __func__ ); + ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + } + } + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_EXECUTE ); + } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ) ) { + ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ ); + /* Execute specified error process callback function. */ + errorType = eMBMasterGetErrorType( ); + vMBMasterGetPDUSndBuf( &ucMBFrame ); + switch ( errorType ) + { + case EV_ERROR_RESPOND_TIMEOUT: + vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ), + ucMBFrame, usMBMasterGetPDUSndLength( ) ); + break; + case EV_ERROR_RECEIVE_DATA: + vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ), + ucMBFrame, usMBMasterGetPDUSndLength( ) ); + break; + case EV_ERROR_EXECUTE_FUNCTION: + vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ), + ucMBFrame, usMBMasterGetPDUSndLength( ) ); + break; + case EV_ERROR_OK: + vMBMasterCBRequestSuccess( ); + break; + default: + ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType); + break; + } + vMBMasterSetErrorType( EV_ERROR_INIT ); + MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ); + vMBMasterRunResRelease( ); + } + if ( eEvent ) { + // Event processing is done, but some poll events still set then + // postpone its processing for next poll cycle (rare case). + ESP_LOGW( MB_PORT_TAG, "%s: Postpone event %x.", __func__, eEvent ); + ( void ) xMBMasterPortEventPost( eEvent ); + } + } else { + // Something went wrong and task unblocked but there are no any correct events set + ESP_LOGE( MB_PORT_TAG, "%s: Unexpected event triggered 0x%02x.", __func__, eEvent ); + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +// Get whether the Modbus Master is run in master mode. +BOOL xMBMasterGetCBRunInMasterMode( void ) +{ + return xMBRunInMasterMode; +} + +// Set whether the Modbus Master is run in master mode. +void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ) +{ + xMBRunInMasterMode = IsMasterMode; +} + +// Get Modbus Master send destination address. +UCHAR ucMBMasterGetDestAddress( void ) +{ + return ucMBMasterDestAddress; +} + +// Set Modbus Master send destination address. +void vMBMasterSetDestAddress( UCHAR Address ) +{ + ucMBMasterDestAddress = Address; +} + +// Get Modbus Master current error event type. +eMBMasterErrorEventType inline eMBMasterGetErrorType( void ) +{ + return eMBMasterCurErrorType; +} + +// Set Modbus Master current error event type. +void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType ) +{ + eMBMasterCurErrorType = errorType; +} + +/* Get Modbus Master send PDU's buffer address pointer.*/ +void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ) +{ + *pucFrame = ( UCHAR * ) &ucMasterSndBuf[MB_SER_PDU_PDU_OFF]; +} + +/* Set Modbus Master send PDU's buffer length.*/ +void vMBMasterSetPDUSndLength( USHORT SendPDULength ) +{ + usMasterSendPDULength = SendPDULength; +} + +/* Get Modbus Master send PDU's buffer length.*/ +USHORT usMBMasterGetPDUSndLength( void ) +{ + return usMasterSendPDULength; +} + +/* Set Modbus Master current timer mode.*/ +void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ) +{ + eMasterCurTimerMode = eMBTimerMode; +} + +/* Get Modbus Master current timer mode.*/ +eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void ) +{ + return eMasterCurTimerMode; +} + +/* The master request is broadcast? */ +BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void ) +{ + return xFrameIsBroadcast; +} + +/* The master request is broadcast? */ +void vMBMasterRequestSetType( BOOL xIsBroadcast ){ + xFrameIsBroadcast = xIsBroadcast; +} + +#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED diff --git a/components/freemodbus/modbus/rtu/mbcrc.c b/components/freemodbus/modbus/rtu/mbcrc.c new file mode 100644 index 000000000..1cd0a6ec8 --- /dev/null +++ b/components/freemodbus/modbus/rtu/mbcrc.c @@ -0,0 +1,103 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbcrc.c,v 1.7 2007/02/18 23:50:27 wolti Exp $ + */ + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" +#include "mbconfig.h" + +#if MB_MASTER_RTU_ENABLED || MB_SLAVE_RTU_ENABLED + +static const UCHAR aucCRCHi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40 +}; + +static const UCHAR aucCRCLo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, + 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, + 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, + 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, + 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, + 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, + 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, + 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40 +}; + +USHORT +usMBCRC16( UCHAR * pucFrame, USHORT usLen ) +{ + UCHAR ucCRCHi = 0xFF; + UCHAR ucCRCLo = 0xFF; + int iIndex; + + while( usLen-- ) + { + iIndex = ucCRCLo ^ *( pucFrame++ ); + ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] ); + ucCRCHi = aucCRCLo[iIndex]; + } + return ( USHORT )( ucCRCHi << 8 | ucCRCLo ); +} + +#endif diff --git a/components/freemodbus/modbus/rtu/mbcrc.h b/components/freemodbus/modbus/rtu/mbcrc.h new file mode 100644 index 000000000..db227763f --- /dev/null +++ b/components/freemodbus/modbus/rtu/mbcrc.h @@ -0,0 +1,36 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbcrc.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_CRC_H +#define _MB_CRC_H + +USHORT usMBCRC16( UCHAR * pucFrame, USHORT usLen ); + +#endif diff --git a/components/freemodbus/modbus/rtu/mbrtu.c b/components/freemodbus/modbus/rtu/mbrtu.c new file mode 100644 index 000000000..066fea3ee --- /dev/null +++ b/components/freemodbus/modbus/rtu/mbrtu.c @@ -0,0 +1,350 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu.c,v 1.18 2007/09/12 10:15:56 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbrtu.h" +#include "mbframe.h" + +#include "mbcrc.h" +#include "mbport.h" + +#if MB_SLAVE_RTU_ENABLED > 0 + +/* ----------------------- Type definitions ---------------------------------*/ +typedef enum +{ + STATE_RX_INIT, /*!< Receiver is in initial state. */ + STATE_RX_IDLE, /*!< Receiver is in idle state. */ + STATE_RX_RCV, /*!< Frame is beeing received. */ + STATE_RX_ERROR /*!< If the frame is invalid. */ +} eMBRcvState; + +typedef enum +{ + STATE_TX_IDLE, /*!< Transmitter is in idle state. */ + STATE_TX_XMIT /*!< Transmitter is in transfer state. */ +} eMBSndState; + +/* ----------------------- Shared variables ---------------------------------*/ +extern volatile UCHAR ucMbSlaveBuf[]; + +/* ----------------------- Static variables ---------------------------------*/ +static volatile eMBSndState eSndState; +static volatile eMBRcvState eRcvState; + +static volatile UCHAR *pucSndBufferCur; +static volatile USHORT usSndBufferCount; + +static volatile USHORT usRcvBufferPos; +static volatile UCHAR *ucRTUBuf = ucMbSlaveBuf; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + ULONG usTimerT35_50us; + + ( void )ucSlaveAddress; + ENTER_CRITICAL_SECTION( ); + + /* Modbus RTU uses 8 Databits. */ + if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + else + { + /* If baudrate > 19200 then we should use the fixed timer values + * t35 = 1750us. Otherwise t35 must be 3.5 times the character time. + */ + if( ulBaudRate > 19200 ) + { + usTimerT35_50us = 35; /* 1800us. */ + } + else + { + /* The timer reload value for a character is given by: + * + * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 ) + * = 11 * Ticks_per_1s / Baudrate + * = 220000 / Baudrate + * The reload for t3.5 is 1.5 times this value and similary + * for t3.5. + */ + usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ); + } + if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + } + EXIT_CRITICAL_SECTION( ); + + return eStatus; +} + +void +eMBRTUStart( void ) +{ + ENTER_CRITICAL_SECTION( ); + /* Initially the receiver is in the state STATE_RX_INIT. we start + * the timer and if no character is received within t3.5 we change + * to STATE_RX_IDLE. This makes sure that we delay startup of the + * modbus protocol stack until the bus is free. + */ + eRcvState = STATE_RX_INIT; + vMBPortSerialEnable( TRUE, FALSE ); + vMBPortTimersEnable( ); + + EXIT_CRITICAL_SECTION( ); +} + +void +eMBRTUStop( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBPortSerialEnable( FALSE, FALSE ); + vMBPortTimersDisable( ); + EXIT_CRITICAL_SECTION( ); +} + +eMBErrorCode +eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); + assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ); + + /* Length and CRC check */ + if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) + && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) ) + { + /* Save the address field. All frames are passed to the upper layed + * and the decision if a frame is used is done there. + */ + *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF]; + + /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus + * size of address field and CRC checksum. + */ + *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); + + /* Return the start of the Modbus PDU to the caller. */ + *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF]; + } + else + { + eStatus = MB_EIO; + } + + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +eMBErrorCode +eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT usCRC16; + + ENTER_CRITICAL_SECTION( ); + + /* Check if the receiver is still in idle state. If not we where to + * slow with processing the received frame and the master sent another + * frame on the network. We have to abort sending the frame. + */ + if( eRcvState == STATE_RX_IDLE ) + { + /* First byte before the Modbus-PDU is the slave address. */ + pucSndBufferCur = ( UCHAR * ) pucFrame - 1; + usSndBufferCount = 1; + + /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ + pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; + usSndBufferCount += usLength; + + /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ + usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); + ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); + ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); + + /* Activate the transmitter. */ + eSndState = STATE_TX_XMIT; + vMBPortSerialEnable( FALSE, TRUE ); + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +BOOL +xMBRTUReceiveFSM( void ) +{ + BOOL xStatus = FALSE; + UCHAR ucByte; + + assert( eSndState == STATE_TX_IDLE ); + + /* Always read the character. */ + xStatus = xMBPortSerialGetByte( ( CHAR * ) & ucByte ); + + switch ( eRcvState ) + { + /* If we have received a character in the init state we have to + * wait until the frame is finished. + */ + case STATE_RX_INIT: + vMBPortTimersEnable( ); + break; + + /* In the error state we wait until all characters in the + * damaged frame are transmitted. + */ + case STATE_RX_ERROR: + vMBPortTimersEnable( ); + break; + + /* In the idle state we wait for a new character. If a character + * is received the t1.5 and t3.5 timers are started and the + * receiver is in the state STATE_RX_RCV. + */ + case STATE_RX_IDLE: + usRcvBufferPos = 0; + ucRTUBuf[usRcvBufferPos++] = ucByte; + eRcvState = STATE_RX_RCV; + + /* Enable t3.5 timers. */ + vMBPortTimersEnable( ); + break; + + /* We are currently receiving a frame. Reset the timer after + * every character received. If more than the maximum possible + * number of bytes in a modbus frame is received the frame is + * ignored. + */ + case STATE_RX_RCV: + if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) + { + if ( xStatus ) { + ucRTUBuf[usRcvBufferPos++] = ucByte; + } + } + else + { + eRcvState = STATE_RX_ERROR; + } + vMBPortTimersEnable( ); + break; + } + + return xStatus; +} + +BOOL +xMBRTUTransmitFSM( void ) +{ + BOOL xNeedPoll = TRUE; + + assert( eRcvState == STATE_RX_IDLE ); + + switch ( eSndState ) + { + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_TX_IDLE: + break; + + case STATE_TX_XMIT: + /* check if we are finished. */ + if( usSndBufferCount != 0 ) + { + xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur ); + pucSndBufferCur++; /* next byte in sendbuffer. */ + usSndBufferCount--; + } + else + { + xMBPortEventPost( EV_FRAME_TRANSMIT ); + xNeedPoll = FALSE; + eSndState = STATE_TX_IDLE; + vMBPortTimersEnable( ); + } + break; + } + + return xNeedPoll; +} + +BOOL MB_PORT_ISR_ATTR +xMBRTUTimerT35Expired( void ) +{ + BOOL xNeedPoll = FALSE; + + switch ( eRcvState ) + { + /* Timer t35 expired. Startup phase is finished. */ + case STATE_RX_INIT: + xNeedPoll = xMBPortEventPost( EV_READY ); + break; + + /* A frame was received and t35 expired. Notify the listener that + * a new frame was received. */ + case STATE_RX_RCV: + xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED ); + break; + + /* An error occured while receiving the frame. */ + case STATE_RX_ERROR: + break; + + /* Function called in an illegal state. */ + default: + assert( ( eRcvState == STATE_RX_IDLE ) || ( eRcvState == STATE_RX_ERROR ) ); + } + + vMBPortTimersDisable( ); + eRcvState = STATE_RX_IDLE; + + return xNeedPoll; +} +#endif diff --git a/components/freemodbus/modbus/rtu/mbrtu.h b/components/freemodbus/modbus/rtu/mbrtu.h new file mode 100644 index 000000000..4adf99fa8 --- /dev/null +++ b/components/freemodbus/modbus/rtu/mbrtu.h @@ -0,0 +1,69 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ + */ +#include "mbconfig.h" + +#ifndef _MB_RTU_H +#define _MB_RTU_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */ + +#if MB_SLAVE_RTU_ENABLED +eMBErrorCode eMBRTUInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate, + eMBParity eParity ); +void eMBRTUStart( void ); +void eMBRTUStop( void ); +eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); +eMBErrorCode eMBRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); +BOOL xMBRTUReceiveFSM( void ); +BOOL xMBRTUTransmitFSM( void ); +BOOL xMBRTUTimerT15Expired( void ); +BOOL xMBRTUTimerT35Expired( void ); +#endif + +#if MB_MASTER_RTU_ENABLED +eMBErrorCode eMBMasterRTUInit( UCHAR ucPort, ULONG ulBaudRate,eMBParity eParity ); +void eMBMasterRTUStart( void ); +void eMBMasterRTUStop( void ); +eMBErrorCode eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); +eMBErrorCode eMBMasterRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); +BOOL xMBMasterRTUReceiveFSM( void ); +BOOL xMBMasterRTUTransmitFSM( void ); +BOOL xMBMasterRTUTimerExpired( void ); +#endif + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/rtu/mbrtu_m.c b/components/freemodbus/modbus/rtu/mbrtu_m.c new file mode 100644 index 000000000..19be4b8ae --- /dev/null +++ b/components/freemodbus/modbus/rtu/mbrtu_m.c @@ -0,0 +1,408 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2013 China Beijing Armink + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" +#include "stdio.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ + +#include "mb_m.h" +#include "mbrtu.h" +#include "mbframe.h" + +#include "mbcrc.h" +#include "mbport.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_RTU_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */ + +/* ----------------------- Type definitions ---------------------------------*/ +typedef enum +{ + STATE_M_RX_INIT, /*!< Receiver is in initial state. */ + STATE_M_RX_IDLE, /*!< Receiver is in idle state. */ + STATE_M_RX_RCV, /*!< Frame is beeing received. */ + STATE_M_RX_ERROR, /*!< If the frame is invalid. */ +} eMBMasterRcvState; + +typedef enum +{ + STATE_M_TX_IDLE, /*!< Transmitter is in idle state. */ + STATE_M_TX_XMIT, /*!< Transmitter is in transfer state. */ + STATE_M_TX_XFWR, /*!< Transmitter is in transfer finish and wait receive state. */ +} eMBMasterSndState; + +#if MB_MASTER_RTU_ENABLED > 0 +/*------------------------ Shared variables ---------------------------------*/ +extern volatile UCHAR ucMasterRcvBuf[]; +extern volatile UCHAR ucMasterSndBuf[]; + +/* ----------------------- Static variables ---------------------------------*/ +static volatile eMBMasterSndState eSndState; +static volatile eMBMasterRcvState eRcvState; + +static volatile UCHAR *pucMasterSndBufferCur; +static volatile USHORT usMasterSndBufferCount; +static volatile USHORT usMasterRcvBufferPos; + +static volatile UCHAR *ucMasterRTURcvBuf = ucMasterRcvBuf; +static volatile UCHAR *ucMasterRTUSndBuf = ucMasterSndBuf; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBMasterRTUInit(UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + ULONG usTimerT35_50us; + + ENTER_CRITICAL_SECTION( ); + + /* Modbus RTU uses 8 Databits. */ + if( xMBMasterPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + else + { + /* If baudrate > 19200 then we should use the fixed timer values + * t35 = 1750us. Otherwise t35 must be 3.5 times the character time. + */ + if( ulBaudRate > 19200 ) + { + usTimerT35_50us = 35; /* 1800us. */ + } + else + { + /* The timer reload value for a character is given by: + * + * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 ) + * = 11 * Ticks_per_1s / Baudrate + * = 220000 / Baudrate + * The reload for t3.5 is 1.5 times this value and similary + * for t3.5. + */ + usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ); + } + if( xMBMasterPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + } + EXIT_CRITICAL_SECTION( ); + + return eStatus; +} + +void +eMBMasterRTUStart( void ) +{ + ENTER_CRITICAL_SECTION( ); + /* Initially the receiver is in the state STATE_M_RX_INIT. we start + * the timer and if no character is received within t3.5 we change + * to STATE_M_RX_IDLE. This makes sure that we delay startup of the + * modbus protocol stack until the bus is free. + */ + eRcvState = STATE_M_RX_IDLE; //STATE_M_RX_INIT (We start processing immediately) + vMBMasterPortSerialEnable( TRUE, FALSE ); + vMBMasterPortTimersT35Enable( ); + + EXIT_CRITICAL_SECTION( ); +} + +void +eMBMasterRTUStop( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBMasterPortSerialEnable( FALSE, FALSE ); + vMBMasterPortTimersDisable( ); + EXIT_CRITICAL_SECTION( ); +} + +eMBErrorCode +eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); + assert( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); + + /* Length and CRC check */ + if( ( usMasterRcvBufferPos >= MB_RTU_SER_PDU_SIZE_MIN ) + && ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) ) + { + /* Save the address field. All frames are passed to the upper layed + * and the decision if a frame is used is done there. + */ + *pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF]; + + /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus + * size of address field and CRC checksum. + */ + *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); + + /* Return the start of the Modbus PDU to the caller. */ + *pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF]; + } + else + { + eStatus = MB_EIO; + } + + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +eMBErrorCode +eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT usCRC16; + + if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL; + + ENTER_CRITICAL_SECTION( ); + + /* Check if the receiver is still in idle state. If not we where to + * slow with processing the received frame and the master sent another + * frame on the network. We have to abort sending the frame. + */ + if( eRcvState == STATE_M_RX_IDLE ) + { + /* First byte before the Modbus-PDU is the slave address. */ + pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1; + usMasterSndBufferCount = 1; + + /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ + pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; + usMasterSndBufferCount += usLength; + + /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ + usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ); + ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); + ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); + + /* Activate the transmitter. */ + eSndState = STATE_M_TX_XMIT; + // The place to enable RS485 driver + vMBMasterPortSerialEnable( FALSE, TRUE ); + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +BOOL +xMBMasterRTUReceiveFSM( void ) +{ + BOOL xStatus = FALSE; + UCHAR ucByte; + + assert(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); + + /* Always read the character. */ + xStatus = xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte ); + + switch ( eRcvState ) + { + /* If we have received a character in the init state we have to + * wait until the frame is finished. + */ + case STATE_M_RX_INIT: + vMBMasterPortTimersT35Enable( ); + break; + + /* In the error state we wait until all characters in the + * damaged frame are transmitted. + */ + case STATE_M_RX_ERROR: + vMBMasterPortTimersT35Enable( ); + break; + + /* In the idle state we wait for a new character. If a character + * is received the t1.5 and t3.5 timers are started and the + * receiver is in the state STATE_M_RX_RCV and disable early + * the timer of respond timeout . + */ + case STATE_M_RX_IDLE: + /* In time of respond timeout,the receiver receive a frame. + * Disable timer of respond timeout and change the transmiter state to idle. + */ + vMBMasterPortTimersDisable( ); + eSndState = STATE_M_TX_IDLE; + + usMasterRcvBufferPos = 0; + ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; + eRcvState = STATE_M_RX_RCV; + + /* Enable t3.5 timers. */ + vMBMasterPortTimersT35Enable( ); + break; + + /* We are currently receiving a frame. Reset the timer after + * every character received. If more than the maximum possible + * number of bytes in a modbus frame is received the frame is + * ignored. + */ + case STATE_M_RX_RCV: + if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ) + { + if ( xStatus ) { + ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; + } + } + else + { + eRcvState = STATE_M_RX_ERROR; + } + vMBMasterPortTimersT35Enable( ); + break; + } + return xStatus; +} + +BOOL +xMBMasterRTUTransmitFSM( void ) +{ + BOOL xNeedPoll = TRUE; + BOOL xFrameIsBroadcast = FALSE; + + assert( eRcvState == STATE_M_RX_IDLE ); + + switch ( eSndState ) + { + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_M_TX_XFWR: + xNeedPoll = FALSE; + break; + + case STATE_M_TX_IDLE: + break; + + case STATE_M_TX_XMIT: + /* check if we are finished. */ + if( usMasterSndBufferCount != 0 ) + { + xMBMasterPortSerialPutByte( ( CHAR )*pucMasterSndBufferCur ); + pucMasterSndBufferCur++; /* next byte in sendbuffer. */ + usMasterSndBufferCount--; + } + else + { + xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; + vMBMasterRequestSetType( xFrameIsBroadcast ); + eSndState = STATE_M_TX_XFWR; + /* If the frame is broadcast ,master will enable timer of convert delay, + * else master will enable timer of respond timeout. */ + if ( xFrameIsBroadcast == TRUE ) + { + vMBMasterPortTimersConvertDelayEnable( ); + } + else + { + vMBMasterPortTimersRespondTimeoutEnable( ); + } + } + break; + } + + return xNeedPoll; +} + +BOOL MB_PORT_ISR_ATTR +xMBMasterRTUTimerExpired(void) +{ + BOOL xNeedPoll = FALSE; + + switch (eRcvState) + { + /* Timer t35 expired. Startup phase is finished. */ + case STATE_M_RX_INIT: + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY); + break; + + /* A frame was received and t35 expired. Notify the listener that + * a new frame was received. */ + case STATE_M_RX_RCV: + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED); + break; + + /* An error occured while receiving the frame. */ + case STATE_M_RX_ERROR: + vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + break; + + /* Function called in an illegal state. */ + default: + assert(eRcvState == STATE_M_RX_IDLE); + break; + } + eRcvState = STATE_M_RX_IDLE; + + switch (eSndState) + { + /* A frame was send finish and convert delay or respond timeout expired. + * If the frame is broadcast,The master will idle,and if the frame is not + * broadcast. Notify the listener process error.*/ + case STATE_M_TX_XFWR: + if ( xMBMasterRequestIsBroadcast( ) == FALSE ) { + vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT); + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + } + break; + /* Function called in an illegal state. */ + default: + assert( ( eSndState == STATE_M_TX_XMIT ) || ( eSndState == STATE_M_TX_IDLE )); + break; + } + eSndState = STATE_M_TX_IDLE; + + vMBMasterPortTimersDisable( ); + /* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */ + if (xMBMasterGetCurTimerMode() == MB_TMODE_CONVERT_DELAY) { + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_EXECUTE); + } + + return xNeedPoll; +} + + +#endif + + diff --git a/components/freemodbus/modbus/tcp/mbtcp.c b/components/freemodbus/modbus/tcp/mbtcp.c new file mode 100644 index 000000000..58542d8c9 --- /dev/null +++ b/components/freemodbus/modbus/tcp/mbtcp.c @@ -0,0 +1,152 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbconfig.h" +#include "mbtcp.h" +#include "mbframe.h" +#include "mbport.h" + +#if MB_TCP_ENABLED + +/* ----------------------- Defines ------------------------------------------*/ + +/* ----------------------- MBAP Header --------------------------------------*/ +/* + * + * <------------------------ MODBUS TCP/IP ADU(1) -------------------------> + * <----------- MODBUS PDU (1') ----------------> + * +-----------+---------------+------------------------------------------+ + * | TID | PID | Length | UID |Code | Data | + * +-----------+---------------+------------------------------------------+ + * | | | | | + * (2) (3) (4) (5) (6) + * + * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte) + * (3) ... MB_TCP_PID = 2 (Protocol Identifier - 2 Byte) + * (4) ... MB_TCP_LEN = 4 (Number of bytes - 2 Byte) + * (5) ... MB_TCP_UID = 6 (Unit Identifier - 1 Byte) + * (6) ... MB_TCP_FUNC = 7 (Modbus Function Code) + * + * (1) ... Modbus TCP/IP Application Data Unit + * (1') ... Modbus Protocol Data Unit + */ + +#define MB_TCP_PROTOCOL_ID 0 /* 0 = Modbus Protocol */ + + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBTCPDoInit( USHORT ucTCPPort ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( xMBTCPPortInit( ucTCPPort ) == FALSE ) + { + eStatus = MB_EPORTERR; + } + return eStatus; +} + +void +eMBTCPStart( void ) +{ +} + +void +eMBTCPStop( void ) +{ + /* Make sure that no more clients are connected. */ + vMBTCPPortDisable( ); +} + +eMBErrorCode +eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_EIO; + UCHAR *pucMBTCPFrame; + USHORT usLength; + USHORT usPID; + + if( xMBTCPPortGetRequest( &pucMBTCPFrame, &usLength ) != FALSE ) + { + usPID = pucMBTCPFrame[MB_TCP_PID] << 8U; + usPID |= pucMBTCPFrame[MB_TCP_PID + 1]; + + if( usPID == MB_TCP_PROTOCOL_ID ) + { + *ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC]; + *pusLength = usLength - MB_TCP_FUNC; + eStatus = MB_ENOERR; + + /* Modbus TCP does not use any addresses. Fake the source address such + * that the processing part deals with this frame. + */ + *pucRcvAddress = MB_TCP_PSEUDO_ADDRESS; + } + } + else + { + eStatus = MB_EIO; + } + return eStatus; +} + +eMBErrorCode +eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + UCHAR *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC; + USHORT usTCPLength = usLength + MB_TCP_FUNC; + + /* The MBAP header is already initialized because the caller calls this + * function with the buffer returned by the previous call. Therefore we + * only have to update the length in the header. Note that the length + * header includes the size of the Modbus PDU and the UID Byte. Therefore + * the length is usLength plus one. + */ + pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U; + pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF; + if( xMBTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE ) + { + eStatus = MB_EIO; + } + return eStatus; +} + +#endif diff --git a/components/freemodbus/modbus/tcp/mbtcp.h b/components/freemodbus/modbus/tcp/mbtcp.h new file mode 100644 index 000000000..6e55718c5 --- /dev/null +++ b/components/freemodbus/modbus/tcp/mbtcp.h @@ -0,0 +1,56 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_TCP_H +#define _MB_TCP_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Defines ------------------------------------------*/ + +#if MB_TCP_ENABLED + +/* ----------------------- Function prototypes ------------------------------*/ +eMBErrorCode eMBTCPDoInit( USHORT ucTCPPort ); +void eMBTCPStart( void ); +void eMBTCPStop( void ); +eMBErrorCode eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, + USHORT * pusLength ); +eMBErrorCode eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, + USHORT usLength ); + +#endif + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/modbus/tcp/mbtcp_m.c b/components/freemodbus/modbus/tcp/mbtcp_m.c new file mode 100644 index 000000000..419710def --- /dev/null +++ b/components/freemodbus/modbus/tcp/mbtcp_m.c @@ -0,0 +1,152 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbconfig.h" +#include "mbtcp_m.h" +#include "mbframe.h" +#include "mbport.h" + +#if MB_MASTER_TCP_ENABLED + +/* ----------------------- Defines ------------------------------------------*/ + +/* ----------------------- MBAP Header --------------------------------------*/ +/* + * + * <------------------------ MODBUS TCP/IP ADU(1) -------------------------> + * <----------- MODBUS PDU (1') ----------------> + * +-----------+---------------+------------------------------------------+ + * | TID | PID | Length | UID |Code | Data | + * +-----------+---------------+------------------------------------------+ + * | | | | | + * (2) (3) (4) (5) (6) + * + * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte) + * (3) ... MB_TCP_PID = 2 (Protocol Identifier - 2 Byte) + * (4) ... MB_TCP_LEN = 4 (Number of bytes - 2 Byte) + * (5) ... MB_TCP_UID = 6 (Unit Identifier - 1 Byte) + * (6) ... MB_TCP_FUNC = 7 (Modbus Function Code) + * + * (1) ... Modbus TCP/IP Application Data Unit + * (1') ... Modbus Protocol Data Unit + */ + +#define MB_TCP_PROTOCOL_ID 0 /* 0 = Modbus Protocol */ + + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBMasterTCPDoInit( USHORT ucTCPPort ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( xMBMasterTCPPortInit( ucTCPPort ) == FALSE ) + { + eStatus = MB_EPORTERR; + } + return eStatus; +} + +void +eMBMasterTCPStart( void ) +{ +} + +void +eMBMasterTCPStop( void ) +{ + /* Make sure that no more clients are connected. */ + vMBMasterTCPPortDisable( ); +} + +eMBErrorCode +eMBMasterTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_EIO; + UCHAR *pucMBTCPFrame; + USHORT usLength; + USHORT usPID; + + if( xMBMasterTCPPortGetRequest( &pucMBTCPFrame, &usLength ) != FALSE ) + { + usPID = pucMBTCPFrame[MB_TCP_PID] << 8U; + usPID |= pucMBTCPFrame[MB_TCP_PID + 1]; + + if( usPID == MB_TCP_PROTOCOL_ID ) + { + *ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC]; + *pusLength = usLength - MB_TCP_FUNC; + eStatus = MB_ENOERR; + + /* Modbus TCP does not use any addresses. Fake the source address such + * that the processing part deals with this frame. + */ + *pucRcvAddress = MB_TCP_PSEUDO_ADDRESS; + } + } + else + { + eStatus = MB_EIO; + } + return eStatus; +} + +eMBErrorCode +eMBMasterTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + UCHAR *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC; + USHORT usTCPLength = usLength + MB_TCP_FUNC; + + /* The MBAP header is already initialized because the caller calls this + * function with the buffer returned by the previous call. Therefore we + * only have to update the length in the header. Note that the length + * header includes the size of the Modbus PDU and the UID Byte. Therefore + * the length is usLength plus one. + */ + pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U; + pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF; + if( xMBMasterTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE ) + { + eStatus = MB_EIO; + } + return eStatus; +} + +#endif diff --git a/components/freemodbus/modbus/tcp/mbtcp_m.h b/components/freemodbus/modbus/tcp/mbtcp_m.h new file mode 100644 index 000000000..3445ca9ec --- /dev/null +++ b/components/freemodbus/modbus/tcp/mbtcp_m.h @@ -0,0 +1,57 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $ + */ + +#ifndef _MB_TCP_M_H +#define _MB_TCP_M_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Defines ------------------------------------------*/ + +#if MB_MASTER_TCP_ENABLED + +/* ----------------------- Function prototypes ------------------------------*/ +eMBErrorCode eMBMasterTCPDoInit( USHORT ucTCPPort ); +void eMBMasterTCPStart( void ); +void eMBMasterTCPStop( void ); +eMBErrorCode eMBMasterTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, + USHORT * pusLength ); +eMBErrorCode eMBMasterTCPSend( UCHAR _unused, const UCHAR * pucFrame, + USHORT usLength ); +BOOL xMBMasterTCPTimerExpired(void); + +#endif + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/port/port.c b/components/freemodbus/port/port.c new file mode 100644 index 000000000..dd9063f27 --- /dev/null +++ b/components/freemodbus/port/port.c @@ -0,0 +1,146 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $ + */ + +/* ----------------------- System includes --------------------------------*/ + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "freertos/FreeRTOS.h" +#include "sys/lock.h" +#include "port.h" + +/* ----------------------- Variables ----------------------------------------*/ +static _lock_t s_port_lock; +static UCHAR ucPortMode = 0; + +/* ----------------------- Start implementation -----------------------------*/ +inline void +vMBPortEnterCritical(void) +{ + _lock_acquire(&s_port_lock); +} + +inline void +vMBPortExitCritical(void) +{ + _lock_release(&s_port_lock); +} + +UCHAR +ucMBPortGetMode( void ) +{ + return ucPortMode; +} + +void +vMBPortSetMode( UCHAR ucMode ) +{ + ENTER_CRITICAL_SECTION(); + ucPortMode = ucMode; + EXIT_CRITICAL_SECTION(); +} + +#if MB_TCP_DEBUG + +// This function is kept to realize legacy freemodbus frame logging functionality +void +prvvMBTCPLogFrame( const CHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen ) +{ + int i; + int res = 0; + int iBufPos = 0; + size_t iBufLeft = MB_TCP_FRAME_LOG_BUFSIZE; + static CHAR arcBuffer[MB_TCP_FRAME_LOG_BUFSIZE]; + + assert( pucFrame != NULL ); + + for ( i = 0; i < usFrameLen; i++ ) { + // Print some additional frame information. + switch ( i ) + { + case 0: + // TID = Transaction Identifier. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, "| TID = " ); + break; + case 2: + // PID = Protocol Identifier. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | PID = " ); + break; + case 4: + // Length + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | LEN = " ); + break; + case 6: + // UID = Unit Identifier. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | UID = " ); + break; + case 7: + // MB Function Code. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | FUNC = " ); + break; + case 8: + // MB PDU rest. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | DATA = " ); + break; + default: + res = 0; + break; + } + if( res == -1 ) { + break; + } + else { + iBufPos += res; + iBufLeft -= res; + } + + // Print the data. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, "%02X", pucFrame[i] ); + if( res == -1 ) { + break; + } else { + iBufPos += res; + iBufLeft -= res; + } + } + + if( res != -1 ) { + // Append an end of frame string. + res = snprintf( &arcBuffer[iBufPos], iBufLeft, " |" ); + if( res != -1 ) { + ESP_LOGD(pucMsg, "%s", arcBuffer); + } + } +} +#endif diff --git a/components/freemodbus/port/port.h b/components/freemodbus/port/port.h new file mode 100644 index 000000000..3ff8e9547 --- /dev/null +++ b/components/freemodbus/port/port.h @@ -0,0 +1,144 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PORT_COMMON_H_ +#define PORT_COMMON_H_ + +#include "freertos/FreeRTOS.h" +#include "esp_log.h" // for ESP_LOGE macro +#include "mbconfig.h" + +#define INLINE inline +#define PR_BEGIN_EXTERN_C extern "C" { +#define PR_END_EXTERN_C } + +#define MB_PORT_TAG "MB_PORT_COMMON" + +#define MB_BAUD_RATE_DEFAULT (115200) +#define MB_QUEUE_LENGTH (CONFIG_FMB_QUEUE_LENGTH) + +#define MB_SERIAL_TASK_PRIO (CONFIG_FMB_PORT_TASK_PRIO) +#define MB_SERIAL_TASK_STACK_SIZE (CONFIG_FMB_PORT_TASK_STACK_SIZE) +#define MB_SERIAL_TOUT (3) // 3.5*8 = 28 ticks, TOUT=3 -> ~24..33 ticks + +// Set buffer size for transmission +#define MB_SERIAL_BUF_SIZE (CONFIG_FMB_SERIAL_BUF_SIZE) + +// common definitions for serial port implementations +#define MB_SERIAL_TX_TOUT_MS (100) +#define MB_SERIAL_TX_TOUT_TICKS (pdMS_TO_TICKS(MB_SERIAL_TX_TOUT_MS)) // timeout for transmission +#define MB_SERIAL_RX_TOUT_MS (1) +#define MB_SERIAL_RX_TOUT_TICKS (pdMS_TO_TICKS(MB_SERIAL_RX_TOUT_MS)) // timeout for receive + +#define MB_SERIAL_RESP_LEN_MIN (4) + +// Common definitions for TCP port +#define MB_TCP_BUF_SIZE (256 + 7) // Must hold a complete Modbus TCP frame. +#define MB_TCP_DEFAULT_PORT (CONFIG_FMB_TCP_PORT_DEFAULT) +#define MB_TCP_STACK_SIZE (CONFIG_FMB_PORT_TASK_STACK_SIZE) +#define MB_TCP_TASK_PRIO (CONFIG_FMB_PORT_TASK_PRIO) + +#define MB_TCP_READ_TIMEOUT_MS (100) // read timeout in mS +#define MB_TCP_READ_TIMEOUT (pdMS_TO_TICKS(MB_TCP_READ_TIMEOUT_MS)) +#define MB_TCP_SEND_TIMEOUT_MS (500) // send event timeout in mS +#define MB_TCP_SEND_TIMEOUT (pdMS_TO_TICKS(MB_TCP_SEND_TIMEOUT_MS)) +#define MB_TCP_PORT_MAX_CONN (CONFIG_FMB_TCP_PORT_MAX_CONN) + +#define MB_TCP_FRAME_LOG_BUFSIZE (256) + +// Define number of timer reloads per 1 mS +#define MB_TIMER_TICS_PER_MS (20UL) + +#define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module. + +#define MB_TCP_GET_FIELD(buffer, field) ((USHORT)((buffer[field] << 8U) | buffer[field + 1])) + +#define MB_PORT_CHECK(a, ret_val, str, ...) \ + if (!(a)) { \ + ESP_LOGE(MB_PORT_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return ret_val; \ + } + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif /* __cplusplus */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +typedef char BOOL; + +typedef unsigned char UCHAR; +typedef char CHAR; + +typedef unsigned short USHORT; +typedef short SHORT; + +typedef unsigned long ULONG; +typedef long LONG; + +#if MB_TCP_DEBUG +typedef enum +{ + MB_LOG_DEBUG, + MB_LOG_INFO, + MB_LOG_WARN, + MB_LOG_ERROR +} eMBPortLogLevel; +#endif + +typedef enum +{ + MB_PROTO_TCP, + MB_PROTO_UDP, +} eMBPortProto; + +typedef enum { + MB_PORT_IPV4 = 0, /*!< TCP IPV4 addressing */ + MB_PORT_IPV6 = 1 /*!< TCP IPV6 addressing */ +} eMBPortIpVer; + +void vMBPortEnterCritical(void); +void vMBPortExitCritical(void); + +#define ENTER_CRITICAL_SECTION( ) { ESP_EARLY_LOGD(MB_PORT_TAG,"%s: Port enter critical.", __func__); \ + vMBPortEnterCritical(); } + +#define EXIT_CRITICAL_SECTION( ) { vMBPortExitCritical(); \ + ESP_EARLY_LOGD(MB_PORT_TAG,"%s: Port exit critical", __func__); } + +#define MB_PORT_CHECK_EVENT( event, mask ) ( event & mask ) +#define MB_PORT_CLEAR_EVENT( event, mask ) do { event &= ~mask; } while(0) + +// Legacy Modbus logging function +#if MB_TCP_DEBUG +void vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule, + const CHAR * szFmt, ... ); +void prvvMBTCPLogFrame( const CHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen ); +#endif + +void vMBPortSetMode( UCHAR ucMode ); +UCHAR ucMBPortGetMode( void ); + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif /* __cplusplus */ + +#endif /* PORT_COMMON_H_ */ diff --git a/components/freemodbus/port/portevent.c b/components/freemodbus/port/portevent.c new file mode 100644 index 000000000..bb26644fa --- /dev/null +++ b/components/freemodbus/port/portevent.c @@ -0,0 +1,131 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Port Demo Application + * Copyright (C) 2010 Christian Walter + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * IF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * File: $Id: portevent.c,v 1.1 2010/06/06 13:07:20 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include +#include +#include + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" +#include "port.h" +#include "sdkconfig.h" +/* ----------------------- Variables ----------------------------------------*/ +static xQueueHandle xQueueHdl; + +#define MB_EVENT_QUEUE_SIZE (6) +#define MB_EVENT_QUEUE_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_EVENT_QUEUE_TIMEOUT)) + +/* ----------------------- Start implementation -----------------------------*/ +BOOL +xMBPortEventInit( void ) +{ + BOOL bStatus = FALSE; + if((xQueueHdl = xQueueCreate(MB_EVENT_QUEUE_SIZE, sizeof(eMBEventType))) != NULL) + { + vQueueAddToRegistry(xQueueHdl, "MbPortEventQueue"); + bStatus = TRUE; + } + return bStatus; +} + +void +vMBPortEventClose( void ) +{ + if(xQueueHdl != NULL) + { + vQueueDelete(xQueueHdl); + xQueueHdl = NULL; + } +} + +BOOL MB_PORT_ISR_ATTR +xMBPortEventPost( eMBEventType eEvent ) +{ + BaseType_t xStatus, xHigherPriorityTaskWoken = pdFALSE; + assert(xQueueHdl != NULL); + + if( (BOOL)xPortInIsrContext() == TRUE ) + { + xStatus = xQueueSendFromISR(xQueueHdl, (const void*)&eEvent, &xHigherPriorityTaskWoken); + if ( xHigherPriorityTaskWoken ) + { + portYIELD_FROM_ISR(); + } + if (xStatus != pdTRUE) { + ESP_EARLY_LOGV(MB_PORT_TAG, "%s: Post message failure = %d.", __func__, xStatus); + return FALSE; + } + } + else + { + xStatus = xQueueSend(xQueueHdl, (const void*)&eEvent, MB_EVENT_QUEUE_TIMEOUT); + MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "%s: Post message failure.", __func__); + } + return TRUE; +} + +BOOL +xMBPortEventGet(eMBEventType * peEvent) +{ + assert(xQueueHdl != NULL); + BOOL xEventHappened = FALSE; + + if (xQueueReceive(xQueueHdl, peEvent, portMAX_DELAY) == pdTRUE) { + xEventHappened = TRUE; + } + return xEventHappened; +} + +xQueueHandle +xMBPortEventGetHandle(void) +{ + if(xQueueHdl != NULL) + { + return xQueueHdl; + } + return NULL; +} + diff --git a/components/freemodbus/port/portevent_m.c b/components/freemodbus/port/portevent_m.c new file mode 100644 index 000000000..421b13e44 --- /dev/null +++ b/components/freemodbus/port/portevent_m.c @@ -0,0 +1,317 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Port Demo Application + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portevent.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ + */ + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbport.h" +#include "mbconfig.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "port.h" +#include "mbport.h" +#include "freertos/semphr.h" + + +#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED +/* ----------------------- Defines ------------------------------------------*/ +// Event bit mask for xMBMasterPortEventGet() +#define MB_EVENT_POLL_MASK (EventBits_t)( EV_MASTER_READY | \ + EV_MASTER_FRAME_RECEIVED | \ + EV_MASTER_EXECUTE | \ + EV_MASTER_FRAME_SENT | \ + EV_MASTER_FRAME_TRANSMIT | \ + EV_MASTER_ERROR_PROCESS ) + +// Event bit mask for eMBMasterWaitRequestFinish() +#define MB_EVENT_REQ_MASK (EventBits_t)( EV_MASTER_PROCESS_SUCCESS | \ + EV_MASTER_ERROR_RESPOND_TIMEOUT | \ + EV_MASTER_ERROR_RECEIVE_DATA | \ + EV_MASTER_ERROR_EXECUTE_FUNCTION ) + +#define MB_EVENT_RESOURCE (EventBits_t)( 0x0080 ) + +/* ----------------------- Variables ----------------------------------------*/ +static EventGroupHandle_t xResourceMasterHdl; +static EventGroupHandle_t xEventGroupMasterHdl; +static EventGroupHandle_t xEventGroupMasterConfirmHdl; + +/* ----------------------- Start implementation -----------------------------*/ + +BOOL +xMBMasterPortEventInit( void ) +{ + xEventGroupMasterHdl = xEventGroupCreate(); + xEventGroupMasterConfirmHdl = xEventGroupCreate(); + MB_PORT_CHECK((xEventGroupMasterHdl != NULL) && (xEventGroupMasterConfirmHdl != NULL), + FALSE, "mb stack event group creation error."); + return TRUE; +} + +BOOL MB_PORT_ISR_ATTR +xMBMasterPortEventPost( eMBMasterEventType eEvent ) +{ + BOOL bStatus = FALSE; + eMBMasterEventType eTempEvent = eEvent; + + if( (BOOL)xPortInIsrContext() == TRUE ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xResult = xEventGroupSetBitsFromISR( xEventGroupMasterHdl, + (EventBits_t) eTempEvent, + &xHigherPriorityTaskWoken ); + // Was the message posted successfully? + if( xResult == pdPASS ) { + // If xHigherPriorityTaskWoken is now set to pdTRUE + // then a context switch should be requested. + if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR(); + bStatus = TRUE; + } else { + bStatus = FALSE; + } + } + else + { + // Set event bits if the function is called from task + // The return result is not checked here because + // It might be that event bit was cleared automatically as a + // task that was waiting for the bit was removed from the Blocked state. + (void) xEventGroupSetBits( xEventGroupMasterHdl, (EventBits_t)eTempEvent ); + bStatus = TRUE; + } + return bStatus; +} + +eMBMasterEventType +xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout) +{ + EventBits_t uxBits; + uxBits = xEventGroupWaitBits( xEventGroupMasterConfirmHdl, // The event group being tested. + eEventMask, // The bits within the event group to wait for. + pdFALSE, // Keep masked bits. + pdFALSE, // Don't wait for both bits, either bit will do. + ulTimeout); // Wait timeout for either bit to be set. + if (ulTimeout && uxBits) { + // Clear confirmation events that where set in the mask + xEventGroupClearBits( xEventGroupMasterConfirmHdl, (uxBits & eEventMask) ); + } + return (eMBMasterEventType)(uxBits & eEventMask); +} + +BOOL +xMBMasterPortEventGet( eMBMasterEventType* eEvent ) +{ + EventBits_t uxBits; + BOOL xEventHappened = FALSE; + uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested. + MB_EVENT_POLL_MASK, // The bits within the event group to wait for. + pdTRUE, // Masked bits should be cleared before returning. + pdFALSE, // Don't wait for both bits, either bit will do. + portMAX_DELAY); // Wait forever for either bit to be set. + // Check if poll event is correct + if (MB_PORT_CHECK_EVENT(uxBits, MB_EVENT_POLL_MASK)) { + *eEvent = (eMBMasterEventType)(uxBits & MB_EVENT_POLL_MASK); + // Set event bits in confirmation group (for synchronization with port task) + xEventGroupSetBits( xEventGroupMasterConfirmHdl, *eEvent ); + xEventHappened = TRUE; + } else { + ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event triggered = %d.", __func__, uxBits); + *eEvent = (eMBMasterEventType)uxBits; + xEventHappened = FALSE; + } + return xEventHappened; +} + +// This function is initialize the OS resource for modbus master. +void vMBMasterOsResInit( void ) +{ + xResourceMasterHdl = xEventGroupCreate(); + xEventGroupSetBits(xResourceMasterHdl, MB_EVENT_RESOURCE); + MB_PORT_CHECK((xResourceMasterHdl != NULL), ; , "Resource create error."); +} + +/** + * This function is take Mobus Master running resource. + * Note:The resource is define by Operating System. + * + * @param lTimeOut the waiting time. + * + * @return resource take result + */ +BOOL xMBMasterRunResTake( LONG lTimeOut ) +{ + EventBits_t uxBits; + uxBits = xEventGroupWaitBits( xResourceMasterHdl, // The event group being tested. + MB_EVENT_RESOURCE, // The bits within the event group to wait for. + pdTRUE, // Masked bits should be cleared before returning. + pdFALSE, // Don't wait for both bits, either bit will do. + lTimeOut); // Resource wait timeout. + MB_PORT_CHECK((uxBits == MB_EVENT_RESOURCE), FALSE , "Take resource failure."); + ESP_LOGD(MB_PORT_TAG,"%s:Take resource (%x) (%lu ticks).", __func__, uxBits, lTimeOut); + return TRUE; +} + +/** + * This function is release Modbus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be empty. + */ +void vMBMasterRunResRelease( void ) +{ + EventBits_t uxBits = xEventGroupSetBits( xResourceMasterHdl, MB_EVENT_RESOURCE ); + MB_PORT_CHECK((uxBits == MB_EVENT_RESOURCE), ; , "Resource release failure."); + ESP_LOGD(MB_PORT_TAG,"%s: Release resource (%x).", __func__, uxBits); +} + +/** + * This is modbus master respond timeout error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +{ + BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_RESPOND_TIMEOUT); + MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_RESPOND_TIMEOUT' failed!", __func__); + ESP_LOGD(MB_PORT_TAG,"%s:Callback respond timeout.", __func__); +} + +/** + * This is modbus master receive data error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + */ +void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +{ + BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_RECEIVE_DATA); + MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_RECEIVE_DATA' failed!", __func__); + ESP_LOGD(MB_PORT_TAG,"%s:Callback receive data timeout failure.", __func__); + ESP_LOG_BUFFER_HEX_LEVEL("Err rcv buf", (void*)pucPDUData, (uint16_t)ucPDULength, ESP_LOG_DEBUG); +} + +/** + * This is modbus master execute function error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +{ + BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_EXECUTE_FUNCTION); + MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_EXECUTE_FUNCTION' failed!", __func__); + ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data handler failure.", __func__); + ESP_LOG_BUFFER_HEX_LEVEL("Exec func buf", (void*)pucPDUData, (uint16_t)ucPDULength, ESP_LOG_DEBUG); +} + +/** + * This is modbus master request process success callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system. Do not execute too much waiting process. + */ +void vMBMasterCBRequestSuccess( void ) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + BOOL ret = xMBMasterPortEventPost(EV_MASTER_PROCESS_SUCCESS); + MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_PROCESS_SUCCESS' failed!", __func__); + ESP_LOGD(MB_PORT_TAG,"%s: Callback request success.", __func__); +} + +/** + * This function is wait for modbus master request finish and return result. + * Waiting result include request process success, request respond timeout, + * receive data error and execute function error.You can use the above callback function. + * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run + * much user custom delay for waiting. + * + * @return request error code + */ +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + eMBMasterEventType xRecvedEvent; + + EventBits_t uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested. + MB_EVENT_REQ_MASK, // The bits within the event group to wait for. + pdTRUE, // Masked bits should be cleared before returning. + pdFALSE, // Don't wait for both bits, either bit will do. + portMAX_DELAY ); // Wait forever for either bit to be set. + xRecvedEvent = (eMBMasterEventType)(uxBits); + if (xRecvedEvent) { + ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, xRecvedEvent); + if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) { + // if we wait for certain event bits but get from poll subset + ESP_LOGE(MB_PORT_TAG,"%s: incorrect event set = 0x%x", __func__, xRecvedEvent); + } + xEventGroupSetBits( xEventGroupMasterConfirmHdl, (xRecvedEvent & MB_EVENT_REQ_MASK) ); + if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_PROCESS_SUCCESS)) { + eErrStatus = MB_MRE_NO_ERR; + } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT)) { + eErrStatus = MB_MRE_TIMEDOUT; + } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RECEIVE_DATA)) { + eErrStatus = MB_MRE_REV_DATA; + } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION)) { + eErrStatus = MB_MRE_EXE_FUN; + } + } else { + ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event or timeout xRecvedEvent = 0x%x", __func__, uxBits); + // https://github.com/espressif/esp-idf/issues/5275 + // if a no event is received, that means vMBMasterPortEventClose() + // has been closed, so event group has been deleted by FreeRTOS, which + // triggers the send of 0 value to the event group to unlock this task + // waiting on it. For this patch, handles it as a time out without assert. + eErrStatus = MB_MRE_TIMEDOUT; + } + return eErrStatus; +} + +void vMBMasterPortEventClose(void) +{ + vEventGroupDelete(xEventGroupMasterHdl); + vEventGroupDelete(xEventGroupMasterConfirmHdl); + vEventGroupDelete(xResourceMasterHdl); +} + +#endif diff --git a/components/freemodbus/port/portother.c b/components/freemodbus/port/portother.c new file mode 100644 index 000000000..43b6e967f --- /dev/null +++ b/components/freemodbus/port/portother.c @@ -0,0 +1,76 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Demo Application + * Copyright (C) 2010 Christian Walter + * + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * IF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include +#include +#include + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" + +/* ----------------------- Modbus includes ----------------------------------*/ + +/* ----------------------- Variables ----------------------------------------*/ + +/* ----------------------- Start implementation -----------------------------*/ + +BOOL +bMBPortIsWithinException( void ) +{ + BOOL bIsWithinException = xPortInIsrContext(); + return bIsWithinException; +} + +void +vMBPortClose( void ) +{ + extern void vMBPortSerialClose( void ); + extern void vMBPortTimerClose( void ); + extern void vMBPortEventClose( void ); + vMBPortSerialClose( ); + vMBPortTimerClose( ); + vMBPortEventClose( ); +} diff --git a/components/freemodbus/port/portother_m.c b/components/freemodbus/port/portother_m.c new file mode 100644 index 000000000..15b727a44 --- /dev/null +++ b/components/freemodbus/port/portother_m.c @@ -0,0 +1,71 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Demo Application + * Copyright (c) 2006 Christian Walter + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include +#include +#include +#include + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbport.h" + +/* ----------------------- Modbus includes ----------------------------------*/ + +/* ----------------------- Variables ----------------------------------------*/ + +/* ----------------------- Start implementation -----------------------------*/ + +void +vMBMasterPortClose( void ) +{ + extern void vMBMasterPortSerialClose( void ); + extern void vMBMasterPortTimerClose( void ); + extern void vMBMasterPortEventClose( void ); + vMBMasterPortSerialClose( ); + vMBMasterPortTimerClose( ); + vMBMasterPortEventClose( ); +} + diff --git a/components/freemodbus/port/porttimer.c b/components/freemodbus/port/porttimer.c new file mode 100644 index 000000000..9673e62db --- /dev/null +++ b/components/freemodbus/port/porttimer.c @@ -0,0 +1,152 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Port Demo Application + * Copyright (C) 2010 Christian Walter + * + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * IF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $ + */ +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "sdkconfig.h" +#include "mb.h" +#include "mbport.h" +#include "sdkconfig.h" + +#if CONFIG_FMB_TIMER_PORT_ENABLED + +#define MB_US50_FREQ (20000) // 20kHz 1/20000 = 50mks +#define MB_DISCR_TIME_US (50) // 50uS = one discreet for timer + +#define MB_TIMER_PRESCALLER ((TIMER_BASE_CLK / MB_US50_FREQ) - 1); +#define MB_TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds +#define MB_TIMER_DIVIDER ((TIMER_BASE_CLK / 1000000UL) * MB_DISCR_TIME_US - 1) // divider for 50uS +#define MB_TIMER_WITH_RELOAD (1) + +static const USHORT usTimerIndex = CONFIG_FMB_TIMER_INDEX; // Modbus Timer index used by stack +static const USHORT usTimerGroupIndex = CONFIG_FMB_TIMER_GROUP; // Modbus Timer group index used by stack +static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle + +/* ----------------------- Start implementation -----------------------------*/ +static void IRAM_ATTR vTimerGroupIsr(void *param) +{ + assert((int)param == usTimerIndex); + // Retrieve the counter value from the timer that reported the interrupt + timer_group_clr_intr_status_in_isr(usTimerGroupIndex, usTimerIndex); + (void)pxMBPortCBTimerExpired(); // Timer callback function + // Enable alarm + timer_group_enable_alarm_in_isr(usTimerGroupIndex, usTimerIndex); +} +#endif + +BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) +{ +#if CONFIG_FMB_TIMER_PORT_ENABLED + MB_PORT_CHECK((usTim1Timerout50us > 0), FALSE, + "Modbus timeout discreet is incorrect."); + esp_err_t xErr; + timer_config_t config; + config.alarm_en = TIMER_ALARM_EN; + config.auto_reload = MB_TIMER_WITH_RELOAD; + config.counter_dir = TIMER_COUNT_UP; + config.divider = MB_TIMER_PRESCALLER; + config.intr_type = TIMER_INTR_LEVEL; + config.counter_en = TIMER_PAUSE; + // Configure timer + xErr = timer_init(usTimerGroupIndex, usTimerIndex, &config); + MB_PORT_CHECK((xErr == ESP_OK), FALSE, + "timer init failure, timer_init() returned (0x%x).", xErr); + // Stop timer counter + xErr = timer_pause(usTimerGroupIndex, usTimerIndex); + MB_PORT_CHECK((xErr == ESP_OK), FALSE, + "stop timer failure, timer_pause() returned (0x%x).", xErr); + // Reset counter value + xErr = timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0x00000000ULL); + MB_PORT_CHECK((xErr == ESP_OK), FALSE, + "timer set value failure, timer_set_counter_value() returned (0x%x).", xErr); + // wait3T5_us = 35 * 11 * 100000 / baud; // the 3.5T symbol time for baudrate + // Set alarm value for usTim1Timerout50us * 50uS + xErr = timer_set_alarm_value(usTimerGroupIndex, usTimerIndex, (uint32_t)(usTim1Timerout50us)); + MB_PORT_CHECK((xErr == ESP_OK), FALSE, + "failure to set alarm failure, timer_set_alarm_value() returned (0x%x).", + (uint32_t)xErr); + // Register ISR for timer + xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex, vTimerGroupIsr, + (void*)(uint32_t)usTimerIndex, MB_PORT_TIMER_ISR_FLAG, &xTimerIntHandle); + MB_PORT_CHECK((xErr == ESP_OK), FALSE, + "timer set value failure, timer_isr_register() returned (0x%x).", + (uint32_t)xErr); +#endif + return TRUE; +} + +void vMBPortTimersEnable(void) +{ +#if CONFIG_FMB_TIMER_PORT_ENABLED + ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL)); + ESP_ERROR_CHECK(timer_enable_intr(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_start(usTimerGroupIndex, usTimerIndex)); +#endif +} + +void MB_PORT_ISR_ATTR +vMBPortTimersDisable(void) +{ +#if CONFIG_FMB_TIMER_PORT_ENABLED + if( (BOOL)xPortInIsrContext() ) { + timer_group_set_counter_enable_in_isr(usTimerGroupIndex, usTimerIndex, TIMER_PAUSE); + } else { + ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL)); + // Disable timer interrupt + ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex)); + } +#endif +} + +void vMBPortTimerClose(void) +{ +#ifdef CONFIG_FMB_TIMER_PORT_ENABLED + ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle)); +#endif +} diff --git a/components/freemodbus/port/porttimer_m.c b/components/freemodbus/port/porttimer_m.c new file mode 100644 index 000000000..fbada7e61 --- /dev/null +++ b/components/freemodbus/port/porttimer_m.c @@ -0,0 +1,120 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FreeModbus Libary: ESP32 Port Demo Application + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ + */ + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "mbport.h" +#include "sdkconfig.h" +#include "esp_timer.h" + +/* ----------------------- Variables ----------------------------------------*/ +static USHORT msT35TimeOut; +static esp_timer_handle_t xTimerIntHandle; +/* ----------------------- static functions ---------------------------------*/ +static void IRAM_ATTR vTimerGroupIsr(void *param) +{ + (void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function +} + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortTimersInit(USHORT msTimeOut) +{ + MB_PORT_CHECK((msTimeOut > 0), FALSE, + "Modbus timeout discreet is incorrect."); + // Save timer reload value for Modbus T35 period + msT35TimeOut = msTimeOut; + esp_timer_create_args_t timer_conf = { + .callback = vTimerGroupIsr, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "PORT_TIMER_M" + }; + ESP_ERROR_CHECK(esp_timer_create(&timer_conf, &xTimerIntHandle)); + + return TRUE; +} + +// Set alarm value for usTimerTimeOut50us * 50uS +static BOOL xMBMasterPortTimersEnable(USHORT msTimeOut) +{ + MB_PORT_CHECK((msTimeOut > 0), FALSE, + "incorrect tick value for timer = (0x%x).", + (uint32_t)msTimeOut); + ESP_ERROR_CHECK(esp_timer_stop(xTimerIntHandle)); + ESP_ERROR_CHECK(esp_timer_start_once(xTimerIntHandle, msTimeOut * 1000)); + return TRUE; +} + +void vMBMasterPortTimersT35Enable(void) +{ + USHORT msTimeOut = msT35TimeOut; + + // Set current timer mode, don't change it. + vMBMasterSetCurTimerMode(MB_TMODE_T35); + // Set timer period + (void)xMBMasterPortTimersEnable(msTimeOut); +} + +void vMBMasterPortTimersConvertDelayEnable(void) +{ + // Covert time in milliseconds into ticks + USHORT msTimeOut = MB_MASTER_DELAY_MS_CONVERT; + // Set current timer mode + vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); + ESP_LOGD(MB_PORT_TAG,"%s Convert delay enable.", __func__); + (void)xMBMasterPortTimersEnable(msTimeOut); +} + +void vMBMasterPortTimersRespondTimeoutEnable(void) +{ + USHORT msTimeOut = MB_MASTER_TIMEOUT_MS_RESPOND; + vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); + ESP_LOGD(MB_PORT_TAG,"%s Respond enable timeout.", __func__); + (void)xMBMasterPortTimersEnable(msTimeOut); +} + +void MB_PORT_ISR_ATTR +vMBMasterPortTimersDisable() +{ + ESP_ERROR_CHECK(esp_timer_stop(xTimerIntHandle)); +} + +void vMBMasterPortTimerClose(void) +{ + ESP_ERROR_CHECK(esp_timer_delete(xTimerIntHandle)); +} diff --git a/components/freemodbus/sdkconfig.rename b/components/freemodbus/sdkconfig.rename new file mode 100644 index 000000000..89c1c237f --- /dev/null +++ b/components/freemodbus/sdkconfig.rename @@ -0,0 +1,18 @@ +# sdkconfig replacement configurations for deprecated options formatted as +# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION + +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_PORT_TASK_STACK_SIZE +CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_PORT_TASK_PRIO +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT +CONFIG_MB_CONTROLLER_SLAVE_ID CONFIG_FMB_CONTROLLER_SLAVE_ID +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX diff --git a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c new file mode 100644 index 000000000..5b5bb325b --- /dev/null +++ b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c @@ -0,0 +1,716 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// mbc_tcp_master.c +// TCP master implementation of the Modbus controller + +#include // for calculation of time stamp in milliseconds +#include "esp_log.h" // for log_write +#include // for memcpy +#include "freertos/FreeRTOS.h" // for task creation and queue access +#include "freertos/task.h" // for task api access +#include "freertos/event_groups.h" // for event groups +#include "freertos/queue.h" // for queue api access +#include "mb_m.h" // for modbus stack master types definition +#include "port.h" // for port callback functions and defines +#include "mbutils.h" // for mbutils functions definition for stack callback +#include "sdkconfig.h" // for KConfig values +#include "esp_modbus_common.h" // for common types +#include "esp_modbus_master.h" // for public master types +#include "mbc_master.h" // for private master types +#include "mbc_tcp_master.h" // for tcp master create function and types +#include "port_tcp_master.h" // for tcp master port defines and types + +/*-----------------------Master mode use these variables----------------------*/ + +// The response time is average processing time + data transmission +#define MB_RESPONSE_TIMEOUT pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND) + +static mb_master_interface_t* mbm_interface_ptr = NULL; + +// Modbus event processing task +static void modbus_tcp_master_task(void *pvParameters) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_ASSERT(mbm_opts != NULL); + + // Main Modbus stack processing cycle + for (;;) { + // Wait for poll events + BaseType_t status = xEventGroupWaitBits(mbm_opts->mbm_event_group, + (BaseType_t)(MB_EVENT_STACK_STARTED), + pdFALSE, // do not clear bits + pdFALSE, + portMAX_DELAY); + // Check if stack started then poll for data + if (status & MB_EVENT_STACK_STARTED) { + (void)eMBMasterPoll(); // Allow stack to process data + } + } +} + +// Setup Modbus controller parameters +static esp_err_t mbc_tcp_master_setup(void* comm_info) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb incorrect options pointer."); + + const mb_communication_info_t* comm_info_ptr = (mb_communication_info_t*)comm_info; + // Check communication options + MB_MASTER_CHECK((comm_info_ptr->ip_mode == MB_MODE_TCP), + ESP_ERR_INVALID_ARG, "mb incorrect mode = (0x%x).", + (uint32_t)comm_info_ptr->ip_mode); + MB_MASTER_CHECK((comm_info_ptr->ip_addr != NULL), + ESP_ERR_INVALID_ARG, "mb wrong slave ip address table."); + MB_MASTER_CHECK(((comm_info_ptr->ip_addr_type == MB_IPV4) || (comm_info_ptr->ip_addr_type == MB_IPV6)), + ESP_ERR_INVALID_ARG, "mb incorrect addr type = (0x%x).", (uint8_t)comm_info_ptr->ip_addr_type); + MB_MASTER_CHECK((comm_info_ptr->ip_netif_ptr != NULL), + ESP_ERR_INVALID_ARG, "mb incorrect iface address."); + // Save the communication options + mbm_opts->mbm_comm = *(mb_communication_info_t*)comm_info_ptr; + return ESP_OK; +} + +// Modbus controller stack start function +static esp_err_t mbc_tcp_master_start(void) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + eMBErrorCode status = MB_EIO; + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb incorrect options pointer."); + const mb_communication_info_t* comm_info = (mb_communication_info_t*)&mbm_opts->mbm_comm; + + // Initialize Modbus stack using mbcontroller parameters + status = eMBMasterTCPInit((USHORT)comm_info->ip_port); + MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, + "mb stack initialization failure, eMBMasterInit() returns (0x%x).", status); + + MB_MASTER_CHECK((mbm_opts->mbm_param_descriptor_size >= 1), ESP_ERR_INVALID_ARG, "mb table size is incorrect."); + + bool result = false; + const char** comm_ip_table = (const char**)comm_info->ip_addr; + MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); + + eMBPortProto proto = (comm_info->ip_mode == MB_MODE_TCP) ? MB_PROTO_TCP : MB_PROTO_UDP; + eMBPortIpVer ip_ver = (comm_info->ip_addr_type == MB_IPV4) ? MB_PORT_IPV4 : MB_PORT_IPV6; + vMBTCPPortMasterSetNetOpt(comm_info->ip_netif_ptr, ip_ver, proto); + vMBTCPPortMasterTaskStart(); + + // Add slave IP address for each slave to initialise connection + for (int idx = 0; *comm_ip_table != NULL; idx++, comm_ip_table++) + { + result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table); + MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table); + } + // Add end of list condition + (void)xMBTCPPortMasterAddSlaveIp(NULL); + + status = eMBMasterEnable(); + MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, + "mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status); + + bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED); + MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE, "mb stack start failed."); + return ESP_OK; +} + +// Modbus controller destroy function +static esp_err_t mbc_tcp_master_destroy(void) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb incorrect options pointer."); + eMBErrorCode mb_error = MB_ENOERR; + + // Stop polling by clearing correspondent bit in the event group + xEventGroupClearBits(mbm_opts->mbm_event_group, + (EventBits_t)MB_EVENT_STACK_STARTED); + // Disable and then destroy the Modbus stack + mb_error = eMBMasterDisable(); + MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure."); + (void)vTaskDelete(mbm_opts->mbm_task_handle); + (void)vEventGroupDelete(mbm_opts->mbm_event_group); + mb_error = eMBMasterClose(); + MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, + "mb stack close failure returned (0x%x).", (uint32_t)mb_error); + free(mbm_interface_ptr); // free the memory allocated for options + vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); + mbm_interface_ptr = NULL; + return ESP_OK; +} + +// Set Modbus parameter description table +static esp_err_t mbc_tcp_master_set_descriptor(const mb_parameter_descriptor_t* descriptor, const uint16_t num_elements) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + MB_MASTER_CHECK((descriptor != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor."); + MB_MASTER_CHECK((num_elements >= 1), ESP_ERR_INVALID_ARG, "mb table size is incorrect."); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb options."); + + const char** comm_ip_table = (const char**)mbm_opts->mbm_comm.ip_addr; + MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); + + const mb_parameter_descriptor_t *reg_ptr = descriptor; + // Go through all items in the table to check all Modbus registers + for (uint16_t counter = 0; counter < (num_elements); counter++, reg_ptr++) + { + MB_MASTER_CHECK((comm_ip_table[reg_ptr->mb_slave_addr - 1] != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); + // Below is the code to check consistency of the table format and required fields. + MB_MASTER_CHECK((reg_ptr->cid == counter), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect."); + MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "mb descriptor param key is incorrect."); + MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "mb descriptor param size is incorrect."); + } + mbm_opts->mbm_param_descriptor_table = descriptor; + mbm_opts->mbm_param_descriptor_size = num_elements; + return ESP_OK; +} + +// Send custom Modbus request defined as mb_param_request_t structure +static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void* data_ptr) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_CHECK((request != NULL), ESP_ERR_INVALID_ARG, "mb request structure."); + MB_MASTER_CHECK((data_ptr != NULL), ESP_ERR_INVALID_ARG, "mb incorrect data pointer."); + + eMBMasterReqErrCode mb_error = MB_MRE_NO_REG; + esp_err_t error = ESP_FAIL; + + uint8_t mb_slave_addr = request->slave_addr; + uint8_t mb_command = request->command; + uint16_t mb_offset = request->reg_start; + uint16_t mb_size = request->reg_size; + + // Set the buffer for callback function processing of received data + mbm_opts->mbm_reg_buffer_ptr = (uint8_t*)data_ptr; + mbm_opts->mbm_reg_buffer_size = mb_size; + + // Calls appropriate request function to send request and waits response + switch(mb_command) + { + case MB_FUNC_READ_COILS: + mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size , (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_WRITE_SINGLE_COIL: + mb_error = eMBMasterReqWriteCoil((UCHAR)mb_slave_addr, (USHORT)mb_offset, + *(USHORT*)data_ptr, (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_WRITE_MULTIPLE_COILS: + mb_error = eMBMasterReqWriteMultipleCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size, (UCHAR*)data_ptr, + (LONG)MB_RESPONSE_TIMEOUT); + break; + case MB_FUNC_READ_DISCRETE_INPUTS: + mb_error = eMBMasterReqReadDiscreteInputs((UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_READ_HOLDING_REGISTER: + mb_error = eMBMasterReqReadHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_WRITE_REGISTER: + mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, + *(USHORT*)data_ptr, (LONG)MB_RESPONSE_TIMEOUT ); + break; + + case MB_FUNC_WRITE_MULTIPLE_REGISTERS: + mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr, + (USHORT)mb_offset, (USHORT)mb_size, + (USHORT*)data_ptr, (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_READWRITE_MULTIPLE_REGISTERS: + mb_error = eMBMasterReqReadWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size, (USHORT*)data_ptr, + (USHORT)mb_offset, (USHORT)mb_size, + (LONG)MB_RESPONSE_TIMEOUT ); + break; + case MB_FUNC_READ_INPUT_REGISTER: + mb_error = eMBMasterReqReadInputRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, + (USHORT)mb_size, (LONG) MB_RESPONSE_TIMEOUT ); + break; + default: + ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ", + __FUNCTION__, mb_command); + mb_error = MB_MRE_NO_REG; + break; + } + + // Propagate the Modbus errors to higher level + switch(mb_error) + { + case MB_MRE_NO_ERR: + error = ESP_OK; + break; + + case MB_MRE_NO_REG: + error = ESP_ERR_NOT_SUPPORTED; // Invalid register request + break; + + case MB_MRE_TIMEDOUT: + error = ESP_ERR_TIMEOUT; // Slave did not send response + break; + + case MB_MRE_EXE_FUN: + case MB_MRE_REV_DATA: + error = ESP_ERR_INVALID_RESPONSE; // Invalid response from slave + break; + + case MB_MRE_MASTER_BUSY: + error = ESP_ERR_INVALID_STATE; // Master is busy (previous request is pending) + break; + + default: + ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); + error = ESP_FAIL; + break; + } + + return error; +} + +static esp_err_t mbc_tcp_master_get_cid_info(uint16_t cid, const mb_parameter_descriptor_t** param_buffer) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + + MB_MASTER_CHECK((param_buffer != NULL), ESP_ERR_INVALID_ARG, "mb incorrect data buffer pointer."); + MB_MASTER_CHECK((mbm_opts->mbm_param_descriptor_table != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor table or not set."); + MB_MASTER_CHECK((cid < mbm_opts->mbm_param_descriptor_size), ESP_ERR_NOT_FOUND, "mb incorrect cid of characteristic."); + + // It is assumed that characteristics cid increased in the table + const mb_parameter_descriptor_t* reg_info = &mbm_opts->mbm_param_descriptor_table[cid]; + + MB_MASTER_CHECK((reg_info->param_key != NULL), ESP_ERR_INVALID_ARG, "mb incorrect characteristic key."); + *param_buffer = reg_info; + return ESP_OK; +} + +// Helper function to get modbus command for each type of Modbus register area +static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_mode_t mode) +{ + uint8_t command = 0; + switch(param_type) + { // + case MB_PARAM_HOLDING: + command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_REGISTERS : MB_FUNC_READ_HOLDING_REGISTER; + break; + case MB_PARAM_INPUT: + command = MB_FUNC_READ_INPUT_REGISTER; + break; + case MB_PARAM_COIL: + command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_COILS : MB_FUNC_READ_COILS; + break; + case MB_PARAM_DISCRETE: + if (mode != MB_PARAM_WRITE) { + command = MB_FUNC_READ_DISCRETE_INPUTS; + } else { + ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); + } + break; + default: + ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); + break; + } + return command; +} + +// Helper function to set parameter buffer according to its type +static esp_err_t mbc_tcp_master_set_param_data(void* dest, void* src, mb_descr_type_t param_type, size_t param_size) +{ + esp_err_t err = ESP_OK; + MB_MASTER_CHECK((dest != NULL), ESP_ERR_INVALID_ARG, "incorrect parameter pointer."); + MB_MASTER_CHECK((src != NULL), ESP_ERR_INVALID_ARG, "incorrect parameter pointer."); + // Transfer parameter data into value of characteristic + switch(param_type) + { + case PARAM_TYPE_U8: + *((uint8_t*)dest) = *((uint8_t*)src); + break; + case PARAM_TYPE_U16: + *((uint16_t*)dest) = *((uint16_t*)src); + break; + case PARAM_TYPE_U32: + *((uint32_t*)dest) = *((uint32_t*)src); + break; + case PARAM_TYPE_FLOAT: + *((float*)dest) = *(float*)src; + break; + case PARAM_TYPE_ASCII: + memcpy((void*)dest, (void*)src, (size_t)param_size); + break; + default: + ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u).", + __FUNCTION__, (uint16_t)param_type); + err = ESP_ERR_NOT_SUPPORTED; + break; + } + return err; +} + +// Helper to search parameter by name in the parameter description table and fills Modbus request fields accordingly +static esp_err_t mbc_tcp_master_set_request(char* name, mb_param_mode_t mode, mb_param_request_t* request, + mb_parameter_descriptor_t* reg_data) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + esp_err_t error = ESP_ERR_NOT_FOUND; + MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect parameter name."); + MB_MASTER_CHECK((request != NULL), ESP_ERR_INVALID_ARG, "mb incorrect request parameter."); + MB_MASTER_CHECK((mode <= MB_PARAM_WRITE), ESP_ERR_INVALID_ARG, "mb incorrect mode."); + MB_MASTER_ASSERT(mbm_opts->mbm_param_descriptor_table != NULL); + const mb_parameter_descriptor_t* reg_ptr = mbm_opts->mbm_param_descriptor_table; + for (uint16_t counter = 0; counter < (mbm_opts->mbm_param_descriptor_size); counter++, reg_ptr++) + { + // Check the cid of the parameter is equal to record number in the table + // Check the length of name and parameter key strings from table + size_t param_key_len = strlen((const char*)reg_ptr->param_key); + if (param_key_len != strlen((const char*)name)) { + continue; // The length of strings is different then check next record in the table + } + // Compare the name of parameter with parameter key from table + uint8_t comp_result = memcmp((const char*)name, (const char*)reg_ptr->param_key, (size_t)param_key_len); + if (comp_result == 0) { + // The correct line is found in the table and reg_ptr points to the found parameter description + request->slave_addr = reg_ptr->mb_slave_addr; + request->reg_start = reg_ptr->mb_reg_start; + request->reg_size = reg_ptr->mb_size; + request->command = mbc_tcp_master_get_command(reg_ptr->mb_param_type, mode); + MB_MASTER_CHECK((request->command > 0), ESP_ERR_INVALID_ARG, "mb incorrect command or parameter type."); + if (reg_data != NULL) { + *reg_data = *reg_ptr; // Set the cid registered parameter data + } + error = ESP_OK; + break; + } + } + return error; +} + +// Get parameter data for corresponding characteristic +static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t *type) +{ + MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor."); + MB_MASTER_CHECK((type != NULL), ESP_ERR_INVALID_ARG, "type pointer is incorrect."); + esp_err_t error = ESP_ERR_INVALID_RESPONSE; + mb_param_request_t request ; + mb_parameter_descriptor_t reg_info = { 0 }; + uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 }; + + error = mbc_tcp_master_set_request(name, MB_PARAM_READ, &request, ®_info); + if ((error == ESP_OK) && (cid == reg_info.cid)) { + error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]); + if (error == ESP_OK) { + // If data pointer is NULL then we don't need to set value (it is still in the cache of cid) + if (value != NULL) { + error = mbc_tcp_master_set_param_data((void*)value, (void*)¶m_buffer[0], + reg_info.param_type, reg_info.param_size); + MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "fail to set parameter data."); + } + ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s", + __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); + } else { + ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s", + __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); + } + // Set the type of parameter found in the table + *type = reg_info.param_type; + } else { + ESP_LOGD(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", + __FUNCTION__, reg_info.cid); + } + return error; +} + +// Set parameter value for characteristic selected by name and cid +static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t* value, uint8_t *type) +{ + MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor."); + MB_MASTER_CHECK((value != NULL), ESP_ERR_INVALID_ARG, "value pointer is incorrect."); + MB_MASTER_CHECK((type != NULL), ESP_ERR_INVALID_ARG, "type pointer is incorrect."); + + esp_err_t error = ESP_ERR_INVALID_RESPONSE; + mb_param_request_t request ; + mb_parameter_descriptor_t reg_info = { 0 }; + uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 }; + + error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, ®_info); + if ((error == ESP_OK) && (cid == reg_info.cid)) { + // Transfer value of characteristic into parameter buffer + error = mbc_tcp_master_set_param_data((void*)¶m_buffer[0], (void*)value, + reg_info.param_type, reg_info.param_size); + MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "failure to set parameter data."); + // Send request to write characteristic data + error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]); + if (error == ESP_OK) { + ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s", + __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); + } else { + ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s", + __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); + } + // Set the type of parameter found in the table + *type = reg_info.param_type; + } else { + ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", + __FUNCTION__, reg_info.cid); + } + return error; +} + +/* ----------------------- Callback functions for Modbus stack ---------------------------------*/ +// These are executed by modbus stack to read appropriate type of registers. + +/** + * Modbus master input register callback function. + * + * @param pucRegBuffer input register buffer + * @param usAddress input register address + * @param usNRegs input register number + * + * @return result + */ +// Callback function for reading of MB Input Registers +eMBErrorCode eMBRegInputCBTcpMaster(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_ASSERT(pucRegBuffer != NULL); + USHORT usRegInputNregs = (USHORT)mbm_opts->mbm_reg_buffer_size; // Number of input registers to be transferred + UCHAR* pucInputBuffer = (UCHAR*)mbm_opts->mbm_reg_buffer_ptr; // Get instance address + USHORT usRegs = usNRegs; + eMBErrorCode eStatus = MB_ENOERR; + // If input or configuration parameters are incorrect then return an error to stack layer + if ((pucInputBuffer != NULL) + && (usNRegs >= 1) + && (usRegInputNregs == usRegs)) { + while (usRegs > 0) { + _XFER_2_RD(pucInputBuffer, pucRegBuffer); + usRegs -= 1; + } + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master holding register callback function. + * + * @param pucRegBuffer holding register buffer + * @param usAddress holding register address + * @param usNRegs holding register number + * @param eMode read or write + * + * @return result + */ +// Callback function for reading of MB Holding Registers +// Executed by stack when request to read/write holding registers is received +eMBErrorCode eMBRegHoldingCBTcpMaster(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_ASSERT(pucRegBuffer != NULL); + USHORT usRegHoldingNregs = (USHORT)mbm_opts->mbm_reg_buffer_size; + UCHAR* pucHoldingBuffer = (UCHAR*)mbm_opts->mbm_reg_buffer_ptr; + eMBErrorCode eStatus = MB_ENOERR; + USHORT usRegs = usNRegs; + // Check input and configuration parameters for correctness + if ((pucHoldingBuffer != NULL) + && (usRegHoldingNregs == usNRegs) + && (usNRegs >= 1)) { + switch (eMode) { + case MB_REG_WRITE: + while (usRegs > 0) { + _XFER_2_RD(pucRegBuffer, pucHoldingBuffer); + usRegs -= 1; + }; + break; + case MB_REG_READ: + while (usRegs > 0) { + _XFER_2_WR(pucHoldingBuffer, pucRegBuffer); + pucHoldingBuffer += 2; + usRegs -= 1; + }; + break; + } + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master coils callback function. + * + * @param pucRegBuffer coils buffer + * @param usAddress coils address + * @param usNCoils coils number + * @param eMode read or write + * + * @return result + */ +// Callback function for reading of MB Coils Registers +eMBErrorCode eMBRegCoilsCBTcpMaster(UCHAR* pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_ASSERT(NULL != pucRegBuffer); + USHORT usRegCoilNregs = (USHORT)mbm_opts->mbm_reg_buffer_size; + UCHAR* pucRegCoilsBuf = (UCHAR*)mbm_opts->mbm_reg_buffer_ptr; + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT usCoils = usNCoils; + usAddress--; // The address is already + 1 + if ((usRegCoilNregs >= 1) + && (pucRegCoilsBuf != NULL) + && (usNCoils == usRegCoilNregs)) { + iRegIndex = (usAddress % 8); + switch (eMode) { + case MB_REG_WRITE: + while (usCoils > 0) { + UCHAR ucResult = xMBUtilGetBits((UCHAR*)pucRegCoilsBuf, iRegIndex, 1); + xMBUtilSetBits(pucRegBuffer, iRegIndex - (usAddress % 8) , 1, ucResult); + iRegIndex++; + usCoils--; + } + break; + case MB_REG_READ: + while (usCoils > 0) { + UCHAR ucResult = xMBUtilGetBits(pucRegBuffer, iRegIndex - (usAddress % 8), 1); + xMBUtilSetBits((uint8_t*)pucRegCoilsBuf, iRegIndex, 1, ucResult); + iRegIndex++; + usCoils--; + } + break; + } // switch ( eMode ) + } else { + // If the configuration or input parameters are incorrect then return error to stack + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master discrete callback function. + * + * @param pucRegBuffer discrete buffer + * @param usAddress discrete address + * @param usNDiscrete discrete number + * + * @return result + */ +// Callback function for reading of MB Discrete Input Registers +eMBErrorCode eMBRegDiscreteCBTcpMaster(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + MB_MASTER_ASSERT(pucRegBuffer != NULL); + USHORT usRegDiscreteNregs = (USHORT)mbm_opts->mbm_reg_buffer_size; + UCHAR* pucRegDiscreteBuf = (UCHAR*)mbm_opts->mbm_reg_buffer_ptr; + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegBitIndex, iNReg; + UCHAR* pucDiscreteInputBuf; + iNReg = usNDiscrete / 8 + 1; + pucDiscreteInputBuf = (UCHAR*) pucRegDiscreteBuf; + // It is already plus one in Modbus function method. + usAddress--; + if ((usRegDiscreteNregs >= 1) + && (pucRegDiscreteBuf != NULL) + && (usNDiscrete >= 1)) { + iRegBitIndex = (USHORT)(usAddress) % 8; // Get bit index + while (iNReg > 1) + { + xMBUtilSetBits(pucDiscreteInputBuf++, iRegBitIndex, 8, *pucRegBuffer++); + iNReg--; + } + // last discrete + usNDiscrete = usNDiscrete % 8; + // xMBUtilSetBits has bug when ucNBits is zero + if (usNDiscrete != 0) + { + xMBUtilSetBits(pucDiscreteInputBuf, iRegBitIndex, usNDiscrete, *pucRegBuffer++); + } + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} + +// Initialization of resources for Modbus TCP master controller +esp_err_t mbc_tcp_master_create(void** handler) +{ + // Allocate space for master interface structure + if (mbm_interface_ptr == NULL) { + mbm_interface_ptr = malloc(sizeof(mb_master_interface_t)); + } + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + + // Initialize interface properties + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + mbm_opts->port_type = MB_PORT_TCP_MASTER; + + vMBPortSetMode((UCHAR)MB_PORT_TCP_MASTER); + + mbm_opts->mbm_comm.ip_mode = MB_MODE_TCP; + mbm_opts->mbm_comm.ip_port = MB_TCP_DEFAULT_PORT; + + // Initialization of active context of the modbus controller + BaseType_t status = 0; + // Parameter change notification queue + mbm_opts->mbm_event_group = xEventGroupCreate(); + MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL), ESP_ERR_NO_MEM, "mb event group error."); + // Create modbus controller task + status = xTaskCreate((void*)&modbus_tcp_master_task, + "modbus_tcp_master_task", + MB_CONTROLLER_STACK_SIZE, + NULL, // No parameters + MB_CONTROLLER_PRIORITY, + &mbm_opts->mbm_task_handle); + if (status != pdPASS) { + vTaskDelete(mbm_opts->mbm_task_handle); + MB_MASTER_CHECK((status == pdPASS), ESP_ERR_NO_MEM, + "mb controller task creation error, xTaskCreate() returns (0x%x).", + (uint32_t)status); + } + MB_MASTER_ASSERT(mbm_opts->mbm_task_handle != NULL); // The task is created but handle is incorrect + + // Initialize public interface methods of the interface + mbm_interface_ptr->init = mbc_tcp_master_create; + mbm_interface_ptr->destroy = mbc_tcp_master_destroy; + mbm_interface_ptr->setup = mbc_tcp_master_setup; + mbm_interface_ptr->start = mbc_tcp_master_start; + mbm_interface_ptr->get_cid_info = mbc_tcp_master_get_cid_info; + mbm_interface_ptr->get_parameter = mbc_tcp_master_get_parameter; + mbm_interface_ptr->send_request = mbc_tcp_master_send_request; + mbm_interface_ptr->set_descriptor = mbc_tcp_master_set_descriptor; + mbm_interface_ptr->set_parameter = mbc_tcp_master_set_parameter; + + mbm_interface_ptr->master_reg_cb_discrete = eMBRegDiscreteCBTcpMaster; + mbm_interface_ptr->master_reg_cb_input = eMBRegInputCBTcpMaster; + mbm_interface_ptr->master_reg_cb_holding = eMBRegHoldingCBTcpMaster; + mbm_interface_ptr->master_reg_cb_coils = eMBRegCoilsCBTcpMaster; + + *handler = mbm_interface_ptr; + + return ESP_OK; +} diff --git a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.h b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.h new file mode 100644 index 000000000..612f8a1c7 --- /dev/null +++ b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.h @@ -0,0 +1,43 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// mbc_tcp_master.h Modbus controller TCP master implementation header file + +#ifndef _MODBUS_TCP_CONTROLLER_MASTER +#define _MODBUS_TCP_CONTROLLER_MASTER + +#include // for standard int types definition +#include // for NULL and std defines +#include "esp_modbus_common.h" // for common defines + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_INST_MIN_SIZE (2) // The minimal size of Modbus registers area in bytes +#define MB_INST_MAX_SIZE (CONFIG_MB_INST_MAX_SIZE) // The maximum size of Modbus area in bytes + +#define MB_CONTROLLER_NOTIFY_QUEUE_SIZE (CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue +#define MB_CONTROLLER_NOTIFY_TIMEOUT (pdMS_TO_TICKS(CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout + +/** + * @brief Create Modbus Master controller and stack for TCP port + * + * @param[out] handler handler(pointer) to master data structure + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + */ +esp_err_t mbc_tcp_master_create(void** handler); + +#endif // _MODBUS_TCP_CONTROLLER_SLAVE + diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.c b/components/freemodbus/tcp_master/port/port_tcp_master.c new file mode 100644 index 000000000..5ef3be220 --- /dev/null +++ b/components/freemodbus/tcp_master/port/port_tcp_master.c @@ -0,0 +1,946 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* + * FreeModbus Libary: ESP32 TCP Port + * Copyright (C) 2006 Christian Walter + * Parts of crt0.S Copyright (c) 1995, 1996, 1998 Cygnus Support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.h,v 1.2 2006/09/04 14:39:20 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include +#include +#include "esp_err.h" +#include "esp_timer.h" +/* ----------------------- lwIP includes ------------------------------------*/ +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#include "esp_netif.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb_m.h" +#include "port.h" +#include "mbport.h" +#include "mbframe.h" +#include "port_tcp_master.h" + +/* ----------------------- Defines -----------------------------------------*/ +#define MB_TCP_CONNECTION_TIMEOUT_MS ( 20 ) // Connection timeout in mS +#define MB_TCP_RECONNECT_TIMEOUT ( 5000000 ) // Connection timeout in uS + +#define MB_TCP_MASTER_PORT_TAG "MB_TCP_MASTER_PORT" +#define MB_EVENT_REQ_DONE_MASK ( EV_MASTER_PROCESS_SUCCESS | \ + EV_MASTER_ERROR_RESPOND_TIMEOUT | \ + EV_MASTER_ERROR_RECEIVE_DATA | \ + EV_MASTER_ERROR_EXECUTE_FUNCTION ) + +#define MB_EVENT_REQ_ERR_MASK ( EV_MASTER_PROCESS_SUCCESS ) + +#define MB_EVENT_WAIT_TOUT_MS ( 2000 ) + +#define MB_TCP_READ_TICK_MS ( 1 ) +#define MB_TCP_READ_BUF_RETRY_CNT ( 4 ) +#define MB_SLAVE_FMT(fmt) "Slave #%d, Socket(#%d)(%s)"fmt + +/* ----------------------- Types & Prototypes --------------------------------*/ +void vMBPortEventClose( void ); + +/* ----------------------- Static variables ---------------------------------*/ +static MbPortConfig_t xMbPortConfig; +static EventGroupHandle_t xMasterEventHandle = NULL; +static EventBits_t xMasterEvent = 0; + +/* ----------------------- Static functions ---------------------------------*/ +static void vMBTCPPortMasterTask(void *pvParameters); + +/* ----------------------- Begin implementation -----------------------------*/ + +// Waits for stack start event to start Modbus event processing +BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent) +{ + xMasterEventHandle = xEventHandle; + xMasterEvent = xEvent; + BaseType_t status = xEventGroupWaitBits(xMasterEventHandle, + (BaseType_t)(xEvent), + pdFALSE, // do not clear start bit + pdFALSE, + portMAX_DELAY); + return (BOOL)(status & xEvent); +} + +BOOL +xMBMasterTCPPortInit( USHORT usTCPPort ) +{ + BOOL bOkay = FALSE; + + xMbPortConfig.pxMbSlaveInfo = calloc(MB_TCP_PORT_MAX_CONN, sizeof(MbSlaveInfo_t*)); + if (!xMbPortConfig.pxMbSlaveInfo) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP slave info alloc failure."); + return FALSE; + } + for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xMbPortConfig.pxMbSlaveInfo[idx] = NULL, idx++); + + xMbPortConfig.xConnectQueue = NULL; + xMbPortConfig.usPort = usTCPPort; + xMbPortConfig.usMbSlaveInfoCount = 0; + xMbPortConfig.ucCurSlaveIndex = 1; + + xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(CHAR*)); + if (xMbPortConfig.xConnectQueue == 0) + { + // Queue was not created and must not be used. + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master queue creation failure."); + return FALSE; + } + + // Create task for packet processing + BaseType_t xErr = xTaskCreate(vMBTCPPortMasterTask, + "tcp_master_task", + MB_TCP_STACK_SIZE, + NULL, + MB_TCP_TASK_PRIO, + &xMbPortConfig.xMbTcpTaskHandle); + if (xErr != pdTRUE) + { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master task creation failure."); + (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); + } else { + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "TCP master stack initialized."); + bOkay = TRUE; + } + + vTaskSuspend(xMbPortConfig.xMbTcpTaskHandle); + return bOkay; +} + +static MbSlaveInfo_t* vMBTCPPortMasterGetCurrInfo(void) +{ + return xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.ucCurSlaveIndex - 1]; +} + +// Start Modbus event state machine +static void vMBTCPPortMasterStartPoll(void) +{ + if (xMasterEventHandle) { + // Set the mbcontroller start flag + EventBits_t xFlags = xEventGroupSetBits(xMasterEventHandle, + (EventBits_t)xMasterEvent); + if (!(xFlags & xMasterEvent)) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack."); + } + } +} + +// Stop Modbus event state machine +static void vMBTCPPortMasterStopPoll(void) +{ + if (xMasterEventHandle) { + // Set the mbcontroller start flag + EventBits_t xFlags = xEventGroupClearBits(xMasterEventHandle, + (EventBits_t)xMasterEvent); + if (!(xFlags & xMasterEvent)) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling."); + } + } +} + +// The helper function to get time stamp in microseconds +static int64_t xMBTCPGetTimeStamp(void) +{ + int64_t xTimeStamp = esp_timer_get_time(); + return xTimeStamp; +} + +static void vMBTCPPortMasterMStoTimeVal(USHORT usTimeoutMs, struct timeval *tv) +{ + tv->tv_sec = usTimeoutMs / 1000; + tv->tv_usec = (usTimeoutMs - (tv->tv_sec * 1000)) * 1000; +} + +static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo) +{ + if (!pxInfo) { + return FALSE; + } + if (pxInfo->xSockId == -1) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId); + return FALSE; + } + if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno); + } + close(pxInfo->xSockId); + pxInfo->xSockId = -1; + return TRUE; +} + +void vMBTCPPortMasterSetNetOpt(void* pvNetIf, eMBPortIpVer xIpVersion, eMBPortProto xProto) +{ + xMbPortConfig.pvNetIface = pvNetIf; + xMbPortConfig.eMbProto = xProto; + xMbPortConfig.eMbIpVer = xIpVersion; +} + +void vMBTCPPortMasterTaskStart(void) +{ + vTaskResume(xMbPortConfig.xMbTcpTaskHandle); +} + +// Function returns time left for response processing according to response timeout +static int64_t xMBTCPPortMasterGetRespTimeLeft(MbSlaveInfo_t* pxInfo) +{ + if (!pxInfo) { + return 0; + } + int64_t xTimeStamp = xMBTCPGetTimeStamp() - pxInfo->xSendTimeStamp; + return (xTimeStamp > (1000 * MB_MASTER_TIMEOUT_MS_RESPOND)) ? 0 : + (MB_MASTER_TIMEOUT_MS_RESPOND - (xTimeStamp / 1000) - 1); +} + +// Wait socket ready to read state +static int vMBTCPPortMasterRxCheck(int xSd, fd_set* pxFdSet, int xTimeMs) +{ + fd_set xReadSet = *pxFdSet; + fd_set xErrorSet = *pxFdSet; + int xRes = 0; + struct timeval xTimeout; + + vMBTCPPortMasterMStoTimeVal(xTimeMs, &xTimeout); + xRes = select(xSd + 1, &xReadSet, NULL, &xErrorSet, &xTimeout); + if (xRes == 0) { + // No respond from slave during timeout + xRes = ERR_TIMEOUT; + } else if ((xRes < 0) || FD_ISSET(xSd, &xErrorSet)) { + xRes = -1; + } + + *pxFdSet = xReadSet; + return xRes; +} + +static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHORT usLength) +{ + int xLength = 0; + UCHAR* pucBuf = pucDstBuf; + USHORT usBytesLeft = usLength; + + MB_PORT_CHECK((pxInfo && pxInfo->xSockId > -1), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId); + + // Receive data from connected client + while (usBytesLeft > 0) { + // none blocking read from socket with timeout + xLength = recv(pxInfo->xSockId, pucBuf, usBytesLeft, MSG_DONTWAIT); + if (xLength < 0) { + if (errno == EAGAIN) { + // Read timeout occurred, continue reading + continue; + } else if (errno == ENOTCONN) { + // Socket connection closed + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection closed.", + pxInfo->xSockId, pxInfo->pcIpAddr); + return ERR_CONN; + } else { + // Other error occurred during receiving + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d", + pxInfo->xSockId, pxInfo->pcIpAddr, xLength, errno); + return -1; + } + } else if (xLength) { + pucBuf += xLength; + usBytesLeft -= xLength; + } + if (xMBTCPPortMasterGetRespTimeLeft(pxInfo) == 0) { + return ERR_TIMEOUT; + } + vTaskDelay(1); + } + return usLength; +} + +static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) +{ + int xLength = 0; + int xRet = 0; + USHORT usTidRcv = 0; + + // Receive data from connected client + if (pxInfo) { + MB_PORT_CHECK((pxInfo->xSockId > 0), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId); + // Read packet header + xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[0], MB_TCP_UID); + if (xRet < 0) { + pxInfo->xRcvErr = xRet; + return xRet; + } else if (xRet != MB_TCP_UID) { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d", + pxInfo->xSockId, pxInfo->pcIpAddr, xRet); + pxInfo->xRcvErr = ERR_VAL; + return ERR_VAL; + } + // If we have received the MBAP header we can analyze it and calculate + // the number of bytes left to complete the current request. + xLength = (int)MB_TCP_GET_FIELD(pxInfo->pucRcvBuf, MB_TCP_LEN); + xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[MB_TCP_UID], xLength); + if (xRet < 0) { + pxInfo->xRcvErr = xRet; + return xRet; + } else if (xRet != xLength) { + // Received incorrect or fragmented packet. + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)", + pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, + usTidRcv, errno, strerror(errno)); + pxInfo->xRcvErr = ERR_VAL; + return ERR_VAL; + } + usTidRcv = MB_TCP_GET_FIELD(pxInfo->pucRcvBuf, MB_TCP_TID); + + // Check transaction identifier field in the incoming packet. + if ((pxInfo->usTidCnt - 1) != usTidRcv) { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.", + pxInfo->xSockId, pxInfo->pcIpAddr, usTidRcv, (pxInfo->usTidCnt - 1)); + pxInfo->xRcvErr = ERR_BUF; + return ERR_BUF; + } + pxInfo->usRcvPos += xRet + MB_TCP_UID; + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)", + pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, + usTidRcv, errno, strerror(errno)); + pxInfo->xRcvErr = ERR_OK; + return pxInfo->usRcvPos; + } + return -1; +} + +static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo) +{ + // Set non blocking attribute for socket + ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL); + if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), fcntl() call error=%d", + pxInfo->xSockId, pxInfo->pcIpAddr, errno); + return ERR_WOULDBLOCK; + } + return ERR_OK; +} + +static void vMBTCPPortSetKeepAlive(MbSlaveInfo_t* pxInfo) +{ + int optval = 1; + setsockopt(pxInfo->xSockId, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); +} + +// Check connection for timeout helper +static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs) +{ + fd_set xWriteSet; + fd_set xErrorSet; + err_t xErr = -1; + struct timeval xTimeVal; + + if (pxInfo && pxInfo->xSockId != -1) { + FD_ZERO(&xWriteSet); + FD_ZERO(&xErrorSet); + FD_SET(pxInfo->xSockId, &xWriteSet); + FD_SET(pxInfo->xSockId, &xErrorSet); + vMBTCPPortMasterMStoTimeVal(xTimeoutMs, &xTimeVal); + // Check if the socket is writable + xErr = select(pxInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal); + if ((xErr < 0) || FD_ISSET(pxInfo->xSockId, &xErrorSet)) { + if (errno == EINPROGRESS) { + xErr = ERR_INPROGRESS; + } else { + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); + xErr = ERR_CONN; + } + } else if (xErr == 0) { + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).", + pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); + return ERR_INPROGRESS; + } else { + int xOptErr = 0; + ULONG ulOptLen = sizeof(xOptErr); + // Check socket error + xErr = getsockopt(pxInfo->xSockId, SOL_SOCKET, SO_ERROR, (void*)&xOptErr, (socklen_t*)&ulOptLen); + if (xOptErr != 0) { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), sock error occurred (%d).", + pxInfo->xSockId, pxInfo->pcIpAddr, xOptErr); + return ERR_CONN; + } + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), is alive.", + pxInfo->xSockId, pxInfo->pcIpAddr); + return ERR_OK; + } + } else { + xErr = ERR_CONN; + } + return xErr; +} + +// Resolve host name and/or fill the IP address structure +static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAddr) +{ + MB_PORT_CHECK((pcHostStr), FALSE, "Wrong host name or IP."); + CHAR cStr[45]; + CHAR* pcStr = &cStr[0]; + ip_addr_t xTargetAddr; + struct addrinfo xHint; + struct addrinfo* pxAddrList; + memset(&xHint, 0, sizeof(xHint)); + // Do name resolution for both protocols + xHint.ai_family = AF_UNSPEC; + xHint.ai_flags = AI_ADDRCONFIG; // get IPV6 address if supported, otherwise IPV4 + memset(&xTargetAddr, 0, sizeof(xTargetAddr)); + + // convert domain name to IP address + // Todo: check EAI_FAIL error when resolve host name + int xRet = getaddrinfo(pcHostStr, NULL, &xHint, &pxAddrList); + + if (xRet != 0) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect host name or IP: %s", pcHostStr); + return FALSE; + } + if (pxAddrList->ai_family == AF_INET) { + struct in_addr addr4 = ((struct sockaddr_in *) (pxAddrList->ai_addr))->sin_addr; + inet_addr_to_ip4addr(ip_2_ip4(&xTargetAddr), &addr4); + pcStr = ip4addr_ntoa_r(ip_2_ip4(&xTargetAddr), cStr, sizeof(cStr)); + } +#if LWIP_IPV6 + else { + struct in6_addr addr6 = ((struct sockaddr_in6 *) (pxAddrList->ai_addr))->sin6_addr; + inet6_addr_to_ip6addr(ip_2_ip6(&xTargetAddr), &addr6); + pcStr = ip6addr_ntoa_r(ip_2_ip6(&xTargetAddr), cStr, sizeof(cStr)); + } +#endif + if (pxHostAddr) { + *pxHostAddr = xTargetAddr; + } + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr); + freeaddrinfo(pxAddrList); + return TRUE; +} + +BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr) +{ + BOOL xRes = FALSE; + MB_PORT_CHECK(xMbPortConfig.xConnectQueue != NULL, FALSE, "Wrong slave IP address to add."); + if (pcIpStr) { + xRes = xMBTCPPortMasterCheckHost(pcIpStr, NULL); + } + if (xRes || !pcIpStr) { + BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (const void*)&pcIpStr, 100); + MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to add slave IP address: [%s].", pcIpStr); + } + return xRes; +} + +// Unblocking connect function +static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) +{ + err_t xErr = ERR_OK; + CHAR cStr[128]; + CHAR* pcStr = NULL; + ip_addr_t xTargetAddr; + struct addrinfo xHint; + struct addrinfo* pxAddrList; + struct addrinfo* pxCurAddr; + + memset(&xHint, 0, sizeof(xHint)); + // Do name resolution for both protocols + //xHint.ai_family = AF_UNSPEC; Todo: Find a reason why AF_UNSPEC does not work + xHint.ai_flags = AI_ADDRCONFIG; // get IPV6 address if supported, otherwise IPV4 + xHint.ai_family = (xMbPortConfig.eMbIpVer == MB_PORT_IPV4) ? AF_INET : AF_INET6; + xHint.ai_socktype = (pxInfo->xMbProto == MB_PROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; + xHint.ai_protocol = (pxInfo->xMbProto == MB_PROTO_UDP) ? IPPROTO_UDP : IPPROTO_TCP; + memset(&xTargetAddr, 0, sizeof(xTargetAddr)); + + if (asprintf(&pcStr, "%u", xMbPortConfig.usPort) == -1) { + abort(); + } + + // convert domain name to IP address + int xRet = getaddrinfo(pxInfo->pcIpAddr, pcStr, &xHint, &pxAddrList); + free(pcStr); + if (xRet != 0) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr); + return ERR_CONN; + } + + for (pxCurAddr = pxAddrList; pxCurAddr != NULL; pxCurAddr = pxCurAddr->ai_next) { + if (pxCurAddr->ai_family == AF_INET) { + struct in_addr addr4 = ((struct sockaddr_in *) (pxCurAddr->ai_addr))->sin_addr; + inet_addr_to_ip4addr(ip_2_ip4(&xTargetAddr), &addr4); + pcStr = ip4addr_ntoa_r(ip_2_ip4(&xTargetAddr), cStr, sizeof(cStr)); + } +#if LWIP_IPV6 + else if (pxCurAddr->ai_family == AF_INET6) { + struct in6_addr addr6 = ((struct sockaddr_in6 *) (pxCurAddr->ai_addr))->sin6_addr; + inet6_addr_to_ip6addr(ip_2_ip6(&xTargetAddr), &addr6); + pcStr = ip6addr_ntoa_r(ip_2_ip6(&xTargetAddr), cStr, sizeof(cStr)); + // Set scope id to fix routing issues with local address + ((struct sockaddr_in6 *) (pxCurAddr->ai_addr))->sin6_scope_id = + tcpip_adapter_get_netif_index(TCPIP_ADAPTER_IF_STA); + } +#endif + if (pxInfo->xSockId <= 0) { + pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol); + if (pxInfo->xSockId < 0) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno); + xErr = ERR_IF; + continue; + } + } else { + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr); + } + + // Set non blocking attribute for socket + xMBTCPPortMasterSetNonBlocking(pxInfo); + + // Can return EINPROGRESS as an error which means + // that connection is in progress and should be checked later + xErr = connect(pxInfo->xSockId, (struct sockaddr*)pxCurAddr->ai_addr, pxCurAddr->ai_addrlen); + if ((xErr < 0) && (errno == EINPROGRESS || errno == EALREADY)) { + // The unblocking connect is pending (check status later) or already connected + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).", + pxInfo->xSockId, cStr, errno, strerror(errno)); + + // Set keep alive flag in socket options + vMBTCPPortSetKeepAlive(pxInfo); + xErr = xMBTCPPortMasterCheckAlive(pxInfo, MB_TCP_CONNECTION_TIMEOUT_MS); + continue; + } else if ((xErr < 0) && (errno == EISCONN)) { + // Socket already connected + xErr = ERR_OK; + continue; + } else if (xErr != ERR_OK) { + // Other error occurred during connection + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"), + pxInfo->xIndex, pxInfo->xSockId, cStr, xErr, errno, strerror(errno)); + xMBTCPPortMasterCloseConnection(pxInfo); + xErr = ERR_CONN; + } else { + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", successfully connected."), + pxInfo->xIndex, pxInfo->xSockId, cStr); + continue; + } + } + freeaddrinfo(pxAddrList); + return xErr; +} + +// Find the first slave info whose descriptor is set in xFdSet +static MbSlaveInfo_t* xMBTCPPortMasterGetSlaveReady(fd_set* pxFdSet) +{ + MbSlaveInfo_t* pxInfo = NULL; + + // Slave connection loop + for (int xIndex = 0; (xIndex < MB_TCP_PORT_MAX_CONN); xIndex++) { + pxInfo = xMbPortConfig.pxMbSlaveInfo[xIndex]; + if (pxInfo) { + // Is this response for current processing slave + if (FD_ISSET(pxInfo->xSockId, pxFdSet)) { + FD_CLR(pxInfo->xSockId, pxFdSet); + return pxInfo; + } + } + } + return (MbSlaveInfo_t*)NULL; +} + +static int xMBTCPPortMasterCheckConnState(fd_set* pxFdSet) +{ + fd_set xConnSetCheck = *pxFdSet; + MbSlaveInfo_t* pxInfo = NULL; + int64_t xTime = 0; + int xErr = 0; + int xCount = 0; + do { + xTime = xMBTCPGetTimeStamp(); + pxInfo = xMBTCPPortMasterGetSlaveReady(&xConnSetCheck); + if (pxInfo) { + xErr = xMBTCPPortMasterCheckAlive(pxInfo, 0); + if ((xErr < 0) && (((xTime - pxInfo->xRecvTimeStamp) > MB_TCP_RECONNECT_TIMEOUT) || + ((xTime - pxInfo->xSendTimeStamp) > MB_TCP_RECONNECT_TIMEOUT))) { + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."), + pxInfo->xIndex, + pxInfo->xSockId, + pxInfo->pcIpAddr, + (int64_t)(xTime - pxInfo->xRecvTimeStamp), + (int64_t)(xTime - pxInfo->xSendTimeStamp)); + xCount++; + } + } + } while (pxInfo && (xCount < MB_TCP_PORT_MAX_CONN)); + return xCount; +} + +static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMasterEventType xPostEvent) +{ + vMBMasterPortTimersDisable(); + vMBMasterSetErrorType(xErrType); + xMBMasterPortEventPost(xPostEvent); +} + +static void vMBTCPPortMasterTask(void *pvParameters) +{ + CHAR* pcAddrStr = NULL; + MbSlaveInfo_t* pxInfo; + MbSlaveInfo_t* pxCurrInfo; + fd_set xConnSet; + fd_set xReadSet; + int xMaxSd = 0; + err_t xErr = ERR_ABRT; + USHORT usSlaveConnCnt = 0; + int64_t xTime = 0; + + // Register each slave in the connection info structure + while (1) { + BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, portMAX_DELAY); + if (xStatus != pdTRUE) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP."); + } else { + if (pcAddrStr == NULL && xMbPortConfig.usMbSlaveInfoCount) { + break; + } + if (xMbPortConfig.usMbSlaveInfoCount > MB_TCP_PORT_MAX_CONN) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN); + break; + } + pxInfo = calloc(1, sizeof(MbSlaveInfo_t)); + if (!pxInfo) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), info structure allocation fail.", + xMbPortConfig.usMbSlaveInfoCount); + free(pxInfo); + break; + } + pxInfo->pucRcvBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); + if (!pxInfo->pucRcvBuf) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), receive buffer allocation fail.", + xMbPortConfig.usMbSlaveInfoCount); + free(pxInfo->pucRcvBuf); + break; + } + pxInfo->usRcvPos = 0; + pxInfo->pcIpAddr = pcAddrStr; + pxInfo->xSockId = -1; + pxInfo->xError = -1; + pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); + pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); + pxInfo->xMbProto = MB_PROTO_TCP; + pxInfo->xIndex = xMbPortConfig.usMbSlaveInfoCount; + pxInfo->usTidCnt = (USHORT)(xMbPortConfig.usMbSlaveInfoCount << 8U); + // Register slave + xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.usMbSlaveInfoCount++] = pxInfo; + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Add slave IP: %s", pcAddrStr); + } + } + + // Main connection cycle + while (1) + { + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connecting to slaves..."); + xTime = xMBTCPGetTimeStamp(); + usSlaveConnCnt = 0; + CHAR ucDot = '.'; + while(usSlaveConnCnt < xMbPortConfig.usMbSlaveInfoCount) { + usSlaveConnCnt = 0; + FD_ZERO(&xConnSet); + ucDot ^= 0x03; + // Slave connection loop + for (UCHAR ucCnt = 0; (ucCnt < MB_TCP_PORT_MAX_CONN); ucCnt++) { + pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt]; + // if slave descriptor is NULL then it is end of list or connection closed. + if (!pxInfo) { + ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Index: %d is not initialized, skip.", ucCnt); + if (xMbPortConfig.usMbSlaveInfoCount) { + continue; + } + break; + } + putchar(ucDot); + xErr = xMBTCPPortMasterConnect(pxInfo); + switch(xErr) + { + case ERR_CONN: + case ERR_INPROGRESS: + // In case of connection errors remove the socket from set + if (FD_ISSET(pxInfo->xSockId, &xConnSet)) { + FD_CLR(pxInfo->xSockId, &xConnSet); + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connect failed, error = %d."), + pxInfo->xIndex, pxInfo->xSockId, + (char*)pxInfo->pcIpAddr, xErr); + if (usSlaveConnCnt) { + usSlaveConnCnt--; + } + } + break; + case ERR_OK: + // if connection is successful, add the descriptor into set + if (!FD_ISSET(pxInfo->xSockId, &xConnSet)) { + FD_SET(pxInfo->xSockId, &xConnSet); + usSlaveConnCnt++; + xMaxSd = (pxInfo->xSockId > xMaxSd) ? pxInfo->xSockId : xMaxSd; + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."), + pxInfo->xIndex, pxInfo->xSockId, + pxInfo->pcIpAddr, + usSlaveConnCnt, xErr); + // Update time stamp for connected slaves + pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); + pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); + } + break; + default: + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", unexpected error = %d."), + pxInfo->xIndex, + pxInfo->xSockId, + pxInfo->pcIpAddr, xErr); + break; + } + pxInfo->xError = xErr; + } + } + ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); + vMBTCPPortMasterStartPoll(); // Send event to start stack + + // Slave receive data loop + while(usSlaveConnCnt) { + xReadSet = xConnSet; + // Check transmission event to clear appropriate bit. + xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_TRANSMIT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); + // Synchronize state machine with send packet event + if (xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_SENT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS))) { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "FSM Synchronized with sent event."); + } + // Get slave info for the current slave. + pxCurrInfo = vMBTCPPortMasterGetCurrInfo(); + if (!pxCurrInfo) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.", + xMbPortConfig.ucCurSlaveIndex); + vMBTCPPortMasterStopPoll(); + break; // incorrect slave descriptor, reconnect. + } + xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Set select timeout, left time: %ju ms.", + xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); + // Wait respond from current slave during respond timeout + int xRes = vMBTCPPortMasterRxCheck(pxCurrInfo->xSockId, &xReadSet, xTime); + if (xRes == ERR_TIMEOUT) { + // No respond from current slave, process timeout. + // Need to drop response later if it is received after timeout. + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Select timeout, left time: %ju ms.", + xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); + xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); + // Wait completion of last transaction + xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime + 1)); + continue; + } else if (xRes < 0) { + // Select error (slave connection or r/w failure). + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); + xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); + // Wait completion of last transaction + xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime)); + // Stop polling process + vMBTCPPortMasterStopPoll(); + // Check disconnected slaves, do not need a result just to print information. + xMBTCPPortMasterCheckConnState(&xConnSet); + break; + } else { + // Check to make sure that active slave data is ready + if (FD_ISSET(pxCurrInfo->xSockId, &xReadSet)) { + xErr = ERR_BUF; + for (int retry = 0; (xErr == ERR_BUF) && (retry < MB_TCP_READ_BUF_RETRY_CNT); retry++) { + xErr = vMBTCPPortMasterReadPacket(pxCurrInfo); + // The error ERR_BUF means received response to previous request + // (due to timeout) with the same socket ID and incorrect TID, + // then ignore it and try to get next response buffer. + } + if (xErr > 0) { + // Response received correctly, send an event to stack + xMBTCPPortMasterFsmSetError(EV_ERROR_INIT, EV_MASTER_FRAME_RECEIVED); + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame received."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); + } else if ((xErr == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) { + // Timeout occurred when receiving frame, process respond timeout + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame read timeout."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); + } else if (xErr == ERR_BUF) { + // After retries a response with incorrect TID received, process failure. + xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS); + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame error."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); + } else { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", critical error=%d."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xErr); + // Stop polling process + vMBTCPPortMasterStopPoll(); + // Check disconnected slaves, do not need a result just to print information. + xMBTCPPortMasterCheckConnState(&xConnSet); + break; + } + xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime); + // Wait completion of Modbus frame processing before start of new transaction. + if (xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime))) { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", data processing completed."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); + } + xTime = xMBTCPGetTimeStamp() - pxCurrInfo->xSendTimeStamp; + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", processing time[us] = %ju."), + pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime); + } + } + } // while(usMbSlaveInfoCount) + } // while (1) + vTaskDelete(NULL); +} + +extern void vMBMasterPortEventClose(void); +extern void vMBMasterPortTimerClose(void); + +void +vMBMasterTCPPortClose(void) +{ + (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); + (void)vMBMasterTCPPortDisable(); + free(xMbPortConfig.pxMbSlaveInfo); + vQueueDelete(xMbPortConfig.xConnectQueue); + vMBMasterPortTimerClose(); + // Release resources for the event queue. + vMBMasterPortEventClose(); +} + +void +vMBMasterTCPPortDisable(void) +{ + for (USHORT ucCnt = 0; ucCnt < MB_TCP_PORT_MAX_CONN; ucCnt++) { + MbSlaveInfo_t* pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt]; + if (pxInfo) { + xMBTCPPortMasterCloseConnection(pxInfo); + if (pxInfo->pucRcvBuf) { + free(pxInfo->pucRcvBuf); + } + free(pxInfo); + xMbPortConfig.pxMbSlaveInfo[ucCnt] = NULL; + } + } +} + +BOOL +xMBMasterTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength ) +{ + MbSlaveInfo_t* pxInfo = vMBTCPPortMasterGetCurrInfo(); + *ppucMBTCPFrame = pxInfo->pucRcvBuf; + *usTCPLength = pxInfo->usRcvPos; + + // Reset the buffer. + pxInfo->usRcvPos = 0; + // Save slave receive timestamp + if (pxInfo->xRcvErr == ERR_OK && *usTCPLength > 0) { + pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); + return TRUE; + } + return FALSE; +} + +int xMBMasterTCPPortWritePoll(MbSlaveInfo_t* pxInfo, const UCHAR * pucMBTCPFrame, USHORT usTCPLength, ULONG xTimeout) +{ + // Check if the socket is alive (writable and SO_ERROR == 0) + int xRes = (int)xMBTCPPortMasterCheckAlive(pxInfo, xTimeout); + if ((xRes < 0) && (xRes != ERR_INPROGRESS)) + { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); + return xRes; + } + xRes = send(pxInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); + if (xRes < 0) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); + } + return xRes; +} + +BOOL +xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) +{ + BOOL bFrameSent = FALSE; + xMbPortConfig.ucCurSlaveIndex = ucMBMasterGetDestAddress(); + MbSlaveInfo_t* pxInfo = vMBTCPPortMasterGetCurrInfo(); + + // If socket active then send data + if (pxInfo->xSockId > -1) { + // Apply TID field to the frame before send + pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U); + pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF); + int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS); + if (xRes < 0) { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); + bFrameSent = FALSE; + pxInfo->xError = xRes; + } else { + bFrameSent = TRUE; + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno); + pxInfo->xError = 0; + pxInfo->usRcvPos = 0; + if (pxInfo->usTidCnt < (USHRT_MAX - 1)) { + pxInfo->usTidCnt++; + } else { + pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U); + } + } + pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); + } else { + ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send to died slave, error = %d"), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->xError); + } + vMBMasterPortTimersRespondTimeoutEnable(); + xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); + return bFrameSent; +} + +// Timer handler to check timeout of socket response +BOOL MB_PORT_ISR_ATTR +xMBMasterTCPTimerExpired(void) +{ + BOOL xNeedPoll = FALSE; + + vMBMasterPortTimersDisable(); + // If timer mode is respond timeout, the master event then turns EV_MASTER_EXECUTE status. + if (xMBMasterGetCurTimerMode() == MB_TMODE_RESPOND_TIMEOUT) { + vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT); + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + } + + return xNeedPoll; +} diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.h b/components/freemodbus/tcp_master/port/port_tcp_master.h new file mode 100644 index 000000000..c1b0b816e --- /dev/null +++ b/components/freemodbus/tcp_master/port/port_tcp_master.h @@ -0,0 +1,133 @@ + /* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + /* + * FreeModbus Libary: ESP32 TCP Port + * Copyright (C) 2006 Christian Walter + * Parts of crt0.S Copyright (c) 1995, 1996, 1998 Cygnus Support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.h,v 1.2 2006/09/04 14:39:20 wolti Exp $ + */ + +#ifndef _PORT_TCP_SLAVE_H +#define _PORT_TCP_SLAVE_H + +/* ----------------------- Platform includes --------------------------------*/ +#include "esp_log.h" + +#include "lwip/sys.h" +#include "freertos/event_groups.h" +#include "port.h" + +/* ----------------------- Defines ------------------------------------------*/ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Type definitions ---------------------------------*/ + +typedef struct { + int xIndex; /*!< Slave information index */ + int xSockId; /*!< Socket ID of slave */ + int xError; /*!< Socket error */ + int xRcvErr; /*!< Socket receive error */ + const char* pcIpAddr; /*!< TCP/UDP IP address */ + UCHAR* pucRcvBuf; /*!< Receive buffer pointer */ + USHORT usRcvPos; /*!< Receive buffer position */ + int pcPort; /*!< TCP/UDP port number */ + eMBPortProto xMbProto; /*!< Protocol type */ + int64_t xSendTimeStamp; /*!< Send request time stamp */ + int64_t xRecvTimeStamp; /*!< Receive response time stamp */ + uint16_t usTidCnt; /*!< Transaction identifier (TID) for slave */ +} MbSlaveInfo_t; + +typedef struct { + TaskHandle_t xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */ + QueueHandle_t xConnectQueue; /*!< Master connection queue */ + USHORT usPort; /*!< Master TCP/UDP port number */ + USHORT usMbSlaveInfoCount; /*!< Master count of connected slaves */ + USHORT ucCurSlaveIndex; /*!< Master current processing slave index */ + eMBPortIpVer eMbIpVer; /*!< Master IP version */ + eMBPortProto eMbProto; /*!< Master protocol type */ + void* pvNetIface; /*!< Master netif interface pointer */ + MbSlaveInfo_t** pxMbSlaveInfo; /*!< Master information structure for each connected slave */ +} MbPortConfig_t; + +/* ----------------------- Function prototypes ------------------------------*/ + +// The functions below are used by Modbus controller interface to configure Modbus port. +/** + * Registers slave IP address + * + * @param pcIpStr IP address to register + * + * @return TRUE if address registered successfully, else FALSE + */ +BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr); + +/** + * Keeps FSM event handle and mask then wait for Master stack to start + * + * @param xEventHandle Master event handle + * @param xEvent event mask to start Modbus stack FSM + * + * @return TRUE if stack started, else FALSE + */ +BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent); + +/** + * Set network options for Master port + * + * @param pvNetIf netif interface pointer + * @param xIpVersion IP version option for the Master port + * @param xProto Protocol version option for the Master port + * + * @return None + */ +void vMBTCPPortMasterSetNetOpt(void* pvNetIf, eMBPortIpVer xIpVersion, eMBPortProto xProto); + +/** + * Resume TCP/UDP Master processing task + * + * @return None + */ +void vMBTCPPortMasterTaskStart(void); + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c new file mode 100644 index 000000000..edaf039d2 --- /dev/null +++ b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c @@ -0,0 +1,484 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// mbc_tcp_slave.c +// Implementation of the Modbus controller TCP slave + +#include // for calculation of time stamp in milliseconds +#include "esp_log.h" // for log_write +#include "mb.h" // for mb types definition +#include "mbutils.h" // for mbutils functions definition for stack callback +#include "port.h" // for port callback functions and defines +#include "sdkconfig.h" // for KConfig values +#include "esp_modbus_common.h" // for common defines +#include "esp_modbus_slave.h" // for public slave interface types +#include "mbc_slave.h" // for private slave interface types +#include "mbc_tcp_slave.h" // for tcp slave mb controller defines +#include "port_tcp_slave.h" // for tcp slave port defines +#include "esp_timer.h" +// Shared pointer to interface structure +static mb_slave_interface_t* mbs_interface_ptr = NULL; + +// The helper function to get time stamp in microseconds +static uint64_t get_time_stamp(void) +{ + uint64_t time_stamp = esp_timer_get_time(); + return time_stamp; +} + +// Modbus task function +static void modbus_tcp_slave_task(void *pvParameters) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + + // Main Modbus stack processing cycle + for (;;) { + BaseType_t status = xEventGroupWaitBits(mbs_opts->mbs_event_group, + (BaseType_t)(MB_EVENT_STACK_STARTED), + pdFALSE, // do not clear bits + pdFALSE, + portMAX_DELAY); + // Check if stack started then poll for data + if (status & MB_EVENT_STACK_STARTED) { + (void)eMBPoll(); // allow stack to process data + } + } +} + +// Setup Modbus controller parameters +static esp_err_t mbc_tcp_slave_setup(void* comm_info) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_CHECK((comm_info != NULL), ESP_ERR_INVALID_ARG, + "mb wrong communication settings."); + mb_communication_info_t* comm_settings = (mb_communication_info_t*)comm_info; + MB_SLAVE_CHECK((comm_settings->ip_mode == MB_MODE_TCP), + ESP_ERR_INVALID_ARG, "mb incorrect mode = (0x%x).", (uint8_t)comm_settings->ip_mode); + MB_SLAVE_CHECK(((comm_settings->ip_addr_type == MB_IPV4) || (comm_settings->ip_addr_type == MB_IPV6)), + ESP_ERR_INVALID_ARG, "mb incorrect addr type = (0x%x).", (uint8_t)comm_settings->ip_addr_type); + MB_SLAVE_CHECK((comm_settings->ip_netif_ptr != NULL), + ESP_ERR_INVALID_ARG, "mb incorrect iface address."); + // Set communication options of the controller + mbs_opts->mbs_comm = *comm_settings; + return ESP_OK; +} + +// Start Modbus controller start function +static esp_err_t mbc_tcp_slave_start(void) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + eMBErrorCode status = MB_EIO; + + // Initialize Modbus stack using mbcontroller parameters + status = eMBTCPInit((USHORT)mbs_opts->mbs_comm.ip_port); + MB_SLAVE_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, + "mb stack initialization failure, eMBInit() returns (0x%x).", status); + + eMBPortProto proto = (mbs_opts->mbs_comm.ip_mode == MB_MODE_TCP) ? MB_PROTO_TCP : MB_PROTO_UDP; + eMBPortIpVer ip_ver = (mbs_opts->mbs_comm.ip_addr_type == MB_IPV4) ? MB_PORT_IPV4 : MB_PORT_IPV6; + vMBTCPPortSlaveSetNetOpt(mbs_opts->mbs_comm.ip_netif_ptr, ip_ver, proto, (char*)mbs_opts->mbs_comm.ip_addr); + vMBTCPPortSlaveStartServerTask(); + + status = eMBEnable(); + MB_SLAVE_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, + "mb TCP stack start failure, eMBEnable() returned (0x%x).", (uint32_t)status); + // Set the mbcontroller start flag + EventBits_t flag = xEventGroupSetBits(mbs_opts->mbs_event_group, + (EventBits_t)MB_EVENT_STACK_STARTED); + MB_SLAVE_CHECK((flag & MB_EVENT_STACK_STARTED), + ESP_ERR_INVALID_STATE, "mb stack start event set error."); + return ESP_OK; +} + +// Modbus controller destroy function +static esp_err_t mbc_tcp_slave_destroy(void) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + eMBErrorCode mb_error = MB_ENOERR; + // Stop polling by clearing correspondent bit in the event group + EventBits_t flag = xEventGroupClearBits(mbs_opts->mbs_event_group, + (EventBits_t)MB_EVENT_STACK_STARTED); + MB_SLAVE_CHECK((flag & MB_EVENT_STACK_STARTED), + ESP_ERR_INVALID_STATE, "mb stack stop event failure."); + // Disable and then destroy the Modbus stack + mb_error = eMBDisable(); + MB_SLAVE_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure."); + (void)vTaskDelete(mbs_opts->mbs_task_handle); + (void)vQueueDelete(mbs_opts->mbs_notification_queue_handle); + (void)vEventGroupDelete(mbs_opts->mbs_event_group); + (void)vMBTCPPortClose(); + free(mbs_interface_ptr); + vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); + mbs_interface_ptr = NULL; + return ESP_OK; +} + +esp_err_t mbc_tcp_slave_set_descriptor(const mb_register_area_descriptor_t descr_info) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_CHECK(((descr_info.type < MB_PARAM_COUNT) && (descr_info.type >= MB_PARAM_HOLDING)), + ESP_ERR_INVALID_ARG, "mb incorrect modbus instance type = (0x%x).", + (uint32_t)descr_info.type); + MB_SLAVE_CHECK((descr_info.address != NULL), + ESP_ERR_INVALID_ARG, "mb instance pointer is NULL."); + MB_SLAVE_CHECK((descr_info.size >= MB_INST_MIN_SIZE) && (descr_info.size < (MB_INST_MAX_SIZE)), + ESP_ERR_INVALID_ARG, "mb instance size is incorrect = (0x%x).", + (uint32_t)descr_info.size); + mbs_opts->mbs_area_descriptors[descr_info.type] = descr_info; + return ESP_OK; +} + +// Helper function to send parameter information to application task +static esp_err_t send_param_info(mb_event_group_t par_type, uint16_t mb_offset, + uint8_t* par_address, uint16_t par_size) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + esp_err_t error = ESP_FAIL; + mb_param_info_t par_info; + // Check if queue is not full the send parameter information + par_info.type = par_type; + par_info.size = par_size; + par_info.address = par_address; + par_info.time_stamp = get_time_stamp(); + par_info.mb_offset = mb_offset; + BaseType_t status = xQueueSend(mbs_opts->mbs_notification_queue_handle, + &par_info, MB_PAR_INFO_TOUT); + if (pdTRUE == status) { + ESP_LOGD(MB_SLAVE_TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d", + par_type, (uint32_t)par_address, par_size); + error = ESP_OK; + } else if (errQUEUE_FULL == status) { + ESP_LOGD(MB_SLAVE_TAG, "Parameter queue is overflowed."); + } + return error; +} + +// Helper function to send notification +static esp_err_t send_param_access_notification(mb_event_group_t event) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + esp_err_t err = ESP_FAIL; + mb_event_group_t bits = (mb_event_group_t)xEventGroupSetBits(mbs_opts->mbs_event_group, + (EventBits_t)event); + if (bits & event) { + ESP_LOGD(MB_SLAVE_TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event); + err = ESP_OK; + } + return err; +} + +// Blocking function to get event on parameter group change for application task +static mb_event_group_t mbc_tcp_slave_check_event(mb_event_group_t group) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_ASSERT(mbs_opts->mbs_event_group != NULL); + BaseType_t status = xEventGroupWaitBits(mbs_opts->mbs_event_group, (BaseType_t)group, + pdTRUE , pdFALSE, portMAX_DELAY); + return (mb_event_group_t)status; +} + +// Function to get notification about parameter change from application task +static esp_err_t mbc_tcp_slave_get_param_info(mb_param_info_t* reg_info, uint32_t timeout) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + esp_err_t err = ESP_ERR_TIMEOUT; + MB_SLAVE_CHECK((mbs_opts->mbs_notification_queue_handle != NULL), + ESP_ERR_INVALID_ARG, "mb queue handle is invalid."); + MB_SLAVE_CHECK((reg_info != NULL), ESP_ERR_INVALID_ARG, "mb register information is invalid."); + BaseType_t status = xQueueReceive(mbs_opts->mbs_notification_queue_handle, + reg_info, pdMS_TO_TICKS(timeout)); + if (status == pdTRUE) { + err = ESP_OK; + } + return err; +} + +/* ----------------------- Callback functions for Modbus stack ---------------------------------*/ +// These are executed by modbus stack to read appropriate type of registers. + +// This is required to suppress warning when register start address is zero +#pragma GCC diagnostic ignored "-Wtype-limits" + +// Callback function for reading of MB Input Registers +eMBErrorCode eMBRegInputCBTcpSlave(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_ASSERT(pucRegBuffer != NULL); + USHORT usRegInputNregs = (USHORT)(mbs_opts->mbs_area_descriptors[MB_PARAM_INPUT].size >> 1); // Number of input registers + USHORT usInputRegStart = (USHORT)mbs_opts->mbs_area_descriptors[MB_PARAM_INPUT].start_offset; // Get Modbus start address + UCHAR* pucInputBuffer = (UCHAR*)mbs_opts->mbs_area_descriptors[MB_PARAM_INPUT].address; // Get instance address + USHORT usRegs = usNRegs; + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + // If input or configuration parameters are incorrect then return an error to stack layer + if ((usAddress >= usInputRegStart) + && (pucInputBuffer != NULL) + && (usNRegs >= 1) + && ((usAddress + usRegs) <= (usInputRegStart + usRegInputNregs + 1)) + && (usRegInputNregs >= 1)) { + iRegIndex = (USHORT)(usAddress - usInputRegStart - 1); + iRegIndex <<= 1; // register Address to byte address + pucInputBuffer += iRegIndex; + UCHAR* pucBufferStart = pucInputBuffer; + while (usRegs > 0) { + _XFER_2_RD(pucRegBuffer, pucInputBuffer); + iRegIndex += 2; + usRegs -= 1; + } + // Send access notification + (void)send_param_access_notification(MB_EVENT_INPUT_REG_RD); + // Send parameter info to application task + (void)send_param_info(MB_EVENT_INPUT_REG_RD, (uint16_t)usAddress, + (uint8_t*)pucBufferStart, (uint16_t)usNRegs); + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} + +// Callback function for reading of MB Holding Registers +// Executed by stack when request to read/write holding registers is received +eMBErrorCode eMBRegHoldingCBTcpSlave(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_ASSERT(pucRegBuffer != NULL); + USHORT usRegHoldingNregs = (USHORT)(mbs_opts->mbs_area_descriptors[MB_PARAM_HOLDING].size >> 1); + USHORT usRegHoldingStart = (USHORT)mbs_opts->mbs_area_descriptors[MB_PARAM_HOLDING].start_offset; + UCHAR* pucHoldingBuffer = (UCHAR*)mbs_opts->mbs_area_descriptors[MB_PARAM_HOLDING].address; + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT usRegs = usNRegs; + // Check input and configuration parameters for correctness + if ((usAddress >= usRegHoldingStart) + && (pucHoldingBuffer != NULL) + && ((usAddress + usRegs) <= (usRegHoldingStart + usRegHoldingNregs + 1)) + && (usRegHoldingNregs >= 1) + && (usNRegs >= 1)) { + iRegIndex = (USHORT) (usAddress - usRegHoldingStart - 1); + iRegIndex <<= 1; // register Address to byte address + pucHoldingBuffer += iRegIndex; + UCHAR* pucBufferStart = pucHoldingBuffer; + switch (eMode) { + case MB_REG_READ: + while (usRegs > 0) { + _XFER_2_RD(pucRegBuffer, pucHoldingBuffer); + iRegIndex += 2; + usRegs -= 1; + }; + // Send access notification + (void)send_param_access_notification(MB_EVENT_HOLDING_REG_RD); + // Send parameter info + (void)send_param_info(MB_EVENT_HOLDING_REG_RD, (uint16_t)usAddress, + (uint8_t*)pucBufferStart, (uint16_t)usNRegs); + break; + case MB_REG_WRITE: + while (usRegs > 0) { + _XFER_2_WR(pucHoldingBuffer, pucRegBuffer); + pucHoldingBuffer += 2; + iRegIndex += 2; + usRegs -= 1; + }; + // Send access notification + (void)send_param_access_notification(MB_EVENT_HOLDING_REG_WR); + // Send parameter info + (void)send_param_info(MB_EVENT_HOLDING_REG_WR, (uint16_t)usAddress, + (uint8_t*)pucBufferStart, (uint16_t)usNRegs); + break; + } + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} + +// Callback function for reading of MB Coils Registers +eMBErrorCode eMBRegCoilsCBTcpSlave(UCHAR* pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_ASSERT(NULL != pucRegBuffer); + USHORT usRegCoilNregs = (USHORT)(mbs_opts->mbs_area_descriptors[MB_PARAM_COIL].size >> 1); // number of registers in storage area + USHORT usRegCoilsStart = (USHORT)mbs_opts->mbs_area_descriptors[MB_PARAM_COIL].start_offset; // MB offset of coils registers + UCHAR* pucRegCoilsBuf = (UCHAR*)mbs_opts->mbs_area_descriptors[MB_PARAM_COIL].address; + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT usCoils = usNCoils; + usAddress--; // The address is already +1 + if ((usAddress >= usRegCoilsStart) + && (usRegCoilNregs >= 1) + && ((usAddress + usCoils) <= (usRegCoilsStart + (usRegCoilNregs << 4) + 1)) + && (pucRegCoilsBuf != NULL) + && (usNCoils >= 1)) { + iRegIndex = (USHORT) (usAddress - usRegCoilsStart); + CHAR* pucCoilsDataBuf = (CHAR*)(pucRegCoilsBuf + (iRegIndex >> 3)); + switch (eMode) { + case MB_REG_READ: + while (usCoils > 0) { + UCHAR ucResult = xMBUtilGetBits((UCHAR*)pucRegCoilsBuf, iRegIndex, 1); + xMBUtilSetBits(pucRegBuffer, iRegIndex - (usAddress - usRegCoilsStart), 1, ucResult); + iRegIndex++; + usCoils--; + } + // Send an event to notify application task about event + (void)send_param_access_notification(MB_EVENT_COILS_RD); + (void)send_param_info(MB_EVENT_COILS_RD, (uint16_t)usAddress, + (uint8_t*)(pucCoilsDataBuf), (uint16_t)usNCoils); + break; + case MB_REG_WRITE: + while (usCoils > 0) { + UCHAR ucResult = xMBUtilGetBits(pucRegBuffer, + iRegIndex - (usAddress - usRegCoilsStart), 1); + xMBUtilSetBits((uint8_t*)pucRegCoilsBuf, iRegIndex, 1, ucResult); + iRegIndex++; + usCoils--; + } + // Send an event to notify application task about event + (void)send_param_access_notification(MB_EVENT_COILS_WR); + (void)send_param_info(MB_EVENT_COILS_WR, (uint16_t)usAddress, + (uint8_t*)pucCoilsDataBuf, (uint16_t)usNCoils); + break; + } // switch ( eMode ) + } else { + // If the configuration or input parameters are incorrect then return error to stack + eStatus = MB_ENOREG; + } + return eStatus; +} + +// Callback function for reading of MB Discrete Input Registers +eMBErrorCode eMBRegDiscreteCBTcpSlave(UCHAR* pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete) +{ + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + MB_SLAVE_ASSERT(pucRegBuffer != NULL); + USHORT usRegDiscreteNregs = (USHORT)(mbs_opts->mbs_area_descriptors[MB_PARAM_DISCRETE].size >> 1); // number of registers in storage area + USHORT usRegDiscreteStart = (USHORT)mbs_opts->mbs_area_descriptors[MB_PARAM_DISCRETE].start_offset; // MB offset of registers + UCHAR* pucRegDiscreteBuf = (UCHAR*)mbs_opts->mbs_area_descriptors[MB_PARAM_DISCRETE].address; // the storage address + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex, iRegBitIndex, iNReg; + UCHAR* pucDiscreteInputBuf; + iNReg = usNDiscrete / 8 + 1; + pucDiscreteInputBuf = (UCHAR*) pucRegDiscreteBuf; + // It already plus one in modbus function method. + usAddress--; + if ((usAddress >= usRegDiscreteStart) + && (usRegDiscreteNregs >= 1) + && (pucRegDiscreteBuf != NULL) + && ((usAddress + usNDiscrete) <= (usRegDiscreteStart + (usRegDiscreteNregs * 16))) + && (usNDiscrete >= 1)) { + iRegIndex = (USHORT) (usAddress - usRegDiscreteStart) / 8; // Get register index in the buffer for bit number + iRegBitIndex = (USHORT)(usAddress - usRegDiscreteStart) % 8; // Get bit index + UCHAR* pucTempBuf = &pucDiscreteInputBuf[iRegIndex]; + while (iNReg > 0) { + *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + // Last discrete + usNDiscrete = usNDiscrete % 8; + // Filling zero to high bit + *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete); + *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete); + // Send an event to notify application task about event + (void)send_param_access_notification(MB_EVENT_DISCRETE_RD); + (void)send_param_info(MB_EVENT_DISCRETE_RD, (uint16_t)usAddress, + (uint8_t*)pucTempBuf, (uint16_t)usNDiscrete); + } else { + eStatus = MB_ENOREG; + } + return eStatus; +} +#pragma GCC diagnostic pop // require GCC + +// Initialization of Modbus controller +esp_err_t mbc_tcp_slave_create(void** handler) +{ + // Allocate space for options + if (mbs_interface_ptr == NULL) { + mbs_interface_ptr = malloc(sizeof(mb_slave_interface_t)); + } + MB_SLAVE_ASSERT(mbs_interface_ptr != NULL); + mb_slave_options_t* mbs_opts = &mbs_interface_ptr->opts; + mbs_opts->port_type = MB_PORT_TCP_SLAVE; // set interface port type + + vMBPortSetMode((UCHAR)MB_PORT_TCP_SLAVE); + + // Set default values of communication options + mbs_opts->mbs_comm.ip_port = MB_TCP_DEFAULT_PORT; + + // Initialization of active context of the Modbus controller + BaseType_t status = 0; + + // Parameter change notification queue + mbs_opts->mbs_event_group = xEventGroupCreate(); + MB_SLAVE_CHECK((mbs_opts->mbs_event_group != NULL), + ESP_ERR_NO_MEM, "mb event group error."); + // Parameter change notification queue + mbs_opts->mbs_notification_queue_handle = xQueueCreate( + MB_CONTROLLER_NOTIFY_QUEUE_SIZE, + sizeof(mb_param_info_t)); + MB_SLAVE_CHECK((mbs_opts->mbs_notification_queue_handle != NULL), + ESP_ERR_NO_MEM, "mb notify queue creation error."); + // Create Modbus controller task + status = xTaskCreate((void*)&modbus_tcp_slave_task, + "modbus_tcp_slave_task", + MB_CONTROLLER_STACK_SIZE, + NULL, + MB_CONTROLLER_PRIORITY, + &mbs_opts->mbs_task_handle); + if (status != pdPASS) { + vTaskDelete(mbs_opts->mbs_task_handle); + MB_SLAVE_CHECK((status == pdPASS), ESP_ERR_NO_MEM, + "mb controller task creation error, xTaskCreate() returns (0x%x).", + (uint32_t)status); + } + + // The task is created but handle is incorrect + MB_SLAVE_ASSERT(mbs_opts->mbs_task_handle != NULL); + + // Initialization of interface pointers + mbs_interface_ptr->init = mbc_tcp_slave_create; + mbs_interface_ptr->destroy = mbc_tcp_slave_destroy; + mbs_interface_ptr->setup = mbc_tcp_slave_setup; + mbs_interface_ptr->start = mbc_tcp_slave_start; + mbs_interface_ptr->check_event = mbc_tcp_slave_check_event; + mbs_interface_ptr->get_param_info = mbc_tcp_slave_get_param_info; + mbs_interface_ptr->set_descriptor = mbc_tcp_slave_set_descriptor; + + // Initialize stack callback function pointers + mbs_interface_ptr->slave_reg_cb_discrete = eMBRegDiscreteCBTcpSlave; + mbs_interface_ptr->slave_reg_cb_input = eMBRegInputCBTcpSlave; + mbs_interface_ptr->slave_reg_cb_holding = eMBRegHoldingCBTcpSlave; + mbs_interface_ptr->slave_reg_cb_coils = eMBRegCoilsCBTcpSlave; + + *handler = (void*)mbs_interface_ptr; + + return ESP_OK; +} diff --git a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.h b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.h new file mode 100644 index 000000000..efa9194d7 --- /dev/null +++ b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.h @@ -0,0 +1,41 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// mbc_tcp_slave.h Modbus controller TCP slave implementation header file + +#ifndef _MODBUS_TCP_CONTROLLER_SLAVE +#define _MODBUS_TCP_CONTROLLER_SLAVE + +#include // for standard int types definition +#include // for NULL and std defines +#include "esp_modbus_common.h" // for common defines + +/* ----------------------- Defines ------------------------------------------*/ + +#define MB_CONTROLLER_NOTIFY_QUEUE_SIZE (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue +#define MB_CONTROLLER_NOTIFY_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout + +/** + * @brief Initialize Modbus controller and stack for TCP slave + * + * @param[out] handler handler(pointer) to slave data structure + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM Parameter error + */ +esp_err_t mbc_tcp_slave_create(void** handler); + +#endif // _MODBUS_TCP_CONTROLLER_SLAVE + diff --git a/components/freemodbus/tcp_slave/port/port_tcp_slave.c b/components/freemodbus/tcp_slave/port/port_tcp_slave.c new file mode 100644 index 000000000..0dc9fb5d2 --- /dev/null +++ b/components/freemodbus/tcp_slave/port/port_tcp_slave.c @@ -0,0 +1,719 @@ +/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* + * FreeModbus Libary: ESP32 TCP Port + * Copyright (C) 2006 Christian Walter + * Parts of crt0.S Copyright (c) 1995, 1996, 1998 Cygnus Support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.h,v 1.2 2006/09/04 14:39:20 wolti Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include +#include +#include "esp_err.h" +#include "sys/time.h" +#include "esp_netif.h" +#include "esp_timer.h" +/* ----------------------- lwIP includes ------------------------------------*/ +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" +#include "port.h" +#include "mbframe.h" +#include "port_tcp_slave.h" +#include "esp_modbus_common.h" // for common types for network options + +/* ----------------------- Defines -----------------------------------------*/ +#define MB_TCP_DISCONNECT_TIMEOUT ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS +#define MB_TCP_RESP_TIMEOUT_MS ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit +#define MB_TCP_SLAVE_PORT_TAG "MB_TCP_SLAVE_PORT" +#ifndef SOMAXCONN +#define SOMAXCONN 128 +#endif +#define MB_TCP_NET_LISTEN_BACKLOG ( SOMAXCONN ) + +/* ----------------------- Prototypes ---------------------------------------*/ +void vMBPortEventClose( void ); + +/* ----------------------- Static variables ---------------------------------*/ +static int xListenSock = -1; +static MbSlavePortConfig_t xConfig = { 0 }; + +/* ----------------------- Static functions ---------------------------------*/ +// The helper function to get time stamp in microseconds +static int64_t xMBTCPGetTimeStamp(void) +{ + int64_t xTimeStamp = esp_timer_get_time(); + return xTimeStamp; +} + +static void vxMBTCPPortMStoTimeVal(USHORT usTimeoutMs, struct timeval *pxTimeout) +{ + pxTimeout->tv_sec = usTimeoutMs / 1000; + pxTimeout->tv_usec = (usTimeoutMs - (pxTimeout->tv_sec * 1000)) * 1000; +} + +static xQueueHandle xMBTCPPortRespQueueCreate(void) +{ + xQueueHandle xRespQueueHandle = xQueueCreate(2, sizeof(void*)); + MB_PORT_CHECK((xRespQueueHandle != NULL), NULL, "TCP respond queue creation failure."); + return xRespQueueHandle; +} + +static void vMBTCPPortRespQueueDelete(xQueueHandle xRespQueueHandle) +{ + vQueueDelete(xRespQueueHandle); +} + +static void* vxMBTCPPortRespQueueRecv(xQueueHandle xRespQueueHandle) +{ + void* pvResp = NULL; + MB_PORT_CHECK(xRespQueueHandle != NULL, NULL, "Response queue is not initialized."); + BaseType_t xStatus = xQueueReceive(xRespQueueHandle, + (void*)&pvResp, + pdMS_TO_TICKS(MB_TCP_RESP_TIMEOUT_MS)); + MB_PORT_CHECK((xStatus == pdTRUE), NULL, "Could not get respond confirmation."); + MB_PORT_CHECK((pvResp), NULL, "Incorrect response processing."); + return pvResp; +} + +static BOOL vxMBTCPPortRespQueueSend(xQueueHandle xRespQueueHandle, void* pvResp) +{ + MB_PORT_CHECK(xRespQueueHandle != NULL, FALSE, "Response queue is not initialized."); + BaseType_t xStatus = xQueueSend(xConfig.xRespQueueHandle, + (const void*)&pvResp, + pdMS_TO_TICKS(MB_TCP_RESP_TIMEOUT_MS)); + MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to send to response queue."); + return TRUE; +} + +static void vMBTCPPortServerTask(void *pvParameters); + +/* ----------------------- Begin implementation -----------------------------*/ +BOOL +xMBTCPPortInit( USHORT usTCPPort ) +{ + BOOL bOkay = FALSE; + + xConfig.pxMbClientInfo = calloc(MB_TCP_PORT_MAX_CONN + 1, sizeof(MbClientInfo_t*)); + if (!xConfig.pxMbClientInfo) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "TCP client info allocation failure."); + return FALSE; + } + for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xConfig.pxMbClientInfo[idx] = NULL, idx++); + + xConfig.xRespQueueHandle = xMBTCPPortRespQueueCreate(); + if (!xConfig.xRespQueueHandle) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response queue allocation failure."); + return FALSE; + } + + xConfig.usPort = usTCPPort; + xConfig.eMbProto = MB_PROTO_TCP; + xConfig.usClientCount = 0; + xConfig.pvNetIface = NULL; + xConfig.xIpVer = MB_PORT_IPV4; + xConfig.pcBindAddr = NULL; + + // Create task for packet processing + BaseType_t xErr = xTaskCreate(vMBTCPPortServerTask, + "tcp_server_task", + MB_TCP_STACK_SIZE, + NULL, + MB_TCP_TASK_PRIO, + &xConfig.xMbTcpTaskHandle); + vTaskSuspend(xConfig.xMbTcpTaskHandle); + if (xErr != pdTRUE) + { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Server task creation failure."); + vTaskDelete(xConfig.xMbTcpTaskHandle); + } else { + ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Protocol stack initialized."); + bOkay = TRUE; + } + return bOkay; +} + +void vMBTCPPortSlaveSetNetOpt(void* pvNetIf, eMBPortIpVer xIpVersion, eMBPortProto xProto, CHAR* pcBindAddrStr) +{ + // Set network options + xConfig.pvNetIface = pvNetIf; + xConfig.eMbProto = xProto; + xConfig.xIpVer = xIpVersion; + xConfig.pcBindAddr = pcBindAddrStr; +} + +void vMBTCPPortSlaveStartServerTask(void) +{ + vTaskResume(xConfig.xMbTcpTaskHandle); +} + +static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr) +{ + MB_PORT_CHECK(pcIPAddr, -1, "Wrong IP address pointer."); + MB_PORT_CHECK((xListenSockId > 0), -1, "Incorrect listen socket ID."); + + // Address structure large enough for both IPv4 or IPv6 address +#if LWIP_IPV6 + struct sockaddr_in6 xSrcAddr; + socklen_t xSize = sizeof(struct sockaddr_in6); +#else + struct sockaddr_in xSrcAddr; + socklen_t xSize = sizeof(struct sockaddr_in); +#endif + CHAR cAddrStr[128]; + int xSockId = -1; + CHAR* pcStr = NULL; + + // Accept new socket connection if not active + xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize); + if (xSockId < 0) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Unable to accept connection: errno=%d", errno); + close(xSockId); + } else { + // Get the sender's ip address as string +#if LWIP_IPV6 + if (xSrcAddr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&xSrcAddr)->sin_addr.s_addr, cAddrStr, sizeof(cAddrStr) - 1); + } else if (xSrcAddr.sin6_family == PF_INET6) { + inet6_ntoa_r(xSrcAddr.sin6_addr, cAddrStr, sizeof(cAddrStr) - 1); + } +#else + inet_ntoa_r(((struct sockaddr_in *)&xSrcAddr)->sin_addr.s_addr, cAddrStr, sizeof(cAddrStr) - 1); +#endif + ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr); + pcStr = calloc(1, strlen(cAddrStr) + 1); + if (pcStr && pcIPAddr) { + memcpy(pcStr, cAddrStr, strlen(cAddrStr)); + pcStr[strlen(cAddrStr)] = '\0'; + *pcIPAddr = pcStr; // Set IP address of connected client + } + } + return xSockId; +} + +static BOOL xMBTCPPortCloseConnection(MbClientInfo_t* pxInfo) +{ + MB_PORT_CHECK(pxInfo, FALSE, "Client info is NULL."); + + if (pxInfo->xSockId == -1) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId); + return FALSE; + } + if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno); + } + close(pxInfo->xSockId); + pxInfo->xSockId = -1; + if (xConfig.usClientCount) { + xConfig.usClientCount--; // decrement counter of client connections + } else { + xConfig.pxCurClientInfo = NULL; + } + return TRUE; +} + +static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) +{ + int xRet = ERR_CLSD; + struct timeval xTimeVal; + fd_set xReadSet; + int64_t xStartTimeStamp = 0; + + // Receive data from connected client + if (pxClientInfo && pxClientInfo->xSockId > -1) { + // Set receive timeout + vxMBTCPPortMStoTimeVal(xTimeoutMs, &xTimeVal); + xStartTimeStamp = xMBTCPGetTimeStamp(); + while (1) + { + FD_ZERO(&xReadSet); + FD_SET(pxClientInfo->xSockId, &xReadSet); + xRet = select(pxClientInfo->xSockId + 1, &xReadSet, NULL, NULL, &xTimeVal); + if (xRet == -1) + { + // If select an error occurred + xRet = ERR_CLSD; + break; + } else if (xRet == 0) { + // timeout occurred + if ((xStartTimeStamp + xTimeoutMs * 1000) > xMBTCPGetTimeStamp()) { + ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId); + xRet = ERR_TIMEOUT; + break; + } + } + if (FD_ISSET(pxClientInfo->xSockId, &xReadSet)) { + // If new buffer received then read Modbus packet into buffer + MB_PORT_CHECK((pxClientInfo->usTCPBufPos + pxClientInfo->usTCPFrameBytesLeft < MB_TCP_BUF_SIZE), + ERR_BUF, "Socket (#%d), incorrect request buffer size = %d, ignore.", + pxClientInfo->xSockId, + (pxClientInfo->usTCPBufPos + pxClientInfo->usTCPFrameBytesLeft)); + int xLength = recv(pxClientInfo->xSockId, &pxClientInfo->pucTCPBuf[pxClientInfo->usTCPBufPos], + pxClientInfo->usTCPFrameBytesLeft, MSG_DONTWAIT); + if (xLength < 0) { + // If an error occurred during receiving + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Receive failed: length=%d, errno=%d", xLength, errno); + xRet = (err_t)xLength; + break; + } else if (xLength == 0) { + // Socket connection closed + ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed.", + pxClientInfo->xSockId, pxClientInfo->pcIpAddr); + xRet = ERR_CLSD; + break; + } else { + // New data received + pxClientInfo->usTCPBufPos += xLength; + pxClientInfo->usTCPFrameBytesLeft -= xLength; + if (pxClientInfo->usTCPBufPos >= MB_TCP_FUNC) { + // Length is a byte count of Modbus PDU (function code + data) and the + // unit identifier. + xLength = (int)MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_LEN); + // Is the frame already complete. + if (pxClientInfo->usTCPBufPos < (MB_TCP_UID + xLength)) { + // The incomplete frame is received + pxClientInfo->usTCPFrameBytesLeft = xLength + MB_TCP_UID - pxClientInfo->usTCPBufPos; + } else if (pxClientInfo->usTCPBufPos == (MB_TCP_UID + xLength)) { +#if MB_TCP_DEBUG + prvvMBTCPLogFrame(MB_TCP_SLAVE_PORT_TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos); +#endif + // Copy TID field from incoming packet + pxClientInfo->usTidCnt = MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_TID); + xRet = pxClientInfo->usTCPBufPos; + break; + } else if ((pxClientInfo->usTCPBufPos + xLength) >= MB_TCP_BUF_SIZE) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Incorrect buffer received (%u) bytes.", xLength); + // This should not happen. We can't deal with such a client and + // drop the connection for security reasons. + xRet = ERR_BUF; + break; + } + } // if ( pxClientInfo->usTCPBufPos >= MB_TCP_FUNC ) + } // if data received + } // if (FD_ISSET(pxClientInfo->xSockId, &xReadSet)) + } // while (1) + } + return (xRet); +} + +// Create a listening socket on pcBindIp: Port +static int +vMBTCPPortBindAddr(const CHAR* pcBindIp) +{ + int xPar, xRet; + int xListenSockFd = -1; + struct addrinfo xHint; + struct addrinfo* pxAddrList; + struct addrinfo* pxCurAddr; + CHAR* pcStr = NULL; + + memset( &xHint, 0, sizeof( xHint ) ); + + // Bind to IPv6 and/or IPv4, but only in the desired protocol + // Todo: Find a reason why AF_UNSPEC does not work for IPv6 + xHint.ai_family = (xConfig.xIpVer == MB_PORT_IPV4) ? AF_INET : AF_INET6; + xHint.ai_socktype = (xConfig.eMbProto == MB_PROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; + // The LWIP has an issue when connection to IPv6 socket + xHint.ai_protocol = (xConfig.eMbProto == MB_PROTO_UDP) ? IPPROTO_UDP : IPPROTO_TCP; + xHint.ai_flags = AI_NUMERICSERV; + + if (pcBindIp == NULL) { + xHint.ai_flags |= AI_PASSIVE; + } else { + xHint.ai_flags |= AI_CANONNAME; + } + + if (asprintf(&pcStr, "%u", xConfig.usPort) == -1) { + abort(); + } + + xRet = getaddrinfo(pcBindIp, pcStr, &xHint, &pxAddrList); + free(pcStr); + + if (xRet != 0) { + return -1; + } + + // Try the sockaddr until a binding succeeds + for (pxCurAddr = pxAddrList; pxCurAddr != NULL; pxCurAddr = pxCurAddr->ai_next) + { + xListenSockFd = (int)socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, + pxCurAddr->ai_protocol); + if (xListenSockFd < 0) + { + continue; + } + + xPar = 1; + // Allow multi client connections + if (setsockopt(xListenSockFd, SOL_SOCKET, SO_REUSEADDR, + (const char*)&xPar, sizeof(xPar)) != 0) + { + close(xListenSockFd); + xListenSockFd = -1; + continue; + } + + if (bind(xListenSockFd, (struct sockaddr *)pxCurAddr->ai_addr, + (socklen_t)pxCurAddr->ai_addrlen) != 0 ) + { + close(xListenSockFd); + xListenSockFd = -1; + continue; + } + + // Listen only makes sense for TCP + if (xConfig.eMbProto == MB_PROTO_TCP) + { + if (listen(xListenSockFd, MB_TCP_NET_LISTEN_BACKLOG) != 0) + { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Error occurred during listen: errno=%d", errno); + close(xListenSockFd); + xListenSockFd = -1; + continue; + } + } + // Bind was successful + pcStr = (pxCurAddr->ai_canonname == NULL) ? (CHAR*)"\0" : pxCurAddr->ai_canonname; + ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), listener %s on port: %d, errno=%d", + xListenSockFd, pcStr, xConfig.usPort, errno); + break; + } + + freeaddrinfo(pxAddrList); + return(xListenSockFd); +} + +static void +vMBTCPPortFreeClientInfo(MbClientInfo_t* pxClientInfo) +{ + if (pxClientInfo) { + if (pxClientInfo->pucTCPBuf) { + free((void*)pxClientInfo->pucTCPBuf); + } + if (pxClientInfo->pcIpAddr) { + free((void*)pxClientInfo->pcIpAddr); + } + free((void*)pxClientInfo); + } +} + + +static void vMBTCPPortServerTask(void *pvParameters) +{ + int xErr = 0; + fd_set xReadSet; + int i; + CHAR* pcClientIp = NULL; + struct timeval xTimeVal; + + // Main connection cycle + while (1) { + // Create listen socket + xListenSock = vMBTCPPortBindAddr(xConfig.pcBindAddr); + if (xListenSock < 0) { + continue; + } + + // Connections handling cycle + while (1) { + //clear the socket set + FD_ZERO(&xReadSet); + //add master socket to set + FD_SET(xListenSock, &xReadSet); + int xMaxSd = xListenSock; + xConfig.usClientCount = 0; + + vxMBTCPPortMStoTimeVal(1, &xTimeVal); + // Initialize read set and file descriptor according to + // all registered connected clients + for (i = 0; i < MB_TCP_PORT_MAX_CONN; i++) { + if ((xConfig.pxMbClientInfo[i] != NULL) && (xConfig.pxMbClientInfo[i]->xSockId > 0)) { + // calculate max file descriptor for select + xMaxSd = (xConfig.pxMbClientInfo[i]->xSockId > xMaxSd) ? + xConfig.pxMbClientInfo[i]->xSockId : xMaxSd; + FD_SET(xConfig.pxMbClientInfo[i]->xSockId, &xReadSet); + xConfig.usClientCount++; + } + } + + // Wait for an activity on one of the sockets, timeout is NULL, so wait indefinitely + xErr = select(xMaxSd + 1 , &xReadSet , NULL , NULL , NULL); + if ((xErr < 0) && (errno != EINTR)) { + // error occurred during wait for read + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() errno = %d.", errno); + continue; + } else if (xErr == 0) { + // If timeout happened, something is wrong + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() timeout, errno = %d.", errno); + } + + // If something happened on the master socket, then its an incoming connection. + if (FD_ISSET(xListenSock, &xReadSet) && xConfig.usClientCount < MB_TCP_PORT_MAX_CONN) { + MbClientInfo_t* pxClientInfo = NULL; + // find first empty place to insert connection info + for (i = 0; i < MB_TCP_PORT_MAX_CONN; i++) { + pxClientInfo = xConfig.pxMbClientInfo[i]; + if (pxClientInfo == NULL) { + break; + } + } + // if request for new connection but no space left + if (pxClientInfo != NULL) { + if (xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] == NULL) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN); + } + xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = pxClientInfo; // set last connection info + } else { + // allocate memory for new client info + pxClientInfo = calloc(1, sizeof(MbClientInfo_t)); + if (!pxClientInfo) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client info allocation fail."); + vMBTCPPortFreeClientInfo(pxClientInfo); + pxClientInfo = NULL; + } else { + // Accept new client connection + pxClientInfo->xSockId = xMBTCPPortAcceptConnection(xListenSock, &pcClientIp); + if (pxClientInfo->xSockId < 0) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1)); + // Accept connection fail, then free client info and continue polling. + vMBTCPPortFreeClientInfo(pxClientInfo); + pxClientInfo = NULL; + continue; + } + pxClientInfo->pucTCPBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); + if (!pxClientInfo->pucTCPBuf) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1)); + vMBTCPPortFreeClientInfo(pxClientInfo); + pxClientInfo = NULL; + continue; + } + // Fill the connection info structure + xConfig.pxMbClientInfo[i] = pxClientInfo; + pxClientInfo->xIndex = i; + xConfig.usClientCount++; + pxClientInfo->pcIpAddr = pcClientIp; + pxClientInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); + xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = NULL; + pxClientInfo->usTCPFrameBytesLeft = MB_TCP_FUNC; + pxClientInfo->usTCPBufPos = 0; + } + } + } + // Handle data request from client + if (xErr > 0) { + // Handling client connection requests + for (i = 0; i < MB_TCP_PORT_MAX_CONN; i++) { + MbClientInfo_t* pxClientInfo = xConfig.pxMbClientInfo[i]; + if ((pxClientInfo != NULL) && (pxClientInfo->xSockId > 0)) { + if (FD_ISSET(pxClientInfo->xSockId, &xReadSet)) { + // Other sockets are ready to be read + xErr = xMBTCPPortRxPoll(pxClientInfo, MB_TCP_READ_TIMEOUT_MS); + // If an invalid data received from socket or connection fail + // or if timeout then drop connection and restart + if (xErr < 0) { + uint64_t xTimeStamp = xMBTCPGetTimeStamp(); + // If data update is timed out + switch(xErr) + { + case ERR_TIMEOUT: + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.", + pxClientInfo->xSockId, pxClientInfo->pcIpAddr, + (int)(xTimeStamp - pxClientInfo->xRecvTimeStamp)); + break; + case ERR_CLSD: + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed by peer.", + pxClientInfo->xSockId, pxClientInfo->pcIpAddr); + break; + case ERR_BUF: + default: + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), read data error: %d", + pxClientInfo->xSockId, pxClientInfo->pcIpAddr, xErr); + break; + } + // Close client connection + xMBTCPPortCloseConnection(pxClientInfo); + + // This client does not respond, then unregister it + vMBTCPPortFreeClientInfo(pxClientInfo); + xConfig.pxMbClientInfo[i] = NULL; + xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = NULL; + // If no any active connections, break + if (!xConfig.usClientCount) { + xConfig.pxCurClientInfo = NULL; + break; + } + } else { + pxClientInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); + + // set current client info to active client from which we received request + xConfig.pxCurClientInfo = pxClientInfo; + + // Complete frame received, inform state machine to process frame + xMBPortEventPost(EV_FRAME_RECEIVED); + + ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.", + pxClientInfo->xSockId, pxClientInfo->pcIpAddr, + pxClientInfo->usTidCnt, xErr); + + // Wait while response is not processed by stack by timeout + UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle); + if (pucSentBuffer == NULL) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response time exceeds configured %d [ms], ignore packet.", + MB_TCP_RESP_TIMEOUT_MS); + } else { + USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID); + if (usSentTid != pxClientInfo->usTidCnt) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.", + usSentTid, pxClientInfo->usTidCnt); + } + } + + // Get time stamp of last data update + pxClientInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); + ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d), processing time = %d (us).", + pxClientInfo->xIndex, pxClientInfo->xSockId, + (int)(pxClientInfo->xSendTimeStamp - pxClientInfo->xRecvTimeStamp)); + } + } else { + if (pxClientInfo) { + // client is not ready to be read + int64_t xTime = xMBTCPGetTimeStamp() - pxClientInfo->xRecvTimeStamp; + if (xTime > MB_TCP_DISCONNECT_TIMEOUT) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...", + pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(xTime)); + xMBTCPPortCloseConnection(pxClientInfo); + + // This client does not respond, then delete registered data + vMBTCPPortFreeClientInfo(pxClientInfo); + xConfig.pxMbClientInfo[i] = NULL; + } + } else { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d is disconnected.", i); + } + } + } // if ((pxClientInfo != NULL) + } // Handling client connection requests + } + } // while(1) // Handle connection cycle + } // Main connection cycle + vTaskDelete(NULL); +} + +void +vMBTCPPortClose( ) +{ + // Release resources for the event queue. + vMBPortEventClose( ); + vTaskDelete(xConfig.xMbTcpTaskHandle); +} + +void +vMBTCPPortDisable( void ) +{ + vTaskSuspend(xConfig.xMbTcpTaskHandle); + for (int i = 0; i < MB_TCP_PORT_MAX_CONN; i++) { + MbClientInfo_t* pxClientInfo = xConfig.pxMbClientInfo[i]; + if ((pxClientInfo != NULL) && (pxClientInfo->xSockId > 0)) { + xMBTCPPortCloseConnection(pxClientInfo); + vMBTCPPortFreeClientInfo(pxClientInfo); + xConfig.pxMbClientInfo[i] = NULL; + } + } + close(xListenSock); + xListenSock = -1; + vMBTCPPortRespQueueDelete(xConfig.xRespQueueHandle); +} + +BOOL +xMBTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength ) +{ + BOOL xRet = FALSE; + if (xConfig.pxCurClientInfo) { + *ppucMBTCPFrame = &xConfig.pxCurClientInfo->pucTCPBuf[0]; + *usTCPLength = xConfig.pxCurClientInfo->usTCPBufPos; + + // Reset the buffer. + xConfig.pxCurClientInfo->usTCPBufPos = 0; + xConfig.pxCurClientInfo->usTCPFrameBytesLeft = MB_TCP_FUNC; + xRet = TRUE; + } + return xRet; +} + +BOOL +xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) +{ + BOOL bFrameSent = FALSE; + fd_set xWriteSet; + fd_set xErrorSet; + int xErr = -1; + struct timeval xTimeVal; + + if (xConfig.pxCurClientInfo) { + FD_ZERO(&xWriteSet); + FD_ZERO(&xErrorSet); + FD_SET(xConfig.pxCurClientInfo->xSockId, &xWriteSet); + FD_SET(xConfig.pxCurClientInfo->xSockId, &xErrorSet); + vxMBTCPPortMStoTimeVal(MB_TCP_SEND_TIMEOUT_MS, &xTimeVal); + // Check if socket writable + xErr = select(xConfig.pxCurClientInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal); + if ((xErr == -1) || FD_ISSET(xConfig.pxCurClientInfo->xSockId, &xErrorSet)) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d) , send select() error = %d.", + xConfig.pxCurClientInfo->xSockId, errno); + return FALSE; + } + + // Apply TID field from request to the frame before send response + pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(xConfig.pxCurClientInfo->usTidCnt >> 8U); + pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(xConfig.pxCurClientInfo->usTidCnt & 0xFF); + + // Write message into socket and disable Nagle's algorithm + xErr = send(xConfig.pxCurClientInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); + if (xErr < 0) { + ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d), fail to send data, errno = %d", + xConfig.pxCurClientInfo->xSockId, errno); + xConfig.pxCurClientInfo->xError = xErr; + } else { + bFrameSent = TRUE; + vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); + } + } else { + ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Port is not active. Release lock."); + vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); + } + return bFrameSent; +} + diff --git a/components/freemodbus/tcp_slave/port/port_tcp_slave.h b/components/freemodbus/tcp_slave/port/port_tcp_slave.h new file mode 100644 index 000000000..ffed7959b --- /dev/null +++ b/components/freemodbus/tcp_slave/port/port_tcp_slave.h @@ -0,0 +1,113 @@ + /* Copyright 2018 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + /* + * FreeModbus Libary: ESP32 TCP Port + * Copyright (C) 2006 Christian Walter + * Parts of crt0.S Copyright (c) 1995, 1996, 1998 Cygnus Support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.h,v 1.2 2006/09/04 14:39:20 wolti Exp $ + */ + +#ifndef _PORT_TCP_SLAVE_H +#define _PORT_TCP_SLAVE_H + +/* ----------------------- Platform includes --------------------------------*/ +#include "esp_log.h" + +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "port.h" +#include "esp_modbus_common.h" // for common types for network options + +/* ----------------------- Defines ------------------------------------------*/ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/* ----------------------- Type definitions ---------------------------------*/ +typedef struct { + int xIndex; /*!< Modbus info index */ + int xSockId; /*!< Socket id */ + int xError; /*!< TCP/UDP sock error */ + const char* pcIpAddr; /*!< TCP/UDP IP address (string) */ + UCHAR* pucTCPBuf; /*!< buffer pointer */ + USHORT usTCPBufPos; /*!< buffer active position */ + USHORT usTCPFrameBytesLeft; /*!< buffer left bytes to receive transaction */ + int64_t xSendTimeStamp; /*!< send request timestamp */ + int64_t xRecvTimeStamp; /*!< receive response timestamp */ + USHORT usTidCnt; /*!< last TID counter from packet */ +} MbClientInfo_t; + +typedef struct { + TaskHandle_t xMbTcpTaskHandle; /*!< Server task handle */ + xQueueHandle xRespQueueHandle; /*!< Response queue handle */ + MbClientInfo_t* pxCurClientInfo; /*!< Current client info */ + MbClientInfo_t** pxMbClientInfo; /*!< Pointers to information about connected clients */ + USHORT usPort; /*!< TCP/UDP port number */ + CHAR* pcBindAddr; /*!< IP address to bind */ + eMBPortProto eMbProto; /*!< Protocol type used by port */ + USHORT usClientCount; /*!< Client connection count */ + void* pvNetIface; /*!< Network netif interface pointer for port */ + eMBPortIpVer xIpVer; /*!< IP protocol version */ +} MbSlavePortConfig_t; + +/* ----------------------- Function prototypes ------------------------------*/ + +/** + * Function to setup communication options for TCP/UDP Modbus port + * + * @param pvNetIf netif interface pointer + * @param xIpVersion IP version + * @param xProto protocol type option + * @param pcBindAddr IP bind address + * + * @return error code + */ +void vMBTCPPortSlaveSetNetOpt(void* pvNetIf, eMBPortIpVer xIpVersion, eMBPortProto xProto, CHAR* pcBindAddr); + +/** + * Resume TCP Slave processing task + * + * @return None + */ +void vMBTCPPortSlaveStartServerTask(void); + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index d6a700686..05047cb38 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -1,9 +1,17 @@ -set(COMPONENT_ADD_INCLUDEDIRS include - include/freertos - include/freertos/private - port/esp8266/include - port/esp8266/include/freertos) -set(COMPONENT_SRCDIRS freertos port/esp8266) -set(COMPONENT_REQUIRES esp8266) +set(COMPONENT_ADD_INCLUDEDIRS include include/freertos include/freertos/private port/esp8266/include port/esp8266/include/freertos) +set(COMPONENT_SRCDIRS "freertos" "port/esp8266") +set(COMPONENT_ADD_LDFRAGMENTS "linker.lf") register_component() + +target_link_libraries(${COMPONENT_LIB} "-Wl,--undefined=uxTopUsedPriority") + +set_source_files_properties( + tasks.c + event_groups.c + timers.c + queue.c + ringbuf.c + PROPERTIES COMPILE_DEFINITIONS + _ESP_FREERTOS_INTERNAL + ) diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 114b9bcc6..1982c3c3a 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -1,5 +1,18 @@ menu "FreeRTOS" +config DISABLE_FREERTOS + bool "Disable FreeRTOS" + default n + help + Enable this option, FreeRTOS will not be compiled and linked, and the user + can user other OS platform. + +config FREERTOS_UNICORE + bool + default y + help + Only for code compatible. + config FREERTOS_ENABLE_REENT bool "Enable \"reent\" function" default n @@ -9,6 +22,10 @@ config FREERTOS_ENABLE_REENT The configuration will enable newlib. +config FREERTOS_NO_AFFINITY + hex + default 0x7FFFFFFF + config FREERTOS_HZ int "Tick rate (Hz)" range 1 1000 @@ -25,6 +42,18 @@ config FREERTOS_MAX_HOOK help configurate the max number of FreeRTOS hook function. +config FREERTOS_IDLE_TASK_STACKSIZE + int "Idle Task stack size" + range 1024 32768 + default 1024 + help + The idle task has its own stack, sized in bytes. The default size is enough for most uses. Size can be reduced + to 1024 bytes if no (or simple) FreeRTOS idle hooks are used and pthread local storage or FreeRTOS local storage + cleanup callbacks are not used. + + The stack size may need to be increased above the default if the app installs idle or thread local storage + cleanup hooks that use a lot of stack memory. + config FREERTOS_ISR_STACKSIZE int "ISR stack size" range 512 8192 @@ -32,6 +61,17 @@ config FREERTOS_ISR_STACKSIZE help The interrupt handlers have their own stack. The size of the stack can be defined here. +config FREERTOS_EXTENED_HOOKS + bool "Use FreeRTOS extened hooks" + default n + help + By using the "esp_register_freertos_xxx_hook system", extened hook function offers a number + of registerable hooks/callback functions that are called when a timer tick happens, + the idle thread runs etc. + + Otherwise User can also use FreeRTOS raw hook functions "vApplicationIdleHook" and + "vApplicationTickHook". + config FREERTOS_GLOBAL_DATA_LINK_IRAM bool "Link FreeRTOS global data to IRAM" default y @@ -40,10 +80,122 @@ config FREERTOS_GLOBAL_DATA_LINK_IRAM help Link FreeRTOS global data(.bss .data COMMON) from DRAM to IRAM. +config FREERTOS_CODE_LINK_TO_IRAM + bool "Link FreeRTOS code to IRAM" + default n + help + Link FreeRTOS code from Flash to IRAM. + config FREERTOS_TIMER_STACKSIZE int "Timer stack size" default 2048 help The size of the stack used by the timer in FreeRTOS. + +config TASK_SWITCH_FASTER + bool "Task switch faster" + default y + help + Enable this option, linking task switch function and its father functions to IRAM + to speed up task switch. It is specific for faster I/O application and so on. + + But it may cost more 1KB IRAM, so user global heap may decrease 1KB. + +config USE_QUEUE_SETS + bool "Using Queue Sets" + default n + help + Enable this option, the FreeRTOS macro "configUSE_QUEUE_SETS" in file "FreeRTOSConfig.h" will be set to be 1. + +config ENABLE_FREERTOS_SLEEP + bool "Enable FreeRTOS SLEEP" + default n + help + Enable this option, FreeRTOS sleep module at idle task will be enable. + The module is not working now, so if users want to make it work, they should do this themselves. + +config FREERTOS_USE_TRACE_FACILITY + bool "Enable FreeRTOS trace facility" + default n + help + If enabled, configUSE_TRACE_FACILITY will be defined as 1 in FreeRTOS. + This will allow the usage of trace facility functions such as + uxTaskGetSystemState(). + +config FREERTOS_USE_STATS_FORMATTING_FUNCTIONS + bool "Enable FreeRTOS stats formatting functions" + depends on FREERTOS_USE_TRACE_FACILITY + default n + help + If enabled, configUSE_STATS_FORMATTING_FUNCTIONS will be defined as 1 in + FreeRTOS. This will allow the usage of stats formatting functions such + as vTaskList(). + +config FREERTOS_GENERATE_RUN_TIME_STATS + bool "Enable FreeRTOS to collect run time stats" + default n + select FREERTOS_USE_TRACE_FACILITY + select FREERTOS_USE_STATS_FORMATTING_FUNCTIONS + help + If enabled, configGENERATE_RUN_TIME_STATS will be defined as 1 in + FreeRTOS. This will allow FreeRTOS to collect information regarding the + usage of processor time amongst FreeRTOS tasks. Run time stats are + generated using either the ESP Timer or the CPU Clock as the clock + source (Note that run time stats are only valid until the clock source + overflows). The function vTaskGetRunTimeStats() will also be available + if FREERTOS_USE_STATS_FORMATTING_FUNCTIONS and + FREERTOS_USE_TRACE_FACILITY are enabled. vTaskGetRunTimeStats() will + display the run time of each task as a % of the total run time of all + CPUs (task run time / no of CPUs) / (total run time / 100 ) + +choice FREERTOS_RUN_TIME_STATS_CLK + prompt "Choose the clock source for run time stats" + depends on FREERTOS_GENERATE_RUN_TIME_STATS + default FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER + help + Choose the clock source for FreeRTOS run time stats. Options are CPU0's + CPU Clock or the ESP Timer. Both clock sources are 32 bits. The CPU + Clock can run at a higher frequency hence provide a finer resolution + but will overflow much quicker. Note that run time stats are only valid + until the clock source overflows. + +config FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER + bool "Use ESP TIMER for run time stats" + help + ESP Timer will be used as the clock source for FreeRTOS run time stats. + The ESP Timer runs at a frequency of 1MHz regardless of Dynamic + Frequency Scaling. Therefore the ESP Timer will overflow in + approximately 4290 seconds. + +config FREERTOS_RUN_TIME_STATS_USING_CPU_CLK + bool "Use CPU Clock for run time stats" + help + CPU Clock will be used as the clock source for the generation of run + time stats. The CPU Clock has a frequency dependent on + ESP32_DEFAULT_CPU_FREQ_MHZ and Dynamic Frequency Scaling (DFS). + Therefore the CPU Clock frequency can fluctuate between 80 to 240MHz. + Run time stats generated using the CPU Clock represents the number of + CPU cycles each task is allocated and DOES NOT reflect the amount of + time each task runs for (as CPU clock frequency can change). If the CPU + clock consistently runs at the maximum frequency of 240MHz, it will + overflow in approximately 17 seconds. + +endchoice + +config FREERTOS_WATCHPOINT_END_OF_STACK + bool "Set a debug watchpoint as a stack overflow check" + default y + help + FreeRTOS can check if a stack has overflown its bounds by checking either the value of + the stack pointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW + for more information.) These checks only happen on a context switch, and the situation that caused + the stack overflow may already be long gone by then. This option will use the debug memory + watchpoint 0 to allow breaking into the debugger (or panic'ing) as soon as any + of the last 16 bytes on the stack of a task are overwritten. + + This check only triggers if the stack overflow writes within 4 bytes of the end of the stack, rather than + overshooting further, so it is worth combining this approach with one of the other stack overflow check + methods. + endmenu diff --git a/components/freertos/component.mk b/components/freertos/component.mk index 03fb5ebf2..37bf38319 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -1,6 +1,16 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS += include include/freertos include/freertos/private port/esp8266/include port/esp8266/include/freertos -COMPONENT_SRCDIRS := freertos port/esp8266 +COMPONENT_ADD_INCLUDEDIRS += include \ + include/freertos \ + include/freertos/private \ + port/esp8266/include \ + port/esp8266/include/freertos + +COMPONENT_SRCDIRS := port/esp8266 +ifndef CONFIG_DISABLE_FREERTOS +COMPONENT_SRCDIRS += freertos +endif + +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/freertos/freertos/list.c b/components/freertos/freertos/list.c index 758523a3d..223daea84 100644 --- a/components/freertos/freertos/list.c +++ b/components/freertos/freertos/list.c @@ -71,7 +71,7 @@ void vListInitialiseItem( ListItem_t * const pxItem ) } /*-----------------------------------------------------------*/ -void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +void TASK_SW_ATTR vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) { ListItem_t * const pxIndex = pxList->pxIndex; @@ -167,7 +167,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; } /*-----------------------------------------------------------*/ -UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) +UBaseType_t TASK_SW_ATTR uxListRemove( ListItem_t * const pxItemToRemove ) { /* The list item knows which list it is in. Obtain the list from the list item. */ diff --git a/components/freertos/freertos/queue.c b/components/freertos/freertos/queue.c index c37d285f3..a87d6d62e 100644 --- a/components/freertos/freertos/queue.c +++ b/components/freertos/freertos/queue.c @@ -360,6 +360,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; Queue_t *pxNewQueue; size_t xQueueSizeInBytes; uint8_t *pucQueueStorage; + BaseType_t overflow; configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); @@ -375,7 +376,29 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } - pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); + /* Check for multiplication overflow. */ + overflow = ( uxItemSize != 0 ) && ( uxQueueLength != ( xQueueSizeInBytes / uxItemSize ) ); + + /* Check for addition overflow. */ + overflow = overflow || ( ( sizeof( Queue_t ) + xQueueSizeInBytes ) < xQueueSizeInBytes ); + + if ( overflow == (BaseType_t) 0 ) + { + /* Allocate the queue and storage area. Justification for MISRA + deviation as follows: pvPortMalloc() always ensures returned memory + blocks are aligned per the requirements of the MCU stack. In this case + pvPortMalloc() must return a pointer that is guaranteed to meet the + alignment requirements of the Queue_t structure - which in this case + is an int8_t *. Therefore, whenever the stack alignment requirements + are greater than or equal to the pointer to char requirements the cast + is safe. In other cases alignment requirements are not strict (one or + two bytes). */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ + } + else + { + pxNewQueue = NULL; + } if( pxNewQueue != NULL ) { diff --git a/components/freertos/freertos/stream_buffer.c b/components/freertos/freertos/stream_buffer.c index c60045f69..317be2355 100644 --- a/components/freertos/freertos/stream_buffer.c +++ b/components/freertos/freertos/stream_buffer.c @@ -242,8 +242,15 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, this is a quirk of the implementation that means otherwise the free space would be reported as one byte smaller than would be logically expected. */ - xBufferSizeBytes++; - pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) + { + xBufferSizeBytes++; + pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + } + else + { + pucAllocatedMemory = NULL; + } if( pucAllocatedMemory != NULL ) { diff --git a/components/freertos/freertos/tasks.c b/components/freertos/freertos/tasks.c index 70e2eaa7c..61e10e501 100644 --- a/components/freertos/freertos/tasks.c +++ b/components/freertos/freertos/tasks.c @@ -1959,7 +1959,7 @@ BaseType_t xReturn; /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, configIDLE_TASK_NAME, - configMINIMAL_STACK_SIZE, + configIDLE_TASK_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ @@ -2522,7 +2522,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) - void vTaskStepTick( const TickType_t xTicksToJump ) + void IRAM_ATTR vTaskStepTick( const TickType_t xTicksToJump ) { /* Correct the tick count value after a period during which the tick was suppressed. Note this does *not* call the tick hook function for @@ -2611,7 +2611,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than #endif /* INCLUDE_xTaskAbortDelay */ /*----------------------------------------------------------*/ -BaseType_t xTaskIncrementTick( void ) +BaseType_t TASK_SW_ATTR xTaskIncrementTick( void ) { TCB_t * pxTCB; TickType_t xItemValue; @@ -2752,6 +2752,12 @@ BaseType_t xSwitchRequired = pdFALSE; } } #endif /* configUSE_TICK_HOOK */ + + #ifdef CONFIG_FREERTOS_EXTENED_HOOKS + { + esp_vApplicationTickHook(); + } + #endif /* CONFIG_FREERTOS_EXTENED_HOOKS */ } else { @@ -2764,6 +2770,12 @@ BaseType_t xSwitchRequired = pdFALSE; vApplicationTickHook(); } #endif + + #ifdef CONFIG_FREERTOS_EXTENED_HOOKS + { + esp_vApplicationTickHook(); + } + #endif /* CONFIG_FREERTOS_EXTENED_HOOKS */ } #if ( configUSE_PREEMPTION == 1 ) @@ -2873,7 +2885,7 @@ BaseType_t xSwitchRequired = pdFALSE; #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ -void vTaskSwitchContext( void ) +void TASK_SW_ATTR vTaskSwitchContext( void ) { if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) { @@ -3032,6 +3044,19 @@ BaseType_t xReturn; { ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif } else { @@ -3056,20 +3081,6 @@ BaseType_t xReturn; xReturn = pdFALSE; } - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - might be set to the blocked task's time out time. If the task is - unblocked for a reason other than a timeout xNextTaskUnblockTime is - normally left unchanged, because it is automatically reset to a new - value when the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter sleep mode - at the earliest possible time - so reset xNextTaskUnblockTime here to - ensure it is updated at the earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif - return xReturn; } /*-----------------------------------------------------------*/ @@ -3309,7 +3320,20 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) vApplicationIdleHook(); } #endif /* configUSE_IDLE_HOOK */ + #ifdef CONFIG_FREERTOS_EXTENED_HOOKS + { + /* Call the esp-idf hook system */ + esp_vApplicationIdleHook(); + } + #endif /* CONFIG_FREERTOS_EXTENED_HOOKS */ + + { + extern void esp_internal_idle_hook(void); + esp_internal_idle_hook(); + } + + #if CONFIG_ENABLE_FREERTOS_SLEEP /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when user defined low power mode implementations require @@ -3359,6 +3383,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } } #endif /* configUSE_TICKLESS_IDLE */ + #endif /* CONFIG_ENABLE_FREERTOS_SLEEP */ } } /*-----------------------------------------------------------*/ @@ -3464,6 +3489,24 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) return pvReturn; } + void **pvTaskGetThreadLocalStorageBufferPointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) + { + void **pvReturn = NULL; + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + pvReturn = &pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + } + else + { + pvReturn = NULL; + } + + return pvReturn; + } + #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ /*-----------------------------------------------------------*/ @@ -5072,6 +5115,89 @@ const TickType_t xConstTickCount = xTickCount; #endif /* INCLUDE_vTaskSuspend */ } +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB ) + { + if (pxTCB == NULL) { + return; + } + pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; + pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack; + #if( portSTACK_GROWTH < 0 ) + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack; + } + #else + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack; + } + #endif + (*uxTask)++; + } + + static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) + { + TCB_t *pxNextTCB, *pxFirstTCB; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + if( *uxTask >= uxArraySize ) + break; + + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) + { + UBaseType_t uxTask = 0, i = 0; + + + *pxTcbSz = sizeof(TCB_t); + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + i = configMAX_PRIORITIES; + do + { + i--; + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( pxReadyTasksLists[ i ] ) ); + } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList ); + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList ); + for (i = 0; i < portNUM_PROCESSORS; i++) { + if( uxTask >= uxArraySize ) + break; + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xPendingReadyList ); + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xTasksWaitingTermination ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xSuspendedTaskList ); + } + #endif + return uxTask; + } + +#endif + /* Code below here allows additional code to be inserted into this source file, especially where access to file scope functions and data is needed (for example when performing module tests). */ @@ -5094,4 +5220,114 @@ when performing module tests). */ #endif +#if( configENABLE_TASK_MODIFY_STACK_DEPTH == 1 ) + +#if( INCLUDE_xTimerPendFunctionCall != 1 || configUSE_TIMERS != 1) +#error "INCLUDE_xTimerPendFunctionCall and configUSE_TIMERS should be enable" +#endif + + #include "semphr.h" + + struct prvTaskModifyParam { + TCB_t *pxTCB; + uint32_t newStackDepth; + SemaphoreHandle_t sem; + BaseType_t uxResult; + }; + + static void prvTaskModifyStackDepth(void *param, uint32_t null_val) + { + struct prvTaskModifyParam *pTaskModifyParam = (struct prvTaskModifyParam *)param; + StackType_t *pxStack; + UBaseType_t oldStackBytes; + TCB_t *pxTCB = (TCB_t *)pTaskModifyParam->pxTCB; + UBaseType_t newStackBytes = (size_t)pTaskModifyParam->newStackDepth * sizeof(StackType_t); + const UBaseType_t unitSize = sizeof(void *); + + oldStackBytes = (size_t)pxTCB->pxEndOfStack - (size_t)pxTCB->pxTopOfStack + unitSize; + if (oldStackBytes >= newStackBytes) { + pTaskModifyParam->uxResult = pdFAIL; + goto exit; + } + + pxStack = pvPortMalloc(newStackBytes); + if (!pxStack) { + pTaskModifyParam->uxResult = pdFAIL; + goto exit; + } + memset(pxStack, tskSTACK_FILL_BYTE, newStackBytes - oldStackBytes); + vPortInitContextFromOldStack(&pxStack[newStackBytes - oldStackBytes], (StackType_t *)pxTCB->pxTopOfStack, oldStackBytes); + + vPortFree(pxTCB->pxStack); + + pxTCB->pxStack = pxStack; + pxTCB->pxTopOfStack = &pxStack[newStackBytes - oldStackBytes]; + pxTCB->pxEndOfStack = (StackType_t *)((size_t)pxStack + (size_t)pTaskModifyParam->newStackDepth - unitSize); + + pTaskModifyParam->uxResult = pdPASS; + + exit: + if (pTaskModifyParam->sem) + xSemaphoreGive(pTaskModifyParam->sem); + } + + BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth) + { + BaseType_t xReturn; + + if (newStackDepth & 0x3) { + return pdFAIL; + } + + if (prvGetTCBFromHandle(xTask) != pxCurrentTCB) { + struct prvTaskModifyParam taskModifyParam; + + taskModifyParam.pxTCB = prvGetTCBFromHandle(xTask); + taskModifyParam.newStackDepth = newStackDepth; + taskModifyParam.sem = NULL; + + vTaskSuspend(xTask); + prvTaskModifyStackDepth(&taskModifyParam, 0); + xReturn = taskModifyParam.uxResult; + vTaskResume(xTask); + } else { + SemaphoreHandle_t sem; + struct prvTaskModifyParam *taskModifyParam; + + if (xTimerGetTimerDaemonTaskHandle() == xTask) { + return pdFAIL; + } + + if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + return pdFAIL; + } + + sem = xSemaphoreCreateBinary(); + if (!sem) { + return pdFAIL; + } + + taskModifyParam = pvPortMalloc(sizeof(struct prvTaskModifyParam)); + if (!taskModifyParam) { + vSemaphoreDelete(sem); + return pdFAIL; + } + + taskModifyParam->pxTCB = prvGetTCBFromHandle(xTask); + taskModifyParam->newStackDepth = newStackDepth; + taskModifyParam->sem = sem; + + xReturn = xTimerPendFunctionCall(prvTaskModifyStackDepth, taskModifyParam, 0, portMAX_DELAY); + if (xReturn == pdPASS) { + xSemaphoreTake(sem, portMAX_DELAY); + xReturn = taskModifyParam->uxResult; + } + + vSemaphoreDelete(sem); + vPortFree(taskModifyParam); + } + + return xReturn; + } +#endif /* configENABLE_TASK_MODIFY_STACK_DEPTH == 1 */ diff --git a/components/freertos/include/freertos/private/portable.h b/components/freertos/include/freertos/private/portable.h index 55d7f04c7..6d2212c76 100644 --- a/components/freertos/include/freertos/private/portable.h +++ b/components/freertos/include/freertos/private/portable.h @@ -146,6 +146,16 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; */ int xPortInIsrContext(void); +/** + * @brief Copy thread context from old thread stack to new thread stack and + * then reset the SP. + * + * @param newStackTop new thread stack pointer + * @param oldStackTop old thread stack pointer + * @param stackSize stack size + */ +void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize); + #ifdef __cplusplus } #endif diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 60267ae8e..5f50397c5 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -1458,6 +1458,7 @@ constant. */ used to set and query a pointer respectively. */ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; + void **pvTaskGetThreadLocalStorageBufferPointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) /** @@ -2359,6 +2360,38 @@ void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; */ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; +/** + * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. + * We need this struct because TCB_t is defined (hidden) in tasks.c. + */ +typedef struct xTASK_SNAPSHOT +{ + void *pxTCB; /*!< Address of task control block. */ + StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ + StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo + pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ +} TaskSnapshot_t; + +/* + * This function fills array with TaskSnapshot_t structures for every task in the system. + * Used by core dump facility to get snapshots of all tasks in the system. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data. + * @param uxArraySize Size of tasks snapshots array. + * @param pxTcbSz Pointer to store size of TCB. + * @return Number of elements stored in array. + */ +UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ); + +/** + * @brief Modify task stack size dynamically. + * + * @param xTask task handle which created by xTaskCreate. + * @param newStackDepth task' new stack size. + * + * @return pdPASS if success or others if failed + */ +BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth); #ifdef __cplusplus } diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf new file mode 100644 index 000000000..3b688f2b3 --- /dev/null +++ b/components/freertos/linker.lf @@ -0,0 +1,15 @@ +[mapping:freertos] +archive: libfreertos.a +entries: + if FREERTOS_GLOBAL_DATA_LINK_IRAM = y: + event_groups (iram_bss) + list (iram_bss) + queue (iram_bss) + stream_buffer (iram_bss) + tasks (iram_bss) + timers (iram_bss) + freertos_hooks (iram_bss) + impure(iram_bss) + + if FREERTOS_CODE_LINK_TO_IRAM = y: + * (noflash_text) diff --git a/components/freertos/port/esp8266/freertos_hooks.c b/components/freertos/port/esp8266/freertos_hooks.c index 4f0b80c0d..74337cde5 100644 --- a/components/freertos/port/esp8266/freertos_hooks.c +++ b/components/freertos/port/esp8266/freertos_hooks.c @@ -22,6 +22,8 @@ #include "sdkconfig.h" +#ifdef CONFIG_FREERTOS_EXTENED_HOOKS + //We use just a static array here because it's not expected many components will need //an idle or tick hook. #define MAX_HOOKS CONFIG_FREERTOS_MAX_HOOK @@ -158,3 +160,4 @@ void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb) portEXIT_CRITICAL(&hooks_spinlock); } +#endif /* CONFIG_FREERTOS_EXTENED_HOOKS */ diff --git a/components/freertos/port/esp8266/impure.c b/components/freertos/port/esp8266/impure.c deleted file mode 100644 index ecea43f33..000000000 --- a/components/freertos/port/esp8266/impure.c +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -static struct _reent impure_data; -struct _reent *_global_impure_ptr = &impure_data; - -struct _reent *__getreent() -{ -#if configUSE_NEWLIB_REENTRANT == 1 - /* - * Locking mutex(only mutex, not ISR mutex) at the following three - * state may cause OS death. So we use a extra _reent data instead - * of task private reent data. - * - * But although at the state none of "taskSCHEDULER_RUNNING", exception - * can cause CPU swicth context, then Locking mutex may cause OS death. - * So we command that use ets_printf(ROM function) instead of "printf" - * at exception and system kernal critical state. - */ - if (xPortInIsrContext() - || !xTaskGetCurrentTaskHandle() - || xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) - return &impure_data; - - /* - * When scheduler starts, _global_impure_ptr = pxCurrentTCB->xNewLib_reent. - */ -#endif - return _global_impure_ptr; -} diff --git a/components/freertos/port/esp8266/include/freertos/FreeRTOSConfig.h b/components/freertos/port/esp8266/include/freertos/FreeRTOSConfig.h index 5fda0652c..44b2f72bc 100644 --- a/components/freertos/port/esp8266/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/port/esp8266/include/freertos/FreeRTOSConfig.h @@ -50,24 +50,32 @@ #define portNUM_PROCESSORS 1 #define configUSE_PREEMPTION 1 + #define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 0 +#define configUSE_TICK_HOOK 1 + #define configUSE_TICKLESS_IDLE 1 #define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) #define configTICK_RATE_HZ ( ( portTickType ) CONFIG_FREERTOS_HZ ) #define configMAX_PRIORITIES 15 +#if CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2048 ) +#else #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 768 ) +#endif //#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) -#define configUSE_TRACE_FACILITY 0 -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define INCLUDE_xTaskGetIdleTaskHandle 1 #define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#ifndef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK #define configCHECK_FOR_STACK_OVERFLOW 2 +#endif + #define configUSE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 @@ -77,6 +85,7 @@ #define configTIMER_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define configTIMER_QUEUE_LENGTH (10) #define configTIMER_TASK_STACK_DEPTH ( ( unsigned short ) CONFIG_FREERTOS_TIMER_STACKSIZE ) +#define INCLUDE_xTimerPendFunctionCall 1 #endif /* Co-routine definitions. */ @@ -98,6 +107,8 @@ to exclude the API function. */ #define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + /* This is the raw value as per the Cortex-M3 NVIC. Values can be 255 (lowest) to 0 (1?) (highest). */ #define configKERNEL_INTERRUPT_PRIORITY 255 @@ -117,15 +128,71 @@ NVIC value of 255. */ #define configUSE_NEWLIB_REENTRANT 1 #endif -#ifdef CONFIG_ENABLE_PTHREAD -#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 2 -#else -#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 -#endif +/** + * 0: LwIP + * 1: pthread (optional) + * 2: errno + */ +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 3 #define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1 /* add this to dump task stack information */ #define configRECORD_STACK_HIGH_ADDRESS 1 +#ifdef CONFIG_TASK_SWITCH_FASTER +#define TASK_SW_ATTR IRAM_ATTR +#else +#define TASK_SW_ATTR +#endif + +#if CONFIG_USE_QUEUE_SETS +#define configUSE_QUEUE_SETS 1 +#endif + +#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY +#define configUSE_TRACE_FACILITY 1 /* Used by uxTaskGetSystemState(), and other trace facility functions */ +#endif + +#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /* Used by vTaskList() */ +#endif + +#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS +#define configGENERATE_RUN_TIME_STATS 1 /* Used by vTaskGetRunTimeStats() */ +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +//ccount or esp_timer are initialized elsewhere +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() + +#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_CPU_CLK +#ifndef __ASSEMBLER__ +extern uint64_t g_esp_os_cpu_clk; +#define portGET_RUN_TIME_COUNTER_VALUE() g_esp_os_cpu_clk +#endif +/* Fine resolution time */ +#elif defined(CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER) +/* Coarse resolution time (us) */ +#ifndef __ASSEMBLER__ +uint32_t esp_get_time(void); +#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) x = (uint32_t)esp_get_time() +#endif /* __ASSEMBLER__ */ +#endif /* CONFIG_FREERTOS_RUN_TIME_STATS_USING_CPU_CLK */ + +#endif /* CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS */ + +#define traceINCREASE_TICK_COUNT(_ticks) esp_increase_tick_cnt(_ticks) + +#ifndef configIDLE_TASK_STACK_SIZE +#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE +#endif /* configIDLE_TASK_STACK_SIZE */ + +#ifndef configENABLE_TASK_SNAPSHOT +#define configENABLE_TASK_SNAPSHOT 1 +#endif + +#ifndef configENABLE_TASK_MODIFY_STACK_DEPTH +#define configENABLE_TASK_MODIFY_STACK_DEPTH 1 +#endif + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/port/esp8266/include/freertos/esp_freertos_hooks.h b/components/freertos/port/esp8266/include/freertos/esp_freertos_hooks.h index 5f24bc35a..1dbc27fd3 100644 --- a/components/freertos/port/esp8266/include/freertos/esp_freertos_hooks.h +++ b/components/freertos/port/esp8266/include/freertos/esp_freertos_hooks.h @@ -15,6 +15,10 @@ #ifndef __ESP_FREERTOS_HOOKS_H__ #define __ESP_FREERTOS_HOOKS_H__ +#include "sdkconfig.h" + +#ifdef CONFIG_FREERTOS_EXTENED_HOOKS + #include #include "esp_err.h" @@ -127,5 +131,6 @@ void esp_deregister_freertos_tick_hook(esp_freertos_tick_cb_t old_tick_cb); } #endif +#endif /* CONFIG_FREERTOS_EXTENED_HOOKS */ #endif diff --git a/components/freertos/port/esp8266/include/freertos/portmacro.h b/components/freertos/port/esp8266/include/freertos/portmacro.h index 709c7771d..b546cd7bd 100644 --- a/components/freertos/port/esp8266/include/freertos/portmacro.h +++ b/components/freertos/port/esp8266/include/freertos/portmacro.h @@ -42,15 +42,11 @@ extern "C" { #include "xtensa_rtos.h" #if defined(configUSE_NEWLIB_REENTRANT) && configUSE_NEWLIB_REENTRANT == 1 -#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) #include "esp_newlib.h" -#define _impure_ptr _global_impure_ptr - #undef _REENT_INIT_PTR #define _REENT_INIT_PTR(p) esp_reent_init(p) #endif -#endif /*----------------------------------------------------------- * Port specific definitions. @@ -63,22 +59,25 @@ extern "C" { */ /* Type definitions. */ -#define portCHAR char +#define portCHAR int8_t #define portFLOAT float #define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE unsigned char -#define portBASE_TYPE long - -#define BaseType_t portBASE_TYPE -#define TickType_t unsigned portLONG -#define UBaseType_t unsigned portBASE_TYPE -#define StackType_t portSTACK_TYPE - -typedef unsigned portLONG portTickType; -typedef unsigned int INT32U; -#define portMAX_DELAY ( portTickType ) 0xffffffff +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif /*-----------------------------------------------------------*/ /* Architecture specifics. */ @@ -88,7 +87,7 @@ typedef unsigned int INT32U; /*-----------------------------------------------------------*/ /* Scheduler utilities. */ -extern void PendSV(char req); +extern void PendSV(int req); //#define portYIELD() vPortYield() #define portYIELD() PendSV(1) @@ -108,6 +107,7 @@ extern void vTaskSwitchContext( void ); \ } \ } +void portYIELD_FROM_ISR(void); /*-----------------------------------------------------------*/ extern unsigned cpu_sr; @@ -131,6 +131,7 @@ void PortEnableInt_NoNest( void ); #define portEXIT_CRITICAL() vPortExitCritical() #define xPortGetCoreID() 0 +#define xTaskGetCurrentTaskHandleForCPU(_cpu) xTaskGetCurrentTaskHandle() // no need to disable/enable lvl1 isr again in ISR //#define portSET_INTERRUPT_MASK_FROM_ISR() PortDisableInt_NoNest() @@ -158,8 +159,6 @@ void _xt_user_exit (void); void _xt_tick_timer_init (void); void _xt_isr_unmask (uint32_t unmask); void _xt_isr_mask (uint32_t mask); -uint32_t _xt_read_ints (void); -void _xt_clear_ints(uint32_t mask); /* interrupt related */ typedef void (* _xt_isr)(void *arg); @@ -201,10 +200,24 @@ uint32_t xPortGetTickRateHz(void); void _xt_enter_first_task(void); +void esp_increase_tick_cnt(const TickType_t ticks); + /* API compatible with esp-idf */ #define xTaskCreatePinnedToCore(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask, tskNO_AFFINITY) \ xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask) +extern void esp_vApplicationIdleHook( void ); +extern void esp_vApplicationTickHook( void ); + +extern uint32_t g_esp_ticks_per_us; + +/* + * @brief Get FreeRTOS system idle ticks + * + * @return idle ticks + */ +TickType_t prvGetExpectedIdleTime(void); + #ifdef __cplusplus } #endif diff --git a/components/freertos/port/esp8266/include/freertos/xtensa_context.h b/components/freertos/port/esp8266/include/freertos/xtensa_context.h index 88458f76c..50fafeab4 100644 --- a/components/freertos/port/esp8266/include/freertos/xtensa_context.h +++ b/components/freertos/port/esp8266/include/freertos/xtensa_context.h @@ -30,6 +30,7 @@ NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes. #include #include #include +#include /* @@ -79,6 +80,52 @@ space to help manage the spilling of the register windows. #define XT_STK_SAR 0x4C #define XT_STK_EXCCAUSE 0x50 +#define XT_STK_EXCVADDR 0x54 + +STRUCT_BEGIN +STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */ +STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */ +STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */ +STRUCT_FIELD (long, 4, XT_STK_A0, a0) +STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */ +STRUCT_FIELD (long, 4, XT_STK_A2, a2) +STRUCT_FIELD (long, 4, XT_STK_A3, a3) +STRUCT_FIELD (long, 4, XT_STK_A4, a4) +STRUCT_FIELD (long, 4, XT_STK_A5, a5) +STRUCT_FIELD (long, 4, XT_STK_A6, a6) +STRUCT_FIELD (long, 4, XT_STK_A7, a7) +STRUCT_FIELD (long, 4, XT_STK_A8, a8) +STRUCT_FIELD (long, 4, XT_STK_A9, a9) +STRUCT_FIELD (long, 4, XT_STK_A10, a10) +STRUCT_FIELD (long, 4, XT_STK_A11, a11) +STRUCT_FIELD (long, 4, XT_STK_A12, a12) +STRUCT_FIELD (long, 4, XT_STK_A13, a13) +STRUCT_FIELD (long, 4, XT_STK_A14, a14) +STRUCT_FIELD (long, 4, XT_STK_A15, a15) +STRUCT_FIELD (long, 4, XT_STK_SAR, sar) +STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause) +STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr) +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg) +STRUCT_FIELD (long, 4, XT_STK_LEND, lend) +STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount) +#endif +#ifndef __XTENSA_CALL0_ABI__ +/* Temporary space for saving stuff during window spill */ +STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0) +STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1) +STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2) +#endif +#ifdef XT_USE_SWPRI +/* Storage for virtual priority mask */ +STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri) +#endif +#ifdef XT_USE_OVLY +/* Storage for overlay state */ +STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly) +#endif +STRUCT_END(XtExcFrame) + #if XCHAL_HAVE_LOOPS #define XT_STK_LBEG 0x50 #define XT_STK_LEND 0x54 @@ -115,6 +162,49 @@ Windowed - #endif +/* +------------------------------------------------------------------------------- + SOLICITED STACK FRAME FOR A THREAD + + A stack frame of this structure is allocated whenever a thread enters the + RTOS kernel intentionally (and synchronously) to submit to thread scheduling. + It goes on the current thread's stack. + + The solicited frame only includes registers that are required to be preserved + by the callee according to the compiler's ABI conventions, some space to save + the return address for returning to the caller, and the caller's PS register. + + For Windowed ABI, this stack frame includes the caller's base save area. + + Note on XT_SOL_EXIT field: + It is necessary to distinguish a solicited from an interrupt stack frame. + This field corresponds to XT_STK_EXIT in the interrupt stack frame and is + always at the same offset (0). It can be written with a code (usually 0) + to distinguish a solicted frame from an interrupt frame. An RTOS port may + opt to ignore this field if it has another way of distinguishing frames. +------------------------------------------------------------------------------- +*/ + +STRUCT_BEGIN +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, a0) +STRUCT_FIELD (long, 4, XT_SOL_A12, a1) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A13, a2) +#else +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) +STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A1, a1) +STRUCT_FIELD (long, 4, XT_SOL_A2, a2) +STRUCT_FIELD (long, 4, XT_SOL_A3, a3) +#endif +STRUCT_END(XtSolFrame) + /******************************************************************************* SOLICTED STACK FRAME FOR A THREAD diff --git a/components/freertos/port/esp8266/include/freertos/xtensa_timer.h b/components/freertos/port/esp8266/include/freertos/xtensa_timer.h index ff97830f7..49559b45d 100644 --- a/components/freertos/port/esp8266/include/freertos/xtensa_timer.h +++ b/components/freertos/port/esp8266/include/freertos/xtensa_timer.h @@ -140,7 +140,6 @@ Derviation of clock divisor for timer tick and interrupt (one per tick). #else #ifndef __ASSEMBLER__ extern unsigned _xt_tick_divisor; -extern void _xt_tick_divisor_init(void); #endif #define XT_TICK_DIVISOR _xt_tick_divisor #endif diff --git a/components/freertos/port/esp8266/os_cpu_a.S b/components/freertos/port/esp8266/os_cpu_a.S index a3e41eae9..b9c0dbcbb 100644 --- a/components/freertos/port/esp8266/os_cpu_a.S +++ b/components/freertos/port/esp8266/os_cpu_a.S @@ -19,7 +19,6 @@ .extern pxCurrentTCB .extern CCOMPARE_AddVal -// .section .iram.text .section .text .macro xtos_lock ax @@ -29,42 +28,6 @@ .macro xtos_unlock ax wsr \ax, PS .endm - -/* -********************************************************************************************************** -* vPortYield -* void vPortYield(void) -* maually switch the context. -* -********************************************************************************************************** -*/ - - .globl vPortYield - .type vPortYield,@function - .align 4 - .literal_position -vPortYield: - wsr a0, EXCSAVE_1 /* preserve a0 */ - addi sp, sp, -XT_STK_FRMSZ - s32i a0, sp, XT_STK_PC - - addi a0, sp, XT_STK_FRMSZ - s32i a0, sp, XT_STK_A1 - rsr a0, PS - s32i a0, sp, XT_STK_PS - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_user_exit - s32i a0, sp, XT_STK_EXIT - - call0 _xt_int_enter - call0 vPortEnterCritical - movi a0, vTaskSwitchContext - callx0 a0 - call0 vPortExitCritical - call0 _xt_int_exit - - ret /* ********************************************************************************************************** @@ -94,9 +57,9 @@ _xt_int_enter: /* Save the rest of the interrupted context (preserves A12-13). */ call0 _xt_context_save - movi a0, pxCurrentTCB - l32i a0, a0, 0 - s32i sp, a0, 0 + movi a0, pxCurrentTCB + l32i a0, a0, 0 + s32i sp, a0, 0 /* Retrieve the return address and return to interrupt handler. */ mov a0, a12 @@ -124,17 +87,27 @@ _xt_int_exit: However a12-13 were already saved by _xt_int_enter(). Save A14, A15 in sp to a14, a15 in cpu */ - #ifdef __XTENSA_CALL0_ABI__ - s32i a14, sp, XT_STK_A14 - s32i a15, sp, XT_STK_A15 - #endif + s32i a14, sp, XT_STK_A14 + s32i a15, sp, XT_STK_A15 /* Save A14, A15 in sp to a14, a15 in cpu */ - movi sp, pxCurrentTCB - l32i sp, sp, 0 - l32i sp, sp, 0 + movi sp, pxCurrentTCB + l32i sp, sp, 0 + l32i sp, sp, 0 + +#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + movi a2, pxCurrentTCB + l32i a2, a2, 0 + l32i a2, a2, 48 + movi a4, ~(0x7) + and a4, a4, a2 + wsr a4, dbreaka0 + + movi a3, 0x80000038 + wsr a3, dbreakc0 +#endif /* We come here only if there was no context switch, that is if this @@ -143,156 +116,19 @@ _xt_int_exit: */ movi a14, pxCurrentTCB l32i a14, a14, 0 - addi a15, sp, XT_STK_FRMSZ - s32i a15, a14 , 0 + addi a15, sp, XT_STK_FRMSZ + s32i a15, a14, 0 /* Restore full context from interrupt stack frame and return to exit dispatcher. */ call0 _xt_context_restore /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */ - #ifdef __XTENSA_CALL0_ABI__ - l32i a14, sp, XT_STK_A14 - l32i a15, sp, XT_STK_A15 - #endif - - #if XCHAL_CP_NUM > 0 - /* Ensure wsr.CPENABLE has completed. */ - rsync - #endif + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 - /* - Must return via the exit dispatcher corresponding to the entrypoint from which - this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt - stack frame is deallocated in the exit dispatcher. - */ - /*rsil a0, 0 */ /* reenable ints above level 1 */ - /*rsync*/ - - l32i a0, sp, XT_STK_EXIT + l32i a0, sp, XT_STK_EXIT ret -/* -********************************************************************************************************** -* _xt_timer_int -* void _xt_timer_int(void) -* -* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for uC/OS-II. -* Called every timer interrupt. -* Manages the tick timer and calls OSTimeTick() every tick, and calls OSTmrSignal() when required. -* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. -* -* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance. -* -********************************************************************************************************** -*/ - /* Define local variable offsets in stack frame for Call0 ABI. */ - #ifdef __XTENSA_CALL0_ABI__ - #define __xt_timer_int_a0 0 /* ENTRY()/RET() saves/restores */ - #define __xt_timer_int_a2 4 /* preserve a2 */ - #define __xt_timer_int_a3 8 /* preserve a3 */ - #endif - - .globl _xt_timer_int - .type _xt_timer_int,@function - .align 4 -_xt_timer_int: - - /* - Xtensa timers work by comparing a cycle counter with a preset value. Once the match occurs - an interrupt is generated, and the handler has to set a new cycle count into the comparator. - To avoid clock drift due to interrupt latency, the new cycle count is computed from the old, - not the time the interrupt was serviced. However if a timer interrupt is ever serviced more - than one tick late, it is necessary to process multiple ticks until the new cycle count is - in the future, otherwise the next timer interrupt would not occur until after the cycle - counter had wrapped (2^32 cycles later). - - do { - ticks++; - old_ccompare = read_ccompare_i(); - write_ccompare_i( old_ccompare + divisor ); - service one tick; - diff = read_ccount() - old_ccompare; - } while ( diff > divisor ); - */ - - ENTRY(16) - -.L_xt_timer_int_catchup: - - /* Update the timer comparator for the next tick. */ - #ifdef XT_CLOCK_FREQ - movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */ - #else - movi a3, _xt_tick_divisor - l32i a2, a3, 0 /* a2 = comparator increment */ - #endif - rsr a3, XT_CCOMPARE /* a3 = old comparator value */ - add a4, a3, a2 /* a4 = new comparator value */ - wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */ - esync - - #ifdef __XTENSA_CALL0_ABI__ - /* Preserve a2 and a3 across C calls. */ - s32i a2, sp, __xt_timer_int_a2 - s32i a3, sp, __xt_timer_int_a3 - #endif - - /* Call the uCOS-II tick handler. */ - #ifdef __XTENSA_CALL0_ABI__ /* OSTimeTick() */ - movi a0, xPortSysTickHandle - callx0 a0 - #else - call4 xTaskIncrementTick - #endif - - #ifdef __XTENSA_CALL0_ABI__ - /* Restore a2 and a3. */ - l32i a2, sp, __xt_timer_int_a2 - l32i a3, sp, __xt_timer_int_a3 - #endif - - /* Check if we need to process more ticks to catch up. */ - esync /* ensure comparator update complete */ - rsr a4, CCOUNT /* a4 = cycle count */ - sub a4, a4, a3 /* diff = ccount - old comparator */ - blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ - - RET(16) - - - - #ifdef __XTENSA_CALL0_ABI__ - #define __xt_timer_int1_a0 0 /* ENTRY()/RET() saves/restores */ - #define __xt_timer_int1_a2 4 /* preserve a2 */ - #define __xt_timer_int1_a3 8 /* preserve a3 */ - #endif - - .globl _xt_timer_int1 - .type _xt_timer_int1,@function - .align 4 -_xt_timer_int1: - - ENTRY(16) - - #ifdef __XTENSA_CALL0_ABI__ - /* Preserve a2 and a3 across C calls. */ - s32i a2, sp, __xt_timer_int1_a2 - s32i a3, sp, __xt_timer_int1_a3 - #endif - - /* Call the uCOS-II tick handler. */ - movi a0, vTaskSwitchContext - callx0 a0 - - #ifdef __XTENSA_CALL0_ABI__ - /* Restore a2 and a3. */ - l32i a2, sp, __xt_timer_int1_a2 - l32i a3, sp, __xt_timer_int1_a3 - #endif - - RET(16) - - /* ********************************************************************************************************** @@ -304,64 +140,55 @@ _xt_timer_int1: * ********************************************************************************************************** */ - .globl _xt_tick_timer_init - .type _xt_tick_timer_init,@function - .align 4 + .section .text._xt_tick_timer_init, "ax" + .globl _xt_tick_timer_init + .type _xt_tick_timer_init,@function + .align 4 _xt_tick_timer_init: ENTRY(16) /* Set up the periodic tick timer (assume enough time to complete init). */ #ifdef XT_CLOCK_FREQ - movi a3, XT_TICK_DIVISOR + movi a3, XT_TICK_DIVISOR #else - movi a2, _xt_tick_divisor - l32i a3, a2, 0 + movi a2, _xt_tick_divisor + l32i a3, a2, 0 #endif - rsr a2, CCOUNT /* current cycle count */ - add a2, a2, a3 /* time of first timer interrupt */ - wsr a2, XT_CCOMPARE /* set the comparator */ + rsr a2, CCOUNT /* current cycle count */ + add a2, a2, a3 /* time of first timer interrupt */ + wsr a2, XT_CCOMPARE /* set the comparator */ /* Enable the timer interrupt at the device level. */ - movi a2, 0 /* protect critical section */ - xsr a2, INTENABLE - movi a3, XT_TIMER_INTEN - or a2, a2, a3 - wsr a2, INTENABLE /* set new INTENABLE, no need to rsync */ + movi a2, 0 /* protect critical section */ + xsr a2, INTENABLE + movi a3, XT_TIMER_INTEN + or a2, a2, a3 + wsr a2, INTENABLE /* set new INTENABLE, no need to rsync */ RET(16) - - .globl _xt_update_xt_ccompare - .type _xt_update_xt_ccompare,@function - .align 4 -_xt_update_xt_ccompare: - + .section .text._xt_set_xt_ccompare_val, "ax" + .globl _xt_set_xt_ccompare_val + .type _xt_set_xt_ccompare_val,@function + .align 4 +_xt_set_xt_ccompare_val: ENTRY(16) /* Set up the periodic tick timer (assume enough time to complete init). */ - movi a3, XT_TICK_DIVISOR - rsr a2, XT_CCOMPARE /* current cycle count */ - add a2, a2, a3 /* time of first timer interrupt */ - wsr a2, XT_CCOMPARE /* set the comparator */ + movi a3, CCOMPARE_AddVal + l32i a2, a3, 0 + wsr a2, XT_CCOMPARE /* set the comparator */ esync - RET(16) - - .globl _xt_set_xt_ccompare_val - .type _xt_set_xt_ccompare_val,@function - .align 4 -_xt_set_xt_ccompare_val: - + .section .text.ResetCcountVal, "ax" + .globl ResetCcountVal + .type ResetCcountVal,@function + .align 4 +ResetCcountVal: ENTRY(16) - - /* Set up the periodic tick timer (assume enough time to complete init). */ - movi a3, CCOMPARE_AddVal - l32i a2, a3, 0 - wsr a2, XT_CCOMPARE /* set the comparator */ - esync - + wsr a2, ccount RET(16) /* @@ -370,78 +197,38 @@ _xt_set_xt_ccompare_val: ********************************************************************************************************** */ - - .globl _xt_isr_unmask - .type _xt_isr_unmask,@function - .align 4 + .section .text._xt_isr_unmask, "ax" + .globl _xt_isr_unmask + .type _xt_isr_unmask,@function + .align 4 _xt_isr_unmask: - ENTRY(16) /* Enable the timer interrupt at the device level. */ - xtos_lock a7 - rsr a3, INTENABLE - or a5, a3, a2 - wsr a5, INTENABLE - xtos_unlock a7 - mov a2, a3 - /*movi a3, 0 */ /* protect critical section */ - /*xsr a3, INTENABLE */ - /*or a3, a2, a3 */ - /*wsr a3, INTENABLE */ /* set new INTENABLE, no need to rsync */ - + xtos_lock a7 + rsr a3, INTENABLE + or a5, a3, a2 + wsr a5, INTENABLE + xtos_unlock a7 + mov a2, a3 RET(16) - .globl _xt_isr_mask - .type _xt_isr_mask,@function - .align 4 + .section .text._xt_isr_mask, "ax" + .globl _xt_isr_mask + .type _xt_isr_mask,@function + .align 4 _xt_isr_mask: - ENTRY(16) /* Enable the timer interrupt at the device level. */ - xtos_lock a7 - rsr a3, INTENABLE - or a5, a3, a2 - xor a5, a5, a2 - wsr a5, INTENABLE + xtos_lock a7 + rsr a3, INTENABLE + or a5, a3, a2 + xor a5, a5, a2 + wsr a5, INTENABLE xtos_unlock a7 - mov a2, a3 - /*movi a3, 0 */ /* protect critical section */ - /*xsr a3, INTENABLE*/ - /*and a3, a2, a3 */ - /*wsr a3, INTENABLE*/ /* set new INTENABLE, no need to rsync */ - - RET(16) - - - - - - - - - .global _xt_read_ints - .type _xt_read_ints,@function - .align 4 -_xt_read_ints: - - ENTRY(16) - - rsr a2, INTERRUPT - - RET(16) - - .global _xt_clear_ints - .type _xt_clear_ints,@function - .align 4 -_xt_clear_ints: - - ENTRY(16) - - wsr a2, INTCLEAR - + mov a2, a3 RET(16) @@ -450,20 +237,32 @@ _xt_clear_ints: .type _xt_enter_first_task, @function .align 4 _xt_enter_first_task: - movi sp, pxCurrentTCB - l32i sp, sp, 0 - l32i sp, sp, 0 + movi sp, pxCurrentTCB + l32i sp, sp, 0 + l32i sp, sp, 0 + +#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + movi a2, pxCurrentTCB + l32i a2, a2, 0 + l32i a2, a2, 48 + movi a4, ~(0x7) + and a4, a4, a2 + wsr a4, dbreaka0 + + movi a3, 0x80000038 + wsr a3, dbreakc0 +#endif movi a14, pxCurrentTCB l32i a14, a14, 0 - addi a15, sp, XT_STK_FRMSZ - s32i a15, a14 ,0 + addi a15, sp, XT_STK_FRMSZ + s32i a15, a14, 0 movi a0, _xt_context_restore callx0 a0 - l32i a14, sp, XT_STK_A14 - l32i a15, sp, XT_STK_A15 + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 - l32i a0, sp, XT_STK_EXIT + l32i a0, sp, XT_STK_EXIT ret diff --git a/components/freertos/port/esp8266/panic.c b/components/freertos/port/esp8266/panic.c index c136c9723..f3421fc6e 100644 --- a/components/freertos/port/esp8266/panic.c +++ b/components/freertos/port/esp8266/panic.c @@ -13,219 +13,196 @@ // limitations under the License. #include "stdlib.h" - +#include #include "esp_attr.h" #include "esp_libc.h" +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "esp_private/esp_system_internal.h" -#include "esp8266/eagle_soc.h" #include "esp8266/rom_functions.h" +#include "esp8266/backtrace.h" #include "rom/ets_sys.h" +#include "rom/uart.h" #include "esp_err.h" #include "FreeRTOS.h" #include "task.h" -#include "private/list.h" -#include "private/portable.h" - -#define STACK_VOL_NUM 16 +#include "freertos/xtensa_context.h" -/* - * @Note: If freeRTOS is updated, the structure must be checked. - */ -typedef struct task_info -{ - volatile StackType_t *pxTopOfStack; +#define PANIC(_fmt, ...) ets_printf(_fmt, ##__VA_ARGS__) -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; +#if defined(CONFIG_ESP_PANIC_SILENT_REBOOT) || defined(CONFIG_ESP_PANIC_PRINT_REBOOT) +#define ESP_PANIC_REBOOT +#else +#undef ESP_PANIC_REBOOT #endif - ListItem_t xStateListItem; - ListItem_t xEventListItem; - UBaseType_t uxPriority; - StackType_t *pxStack; - char pcTaskName[ configMAX_TASK_NAME_LEN ]; - -#if configRECORD_STACK_HIGH_ADDRESS != 1 -#error "configRECORD_STACK_HIGH_ADDRESS must enable" +#if defined(CONFIG_ESP_PANIC_SILENT_REBOOT) +#undef ESP_PANIC_PRINT +#else +#define ESP_PANIC_PRINT #endif -#if portSTACK_GROWTH >= 0 -#error "Task stack must decrease growing." +#if defined(CONFIG_ESP_PANIC_GDBSTUB) +#define ESP_PANIC_GDBSTUB +#else +#undef ESP_PANIC_GDBSTUB #endif - StackType_t *pxEndOfStack; -} task_info_t; - -static void panic_data32(uint32_t data, int hex) +#ifdef ESP_PANIC_PRINT +static inline void panic_frame(XtExcFrame *frame) { - char buf[12]; - size_t off = 0; + static const char *sdesc[] = { + "PC", "PS", "A0", "A1", + "A2", "A3", "A4", "A5", + "A6", "A7", "A8", "A9", + "A10", "A11", "A12", "A13", + "A14", "A15", "SAR", "EXCCAUSE" + }; + static const char *edesc[] = { + "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", + "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue", + "Privileged", "LoadStoreAlignment", "res", "res", + "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError", + "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res", + "InstrFetchProhibited", "res", "res", "res", + "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res", + "LoadProhibited", "StoreProhibited", + }; + + void *i_lr = (void *)frame->a0; + void *i_pc = (void *)frame->pc; + void *i_sp = (void *)frame->a1; - if (!data) - buf[off++] = '0'; - else { - while (data) { - char tmp = data % hex; + void *o_pc; + void *o_sp; - if (tmp >= 10) - tmp = tmp - 10 + 'a'; - else - tmp = tmp + '0'; +#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + if (frame->exccause == 1) { + uint32_t reason = soc_debug_reason(); - data = data / hex; + if (reason & XCHAL_DEBUGCAUSE_DBREAK_MASK) { + char name[configMAX_TASK_NAME_LEN]; - buf[off++] = tmp; + strncpy(name, pcTaskGetTaskName(NULL), configMAX_TASK_NAME_LEN); + ets_printf("Stack canary watchpoint triggered (%s)\n", name); } - } + } else +#endif + { + const char *reason = frame->exccause < 30 ? edesc[frame->exccause] : "unknown"; + const uint32_t *regs = (const uint32_t *)frame; + + PANIC("Guru Meditation Error: Core 0 panic'ed (%s). Exception was unhandled.\r\n", reason); + PANIC("Core 0 register dump:\n"); - if (hex == 16) { - while (off < 8) - buf[off++] = '0'; + for (int i = 0; i < 20; i += 4) { + for (int j = 0; j < 4; j++) { + PANIC("%-8s: 0x%08x ", sdesc[i + j], regs[i + j + 1]); + } + PANIC("\r\n"); + } } - while (off) - ets_putc(buf[--off]); + PANIC("\r\nBacktrace: %p:%p ", i_pc, i_sp); + while(xt_retaddr_callee(i_pc, i_sp, i_lr, &o_pc, &o_sp)) { + PANIC("%p:%p ", o_pc, o_sp); + i_pc = o_pc; + i_sp = o_sp; + } + PANIC("\r\n"); } +#endif /* ESP_PANIC_PRINT */ -static void panic_str(const char *s) +#ifdef ESP_PANIC_REBOOT +static void hardware_restart(void) { - while (*s) - ets_putc(*s++); + CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, BIT0); + WDT_REG_WRITE(WDT_OP_ADDRESS, 1); + WDT_REG_WRITE(WDT_OP_ND_ADDRESS, 1); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_RSTLEN_MASK, + 7 << WDT_CTL_RSTLEN_LSB, + 0); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_RSPMOD_MASK, + 0 << WDT_CTL_RSPMOD_LSB, + 0); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_EN_MASK, + 1 << WDT_CTL_EN_LSB, + 0); } -static void panic_stack(StackType_t *start_stk, StackType_t *end_stk) +static void esp_panic_reset(void) { - uint32_t *start = (uint32_t *)start_stk, *end = (uint32_t *)end_stk; - size_t i, j; - size_t size = end - start; - - panic_str(" "); - for (i = 0; i < STACK_VOL_NUM; i++) { - panic_data32(i * sizeof(void *), 16); - panic_str(" "); - } - panic_str("\r\n\r\n"); - - for (i = 0; i < size; i += STACK_VOL_NUM) { - size_t len = size > i ? size - i : STACK_VOL_NUM - (i - size); + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); - if (len > STACK_VOL_NUM) - len = STACK_VOL_NUM; + esp_reset_reason_set_hint(ESP_RST_PANIC); - panic_data32((uint32_t)&start[i], 16); - panic_str(" "); + hardware_restart(); - for (j = 0; j < len; j++) { - panic_data32((uint32_t)start[i + j], 16); - panic_str(" "); - } - panic_str("\r\n"); - } + while (1); } +#endif -/* - * @brief output xtensa register value map when crash - * - * @param frame xtensa register value map pointer - * - * @return none - */ -static __attribute__((noreturn)) void panic_info(void *frame, int wdt) +void panicHandler(void *frame, int wdt) { extern int _chip_nmi_cnt; - task_info_t *task; - int *regs = (int *)frame; - int x, y; - const char *sdesc[] = { - " PC", " PS", " A0", " A1", - " A2", " A3", " A4", " A5", - " A6", " A7", " A8", " A9", - " A10", " A11", " A12", " A13", - " A14", " A15", " SAR", "EXCCAUSE" - }; + _chip_nmi_cnt = 0; - panic_str("\r\n\r\n"); + /* NMI can interrupt exception. */ + vPortEnterCritical(); + do { + REG_WRITE(INT_ENA_WDEV, 0); + } while (REG_READ(INT_ENA_WDEV) != 0); +#ifdef ESP_PANIC_PRINT if (wdt) { - panic_str("Task watchdog got triggered.\r\n\r\n"); - } - - if (_chip_nmi_cnt) { - extern StackType_t _chip_nmi_stk, LoadStoreErrorHandlerStack; - - _chip_nmi_cnt = 0; - panic_str("Core 0 was running in NMI context:\r\n\r\n"); - - panic_stack(&_chip_nmi_stk, &LoadStoreErrorHandlerStack); - } else { - if (xPortInIsrContext() && !wdt) { - extern StackType_t _chip_interrupt_stk, _chip_interrupt_tmp; - - panic_str("Core 0 was running in ISR context:\r\n\r\n"); - - panic_stack(&_chip_interrupt_stk, &_chip_interrupt_tmp); - } else { - if ((task = (task_info_t *)xTaskGetCurrentTaskHandle())) { - StackType_t *pdata = task->pxStack; - StackType_t *end = task->pxEndOfStack + 4; - - // "Task stack [%s] stack from [%p] to [%p], total [%d] size\r\n\r\n" - panic_str("Task stack ["); - panic_str(task->pcTaskName); - panic_str("] stack from ["); - panic_data32((uint32_t)pdata, 16); - panic_str("] to ["); - panic_data32((uint32_t)end, 16); - panic_str("], total ["); - panic_data32((uint32_t)(end - pdata), 10); - panic_str("] size\r\n\r\n"); - - panic_stack(pdata, end); - - panic_str("\r\n\r\n"); - } else { - panic_str("No task\r\n\r\n"); - } - } + PANIC("Task watchdog got triggered.\r\n\r\n"); } - for (x = 0; x < 20; x += 4) { - for (y = 0; y < 4; y++) { - panic_str(sdesc[x + y]); - panic_str(": 0x"); - panic_data32((uint32_t)regs[x + y + 1], 16); - panic_str(" "); - } - panic_str("\r\n"); - } + panic_frame(frame); +#endif - /* - * Todo: add more option to select here to 'Kconfig': - * 1. blocking - * 2. restart - * 3. GBD break - */ - while (1); +#ifdef ESP_PANIC_REBOOT + esp_panic_reset(); +#elif defined(ESP_PANIC_GDBSTUB) + extern void esp_gdbstub_panic_handler(void *frame); + + PANIC("Entering gdb stub now.\r\n"); + esp_gdbstub_panic_handler(frame); +#else + while (1) { + esp_task_wdt_reset(); + } +#endif } -void __attribute__((noreturn)) panicHandler(void *frame, int wdt) +static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - int cnt = 10; - - /* NMI can interrupt exception. */ - vPortEnterCritical(); - while (cnt--) { - REG_WRITE(INT_ENA_WDEV, 0); - } + PANIC("%s failed: esp_err_t 0x%x", msg, rc); +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + PANIC(" (%s)", esp_err_to_name(rc)); +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + PANIC(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3); + + // ESP8266 put main FreeRTOS code at flash + //if (spi_flash_cache_enabled()) { // strings may be in flash cache + PANIC("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); + //} +} - panic_info(frame, wdt); +void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression) +{ + esp_error_check_failed_print("ESP_ERROR_CHECK_WITHOUT_ABORT", rc, file, line, function, expression); } -void __attribute__((noreturn)) _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) +void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0)); - printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); + esp_error_check_failed_print("ESP_ERROR_CHECK", rc, file, line, function, expression); abort(); -} \ No newline at end of file +} diff --git a/components/freertos/port/esp8266/port.c b/components/freertos/port/esp8266/port.c index 70e077c44..89c2da3f8 100644 --- a/components/freertos/port/esp8266/port.c +++ b/components/freertos/port/esp8266/port.c @@ -29,6 +29,7 @@ /* Scheduler includes. */ #include +#include #include #include @@ -41,39 +42,49 @@ #include "esp_attr.h" #include "esp_libc.h" +#include "esp_task_wdt.h" +#include "esp_sleep.h" #include "esp8266/eagle_soc.h" #include "rom/ets_sys.h" #include "esp8266/rom_functions.h" +#include "driver/soc.h" -#define PORT_ASSERT(x) do { if (!(x)) {ets_printf("%s %u\n", "rtos_port", __LINE__); while(1){}; }} while (0) +#define SET_STKREG(r,v) sp[(r) >> 2] = (uint32_t)(v) +#define PORT_ASSERT(x) do { if (!(x)) {ets_printf("%s %u\n", "rtos_port", __LINE__); while(1){}; }} while (0) -extern char NMIIrqIsOn; -static uint8_t HdlMacSig = 0; -static uint8_t SWReq = 0; +extern uint8_t NMIIrqIsOn; -unsigned cpu_sr; +uint32_t cpu_sr; + +uint32_t _xt_tick_divisor; /* Each task maintains its own interrupt status in the critical nesting variable. */ static uint32_t uxCriticalNesting = 0; +uint32_t g_esp_boot_ccount; +uint64_t g_esp_os_ticks; +uint64_t g_esp_os_us; +uint64_t g_esp_os_cpu_clk; + +static uint32_t s_switch_ctx_flag; + void vPortEnterCritical(void); void vPortExitCritical(void); -void _xt_timer_int1(void); - +void IRAM_ATTR portYIELD_FROM_ISR(void) +{ + s_switch_ctx_flag = 1; +} -/* - * See header file for description. - */ -StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters) +uint8_t *__cpu_init_stk(uint8_t *stack_top, void (*_entry)(void *), void *param, void (*_exit)(void)) { -#define SET_STKREG(r,v) sp[(r) >> 2] = (unsigned long)(v) - unsigned long *sp, *tp, *stk = (unsigned long *)pxTopOfStack; + + uint32_t *sp, *tp, *stk = (uint32_t *)stack_top; /* Create interrupt stack frame aligned to 16 byte boundary */ - sp = (unsigned long *)(((INT32U)(stk + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf); + sp = (uint32_t *)(((uint32_t)(stk + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf); /* Clear the entire frame (do not use memset() because we don't depend on C library) */ for (tp = sp; tp <= stk; ++tp) { @@ -81,69 +92,96 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, pdTASK_CODE pxCode } /* Explicitly initialize certain saved registers */ - SET_STKREG(XT_STK_PC, pxCode); /* task entrypoint */ - SET_STKREG(XT_STK_A0, 0); /* to terminate GDB backtrace */ - SET_STKREG(XT_STK_A1, (INT32U)sp + XT_STK_FRMSZ); /* physical top of stack frame */ - SET_STKREG(XT_STK_A2, pvParameters); /* parameters */ + SET_STKREG(XT_STK_PC, _entry); /* task entrypoint */ + SET_STKREG(XT_STK_A0, _exit); /* to terminate GDB backtrace */ + SET_STKREG(XT_STK_A1, (uint32_t)sp + XT_STK_FRMSZ); /* physical top of stack frame */ + SET_STKREG(XT_STK_A2, param); /* parameters */ SET_STKREG(XT_STK_EXIT, _xt_user_exit); /* user exception exit dispatcher */ /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ -#ifdef __XTENSA_CALL0_ABI__ SET_STKREG(XT_STK_PS, PS_UM | PS_EXCM); -#else - /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ - SET_STKREG(XT_STK_PS, PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1)); -#endif - return (StackType_t *)sp; + return (uint8_t *)sp; } -void IRAM_ATTR PendSV(char req) +#ifndef DISABLE_FREERTOS +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters) +{ + return (StackType_t *)__cpu_init_stk((uint8_t *)pxTopOfStack, pxCode, pvParameters, NULL); +} +#endif + +void IRAM_ATTR PendSV(int req) { if (req == 1) { vPortEnterCritical(); - SWReq = 1; + s_switch_ctx_flag = 1; xthal_set_intset(1 << ETS_SOFT_INUM); vPortExitCritical(); } else if (req == 2) { - HdlMacSig = 1; xthal_set_intset(1 << ETS_SOFT_INUM); } } -void IRAM_ATTR HDL_MAC_SIG_IN_LV1_ISR(void) +void IRAM_ATTR SoftIsrHdl(void* arg) { - PendSV(2); + extern int MacIsrSigPostDefHdl(void); + + if (MacIsrSigPostDefHdl()) { + portYIELD_FROM_ISR(); + } } -extern portBASE_TYPE MacIsrSigPostDefHdl(void); +void IRAM_ATTR esp_increase_tick_cnt(const TickType_t ticks) +{ + g_esp_os_ticks += ticks; +} -void SoftIsrHdl(void* arg) +void IRAM_ATTR xPortSysTickHandle(void *p) { - ETS_NMI_LOCK(); + uint32_t us; + uint32_t ticks; + uint32_t ccount; + + /** + * System or application may close interrupt too long, such as the operation of read/write/erase flash. + * And then the "ccount" value may be overflow. + * + * So add code here to calibrate system time. + */ + ccount = soc_get_ccount(); + us = ccount / g_esp_ticks_per_us; + + g_esp_os_us += us; + g_esp_os_cpu_clk += ccount; - portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + soc_set_ccount(0); + soc_set_ccompare(_xt_tick_divisor); - if (HdlMacSig == 1) { - HdlMacSig = 0; - xHigherPriorityTaskWoken = MacIsrSigPostDefHdl(); - } + ticks = us / 1000 / portTICK_PERIOD_MS; - if (xHigherPriorityTaskWoken || (SWReq == 1)) { - _xt_timer_int1(); - SWReq = 0; + if (ticks > 1) { + vTaskStepTick(ticks - 1); } - ETS_NMI_UNLOCK(); -} + g_esp_os_ticks++; -void xPortSysTickHandle(void) -{ if (xTaskIncrementTick() != pdFALSE) { - vTaskSwitchContext(); + portYIELD_FROM_ISR(); } } +/** + * @brief Return current CPU clock frequency + */ +int esp_clk_cpu_freq(void) +{ + return _xt_tick_divisor * XT_TICK_PER_SEC; +} + /* * See header file for description. */ @@ -163,8 +201,13 @@ portBASE_TYPE xPortStartScheduler(void) _xt_isr_attach(ETS_SOFT_INUM, SoftIsrHdl, NULL); _xt_isr_unmask(1 << ETS_SOFT_INUM); + _xt_isr_attach(ETS_MAX_INUM, xPortSysTickHandle, NULL); + /* Initialize system tick timer interrupt and schedule the first tick. */ - _xt_tick_divisor_init(); + _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; + + g_esp_boot_ccount = soc_get_ccount(); + soc_set_ccount(0); _xt_tick_timer_init(); vTaskSwitchContext(); @@ -176,6 +219,15 @@ portBASE_TYPE xPortStartScheduler(void) return pdTRUE; } +void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize) +{ + uintptr_t *sp; + + memcpy(newStackTop, oldStackTop, stackSize); + sp = (uintptr_t *)newStackTop; + sp[XT_STK_A1 / sizeof(uintptr_t)] = (uintptr_t)sp + XT_STK_FRMSZ; +} + void vPortEndScheduler(void) { /* It is unlikely that the CM3 port will require this function as there @@ -221,44 +273,61 @@ void IRAM_ATTR vPortExitCritical(void) void show_critical_info(void) { ets_printf("ShowCritical:%u\n", uxCriticalNesting); - ets_printf("HdlMacSig:%u\n", HdlMacSig); - ets_printf("SWReq:%u\n", SWReq); + ets_printf("s_switch_ctx_flag:%u\n", s_switch_ctx_flag); } -void IRAM_ATTR vPortETSIntrLock(void) -{ - ETS_INTR_LOCK(); -} +#ifdef ESP_DPORT_CLOSE_NMI +static int s_nmi_is_closed; -void IRAM_ATTR vPortETSIntrUnlock(void) +void esp_dport_close_nmi(void) { - ETS_INTR_UNLOCK(); + vPortEnterCritical(); + REG_WRITE(PERIPHS_DPORT_BASEADDR, REG_READ(PERIPHS_DPORT_BASEADDR) & ~0x1); + s_nmi_is_closed = 1; + vPortExitCritical(); } -void PortDisableInt_NoNest(void) +#define ESP_NMI_IS_CLOSED() s_nmi_is_closed +#else +#define ESP_NMI_IS_CLOSED() 0 +#endif + +void IRAM_ATTR vPortETSIntrLock(void) { if (NMIIrqIsOn == 0) { - if (ClosedLv1Isr != 1) { - portDISABLE_INTERRUPTS(); - ClosedLv1Isr = 1; + uint32_t regval = REG_READ(NMI_INT_ENABLE_REG); + + vPortEnterCritical(); + + REG_WRITE(NMI_INT_ENABLE_REG, 0); + + if (!ESP_NMI_IS_CLOSED()) { + do { + REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT); + } while(REG_READ(INT_ENA_WDEV) != WDEV_TSF0_REACH_INT); } + + REG_WRITE(NMI_INT_ENABLE_REG, regval); } } -void PortEnableInt_NoNest(void) +void IRAM_ATTR vPortETSIntrUnlock(void) { if (NMIIrqIsOn == 0) { - if (ClosedLv1Isr == 1) { - ClosedLv1Isr = 0; - portENABLE_INTERRUPTS(); + uint32_t regval = REG_READ(NMI_INT_ENABLE_REG); + + REG_WRITE(NMI_INT_ENABLE_REG, 0); + + if (!ESP_NMI_IS_CLOSED()) { + extern uint32_t WDEV_INTEREST_EVENT; + + REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT); } - } -} -/*-----------------------------------------------------------*/ -void ResetCcountVal(unsigned int cnt_val) -{ - asm volatile("wsr a2, ccount"); + REG_WRITE(NMI_INT_ENABLE_REG, regval); + + vPortExitCritical(); + } } /* @@ -275,50 +344,50 @@ bool interrupt_is_disable(void) return tmp & 0xFUL ? true : false; } -_xt_isr_entry isr[16]; -char _xt_isr_status = 0; +static _xt_isr_entry s_isr[16]; +static uint8_t s_xt_isr_status = 0; void _xt_isr_attach(uint8_t i, _xt_isr func, void* arg) { - isr[i].handler = func; - isr[i].arg = arg; + s_isr[i].handler = func; + s_isr[i].arg = arg; } -uint16_t _xt_isr_handler(uint16_t i) +void IRAM_ATTR _xt_isr_handler(void) { - uint8_t index; - - if (i & (1 << ETS_WDT_INUM)) { - index = ETS_WDT_INUM; - } else if (i & (1 << ETS_GPIO_INUM)) { - index = ETS_GPIO_INUM; - } else { - index = __builtin_ffs(i) - 1; - - if (index == ETS_MAX_INUM) { - i &= ~(1 << ETS_MAX_INUM); - index = __builtin_ffs(i) - 1; - } - } + do { + uint32_t mask = soc_get_int_mask(); + + for (int i = 0; i < ETS_INT_MAX && mask; i++) { + int bit = 1 << i; - _xt_clear_ints(1 << index); + if (!(bit & mask) || !s_isr[i].handler) + continue; - _xt_isr_status = 1; - isr[index].handler(isr[index].arg); - _xt_isr_status = 0; + soc_clear_int_mask(bit); + + s_xt_isr_status = 1; + s_isr[i].handler(s_isr[i].arg); + s_xt_isr_status = 0; + + mask &= ~bit; + } + } while (soc_get_int_mask()); - return i & ~(1 << index); + if (s_switch_ctx_flag) { + vTaskSwitchContext(); + s_switch_ctx_flag = 0; + } } int xPortInIsrContext(void) { - return _xt_isr_status != 0; + return s_xt_isr_status != 0; } void __attribute__((weak, noreturn)) vApplicationStackOverflowHook(xTaskHandle xTask, const char *pcTaskName) { ets_printf("***ERROR*** A stack overflow in task %s has been detected.\r\n", pcTaskName); - abort(); } @@ -344,15 +413,29 @@ BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void * const pvBuffer, return xQueueReceive(xQueue, pvBuffer, xTicksToWait); } -void vApplicationIdleHook(void) +void esp_internal_idle_hook(void) { - extern void pmIdleHook(void); - extern void esp_task_wdt_reset(void); - - pmIdleHook(); esp_task_wdt_reset(); + + esp_sleep_start(); } +#ifndef DISABLE_FREERTOS +#if configUSE_IDLE_HOOK == 1 +void __attribute__((weak)) vApplicationIdleHook(void) +{ + +} +#endif + +#if configUSE_TICK_HOOK == 1 +void __attribute__((weak)) vApplicationTickHook(void) +{ + +} +#endif +#endif + uint32_t xPortGetTickRateHz(void) { return (uint32_t)configTICK_RATE_HZ; diff --git a/components/freertos/port/esp8266/xtensa_context.S b/components/freertos/port/esp8266/xtensa_context.S index 903c7d9f4..8c4b66739 100644 --- a/components/freertos/port/esp8266/xtensa_context.S +++ b/components/freertos/port/esp8266/xtensa_context.S @@ -37,7 +37,6 @@ NOERROR: .error "C preprocessor needed for this file: make sure its filename\ #include "freertos/xtensa_rtos.h" -// .section .iram.text .section .text /******************************************************************************* @@ -76,82 +75,19 @@ Exit conditions: .type _xt_context_save,@function .align 4 _xt_context_save: - - s32i a2, sp, XT_STK_A2 - s32i a3, sp, XT_STK_A3 - s32i a4, sp, XT_STK_A4 - s32i a5, sp, XT_STK_A5 - s32i a6, sp, XT_STK_A6 - s32i a7, sp, XT_STK_A7 - s32i a8, sp, XT_STK_A8 - s32i a9, sp, XT_STK_A9 - s32i a10, sp, XT_STK_A10 - s32i a11, sp, XT_STK_A11 - - /* - Call0 ABI callee-saved regs a12-15 do not need to be saved here. - a12-13 are the caller's responsibility so it can use them as scratch. - So only need to save a14-a15 here for Windowed ABI (not Call0). - */ - #ifndef __XTENSA_CALL0_ABI__ - s32i a14, sp, XT_STK_A14 - s32i a15, sp, XT_STK_A15 - #endif + s32i a2, sp, XT_STK_A2 + s32i a3, sp, XT_STK_A3 + s32i a4, sp, XT_STK_A4 + s32i a5, sp, XT_STK_A5 + s32i a6, sp, XT_STK_A6 + s32i a7, sp, XT_STK_A7 + s32i a8, sp, XT_STK_A8 + s32i a9, sp, XT_STK_A9 + s32i a10, sp, XT_STK_A10 + s32i a11, sp, XT_STK_A11 rsr a3, SAR - s32i a3, sp, XT_STK_SAR - - #if XCHAL_HAVE_LOOPS - rsr a3, LBEG - s32i a3, sp, XT_STK_LBEG - rsr a3, LEND - s32i a3, sp, XT_STK_LEND - rsr a3, LCOUNT - s32i a3, sp, XT_STK_LCOUNT - #endif - - #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) - mov a9, a0 /* preserve ret addr */ - #endif - - #ifndef __XTENSA_CALL0_ABI__ - /* - To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15. - Need to save a9,12,13 temporarily (in frame temps) and recover originals. - Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow - and underflow exceptions disabled (assured by PS.EXCM == 1). - */ - s32i a12, sp, XT_STK_TMP+0 /* temp. save stuff in stack frame */ - s32i a13, sp, XT_STK_TMP+4 - s32i a9, sp, XT_STK_TMP+8 - l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */ - l32i a13, sp, XT_STK_A13 - l32i a9, sp, XT_STK_A9 - addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */ - call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */ - addi sp, sp, -XT_STK_FRMSZ - l32i a12, sp, XT_STK_TMP+0 /* recover stuff from stack frame */ - l32i a13, sp, XT_STK_TMP+4 - l32i a9, sp, XT_STK_TMP+8 - #endif - - #if XCHAL_EXTRA_SA_SIZE > 0 - /* - NOTE: Normally the xthal_save_extra_nw macro only affects address - registers a2-a5. It is theoretically possible for Xtensa processor - designers to write TIE that causes more address registers to be - affected, but it is generally unlikely. If that ever happens, - more registers need to be saved/restored around this macro invocation. - Here we assume a9,12,13 are preserved. - Future Xtensa tools releases might limit the regs that can be affected. - */ - addi a2, sp, XT_STK_EXTRA /* where to save it */ - call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */ - #endif - - #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) - mov a0, a9 /* retrieve ret addr */ - #endif + s32i a3, sp, XT_STK_SAR ret @@ -184,155 +120,25 @@ Exit conditions: .type _xt_context_restore,@function .align 4 _xt_context_restore: - - #if XCHAL_EXTRA_SA_SIZE > 0 - /* - NOTE: Normally the xthal_restore_extra_nw macro only affects address - registers a2-a5. It is theoretically possible for Xtensa processor - designers to write TIE that causes more address registers to be - affected, but it is generally unlikely. If that ever happens, - more registers need to be saved/restored around this macro invocation. - Here we only assume a13 is preserved. - Future Xtensa tools releases might limit the regs that can be affected. - */ - mov a13, a0 /* preserve ret addr */ - addi a2, sp, XT_STK_EXTRA /* where to find it */ - call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */ - mov a0, a13 /* retrieve ret addr */ - #endif - - #if XCHAL_HAVE_LOOPS - l32i a2, sp, XT_STK_LBEG - l32i a3, sp, XT_STK_LEND - wsr a2, LBEG - l32i a2, sp, XT_STK_LCOUNT - wsr a3, LEND - wsr a2, LCOUNT - #endif - - l32i a3, sp, XT_STK_SAR - l32i a2, sp, XT_STK_A2 + l32i a3, sp, XT_STK_SAR + l32i a2, sp, XT_STK_A2 wsr a3, SAR - l32i a3, sp, XT_STK_A3 - l32i a4, sp, XT_STK_A4 - l32i a5, sp, XT_STK_A5 - l32i a6, sp, XT_STK_A6 - l32i a7, sp, XT_STK_A7 - l32i a8, sp, XT_STK_A8 - l32i a9, sp, XT_STK_A9 - l32i a10, sp, XT_STK_A10 - l32i a11, sp, XT_STK_A11 + l32i a3, sp, XT_STK_A3 + l32i a4, sp, XT_STK_A4 + l32i a5, sp, XT_STK_A5 + l32i a6, sp, XT_STK_A6 + l32i a7, sp, XT_STK_A7 + l32i a8, sp, XT_STK_A8 + l32i a9, sp, XT_STK_A9 + l32i a10, sp, XT_STK_A10 + l32i a11, sp, XT_STK_A11 /* Call0 ABI callee-saved regs a12-15 do not need to be restored here. However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), so need to be restored anyway, despite being callee-saved in Call0. */ - l32i a12, sp, XT_STK_A12 - l32i a13, sp, XT_STK_A13 - #ifndef __XTENSA_CALL0_ABI__ - l32i a14, sp, XT_STK_A14 - l32i a15, sp, XT_STK_A15 - #endif + l32i a12, sp, XT_STK_A12 + l32i a13, sp, XT_STK_A13 ret - - -/******************************************************************************* - -_xt_coproc_init - -Initializes global co-processor management data, setting all co-processors -to "unowned". Leaves CPENABLE as it found it (does NOT clear it). - -Called during initialization of the RTOS, before any threads run. - -This may be called from normal Xtensa single-threaded application code which -might use co-processors. The Xtensa run-time initialization enables all -co-processors. They must remain enabled here, else a co-processor exception -might occur outside of a thread, which the exception handler doesn't expect. - -Entry Conditions: - Xtensa single-threaded run-time environment is in effect. - No thread is yet running. - -Exit conditions: - None. - -Obeys ABI conventions per prototype: - void _xt_coproc_init(void) - -*******************************************************************************/ - -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_init - .type _xt_coproc_init,@function - .align 4 -_xt_coproc_init: - ENTRY0 - - /* Initialize thread co-processor ownerships to 0 (unowned). */ - movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */ - addi a3, a2, XCHAL_CP_MAX << 2 /* a3 = top+1 of owner array */ - movi a4, 0 /* a4 = 0 (unowned) */ -1: s32i a4, a2, 0 - addi a2, a2, 4 - bltu a2, a3, 1b - - RET0 - -#endif - - -/******************************************************************************* - -_xt_coproc_release - -Releases any and all co-processors owned by a given thread. The thread is -identified by it's co-processor state save area defined in xtensa_context.h . - -Must be called before a thread's co-proc save area is deleted to avoid -memory corruption when the exception handler tries to save the state. -May be called when a thread terminates or completes but does not delete -the co-proc save area, to avoid the exception handler having to save the -thread's co-proc state before another thread can use it (optimization). - -Entry Conditions: - A2 = Pointer to base of co-processor state save area. - -Exit conditions: - None. - -Obeys ABI conventions per prototype: - void _xt_coproc_release(void * coproc_sa_base) - -*******************************************************************************/ - -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_release - .type _xt_coproc_release,@function - .align 4 -_xt_coproc_release: - ENTRY0 /* a2 = base of save area */ - - movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */ - addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */ - movi a5, 0 /* a5 = 0 (unowned) */ - - rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */ - -1: l32i a7, a3, 0 /* a7 = owner at a3 */ - bne a2, a7, 2f /* if (coproc_sa_base == owner) */ - s32i a5, a3, 0 /* owner = unowned */ -2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ - bltu a3, a4, 1b /* repeat until end of array */ - -3: wsr a6, PS /* restore interrupts */ - - RET0 - -#endif - - diff --git a/components/freertos/port/esp8266/xtensa_init.c b/components/freertos/port/esp8266/xtensa_init.c deleted file mode 100644 index 9b37253c1..000000000 --- a/components/freertos/port/esp8266/xtensa_init.c +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* -Copyright (c) 2006-2009 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - - XTENSA INITIALIZATION ROUTINES CODED IN C - -This header is a place to put miscellaneous Xtensa RTOS-generic initialization -functions that are implemented in C. - -This header contains definitions and macros for use primarily by Xtensa -RTOS assembly coded source files. It includes and uses the Xtensa hardware -abstraction layer (HAL) to deal with config specifics. It may also be -included in C source files. - -*******************************************************************************/ - -#ifndef XTENSA_INIT_H -#define XTENSA_INIT_H - -#ifdef XT_BOARD -#include -#endif - -#include "freertos/xtensa_rtos.h" - - -#ifdef XT_RTOS_TIMER_INT -#ifndef XT_CLOCK_FREQ - -unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ - -/* -Compute and initialize at run-time the tick divisor (the number of -processor clock cycles in an RTOS tick, used to set the tick timer). -Called when the processor clock frequency is not known at compile-time. -*/ -void _xt_tick_divisor_init(void) -{ - #ifdef XT_BOARD - _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; - #else - #error "No way to obtain processor clock frequency" - #endif /* XT_BOARD */ -} - -#endif /* XT_CLOCK_FREQ */ -#endif /* XT_RTOS_TIMER_INT */ - -#endif /* XTENSA_INIT_H */ diff --git a/components/freertos/port/esp8266/xtensa_vectors.S b/components/freertos/port/esp8266/xtensa_vectors.S index 1dcc2060f..3485d74bf 100644 --- a/components/freertos/port/esp8266/xtensa_vectors.S +++ b/components/freertos/port/esp8266/xtensa_vectors.S @@ -80,45 +80,19 @@ Add to compile passing. #define _INTERRUPT_LEVEL 3 STRUCT_BEGIN +STRUCT_FIELD (long,4,HESF_,EPC3) +STRUCT_FIELD (long,4,HESF_,EPS3) +STRUCT_AFIELD(long,4,HESF_,AREG, 16) /* address registers ar0..ar15 */ STRUCT_FIELD (long,4,HESF_,SAR) -#ifdef __XTENSA_WINDOWED_ABI__ -STRUCT_FIELD (long,4,HESF_,WINDOWSTART) -STRUCT_FIELD (long,4,HESF_,WINDOWBASE) -#endif -STRUCT_FIELD (long,4,HESF_,EPC1) STRUCT_FIELD (long,4,HESF_,EXCCAUSE) +STRUCT_FIELD (long,4,HESF_,EPC1) STRUCT_FIELD (long,4,HESF_,EXCVADDR) STRUCT_FIELD (long,4,HESF_,EXCSAVE1) -STRUCT_FIELD (long,4,HESF_,EPC3) -STRUCT_FIELD (long,4,HESF_,EPS3) -#if XCHAL_HAVE_XEA1 -STRUCT_FIELD (long,4,HESF_,VPRI) /* (XEA1 only) */ -#endif -#if XCHAL_HAVE_MAC16 -STRUCT_FIELD (long,4,HESF_,ACCLO) -STRUCT_FIELD (long,4,HESF_,ACCHI) -/*STRUCT_AFIELD(long,4,HESF_,MR, 4)*/ -#endif -#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,HESF_,LCOUNT) -STRUCT_FIELD (long,4,HESF_,LBEG) -STRUCT_FIELD (long,4,HESF_,LEND) -#endif -#ifdef __XTENSA_WINDOWED_ABI__ -STRUCT_AFIELD(long,4,HESF_,AREG, 64) /* address registers ar0..ar63 */ -#else -STRUCT_AFIELD(long,4,HESF_,AREG, 16) /* address registers ar0..ar15 */ -#endif #define HESF_AR(n) HESF_AREG+((n)*4) STRUCT_END(HighPriFrame) #define HESF_TOTALSIZE HighPriFrameSize+32 /* 32 bytes for interrupted code's save areas under SP */ -#if XCHAL_HAVE_XEA1 && HAVE_XSR /* could be made true for T1040 and T1050 */ -# error "high-priority interrupt stack frame needs adjustment if HAVE_XSR is allowed with XEA1" -#endif - - #define PRI_N_STACK_SIZE 512 /* default to 1 kB stack for each level-N handling */ #define PRI_N_STACK_SIZE2 256 /* default to 1 kB stack for each level-N handling */ @@ -133,6 +107,7 @@ STRUCT_END(HighPriFrame) .align 16 _chip_nmi_stk: .space PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2 + HESF_TOTALSIZE + .global LoadStoreErrorHandlerStack .balign 16 LoadStoreErrorHandlerStack: @@ -182,55 +157,52 @@ _chip_interrupt_tmp: * (Fast path (no branches) is for L8UI) */ .literal_position - + .type LoadStoreErrorHandler, @function .balign 4 LoadStoreErrorHandler: -// .global LoadStoreErrorHandler - .type LoadStoreErrorHandler, @function - - rsr a0, excsave1 # restore a0 saved by UserExceptionVector - wsr a1, excsave1 # save a1 to excsave1, a1 can be used as varalbe + rsr a0, excsave1 # restore a0 saved by UserExceptionVector + wsr a1, excsave1 # save a1 to excsave1, a1 can be used as varalbe - movi a1, _chip_nmi_cnt - l32i a1, a1, 0 + movi a1, _chip_nmi_cnt + l32i a1, a1, 0 - bnez a1, LoadStoreErrorHandler_reentry - movi sp, LoadStoreErrorHandlerStack + bnez a1, LoadStoreErrorHandler_reentry + movi sp, LoadStoreErrorHandlerStack j LoadStoreErrorHandler_common LoadStoreErrorHandler_reentry: - movi sp, LoadStoreErrorHandlerStack_reentry + movi sp, LoadStoreErrorHandlerStack_reentry LoadStoreErrorHandler_common: /* Registers are saved in the address corresponding to their register * number times 4. This allows a quick and easy mapping later on when * needing to store the value to a particular register number. */ - s32i a0, sp, 0 - s32i a2, sp, 0x08 - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - rsr a0, sar # Save SAR in a0 to restore later + s32i a0, sp, 0 + s32i a2, sp, 0x08 + s32i a3, sp, 0x0c + s32i a4, sp, 0x10 + rsr a0, sar # Save SAR in a0 to restore later /* Examine the opcode which generated the exception */ /* Note: Instructions are in this order to avoid pipeline stalls. */ rsr a2, epc1 movi a3, ~3 - ssa8l a2 # sar is now correct shift for aligned read - and a2, a2, a3 # a2 now 4-byte aligned address of instruction - l32i a4, a2, 0 - l32i a2, a2, 4 - movi a3, 0x00700F # opcode mask for l8ui/l16si/l16ui - src a2, a2, a4 # a2 now instruction that failed - and a3, a2, a3 # a3 is masked instruction + ssa8l a2 # sar is now correct shift for aligned read + and a2, a2, a3 # a2 now 4-byte aligned address of instruction + l32i a4, a2, 0 + l32i a2, a2, 4 + movi a3, 0x00700F # opcode mask for l8ui/l16si/l16ui + src a2, a2, a4 # a2 now instruction that failed + and a3, a2, a3 # a3 is masked instruction # This is store instruction movi a4, 0x004002 - beq a3, a4, .LSE_check_s8i_store # s8i + beq a3, a4, .LSE_check_s8i_store # s8i - movi a4, 0x005002 - beq a3, a4, .LSE_check_s16i_store # s16i + movi a4, 0x005002 + beq a3, a4, .LSE_check_s16i_store # s16i - bnei a3, 0x000002, .LSE_check_l16 + bnei a3, 0x000002, .LSE_check_l16 /* Note: At this point, opcode could technically be one of two things: * xx0xx2 (L8UI) @@ -239,14 +211,14 @@ LoadStoreErrorHandler_common: * opcode, so we don't bother to check for that case and presume this * is always an L8UI. */ - movi a4, ~3 - rsr a3, excvaddr # read faulting address - and a4, a3, a4 # a4 now word aligned read address + movi a4, ~3 + rsr a3, excvaddr # read faulting address + and a4, a3, a4 # a4 now word aligned read address - l32i a4, a4, 0 # perform the actual read - ssa8l a3 # sar is now shift to extract a3's byte - srl a3, a4 # shift right correct distance - extui a4, a3, 0, 8 # mask off bits we need for an l8 + l32i a4, a4, 0 # perform the actual read + ssa8l a3 # sar is now shift to extract a3's byte + srl a3, a4 # shift right correct distance + extui a4, a3, 0, 8 # mask off bits we need for an l8 .LSE_post_fetch: /* We jump back here after either the L8UI or the L16*I routines do the @@ -258,10 +230,10 @@ LoadStoreErrorHandler_common: * return back to the instruction following the one we just emulated */ /* Note: Instructions are in this order to avoid pipeline stalls */ - rsr a3, epc1 - wsr a0, sar - addi a3, a3, 0x3 - wsr a3, epc1 + rsr a3, epc1 + wsr a0, sar + addi a3, a3, 0x3 + wsr a3, epc1 /* Stupid opcode tricks: The jumptable we use later on needs 16 bytes * per entry (so we can avoid a second jump by just doing a RFE inside @@ -272,24 +244,24 @@ LoadStoreErrorHandler_common: * instead of 4, we will get the register number multiplied by 2. This * combined with an addx8 will give us an effective addx16 without * needing any extra shift operations. */ - extui a2, a2, 3, 5 # a2 is now destination register 0-15 times 2 + extui a2, a2, 3, 5 # a2 is now destination register 0-15 times 2 - bgei a2, 10, .LSE_assign_reg # a5..a15 use jumptable - beqi a2, 2, .LSE_assign_a1 # a1 uses a special routine + bgei a2, 10, .LSE_assign_reg # a5..a15 use jumptable + beqi a2, 2, .LSE_assign_a1 # a1 uses a special routine /* We're storing into a0 or a2..a4, which are all saved in our "stack" * area. Calculate the correct address and stick the value in there, * then just do our normal restore and RFE (no jumps required, which * actually makes a0..a4 substantially faster). */ - addx2 a2, a2, sp - s32i a4, a2, 0 + addx2 a2, a2, sp + s32i a4, a2, 0 /* Restore all regs and return */ - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - rsr a1, excsave1 # restore a1 saved by UserExceptionVector + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr a1, excsave1 # restore a1 saved by UserExceptionVector rfe .LSE_assign_reg: @@ -299,171 +271,171 @@ LoadStoreErrorHandler_common: /* Calculate the jumptable address, and restore all regs except a2 and * a4 so we have less to do after jumping. */ /* Note: Instructions are in this order to avoid pipeline stalls. */ - movi a3, .LSE_jumptable_base - l32i a0, sp, 0 - addx8 a2, a2, a3 # a2 is now the address to jump to - l32i a3, sp, 0x0c + movi a3, .LSE_jumptable_base + l32i a0, sp, 0 + addx8 a2, a2, a3 # a2 is now the address to jump to + l32i a3, sp, 0x0c jx a2 .balign 4 .LSE_check_l16: /* At this point, a2 contains the opcode, a3 is masked opcode */ - movi a4, 0x001002 # l16si or l16ui opcode after masking - bne a3, a4, .LSE_wrong_opcode + movi a4, 0x001002 # l16si or l16ui opcode after masking + bne a3, a4, .LSE_wrong_opcode /* Note: At this point, the opcode could be one of two things: * xx1xx2 (L16UI) * xx9xx2 (L16SI) * Both of these we can handle. */ - movi a4, ~3 - rsr a3, excvaddr # read faulting address - and a4, a3, a4 # a4 now word aligned read address + movi a4, ~3 + rsr a3, excvaddr # read faulting address + and a4, a3, a4 # a4 now word aligned read address - l32i a4, a4, 0 # perform the actual read - ssa8l a3 # sar is now shift to extract a3's bytes - srl a3, a4 # shift right correct distance - extui a4, a3, 0, 16 # mask off bits we need for an l16 + l32i a4, a4, 0 # perform the actual read + ssa8l a3 # sar is now shift to extract a3's bytes + srl a3, a4 # shift right correct distance + extui a4, a3, 0, 16 # mask off bits we need for an l16 - bbci a2, 15, .LSE_post_fetch # Not a signed op - bbci a4, 15, .LSE_post_fetch # Value does not need sign-extension + bbci a2, 15, .LSE_post_fetch # Not a signed op + bbci a4, 15, .LSE_post_fetch # Value does not need sign-extension movi a3, 0xFFFF0000 - or a4, a3, a4 # set 32-bit sign bits + or a4, a3, a4 # set 32-bit sign bits j .LSE_post_fetch .balign 4 .LSE_check_s8i_store: - s32i a5, sp, 0x14 - s32i a6, sp, 0x18 + s32i a5, sp, 0x14 + s32i a6, sp, 0x18 movi a5,0xff j .LSE_check_store .LSE_check_s16i_store: - s32i a5, sp, 0x14 - s32i a6, sp, 0x18 - movi a5,0xffff + s32i a5, sp, 0x14 + s32i a6, sp, 0x18 + movi a5, 0xffff j .LSE_check_store .LSE_check_store: movi a4, ~3 - rsr a3, excvaddr # write faulting address - and a4, a3, a4 # a4 now word aligned write address + rsr a3, excvaddr # write faulting address + and a4, a3, a4 # a4 now word aligned write address ssa8b a3 - l32i a3, a4, 0 # perform the actual read + l32i a3, a4, 0 # perform the actual read - mov a4,a5 - sll a4,a4 - movi a6,-1 - xor a4,a6,a4 - and a3,a3,a4 + mov a4, a5 + sll a4, a4 + movi a6, -1 + xor a4, a6, a4 + and a3, a3, a4 - movi a4, ~3 - rsr a6, excvaddr # write faulting address - and a4, a6, a4 # a4 now word aligned write address + movi a4, ~3 + rsr a6, excvaddr # write faulting address + and a4, a6, a4 # a4 now word aligned write address - extui a2, a2, 4, 4 # a2 is now destination register 0-15 times 2 + extui a2, a2, 4, 4 # a2 is now destination register 0-15 times 2 - bgei a2,7,.LSE_big_reg - movi a6,4 - mull a6,a2,a6 - add a2, a6, sp - l32i a2, a2, 0 + bgei a2, 7, .LSE_big_reg + movi a6, 4 + mull a6, a2, a6 + add a2, a6, sp + l32i a2, a2, 0 j .Write_data .LSE_big_reg: - movi a6,7 - sub a2,a2,a6 - movi a6,8 - mull a2,a2,a6 + movi a6, 7 + sub a2, a2, a6 + movi a6, 8 + mull a2, a2, a6 movi a6,.LSE_big_reg_table - add a2,a2,a6 - jx a2 + add a2, a2, a6 + jx a2 .balign 4 .LSE_big_reg_table: .org .LSE_big_reg_table + (0*(2*4)) - mov a2,a7 + mov a2, a7 j .Write_data .org .LSE_big_reg_table + (1*(2*4)) - mov a2,a8 + mov a2, a8 j .Write_data .org .LSE_big_reg_table + (2*(2*4)) - mov a2,a9 + mov a2, a9 j .Write_data .org .LSE_big_reg_table + (3*(2*4)) - mov a2,a10 + mov a2, a10 j .Write_data .org .LSE_big_reg_table + (4*(2*4)) - mov a2,a11 + mov a2, a11 j .Write_data .org .LSE_big_reg_table + (5*(2*4)) - mov a2,a12 + mov a2, a12 j .Write_data .org .LSE_big_reg_table + (6*(2*4)) - mov a2,a13 + mov a2, a13 j .Write_data .org .LSE_big_reg_table + (7*(2*4)) - mov a2,a14 + mov a2, a14 j .Write_data .org .LSE_big_reg_table + (8*(2*4)) - mov a2,a15 + mov a2, a15 j .Write_data .Write_data: - and a2,a2,a5 - sll a2,a2 - or a3,a3,a2 + and a2, a2, a5 + sll a2, a2 + or a3, a3, a2 - s32i a3,a4,0 + s32i a3, a4, 0 - rsr a3, epc1 - wsr a0, sar - addi a3, a3, 0x3 - wsr a3, epc1 + rsr a3, epc1 + wsr a0, sar + addi a3, a3, 0x3 + wsr a3, epc1 /* Restore all regs and return */ - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - l32i a5, sp, 0x14 - l32i a6, sp, 0x18 - rsr a1, excsave1 # restore a1 saved by UserExceptionVector + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + l32i a5, sp, 0x14 + l32i a6, sp, 0x18 + rsr a1, excsave1 # restore a1 saved by UserExceptionVector rfe .LSE_wrong_opcode: /* If we got here it's not an opcode we can try to fix, so bomb out. * Restore registers so any dump the fatal exception routine produces * will have correct values */ - wsr a0, sar - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 + wsr a0, sar + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 rsr a1, excsave1 call0 _xt_ext_panic .balign 4 .LSE_assign_a1: /* a1 is saved in excsave1, so just update that with the value, */ - s32i a4, sp, 0x04 + s32i a4, sp, 0x04 /* Then restore all regs and return */ - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - l32i a1, sp, 0x04 + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + l32i a1, sp, 0x04 rfe .balign 4 @@ -475,129 +447,82 @@ LoadStoreErrorHandler_common: .set .LSE_jumptable_base, .LSE_jumptable - (16 * 5) .org .LSE_jumptable_base + (16 * 5) - mov a5, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + mov a5, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 6) - mov a6, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + mov a6, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 7) - mov a7, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + mov a7, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 8) - mov a8, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + mov a8, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 9) - mov a9, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + mov a9, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 10) mov a10, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 11) mov a11, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 12) mov a12, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 13) mov a13, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 14) mov a14, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe .org .LSE_jumptable_base + (16 * 15) mov a15, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr a1, excsave1 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 rfe -#if 0 -/* -Panic handler. -Should be reached by call0 (preferable) or jump only. If call0, a0 says where -from. If on simulator, display panic message and abort, else loop indefinitely. -*/ -// .section .iram.text - .section .text - .global _xt_panic - .type _xt_panic,@function - .align 4 -_xt_panic: - #ifdef XT_SIMULATOR - addi a4, a0, -3 /* point to call0 */ - movi a3, _xt_panic_message - movi a2, SYS_log_msg - simcall - movi a2, SYS_gdb_abort - simcall - #else - rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */ -1: j 1b /* loop infinitely */ - #endif - - .section .rodata, "a" - .align 4 -_xt_panic_message: - .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n" -#endif - -#ifdef XT_INTEXC_HOOKS - /* - Hooks to dynamically install handlers for exceptions and interrupts. - Allows automated regression frameworks to install handlers per test. - Consists of an array of function pointers indexed by interrupt level, - with index 0 containing the entry for user exceptions. - Initialized with all 0s, meaning no handler is installed at each level. - See comment in xtensa_rtos.h for more details. - */ - .data - .global _xt_intexc_hooks - .type _xt_intexc_hooks,@object - .align 4 -_xt_intexc_hooks: - .fill XT_INTEXC_HOOK_NUM, 4, 0 -#endif - /******************************************************************************* @@ -629,38 +554,28 @@ Debug Exception. -------------------------------------------------------------------------------- */ -#if XCHAL_HAVE_DEBUG - .begin literal_prefix .DebugExceptionVector .section .DebugExceptionVector.text, "ax" .global _DebugExceptionVector .align 4 .literal_position _DebugExceptionVector: - - #ifdef XT_SIMULATOR - /* - In the simulator, let the debugger (if any) handle the debug exception, - or simply stop the simulation: - */ - wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */ - movi a2, SYS_gdb_enter_sktloop - simcall /* have ISS handle debug exc. */ - #elif 0 /* change condition to 1 to use the HAL minimal debug handler */ - wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL - movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */ - jx a3 - #else - wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */ - wsr a0, EXCSAVE_1 - wsr a1, EXCSAVE_2 - call0 _xt_ext_panic /* does not return */ - rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */ - #endif + wsr a0, EXCSAVE_1 + wsr a1, EXCSAVE_2 + movi a0, 1 + wsr a0, EXCCAUSE + call0 _xt_debug_exc .end literal_prefix -#endif + + .section .text + .type _xt_user_exc,@function + .align 4 +_xt_debug_exc: + rsr a0, (EPC + XCHAL_DEBUGLEVEL) + wsr a0, EPC1 + call0 _xt_ext_panic /* does not return */ /* -------------------------------------------------------------------------------- @@ -669,27 +584,19 @@ Double exceptions are not a normal occurrence. They indicate a bug of some kind. -------------------------------------------------------------------------------- */ -#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR - .begin literal_prefix .DoubleExceptionVector .section .DoubleExceptionVector.text, "ax" .global _DoubleExceptionVector .align 4 .literal_position _DoubleExceptionVector: - wsr a0, EXCSAVE_1 - wsr a1, EXCSAVE_2 + wsr a0, EXCSAVE_1 + wsr a1, EXCSAVE_2 j _xt_ext_panic - - #if XCHAL_HAVE_DEBUG - break 1, 4 /* unhandled double exception */ - #endif - call0 _xt_ext_panic /* does not return */ - rfde /* make a0 point here not later */ + rfde /* make a0 point here not later */ .end literal_prefix -#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ /* -------------------------------------------------------------------------------- @@ -703,25 +610,14 @@ Kernel Exception (including Level 1 Interrupt from kernel mode). .align 4 .literal_position _KernelExceptionVector: - wsr a0, EXCSAVE_1 /* preserve a0 */ - wsr a1, EXCSAVE_2 + wsr a0, EXCSAVE_1 /* preserve a0 */ + wsr a1, EXCSAVE_2 j _xt_ext_panic /* never returns here - call0 is used as a jump (see note at top) */ .end literal_prefix -// .section .iram.text - .section .text - .align 4 - .literal_position -_xt_kernel_exc: - #if XCHAL_HAVE_DEBUG - break 1, 0 /* unhandled kernel exception */ - #endif - call0 _xt_ext_panic /* does not return */ - rfe /* make a0 point here not there */ - /* -------------------------------------------------------------------------------- @@ -737,36 +633,16 @@ User Exception (including Level 1 Interrupt from user mode). .literal_position _UserExceptionVector: - wsr a0, EXCSAVE_1 /* preserve a0 */ - wsr a1, EXCSAVE_2 - call0 _xt_user_exc /* user exception handler */ + wsr a0, EXCSAVE_1 /* preserve a0 */ + wsr a1, EXCSAVE_2 + call0 _xt_user_exc /* user exception handler */ /* never returns here - call0 is used as a jump (see note at top) */ .end literal_prefix -// .section .iram.text - .section .text - /* - Insert some waypoints for jumping beyond the signed 8-bit range - of conditional branch instructions, so the conditional branchces - to specific-cause exception handlers are not taken in the mainline. - Saves some cycles in the mainline. - */ - - #if XCHAL_HAVE_WINDOWED - .align 4 -_xt_to_alloca_exc: - call0 _xt_alloca_exc /* in window vectors section */ - /* never returns here - call0 is used as a jump (see note at top) */ - #endif - - .align 4 - .literal_position -_xt_to_syscall_exc: - call0 _xt_syscall_exc - /* never returns here - call0 is used as a jump (see note at top) */ /* User exception handler begins here. */ + .section .text .type _xt_user_exc,@function .align 4 _xt_user_exc: @@ -774,126 +650,40 @@ _xt_user_exc: Handle alloca and syscall exceptions before allocating stack frame and interacting with RTOS. */ - rsr a0, EXCCAUSE - #if XCHAL_HAVE_WINDOWED - beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc - #endif - beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc - beqi a0, EXCCAUSE_LOAD_STORE_ERROR, LoadStoreErrorHandler - beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_user_entry1 + rsr a0, EXCCAUSE + beqi a0, EXCCAUSE_LOAD_STORE_ERROR, LoadStoreErrorHandler + beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_user_entry1 j _xt_ext_panic _xt_user_entry1: /* Allocate interrupt stack frame and save minimal context. */ - mov a0, sp /* sp == a1 */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ - rsr a0, PS /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_1 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 - movi a0, _xt_user_exit /* save exit point for dispatch */ - s32i a0, sp, XT_STK_EXIT - - /* - Handle co-processor exceptions after allocating stack frame and before - interacting with RTOS. - */ - #if XCHAL_CP_NUM > 0 - rsr a0, EXCCAUSE - bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc -.L_xt_user_exc_not_coproc: - #endif + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_user_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT /* Save rest of interrupt context and enter RTOS. */ - call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ /* !! We are now on the RTOS system stack !! */ /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ - #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM - #else - movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE - #endif - wsr a0, PS + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + wsr a0, PS rsync /* !! It is OK to call C handlers after this point. !! */ - /* Handle exceptions per EXCCAUSE. */ - rsr a2, EXCCAUSE /* a2 = exception cause */ - beqi a2, EXCCAUSE_LEVEL1INTERRUPT, .L_xt_user_int /* level 3 int */ - - #ifdef XT_INTEXC_HOOKS - /* - Call exception hook to pre-handle exceptions (if installed). - Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). - */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 0 /* user exception hook index 0 */ - beqz a0, 1f -.Ln_xt_user_exc_call_hook: - #ifdef __XTENSA_CALL0_ABI__ - callx0 a0 - beqi a2, -1, .L_xt_user_done - #else - mov a6, a2 - callx4 a0 - beqi a6, -1, .L_xt_user_done - mov a2, a6 - #endif -1: - #endif - - /* USER_EDIT: - ADD ANY CUSTOM EXCEPTION HANDLER CODE HERE, OR CALL C HANDLER. - The exeption cause is in A2. After handling, jump to .L_xt_user_int . - Note on Call0 ABI: Callee-saved regs (a12-15) have not yet been saved, - so should not be corrupted here. A C handler will not corrupt them. - */ - - /* If we get here, the exception has not been handled. */ -.Ln_xt_user_unhandled: - #if XCHAL_HAVE_DEBUG - break 1, 1 /* unhandled user exception */ - #endif - call0 _xt_ext_panic - - /* Handle level 1 interrupts. OK to enable med-pri interrupts now. */ + /* Handle level 1 interrupts. No need to enable med-pri interrupts now. */ .L_xt_user_int: - rsil a0, 1 /* reenable ints above level 1 */ - - /* - Get mask of pending, enabled interrupts at this level into a2. - Comment this out if there is only one interrupt at this level. - */ - rsr a2, INTENABLE - rsr a3, INTERRUPT - movi a4, XCHAL_INTLEVEL1_MASK - and a2, a2, a3 - and a2, a2, a4 - - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, 1<<2 - beqz a0, 2f -.Ln_xt_user_int_call_hook: - #ifdef __XTENSA_CALL0_ABI__ - callx0 a0 - beqz a2, .L_xt_user_done - #else - mov a6, a2 - callx4 a0 - beqz a6, .L_xt_user_done - mov a2, a6 - #endif -2: - #endif /* USER_EDIT: ADD LOW PRIORITY LEVEL 1 INTERRUPT HANDLER CODE HERE, OR CALL C HANDLER. @@ -904,48 +694,21 @@ _xt_user_entry1: When done, ensure a2 contains a mask of unhandled (still pending) enabled ints at this level, and fall through. */ - - #if XT_TIMER_INTPRI == 1 -.Ln_xt_user_int_timer: - movi a3, 0xFFBF - and a3, a2, a3 - bnez a3, 3f - /* Interrupt handler for the RTOS tick timer if at this level. */ - movi a3, XT_TIMER_INTEN /* timer interrupt bit */ - /*bnone a2, a3, 3f*/ - #ifdef __XTENSA_CALL0_ABI__ - sub a12, a2, a3 /* clear timer int and save mask */ - call0 XT_RTOS_TIMER_INT - mov a2, a12 /* recover mask of remaining ints */ - beqz a2, 4f - #else - call4 XT_RTOS_TIMER_INT /* a2 automatically preserved */ - sub a2, a2, a3 /* clear timer int from mask */ - #endif 3: movi a0, _chip_interrupt_tmp s32i a1, a0, 0 mov a1, a0 +#ifndef CONFIG_TASK_SWITCH_FASTER movi a0, _xt_isr_handler callx0 a0 +#else + call0 _xt_isr_handler +#endif movi a0, _chip_interrupt_tmp l32i a1, a0, 0 - bnez a2, .Ln_xt_user_int_timer - #endif -4: - /* All interrupts at this level should have been handled now. */ - beqz a2, .L_xt_user_done - - /* If we get here, we have an unhandled interrupt. */ - #if XCHAL_HAVE_DEBUG - break 1, 1 /* unhandled user exception */ - /* EXCCAUSE == 4 (level 1 int) */ - #endif - call0 _xt_ext_panic - /* Done handling after XT_RTOS_INT_ENTER. Give control to RTOS. */ .L_xt_user_done: call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -958,85 +721,14 @@ _xt_user_entry1: .type _xt_user_exit,@function .align 4 _xt_user_exit: - l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ - wsr a0, PS - l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ - wsr a0, EPC_1 - l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ - l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ - rsync /* ensure PS and EPC written */ - rfe /* PS.EXCM is cleared */ - -/* --------------------------------------------------------------------------------- -Syscall Exception Handler (jumped to from User Exception Handler). -Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). -Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. --------------------------------------------------------------------------------- -*/ - -// .section .iram.text - .section .text - .type _xt_syscall_exc,@function - .align 4 -_xt_syscall_exc: - - #ifdef __XTENSA_CALL0_ABI__ - /* - Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. - Use a minimal stack frame (16B) to save A2 & A3 for scratch. - PS.EXCM could be cleared here, but unlikely to improve worst-case latency. - rsr a0, PS - addi a0, a0, -PS_EXCM_MASK - wsr a0, PS - */ - addi sp, sp, -16 - s32i a2, sp, 8 - s32i a3, sp, 12 - #else /* Windowed ABI */ - /* - Save necessary context and spill the register windows. - PS.EXCM is still set and must remain set until after the spill. - Reuse context save function though it saves more than necessary. - For this reason, a full interrupt stack frame is allocated. - */ - addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ - s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ - s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ - call0 _xt_context_save - #endif - - /* - Grab the interruptee's PC and skip over the 'syscall' instruction. - If it's at the end of a zero-overhead loop and it's not on the last - iteration, decrement loop counter and skip to beginning of loop. - */ - rsr a2, EPC_1 /* a2 = PC of 'syscall' */ - addi a3, a2, 3 /* ++PC */ - #if XCHAL_HAVE_LOOPS - rsr a0, LEND /* if (PC == LEND */ - bne a3, a0, 1f - rsr a0, LCOUNT /* && LCOUNT != 0) */ - beqz a0, 1f /* { */ - addi a0, a0, -1 /* --LCOUNT */ - rsr a3, LBEG /* PC = LBEG */ - wsr a0, LCOUNT /* } */ - #endif -1: wsr a3, EPC_1 /* update PC */ - - /* Restore interruptee's context and return from exception. */ - #ifdef __XTENSA_CALL0_ABI__ - l32i a2, sp, 8 - l32i a3, sp, 12 - addi sp, sp, 16 - #else - call0 _xt_context_restore - addi sp, sp, XT_STK_FRMSZ - #endif - movi a0, -1 - movnez a2, a0, a2 /* return -1 if not syscall 0 */ - rsr a0, EXCSAVE_1 - rfe + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ /* @@ -1045,8 +737,6 @@ here. However a template and example can be found in the Tensilica tools documentation: "Microprocessor Programmer's Guide". */ -#if XCHAL_HAVE_NMI - .begin literal_prefix .NMIExceptionVector .section .NMIExceptionVector.text, "ax" .global _NMIExceptionVector @@ -1054,63 +744,45 @@ documentation: "Microprocessor Programmer's Guide". .align 4 .literal_position _NMIExceptionVector: - wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */ - wsr a1, EXCSAVE_2 - call0 _xt_nmi /* load interrupt handler */ + wsr a0, EXCSAVE + XCHAL_NMILEVEL /* preserve a0 */ + wsr a1, EXCSAVE_2 + call0 _xt_nmi /* load interrupt handler */ /* never returns here - call0 is used as a jump (see note at top) */ .end literal_prefix -// .section .iram.text + .section .text .type _xt_nmi,@function .align 4 _xt_nmi: - - #ifdef XT_INTEXC_HOOKS - #error - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a0, _xt_intexc_hooks - l32i a0, a0, XCHAL_NMILEVEL<<2 - beqz a0, 1f -.Ln_xt_nmi_call_hook: - callx0 a0 /* must NOT disturb stack! */ -1: - #endif - /* USER_EDIT: ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. */ - movi a0, _chip_nmi_cnt - l32i a0, a0, 0 + movi a0, _chip_nmi_cnt + l32i a0, a0, 0 - bnez a0, nmi_reentry - movi a0, _chip_nmi_stk + PRI_N_STACK_SIZE // get ptr to save area + bnez a0, nmi_reentry + movi a0, _chip_nmi_stk + PRI_N_STACK_SIZE // get ptr to save area j nmi_common nmi_reentry: - movi a0, _chip_nmi_stk + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2// get ptr to save area + movi a0, _chip_nmi_stk + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2// get ptr to save area nmi_common: // interlock // Save a few registers so we can do some work: - s32i a2, a0, HESF_AR(2) -#if HAVE_XSR - //movi a0, LABEL(_Level,FromVector) // this dispatcher's address - movi a2, LABEL(_Pri_,_HandlerAddress) // dispatcher address var. - s32i a1, a0, HESF_AR(1) - l32i a2, a2, 0 // get dispatcher address - s32i a3, a0, HESF_AR(3) - xsr a2, EXCSAVE_LEVEL // get saved a0, restore dispatcher address -#else - #error - rsr a2, EXCSAVE_LEVEL // get saved a0 - s32i a1, a0, HESF_AR(1) - s32i a3, a0, HESF_AR(3) -#endif - s32i a4, a0, HESF_AR(4) - s32i a2, a0, HESF_AR(0) + s32i a2, a0, HESF_AR(2) + + movi a2, LABEL(_Pri_,_HandlerAddress) // dispatcher address var. + s32i a1, a0, HESF_AR(1) + l32i a2, a2, 0 // get dispatcher address + s32i a3, a0, HESF_AR(3) + xsr a2, EXCSAVE_LEVEL // get saved a0, restore dispatcher address + + s32i a4, a0, HESF_AR(4) + s32i a2, a0, HESF_AR(0) // Save/restore all exception state // (IMPORTANT: this code assumes no general exceptions occur @@ -1125,72 +797,37 @@ nmi_common: // is also possibly corrupted by any access thru an auto-refill // way on a processor with a full MMU). // - rsr a3, EPC1 - rsr a4, EXCCAUSE - s32i a3, a0, HESF_EPC1 - s32i a4, a0, HESF_EXCCAUSE -#if !XCHAL_HAVE_XEA1 - rsr a3, EXCVADDR - s32i a3, a0, HESF_EXCVADDR -#endif - rsr a4, EXCSAVE1 - s32i a4, a0, HESF_EXCSAVE1 - rsr a3, EPC3 - movi a4, nmi_rfi - beq a3, a4, nmi_reentried - s32i a3, a0, HESF_EPC3 - rsr a4, EPS3 - s32i a4, a0, HESF_EPS3 + rsr a3, EPC1 + rsr a4, EXCCAUSE + s32i a3, a0, HESF_EPC1 + s32i a4, a0, HESF_EXCCAUSE + rsr a3, EXCVADDR + s32i a3, a0, HESF_EXCVADDR + rsr a4, EXCSAVE1 + s32i a4, a0, HESF_EXCSAVE1 + rsr a3, EPC3 + movi a4, nmi_rfi + beq a3, a4, nmi_reentried + s32i a3, a0, HESF_EPC3 + rsr a4, EPS3 + s32i a4, a0, HESF_EPS3 nmi_reentried: - -#ifdef __XTENSA_WINDOWED_ABI__ - // Save remainder of entire address register file (!): - movi a2, XCHAL_NUM_AREGS - 8 // how many saved so far -#endif - - s32i a5, a0, HESF_AR(5) - s32i a6, a0, HESF_AR(6) - s32i a7, a0, HESF_AR(7) - -1: s32i a8, a0, HESF_AR(8) - s32i a9, a0, HESF_AR(9) - s32i a10, a0, HESF_AR(10) - s32i a11, a0, HESF_AR(11) - s32i a12, a0, HESF_AR(12) - s32i a13, a0, HESF_AR(13) - s32i a14, a0, HESF_AR(14) - s32i a15, a0, HESF_AR(15) - -#ifdef __XTENSA_WINDOWED_ABI__ - addi a8, a2, -8 - addi a10, a0, 8*4 - rotw 2 - bnez a2, 1b // loop until done - - rotw 2 - // back to original a2 ... - - // Save a few other registers required for C: - rsr a3, WINDOWSTART - rsr a4, WINDOWBASE - s32i a3, a0, HESF_WINDOWSTART - s32i a4, a0, HESF_WINDOWBASE - - // Setup window registers for first caller: - movi a3, 1 - movi a4, 0 - wsr a3, WINDOWSTART - wsr a4, WINDOWBASE - rsync - - // Note: register window has rotated, ie. a0..a15 clobbered. - -#endif /* __XTENSA_WINDOWED_ABI__ */ - - //movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE // get ptr to save area (is also initial stack ptr) - mov a1, a0 - movi a0, 0 // mark start of call frames in stack + s32i a5, a0, HESF_AR(5) + s32i a6, a0, HESF_AR(6) + s32i a7, a0, HESF_AR(7) + +1: s32i a8, a0, HESF_AR(8) + s32i a9, a0, HESF_AR(9) + s32i a10, a0, HESF_AR(10) + s32i a11, a0, HESF_AR(11) + s32i a12, a0, HESF_AR(12) + s32i a13, a0, HESF_AR(13) + s32i a14, a0, HESF_AR(14) + s32i a15, a0, HESF_AR(15) + + mov a1, a0 + movi a0, 0 // mark start of call frames in stack // Critical state saved, a bit more to do to allow window exceptions... @@ -1198,28 +835,9 @@ nmi_reentried: // Still have to fix PS while making sure interrupts stay disabled // at the appropriate level (ie. level 2 and below are disabled in this case). -#if XCHAL_HAVE_XEA1 - #error - movi a7, _xtos_intstruct // address of interrupt management globals - rsilft a3, _INTERRUPT_LEVEL, XTOS_LOCKLEVEL // lockout - movi a4, ~INTLEVEL_N_BELOW_MASK // mask out all interrupts at this level or lower - l32i a3, a7, XTOS_VPRI_ENABLED_OFS // read previous _xtos_vpri_enabled - l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled - s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled (mask interrupts as if at _INTERRUPT_LEVEL) - s32i a3, a1, HESF_VPRI // save previous vpri - movi a2, 0x50020 // WOE=1, UM=1, INTLEVEL=0 - and a3, a5, a4 // mask out selected interrupts - wsr a3, INTENABLE // disable all low-priority interrupts -#else // Load PS for C code, clear EXCM (NOTE: this step is different for XEA1): -# ifdef __XTENSA_CALL0_ABI__ - movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=0, RING=0 -# else - movi a2, 0x50020 + _INTERRUPT_LEVEL // WOE=1, CALLINC=1, UM=1, INTLEVEL=N, EXCM=0, RING=0 -# endif - -#endif - wsr a2, PS // update PS to enable window exceptions, etc as per above + movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=0, RING=0 + wsr a2, PS // update PS to enable window exceptions, etc as per above rsync // Okay, window exceptions can now happen (although we have to call @@ -1229,199 +847,88 @@ nmi_reentried: ////////////////// COMMON DISPATCH CODE BEGIN - rsr a14, SAR - s32i a14, a1, HESF_SAR -#if XCHAL_HAVE_LOOPS - #error - rsr a14, LCOUNT - s32i a14, a1, HESF_LCOUNT - rsr a14, LBEG - s32i a14, a1, HESF_LBEG - rsr a14, LEND - s32i a14, a1, HESF_LEND -#endif -#if XCHAL_HAVE_MAC16 - #error - rsr a14, ACCLO - s32i a14, a1, HESF_ACCLO - rsr a14, ACCHI - s32i a14, a1, HESF_ACCHI -#endif + rsr a14, SAR + s32i a14, a1, HESF_SAR //save NMI Count - movi a2, _chip_nmi_cnt - l32i a3, a2, 0 - addi a3, a3, 1 - s32i a3, a2, 0 - -#ifdef __XTENSA_CALL0_ABI__ -// movi a13, pwm_tim1_intr_handler - movi a13, wDev_ProcessFiq - callx0 a13 // call interrupt's C handler -#else - movi a13, NMI_Handler - callx4 a13 // call interrupt's C handler -#endif + movi a2, _chip_nmi_cnt + l32i a3, a2, 0 + addi a3, a3, 1 + s32i a3, a2, 0 + + call0 wDev_ProcessFiq // call interrupt's C handler //Restore NMI level - movi a2, _chip_nmi_cnt - l32i a3, a2, 0 - addi a3, a3, -1 - s32i a3, a2, 0 + movi a2, _chip_nmi_cnt + l32i a3, a2, 0 + addi a3, a3, -1 + s32i a3, a2, 0 - beqi a3, 1, nmi_reentry2 - movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE // get ptr to save area + beqi a3, 1, nmi_reentry2 + movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE // get ptr to save area j nmi_common2 nmi_reentry2: - movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2// get ptr to save area + movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2// get ptr to save area nmi_common2: + l32i a15, a1, HESF_SAR + wsr a15, SAR - // Restore everything, and return. - - // Three temp registers are required for this code to be optimal (no interlocks) in - // T2xxx microarchitectures with 7-stage pipe; otherwise only two - // registers would be needed. - // -#if XCHAL_HAVE_LOOPS - l32i a13, a1, HESF_LCOUNT - l32i a14, a1, HESF_LBEG - l32i a15, a1, HESF_LEND - wsr a13, LCOUNT - wsr a14, LBEG - wsr a15, LEND -#endif - -#if XCHAL_HAVE_MAC16 - l32i a13, a1, HESF_ACCLO - l32i a14, a1, HESF_ACCHI - wsr a13, ACCLO - wsr a14, ACCHI -#endif - l32i a15, a1, HESF_SAR - wsr a15, SAR - -////////////////// COMMON DISPATCH CODE END - -#if XCHAL_HAVE_XEA1 - // Here, a7 = address of interrupt management globals - l32i a4, a1, HESF_VPRI // restore previous vpri - rsil a3, XTOS_LOCKLEVEL // lockout - l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled - s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled - movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, UM=1, INTLEVEL=N - /* movi a2, 0x00020 + 0 // WOE=0, UM=1, INTLEVEL=N */ - and a3, a5, a4 // mask out selected interrupts - wsr a3, INTENABLE // disable all low-priority interrupts -#else // Load PS for interrupt exit, set EXCM: - movi a2, 0x00030 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0 - /* movi a2, 0x00030 + 0 // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0 */ -#endif - wsr a2, PS // update PS to disable window exceptions, etc as per above + movi a2, 0x00030 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0 + wsr a2, PS // update PS to disable window exceptions, etc as per above rsync // NOTE: here for XEA1, restore INTENABLE etc... -#ifdef __XTENSA_WINDOWED_ABI__ - // Restore window registers: - l32i a2, a1, HESF_WINDOWSTART - l32i a3, a1, HESF_WINDOWBASE - wsr a2, WINDOWSTART - wsr a3, WINDOWBASE - rsync - // Note: register window has rotated, ie. a0..a15 clobbered. - - // Reload initial stack pointer: - movi a1, _chip_nmi_stk + PRI_N_STACK_SIZE // - 16 - movi a6, XCHAL_NUM_AREGS - 8 // how many saved so far - addi a7, a1, -8*4 - - // Restore entire register file (!): - -1: - addi a14, a6, -8 - addi a15, a7, 8*4 - l32i a4, a15, HESF_AR(4) - l32i a5, a15, HESF_AR(5) - l32i a6, a15, HESF_AR(6) - l32i a7, a15, HESF_AR(7) - l32i a8, a15, HESF_AR(8) - l32i a9, a15, HESF_AR(9) - l32i a10,a15, HESF_AR(10) - l32i a11,a15, HESF_AR(11) - rotw 2 - bnez a6, 1b // loop until done - - l32i a4, a7, HESF_AR(12) - l32i a5, a7, HESF_AR(13) - l32i a6, a7, HESF_AR(14) - l32i a7, a7, HESF_AR(15) - rotw 2 - - // back to original a1 ... - -#else /* Call0 ABI: */ - - l32i a4, a1, HESF_AR(4) // restore general registers - l32i a5, a1, HESF_AR(5) - l32i a6, a1, HESF_AR(6) - l32i a7, a1, HESF_AR(7) - l32i a8, a1, HESF_AR(8) - l32i a9, a1, HESF_AR(9) - l32i a10, a1, HESF_AR(10) - l32i a11, a1, HESF_AR(11) - l32i a12, a1, HESF_AR(12) - l32i a13, a1, HESF_AR(13) - l32i a14, a1, HESF_AR(14) - l32i a15, a1, HESF_AR(15) - -#endif /* __XTENSA_WINDOWED_ABI__ */ + l32i a4, a1, HESF_AR(4) // restore general registers + l32i a5, a1, HESF_AR(5) + l32i a6, a1, HESF_AR(6) + l32i a7, a1, HESF_AR(7) + l32i a8, a1, HESF_AR(8) + l32i a9, a1, HESF_AR(9) + l32i a10, a1, HESF_AR(10) + l32i a11, a1, HESF_AR(11) + l32i a12, a1, HESF_AR(12) + l32i a13, a1, HESF_AR(13) + l32i a14, a1, HESF_AR(14) + l32i a15, a1, HESF_AR(15) // Restore exception state: - l32i a2, a1, HESF_EPC1 - l32i a3, a1, HESF_EXCCAUSE - wsr a2, EPC1 - wsr a3, EXCCAUSE -#if !XCHAL_HAVE_XEA1 - l32i a2, a1, HESF_EXCVADDR - wsr a2, EXCVADDR -#endif - l32i a3, a1, HESF_EXCSAVE1 - wsr a3, EXCSAVE1 - l32i a2, a1, HESF_EPC3 - wsr a2, EPC3 - l32i a3, a1, HESF_EPS3 - wsr a3, EPS3 - - l32i a0, a1, HESF_AR(0) + l32i a2, a1, HESF_EPC1 + l32i a3, a1, HESF_EXCCAUSE + wsr a2, EPC1 + wsr a3, EXCCAUSE + l32i a2, a1, HESF_EXCVADDR + wsr a2, EXCVADDR + + l32i a3, a1, HESF_EXCSAVE1 + wsr a3, EXCSAVE1 + l32i a2, a1, HESF_EPC3 + wsr a2, EPC3 + l32i a3, a1, HESF_EPS3 + wsr a3, EPS3 + + l32i a0, a1, HESF_AR(0) /* Re-Open NMI */ - rsr a3, SAR - movi a2, 0x3ff - slli a2,a2,20 - wsr a3, SAR + rsr a3, SAR + movi a2, 0x3ff + slli a2, a2, 20 + wsr a3, SAR rsync - movi a3, 1 - s32i a3,a2,0 + movi a3, 1 + s32i a3, a2, 0 - l32i a2, a1, HESF_AR(2) - l32i a3, a1, HESF_AR(3) - l32i a1, a1, HESF_AR(1) + l32i a2, a1, HESF_AR(2) + l32i a3, a1, HESF_AR(3) + l32i a1, a1, HESF_AR(1) nmi_rfi: rfi XCHAL_NMILEVEL -#if 0 - .align 4 -.L_xt_nmi_exit: - rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ - rfi XCHAL_NMILEVEL -#endif -#endif /* NMI */ - .global Cache_Read_Enable_New .global _xt_ext_panic .type _xt_ext_panic, @function .align 4 @@ -1429,59 +936,57 @@ nmi_rfi: _xt_ext_panic: /* * First close intrrupt, only use code, can't use data - * - * Todo: Close NMI */ - rsil a0, PS_INTLEVEL(5) - wsr a0, EXCSAVE_2 + rsil a0, PS_INTLEVEL(5) + wsr a0, EXCSAVE_2 /* * CPU must switch from kernel mode to user mode */ - movi a0, PS_INTLEVEL(5) | PS_UM - wsr a0, PS + movi a0, PS_INTLEVEL(5) | PS_UM + wsr a0, PS - mov a0, sp + mov a0, sp - movi sp, _chip_nmi_cnt - l32i sp, sp, 0 + movi sp, _chip_nmi_cnt + l32i sp, sp, 0 - beqz sp, _panic_add_nmi_stk + beqz sp, _panic_add_nmi_stk /* Allocate exception frame and save minimal context. */ - movi sp, _chip_interrupt_tmp + movi sp, _chip_interrupt_tmp j _panic_dump_reg _panic_add_nmi_stk: - movi sp, LoadStoreErrorHandlerStack + movi sp, LoadStoreErrorHandlerStack _panic_dump_reg: - addi sp, sp, -PANIC_STK_FRMSZ - s32i a0, sp, XT_STK_A1 - - rsr a0, EXCSAVE_2 /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_1 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - - s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ - s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ - s32i a14, sp, XT_STK_A14 - s32i a15, sp, XT_STK_A15 + addi sp, sp, -PANIC_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + + rsr a0, EXCSAVE_2 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + s32i a14, sp, XT_STK_A14 + s32i a15, sp, XT_STK_A15 call0 _xt_context_save /* Save exc cause and vaddr into exception frame */ - rsr a0, EXCCAUSE - s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */ - rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ - s32i a0, sp, XT_STK_A0 + s32i a0, sp, XT_STK_A0 call0 Cache_Read_Enable_New //Call panic handler - mov a2, sp - movi a3, 0 - movi a0, panicHandler + mov a2, sp + movi a3, 0 + movi a0, panicHandler callx0 a0 diff --git a/components/freertos/test/CMakeLists.txt b/components/freertos/test/CMakeLists.txt new file mode 100644 index 000000000..6cb8b29f4 --- /dev/null +++ b/components/freertos/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + INCLUDE_DIRS "." + REQUIRES unity test_utils freertos) diff --git a/components/partition_table/test/component.mk b/components/freertos/test/component.mk similarity index 100% rename from components/partition_table/test/component.mk rename to components/freertos/test/component.mk diff --git a/components/freertos/test/test_errno.c b/components/freertos/test/test_errno.c new file mode 100644 index 000000000..8e1671545 --- /dev/null +++ b/components/freertos/test/test_errno.c @@ -0,0 +1,57 @@ +/* mbedTLS AES performance test +*/ +#include +#include +#include +#include +#include "unity.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +void __set_errno(int i) +{ + errno = i; +} + +void __get_errno(int *i) +{ + *i = errno; +} + +static void errno_check_task(void *p) +{ + SemaphoreHandle_t wait_sem = p; + + for (volatile int i = 0; i < 10 * 1000 * 1000; i++) { + int j; + + __set_errno(i); + __get_errno(&j); + assert(i == j); + } + + xSemaphoreGive(wait_sem); + + vTaskDelete(NULL); +} + +TEST_CASE("thread local errno", "[reent]") +{ + SemaphoreHandle_t wait1_sem, wait2_sem; + + wait1_sem = xSemaphoreCreateBinary(); + wait2_sem = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(&errno_check_task, "errno1", 2048, wait1_sem, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&errno_check_task, "errno2", 2048, wait2_sem, 3, NULL, cpuid_1); + + xSemaphoreTake(wait1_sem, portMAX_DELAY); + xSemaphoreTake(wait2_sem, portMAX_DELAY); + + vQueueDelete(wait1_sem); + vQueueDelete(wait2_sem); +} + + diff --git a/components/freertos/test/test_freertos_task_modify_stack_depth.c b/components/freertos/test/test_freertos_task_modify_stack_depth.c new file mode 100644 index 000000000..e4955114c --- /dev/null +++ b/components/freertos/test/test_freertos_task_modify_stack_depth.c @@ -0,0 +1,113 @@ +/* FreeRTOS timer tests +*/ +//#define LOG_LOCAL_LEVEL 5 + +#include +#include "unity.h" +#include "esp_system.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +#define TASK_DEPTH_SIZE 8192 +#define TAG "test_modify_stack_depth" + +static SemaphoreHandle_t s_main_sem, s_sync_sem[3]; +static TaskHandle_t s_task_handle[3]; + +static void test_thread_1(void *p) +{ + for (int i = 0; i < 16; i++) { + ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128); + + vTaskModifyStackDepth(NULL, TASK_DEPTH_SIZE - i * 128); + } + + xSemaphoreGive(s_main_sem); + + vTaskDelete(NULL); +} + +static void test_thread_2(void *p) +{ + for (int i = 0; i < 10; i++) { + vTaskPrioritySet(NULL, 5); + + ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128); + + for (int j = 0; j < 3; j++) { + vTaskModifyStackDepth(s_task_handle[j], TASK_DEPTH_SIZE - i * 128); + xSemaphoreGive(s_sync_sem[j]); + } + + ESP_LOGD(TAG, "Modify successfully"); + + vTaskPrioritySet(NULL, 3); + } + + xSemaphoreGive(s_main_sem); + + vTaskDelete(NULL); +} + +static void test_thread_3(void *p) +{ + int count = 10; + int num = (int)p; + + while (count--) { + TEST_ASSERT(xSemaphoreTake(s_sync_sem[num], portMAX_DELAY) == pdTRUE); + } + + vTaskDelete(NULL); +} + +TEST_CASE("Test task modifies itself's stack depth", "[freertos]") +{ + TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary()); + + TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_1, "thread_1", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE); + + TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE); + + vQueueDelete(s_main_sem); + s_main_sem = NULL; + + vTaskDelay(5); +} + +TEST_CASE("Test task modifies other tasks' stack depth", "[freertos]") +{ + ESP_LOGD(TAG, "before heap is %u", esp_get_free_heap_size()); + + TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary()); + + for (int i = 0; i < 3; i++) { + TEST_ASSERT(s_sync_sem[i] = xSemaphoreCreateBinary()); + } + + vTaskSuspendAll(); + + TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_2, "thread_2", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE); + + TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_4", TASK_DEPTH_SIZE, (void *)0, 4, &s_task_handle[0], 0) == pdTRUE); + TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_5", TASK_DEPTH_SIZE, (void *)1, 5, &s_task_handle[1], 0) == pdTRUE); + TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_6", TASK_DEPTH_SIZE, (void *)2, 6, &s_task_handle[2], 0) == pdTRUE); + + xTaskResumeAll(); + + TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE); + + for (int i = 0; i < 3; i++) { + vQueueDelete(s_sync_sem[i]); + s_sync_sem[i] = NULL; + } + + vQueueDelete(s_main_sem); + s_main_sem = NULL; + + vTaskDelay(5); + + ESP_LOGD(TAG, "after heap is %u", esp_get_free_heap_size()); +} diff --git a/components/heap/CMakeLists.txt b/components/heap/CMakeLists.txt new file mode 100644 index 000000000..bb14864db --- /dev/null +++ b/components/heap/CMakeLists.txt @@ -0,0 +1,25 @@ +set(COMPONENT_SRCDIRS "src" "port/esp8266") + +set(COMPONENT_ADD_INCLUDEDIRS "include" "port/esp8266/include") + +set(COMPONENT_REQUIRES "log" "newlib") + +register_component() + +if(CONFIG_HEAP_TRACING) + set(WRAP_FUNCTIONS + calloc + malloc + free + realloc + heap_caps_malloc + heap_caps_free + heap_caps_realloc + heap_caps_malloc_default + heap_caps_realloc_default) + + foreach(wrap ${WRAP_FUNCTIONS}) + target_link_libraries(heap "-Wl,--wrap=${wrap}") + endforeach() + +endif() diff --git a/components/heap/Kconfig b/components/heap/Kconfig new file mode 100644 index 000000000..551cf58d4 --- /dev/null +++ b/components/heap/Kconfig @@ -0,0 +1,16 @@ + +menu "Heap memory" + + config HEAP_DISABLE_IRAM + bool "Disable IRAM as heap memory" + default n + help + Disable IRAM as heap memory, and heap memory only use DRAM. + + config HEAP_TRACING + bool "Enables heap tracing API" + default n + help + Enables heap tracing API. + +endmenu diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index e93a17b49..ac025cdbe 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -31,9 +31,12 @@ extern "C" { */ #define HEAP_ALIGN(ptr) (((size_t)ptr + (HEAP_ALIGN_SIZE - 1)) & ~(HEAP_ALIGN_SIZE - 1)) +#define MALLOC_CAP_EXEC (1 << 0) ///< Memory must be able to run executable code #define MALLOC_CAP_32BIT (1 << 1) ///< Memory must allow for aligned 32-bit data accesses #define MALLOC_CAP_8BIT (1 << 2) ///< Memory must allow for 8-bit data accesses #define MALLOC_CAP_DMA (1 << 3) ///< Memory must be able to accessed by DMA +#define MALLOC_CAP_INTERNAL (1 << 11) ///< Just for code compatibility +#define MALLOC_CAP_SPIRAM (1 << 10) ///< Just for code compatibility #define MEM_HEAD_SIZE sizeof(mem_blk_t) ///< Size of first type memory block #define MEM2_HEAD_SIZE sizeof(mem2_blk_t) ///< Size of second type memory block @@ -49,6 +52,7 @@ typedef struct mem_blk { /** * Second type memory block. */ +#ifdef CONFIG_HEAP_TRACING typedef struct mem_blk2 { struct mem_blk2 *prev; ///< Point to previous memory block struct mem_blk2 *next; ///< Point to next memory block @@ -56,6 +60,9 @@ typedef struct mem_blk2 { const char *file; ///< Which "file" allocate the memory block size_t line; ///< Which "line" allocate the memory block } mem2_blk_t; +#else +typedef mem_blk_t mem2_blk_t; +#endif /** * User region information. @@ -131,7 +138,7 @@ void *_heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t lin * * @param ptr Pointer to memory previously returned from heap_caps_(m/c/re/z)alloc(). Can be NULL. */ -#define heap_caps_free(p) _heap_caps_free(p, __ESP_FILE__, __LINE__) +#define heap_caps_free(ptr) _heap_caps_free(ptr, __ESP_FILE__, __LINE__) void _heap_caps_free(void *ptr, const char *file, size_t line); @@ -179,7 +186,6 @@ void *_heap_caps_realloc(void *mem, size_t newsize, uint32_t caps, const char *f * * In IDF, ``calloc(c, s)`` is equivalent to ``heap_caps_calloc(c, s, MALLOC_CAP_32BIT)``. * - * @param n Number of continuing chunks of memory to allocate * @param size Size, in bytes, of a chunk of memory to allocate * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type of memory to be returned * diff --git a/components/heap/include/esp_heap_trace.h b/components/heap/include/esp_heap_trace.h index a4655ccd3..ac1f0d658 100644 --- a/components/heap/include/esp_heap_trace.h +++ b/components/heap/include/esp_heap_trace.h @@ -14,20 +14,26 @@ #pragma once +#include "sdkconfig.h" #include "esp_err.h" #ifdef __cplusplus extern "C" { #endif +#ifdef CONFIG_HEAP_TRACING + typedef enum { HEAP_TRACE_NONE = 0, HEAP_TRACE_LEAKS, } heap_trace_mode_t; +/** + * @brief heap trace record information(not used) + */ typedef struct { - char buf[1]; + char buf[1]; /*!< record buffer */ } heap_trace_record_t; /** @@ -77,6 +83,8 @@ esp_err_t heap_trace_resume(void); */ void heap_trace_dump(void); +#endif /* CONFIG_HEAP_TRACING */ + #ifdef __cplusplus } #endif diff --git a/components/heap/port/esp8266/esp_heap_init.c b/components/heap/port/esp8266/esp_heap_init.c index 1afa0a913..8135911be 100644 --- a/components/heap/port/esp8266/esp_heap_init.c +++ b/components/heap/port/esp8266/esp_heap_init.c @@ -13,27 +13,48 @@ // limitations under the License. #include "esp_heap_caps.h" +#include "esp_attr.h" + +#define HEAP_REGION_IRAM_MIN 512 +#define HEAP_REGION_IRAM_MAX 0x00010000 heap_region_t g_heap_region[HEAP_REGIONS_MAX]; +size_t IRAM_ATTR heap_caps_get_dram_free_size(void) +{ +#ifndef CONFIG_HEAP_DISABLE_IRAM + extern size_t g_heap_region_num; + + return g_heap_region[g_heap_region_num - 1].free_bytes; +#else + return g_heap_region[0].free_bytes; +#endif +} + /** * @brief Initialize the capability-aware heap allocator. */ void heap_caps_init(void) { - extern char _heap_start; + extern char _bss_end; + size_t heap_region_num = 0; -#ifndef CONFIG_SOC_FULL_ICACHE - extern char _lit4_end; +#ifndef CONFIG_HEAP_DISABLE_IRAM + extern char _iram_end; + const size_t iram_size = 0x40100000 + CONFIG_SOC_IRAM_SIZE - ((size_t)&_iram_end); - g_heap_region[0].start_addr = (uint8_t *)&_lit4_end; - g_heap_region[0].total_size = ((size_t)(0x4010C000 - (uint32_t)&_lit4_end)); - g_heap_region[0].caps = MALLOC_CAP_32BIT; + if (iram_size > HEAP_REGION_IRAM_MIN && iram_size < HEAP_REGION_IRAM_MAX) { + g_heap_region[heap_region_num].start_addr = (uint8_t *)&_iram_end; + g_heap_region[heap_region_num].total_size = iram_size; + g_heap_region[heap_region_num].caps = MALLOC_CAP_32BIT | MALLOC_CAP_EXEC; + heap_region_num++; + } #endif - g_heap_region[HEAP_REGIONS_MAX - 1].start_addr = (uint8_t *)&_heap_start; - g_heap_region[HEAP_REGIONS_MAX - 1].total_size = ((size_t)(0x40000000 - (uint32_t)&_heap_start)); - g_heap_region[HEAP_REGIONS_MAX - 1].caps = MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_DMA; + g_heap_region[heap_region_num].start_addr = (uint8_t *)&_bss_end; + g_heap_region[heap_region_num].total_size = ((size_t)(0x40000000 - (uint32_t)&_bss_end)); + g_heap_region[heap_region_num].caps = MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_DMA; + heap_region_num++; - esp_heap_caps_init_region(g_heap_region, HEAP_REGIONS_MAX); + esp_heap_caps_init_region(g_heap_region, heap_region_num); } diff --git a/components/heap/port/esp8266/include/esp_heap_config.h b/components/heap/port/esp8266/include/esp_heap_config.h index a912b9510..c58828872 100644 --- a/components/heap/port/esp8266/include/esp_heap_config.h +++ b/components/heap/port/esp8266/include/esp_heap_config.h @@ -18,7 +18,7 @@ #define HEAP_ALIGN_SIZE 4 -#ifdef CONFIG_SOC_FULL_ICACHE +#ifdef CONFIG_HEAP_DISABLE_IRAM #define HEAP_REGIONS_MAX 1 #else #define HEAP_REGIONS_MAX 2 diff --git a/components/heap/port/esp8266/include/esp_heap_port.h b/components/heap/port/esp8266/include/esp_heap_port.h index d820a6c40..bfeb7c622 100644 --- a/components/heap/port/esp8266/include/esp_heap_port.h +++ b/components/heap/port/esp8266/include/esp_heap_port.h @@ -14,6 +14,12 @@ #pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + #define _heap_caps_lock(_num) \ { \ extern void vPortETSIntrLock(void); \ @@ -32,3 +38,13 @@ esp_task_wdt_reset(); \ } +/** + * @brief Get the total free size of DRAM region + * + * @return Amount of free bytes in DRAM region + */ +size_t heap_caps_get_dram_free_size(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/heap/port/esp8266/include/priv/esp_heap_caps_priv.h b/components/heap/port/esp8266/include/priv/esp_heap_caps_priv.h index 2c2916d9c..cc59076c8 100644 --- a/components/heap/port/esp8266/include/priv/esp_heap_caps_priv.h +++ b/components/heap/port/esp8266/include/priv/esp_heap_caps_priv.h @@ -14,14 +14,22 @@ #pragma once +#include "sdkconfig.h" #include #ifdef __cplusplus extern "C" { #endif +#define HEAP_MAX_SIZE (96 * 1024) + #define MEM_BLK_TAG 0x80000000 ///< Mark the memory block used + +#ifdef CONFIG_HEAP_TRACING #define MEM_BLK_TRACE 0x80000000 ///< Mark the memory block traced +#else +#define MEM_BLK_TRACE 0x00000000 ///< Mark the memory block traced +#endif #define _mem_blk_get_ptr(_mem_blk, _offset, _mask) \ ((mem_blk_t *)((((uint32_t *)(_mem_blk))[_offset]) & (~_mask))) @@ -47,12 +55,14 @@ static inline size_t mem_blk_head_size(bool trace) static inline void mem_blk_set_traced(mem2_blk_t *mem_blk, const char *file, size_t line) { +#ifdef CONFIG_HEAP_TRACING uint32_t *val = (uint32_t *)mem_blk + 1; *val |= MEM_BLK_TRACE; mem_blk->file = file; mem_blk->line = line | MEM_BLK_TRACE; +#endif } static inline void mem_blk_set_untraced(mem2_blk_t *mem_blk) @@ -103,9 +113,11 @@ static inline size_t blk_link_size(mem_blk_t *blk) static inline size_t get_blk_region(void *ptr) { size_t num; - extern heap_region_t g_heap_region[HEAP_REGIONS_MAX]; + extern size_t g_heap_region_num; + extern heap_region_t g_heap_region[]; + - for (num = 0; num < HEAP_REGIONS_MAX; num++) { + for (num = 0; num < g_heap_region_num; num++) { if ((uint8_t *)ptr > (uint8_t *)g_heap_region[num].start_addr && (uint8_t *)ptr < ((uint8_t *)g_heap_region[num].start_addr + g_heap_region[num].total_size)) { break; @@ -152,10 +164,12 @@ static inline size_t ptr_size(void *ptr) return size; } +#ifdef CONFIG_HEAP_TRACING static inline size_t mem2_blk_line(mem2_blk_t *mem2_blk) { return mem2_blk->line & ~MEM_BLK_TRACE; } +#endif #ifdef __cplusplus } diff --git a/components/heap/src/esp_heap_caps.c b/components/heap/src/esp_heap_caps.c index 64d7ddeed..0f49e9d63 100644 --- a/components/heap/src/esp_heap_caps.c +++ b/components/heap/src/esp_heap_caps.c @@ -22,12 +22,19 @@ #include "esp_heap_trace.h" #include "priv/esp_heap_caps_priv.h" +#include "esp_attr.h" + #define LOG_LOCAL_LEVEL ESP_LOG_NONE #include "esp_log.h" -static const char *TAG = "heap_caps"; -extern heap_region_t g_heap_region[HEAP_REGIONS_MAX]; +extern heap_region_t g_heap_region[]; + +static const char *TAG = "heap_init"; +size_t g_heap_region_num; +#ifdef CONFIG_HEAP_TRACING +int __g_heap_trace_mode = HEAP_TRACE_NONE; +#endif /** * @brief Initialize regions of memory to the collection of heaps at runtime. @@ -44,10 +51,6 @@ void esp_heap_caps_init_region(heap_region_t *region, size_t max_num) mem_end = (mem_blk_t *)((uint8_t *)mem_end - sizeof(void *)); mem_end = (mem_blk_t *)((uint8_t *)mem_end - MEM_HEAD_SIZE); - ESP_EARLY_LOGV(TAG, "heap %d start from %p to %p total %d bytes, mem_blk from %p to %p total", - num, region[num].start_addr, region[num].start_addr + region[num].total_size, - region[num].total_size, mem_start, mem_end); - mem_start->prev = NULL; mem_start->next = mem_end; @@ -57,6 +60,7 @@ void esp_heap_caps_init_region(heap_region_t *region, size_t max_num) g_heap_region[num].free_blk = mem_start; g_heap_region[num].min_free_bytes = g_heap_region[num].free_bytes = blk_link_size(mem_start); } + g_heap_region_num = max_num; } /** @@ -66,7 +70,7 @@ size_t heap_caps_get_free_size(uint32_t caps) { size_t bytes = 0; - for (int i = 0; i < HEAP_REGIONS_MAX; i++) + for (int i = 0; i < g_heap_region_num; i++) if (caps == (caps & g_heap_region[i].caps)) bytes += g_heap_region[i].free_bytes; @@ -80,7 +84,7 @@ size_t heap_caps_get_minimum_free_size(uint32_t caps) { size_t bytes = 0; - for (int i = 0; i < HEAP_REGIONS_MAX; i++) + for (int i = 0; i < g_heap_region_num; i++) if (caps == (caps & g_heap_region[i].caps)) bytes += g_heap_region[i].min_free_bytes; @@ -90,29 +94,38 @@ size_t heap_caps_get_minimum_free_size(uint32_t caps) /** * @brief Allocate a chunk of memory which has the given capabilities */ -void *_heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t line) +void IRAM_ATTR *_heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t line) { mem_blk_t *mem_blk, *next_mem_blk; void *ret_mem = NULL; uint32_t num; uint32_t mem_blk_size; + if (size > (HEAP_MAX_SIZE - sizeof(mem2_blk_t) * 2)) { + ESP_EARLY_LOGV(TAG, "size=%u is oveflow", size); + return NULL; + } + if (line == 0) { ESP_EARLY_LOGV(TAG, "caller func %p", file); } else { ESP_EARLY_LOGV(TAG, "caller file %s line %d", file, line); } - for (num = 0; num < HEAP_REGIONS_MAX; num++) { + for (num = 0; num < g_heap_region_num; num++) { bool trace; size_t head_size; - if ((g_heap_region[num].caps & caps) != caps) + if ((g_heap_region[num].caps & caps) != caps) { + ESP_EARLY_LOGV(TAG, "caps in %x, num %d region %x @ %p", caps, num, g_heap_region[num].caps, &g_heap_region[num]); continue; + } _heap_caps_lock(num); - trace = heap_trace_is_on(); +#ifdef CONFIG_HEAP_TRACING + trace = __g_heap_trace_mode == HEAP_TRACE_LEAKS; +#endif mem_blk_size = ptr2memblk_size(size, trace); @@ -209,7 +222,7 @@ void *_heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t lin /** * @brief Free memory previously allocated via heap_caps_(m/c/r/z)alloc(). */ -void _heap_caps_free(void *ptr, const char *file, size_t line) +void IRAM_ATTR _heap_caps_free(void *ptr, const char *file, size_t line) { int num; mem_blk_t *mem_blk; @@ -233,7 +246,7 @@ void _heap_caps_free(void *ptr, const char *file, size_t line) num = get_blk_region(ptr); - if (num >= HEAP_REGIONS_MAX) { + if (num >= g_heap_region_num) { ESP_EARLY_LOGE(TAG, "free(ptr_region=NULL)"); return; } @@ -289,9 +302,16 @@ void _heap_caps_free(void *ptr, const char *file, size_t line) */ void *_heap_caps_calloc(size_t count, size_t size, uint32_t caps, const char *file, size_t line) { - void *p = _heap_caps_malloc(count * size, caps, file, line); + size_t size_bytes; + + if (__builtin_mul_overflow(count, size, &size_bytes)) { + ESP_EARLY_LOGV(TAG, "count=%u size=%u is oveflow", count, size); + return NULL; + } + + void *p = _heap_caps_malloc(size_bytes, caps, file, line); if (p) - memset(p, 0, count * size); + memset(p, 0, size_bytes); return p; } diff --git a/components/heap/src/esp_heap_trace.c b/components/heap/src/esp_heap_trace.c index 54de9289b..d6dedae88 100644 --- a/components/heap/src/esp_heap_trace.c +++ b/components/heap/src/esp_heap_trace.c @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "sdkconfig.h" + +#ifdef CONFIG_HEAP_TRACING + #include #include "esp_heap_caps.h" @@ -19,12 +23,12 @@ #include "esp_heap_trace.h" #include "priv/esp_heap_caps_priv.h" -#include "esp_log.h" - //#define CONFIG_TRACE_ALL //#define CONFIG_TRACE_MEM_LINK 1 //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#include "esp_log.h" + #ifdef CONFIG_TRACE_ALL #define HEAP_INFO_STATE " is %s" #define HEAP_INFO_STATE_PARAM(_p) ,mem_blk_is_used(_p)?"used":"freed" @@ -42,8 +46,10 @@ #endif static const char *TAG = "heap_trace"; -static int s_heap_trace_mode = HEAP_TRACE_NONE; -extern heap_region_t g_heap_region[HEAP_REGIONS_MAX]; + +extern size_t g_heap_region_num; +extern heap_region_t g_heap_region[]; +extern int __g_heap_trace_mode; /** * @brief Empty function just for passing compiling some place. @@ -58,7 +64,7 @@ esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t */ int heap_trace_is_on(void) { - return s_heap_trace_mode == HEAP_TRACE_LEAKS; + return __g_heap_trace_mode == HEAP_TRACE_LEAKS; } /** @@ -66,7 +72,7 @@ int heap_trace_is_on(void) */ esp_err_t heap_trace_start(heap_trace_mode_t mode) { - s_heap_trace_mode = mode; + __g_heap_trace_mode = mode; return ESP_OK; } @@ -76,7 +82,7 @@ esp_err_t heap_trace_start(heap_trace_mode_t mode) */ esp_err_t heap_trace_stop(void) { - s_heap_trace_mode = HEAP_TRACE_NONE; + __g_heap_trace_mode = HEAP_TRACE_NONE; return ESP_OK; } @@ -86,7 +92,7 @@ esp_err_t heap_trace_stop(void) */ esp_err_t heap_trace_resume(void) { - s_heap_trace_mode = HEAP_TRACE_LEAKS; + __g_heap_trace_mode = HEAP_TRACE_LEAKS; return ESP_OK; } @@ -99,7 +105,7 @@ void heap_trace_dump(void) uint8_t num; mem_blk_t *mem_start, *mem_end, *p; - for (num = 0; num < HEAP_REGIONS_MAX; num++) { + for (num = 0; num < g_heap_region_num; num++) { mem_start = (mem_blk_t *)HEAP_ALIGN(g_heap_region[num].start_addr); mem_end = (mem_blk_t *)(HEAP_ALIGN(g_heap_region[num].start_addr + g_heap_region[num].total_size)); if ((uint8_t *)mem_end != g_heap_region[num].start_addr + g_heap_region[num].total_size) @@ -108,10 +114,10 @@ void heap_trace_dump(void) _heap_caps_lock(num); - ESP_LOGI(TAG, "\r\n\r\n"); - ESP_LOGD(TAG, "start %p end %p", mem_start, mem_end); - ESP_LOGD(TAG, "free blk %p", g_heap_region[num].free_blk); - ESP_LOGD(TAG, "size %d mini size %d", g_heap_region[num].free_bytes, g_heap_region[num].min_free_bytes); + ESP_EARLY_LOGI(TAG, "\r\n\r\n"); + ESP_EARLY_LOGD(TAG, "start %p end %p", mem_start, mem_end); + ESP_EARLY_LOGD(TAG, "free blk %p", g_heap_region[num].free_blk); + ESP_EARLY_LOGD(TAG, "size %d mini size %d", g_heap_region[num].free_bytes, g_heap_region[num].min_free_bytes); p = mem_start; while (p != mem_end) { @@ -120,7 +126,7 @@ void heap_trace_dump(void) size_t line = mem2_blk_line(mem2_blk); if (!line) { - ESP_LOGI(TAG, HEAP_INFO " caller func %p", HEAP_INFO_PARAM(p), mem2_blk->file); + ESP_EARLY_LOGI(TAG, HEAP_INFO " caller func %p", HEAP_INFO_PARAM(p), mem2_blk->file); } else { const char *file = rindex(mem2_blk->file, '/'); if (file) @@ -128,7 +134,7 @@ void heap_trace_dump(void) else file = mem2_blk->file; - ESP_LOGI(TAG, HEAP_INFO " caller file %s line %d", HEAP_INFO_PARAM(p), file, line); + ESP_EARLY_LOGI(TAG, HEAP_INFO " caller file %s line %d", HEAP_INFO_PARAM(p), file, line); } } #ifdef CONFIG_TRACE_ALL @@ -144,3 +150,5 @@ void heap_trace_dump(void) _heap_caps_unlock(num); } } + +#endif /* CONFIG_HEAP_TRACING */ diff --git a/components/heap/test/CMakeLists.txt b/components/heap/test/CMakeLists.txt new file mode 100644 index 000000000..0c37e41b3 --- /dev/null +++ b/components/heap/test/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +set(COMPONENT_REQUIRES unity heap esp8266) + +register_component() \ No newline at end of file diff --git a/components/heap/test/component.mk b/components/heap/test/component.mk new file mode 100644 index 000000000..5dd172bdb --- /dev/null +++ b/components/heap/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/heap/test/test_heap_effectivity.c b/components/heap/test/test_heap_effectivity.c new file mode 100644 index 000000000..51e596d13 --- /dev/null +++ b/components/heap/test/test_heap_effectivity.c @@ -0,0 +1,119 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include + +#include "esp_attr.h" +#include "esp8266/eagle_soc.h" + +#include "esp_heap_caps.h" + +#define MIXED_HEAP_LIST_NOTES 64 + +#define TIME_US_REG 0x3ff20c00 + +static inline uint32_t get_us(void) +{ + return REG_READ(TIME_US_REG); +} + +static void* IRAM_ATTR test_alloc_time_in_us(size_t n, uint32_t *time) +{ + void *p; + uint32_t t; + + t = get_us(); + + p = heap_caps_malloc(n, MALLOC_CAP_8BIT); + if (!p) + return NULL; + + *time += get_us() - t; + + return p; +} + +static void IRAM_ATTR test_free_time_in_us(void *p, uint32_t *time) +{ + uint32_t t; + + t = get_us(); + + heap_caps_free(p); + + *time += get_us() - t; +} + +static void IRAM_ATTR test_heap_effectivity(uint32_t *time, uint32_t *count) +{ + int cnt = 0; + uint32_t alloc_us = 0, free_us = 0; + + for (; cnt < INT32_MAX; cnt++) { + void *p = test_alloc_time_in_us(cnt + sizeof(void *) + 1, &alloc_us); + if (!p) + break; + test_free_time_in_us(p, &free_us); + } + + time[0] = alloc_us; + time[1] = free_us; + count[0] = cnt; +} + +static void test_heap_init(uint32_t *pbuf) +{ + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i++) { + pbuf[i] = (uint32_t)heap_caps_malloc(1, MALLOC_CAP_8BIT); + assert(pbuf[i]); + } + + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i += 2) { + heap_caps_free((void *)pbuf[i]); + pbuf[i] = 0; + } +} + +static void test_heap_deinit(uint32_t *pbuf) +{ + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i++) { + if (pbuf[i]) { + heap_caps_free((void *)pbuf[i]); + pbuf[i] = 0; + } + } +} + +TEST_CASE("Test Heap alloc/free effectivity", "[Heap]") +{ + uint32_t time_in_us[2], count; + uint32_t buf[MIXED_HEAP_LIST_NOTES]; + + test_heap_init(buf); + + test_heap_effectivity(time_in_us, &count); + + printf("Each alloc costs time %u us, each free costs time %u us\n", time_in_us[0] / count, time_in_us[1] / count); + + test_heap_deinit(buf); +} + +// Enable Heap Trace : Each alloc costs time 27 us, each free costs time 5 us +// Disable Heap Trace : Each alloc costs time 18 us, each free costs time 4 us diff --git a/components/http_parser/CMakeLists.txt b/components/http_parser/CMakeLists.txt new file mode 100644 index 000000000..4ee874218 --- /dev/null +++ b/components/http_parser/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_SRCDIRS "src") + +register_component() + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough) diff --git a/components/http_parser/component.mk b/components/http_parser/component.mk new file mode 100644 index 000000000..a59dff7c3 --- /dev/null +++ b/components/http_parser/component.mk @@ -0,0 +1,6 @@ + +COMPONENT_SRCDIRS := src +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := + +src/http_parser.o: CFLAGS += -Wno-implicit-fallthrough diff --git a/components/http_parser/include/http_parser.h b/components/http_parser/include/http_parser.h new file mode 100644 index 000000000..ea2639482 --- /dev/null +++ b/components/http_parser/include/http_parser.h @@ -0,0 +1,362 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef http_parser_h +#define http_parser_h +#ifdef __cplusplus +extern "C" { +#endif + +/* Also update SONAME in the Makefile whenever you change these. */ +#define HTTP_PARSER_VERSION_MAJOR 2 +#define HTTP_PARSER_VERSION_MINOR 7 +#define HTTP_PARSER_VERSION_PATCH 1 + +#include +#if defined(_WIN32) && !defined(__MINGW32__) && \ + (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) +#include +#include +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run + * faster + */ +#ifndef HTTP_PARSER_STRICT +# define HTTP_PARSER_STRICT 1 +#endif + +/* Maximium header size allowed. If the macro is not defined + * before including this header then the default is used. To + * change the maximum header size, define the macro in the build + * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove + * the effective limit on the size of the header, define the macro + * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) + */ +#ifndef HTTP_MAX_HEADER_SIZE +# define HTTP_MAX_HEADER_SIZE (80*1024) +#endif + +typedef struct http_parser http_parser; +typedef struct http_parser_settings http_parser_settings; + + +/* Callbacks should return non-zero to indicate an error. The parser will + * then halt execution. + * + * The one exception is on_headers_complete. In a HTTP_RESPONSE parser + * returning '1' from on_headers_complete will tell the parser that it + * should not expect a body. This is used when receiving a response to a + * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: + * chunked' headers that indicate the presence of a body. + * + * Returning `2` from on_headers_complete will tell parser that it should not + * expect neither a body nor any futher responses on this connection. This is + * useful for handling responses to a CONNECT request which may not contain + * `Upgrade` or `Connection: upgrade` headers. + * + * http_data_cb does not return data chunks. It will be called arbitrarily + * many times for each string. E.G. you might get 10 callbacks for "on_url" + * each providing just a few characters more data. + */ +typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); +typedef int (*http_cb) (http_parser*); + + +/* Request Methods */ +#define HTTP_METHOD_MAP(XX) \ + XX(0, DELETE, DELETE) \ + XX(1, GET, GET) \ + XX(2, HEAD, HEAD) \ + XX(3, POST, POST) \ + XX(4, PUT, PUT) \ + /* pathological */ \ + XX(5, CONNECT, CONNECT) \ + XX(6, OPTIONS, OPTIONS) \ + XX(7, TRACE, TRACE) \ + /* WebDAV */ \ + XX(8, COPY, COPY) \ + XX(9, LOCK, LOCK) \ + XX(10, MKCOL, MKCOL) \ + XX(11, MOVE, MOVE) \ + XX(12, PROPFIND, PROPFIND) \ + XX(13, PROPPATCH, PROPPATCH) \ + XX(14, SEARCH, SEARCH) \ + XX(15, UNLOCK, UNLOCK) \ + XX(16, BIND, BIND) \ + XX(17, REBIND, REBIND) \ + XX(18, UNBIND, UNBIND) \ + XX(19, ACL, ACL) \ + /* subversion */ \ + XX(20, REPORT, REPORT) \ + XX(21, MKACTIVITY, MKACTIVITY) \ + XX(22, CHECKOUT, CHECKOUT) \ + XX(23, MERGE, MERGE) \ + /* upnp */ \ + XX(24, MSEARCH, M-SEARCH) \ + XX(25, NOTIFY, NOTIFY) \ + XX(26, SUBSCRIBE, SUBSCRIBE) \ + XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + /* RFC-5789 */ \ + XX(28, PATCH, PATCH) \ + XX(29, PURGE, PURGE) \ + /* CalDAV */ \ + XX(30, MKCALENDAR, MKCALENDAR) \ + /* RFC-2068, section 19.6.1.2 */ \ + XX(31, LINK, LINK) \ + XX(32, UNLINK, UNLINK) \ + +enum http_method + { +#define XX(num, name, string) HTTP_##name = num, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; + + +/* Flag values for http_parser.flags field */ +enum flags + { F_CHUNKED = 1 << 0 + , F_CONNECTION_KEEP_ALIVE = 1 << 1 + , F_CONNECTION_CLOSE = 1 << 2 + , F_CONNECTION_UPGRADE = 1 << 3 + , F_TRAILING = 1 << 4 + , F_UPGRADE = 1 << 5 + , F_SKIPBODY = 1 << 6 + , F_CONTENTLENGTH = 1 << 7 + }; + + +/* Map for errno-related constants + * + * The provided argument should be a macro that takes 2 arguments. + */ +#define HTTP_ERRNO_MAP(XX) \ + /* No error */ \ + XX(OK, "success") \ + \ + /* Callback-related errors */ \ + XX(CB_message_begin, "the on_message_begin callback failed") \ + XX(CB_url, "the on_url callback failed") \ + XX(CB_header_field, "the on_header_field callback failed") \ + XX(CB_header_value, "the on_header_value callback failed") \ + XX(CB_headers_complete, "the on_headers_complete callback failed") \ + XX(CB_body, "the on_body callback failed") \ + XX(CB_message_complete, "the on_message_complete callback failed") \ + XX(CB_status, "the on_status callback failed") \ + XX(CB_chunk_header, "the on_chunk_header callback failed") \ + XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ + \ + /* Parsing-related errors */ \ + XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ + XX(HEADER_OVERFLOW, \ + "too many header bytes seen; overflow detected") \ + XX(CLOSED_CONNECTION, \ + "data received after completed connection: close message") \ + XX(INVALID_VERSION, "invalid HTTP version") \ + XX(INVALID_STATUS, "invalid HTTP status code") \ + XX(INVALID_METHOD, "invalid HTTP method") \ + XX(INVALID_URL, "invalid URL") \ + XX(INVALID_HOST, "invalid host") \ + XX(INVALID_PORT, "invalid port") \ + XX(INVALID_PATH, "invalid path") \ + XX(INVALID_QUERY_STRING, "invalid query string") \ + XX(INVALID_FRAGMENT, "invalid fragment") \ + XX(LF_EXPECTED, "LF character expected") \ + XX(INVALID_HEADER_TOKEN, "invalid character in header") \ + XX(INVALID_CONTENT_LENGTH, \ + "invalid character in content-length header") \ + XX(UNEXPECTED_CONTENT_LENGTH, \ + "unexpected content-length header") \ + XX(INVALID_CHUNK_SIZE, \ + "invalid character in chunk size header") \ + XX(INVALID_CONSTANT, "invalid constant string") \ + XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ + XX(STRICT, "strict mode assertion failed") \ + XX(PAUSED, "parser is paused") \ + XX(UNKNOWN, "an unknown error occurred") + + +/* Define HPE_* values for each errno value above */ +#define HTTP_ERRNO_GEN(n, s) HPE_##n, +enum http_errno { + HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) +}; +#undef HTTP_ERRNO_GEN + + +/* Get an http_errno value from an http_parser */ +#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) + + +struct http_parser { + /** PRIVATE **/ + unsigned int type : 2; /* enum http_parser_type */ + unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ + unsigned int state : 7; /* enum state from http_parser.c */ + unsigned int header_state : 7; /* enum header_state from http_parser.c */ + unsigned int index : 7; /* index into current matcher */ + unsigned int lenient_http_headers : 1; + + uint32_t nread; /* # bytes read in various scenarios */ + uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ + + /** READ-ONLY **/ + unsigned short http_major; + unsigned short http_minor; + unsigned int status_code : 16; /* responses only */ + unsigned int method : 8; /* requests only */ + unsigned int http_errno : 7; + + /* 1 = Upgrade header was present and the parser has exited because of that. + * 0 = No upgrade header present. + * Should be checked when http_parser_execute() returns in addition to + * error checking. + */ + unsigned int upgrade : 1; + + /** PUBLIC **/ + void *data; /* A pointer to get hook to the "connection" or "socket" object */ +}; + + +struct http_parser_settings { + http_cb on_message_begin; + http_data_cb on_url; + http_data_cb on_status; + http_data_cb on_header_field; + http_data_cb on_header_value; + http_cb on_headers_complete; + http_data_cb on_body; + http_cb on_message_complete; + /* When on_chunk_header is called, the current chunk length is stored + * in parser->content_length. + */ + http_cb on_chunk_header; + http_cb on_chunk_complete; +}; + + +enum http_parser_url_fields + { UF_SCHEMA = 0 + , UF_HOST = 1 + , UF_PORT = 2 + , UF_PATH = 3 + , UF_QUERY = 4 + , UF_FRAGMENT = 5 + , UF_USERINFO = 6 + , UF_MAX = 7 + }; + + +/* Result structure for http_parser_parse_url(). + * + * Callers should index into field_data[] with UF_* values iff field_set + * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and + * because we probably have padding left over), we convert any port to + * a uint16_t. + */ +struct http_parser_url { + uint16_t field_set; /* Bitmask of (1 << UF_*) values */ + uint16_t port; /* Converted UF_PORT string */ + + struct { + uint16_t off; /* Offset into buffer in which field starts */ + uint16_t len; /* Length of run in buffer */ + } field_data[UF_MAX]; +}; + + +/* Returns the library version. Bits 16-23 contain the major version number, + * bits 8-15 the minor version number and bits 0-7 the patch level. + * Usage example: + * + * unsigned long version = http_parser_version(); + * unsigned major = (version >> 16) & 255; + * unsigned minor = (version >> 8) & 255; + * unsigned patch = version & 255; + * printf("http_parser v%u.%u.%u\n", major, minor, patch); + */ +unsigned long http_parser_version(void); + +void http_parser_init(http_parser *parser, enum http_parser_type type); + + +/* Initialize http_parser_settings members to 0 + */ +void http_parser_settings_init(http_parser_settings *settings); + + +/* Executes the parser. Returns number of parsed bytes. Sets + * `parser->http_errno` on error. */ +size_t http_parser_execute(http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len); + + +/* If http_should_keep_alive() in the on_headers_complete or + * on_message_complete callback returns 0, then this should be + * the last message on the connection. + * If you are the server, respond with the "Connection: close" header. + * If you are the client, close the connection. + */ +int http_should_keep_alive(const http_parser *parser); + +/* Returns a string version of the HTTP method. */ +const char *http_method_str(enum http_method m); + +/* Return a string name of the given error */ +const char *http_errno_name(enum http_errno err); + +/* Return a string description of the given error */ +const char *http_errno_description(enum http_errno err); + +/* Initialize all http_parser_url members to 0 */ +void http_parser_url_init(struct http_parser_url *u); + +/* Parse a URL; return nonzero on failure */ +int http_parser_parse_url(const char *buf, size_t buflen, + int is_connect, + struct http_parser_url *u); + +/* Pause or un-pause the parser; a nonzero value pauses */ +void http_parser_pause(http_parser *parser, int paused); + +/* Checks if this is the final chunk of the body. */ +int http_body_is_final(const http_parser *parser); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/http_parser/src/http_parser.c b/components/http_parser/src/http_parser.c new file mode 100644 index 000000000..895bf0c73 --- /dev/null +++ b/components/http_parser/src/http_parser.c @@ -0,0 +1,2470 @@ +/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev + * + * Additional changes are licensed under the same terms as NGINX and + * copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "http_parser.h" +#include +#include +#include +#include +#include +#include + +#ifndef ULLONG_MAX +# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#ifndef BIT_AT +# define BIT_AT(a, i) \ + (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ + (1 << ((unsigned int) (i) & 7)))) +#endif + +#ifndef ELEM_AT +# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) +#endif + +#define SET_ERRNO(e) \ +do { \ + parser->http_errno = (e); \ +} while(0) + +#define CURRENT_STATE() p_state +#define UPDATE_STATE(V) p_state = (enum state) (V); +#define RETURN(V) \ +do { \ + parser->state = CURRENT_STATE(); \ + return (V); \ +} while (0); +#define REEXECUTE() \ + goto reexecute; \ + + +#ifdef __GNUC__ +# define LIKELY(X) __builtin_expect(!!(X), 1) +# define UNLIKELY(X) __builtin_expect(!!(X), 0) +#else +# define LIKELY(X) (X) +# define UNLIKELY(X) (X) +#endif + + +/* Run the notify callback FOR, returning ER if it fails */ +#define CALLBACK_NOTIFY_(FOR, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ +} while (0) + +/* Run the notify callback FOR and consume the current byte */ +#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) + +/* Run the notify callback FOR and don't consume the current byte */ +#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) + +/* Run data callback FOR with LEN bytes, returning ER if it fails */ +#define CALLBACK_DATA_(FOR, LEN, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (FOR##_mark) { \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != \ + settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ + FOR##_mark = NULL; \ + } \ +} while (0) + +/* Run the data callback FOR and consume the current byte */ +#define CALLBACK_DATA(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) + +/* Run the data callback FOR and don't consume the current byte */ +#define CALLBACK_DATA_NOADVANCE(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) + +/* Set the mark FOR; non-destructive if mark is already set */ +#define MARK(FOR) \ +do { \ + if (!FOR##_mark) { \ + FOR##_mark = p; \ + } \ +} while (0) + +/* Don't allow the total size of the HTTP headers (including the status + * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * embedders against denial-of-service attacks where the attacker feeds + * us a never-ending header that the embedder keeps buffering. + * + * This check is arguably the responsibility of embedders but we're doing + * it on the embedder's behalf because most won't bother and this way we + * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * than any reasonable request or response so this should never affect + * day-to-day operation. + */ +#define COUNT_HEADER_SIZE(V) \ +do { \ + parser->nread += (V); \ + if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ + SET_ERRNO(HPE_HEADER_OVERFLOW); \ + goto error; \ + } \ +} while (0) + + +#define PROXY_CONNECTION "proxy-connection" +#define CONNECTION "connection" +#define CONTENT_LENGTH "content-length" +#define TRANSFER_ENCODING "transfer-encoding" +#define UPGRADE "upgrade" +#define CHUNKED "chunked" +#define KEEP_ALIVE "keep-alive" +#define CLOSE "close" + + +static const char *method_strings[] = + { +#define XX(num, name, string) #string, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +static const char tokens[256] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + 0, '!', 0, '#', '$', '%', '&', '\'', +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 0, 0, '*', '+', 0, '-', '.', 0, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + '0', '1', '2', '3', '4', '5', '6', '7', +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + '8', '9', 0, 0, 0, 0, 0, 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 'x', 'y', 'z', 0, 0, 0, '^', '_', +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 'x', 'y', 'z', 0, '|', 0, '~', 0 }; + + +static const int8_t unhex[256] = + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + }; + + +#if HTTP_PARSER_STRICT +# define T(v) 0 +#else +# define T(v) v +#endif + + +static const uint8_t normal_url_char[32] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; + +#undef T + +enum state + { s_dead = 1 /* important that this is > 0 */ + + , s_start_req_or_res + , s_res_or_resp_H + , s_start_res + , s_res_H + , s_res_HT + , s_res_HTT + , s_res_HTTP + , s_res_first_http_major + , s_res_http_major + , s_res_first_http_minor + , s_res_http_minor + , s_res_first_status_code + , s_res_status_code + , s_res_status_start + , s_res_status + , s_res_line_almost_done + + , s_start_req + + , s_req_method + , s_req_spaces_before_url + , s_req_schema + , s_req_schema_slash + , s_req_schema_slash_slash + , s_req_server_start + , s_req_server + , s_req_server_with_at + , s_req_path + , s_req_query_string_start + , s_req_query_string + , s_req_fragment_start + , s_req_fragment + , s_req_http_start + , s_req_http_H + , s_req_http_HT + , s_req_http_HTT + , s_req_http_HTTP + , s_req_first_http_major + , s_req_http_major + , s_req_first_http_minor + , s_req_http_minor + , s_req_line_almost_done + + , s_header_field_start + , s_header_field + , s_header_value_discard_ws + , s_header_value_discard_ws_almost_done + , s_header_value_discard_lws + , s_header_value_start + , s_header_value + , s_header_value_lws + + , s_header_almost_done + + , s_chunk_size_start + , s_chunk_size + , s_chunk_parameters + , s_chunk_size_almost_done + + , s_headers_almost_done + , s_headers_done + + /* Important: 's_headers_done' must be the last 'header' state. All + * states beyond this must be 'body' states. It is used for overflow + * checking. See the PARSING_HEADER() macro. + */ + + , s_chunk_data + , s_chunk_data_almost_done + , s_chunk_data_done + + , s_body_identity + , s_body_identity_eof + + , s_message_done + }; + + +#define PARSING_HEADER(state) (state <= s_headers_done) + + +enum header_states + { h_general = 0 + , h_C + , h_CO + , h_CON + + , h_matching_connection + , h_matching_proxy_connection + , h_matching_content_length + , h_matching_transfer_encoding + , h_matching_upgrade + + , h_connection + , h_content_length + , h_transfer_encoding + , h_upgrade + + , h_matching_transfer_encoding_chunked + , h_matching_connection_token_start + , h_matching_connection_keep_alive + , h_matching_connection_close + , h_matching_connection_upgrade + , h_matching_connection_token + + , h_transfer_encoding_chunked + , h_connection_keep_alive + , h_connection_close + , h_connection_upgrade + }; + +enum http_host_state + { + s_http_host_dead = 1 + , s_http_userinfo_start + , s_http_userinfo + , s_http_host_start + , s_http_host_v6_start + , s_http_host + , s_http_host_v6 + , s_http_host_v6_end + , s_http_host_v6_zone_start + , s_http_host_v6_zone + , s_http_host_port_start + , s_http_host_port +}; + +/* Macros for character classes; depends on strict-mode */ +#define CR '\r' +#define LF '\n' +#define LOWER(c) (unsigned char)(c | 0x20) +#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') +#define IS_NUM(c) ((c) >= '0' && (c) <= '9') +#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) +#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) +#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ + (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ + (c) == ')') +#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ + (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ + (c) == '$' || (c) == ',') + +#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) + +#if HTTP_PARSER_STRICT +#define TOKEN(c) (tokens[(unsigned char)c]) +#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) +#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') +#else +#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) +#define IS_URL_CHAR(c) \ + (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) +#define IS_HOST_CHAR(c) \ + (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') +#endif + +/** + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + **/ +#define IS_HEADER_CHAR(ch) \ + (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) + +#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) + + +#if HTTP_PARSER_STRICT +# define STRICT_CHECK(cond) \ +do { \ + if (cond) { \ + SET_ERRNO(HPE_STRICT); \ + goto error; \ + } \ +} while (0) +# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) +#else +# define STRICT_CHECK(cond) +# define NEW_MESSAGE() start_state +#endif + + +/* Map errno values to strings for human-readable output */ +#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, +static struct { + const char *name; + const char *description; +} http_strerror_tab[] = { + HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) +}; +#undef HTTP_STRERROR_GEN + +int http_message_needs_eof(const http_parser *parser); + +/* Our URL parser. + * + * This is designed to be shared by http_parser_execute() for URL validation, + * hence it has a state transition + byte-for-byte interface. In addition, it + * is meant to be embedded in http_parser_parse_url(), which does the dirty + * work of turning state transitions URL components for its API. + * + * This function should only be invoked with non-space characters. It is + * assumed that the caller cares about (and can detect) the transition between + * URL and non-URL states by looking for these. + */ +static enum state +parse_url_char(enum state s, const char ch) +{ + if (ch == ' ' || ch == '\r' || ch == '\n') { + return s_dead; + } + +#if HTTP_PARSER_STRICT + if (ch == '\t' || ch == '\f') { + return s_dead; + } +#endif + + switch (s) { + case s_req_spaces_before_url: + /* Proxied requests are followed by scheme of an absolute URI (alpha). + * All methods except CONNECT are followed by '/' or '*'. + */ + + if (ch == '/' || ch == '*') { + return s_req_path; + } + + if (IS_ALPHA(ch)) { + return s_req_schema; + } + + break; + + case s_req_schema: + if (IS_ALPHA(ch)) { + return s; + } + + if (ch == ':') { + return s_req_schema_slash; + } + + break; + + case s_req_schema_slash: + if (ch == '/') { + return s_req_schema_slash_slash; + } + + break; + + case s_req_schema_slash_slash: + if (ch == '/') { + return s_req_server_start; + } + + break; + + case s_req_server_with_at: + if (ch == '@') { + return s_dead; + } + + /* FALLTHROUGH */ + case s_req_server_start: + case s_req_server: + if (ch == '/') { + return s_req_path; + } + + if (ch == '?') { + return s_req_query_string_start; + } + + if (ch == '@') { + return s_req_server_with_at; + } + + if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { + return s_req_server; + } + + break; + + case s_req_path: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + return s_req_query_string_start; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_query_string_start: + case s_req_query_string: + if (IS_URL_CHAR(ch)) { + return s_req_query_string; + } + + switch (ch) { + case '?': + /* allow extra '?' in query string */ + return s_req_query_string; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_fragment_start: + if (IS_URL_CHAR(ch)) { + return s_req_fragment; + } + + switch (ch) { + case '?': + return s_req_fragment; + + case '#': + return s; + } + + break; + + case s_req_fragment: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + case '#': + return s; + } + + break; + + default: + break; + } + + /* We should never fall out of the switch above unless there's an error */ + return s_dead; +} + +size_t http_parser_execute (http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len) +{ + char c, ch; + int8_t unhex_val; + const char *p = data; + const char *header_field_mark = 0; + const char *header_value_mark = 0; + const char *url_mark = 0; + const char *body_mark = 0; + const char *status_mark = 0; + enum state p_state = (enum state) parser->state; + const unsigned int lenient = parser->lenient_http_headers; + + /* We're in an error state. Don't bother doing anything. */ + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + return 0; + } + + if (len == 0) { + switch (CURRENT_STATE()) { + case s_body_identity_eof: + /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if + * we got paused. + */ + CALLBACK_NOTIFY_NOADVANCE(message_complete); + return 0; + + case s_dead: + case s_start_req_or_res: + case s_start_res: + case s_start_req: + return 0; + + default: + SET_ERRNO(HPE_INVALID_EOF_STATE); + return 1; + } + } + + + if (CURRENT_STATE() == s_header_field) + header_field_mark = data; + if (CURRENT_STATE() == s_header_value) + header_value_mark = data; + switch (CURRENT_STATE()) { + case s_req_path: + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_server: + case s_req_server_with_at: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + url_mark = data; + break; + case s_res_status: + status_mark = data; + break; + default: + break; + } + + for (p=data; p != data + len; p++) { + ch = *p; + + if (PARSING_HEADER(CURRENT_STATE())) + COUNT_HEADER_SIZE(1); + +reexecute: + switch (CURRENT_STATE()) { + + case s_dead: + /* this state is used after a 'Connection: close' message + * the parser will error out if it reads another message + */ + if (LIKELY(ch == CR || ch == LF)) + break; + + SET_ERRNO(HPE_CLOSED_CONNECTION); + goto error; + + case s_start_req_or_res: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (ch == 'H') { + UPDATE_STATE(s_res_or_resp_H); + + CALLBACK_NOTIFY(message_begin); + } else { + parser->type = HTTP_REQUEST; + UPDATE_STATE(s_start_req); + REEXECUTE(); + } + + break; + } + + case s_res_or_resp_H: + if (ch == 'T') { + parser->type = HTTP_RESPONSE; + UPDATE_STATE(s_res_HT); + } else { + if (UNLIKELY(ch != 'E')) { + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + parser->type = HTTP_REQUEST; + parser->method = HTTP_HEAD; + parser->index = 2; + UPDATE_STATE(s_req_method); + } + break; + + case s_start_res: + { + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + switch (ch) { + case 'H': + UPDATE_STATE(s_res_H); + break; + + case CR: + case LF: + break; + + default: + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + CALLBACK_NOTIFY(message_begin); + break; + } + + case s_res_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HT); + break; + + case s_res_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HTT); + break; + + case s_res_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_res_HTTP); + break; + + case s_res_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_res_first_http_major); + break; + + case s_res_first_http_major: + if (UNLIKELY(ch < '0' || ch > '9')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_res_http_major); + break; + + /* major HTTP version or dot */ + case s_res_http_major: + { + if (ch == '.') { + UPDATE_STATE(s_res_first_http_minor); + break; + } + + if (!IS_NUM(ch)) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major *= 10; + parser->http_major += ch - '0'; + + if (UNLIKELY(parser->http_major > 999)) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + break; + } + + /* first digit of minor HTTP version */ + case s_res_first_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_res_http_minor); + break; + + /* minor HTTP version or end of request line */ + case s_res_http_minor: + { + if (ch == ' ') { + UPDATE_STATE(s_res_first_status_code); + break; + } + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor *= 10; + parser->http_minor += ch - '0'; + + if (UNLIKELY(parser->http_minor > 999)) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + break; + } + + case s_res_first_status_code: + { + if (!IS_NUM(ch)) { + if (ch == ' ') { + break; + } + + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + parser->status_code = ch - '0'; + UPDATE_STATE(s_res_status_code); + break; + } + + case s_res_status_code: + { + if (!IS_NUM(ch)) { + switch (ch) { + case ' ': + UPDATE_STATE(s_res_status_start); + break; + case CR: + UPDATE_STATE(s_res_line_almost_done); + break; + case LF: + UPDATE_STATE(s_header_field_start); + break; + default: + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + break; + } + + parser->status_code *= 10; + parser->status_code += ch - '0'; + + if (UNLIKELY(parser->status_code > 999)) { + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + + break; + } + + case s_res_status_start: + { + if (ch == CR) { + UPDATE_STATE(s_res_line_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + break; + } + + MARK(status); + UPDATE_STATE(s_res_status); + parser->index = 0; + break; + } + + case s_res_status: + if (ch == CR) { + UPDATE_STATE(s_res_line_almost_done); + CALLBACK_DATA(status); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA(status); + break; + } + + break; + + case s_res_line_almost_done: + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_field_start); + break; + + case s_start_req: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (UNLIKELY(!IS_ALPHA(ch))) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + parser->method = (enum http_method) 0; + parser->index = 1; + switch (ch) { + case 'A': parser->method = HTTP_ACL; break; + case 'B': parser->method = HTTP_BIND; break; + case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; + case 'D': parser->method = HTTP_DELETE; break; + case 'G': parser->method = HTTP_GET; break; + case 'H': parser->method = HTTP_HEAD; break; + case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; + case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; + case 'N': parser->method = HTTP_NOTIFY; break; + case 'O': parser->method = HTTP_OPTIONS; break; + case 'P': parser->method = HTTP_POST; + /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ + break; + case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; + case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; + case 'T': parser->method = HTTP_TRACE; break; + case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + UPDATE_STATE(s_req_method); + + CALLBACK_NOTIFY(message_begin); + + break; + } + + case s_req_method: + { + const char *matcher; + if (UNLIKELY(ch == '\0')) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + matcher = method_strings[parser->method]; + if (ch == ' ' && matcher[parser->index] == '\0') { + UPDATE_STATE(s_req_spaces_before_url); + } else if (ch == matcher[parser->index]) { + ; /* nada */ + } else if (IS_ALPHA(ch)) { + + switch (parser->method << 16 | parser->index << 8 | ch) { +#define XX(meth, pos, ch, new_meth) \ + case (HTTP_##meth << 16 | pos << 8 | ch): \ + parser->method = HTTP_##new_meth; break; + + XX(POST, 1, 'U', PUT) + XX(POST, 1, 'A', PATCH) + XX(CONNECT, 1, 'H', CHECKOUT) + XX(CONNECT, 2, 'P', COPY) + XX(MKCOL, 1, 'O', MOVE) + XX(MKCOL, 1, 'E', MERGE) + XX(MKCOL, 2, 'A', MKACTIVITY) + XX(MKCOL, 3, 'A', MKCALENDAR) + XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(REPORT, 2, 'B', REBIND) + XX(POST, 1, 'R', PROPFIND) + XX(PROPFIND, 4, 'P', PROPPATCH) + XX(PUT, 2, 'R', PURGE) + XX(LOCK, 1, 'I', LINK) + XX(UNLOCK, 2, 'S', UNSUBSCRIBE) + XX(UNLOCK, 2, 'B', UNBIND) + XX(UNLOCK, 3, 'I', UNLINK) +#undef XX + + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (ch == '-' && + parser->index == 1 && + parser->method == HTTP_MKCOL) { + parser->method = HTTP_MSEARCH; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + ++parser->index; + break; + } + + case s_req_spaces_before_url: + { + if (ch == ' ') break; + + MARK(url); + if (parser->method == HTTP_CONNECT) { + UPDATE_STATE(s_req_server_start); + } + + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + + break; + } + + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + { + switch (ch) { + /* No whitespace allowed here */ + case ' ': + case CR: + case LF: + SET_ERRNO(HPE_INVALID_URL); + goto error; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + + break; + } + + case s_req_server: + case s_req_server_with_at: + case s_req_path: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + { + switch (ch) { + case ' ': + UPDATE_STATE(s_req_http_start); + CALLBACK_DATA(url); + break; + case CR: + case LF: + parser->http_major = 0; + parser->http_minor = 9; + UPDATE_STATE((ch == CR) ? + s_req_line_almost_done : + s_header_field_start); + CALLBACK_DATA(url); + break; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + break; + } + + case s_req_http_start: + switch (ch) { + case 'H': + UPDATE_STATE(s_req_http_H); + break; + case ' ': + break; + default: + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + break; + + case s_req_http_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HT); + break; + + case s_req_http_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HTT); + break; + + case s_req_http_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_req_http_HTTP); + break; + + case s_req_http_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_req_first_http_major); + break; + + /* first digit of major HTTP version */ + case s_req_first_http_major: + if (UNLIKELY(ch < '1' || ch > '9')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_req_http_major); + break; + + /* major HTTP version or dot */ + case s_req_http_major: + { + if (ch == '.') { + UPDATE_STATE(s_req_first_http_minor); + break; + } + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major *= 10; + parser->http_major += ch - '0'; + + if (UNLIKELY(parser->http_major > 999)) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + break; + } + + /* first digit of minor HTTP version */ + case s_req_first_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_req_http_minor); + break; + + /* minor HTTP version or end of request line */ + case s_req_http_minor: + { + if (ch == CR) { + UPDATE_STATE(s_req_line_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + break; + } + + /* XXX allow spaces after digit? */ + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor *= 10; + parser->http_minor += ch - '0'; + + if (UNLIKELY(parser->http_minor > 999)) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + break; + } + + /* end of request line */ + case s_req_line_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_field_start); + break; + } + + case s_header_field_start: + { + if (ch == CR) { + UPDATE_STATE(s_headers_almost_done); + break; + } + + if (ch == LF) { + /* they might be just sending \n instead of \r\n so this would be + * the second \n to denote the end of headers*/ + UPDATE_STATE(s_headers_almost_done); + REEXECUTE(); + } + + c = TOKEN(ch); + + if (UNLIKELY(!c)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + MARK(header_field); + + parser->index = 0; + UPDATE_STATE(s_header_field); + + switch (c) { + case 'c': + parser->header_state = h_C; + break; + + case 'p': + parser->header_state = h_matching_proxy_connection; + break; + + case 't': + parser->header_state = h_matching_transfer_encoding; + break; + + case 'u': + parser->header_state = h_matching_upgrade; + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_field: + { + const char* start = p; + for (; p != data + len; p++) { + ch = *p; + c = TOKEN(ch); + + if (!c) + break; + + switch (parser->header_state) { + case h_general: + break; + + case h_C: + parser->index++; + parser->header_state = (c == 'o' ? h_CO : h_general); + break; + + case h_CO: + parser->index++; + parser->header_state = (c == 'n' ? h_CON : h_general); + break; + + case h_CON: + parser->index++; + switch (c) { + case 'n': + parser->header_state = h_matching_connection; + break; + case 't': + parser->header_state = h_matching_content_length; + break; + default: + parser->header_state = h_general; + break; + } + break; + + /* connection */ + + case h_matching_connection: + parser->index++; + if (parser->index > sizeof(CONNECTION)-1 + || c != CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* proxy-connection */ + + case h_matching_proxy_connection: + parser->index++; + if (parser->index > sizeof(PROXY_CONNECTION)-1 + || c != PROXY_CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* content-length */ + + case h_matching_content_length: + parser->index++; + if (parser->index > sizeof(CONTENT_LENGTH)-1 + || c != CONTENT_LENGTH[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + parser->header_state = h_content_length; + } + break; + + /* transfer-encoding */ + + case h_matching_transfer_encoding: + parser->index++; + if (parser->index > sizeof(TRANSFER_ENCODING)-1 + || c != TRANSFER_ENCODING[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { + parser->header_state = h_transfer_encoding; + } + break; + + /* upgrade */ + + case h_matching_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE)-1 + || c != UPGRADE[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(UPGRADE)-2) { + parser->header_state = h_upgrade; + } + break; + + case h_connection: + case h_content_length: + case h_transfer_encoding: + case h_upgrade: + if (ch != ' ') parser->header_state = h_general; + break; + + default: + assert(0 && "Unknown header_state"); + break; + } + } + + COUNT_HEADER_SIZE(p - start); + + if (p == data + len) { + --p; + break; + } + + if (ch == ':') { + UPDATE_STATE(s_header_value_discard_ws); + CALLBACK_DATA(header_field); + break; + } + + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + case s_header_value_discard_ws: + if (ch == ' ' || ch == '\t') break; + + if (ch == CR) { + UPDATE_STATE(s_header_value_discard_ws_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + /* FALLTHROUGH */ + + case s_header_value_start: + { + MARK(header_value); + + UPDATE_STATE(s_header_value); + parser->index = 0; + + c = LOWER(ch); + + switch (parser->header_state) { + case h_upgrade: + parser->flags |= F_UPGRADE; + parser->header_state = h_general; + break; + + case h_transfer_encoding: + /* looking for 'Transfer-Encoding: chunked' */ + if ('c' == c) { + parser->header_state = h_matching_transfer_encoding_chunked; + } else { + parser->header_state = h_general; + } + break; + + case h_content_length: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + if (parser->flags & F_CONTENTLENGTH) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + parser->flags |= F_CONTENTLENGTH; + parser->content_length = ch - '0'; + break; + + case h_connection: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + parser->header_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + parser->header_state = h_matching_connection_close; + } else if (c == 'u') { + parser->header_state = h_matching_connection_upgrade; + } else { + parser->header_state = h_matching_connection_token; + } + break; + + /* Multi-value `Connection` header */ + case h_matching_connection_token_start: + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_value: + { + const char* start = p; + enum header_states h_state = (enum header_states) parser->header_state; + for (; p != data + len; p++) { + ch = *p; + if (ch == CR) { + UPDATE_STATE(s_header_almost_done); + parser->header_state = h_state; + CALLBACK_DATA(header_value); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_almost_done); + COUNT_HEADER_SIZE(p - start); + parser->header_state = h_state; + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + + if (!lenient && !IS_HEADER_CHAR(ch)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + c = LOWER(ch); + + switch (h_state) { + case h_general: + { + const char* p_cr; + const char* p_lf; + size_t limit = data + len - p; + + limit = MIN(limit, HTTP_MAX_HEADER_SIZE); + + p_cr = (const char*) memchr(p, CR, limit); + p_lf = (const char*) memchr(p, LF, limit); + if (p_cr != NULL) { + if (p_lf != NULL && p_cr >= p_lf) + p = p_lf; + else + p = p_cr; + } else if (UNLIKELY(p_lf != NULL)) { + p = p_lf; + } else { + p = data + len; + } + --p; + + break; + } + + case h_connection: + case h_transfer_encoding: + assert(0 && "Shouldn't get here."); + break; + + case h_content_length: + { + uint64_t t; + + if (ch == ' ') break; + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + t = parser->content_length; + t *= 10; + t += ch - '0'; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + parser->content_length = t; + break; + } + + /* Transfer-Encoding: chunked */ + case h_matching_transfer_encoding_chunked: + parser->index++; + if (parser->index > sizeof(CHUNKED)-1 + || c != CHUNKED[parser->index]) { + h_state = h_general; + } else if (parser->index == sizeof(CHUNKED)-2) { + h_state = h_transfer_encoding_chunked; + } + break; + + case h_matching_connection_token_start: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + h_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + h_state = h_matching_connection_close; + } else if (c == 'u') { + h_state = h_matching_connection_upgrade; + } else if (STRICT_TOKEN(c)) { + h_state = h_matching_connection_token; + } else if (c == ' ' || c == '\t') { + /* Skip lws */ + } else { + h_state = h_general; + } + break; + + /* looking for 'Connection: keep-alive' */ + case h_matching_connection_keep_alive: + parser->index++; + if (parser->index > sizeof(KEEP_ALIVE)-1 + || c != KEEP_ALIVE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + h_state = h_connection_keep_alive; + } + break; + + /* looking for 'Connection: close' */ + case h_matching_connection_close: + parser->index++; + if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(CLOSE)-2) { + h_state = h_connection_close; + } + break; + + /* looking for 'Connection: upgrade' */ + case h_matching_connection_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE) - 1 || + c != UPGRADE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(UPGRADE)-2) { + h_state = h_connection_upgrade; + } + break; + + case h_matching_connection_token: + if (ch == ',') { + h_state = h_matching_connection_token_start; + parser->index = 0; + } + break; + + case h_transfer_encoding_chunked: + if (ch != ' ') h_state = h_general; + break; + + case h_connection_keep_alive: + case h_connection_close: + case h_connection_upgrade: + if (ch == ',') { + if (h_state == h_connection_keep_alive) { + parser->flags |= F_CONNECTION_KEEP_ALIVE; + } else if (h_state == h_connection_close) { + parser->flags |= F_CONNECTION_CLOSE; + } else if (h_state == h_connection_upgrade) { + parser->flags |= F_CONNECTION_UPGRADE; + } + h_state = h_matching_connection_token_start; + parser->index = 0; + } else if (ch != ' ') { + h_state = h_matching_connection_token; + } + break; + + default: + UPDATE_STATE(s_header_value); + h_state = h_general; + break; + } + } + parser->header_state = h_state; + + COUNT_HEADER_SIZE(p - start); + + if (p == data + len) + --p; + break; + } + + case s_header_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_value_lws); + break; + } + + case s_header_value_lws: + { + if (ch == ' ' || ch == '\t') { + UPDATE_STATE(s_header_value_start); + REEXECUTE(); + } + + /* finished the header */ + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + default: + break; + } + + UPDATE_STATE(s_header_field_start); + REEXECUTE(); + } + + case s_header_value_discard_ws_almost_done: + { + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + case s_header_value_discard_lws: + { + if (ch == ' ' || ch == '\t') { + UPDATE_STATE(s_header_value_discard_ws); + break; + } else { + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + default: + break; + } + + /* header value was empty */ + MARK(header_value); + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + } + + case s_headers_almost_done: + { + STRICT_CHECK(ch != LF); + + if (parser->flags & F_TRAILING) { + /* End of a chunked request */ + UPDATE_STATE(s_message_done); + CALLBACK_NOTIFY_NOADVANCE(chunk_complete); + REEXECUTE(); + } + + /* Cannot use chunked encoding and a content-length header together + per the HTTP specification. */ + if ((parser->flags & F_CHUNKED) && + (parser->flags & F_CONTENTLENGTH)) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + UPDATE_STATE(s_headers_done); + + /* Set this here so that on_headers_complete() callbacks can see it */ + parser->upgrade = + ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) == + (F_UPGRADE | F_CONNECTION_UPGRADE) || + parser->method == HTTP_CONNECT); + + /* Here we call the headers_complete callback. This is somewhat + * different than other callbacks because if the user returns 1, we + * will interpret that as saying that this message has no body. This + * is needed for the annoying case of recieving a response to a HEAD + * request. + * + * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so + * we have to simulate it by handling a change in errno below. + */ + if (settings->on_headers_complete) { + switch (settings->on_headers_complete(parser)) { + case 0: + break; + + case 2: + parser->upgrade = 1; + + case 1: + parser->flags |= F_SKIPBODY; + break; + + default: + SET_ERRNO(HPE_CB_headers_complete); + RETURN(p - data); /* Error */ + } + } + + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + RETURN(p - data); + } + + REEXECUTE(); + } + + case s_headers_done: + { + int hasBody; + STRICT_CHECK(ch != LF); + + parser->nread = 0; + + hasBody = parser->flags & F_CHUNKED || + (parser->content_length > 0 && parser->content_length != ULLONG_MAX); + if (parser->upgrade && (parser->method == HTTP_CONNECT || + (parser->flags & F_SKIPBODY) || !hasBody)) { + /* Exit, the rest of the message is in a different protocol. */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + RETURN((p - data) + 1); + } + + if (parser->flags & F_SKIPBODY) { + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->flags & F_CHUNKED) { + /* chunked encoding - ignore Content-Length header */ + UPDATE_STATE(s_chunk_size_start); + } else { + if (parser->content_length == 0) { + /* Content-Length header given but zero: Content-Length: 0\r\n */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->content_length != ULLONG_MAX) { + /* Content-Length header given and non-zero */ + UPDATE_STATE(s_body_identity); + } else { + if (!http_message_needs_eof(parser)) { + /* Assume content-length 0 - read the next */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else { + /* Read body until EOF */ + UPDATE_STATE(s_body_identity_eof); + } + } + } + + break; + } + + case s_body_identity: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* The difference between advancing content_length and p is because + * the latter will automaticaly advance on the next loop iteration. + * Further, if content_length ends up at 0, we want to see the last + * byte again for our message complete callback. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_message_done); + + /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. + * + * The alternative to doing this is to wait for the next byte to + * trigger the data callback, just as in every other case. The + * problem with this is that this makes it difficult for the test + * harness to distinguish between complete-on-EOF and + * complete-on-length. It's not clear that this distinction is + * important for applications, but let's keep it for now. + */ + CALLBACK_DATA_(body, p - body_mark + 1, p - data); + REEXECUTE(); + } + + break; + } + + /* read until EOF */ + case s_body_identity_eof: + MARK(body); + p = data + len - 1; + + break; + + case s_message_done: + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + if (parser->upgrade) { + /* Exit, the rest of the message is in a different protocol. */ + RETURN((p - data) + 1); + } + break; + + case s_chunk_size_start: + { + assert(parser->nread == 1); + assert(parser->flags & F_CHUNKED); + + unhex_val = unhex[(unsigned char)ch]; + if (UNLIKELY(unhex_val == -1)) { + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + parser->content_length = unhex_val; + UPDATE_STATE(s_chunk_size); + break; + } + + case s_chunk_size: + { + uint64_t t; + + assert(parser->flags & F_CHUNKED); + + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + + unhex_val = unhex[(unsigned char)ch]; + + if (unhex_val == -1) { + if (ch == ';' || ch == ' ') { + UPDATE_STATE(s_chunk_parameters); + break; + } + + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + t = parser->content_length; + t *= 16; + t += unhex_val; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + parser->content_length = t; + break; + } + + case s_chunk_parameters: + { + assert(parser->flags & F_CHUNKED); + /* just ignore this shit. TODO check for overflow */ + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + break; + } + + case s_chunk_size_almost_done: + { + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + + parser->nread = 0; + + if (parser->content_length == 0) { + parser->flags |= F_TRAILING; + UPDATE_STATE(s_header_field_start); + } else { + UPDATE_STATE(s_chunk_data); + } + CALLBACK_NOTIFY(chunk_header); + break; + } + + case s_chunk_data: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->flags & F_CHUNKED); + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* See the explanation in s_body_identity for why the content + * length and data pointers are managed this way. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_chunk_data_almost_done); + } + + break; + } + + case s_chunk_data_almost_done: + assert(parser->flags & F_CHUNKED); + assert(parser->content_length == 0); + STRICT_CHECK(ch != CR); + UPDATE_STATE(s_chunk_data_done); + CALLBACK_DATA(body); + break; + + case s_chunk_data_done: + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + parser->nread = 0; + UPDATE_STATE(s_chunk_size_start); + CALLBACK_NOTIFY(chunk_complete); + break; + + default: + assert(0 && "unhandled state"); + SET_ERRNO(HPE_INVALID_INTERNAL_STATE); + goto error; + } + } + + /* Run callbacks for any marks that we have leftover after we ran our of + * bytes. There should be at most one of these set, so it's OK to invoke + * them in series (unset marks will not result in callbacks). + * + * We use the NOADVANCE() variety of callbacks here because 'p' has already + * overflowed 'data' and this allows us to correct for the off-by-one that + * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' + * value that's in-bounds). + */ + + assert(((header_field_mark ? 1 : 0) + + (header_value_mark ? 1 : 0) + + (url_mark ? 1 : 0) + + (body_mark ? 1 : 0) + + (status_mark ? 1 : 0)) <= 1); + + CALLBACK_DATA_NOADVANCE(header_field); + CALLBACK_DATA_NOADVANCE(header_value); + CALLBACK_DATA_NOADVANCE(url); + CALLBACK_DATA_NOADVANCE(body); + CALLBACK_DATA_NOADVANCE(status); + + RETURN(len); + +error: + if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { + SET_ERRNO(HPE_UNKNOWN); + } + + RETURN(p - data); +} + + +/* Does the parser need to see an EOF to find the end of the message? */ +int +http_message_needs_eof (const http_parser *parser) +{ + if (parser->type == HTTP_REQUEST) { + return 0; + } + + /* See RFC 2616 section 4.4 */ + if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ + parser->status_code == 204 || /* No Content */ + parser->status_code == 304 || /* Not Modified */ + parser->flags & F_SKIPBODY) { /* response to a HEAD request */ + return 0; + } + + if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { + return 0; + } + + return 1; +} + + +int +http_should_keep_alive (const http_parser *parser) +{ + if (parser->http_major > 0 && parser->http_minor > 0) { + /* HTTP/1.1 */ + if (parser->flags & F_CONNECTION_CLOSE) { + return 0; + } + } else { + /* HTTP/1.0 or earlier */ + if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { + return 0; + } + } + + return !http_message_needs_eof(parser); +} + + +const char * +http_method_str (enum http_method m) +{ + return ELEM_AT(method_strings, m, ""); +} + + +void +http_parser_init (http_parser *parser, enum http_parser_type t) +{ + void *data = parser->data; /* preserve application data */ + memset(parser, 0, sizeof(*parser)); + parser->data = data; + parser->type = t; + parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); + parser->http_errno = HPE_OK; +} + +void +http_parser_settings_init(http_parser_settings *settings) +{ + memset(settings, 0, sizeof(*settings)); +} + +const char * +http_errno_name(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].name; +} + +const char * +http_errno_description(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].description; +} + +static enum http_host_state +http_parse_host_char(enum http_host_state s, const char ch) { + switch(s) { + case s_http_userinfo: + case s_http_userinfo_start: + if (ch == '@') { + return s_http_host_start; + } + + if (IS_USERINFO_CHAR(ch)) { + return s_http_userinfo; + } + break; + + case s_http_host_start: + if (ch == '[') { + return s_http_host_v6_start; + } + + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + break; + + case s_http_host: + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + /* FALLTHROUGH */ + case s_http_host_v6_end: + if (ch == ':') { + return s_http_host_port_start; + } + + break; + + case s_http_host_v6: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* FALLTHROUGH */ + case s_http_host_v6_start: + if (IS_HEX(ch) || ch == ':' || ch == '.') { + return s_http_host_v6; + } + + if (s == s_http_host_v6 && ch == '%') { + return s_http_host_v6_zone_start; + } + break; + + case s_http_host_v6_zone: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* FALLTHROUGH */ + case s_http_host_v6_zone_start: + /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ + if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || + ch == '~') { + return s_http_host_v6_zone; + } + break; + + case s_http_host_port: + case s_http_host_port_start: + if (IS_NUM(ch)) { + return s_http_host_port; + } + + break; + + default: + break; + } + return s_http_host_dead; +} + +static int +http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { + enum http_host_state s; + + const char *p; + size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; + + assert(u->field_set & (1 << UF_HOST)); + + u->field_data[UF_HOST].len = 0; + + s = found_at ? s_http_userinfo_start : s_http_host_start; + + for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { + enum http_host_state new_s = http_parse_host_char(s, *p); + + if (new_s == s_http_host_dead) { + return 1; + } + + switch(new_s) { + case s_http_host: + if (s != s_http_host) { + u->field_data[UF_HOST].off = p - buf; + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6: + if (s != s_http_host_v6) { + u->field_data[UF_HOST].off = p - buf; + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + u->field_data[UF_HOST].len++; + break; + + case s_http_host_port: + if (s != s_http_host_port) { + u->field_data[UF_PORT].off = p - buf; + u->field_data[UF_PORT].len = 0; + u->field_set |= (1 << UF_PORT); + } + u->field_data[UF_PORT].len++; + break; + + case s_http_userinfo: + if (s != s_http_userinfo) { + u->field_data[UF_USERINFO].off = p - buf ; + u->field_data[UF_USERINFO].len = 0; + u->field_set |= (1 << UF_USERINFO); + } + u->field_data[UF_USERINFO].len++; + break; + + default: + break; + } + s = new_s; + } + + /* Make sure we don't end somewhere unexpected */ + switch (s) { + case s_http_host_start: + case s_http_host_v6_start: + case s_http_host_v6: + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + case s_http_host_port_start: + case s_http_userinfo: + case s_http_userinfo_start: + return 1; + default: + break; + } + + return 0; +} + +void +http_parser_url_init(struct http_parser_url *u) { + memset(u, 0, sizeof(*u)); +} + +int +http_parser_parse_url(const char *buf, size_t buflen, int is_connect, + struct http_parser_url *u) +{ + enum state s; + const char *p; + enum http_parser_url_fields uf, old_uf; + int found_at = 0; + + u->port = u->field_set = 0; + s = is_connect ? s_req_server_start : s_req_spaces_before_url; + old_uf = UF_MAX; + + for (p = buf; p < buf + buflen; p++) { + s = parse_url_char(s, *p); + + /* Figure out the next field that we're operating on */ + switch (s) { + case s_dead: + return 1; + + /* Skip delimeters */ + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_query_string_start: + case s_req_fragment_start: + continue; + + case s_req_schema: + uf = UF_SCHEMA; + break; + + case s_req_server_with_at: + found_at = 1; + + /* FALLTROUGH */ + case s_req_server: + uf = UF_HOST; + break; + + case s_req_path: + uf = UF_PATH; + break; + + case s_req_query_string: + uf = UF_QUERY; + break; + + case s_req_fragment: + uf = UF_FRAGMENT; + break; + + default: + assert(!"Unexpected state"); + return 1; + } + + /* Nothing's changed; soldier on */ + if (uf == old_uf) { + u->field_data[uf].len++; + continue; + } + + u->field_data[uf].off = p - buf; + u->field_data[uf].len = 1; + + u->field_set |= (1 << uf); + old_uf = uf; + } + + /* host must be present if there is a schema */ + /* parsing http:///toto will fail */ + if ((u->field_set & (1 << UF_SCHEMA)) && + (u->field_set & (1 << UF_HOST)) == 0) { + return 1; + } + + if (u->field_set & (1 << UF_HOST)) { + if (http_parse_host(buf, u, found_at) != 0) { + return 1; + } + } + + /* CONNECT requests can only contain "hostname:port" */ + if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { + return 1; + } + + if (u->field_set & (1 << UF_PORT)) { + /* Don't bother with endp; we've already validated the string */ + unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); + + /* Ports have a max value of 2^16 */ + if (v > 0xffff) { + return 1; + } + + u->port = (uint16_t) v; + } + + return 0; +} + +void +http_parser_pause(http_parser *parser, int paused) { + /* Users should only be pausing/unpausing a parser that is not in an error + * state. In non-debug builds, there's not much that we can do about this + * other than ignore it. + */ + if (HTTP_PARSER_ERRNO(parser) == HPE_OK || + HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { + SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); + } else { + assert(0 && "Attempting to pause parser in error state"); + } +} + +int +http_body_is_final(const struct http_parser *parser) { + return parser->state == s_message_done; +} + +unsigned long +http_parser_version(void) { + return HTTP_PARSER_VERSION_MAJOR * 0x10000 | + HTTP_PARSER_VERSION_MINOR * 0x00100 | + HTTP_PARSER_VERSION_PATCH * 0x00001; +} diff --git a/components/jsmn/CMakeLists.txt b/components/jsmn/CMakeLists.txt new file mode 100644 index 000000000..7c19d9ccb --- /dev/null +++ b/components/jsmn/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS "src") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES "") + +register_component() diff --git a/components/json/CMakeLists.txt b/components/json/CMakeLists.txt new file mode 100644 index 000000000..1ecadb385 --- /dev/null +++ b/components/json/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "cJSON/cJSON.c" + "cJSON/cJSON_Utils.c" + "cJSON/test.c" + INCLUDE_DIRS cJSON) diff --git a/components/json/cJSON b/components/json/cJSON new file mode 160000 index 000000000..3c8935676 --- /dev/null +++ b/components/json/cJSON @@ -0,0 +1 @@ +Subproject commit 3c8935676a97c7c97bf006db8312875b4f292f6c diff --git a/components/json/component.mk b/components/json/component.mk new file mode 100644 index 000000000..7fbd5db1e --- /dev/null +++ b/components/json/component.mk @@ -0,0 +1,7 @@ +# +# Component Makefile +# +COMPONENT_ADD_INCLUDEDIRS := cJSON +COMPONENT_SRCDIRS := cJSON +COMPONENT_SUBMODULES := cJSON +COMPONENT_OBJS := cJSON/cJSON.o cJSON/cJSON_Utils.o diff --git a/components/libsodium/CMakeLists.txt b/components/libsodium/CMakeLists.txt index 49b8adce9..3d55a991c 100644 --- a/components/libsodium/CMakeLists.txt +++ b/components/libsodium/CMakeLists.txt @@ -2,133 +2,77 @@ set(SRC libsodium/src/libsodium) set(COMPONENT_REQUIRES "mbedtls") -# Derived from libsodium/src/libsodium/Makefile.am -# (ignoring the !MINIMAL set) -set(COMPONENT_SRCS "${SRC}/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c" - "${SRC}/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c" - "${SRC}/crypto_auth/crypto_auth.c" - "${SRC}/crypto_auth/hmacsha256/auth_hmacsha256.c" - "${SRC}/crypto_auth/hmacsha512/auth_hmacsha512.c" - "${SRC}/crypto_auth/hmacsha512256/auth_hmacsha512256.c" - "${SRC}/crypto_box/crypto_box.c" - "${SRC}/crypto_box/crypto_box_easy.c" - "${SRC}/crypto_box/crypto_box_seal.c" - "${SRC}/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c" - "${SRC}/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c" - "${SRC}/crypto_core/curve25519/ref10/curve25519_ref10.c" - "${SRC}/crypto_core/hchacha20/core_hchacha20.c" - "${SRC}/crypto_core/hsalsa20/core_hsalsa20.c" - "${SRC}/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c" - "${SRC}/crypto_core/salsa/ref/core_salsa_ref.c" - "${SRC}/crypto_generichash/crypto_generichash.c" - "${SRC}/crypto_generichash/blake2b/generichash_blake2.c" - "${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c" - "${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-ref.c" - "${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c" - "${SRC}/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c" - "${SRC}/crypto_generichash/blake2b/ref/blake2b-ref.c" - "${SRC}/crypto_generichash/blake2b/ref/generichash_blake2b.c" - "${SRC}/crypto_hash/crypto_hash.c" - "${SRC}/crypto_hash/sha256/hash_sha256.c" - "${SRC}/crypto_hash/sha256/cp/hash_sha256_cp.c" - "${SRC}/crypto_hash/sha512/hash_sha512.c" - "${SRC}/crypto_hash/sha512/cp/hash_sha512_cp.c" - "${SRC}/crypto_kdf/crypto_kdf.c" - "${SRC}/crypto_kdf/blake2b/kdf_blake2b.c" - "${SRC}/crypto_kx/crypto_kx.c" - "${SRC}/crypto_onetimeauth/crypto_onetimeauth.c" - "${SRC}/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c" - "${SRC}/crypto_onetimeauth/poly1305/donna/poly1305_donna.c" - "${SRC}/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c" - "${SRC}/crypto_pwhash/crypto_pwhash.c" - "${SRC}/crypto_pwhash/argon2/argon2-core.c" - "${SRC}/crypto_pwhash/argon2/argon2-encoding.c" - "${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c" - "${SRC}/crypto_pwhash/argon2/argon2-fill-block-ssse3.c" - "${SRC}/crypto_pwhash/argon2/argon2.c" - "${SRC}/crypto_pwhash/argon2/blake2b-long.c" - "${SRC}/crypto_pwhash/argon2/pwhash_argon2i.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c" - "${SRC}/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c" - "${SRC}/crypto_scalarmult/crypto_scalarmult.c" - "${SRC}/crypto_scalarmult/curve25519/scalarmult_curve25519.c" - "${SRC}/crypto_scalarmult/curve25519/donna_c64/curve25519_donna_c64.c" - "${SRC}/crypto_scalarmult/curve25519/ref10/x25519_ref10.c" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/consts.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/ladder.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/ladder_base.S" - "${SRC}/crypto_scalarmult/curve25519/sandy2x/sandy2x.S" - "${SRC}/crypto_secretbox/crypto_secretbox.c" - "${SRC}/crypto_secretbox/crypto_secretbox_easy.c" - "${SRC}/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c" - "${SRC}/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c" - "${SRC}/crypto_shorthash/crypto_shorthash.c" - "${SRC}/crypto_shorthash/siphash24/shorthash_siphash24.c" - "${SRC}/crypto_shorthash/siphash24/shorthash_siphashx24.c" - "${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c" - "${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c" - "${SRC}/crypto_sign/crypto_sign.c" - "${SRC}/crypto_sign/ed25519/sign_ed25519.c" - "${SRC}/crypto_sign/ed25519/ref10/keypair.c" - "${SRC}/crypto_sign/ed25519/ref10/obsolete.c" - "${SRC}/crypto_sign/ed25519/ref10/open.c" - "${SRC}/crypto_sign/ed25519/ref10/sign.c" - "${SRC}/crypto_stream/crypto_stream.c" - "${SRC}/crypto_stream/aes128ctr/stream_aes128ctr.c" - "${SRC}/crypto_stream/aes128ctr/nacl/afternm_aes128ctr.c" - "${SRC}/crypto_stream/aes128ctr/nacl/beforenm_aes128ctr.c" - "${SRC}/crypto_stream/aes128ctr/nacl/consts_aes128ctr.c" - "${SRC}/crypto_stream/aes128ctr/nacl/int128_aes128ctr.c" - "${SRC}/crypto_stream/aes128ctr/nacl/stream_aes128ctr_nacl.c" - "${SRC}/crypto_stream/aes128ctr/nacl/xor_afternm_aes128ctr.c" - "${SRC}/crypto_stream/chacha20/stream_chacha20.c" - "${SRC}/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c" - "${SRC}/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c" - "${SRC}/crypto_stream/chacha20/ref/chacha20_ref.c" - "${SRC}/crypto_stream/salsa20/stream_salsa20.c" - "${SRC}/crypto_stream/salsa20/ref/salsa20_ref.c" - "${SRC}/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S" - "${SRC}/crypto_stream/salsa20/xmm6/salsa20_xmm6.c" - "${SRC}/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c" - "${SRC}/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c" - "${SRC}/crypto_stream/salsa2012/stream_salsa2012.c" - "${SRC}/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c" - "${SRC}/crypto_stream/salsa208/stream_salsa208.c" - "${SRC}/crypto_stream/salsa208/ref/stream_salsa208_ref.c" - "${SRC}/crypto_stream/xchacha20/stream_xchacha20.c" - "${SRC}/crypto_stream/xsalsa20/stream_xsalsa20.c" - "${SRC}/crypto_verify/sodium/verify.c" - "${SRC}/randombytes/randombytes.c" - "${SRC}/randombytes/nativeclient/randombytes_nativeclient.c" - "${SRC}/randombytes/salsa20/randombytes_salsa20_random.c" - "${SRC}/randombytes/sysrandom/randombytes_sysrandom.c" - "${SRC}/sodium/core.c" - "${SRC}/sodium/runtime.c" - "${SRC}/sodium/utils.c" - "${SRC}/sodium/version.c" - "port/randombytes_esp8266.c") +set(COMPONENT_SRCDIRS + port + # Derived from libsodium/src/libsodium/Makefile.am + # (ignoring the !MINIMAL set) + ${SRC}/crypto_aead/chacha20poly1305/sodium + ${SRC}/crypto_aead/xchacha20poly1305/sodium + ${SRC}/crypto_auth + ${SRC}/crypto_auth/hmacsha256 + ${SRC}/crypto_auth/hmacsha512 + ${SRC}/crypto_auth/hmacsha512256 + ${SRC}/crypto_box + ${SRC}/crypto_box/curve25519xsalsa20poly1305 + ${SRC}/crypto_core/curve25519/ref10 + ${SRC}/crypto_core/hchacha20 + ${SRC}/crypto_core/hsalsa20/ref2 + ${SRC}/crypto_core/hsalsa20 + ${SRC}/crypto_core/salsa/ref + ${SRC}/crypto_generichash + ${SRC}/crypto_generichash/blake2b + ${SRC}/crypto_generichash/blake2b/ref + ${SRC}/crypto_hash + ${SRC}/crypto_hash/sha256 + ${SRC}/crypto_hash/sha512 + ${SRC}/crypto_kdf/blake2b + ${SRC}/crypto_kdf + ${SRC}/crypto_kx + ${SRC}/crypto_onetimeauth + ${SRC}/crypto_onetimeauth/poly1305 + ${SRC}/crypto_onetimeauth/poly1305/donna + ${SRC}/crypto_pwhash/argon2 + ${SRC}/crypto_pwhash + ${SRC}/crypto_pwhash/scryptsalsa208sha256 + ${SRC}/crypto_pwhash/scryptsalsa208sha256/nosse + ${SRC}/crypto_scalarmult + ${SRC}/crypto_scalarmult/curve25519 + ${SRC}/crypto_scalarmult/curve25519/ref10 + ${SRC}/crypto_secretbox + ${SRC}/crypto_secretbox/xsalsa20poly1305 + ${SRC}/crypto_shorthash + ${SRC}/crypto_shorthash/siphash24 + ${SRC}/crypto_shorthash/siphash24/ref + ${SRC}/crypto_sign + ${SRC}/crypto_sign/ed25519 + ${SRC}/crypto_sign/ed25519/ref10 + ${SRC}/crypto_stream/chacha20 + ${SRC}/crypto_stream/chacha20/ref + ${SRC}/crypto_stream + ${SRC}/crypto_stream/salsa20 + ${SRC}/crypto_stream/salsa20/ref + ${SRC}/crypto_stream/xsalsa20 + ${SRC}/crypto_verify/sodium + ${SRC}/randombytes + ${SRC}/sodium + ) -if(CONFIG_SSL_USING_MBEDTLS) - list(APPEND COMPONENT_SRCS "port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c" - "port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c") +if(CONFIG_LIBSODIUM_USE_MBEDTLS_SHA) + set(COMPONENT_SRCDIRS ${COMPONENT_SRCDIRS} + port/crypto_hash_mbedtls + ) else() - list(APPEND COMPONENT_SRCS "${SRC}/crypto_hash/sha256/cp/hash_sha256_cp.c" - "${SRC}/crypto_hash/sha512/cp/hash_sha512_cp.c") + set(COMPONENT_SRCDIRS ${COMPONENT_SRCDIRS} + ${SRC}/crypto_hash/sha256/cp + ${SRC}/crypto_hash/sha512/cp + ) endif() set(COMPONENT_ADD_INCLUDEDIRS ${SRC}/include port_include) set(COMPONENT_PRIV_INCLUDEDIRS ${SRC}/include/sodium port_include/sodium port) +set(COMPONENT_REQUIRES "tcp_transport") + register_component() component_compile_definitions( @@ -139,8 +83,11 @@ component_compile_definitions( __STDC_CONSTANT_MACROS ) +component_compile_options(-Wno-unknown-pragmas) + # patch around warnings in third-party files set_source_files_properties( + ${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c ${SRC}/crypto_pwhash/argon2/pwhash_argon2i.c ${SRC}/crypto_pwhash/argon2/argon2-core.c ${SRC}/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c @@ -152,15 +99,15 @@ set_source_files_properties( PROPERTIES COMPILE_FLAGS -Wno-unused-variable ) -set_source_files_properties( - ${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c - PROPERTIES COMPILE_FLAGS - -Wno-unknown-pragmas - ) +# Temporary suppress "fallthrough" warnings until they are fixed in libsodium repo set_source_files_properties( ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c PROPERTIES COMPILE_FLAGS - -Wno-implicit-fallthrough - ) \ No newline at end of file + -Wno-implicit-fallthrough) + +set_source_files_properties( + ${SRC}/randombytes/randombytes.c + PROPERTIES COMPILE_FLAGS + -DRANDOMBYTES_DEFAULT_IMPLEMENTATION) diff --git a/components/libsodium/Kconfig b/components/libsodium/Kconfig index 045538c10..171ea55f1 100644 --- a/components/libsodium/Kconfig +++ b/components/libsodium/Kconfig @@ -3,13 +3,12 @@ menu "libsodium" config LIBSODIUM_USE_MBEDTLS_SHA bool "Use mbedTLS SHA256 & SHA512 implementations" default y - depends on !MBEDTLS_HARDWARE_SHA help If this option is enabled, libsodium will use thin wrappers around mbedTLS for SHA256 & SHA512 operations. This saves some code size if mbedTLS is also used. However it - is incompatible with hardware SHA acceleration (due to the + is incompatible with Espressif SHA (due to the way libsodium's API manages SHA state). endmenu # libsodium diff --git a/components/libsodium/component.mk b/components/libsodium/component.mk index 7cb6b8ec4..2f6bd68dc 100644 --- a/components/libsodium/component.mk +++ b/components/libsodium/component.mk @@ -1,4 +1,3 @@ -COMPONENT_SUBMODULES += libsodium # Common root directory for all source directories LSRC := libsodium/src/libsodium @@ -58,7 +57,7 @@ COMPONENT_SRCDIRS += \ $(LSRC)/randombytes \ $(LSRC)/sodium -ifdef CONFIG_SSL_USING_MBEDTLS +ifdef CONFIG_LIBSODIUM_USE_MBEDTLS_SHA COMPONENT_SRCDIRS += port/crypto_hash_mbedtls else COMPONENT_SRCDIRS += \ diff --git a/components/libsodium/libsodium/test/default/sign.c b/components/libsodium/libsodium/test/default/sign.c index 814f96729..4faacf368 100644 --- a/components/libsodium/libsodium/test/default/sign.c +++ b/components/libsodium/libsodium/test/default/sign.c @@ -14,7 +14,7 @@ typedef struct TestData_ { const char *m; } TestData; -static TestData test_data[] = { +static const TestData test_data[] = { {{0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60,},{0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a,},{0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a,0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74,0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55,0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac,0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b,0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24,0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b,},""}, {{0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda,0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f,0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24,0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb,},{0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a,0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc,0x9c,0x98,0x2c,0xcf,0x2e,0xc4,0x96,0x8c,0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c,},{0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8,0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40,0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f,0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda,0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e,0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c,0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee,0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00,},"\x72"}, {{0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7,},{0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25,},{0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a,},"\xaf\x82"}, diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c index 39c36c70a..960e2bda0 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c @@ -16,15 +16,6 @@ #include "mbedtls/sha256.h" #include -#ifdef MBEDTLS_SHA256_ALT -/* Wrapper only works if the libsodium context structure can be mapped - directly to the mbedTLS context structure. - - See extended comments in crypto_hash_sha512_mbedtls.c -*/ -#error "This wrapper only support standard software mbedTLS SHA" -#endif - /* Sanity check that all the context fields have identical sizes (this should be more or less given from the SHA256 algorithm) diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c index 4dd58a1de..b005f0ce0 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c @@ -16,18 +16,6 @@ #include "mbedtls/sha512.h" #include -#ifdef MBEDTLS_SHA512_ALT -/* Wrapper only works if the libsodium context structure can be mapped - directly to the mbedTLS context structure. - - For ESP8266 hardware SHA, the problems are fitting all the data in - the libsodium state structure, and also that libsodium doesn't - have mbedtls_sha512_free() or mbedtls_sha512_clone() so we can't - manage the hardware state in a clean way. -*/ -#error "This wrapper only support standard software mbedTLS SHA" -#endif - /* Sanity check that all the context fields have identical sizes (this should be more or less given from the SHA512 algorithm) diff --git a/components/log/CMakeLists.txt b/components/log/CMakeLists.txt new file mode 100644 index 000000000..203191e00 --- /dev/null +++ b/components/log/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "log.c" + INCLUDE_DIRS "include" + LDFRAGMENTS "linker.lf") diff --git a/components/log/component.mk b/components/log/component.mk index c2c4c03a1..f5e7fc772 100755 --- a/components/log/component.mk +++ b/components/log/component.mk @@ -1,5 +1,2 @@ -# -# Component Makefile -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index 052833864..c0aa87cca 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -78,6 +78,30 @@ void esp_log_level_set(const char* tag, esp_log_level_t level); */ putchar_like_t esp_log_set_putchar(putchar_like_t func); +/** + * @brief Function which returns timestamp to be used in log output + * + * This function is used in expansion of ESP_LOGx macros. + * In the 2nd stage bootloader, and at early application startup stage + * this function uses CPU cycle counter as time source. Later when + * FreeRTOS scheduler start running, it switches to FreeRTOS tick count. + * + * For now, we ignore millisecond counter overflow. + * + * @return timestamp, in milliseconds + */ +uint32_t esp_log_timestamp(void); + +/** + * @brief Function which returns timestamp to be used in log output + * + * This function uses HW cycle counter and does not depend on OS, + * so it can be safely used after application crash. + * + * @return timestamp, in milliseconds + */ +uint32_t esp_log_early_timestamp(void); + /** * @brief Write message into the log * @@ -207,6 +231,31 @@ void esp_early_log_write(esp_log_level_t level, const char* tag, const char* for #define esp_log_buffer_hex ESP_LOG_BUFFER_HEX #define esp_log_buffer_char ESP_LOG_BUFFER_CHAR +#if CONFIG_LOG_COLORS +#define LOG_COLOR_BLACK "30" +#define LOG_COLOR_RED "31" +#define LOG_COLOR_GREEN "32" +#define LOG_COLOR_BROWN "33" +#define LOG_COLOR_BLUE "34" +#define LOG_COLOR_PURPLE "35" +#define LOG_COLOR_CYAN "36" +#define LOG_COLOR(COLOR) "\033[0;" COLOR "m" +#define LOG_BOLD(COLOR) "\033[1;" COLOR "m" +#define LOG_RESET_COLOR "\033[0m" +#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) +#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) +#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) +#define LOG_COLOR_D +#define LOG_COLOR_V +#else //CONFIG_LOG_COLORS +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR +#endif //CONFIG_LOG_COLORS + /** @endcond */ /// macro to output logs in startup code, before heap allocator and syscalls have been initialized. log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE`` diff --git a/components/log/include/esp_log_internal.h b/components/log/include/esp_log_internal.h index 94ec34632..02dbdba65 100644 --- a/components/log/include/esp_log_internal.h +++ b/components/log/include/esp_log_internal.h @@ -16,9 +16,13 @@ #define __ESP_LOG_INTERNAL_H__ //these functions do not check level versus ESP_LOCAL_LEVEL, this should be done in esp_log.h -void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); -void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); -void esp_log_buffer_hexdump_internal( const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level); +#define esp_log_buffer_hex_internal(...) +#define esp_log_buffer_char_internal(...) +#define esp_log_buffer_hexdump_internal(...) +/* TODO: Add the implementation of the below API's */ +// void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); +// void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); +// void esp_log_buffer_hexdump_internal( const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level); #endif diff --git a/components/log/linker.lf b/components/log/linker.lf new file mode 100644 index 000000000..78644ee8c --- /dev/null +++ b/components/log/linker.lf @@ -0,0 +1,4 @@ +[mapping:log] +archive: liblog.a +entries: + * (noflash_data) diff --git a/components/log/log.c b/components/log/log.c index fc59a4c1e..d69e2533d 100644 --- a/components/log/log.c +++ b/components/log/log.c @@ -27,11 +27,16 @@ #include "xtensa/hal.h" #include "esp_log.h" +#include "esp_system.h" + +#ifndef BOOTLOADER_BUILD +#include "FreeRTOS.h" +#endif #ifdef CONFIG_LOG_COLORS -#define LOG_COLOR "\033[0;%dm" -#define LOG_BOLD "\033[1;%dm" -#define LOG_RESET_COLOR "\033[0m" +#define LOG_COLOR_HEAD "\033[0;%dm" +#define LOG_BOLD_HEAD "\033[1;%dm" +#define LOG_COLOR_END "\033[0m" static const uint32_t s_log_color[ESP_LOG_MAX] = { 0, // ESP_LOG_NONE @@ -52,9 +57,20 @@ static const char s_log_prefix[ESP_LOG_MAX] = { 'V', // ESP_LOG_VERBOSE }; -static uint32_t IRAM_ATTR esp_log_early_timestamp() +uint32_t IRAM_ATTR esp_log_early_timestamp() { - return xthal_get_ccount() / (80 * 1000); +#ifndef BOOTLOADER_BUILD + extern uint64_t g_esp_os_us; + extern uint32_t g_esp_boot_ccount; + + const uint32_t ticks_per_ms = g_esp_ticks_per_us * 1000; + const uint32_t ms = g_esp_os_us / 1000 + g_esp_boot_ccount / ((CRYSTAL_USED * 2) * 1000); +#else + const uint32_t ticks_per_ms = ((CRYSTAL_USED * 2) * 1000); + const uint32_t ms = 0; +#endif + + return soc_get_ccount() / ticks_per_ms + ms; } #ifndef BOOTLOADER_BUILD @@ -189,10 +205,6 @@ static int esp_log_write_str(const char *s) return ret; } -static uint32_t esp_log_timestamp() -{ - return clock() * (1000 / CLOCKS_PER_SEC) + esp_log_early_timestamp() % (1000 / CLOCKS_PER_SEC); -} #endif /** @@ -207,7 +219,7 @@ void IRAM_ATTR esp_early_log_write(esp_log_level_t level, const char *tag, const uint32_t color = level >= ESP_LOG_MAX ? 0 : s_log_color[level]; if (color) - ets_printf(LOG_COLOR, color); + ets_printf(LOG_COLOR_HEAD, color); #endif if (ets_printf("%c (%d) %s: ", prefix, esp_log_early_timestamp(), tag) < 0) @@ -220,7 +232,7 @@ void IRAM_ATTR esp_early_log_write(esp_log_level_t level, const char *tag, const out: #ifdef CONFIG_LOG_COLORS if (color) - ets_printf(LOG_RESET_COLOR); + ets_printf(LOG_COLOR_END); #endif ets_printf("\n"); } @@ -248,14 +260,14 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ... uint32_t color = level >= ESP_LOG_MAX ? 0 : s_log_color[level]; if (color) { - sprintf(buf, LOG_COLOR, color); + sprintf(buf, LOG_COLOR_HEAD, color); ret = esp_log_write_str(buf); if (ret == EOF) goto exit; } #endif prefix = level >= ESP_LOG_MAX ? 'N' : s_log_prefix[level]; - ret = asprintf(&pbuf, "%c (%d) %s: ", prefix, esp_log_timestamp(), tag); + ret = asprintf(&pbuf, "%c (%d) %s: ", prefix, esp_log_early_timestamp(), tag); if (ret < 0) goto out; ret = esp_log_write_str(pbuf); @@ -276,7 +288,7 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ... out: #ifdef CONFIG_LOG_COLORS if (color) { - ret = esp_log_write_str(LOG_RESET_COLOR); + ret = esp_log_write_str(LOG_COLOR_END); if (ret == EOF) goto exit; } diff --git a/components/lwip/CMakeLists.txt b/components/lwip/CMakeLists.txt index 8cb4d7489..9d286ec79 100644 --- a/components/lwip/CMakeLists.txt +++ b/components/lwip/CMakeLists.txt @@ -1,23 +1,163 @@ -set(COMPONENT_ADD_INCLUDEDIRS - include/lwip/apps +idf_build_get_property(target IDF_TARGET) +set(include_dirs + include/apps + include/apps/sntp lwip/src/include - lwip/src/include/posix - port/esp8266/include) - -set(COMPONENT_SRCDIRS - apps/dhcpserver - apps/multi-threads - lwip/src/api - lwip/src/apps/sntp - lwip/src/core - lwip/src/core/ipv4 - lwip/src/core/ipv6 - lwip/src/netif - port/esp8266/freertos - port/esp8266/netif) - -set(COMPONENT_REQUIRES tcpip_adapter esp8266 freertos) - -register_component() - -component_compile_options(-Wno-address) + port/${target}/include + port/${target}/include/arch + ) + +set(srcs + "apps/dhcpserver/dhcpserver.c" + "apps/ping/esp_ping.c" + "apps/ping/ping.c" + "apps/ping/ping_sock.c" + "apps/sntp/sntp.c" + "lwip/src/api/api_lib.c" + "lwip/src/api/api_msg.c" + "lwip/src/api/err.c" + "lwip/src/api/if_api.c" + "lwip/src/api/netbuf.c" + "lwip/src/api/netdb.c" + "lwip/src/api/netifapi.c" + "lwip/src/api/sockets.c" + "lwip/src/api/tcpip.c" + "lwip/src/apps/sntp/sntp.c" + "lwip/src/apps/netbiosns/netbiosns.c" + "lwip/src/core/def.c" + "lwip/src/core/dns.c" + "lwip/src/core/inet_chksum.c" + "lwip/src/core/init.c" + "lwip/src/core/ip.c" + "lwip/src/core/mem.c" + "lwip/src/core/memp.c" + "lwip/src/core/netif.c" + "lwip/src/core/pbuf.c" + "lwip/src/core/raw.c" + "lwip/src/core/stats.c" + "lwip/src/core/sys.c" + "lwip/src/core/tcp.c" + "lwip/src/core/tcp_in.c" + "lwip/src/core/tcp_out.c" + "lwip/src/core/timeouts.c" + "lwip/src/core/udp.c" + "lwip/src/core/ipv4/autoip.c" + "lwip/src/core/ipv4/dhcp.c" + "lwip/src/core/ipv4/etharp.c" + "lwip/src/core/ipv4/icmp.c" + "lwip/src/core/ipv4/igmp.c" + "lwip/src/core/ipv4/ip4.c" + "lwip/src/core/ipv4/ip4_napt.c" + "lwip/src/core/ipv4/ip4_addr.c" + "lwip/src/core/ipv4/ip4_frag.c" + "lwip/src/core/ipv6/dhcp6.c" + "lwip/src/core/ipv6/ethip6.c" + "lwip/src/core/ipv6/icmp6.c" + "lwip/src/core/ipv6/inet6.c" + "lwip/src/core/ipv6/ip6.c" + "lwip/src/core/ipv6/ip6_addr.c" + "lwip/src/core/ipv6/ip6_frag.c" + "lwip/src/core/ipv6/mld6.c" + "lwip/src/core/ipv6/nd6.c" + "lwip/src/netif/ethernet.c" + "lwip/src/netif/lowpan6.c" + "lwip/src/netif/slipif.c" + "lwip/src/netif/ppp/auth.c" + "lwip/src/netif/ppp/ccp.c" + "lwip/src/netif/ppp/chap-md5.c" + "lwip/src/netif/ppp/chap-new.c" + "lwip/src/netif/ppp/chap_ms.c" + "lwip/src/netif/ppp/demand.c" + "lwip/src/netif/ppp/eap.c" + "lwip/src/netif/ppp/ecp.c" + "lwip/src/netif/ppp/eui64.c" + "lwip/src/netif/ppp/fsm.c" + "lwip/src/netif/ppp/ipcp.c" + "lwip/src/netif/ppp/ipv6cp.c" + "lwip/src/netif/ppp/lcp.c" + "lwip/src/netif/ppp/magic.c" + "lwip/src/netif/ppp/mppe.c" + "lwip/src/netif/ppp/multilink.c" + "lwip/src/netif/ppp/ppp.c" + "lwip/src/netif/ppp/pppapi.c" + "lwip/src/netif/ppp/pppcrypt.c" + "lwip/src/netif/ppp/pppoe.c" + "lwip/src/netif/ppp/pppol2tp.c" + "lwip/src/netif/ppp/pppos.c" + "lwip/src/netif/ppp/upap.c" + "lwip/src/netif/ppp/utils.c" + "lwip/src/netif/ppp/vj.c" + "port/${target}/vfs_lwip.c" + "port/${target}/debug/lwip_debug.c" + "port/${target}/freertos/sys_arch.c" + "port/${target}/netif/dhcp_state.c" + "port/${target}/netif/wlanif.c") + + +if(CONFIG_LWIP_PPP_SUPPORT) + list(APPEND srcs + "lwip/src/netif/ppp/auth.c" + "lwip/src/netif/ppp/ccp.c" + "lwip/src/netif/ppp/chap-md5.c" + "lwip/src/netif/ppp/chap-new.c" + "lwip/src/netif/ppp/chap_ms.c" + "lwip/src/netif/ppp/demand.c" + "lwip/src/netif/ppp/eap.c" + "lwip/src/netif/ppp/ecp.c" + "lwip/src/netif/ppp/eui64.c" + "lwip/src/netif/ppp/fsm.c" + "lwip/src/netif/ppp/ipcp.c" + "lwip/src/netif/ppp/ipv6cp.c" + "lwip/src/netif/ppp/lcp.c" + "lwip/src/netif/ppp/magic.c" + "lwip/src/netif/ppp/mppe.c" + "lwip/src/netif/ppp/multilink.c" + "lwip/src/netif/ppp/ppp.c" + "lwip/src/netif/ppp/pppapi.c" + "lwip/src/netif/ppp/pppcrypt.c" + "lwip/src/netif/ppp/pppoe.c" + "lwip/src/netif/ppp/pppol2tp.c" + "lwip/src/netif/ppp/pppos.c" + "lwip/src/netif/ppp/upap.c" + "lwip/src/netif/ppp/utils.c" + "lwip/src/netif/ppp/vj.c" + "lwip/src/netif/ppp/polarssl/arc4.c" + "lwip/src/netif/ppp/polarssl/des.c" + "lwip/src/netif/ppp/polarssl/md4.c" + "lwip/src/netif/ppp/polarssl/md5.c" + "lwip/src/netif/ppp/polarssl/sha1.c") +endif() + +if(CONFIG_ETH_ENABLED) + list(APPEND srcs "port/esp32/netif/ethernetif.c") +endif() + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + LDFRAGMENTS linker.lf + REQUIRES vfs + PRIV_REQUIRES ${priv_requires} tcpip_adapter nvs_flash) + +# lots of LWIP source files evaluate macros that check address of stack variables +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address) + +if(GCC_NOT_5_2_0) + set_source_files_properties( + lwip/src/netif/ppp/ppp.c + PROPERTIES COMPILE_FLAGS + -Wno-uninitialized + ) + set_source_files_properties( + lwip/src/netif/ppp/pppos.c + PROPERTIES COMPILE_FLAGS + -Wno-implicit-fallthrough + ) +endif() + +# "comparison is always false due to limited range of data type" warning +# when setting CONFIG_LWIP_TCP_WND_DEFAULT to 65535 +set_source_files_properties( + lwip/src/core/tcp.c + PROPERTIES COMPILE_FLAGS + -Wno-type-limits +) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index eb0d4397d..84233f195 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -1,708 +1,914 @@ menu "LWIP" -config LWIP_USE_IRAM - bool "Enable lwip use iram option" - default n - -config LWIP_HIGH_THROUGHPUT - bool "Enable lwip high throughput" - default n - select TCP_QUEUE_OOSEQ - select TCP_HIGH_SPEED_RETRANSMISSION - select SOC_FULL_ICACHE - select WIFI_TX_RATE_SEQUENCE_FROM_HIGH - help - Enable this option, also enable "TCP_QUEUE_OOSEQ", "TCP_HIGH_SPEED_RETRANSMISSION" and - "SOC_FULL_ICACHE", so lwip should cache TCP message received in disorder sequence and - chip should full 32 KB IRAM as icache. For these 2 reasons, the global heap user can used - may reduce a lot. - -config LWIP_GLOBAL_DATA_LINK_IRAM - bool "Link LWIP global data to IRAM" - default y - depends on !LWIP_HIGH_THROUGHPUT - depends on !SOC_FULL_ICACHE - help - Link LWIP global data(.bss .data COMMON) from DRAM to IRAM. - -menu "ARP" - -config LWIP_ARP_TABLE_SIZE - int "Number of active MAC-IP address pairs cached" - range 1 16 - default 10 - -config LWIP_ARP_MAXAGE - int "The time an ARP entry stays valid after its last update" - range 100 65535 - default 300 - -endmenu # LWIP ARP - -menu "SOCKET" - -config LWIP_IPV6_MLD_SOCK - bool "LWIP socket supports IPv6 multicast configuration" - default y - depends on LWIP_IPV6 - help - Enable the option can enable LWIP socket IPv6 multicast configuration. - -config LWIP_SOCKET_MULTITHREAD - bool "LWIP socket supports multithread" - default y - help - Enable the option can enable LWIP socket multithread and all - function will be thread safe. - -config ESP_UDP_SYNC_SEND - bool "LWIP socket UDP sync send" - default y - help - Enable the option can enable LWIP socket UDP sync send. CPU cost - should decrease but memory cost increase and it can make UDP - throughput increase a lot. - -config ESP_UDP_SYNC_RETRY_MAX - int "LWIP socket UDP sync send retry max count" - range 1 10 - default 5 - depends on ESP_UDP_SYNC_SEND - help - When UDP sync send count reaches the value, then the packet should - be lost and LWIP core thread wake up the up-level send thread. - -config LWIP_MAX_SOCKETS - int "Max number of open sockets" - range 1 16 - default 10 - help - Sockets take up a certain amount of memory, and allowing fewer - sockets to be open at the same time conserves memory. Specify - the maximum amount of sockets here. The valid value is from 1 - to 16. - -config LWIP_SO_REUSE - bool "Enable SO_REUSEADDR option" - default y - help - Enabling this option allows binding to a port which remains in - TIME_WAIT. - -config LWIP_SO_REUSE_RXTOALL - bool "SO_REUSEADDR copies broadcast/multicast to all matches" - depends on LWIP_SO_REUSE - default y - help - Enabling this option means that any incoming broadcast or multicast - packet will be copied to all of the local sockets that it matches - (may be more than one if SO_REUSEADDR is set on the socket.) - - This increases memory overhead as the packets need to be copied, - however they are only copied per matching socket. You can safely - disable it if you don't plan to receive broadcast or multicast - traffic on more than one socket at a time. - -config LWIP_SO_RCVBUF - bool "Enable SO_RCVBUF option" - default n - help - Enabling this option allows checking for available data on a netconn. - -config LWIP_RECV_BUFSIZE_DEFAULT - int "The default value for recv_bufsize" - default 11680 - range 2920 11680 - -config LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT - int "TCP socket/netconn close waits time to send the FIN" - default 10000 - range 10000 20000 - -endmenu # LWIP SOCKET - -config LWIP_IP_FRAG - bool "Enable fragment outgoing IP packets" - default n - help - Enabling this option allows fragmenting outgoing IP packets if their size - exceeds MTU. - -menuconfig LWIP_IP_REASSEMBLY - bool "Enable reassembly incoming fragmented IP packets" - default n - help - Enabling this option allows reassemblying incoming fragmented IP packets. - -config LWIP_IP_REASS_MAX_PBUFS - int "Total maximum amount of pbufs waiting to be reassembled" - default 10 - range 1 16 - -config LWIP_IP_SOF_BROADCAST - bool "Enable broadcast filter per pcb on udp and raw send operation" - default n - help - -config LWIP_IP_SOF_BROADCAST_RECV - bool "Enable the broadcast filter on recv operations" - default n - help - -menuconfig LWIP_ICMP - bool "ICMP" - default y - help - -config LWIP_MULTICAST_PING - bool "Respond to multicast pings" - default n - depends on LWIP_ICMP - -config LWIP_BROADCAST_PING - bool "Respond to broadcast pings" - default n - depends on LWIP_ICMP - -config LWIP_RAW - bool "Enable application layer to hook into the IP layer itself" - default n - -menu "DHCP" - -config LWIP_DHCP_DOES_ARP_CHECK - bool "DHCP: Perform ARP check on any offered address" - default y - help - Enabling this option performs a check (via ARP request) if the offered IP address - is not already in use by another host on the network. - -config LWIP_DHCP_MAX_NTP_SERVERS - int "Maximum number of NTP servers" - default 1 - range 1 8 - help - Set maximum number of NTP servers used by LwIP SNTP module. - First argument of sntp_setserver/sntp_setservername functions - is limited to this value. - -config LWIP_DHCPS_LEASE_UNIT - int "Multiplier for lease time, in seconds" - range 1 3600 - default 60 - help - The DHCP server is calculating lease time multiplying the sent - and received times by this number of seconds per unit. - The default is 60, that equals one minute. - -config LWIP_DHCPS_MAX_STATION_NUM - int "Maximum number of stations" - range 1 8 - default 8 - help - The maximum number of DHCP clients that are connected to the server. - After this number is exceeded, DHCP server removes of the oldest device - from it's address pool, without notification. - -endmenu #DHCP - -menuconfig LWIP_AUTOIP - bool "Enable IPV4 Link-Local Addressing (AUTOIP)" - default n - help - Enabling this option allows the device to self-assign an address - in the 169.256/16 range if none is assigned statically or via DHCP. - - See RFC 3927. - -config LWIP_DHCP_AUTOIP_COOP_TRIES - int "DHCP Probes before self-assigning IPv4 LL address" - range 1 100 - default 2 - depends on LWIP_AUTOIP - help - DHCP client will send this many probes before self-assigning a - link local address. - - From LWIP help: "This can be set as low as 1 to get an AutoIP - address very quickly, but you should be prepared to handle a - changing IP address when DHCP overrides AutoIP." - -config LWIP_AUTOIP_MAX_CONFLICTS - int "Max IP conflicts before rate limiting" - range 1 100 - default 9 - depends on LWIP_AUTOIP - help - If the AUTOIP functionality detects this many IP conflicts while - self-assigning an address, it will go into a rate limited mode. - -config LWIP_AUTOIP_RATE_LIMIT_INTERVAL - int "Rate limited interval (seconds)" - range 5 120 - default 20 - depends on LWIP_AUTOIP - help - If rate limiting self-assignment requests, wait this long between - each request. - -config LWIP_IGMP - bool "Enable IGMP module" - default y - -config DNS_MAX_SERVERS - int "The maximum of DNS servers" - range 1 5 - default 2 - -menuconfig LWIP_NETIF_LOOPBACK - bool "Enable per-interface loopback" - default n - help - Enabling this option means that if a packet is sent with a destination - address equal to the interface's own IP address, it will "loop back" and - be received by this interface. - -config LWIP_LOOPBACK_MAX_PBUFS - int "Max queued loopback packets per interface" - range 0 16 - default 0 - depends on LWIP_NETIF_LOOPBACK - help - Configure the maximum number of packets which can be queued for - loopback on a given interface. Reducing this number may cause packets - to be dropped, but will avoid filling memory with queued packet data. - -menu "TCP" - -config TCP_HIGH_SPEED_RETRANSMISSION - bool "TCP high speed retransmissions" - default n - help - "Enable this option, TCP retransmissions time will always be set to 500ms forcely." - -config LWIP_MAX_ACTIVE_TCP - int "Maximum active TCP Connections" - range 1 32 - default 5 - help - The maximum number of simultaneously active TCP - connections. The practical maximum limit is - determined by available heap memory at runtime. - - Changing this value by itself does not substantially - change the memory usage of LWIP, except for preventing - new TCP connections after the limit is reached. - -config LWIP_MAX_LISTENING_TCP - int "Maximum listening TCP Connections" - range 1 16 - default 8 - help - The maximum number of simultaneously listening TCP - connections. The practical maximum limit is - determined by available heap memory at runtime. - - Changing this value by itself does not substantially - change the memory usage of LWIP, except for preventing - new listening TCP connections after the limit is reached. - - -config TCP_MAXRTX - int "Maximum number of retransmissions of data segments" - default 12 - range 3 12 - help - Set maximum number of retransmissions of data segments. - -config TCP_SYNMAXRTX - int "Maximum number of retransmissions of SYN segments" - default 6 - range 3 12 - help - Set maximum number of retransmissions of SYN segments. - -config TCP_MSS - int "Maximum Segment Size (MSS)" - default 1460 - range 536 1460 - help - Set maximum segment size for TCP transmission. - - Can be set lower to save RAM, the default value 1436 will give best throughput. - -config TCP_SND_BUF_DEFAULT - int "Default send buffer size" - default 2920 # 2 * default MSS - range 2920 11680 - help - Set default send buffer size for new TCP sockets. - - Per-socket send buffer size can be changed at runtime - with lwip_setsockopt(s, TCP_SNDBUF, ...). - - This value must be at least 2x the MSS size, and the default - is 4x the default MSS size. - - Setting a smaller default SNDBUF size can save some RAM, but - will decrease performance. - -config TCP_WND_DEFAULT - int "Default receive window size" - default 5840 # 4 * default MSS - range 2920 14600 - help - Set default TCP receive window size for new TCP sockets. - - Per-socket receive window size can be changed at runtime - with lwip_setsockopt(s, TCP_WINDOW, ...). - - Setting a smaller default receive window size can save some RAM, - but will significantly decrease performance. - -config TCP_RECVMBOX_SIZE - int "Default TCP receive mail box size" - default 6 - range 6 32 - help - Set TCP receive mail box size. Generally bigger value means higher throughput - but more memory. The recommended value is: TCP_WND_DEFAULT/TCP_MSS + 2, e.g. if - TCP_WND_DEFAULT=14360, TCP_MSS=1436, then the recommended receive mail box size is - (14360/1436 + 2) = 12. - - TCP receive mail box is a per socket mail box, when the application receives packets - from TCP socket, LWIP core firstly posts the packets to TCP receive mail box and the - application then fetches the packets from mail box. It means LWIP can caches maximum - TCP_RECCVMBOX_SIZE packets for each TCP socket, so the maximum possible cached TCP packets - for all TCP sockets is TCP_RECCVMBOX_SIZE multiples the maximum TCP socket number. In other - words, the bigger TCP_RECVMBOX_SIZE means more memory. - On the other hand, if the receiv mail box is too small, the mail box may be full. If the - mail box is full, the LWIP drops the packets. So generally we need to make sure the TCP - receive mail box is big enough to avoid packet drop between LWIP core and application. - -config TCP_QUEUE_OOSEQ - bool "Queue incoming out-of-order segments" - default n - help - Queue incoming out-of-order segments for later use. - - Disable this option to save some RAM during TCP sessions, at the expense - of increased retransmissions if segments arrive out of order. - -choice TCP_OVERSIZE - prompt "Pre-allocate transmit PBUF size" - default TCP_OVERSIZE_MSS - help - Allows enabling "oversize" allocation of TCP transmission pbufs ahead of time, - which can reduce the length of pbuf chains used for transmission. - - This will not make a difference to sockets where Nagle's algorithm - is disabled. - - Default value of MSS is fine for most applications, 25% MSS may save - some RAM when only transmitting small amounts of data. Disabled will - have worst performance and fragmentation characteristics, but uses - least RAM overall. - -config TCP_OVERSIZE_MSS - bool "MSS" -config TCP_OVERSIZE_QUARTER_MSS - bool "25% MSS" -config TCP_OVERSIZE_DISABLE - bool "Disabled" - -endchoice - -config LWIP_TCP_TIMESTAMPS - bool "Support the TCP timestamp option" - default n - help - The timestamp option is currently only used to help remote hosts, it is not - really used locally. Therefore, it is only enabled when a TS option is - received in the initial SYN packet from a remote host. - -endmenu # TCP - -menu "UDP" - -config LWIP_MAX_UDP_PCBS - int "Maximum active UDP control blocks" - range 1 32 - default 4 - help - The maximum number of active UDP "connections" (ie - UDP sockets sending/receiving data). - The practical maximum limit is determined by available - heap memory at runtime. - -config UDP_RECVMBOX_SIZE - int "Default UDP receive mail box size" - default 6 - range 6 64 - help - Set UDP receive mail box size. The recommended value is 6. - - UDP receive mail box is a per socket mail box, when the application receives packets - from UDP socket, LWIP core firstly posts the packets to UDP receive mail box and the - application then fetches the packets from mail box. It means LWIP can caches maximum - UDP_RECCVMBOX_SIZE packets for each UDP socket, so the maximum possible cached UDP packets - for all UDP sockets is UDP_RECCVMBOX_SIZE multiples the maximum UDP socket number. In other - words, the bigger UDP_RECVMBOX_SIZE means more memory. - On the other hand, if the receiv mail box is too small, the mail box may be full. If the - mail box is full, the LWIP drops the packets. So generally we need to make sure the UDP - receive mail box is big enough to avoid packet drop between LWIP core and application. - -endmenu # UDP - -config TCPIP_TASK_STACK_SIZE - int "TCP/IP Task Stack Size" - default 2048 - range 2048 8192 - help - Configure TCP/IP task stack size, used by LWIP to process multi-threaded TCP/IP operations. - Setting this stack too small will result in stack overflow crashes. - -menu "LWIP RAW API" - -config LWIP_MAX_RAW_PCBS - int "Maximum LWIP RAW PCBs" - range 1 32 - default 4 - help - The maximum number of simultaneously active LWIP - RAW protocol control blocks. The practical maximum - limit is determined by available heap memory at runtime. - -endmenu # LWIP RAW API - -menuconfig LWIP_IPV6 - bool "Enable IPv6" - default n - -config LWIP_IPV6_NUM_ADDRESSES - int "Number of IPv6 addresses per netif" - depends on LWIP_IPV6 - range 3 5 - default 3 - -config LWIP_IPV6_FORWARD - bool "Forward IPv6 packets across netifs" - depends on LWIP_IPV6 - default n - -config LWIP_IPV6_FRAG - bool "Fragment outgoing IPv6 packets that are too big" - depends on LWIP_IPV6 - default n - -config LWIP_ND6_RDNSS_MAX_DNS_SERVERS - bool "The IPv6 ND6 RDNSS max DNS servers" - depends on LWIP_IPV6 - default n - help - Use IPv6 Router Advertisement Recursive DNS Server Option (as per RFC 6106) - to copy a defined maximum number of DNS servers to the DNS module - -config LWIP_STATS - bool "Enable statistics collection in lwip_stats" - default n - -config ESP_LWIP_MEM_DBG - bool "Enable LWIP memory debug" - default n - help - Enable this option, LWIP allocated memory information can be traced by "heap" components. - - User can call "heap_trace_start(HEAP_TRACE_LEAKS)" to start tracing and call "heap_trace_dump()" - to list the memory map. - -menuconfig LWIP_DEBUG - bool "Enable lwip Debug" - default n - -config LWIP_ETHARP_DEBUG - bool "Enable debugging in etharp.c" - depends on LWIP_DEBUG - default n - -config LWIP_NETIF_DEBUG - bool "Enable debugging in netif.c" - depends on LWIP_DEBUG - default n - -config LWIP_PBUF_DEBUG - bool "Enable debugging in pbuf.c" - depends on LWIP_DEBUG - default n - -config LWIP_API_LIB_DEBUG - bool "Enable debugging in api_lib.c" - depends on LWIP_DEBUG - default n - -config LWIP_API_MSG_DEBUG - bool "Enable debugging in api_msg.c" - depends on LWIP_DEBUG - default n - -config LWIP_SOCKETS_DEBUG - bool "Enable debugging in sockets.c" - depends on LWIP_DEBUG - default n - -config LWIP_ICMP_DEBUG - bool "Enable debugging in icmp.c" - depends on LWIP_DEBUG - default n - -config LWIP_IGMP_DEBUG - bool "Enable debugging in igmp.c" - depends on LWIP_DEBUG - default n - -config LWIP_INET_DEBUG - bool "Enable debugging in inet.c" - depends on LWIP_DEBUG - default n - -config LWIP_ETHERNETIF_DEBUG - bool "Enable debugging in ethernetif.c" - depends on LWIP_DEBUG - default n - -config LWIP_IP_DEBUG - bool "Enable debugging for IP" - depends on LWIP_DEBUG - default n - -config LWIP_IP_REASS_DEBUG - bool "Enable debugging in ip_frag.c for both frag & reass" - depends on LWIP_DEBUG - default n - -config LWIP_RAW_DEBUG - bool "Enable debugging in raw.c" - depends on LWIP_DEBUG - default n - -config LWIP_MEM_DEBUG - bool "Enable debugging in mem.c" - depends on LWIP_DEBUG - default n - -config LWIP_MEMP_DEBUG - bool "Enable debugging in memp.c" - depends on LWIP_DEBUG - default n - -config LWIP_SYS_DEBUG - bool "Enable debugging in sys.c" - depends on LWIP_DEBUG - default n - -config LWIP_TIMERS_DEBUG - bool "Enable debugging in timers.c" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_DEBUG - bool "Enable debugging for TCP" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_INPUT_DEBUG - bool "Enable debugging in tcp_in.c for incoming debug" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_FR_DEBUG - bool "Enable debugging in tcp_in.c for fast retransmit" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_RTO_DEBUG - bool "Enable debugging in TCP for retransmit" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_CWND_DEBUG - bool "Enable debugging for TCP congestion window" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_WND_DEBUG - bool "Enable debugging in tcp_in.c for window updating" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_OUTPUT_DEBUG - bool "Enable debugging in tcp_out.c output functions" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_RST_DEBUG - bool "Enable debugging for TCP with the RST message" - depends on LWIP_DEBUG - default n - -config LWIP_TCP_QLEN_DEBUG - bool "Enable debugging for TCP queue lengths" - depends on LWIP_DEBUG - default n - -config LWIP_UDP_DEBUG - bool "Enable debugging in UDP" - depends on LWIP_DEBUG - default n - -config LWIP_TCPIP_DEBUG - bool "Enable debugging in tcpip.c" - depends on LWIP_DEBUG - default n - -config LWIP_SLIP_DEBUG - bool "Enable debugging in slipif.c" - depends on LWIP_DEBUG - default n - -config LWIP_DHCP_DEBUG - bool "Enable debugging in dhcp.c" - depends on LWIP_DEBUG - default n - -config LWIP_DHCP_SERVER_DEBUG - bool "Enable debugging in dhcpserver.c" - depends on LWIP_DEBUG - default n - -config LWIP_AUTOIP_DEBUG - bool "Enable debugging in autoip.c" - depends on LWIP_DEBUG - default n - -config LWIP_DNS_DEBUG - bool "Enable debugging for DNS" - depends on LWIP_DEBUG - default n - -config LWIP_IP6_DEBUG - bool "Enable debugging for IPv6" - depends on LWIP_DEBUG - default n - -config LWIP_SNTP_DEBUG - bool "Enable debugging for SNTP." - depends on LWIP_DEBUG - default n - -config LWIP_THREAD_SAFE_DEBUG - bool "Enable debugging for LWIP thread safety." - depends on LWIP_DEBUG - default n - -config LWIP_PBUF_CACHE_DEBUG - bool "Enable debugging for LWIP pbuf cache." - depends on LWIP_DEBUG - default n - -endmenu + config LWIP_LOCAL_HOSTNAME + string "Local netif hostname" + default 'espressif' + help + The name this device will report to other devices on the network + + config LWIP_DNS_SUPPORT_MDNS_QUERIES + bool "Enable mDNS queries in resolving host name" + default y + help + If this feature is enabled, standard API such as gethostbyname + support .local addresses by sending one shot multicast mDNS + query + + config LWIP_L2_TO_L3_COPY + bool "Enable copy between Layer2 and Layer3 packets" + default n + help + If this feature is enabled, all traffic from layer2(WIFI Driver) will be + copied to a new buffer before sending it to layer3(LWIP stack), freeing + the layer2 buffer. + Please be notified that the total layer2 receiving buffer is fixed and + ESP32 currently supports 25 layer2 receiving buffer, when layer2 buffer + runs out of memory, then the incoming packets will be dropped in hardware. + The layer3 buffer is allocated from the heap, so the total layer3 receiving + buffer depends on the available heap size, when heap runs out of memory, + no copy will be sent to layer3 and packet will be dropped in layer2. + Please make sure you fully understand the impact of this feature before + enabling it. + + config LWIP_IRAM_OPTIMIZATION + bool "Enable LWIP IRAM optimization" + default n + help + If this feature is enabled, some functions relating to RX/TX in LWIP will be + put into IRAM, it can improve UDP/TCP throughput by >10% for single core mode, + it doesn't help too much for dual core mode. On the other hand, it needs about + 10KB IRAM for these optimizations. + + If this feature is disabled, all lwip functions will be put into FLASH. + + config LWIP_TIMERS_ONDEMAND + bool "Enable LWIP Timers on demand" + default y + help + If this feature is enabled, IGMP and MLD6 timers will be activated only + when joining groups or receiving QUERY packets. + + This feature will reduce the power consumption for applications which do not + use IGMP and MLD6. + + config LWIP_MAX_SOCKETS + int "Max number of open sockets" + range 1 16 + default 10 + help + Sockets take up a certain amount of memory, and allowing fewer + sockets to be open at the same time conserves memory. Specify + the maximum amount of sockets here. The valid value is from 1 + to 16. + + config LWIP_USE_ONLY_LWIP_SELECT + bool "Support LWIP socket select() only" + default n + help + The virtual filesystem layer of select() redirects sockets to + lwip_select() and non-socket file descriptors to their respective driver + implementations. If this option is enabled then all calls of select() + will be redirected to lwip_select(), therefore, select can be used + for sockets only. + + config LWIP_SO_LINGER + bool "Enable SO_LINGER processing" + default n + help + Enabling this option allows SO_LINGER processing. + l_onoff = 1,l_linger can set the timeout. + + If l_linger=0, When a connection is closed, TCP will terminate the connection. + This means that TCP will discard any data packets stored in the socket send buffer + and send an RST to the peer. + + If l_linger!=0,Then closesocket() calls to block the process until + the remaining data packets has been sent or timed out. + + config LWIP_SO_REUSE + bool "Enable SO_REUSEADDR option" + default y + help + Enabling this option allows binding to a port which remains in + TIME_WAIT. + + config LWIP_SO_REUSE_RXTOALL + bool "SO_REUSEADDR copies broadcast/multicast to all matches" + depends on LWIP_SO_REUSE + default y + help + Enabling this option means that any incoming broadcast or multicast + packet will be copied to all of the local sockets that it matches + (may be more than one if SO_REUSEADDR is set on the socket.) + + This increases memory overhead as the packets need to be copied, + however they are only copied per matching socket. You can safely + disable it if you don't plan to receive broadcast or multicast + traffic on more than one socket at a time. + + config LWIP_SO_RCVBUF + bool "Enable SO_RCVBUF option" + default n + help + Enabling this option allows checking for available data on a netconn. + + config LWIP_NETBUF_RECVINFO + bool "Enable IP_PKTINFO option" + default n + help + Enabling this option allows checking for the destination address + of a received IPv4 Packet. + + config LWIP_IP4_FRAG + bool "Enable fragment outgoing IP4 packets" + default y + help + Enabling this option allows fragmenting outgoing IP4 packets if their size + exceeds MTU. + + config LWIP_IP6_FRAG + bool "Enable fragment outgoing IP6 packets" + default y + help + Enabling this option allows fragmenting outgoing IP6 packets if their size + exceeds MTU. + + config LWIP_IP4_REASSEMBLY + bool "Enable reassembly incoming fragmented IP4 packets" + default n + help + Enabling this option allows reassemblying incoming fragmented IP4 packets. + + config LWIP_IP6_REASSEMBLY + bool "Enable reassembly incoming fragmented IP6 packets" + default n + help + Enabling this option allows reassemblying incoming fragmented IP6 packets. + + config LWIP_IP_FORWARD + bool "Enable IP forwarding" + default n + help + Enabling this option allows packets forwarding across multiple interfaces. + + config LWIP_IPV4_NAPT + bool "Enable NAT (new/experimental)" + depends on LWIP_IP_FORWARD + select LWIP_L2_TO_L3_COPY + default n + help + Enabling this option allows Network Address and Port Translation. + + config LWIP_STATS + bool "Enable LWIP statistics" + default n + help + Enabling this option allows LWIP statistics + + config LWIP_ETHARP_TRUST_IP_MAC + bool "Enable LWIP ARP trust" + default n + help + Enabling this option allows ARP table to be updated. + + If this option is enabled, the incoming IP packets cause the ARP table to be + updated with the source MAC and IP addresses supplied in the packet. + You may want to disable this if you do not trust LAN peers to have the + correct addresses, or as a limited approach to attempt to handle + spoofing. If disabled, lwIP will need to make a new ARP request if + the peer is not already in the ARP table, adding a little latency. + The peer *is* in the ARP table if it requested our address before. + Also notice that this slows down input processing of every IP packet! + + There are two known issues in real application if this feature is enabled: + - The LAN peer may have bug to update the ARP table after the ARP entry is aged out. + If the ARP entry on the LAN peer is aged out but failed to be updated, all IP packets + sent from LWIP to the LAN peer will be dropped by LAN peer. + - The LAN peer may not be trustful, the LAN peer may send IP packets to LWIP with + two different MACs, but the same IP address. If this happens, the LWIP has problem + to receive IP packets from LAN peer. + + So the recommendation is to disable this option. + Here the LAN peer means the other side to which the ESP station or soft-AP is connected. + + config LWIP_ESP_GRATUITOUS_ARP + bool "Send gratuitous ARP periodically" + default y + help + Enable this option allows to send gratuitous ARP periodically. + + This option solve the compatibility issues.If the ARP table of the AP is old, and the AP + doesn't send ARP request to update it's ARP table, this will lead to the STA sending IP packet fail. + Thus we send gratuitous ARP periodically to let AP update it's ARP table. + + config LWIP_GARP_TMR_INTERVAL + int "GARP timer interval(seconds)" + default 60 + depends on LWIP_ESP_GRATUITOUS_ARP + help + Set the timer interval for gratuitous ARP. The default value is 60s + + config LWIP_TCPIP_RECVMBOX_SIZE + int "TCPIP task receive mail box size" + default 32 + range 6 64 if !LWIP_WND_SCALE + range 6 1024 if LWIP_WND_SCALE + help + Set TCPIP task receive mail box size. Generally bigger value means higher throughput + but more memory. The value should be bigger than UDP/TCP mail box size. + + config LWIP_DHCP_DOES_ARP_CHECK + bool "DHCP: Perform ARP check on any offered address" + default y + help + Enabling this option performs a check (via ARP request) if the offered IP address + is not already in use by another host on the network. + + config LWIP_DHCP_RESTORE_LAST_IP + bool "DHCP: Restore last IP obtained from DHCP server" + default n + help + When this option is enabled, DHCP client tries to re-obtain last valid IP address obtained from DHCP + server. Last valid DHCP configuration is stored in nvs and restored after reset/power-up. If IP is still + available, there is no need for sending discovery message to DHCP server and save some time. + + menu "DHCP server" + + config LWIP_DHCPS_LEASE_UNIT + int "Multiplier for lease time, in seconds" + range 1 3600 + default 60 + help + The DHCP server is calculating lease time multiplying the sent + and received times by this number of seconds per unit. + The default is 60, that equals one minute. + + config LWIP_DHCPS_MAX_STATION_NUM + int "Maximum number of stations" + range 1 64 + default 8 + help + The maximum number of DHCP clients that are connected to the server. + After this number is exceeded, DHCP server removes of the oldest device + from it's address pool, without notification. + + endmenu # DHCPS + + menuconfig LWIP_AUTOIP + bool "Enable IPV4 Link-Local Addressing (AUTOIP)" + default n + help + Enabling this option allows the device to self-assign an address + in the 169.256/16 range if none is assigned statically or via DHCP. + + See RFC 3927. + + config LWIP_AUTOIP_TRIES + int "DHCP Probes before self-assigning IPv4 LL address" + range 1 100 + default 2 + depends on LWIP_AUTOIP + help + DHCP client will send this many probes before self-assigning a + link local address. + + From LWIP help: "This can be set as low as 1 to get an AutoIP + address very quickly, but you should be prepared to handle a + changing IP address when DHCP overrides AutoIP." (In the case of + ESP-IDF, this means multiple SYSTEM_EVENT_STA_GOT_IP events.) + + config LWIP_AUTOIP_MAX_CONFLICTS + int "Max IP conflicts before rate limiting" + range 1 100 + default 9 + depends on LWIP_AUTOIP + help + If the AUTOIP functionality detects this many IP conflicts while + self-assigning an address, it will go into a rate limited mode. + + config LWIP_AUTOIP_RATE_LIMIT_INTERVAL + int "Rate limited interval (seconds)" + range 5 120 + default 20 + depends on LWIP_AUTOIP + help + If rate limiting self-assignment requests, wait this long between + each request. + + config LWIP_IPV6_AUTOCONFIG + bool "Enable IPV6 stateless address autoconfiguration" + default n + help + Enabling this option allows the devices to IPV6 stateless address autoconfiguration. + + See RFC 4862. + + menuconfig LWIP_NETIF_LOOPBACK + bool "Support per-interface loopback" + default y + help + Enabling this option means that if a packet is sent with a destination + address equal to the interface's own IP address, it will "loop back" and + be received by this interface. + + config LWIP_LOOPBACK_MAX_PBUFS + int "Max queued loopback packets per interface" + range 0 16 + default 8 + depends on LWIP_NETIF_LOOPBACK + help + Configure the maximum number of packets which can be queued for + loopback on a given interface. Reducing this number may cause packets + to be dropped, but will avoid filling memory with queued packet data. + + menu "TCP" + + config LWIP_MAX_ACTIVE_TCP + int "Maximum active TCP Connections" + range 1 1024 + default 16 + help + The maximum number of simultaneously active TCP + connections. The practical maximum limit is + determined by available heap memory at runtime. + + Changing this value by itself does not substantially + change the memory usage of LWIP, except for preventing + new TCP connections after the limit is reached. + + config LWIP_MAX_LISTENING_TCP + int "Maximum listening TCP Connections" + range 1 1024 + default 16 + help + The maximum number of simultaneously listening TCP + connections. The practical maximum limit is + determined by available heap memory at runtime. + + Changing this value by itself does not substantially + change the memory usage of LWIP, except for preventing + new listening TCP connections after the limit is reached. + + + config LWIP_TCP_MAXRTX + int "Maximum number of retransmissions of data segments" + default 12 + range 3 12 + help + Set maximum number of retransmissions of data segments. + + config LWIP_TCP_SYNMAXRTX + int "Maximum number of retransmissions of SYN segments" + default 6 + range 3 12 + help + Set maximum number of retransmissions of SYN segments. + + config LWIP_TCP_MSS + int "Maximum Segment Size (MSS)" + default 1440 + range 536 1460 + help + Set maximum segment size for TCP transmission. + + Can be set lower to save RAM, the default value 1460(ipv4)/1440(ipv6) will give best throughput. + IPv4 TCP_MSS Range: 576 <= TCP_MSS <= 1460 + IPv6 TCP_MSS Range: 1220<= TCP_mSS <= 1440 + + config LWIP_TCP_TMR_INTERVAL + int "TCP timer interval(ms)" + default 250 + help + Set TCP timer interval in milliseconds. + + Can be used to speed connections on bad networks. + A lower value will redeliver unacked packets faster. + + config LWIP_TCP_MSL + int "Maximum segment lifetime (MSL)" + default 60000 + help + Set maximum segment lifetime in in milliseconds. + + config LWIP_TCP_SND_BUF_DEFAULT + int "Default send buffer size" + default 2880 # 2 * default MSS + range 2440 65535 if !LWIP_WND_SCALE + range 2440 1024000 if LWIP_WND_SCALE + help + Set default send buffer size for new TCP sockets. + + Per-socket send buffer size can be changed at runtime + with lwip_setsockopt(s, TCP_SNDBUF, ...). + + This value must be at least 2x the MSS size, and the default + is 2x the default MSS size. + + Setting a smaller default SNDBUF size can save some RAM, but + will decrease performance. + + config LWIP_TCP_WND_DEFAULT + int "Default receive window size" + default 5760 # 4 * default MSS + range 2440 65535 if !LWIP_WND_SCALE + range 2440 1024000 if LWIP_WND_SCALE + help + Set default TCP receive window size for new TCP sockets. + + Per-socket receive window size can be changed at runtime + with lwip_setsockopt(s, TCP_WINDOW, ...). + + Setting a smaller default receive window size can save some RAM, + but will significantly decrease performance. + + config LWIP_TCP_RECVMBOX_SIZE + int "Default TCP receive mail box size" + default 6 + range 6 64 if !LWIP_WND_SCALE + range 6 1024 if LWIP_WND_SCALE + help + Set TCP receive mail box size. Generally bigger value means higher throughput + but more memory. The recommended value is: LWIP_TCP_WND_DEFAULT/TCP_MSS + 2, e.g. if + LWIP_TCP_WND_DEFAULT=14440, TCP_MSS=1440, then the recommended receive mail box size is + (14440/1440 + 2) = 12. + + TCP receive mail box is a per socket mail box, when the application receives packets + from TCP socket, LWIP core firstly posts the packets to TCP receive mail box and the + application then fetches the packets from mail box. It means LWIP can caches maximum + LWIP_TCP_RECCVMBOX_SIZE packets for each TCP socket, so the maximum possible cached TCP packets + for all TCP sockets is LWIP_TCP_RECCVMBOX_SIZE multiples the maximum TCP socket number. In other + words, the bigger LWIP_TCP_RECVMBOX_SIZE means more memory. + On the other hand, if the receiv mail box is too small, the mail box may be full. If the + mail box is full, the LWIP drops the packets. So generally we need to make sure the TCP + receive mail box is big enough to avoid packet drop between LWIP core and application. + + config LWIP_TCP_QUEUE_OOSEQ + bool "Queue incoming out-of-order segments" + default y + help + Queue incoming out-of-order segments for later use. + + Disable this option to save some RAM during TCP sessions, at the expense + of increased retransmissions if segments arrive out of order. + + config LWIP_TCP_SACK_OUT + bool "Support sending selective acknowledgements" + default n + help + TCP will support sending selective acknowledgements (SACKs). + + config LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES + bool "Keep TCP connections when IP changed" + default n + help + This option is enabled when the following scenario happen: + network dropped and reconnected, IP changes is like: 192.168.0.2->0.0.0.0->192.168.0.2 + + Disable this option to keep consistent with the original LWIP code behavior. + + + choice LWIP_TCP_OVERSIZE + prompt "Pre-allocate transmit PBUF size" + default LWIP_TCP_OVERSIZE_MSS + help + Allows enabling "oversize" allocation of TCP transmission pbufs ahead of time, + which can reduce the length of pbuf chains used for transmission. + + This will not make a difference to sockets where Nagle's algorithm + is disabled. + + Default value of MSS is fine for most applications, 25% MSS may save + some RAM when only transmitting small amounts of data. Disabled will + have worst performance and fragmentation characteristics, but uses + least RAM overall. + + config LWIP_TCP_OVERSIZE_MSS + bool "MSS" + config LWIP_TCP_OVERSIZE_QUARTER_MSS + bool "25% MSS" + config LWIP_TCP_OVERSIZE_DISABLE + bool "Disabled" + + endchoice + + config LWIP_WND_SCALE + bool "Support TCP window scale" + depends on SPIRAM_TRY_ALLOCATE_WIFI_LWIP + default n + help + Enable this feature to support TCP window scaling. + + config LWIP_TCP_RCV_SCALE + int "Set TCP receiving window scaling factor" + depends on LWIP_WND_SCALE + range 0 14 + default 0 + help + Enable this feature to support TCP window scaling. + + config LWIP_TCP_RTO_TIME + int "Default TCP rto time" + default 3000 + help + Set default TCP rto time for a reasonable initial rto. + In bad network environment, recommend set value of rto time to 1500. + + endmenu # TCP + + menu "UDP" + + config LWIP_MAX_UDP_PCBS + int "Maximum active UDP control blocks" + range 1 1024 + default 16 + help + The maximum number of active UDP "connections" (ie + UDP sockets sending/receiving data). + The practical maximum limit is determined by available + heap memory at runtime. + + config LWIP_UDP_RECVMBOX_SIZE + int "Default UDP receive mail box size" + default 6 + range 6 64 + help + Set UDP receive mail box size. The recommended value is 6. + + UDP receive mail box is a per socket mail box, when the application receives packets + from UDP socket, LWIP core firstly posts the packets to UDP receive mail box and the + application then fetches the packets from mail box. It means LWIP can caches maximum + UDP_RECCVMBOX_SIZE packets for each UDP socket, so the maximum possible cached UDP packets + for all UDP sockets is UDP_RECCVMBOX_SIZE multiples the maximum UDP socket number. In other + words, the bigger UDP_RECVMBOX_SIZE means more memory. + On the other hand, if the receiv mail box is too small, the mail box may be full. If the + mail box is full, the LWIP drops the packets. So generally we need to make sure the UDP + receive mail box is big enough to avoid packet drop between LWIP core and application. + + endmenu # UDP + + config LWIP_TCPIP_TASK_STACK_SIZE + int "TCP/IP Task Stack Size" + default 2048 + # for high log levels, tcpip_adapter API calls can end up + # a few calls deep and logging there can trigger a stack overflow + range 2048 65536 if LOG_DEFAULT_LEVEL < 4 + range 2560 65536 if LOG_DEFAULT_LEVEL >= 4 + help + Configure TCP/IP task stack size, used by LWIP to process multi-threaded TCP/IP operations. + Setting this stack too small will result in stack overflow crashes. + + choice LWIP_TCPIP_TASK_AFFINITY + prompt "TCP/IP task affinity" + default LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY + help + Allows setting LwIP tasks affinity, i.e. whether the task is pinned to + CPU0, pinned to CPU1, or allowed to run on any CPU. + Currently this applies to "TCP/IP" task and "Ping" task. + + config LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY + bool "No affinity" + config LWIP_TCPIP_TASK_AFFINITY_CPU0 + bool "CPU0" + config LWIP_TCPIP_TASK_AFFINITY_CPU1 + bool "CPU1" + depends on !FREERTOS_UNICORE + + endchoice + + config LWIP_TCPIP_TASK_AFFINITY + hex + default FREERTOS_NO_AFFINITY if LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY + default 0x0 if LWIP_TCPIP_TASK_AFFINITY_CPU0 + default 0x1 if LWIP_TCPIP_TASK_AFFINITY_CPU1 + + + menuconfig LWIP_PPP_SUPPORT + bool "Enable PPP support (new/experimental)" + default n + help + Enable PPP stack. Now only PPP over serial is possible. + + PPP over serial support is experimental and unsupported. + + config LWIP_PPP_ENABLE_IPV6 + bool "Enable IPV6 support for PPP connections (IPV6CP)" + depends on LWIP_PPP_SUPPORT && LWIP_IPV6 + default y + help + Enable IPV6 support in PPP for the local link between the DTE (processor) and DCE (modem). + There are some modems which do not support the IPV6 addressing in the local link. + If they are requested for IPV6CP negotiation, they may time out. + This would in turn fail the configuration for the whole link. + If your modem is not responding correctly to PPP Phase Network, try to disable IPV6 support. + + config LWIP_IPV6_MEMP_NUM_ND6_QUEUE + int "Max number of IPv6 packets to queue during MAC resolution" + range 3 20 + default 3 + help + Config max number of IPv6 packets to queue during MAC resolution. + + config LWIP_IPV6_ND6_NUM_NEIGHBORS + int "Max number of entries in IPv6 neighbor cache" + range 3 10 + default 5 + help + Config max number of entries in IPv6 neighbor cache + + config LWIP_PPP_NOTIFY_PHASE_SUPPORT + bool "Enable Notify Phase Callback" + depends on LWIP_PPP_SUPPORT + default n + help + Enable to set a callback which is called on change of the internal PPP state machine. + + config LWIP_PPP_PAP_SUPPORT + bool "Enable PAP support" + depends on LWIP_PPP_SUPPORT + default n + help + Enable Password Authentication Protocol (PAP) support + + config LWIP_PPP_CHAP_SUPPORT + bool "Enable CHAP support" + depends on LWIP_PPP_SUPPORT + default n + help + Enable Challenge Handshake Authentication Protocol (CHAP) support + + config LWIP_PPP_MSCHAP_SUPPORT + bool "Enable MSCHAP support" + depends on LWIP_PPP_SUPPORT + default n + help + Enable Microsoft version of the Challenge-Handshake Authentication Protocol (MSCHAP) support + + config LWIP_PPP_MPPE_SUPPORT + bool "Enable MPPE support" + depends on LWIP_PPP_SUPPORT + default n + help + Enable Microsoft Point-to-Point Encryption (MPPE) support + + config LWIP_PPP_DEBUG_ON + bool "Enable PPP debug log output" + depends on LWIP_PPP_SUPPORT + default n + help + Enable PPP debug log output + + menu "ICMP" + + config LWIP_MULTICAST_PING + bool "Respond to multicast pings" + default n + + config LWIP_BROADCAST_PING + bool "Respond to broadcast pings" + default n + + endmenu # ICMP + + menu "LWIP RAW API" + + config LWIP_MAX_RAW_PCBS + int "Maximum LWIP RAW PCBs" + range 1 1024 + default 16 + help + The maximum number of simultaneously active LWIP + RAW protocol control blocks. The practical maximum + limit is determined by available heap memory at runtime. + + endmenu # LWIP RAW API + + config LWIP_IPV6 + bool "Enable IPv6" + default n + help + Enable IPV6 + + menu "SNTP" + + config LWIP_DHCP_MAX_NTP_SERVERS + int "Maximum number of NTP servers" + default 1 + range 1 16 + help + Set maximum number of NTP servers used by LwIP SNTP module. + First argument of sntp_setserver/sntp_setservername functions + is limited to this value. + + config LWIP_SNTP_UPDATE_DELAY + int "Request interval to update time (ms)" + range 15000 4294967295 + default 3600000 + help + This option allows you to set the time update period via SNTP. + Default is 1 hour. Must not be below 15 seconds by specification. + (SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds). + + endmenu # SNTP + + config LWIP_ESP_LWIP_ASSERT + bool "Enable LWIP ASSERT checks" + default y + help + Enable this option allows lwip to check assert. + It is recommended to keep it open, do not close it. + + menuconfig LWIP_DEBUG + bool "Enable lwip Debug" + default n + + config LWIP_ETHARP_DEBUG + bool "Enable debugging in etharp.c" + depends on LWIP_DEBUG + default n + + config LWIP_NETIF_DEBUG + bool "Enable debugging in netif.c" + depends on LWIP_DEBUG + default n + + config LWIP_PBUF_DEBUG + bool "Enable debugging in pbuf.c" + depends on LWIP_DEBUG + default n + + config LWIP_API_LIB_DEBUG + bool "Enable debugging in api_lib.c" + depends on LWIP_DEBUG + default n + + config LWIP_API_MSG_DEBUG + bool "Enable debugging in api_msg.c" + depends on LWIP_DEBUG + default n + + config LWIP_SOCKETS_DEBUG + bool "Enable debugging in sockets.c" + depends on LWIP_DEBUG + default n + + config LWIP_ICMP_DEBUG + bool "Enable debugging in icmp.c" + depends on LWIP_DEBUG + default n + + config LWIP_IGMP_DEBUG + bool "Enable debugging in igmp.c" + depends on LWIP_DEBUG + default n + + config LWIP_INET_DEBUG + bool "Enable debugging in inet.c" + depends on LWIP_DEBUG + default n + + config LWIP_ETHERNETIF_DEBUG + bool "Enable debugging in ethernetif.c" + depends on LWIP_DEBUG + default n + + config LWIP_IP_DEBUG + bool "Enable debugging for IP" + depends on LWIP_DEBUG + default n + + config LWIP_IP_REASS_DEBUG + bool "Enable debugging in ip_frag.c for both frag & reass" + depends on LWIP_DEBUG + default n + + config LWIP_RAW_DEBUG + bool "Enable debugging in raw.c" + depends on LWIP_DEBUG + default n + + config LWIP_MEM_DEBUG + bool "Enable debugging in mem.c" + depends on LWIP_DEBUG + default n + + config LWIP_MEMP_DEBUG + bool "Enable debugging in memp.c" + depends on LWIP_DEBUG + default n + + config LWIP_SYS_DEBUG + bool "Enable debugging in sys.c" + depends on LWIP_DEBUG + default n + + config LWIP_TIMERS_DEBUG + bool "Enable debugging in timers.c" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_DEBUG + bool "Enable debugging for TCP" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_INPUT_DEBUG + bool "Enable debugging in tcp_in.c for incoming debug" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_FR_DEBUG + bool "Enable debugging in tcp_in.c for fast retransmit" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_RTO_DEBUG + bool "Enable debugging in TCP for retransmit" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_CWND_DEBUG + bool "Enable debugging for TCP congestion window" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_WND_DEBUG + bool "Enable debugging in tcp_in.c for window updating" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_OUTPUT_DEBUG + bool "Enable debugging in tcp_out.c output functions" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_RST_DEBUG + bool "Enable debugging for TCP with the RST message" + depends on LWIP_DEBUG + default n + + config LWIP_TCP_QLEN_DEBUG + bool "Enable debugging for TCP queue lengths" + depends on LWIP_DEBUG + default n + + config LWIP_UDP_DEBUG + bool "Enable debugging in UDP" + depends on LWIP_DEBUG + default n + + config LWIP_TCPIP_DEBUG + bool "Enable debugging in tcpip.c" + depends on LWIP_DEBUG + default n + + config LWIP_SLIP_DEBUG + bool "Enable debugging in slipif.c" + depends on LWIP_DEBUG + default n + + config LWIP_DHCP_DEBUG + bool "Enable debugging in dhcp.c" + depends on LWIP_DEBUG + default n + + config LWIP_DHCP_SERVER_DEBUG + bool "Enable debugging in dhcpserver.c" + depends on LWIP_DEBUG + default n + + config LWIP_AUTOIP_DEBUG + bool "Enable debugging in autoip.c" + depends on LWIP_DEBUG + default n + + config LWIP_DNS_DEBUG + bool "Enable debugging for DNS" + depends on LWIP_DEBUG + default n + + config LWIP_IP6_DEBUG + bool "Enable debugging for IPv6" + depends on LWIP_DEBUG + default n + + config LWIP_SNTP_DEBUG + bool "Enable debugging for SNTP." + depends on LWIP_DEBUG + default n + + config LWIP_THREAD_SAFE_DEBUG + bool "Enable debugging for LWIP thread safety." + depends on LWIP_DEBUG + default n + + config LWIP_PBUF_CACHE_DEBUG + bool "Enable debugging for LWIP pbuf cache." + depends on LWIP_DEBUG + default n + + config LWIP_TCP_TXRX_PBUF_DEBUG + bool "Enable debugging for TCP TX/RX data." + depends on LWIP_DEBUG + default n + + endmenu diff --git a/components/lwip/apps/dhcpserver/dhcpserver.c b/components/lwip/apps/dhcpserver/dhcpserver.c index be20ea867..64e78a325 100644 --- a/components/lwip/apps/dhcpserver/dhcpserver.c +++ b/components/lwip/apps/dhcpserver/dhcpserver.c @@ -1,4 +1,4 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,27 +11,21 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -#include +//#include "esp_common.h" +#include #include -#include - -#include "esp_libc.h" -#include "esp_wifi.h" - -#include "rom/ets_sys.h" - -#include "sdkconfig.h" #include "lwip/inet.h" #include "lwip/err.h" #include "lwip/pbuf.h" #include "lwip/udp.h" #include "lwip/mem.h" -#include "lwip/timeouts.h" +#include "lwip/ip_addr.h" +#include "tcpip_adapter.h" + #include "dhcpserver/dhcpserver.h" #include "dhcpserver/dhcpserver_options.h" -#include "FreeRTOS.h" +#if ESP_DHCP #define BOOTP_BROADCAST 0x8000 @@ -87,12 +81,19 @@ typedef struct _list_node { static const u32_t magic_cookie = 0x63538263; -static struct udp_pcb *pcb_dhcps = NULL; +static struct netif *dhcps_netif = NULL; static ip4_addr_t broadcast_dhcps; static ip4_addr_t server_address; static ip4_addr_t dns_server = {0}; static ip4_addr_t client_address; //added static ip4_addr_t client_address_plus; +static ip4_addr_t s_dhcps_mask = { +#ifdef USE_CLASS_B_NET + .addr = PP_HTONL(LWIP_MAKEU32(255, 240, 0, 0)) +#else + .addr = PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0)) +#endif + }; static list_node *plist = NULL; static bool renew = false; @@ -142,7 +143,12 @@ void *dhcps_option_info(u8_t op_id, u32_t opt_len) } break; + case SUBNET_MASK: + if (opt_len == sizeof(s_dhcps_mask)) { + option_arg = &s_dhcps_mask; + } + break; default: break; } @@ -191,6 +197,12 @@ void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len) } break; + case SUBNET_MASK: + if (opt_len == sizeof(s_dhcps_mask)) { + s_dhcps_mask = *(ip4_addr_t *)opt_info; + } + + default: break; } @@ -259,11 +271,13 @@ void node_remove_from_list(list_node **phead, list_node *pdelete) *phead = NULL; } else { if (plist == pdelete) { - *phead = plist->pnext; + // Note: Ignoring the "use after free" warnings, as it could only happen + // if the linked list contains loops + *phead = plist->pnext; // NOLINT(clang-analyzer-unix.Malloc) pdelete->pnext = NULL; } else { while (plist != NULL) { - if (plist->pnext == pdelete) { + if (plist->pnext == pdelete) { // NOLINT(clang-analyzer-unix.Malloc) plist->pnext = pdelete->pnext; pdelete->pnext = NULL; } @@ -300,21 +314,12 @@ static u8_t *add_offer_options(u8_t *optptr) ipadd.addr = *((u32_t *) &server_address); -#ifdef USE_CLASS_B_NET - *optptr++ = DHCP_OPTION_SUBNET_MASK; - *optptr++ = 4; //length - *optptr++ = 255; - *optptr++ = 240; - *optptr++ = 0; - *optptr++ = 0; -#else *optptr++ = DHCP_OPTION_SUBNET_MASK; *optptr++ = 4; - *optptr++ = 255; - *optptr++ = 255; - *optptr++ = 255; - *optptr++ = 0; -#endif + *optptr++ = ip4_addr1(&s_dhcps_mask); + *optptr++ = ip4_addr2(&s_dhcps_mask); + *optptr++ = ip4_addr3(&s_dhcps_mask); + *optptr++ = ip4_addr4(&s_dhcps_mask); *optptr++ = DHCP_OPTION_LEASE_TIME; *optptr++ = 4; @@ -361,21 +366,13 @@ static u8_t *add_offer_options(u8_t *optptr) *optptr++ = ip4_addr4(&ipadd); } -#ifdef CLASS_B_NET - *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; - *optptr++ = 4; - *optptr++ = ip4_addr1(&ipadd); - *optptr++ = 255; - *optptr++ = 255; - *optptr++ = 255; -#else + ip4_addr_t broadcast_addr = { .addr = (ipadd.addr & s_dhcps_mask.addr) | ~s_dhcps_mask.addr }; *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; *optptr++ = 4; - *optptr++ = ip4_addr1(&ipadd); - *optptr++ = ip4_addr2(&ipadd); - *optptr++ = ip4_addr3(&ipadd); - *optptr++ = 255; -#endif + *optptr++ = ip4_addr1(&broadcast_addr); + *optptr++ = ip4_addr2(&broadcast_addr); + *optptr++ = ip4_addr3(&broadcast_addr); + *optptr++ = ip4_addr4(&broadcast_addr); *optptr++ = DHCP_OPTION_INTERFACE_MTU; *optptr++ = 2; @@ -529,11 +526,14 @@ static void send_offer(struct dhcps_msg *m, u16_t len) return; } + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; #if DHCPS_DEBUG - SendOffer_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); + SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t); #else - udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); + udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); #endif if (p->ref != 0) { @@ -604,11 +604,14 @@ static void send_nak(struct dhcps_msg *m, u16_t len) return; } + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; #if DHCPS_DEBUG - SendNak_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); + SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t); #else - udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); + udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); #endif if (p->ref != 0) { @@ -678,8 +681,10 @@ static void send_ack(struct dhcps_msg *m, u16_t len) return; } - SendAck_err_t = udp_sendto(pcb_dhcps, p, IP_ADDR_BROADCAST, DHCPS_CLIENT_PORT); - + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; + SendAck_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); #if DHCPS_DEBUG DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t); #endif @@ -897,12 +902,12 @@ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) if ((client_address.addr > dhcps_poll.end_ip.addr) || (ip4_addr_isany(&client_address))) { if (pnode != NULL) { node_remove_from_list(&plist, pnode); - os_free(pnode); + free(pnode); pnode = NULL; } if (pdhcps_pool != NULL) { - os_free(pdhcps_pool); + free(pdhcps_pool); pdhcps_pool = NULL; } @@ -914,12 +919,12 @@ static s16_t parse_msg(struct dhcps_msg *m, u16_t len) if (ret == DHCPS_STATE_RELEASE) { if (pnode != NULL) { node_remove_from_list(&plist, pnode); - os_free(pnode); + free(pnode); pnode = NULL; } if (pdhcps_pool != NULL) { - os_free(pdhcps_pool); + free(pdhcps_pool); pdhcps_pool = NULL; } @@ -1059,7 +1064,7 @@ static void handle_dhcp(void *arg, DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n"); #endif pbuf_free(p); - os_free(pmsg_dhcps); + free(pmsg_dhcps); pmsg_dhcps = NULL; } @@ -1136,16 +1141,21 @@ void dhcps_set_new_lease_cb(dhcps_cb_t cb) *******************************************************************************/ void dhcps_start(struct netif *netif, ip4_addr_t ip) { - if (pcb_dhcps != NULL) { - udp_remove(pcb_dhcps); + dhcps_netif = netif; + + if (dhcps_netif->dhcps_pcb != NULL) { + udp_remove(dhcps_netif->dhcps_pcb); } - pcb_dhcps = udp_new(); + dhcps_netif->dhcps_pcb = udp_new(); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) { printf("dhcps_start(): could not obtain pcb\n"); } + dhcps_netif->dhcps_pcb = pcb_dhcps; + IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255); server_address.addr = ip.addr; @@ -1155,7 +1165,6 @@ void dhcps_start(struct netif *netif, ip4_addr_t ip) udp_bind(pcb_dhcps, &netif->ip_addr, DHCPS_SERVER_PORT); udp_recv(pcb_dhcps, handle_dhcp, NULL); - sys_timeout(1000, (sys_timeout_handler)dhcps_coarse_tmr, NULL); #if DHCPS_DEBUG DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n"); #endif @@ -1177,12 +1186,10 @@ void dhcps_stop(struct netif *netif) return; } - sys_untimeout((sys_timeout_handler)dhcps_coarse_tmr, NULL); - - if (pcb_dhcps != NULL) { - udp_disconnect(pcb_dhcps); - udp_remove(pcb_dhcps); - pcb_dhcps = NULL; + if (apnetif->dhcps_pcb != NULL) { + udp_disconnect(apnetif->dhcps_pcb); + udp_remove(apnetif->dhcps_pcb); + apnetif->dhcps_pcb = NULL; } list_node *pnode = NULL; @@ -1193,9 +1200,9 @@ void dhcps_stop(struct netif *netif) pback_node = pnode; pnode = pback_node->pnext; node_remove_from_list(&plist, pback_node); - os_free(pback_node->pnode); + free(pback_node->pnode); pback_node->pnode = NULL; - os_free(pback_node); + free(pback_node); pback_node = NULL; } } @@ -1212,6 +1219,7 @@ static void kill_oldest_dhcps_pool(void) list_node *minpre = NULL, *minp = NULL; struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL; pre = plist; + assert(pre != NULL && pre->pnext != NULL); // Expect the list to have at least 2 nodes p = pre->pnext; minpre = pre; minp = p; @@ -1230,9 +1238,9 @@ static void kill_oldest_dhcps_pool(void) } minpre->pnext = minp->pnext; - os_free(minp->pnode); + free(minp->pnode); minp->pnode = NULL; - os_free(minp); + free(minp); minp = NULL; } @@ -1258,9 +1266,9 @@ void dhcps_coarse_tmr(void) pback_node = pnode; pnode = pback_node->pnext; node_remove_from_list(&plist, pback_node); - os_free(pback_node->pnode); + free(pback_node->pnode); pback_node->pnode = NULL; - os_free(pback_node); + free(pback_node); pback_node = NULL; } else { pnode = pnode ->pnext; @@ -1271,11 +1279,6 @@ void dhcps_coarse_tmr(void) if (num_dhcps_pool > MAX_STATION_NUM) { kill_oldest_dhcps_pool(); } - - /*Do not restart timer when dhcp server is stopped*/ - if (pcb_dhcps != NULL) { - sys_timeout(1000, (sys_timeout_handler)dhcps_coarse_tmr, NULL); - } } /****************************************************************************** @@ -1327,8 +1330,9 @@ dhcps_dns_setserver(const ip_addr_t *dnsserver) * Returns : ip4_addr_t *******************************************************************************/ ip4_addr_t -dhcps_dns_getserver() +dhcps_dns_getserver(void) { return dns_server; } +#endif // ESP_DHCP diff --git a/components/lwip/apps/multi-threads/sockets_mt.c b/components/lwip/apps/multi-threads/sockets_mt.c deleted file mode 100644 index 205036225..000000000 --- a/components/lwip/apps/multi-threads/sockets_mt.c +++ /dev/null @@ -1,819 +0,0 @@ -// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "lwip/opt.h" - -#ifdef SOCKETS_MT - -#define SOCKETS_MT_DISABLE_SHUTDOWN - -#include "lwip/priv/api_msg.h" - -/* disable all LWIP socket API when compiling LWIP raw socket */ - -#undef lwip_accept -#undef lwip_bind -#undef lwip_shutdown -#undef lwip_getpeername -#undef lwip_getsockname -#undef lwip_setsockopt -#undef lwip_getsockopt -#undef lwip_close -#undef lwip_connect -#undef lwip_listen -#undef lwip_recv -#undef lwip_recvfrom -#undef lwip_send -#undef lwip_sendmsg -#undef lwip_sendto -#undef lwip_socket -#undef lwip_select -#undef lwip_ioctlsocket - -#define lwip_accept lwip_accept_esp -#define lwip_bind lwip_bind_esp -#define lwip_shutdown lwip_shutdown_esp -#define lwip_getpeername lwip_getpeername_esp -#define lwip_getsockname lwip_getsockname_esp -#define lwip_setsockopt lwip_setsockopt_esp -#define lwip_getsockopt lwip_getsockopt_esp -#define lwip_close lwip_closesocket_esp -#define lwip_connect lwip_connect_esp -#define lwip_listen lwip_listen_esp -#define lwip_recv lwip_recv_esp -#define lwip_recvfrom lwip_recvfrom_esp -#define lwip_send lwip_send_esp -#define lwip_sendmsg lwip_sendmsg_esp -#define lwip_sendto lwip_sendto_esp -#define lwip_socket lwip_socket_esp -#define lwip_select lwip_select_esp -#define lwip_ioctlsocket lwip_ioctl_esp - -#if LWIP_POSIX_SOCKETS_IO_NAMES -#undef lwip_read -#undef lwip_write -#undef lwip_writev -#undef lwip_close -#undef closesocket -#undef lwip_fcntl -#undef lwip_ioctl - -#define lwip_read lwip_read_esp -#define lwip_write lwip_write_esp -#define lwip_writev lwip_writev_esp -#define lwip_close lwip_close_esp -#define lwip_fcntl lwip_fcntl_esp -#define lwip_ioctl lwip_ioctl_esp -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ - -#include "../../lwip/src/api/sockets.c" - -/* disable macros to enable LWIP function */ - -#undef lwip_accept -#undef lwip_bind -#undef lwip_shutdown -#undef lwip_getpeername -#undef lwip_getsockname -#undef lwip_setsockopt -#undef lwip_getsockopt -#undef lwip_close -#undef lwip_connect -#undef lwip_listen -#undef lwip_recv -#undef lwip_recvfrom -#undef lwip_send -#undef lwip_sendmsg -#undef lwip_sendto -#undef lwip_socket -#undef lwip_select -#undef lwip_ioctlsocket - -#if LWIP_POSIX_SOCKETS_IO_NAMES -#undef lwip_read -#undef lwip_write -#undef lwip_writev -#undef lwip_close -#undef closesocket -#undef lwip_fcntl -#undef lwip_ioctl -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ - -/********************************************************************/ -#define LWIP_SYNC_MT_SLEEP_MS 10 - -#define SOCK_MT_DEBUG_LEVEL 255 - -typedef struct socket_conn_sync { - struct tcpip_api_call_data call; - struct netconn *conn; -} socket_conn_sync_t; - -typedef int (*lwip_io_mt_fn)(int, int ); - -/* Use about 2 bit */ -#define SOCK_MT_STATE_SOCK 0 -#define SOCK_MT_STATE_ACCEPT 1 -#define SOCK_MT_STATE_CONNECT 2 -#define SOCK_MT_STATE_SEND 3 -#define SOCK_MT_STATE_ILL 4 - -#define SOCK_MT_LOCK_SEND (1 << 0) -#define SOCK_MT_LOCK_RECV (1 << 1) -#define SOCK_MT_LOCK_IOCTL (1 << 2) - -#define SOCK_MT_LOCK_MIN SOCK_MT_LOCK_SEND -#define SOCK_MT_LOCK_MAX SOCK_MT_LOCK_IOCTL - -#define SOCK_MT_SELECT_RECV (1 << 0) -#define SOCK_MT_SELECT_SEND (1 << 1) - -typedef struct _sock_mt { - uint8_t opened : 1; - uint8_t state : 2; - uint8_t select : 2; - uint8_t lock : 3; -} sock_mt_t; - -#if (SOCK_MT_DEBUG_LEVEL < 16) -#define SOCK_MT_DEBUG(level, ...) \ - if (level >= SOCK_MT_DEBUG_LEVEL) \ - printf(__VA_ARGS__); -#else -#define SOCK_MT_DEBUG(level, ...) -#endif - -#define SOCK_MT_ENTER_CHECK(s, l, st) \ -{ \ - if (_sock_lock(s, l) != ERR_OK) \ - return -1; \ - if (st != SOCK_MT_STATE_ILL) \ - _sock_set_state(s, st); \ -} - -#define SOCK_MT_EXIT_CHECK(s, l, st) \ -{ \ - if (st != SOCK_MT_STATE_ILL) \ - _sock_set_state(s, SOCK_MT_STATE_SOCK); \ - if (_sock_unlock(s, l) != ERR_OK) \ - return -1; \ -} - -static volatile sock_mt_t DRAM_ATTR sockets_mt[NUM_SOCKETS]; - -static inline void _sock_mt_init(int s) -{ - memset((void *)&sockets_mt[s], 0, sizeof(sock_mt_t)); -} - -static inline int _sock_is_opened(int s) -{ - return sockets_mt[s].opened != 0; -} - -static inline void _sock_set_open(int s, int opened) -{ - SYS_ARCH_DECL_PROTECT(lev); - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].opened = opened; - SYS_ARCH_UNPROTECT(lev); -} - -static inline void _sock_set_state(int s, int state) -{ - SYS_ARCH_DECL_PROTECT(lev); - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].state = state; - SYS_ARCH_UNPROTECT(lev); -} - -static inline int _sock_get_state(int s) -{ - return sockets_mt[s].state; -} - -static inline int _sock_get_select(int s, int select) -{ - return sockets_mt[s].select & select; -} - -static int inline _sock_is_lock(int s, int l) -{ - return sockets_mt[s].lock & l; -} - -static int inline _sock_next_lock(int lock) -{ - return lock << 1; -} - -static void inline _sock_set_select(int s, int select) -{ - SYS_ARCH_DECL_PROTECT(lev); - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].select |= select; - SYS_ARCH_UNPROTECT(lev); -} - -static void inline _sock_reset_select(int s, int select) -{ - SYS_ARCH_DECL_PROTECT(lev); - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].select &= ~select; - SYS_ARCH_UNPROTECT(lev); -} - -static int _sock_try_lock(int s, int l) -{ - int ret = ERR_OK; - SYS_ARCH_DECL_PROTECT(lev); - - if (!_sock_is_opened(s)) { - ret = ERR_CLSD; - goto exit; - } - - if (sockets_mt[s].lock & l) { - ret = ERR_INPROGRESS; - goto exit; - } - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].lock |= l; - SYS_ARCH_UNPROTECT(lev); - -exit: - return ret; -} - -static int _sock_lock(int s, int l) -{ - int ret = ERR_OK; - if (tryget_socket(s) == NULL) - return -1; - - SOCK_MT_DEBUG(1, "s %d l %d enter ", s, l); - - while (1) { - ret = _sock_try_lock(s, l); - - if (ret != ERR_INPROGRESS) - break; - - vTaskDelay(1); - } - - SOCK_MT_DEBUG(1, "OK %d\n", ret); - - return ret; -} - -static int _sock_unlock(int s, int l) -{ - int ret = 0; - SYS_ARCH_DECL_PROTECT(lev); - - SOCK_MT_DEBUG(1, "s %d l %d exit ", s, l); - - SYS_ARCH_PROTECT(lev); - sockets_mt[s].lock &= ~l; - SYS_ARCH_UNPROTECT(lev); - - if (!_sock_is_opened(s)) { - ret = ERR_CLSD; - goto exit; - } - -exit: - SOCK_MT_DEBUG(1, "OK %d\n", ret); - - return ret; -} - -static int lwip_enter_mt_select(int s, fd_set *read_set, fd_set *write_set) -{ - int i; - - if (s > NUM_SOCKETS || s < 0) - return -1; - - for (i = 0; i < s; i++) { - if(FD_ISSET(i, read_set) || FD_ISSET(i, write_set)) - if (tryget_socket(i) == NULL) - goto failed1; - - if (FD_ISSET(i, read_set)) { - err_t err; - - _sock_set_select(i, SOCK_MT_SELECT_RECV); - err = _sock_lock(i, SOCK_MT_LOCK_RECV); - if (err != ERR_OK) { - goto failed2; - } - } - - if (FD_ISSET(i, write_set)) { - err_t err; - - _sock_set_select(i, SOCK_MT_SELECT_SEND); - err = _sock_lock(i, SOCK_MT_LOCK_SEND); - if (err != ERR_OK) { - goto failed3; - } - } - } - - return 0; - -failed3: - _sock_unlock(i, SOCK_MT_LOCK_SEND); - _sock_reset_select(i, SOCK_MT_SELECT_SEND); -failed2: - if (FD_ISSET(i, read_set)) { - _sock_unlock(i, SOCK_MT_LOCK_RECV); - _sock_reset_select(i, SOCK_MT_SELECT_RECV); - } -failed1: - for (i--; i >=0; i--) { - if (FD_ISSET(i, read_set) ) { - _sock_unlock(i, SOCK_MT_LOCK_RECV); - _sock_reset_select(i, SOCK_MT_SELECT_RECV); - } - - if (FD_ISSET(i, write_set)) { - _sock_unlock(i, SOCK_MT_LOCK_SEND); - _sock_reset_select(i, SOCK_MT_SELECT_SEND); - } - } - - return -1; -} - -static void lwip_exit_mt_select(int s, fd_set *read_set, fd_set *write_set) -{ - int i; - - for (i = 0; i < s; i++) { - if (FD_ISSET(i, read_set)) { - _sock_unlock(i, SOCK_MT_LOCK_RECV); - _sock_reset_select(i, SOCK_MT_SELECT_RECV); - } - - if (FD_ISSET(i, write_set)) { - _sock_unlock(i, SOCK_MT_LOCK_SEND); - _sock_reset_select(i, SOCK_MT_SELECT_SEND); - } - } -} - -static err_t lwip_do_sync_accept(struct tcpip_api_call_data *call) -{ - socket_conn_sync_t *sync = (socket_conn_sync_t *)call; - struct netconn *conn = sync->conn; - - SYS_ARCH_DECL_PROTECT(lev); - SYS_ARCH_PROTECT(lev); - if (sys_mbox_valid(&conn->acceptmbox)) - sys_mbox_trypost(&conn->acceptmbox, NULL); - conn->state = NETCONN_NONE; - SYS_ARCH_UNPROTECT(lev); - - return ERR_OK; -} - -static err_t lwip_do_sync_send(struct tcpip_api_call_data *call) -{ - socket_conn_sync_t *sync = (socket_conn_sync_t *)call; - struct netconn *conn = sync->conn; - - SYS_ARCH_DECL_PROTECT(lev); - SYS_ARCH_PROTECT(lev); - if (conn->current_msg) { - conn->current_msg->err = ERR_OK; - if (sys_sem_valid(conn->current_msg->op_completed_sem)) - sys_sem_signal(conn->current_msg->op_completed_sem); - conn->current_msg = NULL; - } - conn->state = NETCONN_NONE; - SYS_ARCH_UNPROTECT(lev); - - return ERR_OK; -} - -static err_t lwip_do_sync_recv_state(struct tcpip_api_call_data *call) -{ - socket_conn_sync_t *sync = (socket_conn_sync_t *)call; - struct netconn *conn = sync->conn; - - SYS_ARCH_DECL_PROTECT(lev); - SYS_ARCH_PROTECT(lev); - SOCK_MT_DEBUG(1, "sync recv %d\n", conn->socket); - if (sys_mbox_valid(&conn->recvmbox)) - sys_mbox_trypost(&conn->recvmbox, NULL); - conn->state = NETCONN_NONE; - SYS_ARCH_UNPROTECT(lev); - - return ERR_OK; -} - -static err_t lwip_do_sync_select_state(struct tcpip_api_call_data *call) -{ - socket_conn_sync_t *sync = (socket_conn_sync_t *)call; - struct netconn *conn = sync->conn; - - SYS_ARCH_DECL_PROTECT(lev); - SYS_ARCH_PROTECT(lev); - event_callback(conn, NETCONN_EVT_ERROR, 0); - conn->state = NETCONN_NONE; - SYS_ARCH_UNPROTECT(lev); - - return ERR_OK; -} - -static void lwip_sync_state_mt(int s) -{ - struct lwip_sock *sock = tryget_socket(s); - int state = _sock_get_state(s); - socket_conn_sync_t sync = { - .conn = sock->conn, - }; - - SOCK_MT_DEBUG(1, "sync state %d\n", state); - - switch (state) { - case SOCK_MT_STATE_ACCEPT : - tcpip_api_call(lwip_do_sync_accept, &sync.call); - break; - case SOCK_MT_STATE_CONNECT: - case SOCK_MT_STATE_SEND : - tcpip_api_call(lwip_do_sync_send, &sync.call); - break; - default : - break; - } -} - -static void lwip_sync_recv_mt(int s) -{ - struct lwip_sock *sock = tryget_socket(s); - socket_conn_sync_t sync = { - .conn = sock->conn, - }; - - tcpip_api_call(lwip_do_sync_recv_state, &sync.call); -} - -static void lwip_sync_select_mt(int s) -{ - struct lwip_sock *sock = tryget_socket(s); - socket_conn_sync_t sync = { - .conn = sock->conn, - }; - - tcpip_api_call(lwip_do_sync_select_state, &sync.call); -} - -static void lwip_sync_mt(int s, int how) -{ - int lock = SOCK_MT_LOCK_MIN; - - do { - if (_sock_is_lock(s, lock)) { - int need_wait = 0; - extern void sys_arch_msleep(int ms); - - if (!_sock_get_select(s, SOCK_MT_SELECT_RECV | SOCK_MT_SELECT_SEND)) { - switch (lock) { - case SOCK_MT_LOCK_SEND: - lwip_sync_state_mt(s); - need_wait = 1; - break; - case SOCK_MT_LOCK_RECV: - lwip_sync_recv_mt(s); - need_wait = 1; - break; - default : - break; - } - } else { - lwip_sync_select_mt(s); - need_wait = 1; - } - - if (need_wait) - sys_arch_msleep(LWIP_SYNC_MT_SLEEP_MS); - } else - lock = _sock_next_lock(lock); - } while (lock < SOCK_MT_LOCK_MAX); -} - -#if LWIP_SO_LINGER -static void lwip_socket_set_so_link(int s, int linger) -{ - struct lwip_sock *sock = get_socket(s); - - if (sock) { - /* - * linker: - * -1: nothing - * 0: free sent_buf immediately - */ - sock->conn->linger = linger; - } -} -#else -#error "LWIP_SO_LINGER must be enable" -#endif - - -int lwip_socket(int domain, int type, int protocol) -{ - int s; - - s = lwip_socket_esp(domain, type, protocol); - if (s < 0) - return -1; - - lwip_socket_set_so_link(s, 0); - _sock_mt_init(s); - _sock_set_open(s, 1); - - return s; -} - -int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); - - ret = lwip_bind_esp(s, name, namelen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_CONNECT); - - ret = lwip_connect_esp(s, name, namelen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_CONNECT); - - return ret; -} - -int lwip_listen(int s, int backlog) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); - - lwip_socket_set_so_link(s, -1); - - ret = lwip_listen_esp(s, backlog); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ACCEPT) - - lwip_socket_set_so_link(s, -1); - - ret = lwip_accept_esp(s, addr, addrlen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ACCEPT); - - if (ret < 0) - return -1; - - lwip_socket_set_so_link(ret, 0); - _sock_mt_init(ret); - _sock_set_open(ret, 1); - - return ret; -} - -int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - ret = lwip_getpeername_esp(s, name, namelen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - ret = lwip_getsockname_esp(s, name, namelen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - ret = lwip_setsockopt_esp(s, level, optname, optval, optlen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - int ret; - - if (optname == SO_ERROR) { - int retval = 0; - - if (!_sock_is_opened(s)) - retval = ENOTCONN; - - if (retval) { - *(int *)optval = retval; - return 0; - } - } - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - ret = lwip_getsockopt_esp(s, level, optname, optval, optlen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_ioctl(int s, long cmd, void *argp) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL) - - ret = lwip_ioctl_esp(s, cmd, argp); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); - - ret = lwip_sendto_esp(s, data, size, flags, to, tolen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); - - return ret; -} - -int lwip_send(int s, const void *data, size_t size, int flags) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); - - ret = lwip_send_esp(s, data, size, flags); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); - - return ret; -} - -int lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_RECV, SOCK_MT_STATE_ILL); - - ret = lwip_recvfrom_esp(s, mem, len, flags, from, fromlen); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_RECV, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_recv(int s, void *mem, size_t len, int flags) -{ - return lwip_recvfrom(s, mem, len, flags, NULL, NULL); -} - -int lwip_read(int s, void *mem, size_t len) -{ - return lwip_recvfrom(s, mem, len, 0, NULL, NULL); -} - -int lwip_write(int s, const void *data, size_t size) -{ - return lwip_send(s, data, size, 0); -} - -int lwip_fcntl(int s, int cmd, int val) -{ - int ret; - - SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - ret = lwip_fcntl_esp(s, cmd, val); - - SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); - - return ret; -} - -int lwip_shutdown(int s, int how) -{ - return 0; -} - -int lwip_close(int s) -{ - int ret; - -#if ESP_UDP - struct lwip_sock *sock = get_socket(s); - if (sock) - udp_sync_close_netconn(sock->conn); -#endif - - _sock_set_open(s, 0); - - lwip_sync_mt(s, SHUT_RDWR); - - ret = lwip_close_esp(s); - - return ret; -} - -int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, - fd_set *exceptset, struct timeval *timeout) -{ - int ret; - fd_set read_set, write_set; - - if (readset) - MEMCPY(&read_set, readset, sizeof(fd_set)); - else - FD_ZERO(&read_set); - - if (writeset) - MEMCPY(&write_set, writeset, sizeof(fd_set)); - else - FD_ZERO(&write_set); - - ret = lwip_enter_mt_select(maxfdp1, &read_set, &write_set); - if (ret) - return ret; - - ret = lwip_select_esp(maxfdp1, readset, writeset, exceptset, timeout); - - lwip_exit_mt_select(maxfdp1, &read_set, &write_set); - - return ret; -} - -#endif diff --git a/components/lwip/apps/ping/esp_ping.c b/components/lwip/apps/ping/esp_ping.c index 75b669412..c8ae7ec4e 100644 --- a/components/lwip/apps/ping/esp_ping.c +++ b/components/lwip/apps/ping/esp_ping.c @@ -18,10 +18,11 @@ #include "lwip/ip_addr.h" typedef struct _ping_option { - ip4_addr_t ping_target; + ip_addr_t ping_target; uint32_t ping_count; uint32_t ping_rcv_timeout; uint32_t ping_delay; + uint32_t interface; size_t ping_data_len; uint16_t ping_id; u8_t ping_tos; @@ -42,13 +43,16 @@ esp_err_t esp_ping_set_target(ping_target_id_t opt_id, void *opt_val, uint32_t o switch (opt_id) { case PING_TARGET_IP_ADDRESS: - ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); - ping_option_info->ping_target.addr = *(uint32_t *)opt_val; + ipaddr_aton(opt_val, &(ping_option_info->ping_target)); break; case PING_TARGET_IP_ADDRESS_COUNT: ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); ping_option_info->ping_count = *(uint32_t *)opt_val; break; + case PING_TARGET_IF_INDEX: + ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); + ping_option_info->interface = *(uint32_t *)opt_val; + break; case PING_TARGET_RCV_TIMEO: ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); ping_option_info->ping_rcv_timeout = (*(uint32_t *)opt_val); @@ -93,13 +97,16 @@ esp_err_t esp_ping_get_target(ping_target_id_t opt_id, void *opt_val, uint32_t o switch (opt_id) { case PING_TARGET_IP_ADDRESS: - ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); - *(uint32_t *)opt_val = ping_option_info->ping_target.addr; + ip_addr_copy(*(ip_addr_t*)opt_val, ping_option_info->ping_target); break; case PING_TARGET_IP_ADDRESS_COUNT: ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); *(uint32_t *)opt_val = ping_option_info->ping_count; break; + case PING_TARGET_IF_INDEX: + ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); + *(uint32_t *)opt_val = ping_option_info->interface; + break; case PING_TARGET_RCV_TIMEO: ESP_PING_CHECK_OPTLEN(opt_len, uint32_t); *(uint32_t *)opt_val = ping_option_info->ping_rcv_timeout; diff --git a/components/lwip/apps/ping/ping.c b/components/lwip/apps/ping/ping.c index 8b8d5512f..8f954d5a7 100644 --- a/components/lwip/apps/ping/ping.c +++ b/components/lwip/apps/ping/ping.c @@ -5,7 +5,7 @@ */ /* - * Redistribution and use in source and binary forms, with or without modification, + * 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, @@ -14,24 +14,24 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 lwIP TCP/IP stack. - * + * */ -/** +/** * This is an example of a "ping" sender (with raw API and socket API). * It can be used as a start point to maintain opened a network connection, or * like a network "watchdog" for your device. @@ -55,6 +55,7 @@ #if PING_USE_SOCKETS #include "lwip/sockets.h" #include "lwip/inet.h" +#include "ping/ping_sock.h" #endif /* PING_USE_SOCKETS */ #ifdef ESP_PING @@ -98,20 +99,17 @@ #define PING_RESULT(ping_ok) #endif -/* ping variables */ -static u16_t ping_seq_num; -static struct timeval ping_time; -#if ESP_PING -static sys_sem_t ping_sem = NULL; -static bool ping_init_flag = false; -#endif -#if !PING_USE_SOCKETS -static struct raw_pcb *ping_pcb; -#endif /* PING_USE_SOCKETS */ - #define PING_TIME_DIFF_MS(_end, _start) ((uint32_t)(((_end).tv_sec - (_start).tv_sec) * 1000 + (_end.tv_usec - _start.tv_usec)/1000)) #define PING_TIME_DIFF_SEC(_end, _start) ((uint32_t)((_end).tv_sec - (_start).tv_sec)) +#if PING_USE_SOCKETS +/* ping handle */ +static esp_ping_handle_t ping = NULL; +#else +static struct raw_pcb *ping_pcb; +static u16_t ping_seq_num; +static struct timeval ping_time; + /** Prepare a echo ICMP request */ static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) @@ -133,213 +131,6 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) iecho->chksum = inet_chksum(iecho, len); } -#if PING_USE_SOCKETS - -/* Ping using the socket ip */ -static err_t -ping_send(int s, ip_addr_t *addr) -{ - int err; - struct icmp_echo_hdr *iecho; - struct sockaddr_in to; - size_t ping_size; - -#ifdef ESP_PING - size_t ping_data_len = 0; - esp_ping_get_target(PING_TARGET_DATA_LEN, &ping_data_len, sizeof(ping_data_len)); - - if (ping_data_len > 0) { - ping_size = sizeof(struct icmp_echo_hdr) + ping_data_len; - } else { - ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE; - } -#else - ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE; -#endif - - LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); - LWIP_ASSERT("ping: expect IPv4 address", !IP_IS_V6(addr)); - - iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size); - if (!iecho) { - return ERR_MEM; - } - - ping_prepare_echo(iecho, (u16_t)ping_size); - - to.sin_len = sizeof(to); - to.sin_family = AF_INET; - inet_addr_from_ip4addr(&to.sin_addr, ip_2_ip4(addr)); - - err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)); - - mem_free(iecho); - - return (err ? ERR_OK : ERR_VAL); -} - -static void -ping_recv(int s) -{ - char buf[64]; - int len; - struct sockaddr_in from; - struct ip_hdr *iphdr; - struct icmp_echo_hdr *iecho; - int fromlen = sizeof(from); - struct timeval now; - - while((len = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) { - if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) { - if (from.sin_family != AF_INET) { - /* Ping is not IPv4 */ - LWIP_DEBUGF( PING_DEBUG, ("ping: invalid sin_family\n")); - } else { - ip4_addr_t fromaddr; - inet_addr_to_ip4addr(&fromaddr, &from.sin_addr); - iphdr = (struct ip_hdr *)buf; - iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4)); - - LWIP_DEBUGF( PING_DEBUG, ("ping: recv seq=%d ", ntohs(iecho->seqno))); - ip4_addr_debug_print(PING_DEBUG, &fromaddr); - gettimeofday(&now, NULL); - LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", PING_TIME_DIFF_MS(now, ping_time))); - - if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) { - /* do some ping result processing */ -#ifdef ESP_PING - esp_ping_result((ICMPH_TYPE(iecho) == ICMP_ER), len, PING_TIME_DIFF_MS(now, ping_time)); -#else - PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER)); -#endif - return; - } else { - LWIP_DEBUGF( PING_DEBUG, ("ping: drop\n")); - } - } - } - fromlen = sizeof(from); - } - - gettimeofday(&now, NULL); - if (len == 0) { - LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %"U32_F" ms - timeout\n", PING_TIME_DIFF_MS(now, ping_time))); - } - - /* do some ping result processing */ -#ifdef ESP_PING - esp_ping_result(0, len, PING_TIME_DIFF_MS(now, ping_time)); -#else - PING_RESULT(0); -#endif -} - -static void -ping_thread(void *arg) -{ - uint32_t ping_timeout = PING_RCV_TIMEO; - uint32_t ping_delay = PING_DELAY; - ip_addr_t ping_target; - int ret; - int s; - -#ifdef ESP_PING - uint32_t ping_count_cur = 0; - uint32_t ping_count_max = 3; - ip4_addr_t ipaddr; - int lev; - - esp_ping_get_target(PING_TARGET_IP_ADDRESS_COUNT, &ping_count_max, sizeof(ping_count_max)); - esp_ping_get_target(PING_TARGET_RCV_TIMEO, &ping_timeout, sizeof(ping_timeout)); - esp_ping_get_target(PING_TARGET_DELAY_TIME, &ping_delay, sizeof(ping_delay)); - esp_ping_get_target(PING_TARGET_IP_ADDRESS, &ipaddr.addr, sizeof(uint32_t)); - ip_addr_copy_from_ip4(ping_target, ipaddr); -#else - ip_addr_copy_from_ip4(ping_target, PING_TARGET); -#endif - -#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD - int timeout = ping_timeout; -#else - struct timeval timeout; - timeout.tv_sec = ping_timeout/1000; - timeout.tv_usec = (ping_timeout%1000)*1000; -#endif - - LWIP_UNUSED_ARG(arg); - - if ((s = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) { - goto _exit_new_socket_failed; - } - - ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - LWIP_ASSERT("setting receive timeout failed", ret == 0); - LWIP_UNUSED_ARG(ret); - -#ifdef ESP_PING - int tos = 0; - esp_ping_get_target(PING_TARGET_IP_TOS, &tos, sizeof(int)); - if (tos > 0) { - tos <<= 5; - ret = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); - LWIP_ASSERT("setting IP_TOS failed", ret == 0); - LWIP_UNUSED_ARG(ret); - } -#endif - - while (1) { -#ifdef ESP_PING - if (ping_count_cur++ >= ping_count_max) { - goto _exit; - } - - if (ping_init_flag == false) { - goto _exit; - } -#endif - if (ping_send(s, &ping_target) == ERR_OK) { - LWIP_DEBUGF( PING_DEBUG, ("ping: send seq=%d ", ping_seq_num)); - ip_addr_debug_print(PING_DEBUG, &ping_target); - LWIP_DEBUGF( PING_DEBUG, ("\n")); - - gettimeofday(&ping_time, NULL); - ping_recv(s); - } else { - LWIP_DEBUGF( PING_DEBUG, ("ping: send ")); - ip_addr_debug_print(PING_DEBUG, &ping_target); - LWIP_DEBUGF( PING_DEBUG, (" - error\n")); - } - sys_msleep(ping_delay); - } - -#ifdef ESP_PING -_exit: - close(s); - -_exit_new_socket_failed: - esp_ping_result(PING_RES_FINISH, 0, 0); - SYS_ARCH_PROTECT(lev); - if (ping_init_flag) { /* Ping closed by this thread */ - LWIP_DEBUGF( PING_DEBUG, ("ping: closed by self ")); - if (ping_sem) { - sys_sem_free(&ping_sem); - } - ping_sem = NULL; - ping_init_flag = false; - SYS_ARCH_UNPROTECT(lev); - } else { /* Ping closed by task calls ping_deinit */ - LWIP_DEBUGF( PING_DEBUG, ("ping: closed by other")); - SYS_ARCH_UNPROTECT(lev); - if (ping_sem) { - sys_sem_signal(&ping_sem); - } - } - vTaskDelete(NULL); -#endif -} - -#else /* PING_USE_SOCKETS */ - /* Ping using the raw ip */ static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) @@ -436,27 +227,73 @@ ping_send_now(void) #endif /* PING_USE_SOCKETS */ +/** + * + * Re-implement ping_init and ping_deinit with the APIs from ping_sock.h for back-ward compatibility sake. + * It's highly recommended that users should use the new APIs from ping_sock.h. + * ToDo: ping.h and esp_ping.h are deprecated now and should be removed in idf v5.x. + * + */ + +static void +on_ping_success(esp_ping_handle_t hdl, void *args) +{ + uint32_t elapsed_time, recv_len; + esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); + esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); + esp_ping_result(PING_RES_OK, recv_len, elapsed_time); +} + +static void +on_ping_timeout(esp_ping_handle_t hdl, void *args) +{ + uint32_t elapsed_time, recv_len; + esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); + esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); + esp_ping_result(PING_RES_TIMEOUT, recv_len, elapsed_time); +} + +static void +on_ping_end(esp_ping_handle_t hdl, void *args) +{ + esp_ping_result(PING_RES_FINISH, 0, 0); + esp_ping_delete_session(hdl); +} + int ping_init(void) { - int ret; - int lev; - - SYS_ARCH_PROTECT(lev); - if (ping_init_flag) { - SYS_ARCH_UNPROTECT(lev); - /* Currently we only support one ping, call ping_deinit to kill the running ping before start new ping */ - return ERR_INPROGRESS; - } - ret = sys_sem_new(&ping_sem, 0); - if (ERR_OK != ret) { - SYS_ARCH_UNPROTECT(lev); - return ERR_MEM; - } - ping_init_flag = true; - SYS_ARCH_UNPROTECT(lev); #if PING_USE_SOCKETS - sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + uint32_t tos = 0; + uint32_t ping_timeout = PING_RCV_TIMEO; + uint32_t ping_delay = PING_DELAY; + uint32_t ping_count_max = 3; + uint32_t interface = 0; + ip_addr_t ipaddr; + + esp_ping_get_target(PING_TARGET_IP_ADDRESS_COUNT, &ping_count_max, sizeof(ping_count_max)); + esp_ping_get_target(PING_TARGET_RCV_TIMEO, &ping_timeout, sizeof(ping_timeout)); + esp_ping_get_target(PING_TARGET_DELAY_TIME, &ping_delay, sizeof(ping_delay)); + esp_ping_get_target(PING_TARGET_IP_ADDRESS, &ipaddr, sizeof(ip_addr_t)); + esp_ping_get_target(PING_TARGET_IP_TOS, &tos, sizeof(tos)); + esp_ping_get_target(PING_TARGET_IF_INDEX, &interface, sizeof(interface)); + + esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG(); + config.count = ping_count_max; + config.timeout_ms = ping_timeout; + config.interval_ms = ping_delay; + config.target_addr = ipaddr; + config.tos = tos; + config.interface = interface; + + esp_ping_callbacks_t cbs = { + .on_ping_end = on_ping_end, + .on_ping_success = on_ping_success, + .on_ping_timeout = on_ping_timeout, + }; + + esp_ping_new_session(&config, &cbs, &ping); + esp_ping_start(ping); #else /* PING_USE_SOCKETS */ ping_raw_init(); #endif /* PING_USE_SOCKETS */ @@ -466,24 +303,8 @@ ping_init(void) void ping_deinit(void) { - int lev; - - SYS_ARCH_PROTECT(lev); - if (ping_init_flag == false) { - SYS_ARCH_UNPROTECT(lev); - return; - } - - ping_init_flag = false; - SYS_ARCH_UNPROTECT(lev); - if (ping_sem) { - sys_sem_wait(&ping_sem); - - SYS_ARCH_PROTECT(lev); - sys_sem_free(&ping_sem); - ping_sem = NULL; - SYS_ARCH_UNPROTECT(lev); - } + esp_ping_stop(ping); + esp_ping_delete_session(ping); } #endif /* LWIP_IPV4 && LWIP_RAW */ diff --git a/components/lwip/apps/ping/ping_sock.c b/components/lwip/apps/ping/ping_sock.c new file mode 100644 index 000000000..0d6849374 --- /dev/null +++ b/components/lwip/apps/ping/ping_sock.c @@ -0,0 +1,405 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lwip/opt.h" +#include "lwip/init.h" +#include "lwip/mem.h" +#include "lwip/icmp.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "esp_log.h" +#include "ping/ping_sock.h" + +const static char *TAG = "ping_sock"; + +#define PING_CHECK(a, str, goto_tag, ret_value, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +#define PING_TIME_DIFF_MS(_end, _start) ((uint32_t)(((_end).tv_sec - (_start).tv_sec) * 1000 + \ + ((_end).tv_usec - (_start).tv_usec) / 1000)) + +#define PING_CHECK_START_TIMEOUT_MS (1000) + +#define PING_FLAGS_INIT (1 << 0) +#define PING_FLAGS_START (1 << 1) + +typedef struct { + int sock; + struct sockaddr_storage target_addr; + TaskHandle_t ping_task_hdl; + struct icmp_echo_hdr *packet_hdr; + ip_addr_t recv_addr; + uint32_t recv_len; + uint32_t icmp_pkt_size; + uint32_t count; + uint32_t transmitted; + uint32_t received; + uint32_t interval_ms; + uint32_t elapsed_time_ms; + uint32_t total_time_ms; + uint8_t ttl; + uint32_t flags; + void (*on_ping_success)(esp_ping_handle_t hdl, void *args); + void (*on_ping_timeout)(esp_ping_handle_t hdl, void *args); + void (*on_ping_end)(esp_ping_handle_t hdl, void *args); + void *cb_args; +} esp_ping_t; + +static esp_err_t esp_ping_send(esp_ping_t *ep) +{ + esp_err_t ret = ESP_OK; + ep->packet_hdr->seqno++; + /* generate checksum since "seqno" has changed */ + ep->packet_hdr->chksum = 0; + if (ep->packet_hdr->type == ICMP_ECHO) { + ep->packet_hdr->chksum = inet_chksum(ep->packet_hdr, ep->icmp_pkt_size); + } + + int sent = sendto(ep->sock, ep->packet_hdr, ep->icmp_pkt_size, 0, + (struct sockaddr *)&ep->target_addr, sizeof(ep->target_addr)); + + if (sent != ep->icmp_pkt_size) { + int opt_val; + socklen_t opt_len = sizeof(opt_val); + getsockopt(ep->sock, SOL_SOCKET, SO_ERROR, &opt_val, &opt_len); + ESP_LOGE(TAG, "send error=%d", opt_val); + ret = ESP_FAIL; + } else { + ep->transmitted++; + } + return ret; +} + +static int esp_ping_receive(esp_ping_t *ep) +{ + char buf[64]; // 64 bytes are enough to cover IP header and ICMP header + int len = 0; + struct sockaddr_storage from; + int fromlen = sizeof(from); + uint16_t data_head = 0; + + while ((len = recvfrom(ep->sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen)) > 0) { + if (from.ss_family == AF_INET) { + // IPv4 + struct sockaddr_in *from4 = (struct sockaddr_in *)&from; + inet_addr_to_ip4addr(ip_2_ip4(&ep->recv_addr), &from4->sin_addr); + IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V4); + data_head = (uint16_t)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr)); + } +#if LWIP_IPV6 + else { + // IPv6 + struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; + inet6_addr_to_ip6addr(ip_2_ip6(&ep->recv_addr), &from6->sin6_addr); + IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V6); + data_head = (uint16_t)(sizeof(struct ip6_hdr) + sizeof(struct icmp6_echo_hdr)); + } +#endif + if (len >= data_head) { + if (IP_IS_V4_VAL(ep->recv_addr)) { // Currently we process IPv4 + struct ip_hdr *iphdr = (struct ip_hdr *)buf; + struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4)); + if ((iecho->id == ep->packet_hdr->id) && (iecho->seqno == ep->packet_hdr->seqno)) { + ep->received++; + ep->ttl = iphdr->_ttl; + ep->recv_len = lwip_ntohs(IPH_LEN(iphdr)) - data_head; // The data portion of ICMP + return len; + } + } +#if LWIP_IPV6 + else if (IP_IS_V6_VAL(ep->recv_addr)) { // Currently we process IPv6 + struct ip6_hdr *iphdr = (struct ip6_hdr *)buf; + struct icmp6_echo_hdr *iecho6 = (struct icmp6_echo_hdr *)(buf + sizeof(struct ip6_hdr)); // IPv6 head length is 40 + if ((iecho6->id == ep->packet_hdr->id) && (iecho6->seqno == ep->packet_hdr->seqno)) { + ep->received++; + ep->recv_len = IP6H_PLEN(iphdr) - sizeof(struct icmp6_echo_hdr); //The data portion of ICMPv6 + return len; + } + } +#endif + } + fromlen = sizeof(from); + } + // if timeout, len will be -1 + return len; +} + +static void esp_ping_thread(void *args) +{ + esp_ping_t *ep = (esp_ping_t *)(args); + TickType_t last_wake; + struct timeval start_time, end_time; + int recv_ret; + + while (1) { + /* wait for ping start signal */ + if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(PING_CHECK_START_TIMEOUT_MS))) { + /* initialize runtime statistics */ + ep->packet_hdr->seqno = 0; + ep->transmitted = 0; + ep->received = 0; + ep->total_time_ms = 0; + + last_wake = xTaskGetTickCount(); + while ((ep->flags & PING_FLAGS_START) && ((ep->count == 0) || (ep->packet_hdr->seqno < ep->count))) { + esp_ping_send(ep); + gettimeofday(&start_time, NULL); + recv_ret = esp_ping_receive(ep); + gettimeofday(&end_time, NULL); + ep->elapsed_time_ms = PING_TIME_DIFF_MS(end_time, start_time); + ep->total_time_ms += ep->elapsed_time_ms; + if (recv_ret >= 0) { + if (ep->on_ping_success) { + ep->on_ping_success((esp_ping_handle_t)ep, ep->cb_args); + } + } else { + if (ep->on_ping_timeout) { + ep->on_ping_timeout((esp_ping_handle_t)ep, ep->cb_args); + } + } + vTaskDelayUntil(&last_wake, pdMS_TO_TICKS(ep->interval_ms)); // to get a more accurate delay + } + /* batch of ping operations finished */ + if (ep->on_ping_end) { + ep->on_ping_end((esp_ping_handle_t)ep, ep->cb_args); + } + } else { + // check if ping has been de-initialized + if (!(ep->flags & PING_FLAGS_INIT)) { + break; + } + } + } + /* before exit task, free all resources */ + if (ep->packet_hdr) { + free(ep->packet_hdr); + } + if (ep->sock > 0) { + close(ep->sock); + } + free(ep); + vTaskDelete(NULL); +} + +esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_callbacks_t *cbs, esp_ping_handle_t *hdl_out) +{ + esp_err_t ret = ESP_OK; + esp_ping_t *ep = NULL; + PING_CHECK(config, "ping config can't be null", err, ESP_ERR_INVALID_ARG); + PING_CHECK(hdl_out, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); + + ep = mem_calloc(1, sizeof(esp_ping_t)); + PING_CHECK(ep, "no memory for esp_ping object", err, ESP_ERR_NO_MEM); + + /* set INIT flag, so that ping task won't exit (must set before create ping task) */ + ep->flags |= PING_FLAGS_INIT; + + /* create ping thread */ + BaseType_t xReturned = xTaskCreate(esp_ping_thread, "ping", config->task_stack_size, ep, + config->task_prio, &ep->ping_task_hdl); + PING_CHECK(xReturned == pdTRUE, "create ping task failed", err, ESP_ERR_NO_MEM); + + /* callback functions */ + if (cbs) { + ep->cb_args = cbs->cb_args; + ep->on_ping_end = cbs->on_ping_end; + ep->on_ping_timeout = cbs->on_ping_timeout; + ep->on_ping_success = cbs->on_ping_success; + } + /* set parameters for ping */ + ep->recv_addr = config->target_addr; + ep->count = config->count; + ep->interval_ms = config->interval_ms; + ep->icmp_pkt_size = sizeof(struct icmp_echo_hdr) + config->data_size; + ep->packet_hdr = mem_calloc(1, ep->icmp_pkt_size); + PING_CHECK(ep->packet_hdr, "no memory for echo packet", err, ESP_ERR_NO_MEM); + /* set ICMP type and code field */ + ep->packet_hdr->code = 0; + /* ping id should be unique, treat task handle as ping ID */ + ep->packet_hdr->id = ((uint32_t)ep->ping_task_hdl) & 0xFFFF; + /* fill the additional data buffer with some data */ + char *d = (char *)(ep->packet_hdr) + sizeof(struct icmp_echo_hdr); + for (uint32_t i = 0; i < config->data_size; i++) { + d[i] = 'A' + i; + } +#if LWIP_IPV4 && LWIP_IPV6 + /* create socket */ + if (IP_IS_V4(&config->target_addr) || ip6_addr_isipv4mappedipv6(ip_2_ip6(&config->target_addr))) { + ep->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + } else { + ep->sock = socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6); + } +#else + if (IP_IS_V4(&config->target_addr)) { + ep->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + } +#endif + PING_CHECK(ep->sock > 0, "create socket failed: %d", err, ESP_FAIL, ep->sock); + /* set if index */ + if(config->interface) { + struct ifreq iface; + if(netif_index_to_name(config->interface, iface.ifr_name) == NULL) { + goto err; + } + if(setsockopt(ep->sock, SOL_SOCKET, SO_BINDTODEVICE, &iface, sizeof(iface)) !=0) { + goto err; + } + } + struct timeval timeout; + timeout.tv_sec = config->timeout_ms / 1000; + timeout.tv_usec = (config->timeout_ms % 1000) * 1000; + /* set receive timeout */ + setsockopt(ep->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + /* set tos */ + setsockopt(ep->sock, IPPROTO_IP, IP_TOS, &config->tos, sizeof(config->tos)); + + /* set socket address */ + if (IP_IS_V4(&config->target_addr)) { + struct sockaddr_in *to4 = (struct sockaddr_in *)&ep->target_addr; + to4->sin_family = AF_INET; + inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(&config->target_addr)); + ep->packet_hdr->type = ICMP_ECHO; + } +#if LWIP_IPV6 + if (IP_IS_V6(&config->target_addr)) { + struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ep->target_addr; + to6->sin6_family = AF_INET6; + inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(&config->target_addr)); + ep->packet_hdr->type = ICMP6_TYPE_EREQ; + } +#endif + /* return ping handle to user */ + *hdl_out = (esp_ping_handle_t)ep; + return ESP_OK; +err: + if (ep) { + if (ep->sock > 0) { + close(ep->sock); + } + if (ep->packet_hdr) { + free(ep->packet_hdr); + } + if (ep->ping_task_hdl) { + vTaskDelete(ep->ping_task_hdl); + } + free(ep); + } + return ret; +} + +esp_err_t esp_ping_delete_session(esp_ping_handle_t hdl) +{ + esp_err_t ret = ESP_OK; + esp_ping_t *ep = (esp_ping_t *)hdl; + PING_CHECK(ep, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); + /* reset init flags, then ping task will exit */ + ep->flags &= ~PING_FLAGS_INIT; + return ESP_OK; +err: + return ret; +} + +esp_err_t esp_ping_start(esp_ping_handle_t hdl) +{ + esp_err_t ret = ESP_OK; + esp_ping_t *ep = (esp_ping_t *)hdl; + PING_CHECK(ep, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); + ep->flags |= PING_FLAGS_START; + xTaskNotifyGive(ep->ping_task_hdl); + return ESP_OK; +err: + return ret; +} + +esp_err_t esp_ping_stop(esp_ping_handle_t hdl) +{ + esp_err_t ret = ESP_OK; + esp_ping_t *ep = (esp_ping_t *)hdl; + PING_CHECK(ep, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); + ep->flags &= ~PING_FLAGS_START; + return ESP_OK; +err: + return ret; +} + +esp_err_t esp_ping_get_profile(esp_ping_handle_t hdl, esp_ping_profile_t profile, void *data, uint32_t size) +{ + esp_err_t ret = ESP_OK; + esp_ping_t *ep = (esp_ping_t *)hdl; + const void *from = NULL; + uint32_t copy_size = 0; + PING_CHECK(ep, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); + PING_CHECK(data, "profile data can't be null", err, ESP_ERR_INVALID_ARG); + switch (profile) { + case ESP_PING_PROF_SEQNO: + from = &ep->packet_hdr->seqno; + copy_size = sizeof(ep->packet_hdr->seqno); + break; + case ESP_PING_PROF_TTL: + from = &ep->ttl; + copy_size = sizeof(ep->ttl); + break; + case ESP_PING_PROF_REQUEST: + from = &ep->transmitted; + copy_size = sizeof(ep->transmitted); + break; + case ESP_PING_PROF_REPLY: + from = &ep->received; + copy_size = sizeof(ep->received); + break; + case ESP_PING_PROF_IPADDR: + from = &ep->recv_addr; + copy_size = sizeof(ep->recv_addr); + break; + case ESP_PING_PROF_SIZE: + from = &ep->recv_len; + copy_size = sizeof(ep->recv_len); + break; + case ESP_PING_PROF_TIMEGAP: + from = &ep->elapsed_time_ms; + copy_size = sizeof(ep->elapsed_time_ms); + break; + case ESP_PING_PROF_DURATION: + from = &ep->total_time_ms; + copy_size = sizeof(ep->total_time_ms); + break; + default: + PING_CHECK(false, "unknow profile: %d", err, ESP_ERR_INVALID_ARG, profile); + break; + } + PING_CHECK(size >= copy_size, "unmatched data size for profile %d", err, ESP_ERR_INVALID_SIZE, profile); + memcpy(data, from, copy_size); + return ESP_OK; +err: + return ret; +} diff --git a/components/lwip/apps/sntp/sntp.c b/components/lwip/apps/sntp/sntp.c new file mode 100644 index 000000000..d6ff2993c --- /dev/null +++ b/components/lwip/apps/sntp/sntp.c @@ -0,0 +1,119 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "esp_log.h" +#include "sntp.h" +#include "lwip/apps/sntp.h" + +static const char *TAG = "sntp"; + +static volatile sntp_sync_mode_t sntp_sync_mode = SNTP_SYNC_MODE_IMMED; +static volatile sntp_sync_status_t sntp_sync_status = SNTP_SYNC_STATUS_RESET; +static sntp_sync_time_cb_t time_sync_notification_cb = NULL; +static uint32_t s_sync_interval = CONFIG_LWIP_SNTP_UPDATE_DELAY; + +inline void sntp_set_sync_status(sntp_sync_status_t sync_status) +{ + sntp_sync_status = sync_status; +} + +void __attribute__((weak)) sntp_sync_time(struct timeval *tv) +{ + if (sntp_sync_mode == SNTP_SYNC_MODE_IMMED) { + settimeofday(tv, NULL); + sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED); + } else if (sntp_sync_mode == SNTP_SYNC_MODE_SMOOTH) { + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + int64_t cpu_time = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec; + int64_t sntp_time = (int64_t)tv->tv_sec * 1000000L + (int64_t)tv->tv_usec; + int64_t delta = sntp_time - cpu_time; + struct timeval tv_delta = { .tv_sec = delta / 1000000L, .tv_usec = delta % 1000000L }; + if (adjtime(&tv_delta, NULL) == -1) { + ESP_LOGD(TAG, "Function adjtime don't update time because the error is very big"); + settimeofday(tv, NULL); + ESP_LOGD(TAG, "Time was synchronized through settimeofday"); + sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED); + } else { + sntp_set_sync_status(SNTP_SYNC_STATUS_IN_PROGRESS); + } + } + if (time_sync_notification_cb) { + time_sync_notification_cb(tv); + } +} + +void sntp_set_sync_mode(sntp_sync_mode_t sync_mode) +{ + sntp_sync_mode = sync_mode; +} + +sntp_sync_mode_t sntp_get_sync_mode(void) +{ + return sntp_sync_mode; +} + +// set a callback function for time synchronization notification +void sntp_set_time_sync_notification_cb(sntp_sync_time_cb_t callback) +{ + time_sync_notification_cb = callback; +} + +sntp_sync_status_t sntp_get_sync_status(void) +{ + sntp_sync_status_t ret_sync_status = SNTP_SYNC_STATUS_RESET; + sntp_sync_status_t sync_status = sntp_sync_status; + if (sync_status == SNTP_SYNC_STATUS_COMPLETED) { + sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); + ret_sync_status = SNTP_SYNC_STATUS_COMPLETED; + } else if (sync_status == SNTP_SYNC_STATUS_IN_PROGRESS) { + struct timeval outdelta; + adjtime(NULL, &outdelta); + if (outdelta.tv_sec == 0 && outdelta.tv_usec == 0) { + sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); + ret_sync_status = SNTP_SYNC_STATUS_COMPLETED; + } else { + ret_sync_status = SNTP_SYNC_STATUS_IN_PROGRESS; + } + } + return ret_sync_status; +} + +void sntp_set_sync_interval(uint32_t interval_ms) +{ + if (interval_ms < 15000) { + // SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds + interval_ms = 15000; + } + s_sync_interval = interval_ms; +} + +uint32_t sntp_get_sync_interval(void) +{ + return s_sync_interval; +} + +bool sntp_restart(void) +{ + if (sntp_enabled()) { + sntp_stop(); + sntp_init(); + return true; + } + return false; +} diff --git a/components/lwip/component.mk b/components/lwip/component.mk index 54f7a162c..2b668e413 100644 --- a/components/lwip/component.mk +++ b/components/lwip/component.mk @@ -1,30 +1,46 @@ # # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS += include/lwip/apps \ - include/lwip \ - lwip/src/include \ - lwip/src/include/posix \ - port/esp8266/include \ - port/esp8266/include/port - -COMPONENT_SRCDIRS += apps/dhcpserver \ - apps/multi-threads \ - apps/ping \ - lwip/src/api \ - lwip/src/apps/sntp \ - lwip/src/core \ - lwip/src/core/ipv4 \ - lwip/src/core/ipv6 \ - lwip/src/netif \ - port/esp8266/freertos \ - port/esp8266/netif - -CFLAGS += -Wno-address #lots of LWIP source files evaluate macros that check address of stack variables - -lwip/src/apps/sntp/sntp.o: CFLAGS += -Wno-implicit-function-declaration -lwip/src/core/ipv4/ip4.o: CFLAGS += -Wno-implicit-function-declaration - -ifdef CONFIG_LWIP_SOCKET_MULTITHREAD -COMPONENT_OBJEXCLUDE := lwip/src/api/sockets.o +COMPONENT_SUBMODULES += lwip + +COMPONENT_ADD_INCLUDEDIRS := \ + include/apps \ + include/apps/sntp \ + lwip/src/include \ + port/esp8266/include \ + port/esp8266/include/arch + +COMPONENT_SRCDIRS := \ + apps/dhcpserver \ + apps/ping \ + apps/sntp \ + lwip/src/api \ + lwip/src/apps/sntp \ + lwip/src/apps/netbiosns \ + lwip/src/core \ + lwip/src/core/ipv4 \ + lwip/src/core/ipv6 \ + lwip/src/netif \ + port/esp8266 \ + port/esp8266/freertos \ + port/esp8266/netif \ + port/esp8266/debug + +ifndef CONFIG_IDF_TARGET_ESP32 + COMPONENT_OBJEXCLUDE := port/esp8266/netif/ethernetif.o +endif + +ifdef CONFIG_LWIP_PPP_SUPPORT + COMPONENT_SRCDIRS += lwip/src/netif/ppp lwip/src/netif/ppp/polarssl endif + +CFLAGS += -Wno-address # lots of LWIP source files evaluate macros that check address of stack variables + +ifeq ($(GCC_NOT_5_2_0), 1) +lwip/src/netif/ppp/ppp.o: CFLAGS += -Wno-uninitialized +lwip/src/netif/ppp/pppos.o: CFLAGS += -Wno-implicit-fallthrough +endif + +lwip/src/core/tcp.o: CFLAGS += -Wno-type-limits + +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h b/components/lwip/include/apps/dhcpserver/dhcpserver.h similarity index 94% rename from components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h rename to components/lwip/include/apps/dhcpserver/dhcpserver.h index 6e3363b7c..1aef8aaca 100644 --- a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver.h +++ b/components/lwip/include/apps/dhcpserver/dhcpserver.h @@ -1,4 +1,4 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ typedef struct dhcps_msg { u8_t options[312]; }dhcps_msg; +/* Defined in esp_misc.h */ typedef struct { bool enable; ip4_addr_t start_ip; @@ -87,9 +88,8 @@ void *dhcps_option_info(u8_t op_id, u32_t opt_len); void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len); bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip); void dhcps_dns_setserver(const ip_addr_t *dnsserver); -ip4_addr_t dhcps_dns_getserver(); +ip4_addr_t dhcps_dns_getserver(void); void dhcps_set_new_lease_cb(dhcps_cb_t cb); -void dhcps_coarse_tmr(void); #endif diff --git a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h b/components/lwip/include/apps/dhcpserver/dhcpserver_options.h similarity index 98% rename from components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h rename to components/lwip/include/apps/dhcpserver/dhcpserver_options.h index 8a6f18454..38d46f6bf 100644 --- a/components/lwip/include/lwip/apps/dhcpserver/dhcpserver_options.h +++ b/components/lwip/include/apps/dhcpserver/dhcpserver_options.h @@ -1,4 +1,4 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2017 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/components/lwip/include/lwip/apps/esp_ping.h b/components/lwip/include/apps/esp_ping.h similarity index 94% rename from components/lwip/include/lwip/apps/esp_ping.h rename to components/lwip/include/apps/esp_ping.h index 9abb883c2..86dcc6ac0 100644 --- a/components/lwip/include/lwip/apps/esp_ping.h +++ b/components/lwip/include/apps/esp_ping.h @@ -24,7 +24,7 @@ extern "C" { // gen_esp_err_to_name.py: include this as "esp_ping.h" because "components/lwip/include/apps/" is in the compiler path // and not "components/lwip/include" -#define ESP_ERR_PING_BASE 0x6000 +#define ESP_ERR_PING_BASE 0xa000 #define ESP_ERR_PING_INVALID_PARAMS ESP_ERR_PING_BASE + 0x01 #define ESP_ERR_PING_NO_MEM ESP_ERR_PING_BASE + 0x02 @@ -54,12 +54,13 @@ typedef enum { PING_TARGET_RES_FN = 55, /**< ping result callback function */ PING_TARGET_RES_RESET = 56, /**< ping result statistic reset */ PING_TARGET_DATA_LEN = 57, /**< ping data length*/ - PING_TARGET_IP_TOS = 58 /**< ping QOS*/ + PING_TARGET_IP_TOS = 58, /**< ping QOS*/ + PING_TARGET_IF_INDEX = 59 /**< ping if index*/ } ping_target_id_t; typedef enum { PING_RES_TIMEOUT = 0, - PING_RES_OK = 1, + PING_RES_OK = 1, PING_RES_FINISH = 2, } ping_res_t; diff --git a/components/lwip/include/apps/esp_sntp.h b/components/lwip/include/apps/esp_sntp.h new file mode 100644 index 000000000..020f0cf36 --- /dev/null +++ b/components/lwip/include/apps/esp_sntp.h @@ -0,0 +1,22 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_SNTP_H__ +#define __ESP_SNTP_H__ + +#include "lwip/err.h" +#include "lwip/apps/sntp.h" +#include "sntp.h" + +#endif // __ESP_SNTP_H__ diff --git a/components/lwip/include/lwip/apps/ping/ping.h b/components/lwip/include/apps/ping/ping.h similarity index 94% rename from components/lwip/include/lwip/apps/ping/ping.h rename to components/lwip/include/apps/ping/ping.h index 6e8eb24b2..6d1785655 100644 --- a/components/lwip/include/lwip/apps/ping/ping.h +++ b/components/lwip/include/apps/ping/ping.h @@ -43,10 +43,10 @@ extern "C" { #endif -int ping_init(void); +int ping_init(void) __attribute__ ((deprecated)); #ifdef ESP_PING -void ping_deinit(void); +void ping_deinit(void) __attribute__ ((deprecated)); #endif #if !PING_USE_SOCKETS diff --git a/components/lwip/include/apps/ping/ping_sock.h b/components/lwip/include/apps/ping/ping_sock.h new file mode 100644 index 000000000..2bc3ccd90 --- /dev/null +++ b/components/lwip/include/apps/ping/ping_sock.h @@ -0,0 +1,176 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "lwip/ip_addr.h" + +/** +* @brief Type of "ping" session handle +* +*/ +typedef void *esp_ping_handle_t; + +/** +* @brief Type of "ping" callback functions +* +*/ +typedef struct { + /** + * @brief arguments for callback functions + * + */ + void *cb_args; + + /** + * @brief Invoked by internal ping thread when received ICMP echo reply packet + * + */ + void (*on_ping_success)(esp_ping_handle_t hdl, void *args); + + /** + * @brief Invoked by internal ping thread when receive ICMP echo reply packet timeout + * + */ + void (*on_ping_timeout)(esp_ping_handle_t hdl, void *args); + + /** + * @brief Invoked by internal ping thread when a ping session is finished + * + */ + void (*on_ping_end)(esp_ping_handle_t hdl, void *args); +} esp_ping_callbacks_t; + +/** +* @brief Type of "ping" configuration +* +*/ +typedef struct { + uint32_t count; /*!< A "ping" session contains count procedures */ + uint32_t interval_ms; /*!< Milliseconds between each ping procedure */ + uint32_t timeout_ms; /*!< Timeout value (in milliseconds) of each ping procedure */ + uint32_t data_size; /*!< Size of the data next to ICMP packet header */ + uint8_t tos; /*!< Type of Service, a field specified in the IP header */ + ip_addr_t target_addr; /*!< Target IP address, either IPv4 or IPv6 */ + uint32_t task_stack_size; /*!< Stack size of internal ping task */ + uint32_t task_prio; /*!< Priority of internal ping task */ + uint32_t interface; /*!< Netif index, interface=0 means NETIF_NO_INDEX*/ +} esp_ping_config_t; + +/** + * @brief Default ping configuration + * + */ +#if LWIP_IPV4 && LWIP_IPV6 +#define PING_TARGET_ADDR ip_addr_any_type +#else +#define PING_TARGET_ADDR ip_addr_any +#endif +#define ESP_PING_DEFAULT_CONFIG() \ + { \ + .count = 5, \ + .interval_ms = 1000, \ + .timeout_ms = 1000, \ + .data_size = 64, \ + .tos = 0, \ + .target_addr = PING_TARGET_ADDR, \ + .task_stack_size = 2048, \ + .task_prio = 2, \ + .interface = 0,\ + } + +#define ESP_PING_COUNT_INFINITE (0) /*!< Set ping count to zero will ping target infinitely */ + +/** +* @brief Profile of ping session +* +*/ +typedef enum { + ESP_PING_PROF_SEQNO, /*!< Sequence number of a ping procedure */ + ESP_PING_PROF_TTL, /*!< Time to live of a ping procedure */ + ESP_PING_PROF_REQUEST, /*!< Number of request packets sent out */ + ESP_PING_PROF_REPLY, /*!< Number of reply packets received */ + ESP_PING_PROF_IPADDR, /*!< IP address of replied target */ + ESP_PING_PROF_SIZE, /*!< Size of received packet */ + ESP_PING_PROF_TIMEGAP, /*!< Elapsed time between request and reply packet */ + ESP_PING_PROF_DURATION /*!< Elapsed time of the whole ping session */ +} esp_ping_profile_t; + +/** + * @brief Create a ping session + * + * @param config ping configuration + * @param cbs a bunch of callback functions invoked by internal ping task + * @param hdl_out handle of ping session + * @return + * - ESP_ERR_INVALID_ARG: invalid parameters (e.g. configuration is null, etc) + * - ESP_ERR_NO_MEM: out of memory + * - ESP_FAIL: other internal error (e.g. socket error) + * - ESP_OK: create ping session successfully, user can take the ping handle to do follow-on jobs + */ +esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_callbacks_t *cbs, esp_ping_handle_t *hdl_out); + +/** + * @brief Delete a ping session + * + * @param hdl handle of ping session + * @return + * - ESP_ERR_INVALID_ARG: invalid parameters (e.g. ping handle is null, etc) + * - ESP_OK: delete ping session successfully + */ +esp_err_t esp_ping_delete_session(esp_ping_handle_t hdl); + +/** + * @brief Start the ping session + * + * @param hdl handle of ping session + * @return + * - ESP_ERR_INVALID_ARG: invalid parameters (e.g. ping handle is null, etc) + * - ESP_OK: start ping session successfully + */ +esp_err_t esp_ping_start(esp_ping_handle_t hdl); + +/** + * @brief Stop the ping session + * + * @param hdl handle of ping session + * @return + * - ESP_ERR_INVALID_ARG: invalid parameters (e.g. ping handle is null, etc) + * - ESP_OK: stop ping session successfully + */ +esp_err_t esp_ping_stop(esp_ping_handle_t hdl); + +/** + * @brief Get runtime profile of ping session + * + * @param hdl handle of ping session + * @param profile type of profile + * @param data profile data + * @param size profile data size + * @return + * - ESP_ERR_INVALID_ARG: invalid parameters (e.g. ping handle is null, etc) + * - ESP_ERR_INVALID_SIZE: the actual profile data size doesn't match the "size" parameter + * - ESP_OK: get profile successfully + */ +esp_err_t esp_ping_get_profile(esp_ping_handle_t hdl, esp_ping_profile_t profile, void *data, uint32_t size); + +#ifdef __cplusplus +} +#endif diff --git a/components/lwip/include/apps/sntp/sntp.h b/components/lwip/include/apps/sntp/sntp.h new file mode 100644 index 000000000..b4c0939f8 --- /dev/null +++ b/components/lwip/include/apps/sntp/sntp.h @@ -0,0 +1,154 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __SNTP_H__ +#define __SNTP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The time update takes place in the sntp_sync_time() function. + * The user has the ability to redefine this function in order + * to re-define its functionality. This function has two time update modes, + * which can be set via the sntp_set_sync_mode() function. + * Two modes are available: + * - the first is an immediate update when receiving time from the sntp server, + * - the second is a smooth time update (if the time error is no more than 35 minutes, + * and an immediate update if the error is more than 35 minutes). + * + * To receive notification of time synchronization, + * you can use the callback function or get the synchronization status + * via the sntp_get_sync_status() function. + * + * To determine the time synchronization time on the device, you can use: + * 1) sntp_set_time_sync_notification_cb() function to set the callback function, + * which is convenient to use to receive notification of the update time. + * 2) sntp_get_sync_status() function for getting time synchronization status. + * After the time synchronization is completed, the status will be + * SNTP_SYNC_STATUS_COMPLETED, after, it will be reseted to SNTP_SYNC_STATUS_RESET + * to wait for the next sync cycle. + */ + +/// SNTP time update mode +typedef enum { + SNTP_SYNC_MODE_IMMED, /*!< Update system time immediately when receiving a response from the SNTP server. */ + SNTP_SYNC_MODE_SMOOTH, /*!< Smooth time updating. Time error is gradually reduced using adjtime function. If the difference between SNTP response time and system time is large (more than 35 minutes) then update immediately. */ +} sntp_sync_mode_t; + +/// SNTP sync status +typedef enum { + SNTP_SYNC_STATUS_RESET, // Reset status. + SNTP_SYNC_STATUS_COMPLETED, // Time is synchronized. + SNTP_SYNC_STATUS_IN_PROGRESS, // Smooth time sync in progress. +} sntp_sync_status_t; + +/** + * @brief SNTP callback function for notifying about time sync event + * + * @param tv Time received from SNTP server. + */ +typedef void (*sntp_sync_time_cb_t) (struct timeval *tv); + +/** + * @brief This function updates the system time. + * + * This is a weak-linked function. It is possible to replace all SNTP update functionality + * by placing a sntp_sync_time() function in the app firmware source. + * If the default implementation is used, calling sntp_set_sync_mode() allows + * the time synchronization mode to be changed to instant or smooth. + * If a callback function is registered via sntp_set_time_sync_notification_cb(), + * it will be called following time synchronization. + * + * @param tv Time received from SNTP server. + */ +void sntp_sync_time(struct timeval *tv); + +/** + * @brief Set the sync mode + * + * Allowable two mode: SNTP_SYNC_MODE_IMMED and SNTP_SYNC_MODE_SMOOTH. + * @param sync_mode Sync mode. + */ +void sntp_set_sync_mode(sntp_sync_mode_t sync_mode); + +/** + * @brief Get set sync mode + * + * @return SNTP_SYNC_MODE_IMMED: Update time immediately. + * SNTP_SYNC_MODE_SMOOTH: Smooth time updating. + */ +sntp_sync_mode_t sntp_get_sync_mode(void); + +/** + * @brief Get status of time sync + * + * After the update is completed, the status will be returned as SNTP_SYNC_STATUS_COMPLETED. + * After that, the status will be reset to SNTP_SYNC_STATUS_RESET. + * If the update operation is not completed yet, the status will be SNTP_SYNC_STATUS_RESET. + * If a smooth mode was chosen and the synchronization is still continuing (adjtime works), then it will be SNTP_SYNC_STATUS_IN_PROGRESS. + * + * @return SNTP_SYNC_STATUS_RESET: Reset status. + * SNTP_SYNC_STATUS_COMPLETED: Time is synchronized. + * SNTP_SYNC_STATUS_IN_PROGRESS: Smooth time sync in progress. + */ +sntp_sync_status_t sntp_get_sync_status(void); + +/** + * @brief Set status of time sync + * + * @param sync_status status of time sync (see sntp_sync_status_t) + */ +void sntp_set_sync_status(sntp_sync_status_t sync_status); + +/** + * @brief Set a callback function for time synchronization notification + * + * @param callback a callback function + */ +void sntp_set_time_sync_notification_cb(sntp_sync_time_cb_t callback); + +/** + * @brief Set the sync interval of SNTP operation + * + * Note: SNTPv4 RFC 4330 enforces a minimum sync interval of 15 seconds. + * This sync interval will be used in the next attempt update time throught SNTP. + * To apply the new sync interval call the sntp_restart() function, + * otherwise, it will be applied after the last interval expired. + * + * @param interval_ms The sync interval in ms. It cannot be lower than 15 seconds, otherwise 15 seconds will be set. + */ +void sntp_set_sync_interval(uint32_t interval_ms); + +/** + * @brief Get the sync interval of SNTP operation + * + * @return the sync interval + */ +uint32_t sntp_get_sync_interval(void); + +/** + * @brief Restart SNTP + * + * @return True - Restart + * False - SNTP was not initialized yet + */ +bool sntp_restart(void); + +#ifdef __cplusplus +} +#endif + +#endif // __SNTP_H__ diff --git a/components/lwip/include/lwip/apps/sntp/sntp.h b/components/lwip/include/lwip/apps/sntp/sntp.h deleted file mode 100644 index f066a6a86..000000000 --- a/components/lwip/include/lwip/apps/sntp/sntp.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "lwip/apps/sntp.h" diff --git a/components/lwip/include/lwip/sntp/sntp.h b/components/lwip/include/lwip/sntp/sntp.h deleted file mode 100644 index d2a93f425..000000000 --- a/components/lwip/include/lwip/sntp/sntp.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "lwip/app/sntp.h" diff --git a/components/lwip/linker.lf b/components/lwip/linker.lf new file mode 100644 index 000000000..0cb0c919c --- /dev/null +++ b/components/lwip/linker.lf @@ -0,0 +1,4 @@ +[mapping:lwip] +archive: liblwip.a +entries: + * (iram_bss) diff --git a/components/lwip/lwip b/components/lwip/lwip new file mode 160000 index 000000000..4fd84abac --- /dev/null +++ b/components/lwip/lwip @@ -0,0 +1 @@ +Subproject commit 4fd84abace0cd8a5a709c194fa54afb3cd39b3f7 diff --git a/components/lwip/lwip/CHANGELOG b/components/lwip/lwip/CHANGELOG deleted file mode 100644 index 306217fe5..000000000 --- a/components/lwip/lwip/CHANGELOG +++ /dev/null @@ -1,4295 +0,0 @@ -HISTORY - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(STABLE-2.0.3) - - ++ Bugfixes: - - 2017-09-11: Simon Goldschmidt - * tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data) - - 2017-08-02: Abroz Bizjak/Simon Goldschmidt - * multiple fixes in IPv4 reassembly (leading to corrupted datagrams received) - - 2017-03-30: Simon Goldschmidt - * dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf - - 2017-03-23: Dirk Ziegelmeier - * dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work) - -(STABLE-2.0.2) - - ++ New features: - - 2017-02-10: Dirk Ziegelmeier - * Implement task #14367: Hooks need a better place to be defined: - We now have a #define for a header file name that is #included in every .c - file that provides hooks. - - 2017-02-10: Simon Goldschmidt - * tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr) - - ++ Bugfixes: - - 2017-03-08 - * tcp: do not keep sending SYNs when getting ACKs - - 2017-03-08: Joel Cunningham - * tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476) - - 2017-03-01: Simon Goldschmidt - * httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved - is called nested from httpd_post_receive_data() (bug #50424) - - 2017-02-28: David van Moolenbroek/Simon Goldschmidt - * tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb - - 2017-02-17: Simon Goldschmidt - * dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325) - - 2017-02-16: Simon Goldschmidt - * LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274) - - 2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier - * For tiny targtes, LWIP_RAND is optional (fix compile time checks) - - 2017-02-10: Simon Goldschmidt - * tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying - to send FIN from tcp_fasttmr - - 2017-02-09: Simon Goldschmidt - * sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on - invalid/reused socket) by not allowing to reallocate a socket that has - "select_waiting != 0" - - 2017-02-09: Simon Goldschmidt - * httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs. - LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED) - - 2017-02-08: Dirk Ziegelmeier - * Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191: - "IPv4-mapped IPv6 address" - - 2017-02-08: Luc Revardel - * mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even - if last reporter) - - 2017-02-08: David van Moolenbroek - * ip6.c: Patch #9250: fix source substitution in ip6_output_if() - - 2017-02-08: Simon Goldschmidt - * tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value - in tcp_write error path) - - 2017-02-02: Dirk Ziegelmeier - * Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails - - 2017-01-18: Dirk Ziegelmeier - * Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests. - - 2017-01-15: Axel Lin, Dirk Ziegelmeier - * minor bug fixes in mqtt - - 2017-01-11: Knut Andre Tidemann - * sockets/netconn: fix broken default ICMPv6 handling of checksums - -(STABLE-2.0.1) - - ++ New features: - - 2016-12-31: Simon Goldschmidt - * tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error - reason when listening fails (bug #49861) - - 2016-12-20: Erik Andersen - * Add MQTT client - - 2016-12-14: Jan Breuer: - * opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) - - 2016-12-14: David van Moolenbroek - * opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW() - - 2016-12-09: Dirk Ziegelmeier - * ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF - - 2016-12-09: Simon Goldschmidt - * dns.c: added one-shot multicast DNS queries - - 2016-11-24: Ambroz Bizjak, David van Moolenbroek - * tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290) - - 2016-11-16: Dirk Ziegelmeier - * sockets.c: added support for IPv6 mapped IPv4 addresses - - ++ Bugfixes: - - 2016-12-16: Thomas Mueller - * api_lib.c: fixed race condition in return value of netconn_gethostbyname() - (and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo()) - - 2016-12-15: David van Moolenbroek - * opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial - sequence numbers (see contrib/addons/tcp_isn for an example implementation) - - 2016-12-05: Dirk Ziegelmeier - * fixed compiling with IPv4 disabled (IPv6 only case) - - 2016-11-28: Simon Goldschmidt - * api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return - ERR_OK without all bytes being written) - - 2016-11-28: Ambroz Bizjak - * tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK - assumed scaled) - - 2016-11-25: Simon Goldschmidt - * dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options) - - 2016-11-23: Dirk Ziegelmeier - * udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB - (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY - - 2016-11-16: Dirk Ziegelmeier - * *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API - - 2016-11-14: Joel Cunningham - * tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit - in window) - - 2016-11-16: Roberto Barbieri Carrera - * autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address) - - 2016-11-11: Dirk Ziegelmeier - * sockets.c: fixed bug #49578 (dropping multicast membership does not work - with LWIP_SOCKET_OFFSET) - -(STABLE-2.0.0) - - ++ New features: - - 2016-07-27: Simon Goldschmidt - * opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default - implementation of timeouts - - 2016-07-xx: Dirk Ziegelmeier - * Large overhaul of doxygen documentation - - 2016-04-05: Simon Goldschmidt - * timers.h/.c: prepare for overriding current timeout implementation: all - stack-internal caclic timers are avaliable in the lwip_cyclic_timers array - - 2016-03-23: Simon Goldschmidt - * tcp: call accept-callback with ERR_MEM when allocating a pcb fails on - passive open to inform the application about this error - ATTENTION: applications have to handle NULL pcb in accept callback! - - 2016-02-22: Ivan Delamer - * Initial 6LoWPAN support - - 2016-02-XX to 2016-03-XX: Dirk Ziegelmeier - * Cleanup TCPIP thread sync methods in a way that it is possibe to use them - in arbitrary code that needs things to be done in TCPIP thread. Used to - decouple netconn, netif, ppp and 6LoWPAN from LWIP core. - - 2016-02-XX: Dirk Ziegelmeier - * Implement dual-stack support in RAW, UDP and TCP. Add new IP address - type IPADDR_ANY_TYPE for this. Netconn/Socket API: Dual-stack is - automatically supported when an IPv6 netconn/socket is created. - - 2015-12-26: Martin Hentschel and Dirk Ziegelmeier - * Rewrite SNMP agent. SNMPv2c + MIB compiler. - - 2015-11-12: Dirk Ziegelmeier - * Decouple SNMP stack from lwIP core and move stack to apps/ directory. - Breaking change: Users have to call snmp_init() now! - - 2015-11-12: Dirk Ziegelmeier - * Implement possibility to declare private memory pools. This is useful to - decouple some apps from the core (SNMP stack) or make contrib app usage - simpler (httpserver_raw) - - 2015-10-09: Simon Goldschmidt - * started to move "private" header files containing implementation details to - "lwip/priv/" include directory to seperate the API from the implementation. - - 2015-10-07: Simon Goldschmidt - * added sntp client as first "supported" application layer protocol implementation - added 'apps' folder - - 2015-09-30: Dirk Ziegelmeier - * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance - implementation by aggregating the "base class" (struct mib_node) in all - derived node classes to get more type-safe code - - 2015-09-23: Simon Goldschmidt - * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to - ip_addr_t (so they can be used without conversion/temporary storage) - - 2015-09-08: Dirk Ziegelmeier - * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans - up the code and should allow integration of a 3rd party agent/mib2. Simple - counters are kept in MIB2_STATS, tree/table change function prototypes moved to - snmp_mib2.h. - - 2015-09-03: Simon Goldschmidt - * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records - - 2015-09-01: Simon Goldschmidt - * task #12178: hardware checksum capabilities can be configured per netif - (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function) - - 2015-08-30: Simon Goldschmidt - * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in - contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required) - - 2015-08-30: Simon Goldschmidt - * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point - to a routing function - - 2015-08-05: Simon Goldschmidt - * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF - and IP_MULTICAST_LOOP to be used without IGMP - - 2015-04-24: Simon Goldschmidt - * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to - check for the source of address assignment (replacement for NETIF_FLAG_DHCP) - - 2015-04-10: Simon Goldschmidt - * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled, - leaving an IPv6-only stack - - 2015-04-09: Simon Goldschmidt - * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed - ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP - version; ip_addr_t is used for all generic IP addresses for the API, - ip(4/6)_addr_t are only used internally or when initializing netifs or when - calling version-related functions - - 2015-03-24: Simon Goldschmidt - * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic - any more but passed through any netif (ENABLE_LOOPBACK has to be enabled) - - 2015-03-23: Simon Goldschmidt - * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP - addresses on multiple netifs should now be working correctly (if correctly - addressed by routing, that is) - - 2015-03-23: Simon Goldschmidt - * etharp.c: Stable etharp entries that are about to expire are now refreshed - using unicast to prevent unnecessary broadcast. Only if no answer is received - after 15 seconds, broadcast is used. - - 2015-03-06: Philip Gladstone - * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to - an interface) - - 2015-03-05: Simon Goldschmidt - * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling - is unclear): correclty separated administrative status of a netif (up/down) - from 'valid address' status - ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip - is used! - - 2015-02-26: patch by TabascoEye - * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) - - 2015-02-22: chrysn, Simon Goldschmidt - * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take - const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed - port callbacks: netif_output_fn, netif_igmp_mac_filter_fn) - - 2015-02-19: Ivan Delamer - * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate - if DHCP is active is through netif->dhcp field. - - 2015-02-19: Ivan Delamer - * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections - - 2015-02-18: Simon Goldschmidt - * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly - connections half-closed by peer" - - 2015-02-18: Simon Goldschmidt - * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections - (see bug #39565) - - 2015-02-16: Claudius Zingerli, Sergio Caprile - * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP" - - 2015-02-14: Simon Goldschmidt - * opt.h, snmp*: added support for write-access community and dedicated - community for sending traps - - 2015-02-13: Simon Goldschmidt - * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when - a memp pool was empty and an item is now available - - 2015-02-13: Simon Goldschmidt - * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to - allocate additional header space for TX on netifs requiring additional headers - - 2015-02-12: chrysn - * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before - the next timeout is due, for NO_SYS==1) - - 2015-02-11: Nick van Ijzendoorn - * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number - with defined offset" - - 2015-02-11: Frederick Baksik - * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item - - 2015-02-11: Simon Goldschmidt - * api_msg.c, opt.h: started to implement fullduplex sockets/netconns - (note that this is highly unstable yet!) - - 2015-01-17: Simon Goldschmidt - * api: allow enabling socket API without (public) netconn API - netconn API is - still used by sockets, but keeping it private (static) should allow better - compiler optimizations - - 2015-01-16: Simon Goldschmidt - * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again - by implementing the calculation formula from RFC3390 - - 2014-12-10: Simon Goldschmidt - * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread - instead of using one per netconn and per select call - - 2014-12-08: Simon Goldschmidt - * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform - (macro IP6H_VTCFL_SET()) - - 2014-12-08: Simon Goldschmidt - * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX - (IPv6 and IPv4/v6 reassembly might not work yet) - - 2014-11-06: Simon Goldschmidt - * sockets.c/.h, init.c: lwip_socket_init() is not needed any more - -> compatibility define - - 2014-09-16: Simon Goldschmidt - * dns.c, opt.h: reduced ram usage by parsing DNS responses in place - - 2014-09-16: Simon Goldschmidt - * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() - - 2014-09-15: Simon Goldschmidt - * dns.c: added source port randomization to make the DNS client more robust - (see bug #43144) - - 2013-09-02: Simon Goldschmidt - * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and - PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that - do not need packing - - 2013-08-19: Simon Goldschmidt - * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special - networks - - 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) - * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with - multiple gateways - - 2013-04-20: Fatih Asici - * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets - with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them - via hook function LWIP_HOOK_VLAN_CHECK - - 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) - * patch #7885: modification of api modules to support FreeRTOS-MPU - (don't pass stack-pointers to other threads) - - 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") - * patch #6537/#7858: TCP window scaling support - - 2014-01-17: Jiri Engelthaler - * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and - IPv6 ICMP's - - 2012-08-22: Sylvain Rochet - * New PPP stack for lwIP, developed in ppp-new branch. - Based from pppd 2.4.5, released 2009-11-17, with huge changes to match - code size and memory requirements for embedded devices, including: - - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which - is more or less what pppd sys-* files are, so that we get something working - using the unix port. - - Merged some patchs from lwIP Git repository which add interesting features - or fix bugs. - - Merged some patchs from Debian pppd package which add interesting features - or fix bugs. - - Ported PPP timeout handling to the lwIP timers system - - Disabled all the PPP code using filesystem access, replaced in necessary cases - to configuration variables. - - Disabled all the PPP code forking processes. - - Removed IPX support, lwIP does not support IPX. - - Ported and improved random module from the previous PPP port. - - Removed samba TDB (file-driven database) usage, because it needs a filesystem. - - MS-CHAP required a DES implementation, we added the latest PolarSSL DES - implementation which is under a BSD-ish license. - - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be - used in embedded devices with reduced memory footprint. - - Removed PPP configuration file parsing support. - - Added macro definition EAP_SUPPORT to make EAP support optional. - - Added macro definition CHAP_SUPPORT to make CHAP support optional. - - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. - - Added macro definition PAP_SUPPORT to make PAP support optional. - - Cleared all Linux syscall calls. - - Disabled demand support using a macro, so that it can be ported later. - - Disabled ECP support using a macro, so that it can be ported later. - - Disabled CCP support using a macro, so that it can be ported later. - - Disabled CBCP support using a macro, so that it can be ported later. - - Disabled LQR support using a macro, so that it can be ported later. - - Print packet debug feature optional, through PRINTPKT_SUPPORT - - Removed POSIX signal usage. - - Fully ported PPPoS code from the previous port. - - Fully ported PPPoE code from the previous port. - - Fully ported VJ compression protocol code from the previous port. - - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. - - Disabled PPP server support using a macro, so that it can be ported later. - - Switched all PPP debug to lwIP debug system. - - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, - removed all global variables everywhere, did everything necessary for - the PPP stack to support more than one PPP session (pppd only support - one session per process). - - Removed the statically allocated output buffer, now using PBUF. - - Improved structure size of all PPP modules, deep analyze of code to reduce - variables size to the bare minimum. Switched all boolean type (char type in - most architecture) to compiler generated bitfields. - - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. - - Now using a persistent netif interface which can then be used in lwIP - functions requiring a netif. - - Now initializing PPP in lwip_init() function. - - Reworked completely the PPP state machine, so that we don't end up in - anymore in inconsistent state, especially with PPPoE. - - Improved the way we handle PPP reconnection after disconnect, cleaning - everything required so that we start the PPP connection again from a - clean state. - - Added PPP holdoff support, allow the lwIP user to wait a little bit before - reconnecting, prevents connection flood, especially when using PPPoL2TP. - - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client - feature to lwIP, L2TP being a widely used tunnel protocol. - - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) - - Added PPP API "sequential" thread-safe API, based from NETIFAPI. - - 2011-07-21: Simon Goldschmidt - * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes - ioctl/FIONREAD return the size of the next pending datagram. - - 2011-05-25: Simon Goldschmidt - * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, - combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 - and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP - code so that the code is more readable. - - 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) - * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to - Ivan! (this is work in progress: we're just post release anyway :-) - - - ++ Bugfixes: - - 2016-08-23: Simon Goldschmidt - * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need - it any more after implementing unicast ARP renewal towards arp entry timeout - - 2016-07-20: Simon Goldschmidt - * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC) - - 2016-07-21: Simon Goldschmidt (patch by Ambroz Bizjak) - * tcp_in.c, tcp_out.c: fixed bug #48543 (TCP sent callback may prematurely - report sent data when only part of a segment is acked) and don't include - SYN/FIN in snd_buf counter - - 2016-07-19: Simon Goldschmidt - * etharp.c: fixed bug #48477 (ARP input packet might update static entry) - - 2016-07-11: Simon Goldschmidt - * tcp_in.c: fixed bug #48476 (TCP sent callback called wrongly due to picking - up old pcb->acked - - 2016-06-30: Simon Goldschmidt (original patch by Fabian Koch) - * tcp_in.c: fixed bug #48170 (Vulnerable to TCP RST spoofing) - - 2016-05-20: Dirk Ziegelmeier - * sntp.h/.c: Fix return value of sntp_getserver() call to return a pointer - - 2016-04-05: Simon Goldschmidt (patch by Philip Gladstone) - * udp.c: patch #8358: allow more combinations of listening PCB for IPv6 - - 2016-04-05: Simon Goldschmidt - * netconn/socket API: fixed bug# 43739 (Accept not reporting errors about - aborted connections): netconn_accept() returns ERR_ABRT (sockets: ECONNABORTED) - for aborted connections, ERR_CLSD (sockets: EINVAL) if the listening netconn - is closed, which better seems to follow the standard. - - 2016-03-23: Florent Matignon - * dhcp.c: fixed bug #38203: DHCP options are not recorded in all DHCP ack messages - - 2016-03-22: Simon Goldschmidt - * tcp: changed accept handling to be done internally: the application does not - have to call tcp_accepted() any more. Instead, when delaying accept (e.g. sockets - do), call tcp_backlog_delayed()/tcp_backlog_accepted() (fixes bug #46696) - - 2016-03-22: Simon Goldschmidt - * dns.c: ignore dns response parsing errors, only abort resolving for correct - responses or error responses from correct server (bug #47459) - - 2016-03-17: Simon Goldschmidt - * api_msg.c: fixed bug #47448 (netconn/socket leak if RST is received during close) - - 2016-03-17: Joel Cunningham - * api_msg.c: don't fail closing a socket/netconn when failing to allocate the - FIN segment; blocking the calling thread for a while is better than risking - leaking a netconn/socket (see bug #46701) - - 2016-03-16: Joel Cunningham - * tcp_out.c: reset rto timer on fast retransmission - - 2016-03-16: Deomid Ryabkov - * tcp_out.c: fixed bug #46384 Segment size calculation bug with MSS != TCP_MSS - - 2016-03-05: Simon Goldschmidt - * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error - - 2015-11-19: fix by Kerem Hadimli - * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new - netconn was already closed because of peer behavior - - 2015-11-12: fix by Valery Ushakov - * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort() - - 2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt - * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089, - reduce ram/rom usage of tables): incompatible change for private MIBs - - 2015-09-30: Simon Goldschmidt - * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range - of all address parts - - 2015-08-28: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh - is set to the full send window for active open, too, and is updated once - after SYN to ensure the correct send window is used - - 2015-08-28: Simon Goldschmidt - * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks - - 2015-08-26: Simon Goldschmidt - * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms: - define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header - instead of referencing it, which gives more room for struct ip6_reass_helper - - 2015-08-25: Simon Goldschmidt - * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK - - 2015-08-20: Manoj Kumar - * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255 - from SNMP agent - - 2015-08-19: Jens Nielsen - * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple - interfaces handling - - 2015-08-19: Simon Goldschmidt (patch by "Sandra") - * dns.c: fixed bug #45004: dns response without answer might be discarded - - 2015-08-18: Chrysn - * timers.c: patch #8704 fix sys_timeouts_sleeptime function - - 2015-07-01: Erik Ekman - * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset - is at start of pbuf in chain) - - 2015-05-19: Simon Goldschmidt - * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after - fixing bug #38204) - - 2015-03-21: Simon Goldschmidt (patch by Homyak) - * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in - two places) - - 2015-03-21: Simon Goldschmidt - * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input() - after tcp_close()) - - 2015-03-21: Simon Goldschmidt - * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for - data ACKed with the same ack as FIN) - - 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) - * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) - - 2015-03-20: Simon Goldschmidt - * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) - - 2015-03-19: Simon Goldschmidt - * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning - netconn->last_err (fixed bugs #38121 and #37676) - - 2015-03-09: Simon Goldschmidt - * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status) - - 2015-03-04: Simon Goldschmidt - * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation) - - 2015-03-04: Valery Ushakov - * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test) - - 2015-03-04: Zach Smith - * nd6.c: fixed bug #38153 (nd6_input() byte order issues) - - 2015-02-26: Simon Goldschmidt - * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif - remove) - - 2015-02-25: Simon Goldschmidt - * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted - packets), implemented task #12357 (Ensure that malicious packets don't - assert-fail): improved some pbuf_header calls to not assert-fail. - - 2015-02-25: patch by Joel Cunningham - * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast - datagrams) - - 2015-02-25: patch by Greg Renda - * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram) - - 2015-02-25: Simon Goldschmidt - * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership - are dropped when socket (not netconn!) is closed. - - 2015-02-25: Simon Goldschmidt - * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by - adding an optional default netif for multicast routing - - 2015-02-25: Simon Goldschmidt - * netconn API: fixed that netconn_connect still used message passing for - LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-22: patch by Jens Nielsen - * icmp.c: fixed bug #38803 (Source address in broadcast ping reply) - - 2015-02-22: Simon Goldschmidt - * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip - (previously used by get/setsockopt only) - - 2015-02-18: Simon Goldschmidt - * sockets.c: Fixed select not reporting received FIN as 'readable' in certain - rare cases (bug #43779: select(), close(), and TCP retransmission error) - - 2015-02-17: Simon Goldschmidt - * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno": - return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already - connected - - 2015-02-17: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from - ipX_output are not processed". Now tcp_output(_segment) checks for the return - value of ipX_output and does not try to send more on error. A netif driver - can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers - are available again. - - 2015-02-14: patches by Freddie Chopin - * snmp*: made community writable, fixed some const pointers - - 2015-02-13: Simon Goldschmidt - * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP" - - 2015-02-12: Simon Goldschmidt - * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass - inp to higher layers": now the accepting netif is passed up, but the input - netif is available through ip_current_input_netif() if required. - - 2015-02-11: patch by hichard - * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6" - - 2015-02-10: Simon Goldschmidt - * netconn API: fixed that netconn_close/netconn_delete still used message passing - for LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-10: Simon Goldschmidt - * netconn/socket api: fixed bug #44225 "closing TCP socket should time out - eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets - times out after 20 seconds or after the configured SND_TIMEOUT or depending - on the linger settings. - - 2015-01-27: Simon Goldschmidt - * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, - fixed return value of lwip_netconn_do_close on unconnected netconns - - 2015-01-17: Simon Goldschmidt - * sockets.c: fixed bug #43361 select() crashes with stale FDs - - 2015-01-17: Simon Goldschmidt - * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" - by rewriting set/getsockopt functions to combine checks with the actual code - and add more NULL checks; this also fixes that CORE_LOCKING used message - passing for set/getsockopt. - - 2014-12-19: Simon Goldschmidt - * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only - when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for - compatibility reasons) - - 2014-12-17: Simon Goldschmidt - * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for - no-copy data with odd length - - 2014-12-10: Simon Goldschmidt - * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO - take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can - be used to revert to the old 'winsock' style behaviour) - Fixed implementation of SO_ACCEPTCONN to just look at the pcb state - - 2014-12-09: Simon Goldschmidt - * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded - - 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) - * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 - event_callback() handle context switch when calling sys_sem_signal() - - 2014-10-21: Simon Goldschmidt - * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set - - 2014-09-16: Kevin Cernekee - * dns.c: patch #8480 Fix handling of dns_seqno wraparound - - 2014-09-16: Simon Goldschmidt - * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN - when sending FIN - - 2014-09-03: Simon Goldschmidt - * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error - - 2014-09-02: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before - listen() will cause a error - - 2014-09-02: Simon Goldschmidt - * sockets.c: fixed bug #42117 lwip_fcntl does not set errno - - 2014-09-02: Simon Goldschmidt - * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list - - 2014-08-20: Simon Goldschmidt - * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to - non-randomized TXIDs - - 2014-06-03: Simon Goldschmidt - * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in - tcp_input function - - 2014-05-20: Simon Goldschmidt - * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state - - 2014-05-19: Simon Goldschmidt - * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores - from header include guards) - - 2014-04-08: Simon Goldschmidt - * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) - - 2014-04-06: Simon Goldschmidt - * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received - unacceptable ACK - - 2014-04-06: Simon Goldschmidt - * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery - is invalid when an IP is set to thet netif. - - 2014-03-14: Simon Goldschmidt - * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 - - 2014-03-11: Simon Goldschmidt (patch by Mason) - * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for - POSIX-compliance - - 2014-02-27: Simon Goldschmidt - * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST - - 2014-02-27: Simon Goldschmidt - * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when - IP_SOF_BROADCAST_RECV==1 - - 2014-02-27: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on - unconnected/listening TCP sockets - - 2014-02-27: Simon Goldschmidt - * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 - - 2014-02-25: Simon Goldschmidt - * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface - - 2014-02-25: Simon Goldschmidt, patch by Fatih Asici - * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() - - 2014-02-25: Simon Goldschmidt - * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; - renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() - - 2014-02-25: Simon Goldschmidt - * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry - - 2014-02-20: Simon Goldschmidt - * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with - MEM_ALIGNMENT = 8 - - 2014-02-20: Simon Goldschmidt - * sockets.c: fixed bug #39882 No function shall set errno to 0 - - 2014-02-20: Simon Goldschmidt - * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 - - 2014-02-20: Simon Goldschmidt - * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow - - 2014-01-08: Stathis Voukelatos - * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool - creation macro - - 2014-01-18: Brian Fahs - * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize - when necessary - - 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt - * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback - - 2014-01-16: Stathis Voukelatos - * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 - - 2014-01-14: "Freddie Chopin" - * snmp.h, mib2.c: fixed constness and spelling of sysdescr - - 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) - * tcpip.c: patch #8241: Fix implicit declaration of ip_input with - LWIP_TCPIP_CORE_LOCKING_INPUT disabled - - 2014-01-14: chrysn - * timers.c: patch #8244 make timeouts usable reliably from outside of the - timeout routine - - 2014-01-10: Simon Goldschmidt - * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly - - 2014-01-10: Simon Goldschmidt - * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 - - 2014-01-10: Simon Goldschmidt - * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop - - 2013-06-29: Simon Goldschmidt - * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) - - 2013-06-29: Simon Goldschmidt - * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec - - 2013-04-24: patch by Liam - * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert - - 2013-04-24: Simon Goldschmidt - * igmp.c: fixed possible division by zero - - 2013-04-24: Simon Goldschmidt - * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h - - 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): - * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" - - 2013-01-15: Simon Goldschmidt - * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order - - 2013-01-15: Simon Goldschmidt - * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning - - 2013-01-14: Simon Goldschmidt - * dns.c: fixed bug #37705 Possible memory corruption in DNS query - - 2013-01-11: Simon Goldschmidt - * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-08-13: Simon Goldschmidt - * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start - dereferences NULL - - 2012-08-13: Simon Goldschmidt - * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps - configured but no interfaces available - - 2012-08-13: Simon Goldschmidt - * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time - - 2012-05-11: Simon Goldschmidt (patch by Marty) - * memp.c: fixed bug #36412: memp.c does not compile when - MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 - - 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) - * ppp.c: fixed bug #36283 (PPP struct used on header size computation and - not packed) - - 2012-05-03: Simon Goldschmidt (patch by David Empson) - * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with - zero length) - - 2012-03-25: Simon Goldschmidt - * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed - for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 - - 2012-03-25: Simon Goldschmidt - * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space - pollution in api_msg.c and netifapi.c - - 2011-08-24: Simon Goldschmidt - * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard - - - -(STABLE-1.4.1) - - ++ New features: - - 2012-03-25: Simon Goldschmidt (idea by Mason) - * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h - which are a simple wrapper to the correct lwIP include files. - - 2012-01-16: Simon Goldschmidt - * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP - - 2011-12-17: Simon Goldschmidt - * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) - (fixes bug #35061) - - 2011-09-27: Simon Goldschmidt - * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) - (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) - - 2011-09-21: Simon Goldschmidt - * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on - send (TCP only, bug #33820) - - 2011-09-21: Simon Goldschmidt - * init.c: Converted runtime-sanity-checks into compile-time checks that can - be disabled (since runtime checks can often not be seen on embedded targets) - - 2011-09-11: Simon Goldschmidt - * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file - to get a clear separation of which functions an application or port may use - (task #11281) - - 2011-09-11: Simon Goldschmidt - * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize - initial local TCP/UDP ports (so that different port ranges are used after - a reboot; bug #33818; this one added tcp_init/udp_init functions again) - - 2011-09-03: Simon Goldschmidt - * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) - - 2011-08-24: Simon Goldschmidt - * opt.h, netif.h/.c: added netif remove callback (bug #32397) - - 2011-07-26: Simon Goldschmidt - * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter - function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) - - 2011-07-21: Simon Goldschmidt (patch by hanhui) - * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: - Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. - Also added code to allow ip_forward() to forward non-broadcast packets to - the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). - - 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) - * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that - pcb->state != LISTEN - - 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) - * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static - memory message - - - ++ Bugfixes: - - 2012-09-26: Simon Goldschmidt - * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7843 Fix corner case with dhcp timeouts - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-05-08: Simon Goldschmidt - * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was - a debug-check issue only) - - 2012-03-27: Simon Goldschmidt - * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c - - 2012-03-27: Simon Goldschmidt (patch by Mason) - * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the - send MSS - - 2012-03-22: Simon Goldschmidt - * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward - - 2012-03-20: Simon Goldschmidt (patch by Mason) - * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list - - 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) - * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, - possible bug on little endian system - - 2012-02-23: Simon Goldschmidt - * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt - * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() - (bug #35541: PPP Memory Leak) - - 2012-02-16: Simon Goldschmidt - * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) - * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed - - 2012-02-15: Simon Goldschmidt - * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with - MEMP_MEM_MALLOC==1 - - 2012-02-12: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on - MSS > pcb->snd_wnd (by not creating segments bigger than half the window) - - 2012-02-11: Simon Goldschmidt - * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait - queue while closing - - 2012-01-22: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) - - 2012-01-21: Simon Goldschmidt - * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb - - 2012-01-20: Simon Goldschmidt - * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths - - 2012-01-20: Simon Goldschmidt - * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy - - 2011-11-25: Simon Goldschmidt - * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt - tcp_active_pcbs in some cases - - 2011-11-23: Simon Goldschmidt - * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with - '#ifndef sys_msleep' - - 2011-11-22: Simon Goldschmidt - * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when - netif is brought down - - 2011-10-28: Simon Goldschmidt - * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks - - 2011-10-23: Simon Goldschmidt - * mem.c: fixed bug #34429: possible memory corruption with - LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 - - 2011-10-18: Simon Goldschmidt - * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard - error value - - 2011-10-18: Simon Goldschmidt - * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small - windows (bug #34176 select after non-blocking send times out) - - 2011-10-18: Simon Goldschmidt - * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't - consider netif->mtu, causes slow network - - 2011-10-18: Simon Goldschmidt - * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code - - 2011-10-18: Simon Goldschmidt - * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS - - 2011-10-17: Simon Goldschmidt - * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api - - 2011-10-13: Simon Goldschmidt - * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no - zero window is received) by starting the persist timer when a zero window is - received, not when we have more data queued for sending than fits into the - window - - 2011-10-13: Simon Goldschmidt - * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex - - 2011-10-13: Simon Goldschmidt - * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is - used and not all protocols are enabled - - 2011-10-12: Simon Goldschmidt - * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 - - 2011-10-09: Simon Goldschmidt - * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect - byte value when pcb->unacked != NULL - - 2011-10-09: Simon Goldschmidt - * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong - - 2011-09-27: Simon Goldschmidt - * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... - - 2011-09-27: Simon Goldschmidt - * tcp_in.c: fixed bug #28288: Data after FIN in oos queue - - 2011-09-27: Simon Goldschmidt - * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf - - 2011-09-24: Simon Goldschmidt - * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 - - 2011-09-23: Simon Goldschmidt - * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for - the last packet including FIN can lose data - - 2011-09-22: Simon Goldschmidt - * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into - account - - 2011-09-21: Simon Goldschmidt - * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks - in init.c - - 2011-09-20: Simon Goldschmidt - * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) - - 2011-09-11: Simon Goldschmidt - * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs - (bug #34019) - - 2011-09-09: Simon Goldschmidt - * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if - udp port matches - - 2011-09-03: Simon Goldschmidt - * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet - is aggregated and sent to application - - 2011-09-01: Simon Goldschmidt - * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared - to other options - - 2011-09-01: Simon Goldschmidt - * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno - - 2011-08-24: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling - accept() on UDP connections - - 2011-08-24: Simon Goldschmidt - * sockets.h: fixed bug #34057 socklen_t should be a typedef - - 2011-08-24: Simon Goldschmidt - * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) - - 2011-08-24: Simon Goldschmidt - * dhcp.c: fixed bug #34122 dhcp: hostname can overflow - - 2011-08-24: Simon Goldschmidt - * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr - - 2011-08-22: Simon Goldschmidt - * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This - merely prevents nagle from not transmitting fast after closing.) - - 2011-07-22: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns - always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now - lwip_send() sends as much as possible for non-blocking sockets - - 2011-07-22: Simon Goldschmidt - * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented - for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() - at regular intervals from main level. - - 2011-07-21: Simon Goldschmidt - * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by - sending an ARP request when an ARP entry is used in the last minute before - it would time out. - - 2011-07-04: Simon Goldschmidt - * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. - - 2011-06-26: Simon Goldschmidt - * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by - updating its documentation only. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an - unaligned pointer. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" - - 2011-05-25: Simon Goldschmidt - * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) - - - -(STABLE-1.4.0) - - ++ New features: - - 2011-03-27: Simon Goldschmidt - * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and - calculate it in tcp_zero_window_probe (the only place where it was used). - - 2010-11-21: Simon Goldschmidt - * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif - (fixes bug #31525). - - 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) - * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for - IP_MULTICAST_LOOP at socket- and raw-API level. - - 2010-06-16: Simon Goldschmidt - * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow - link-layer-addressed UDP traffic to be received while a netif is down (just - like DHCP during configuration) - - 2010-05-22: Simon Goldschmidt - * many many files: bug #27352: removed packing from ip_addr_t, the packed - version is now only used in protocol headers. Added global storage for - current src/dest IP address while in input functions. - - 2010-05-16: Simon Goldschmidt - * def.h: task #10391: Add preprocessor-macros for compile-time htonl - calculation (and use them throughout the stack where applicable) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool - instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own - MEMP pool instead of the heap - - 2010-05-13: Simon Goldschmidt - * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added - new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast - packets to more than one pcb. - - 2010-05-02: Simon Goldschmidt - * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending - UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-04-30: Simon Goldschmidt - * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that - take a precalculated checksum, added pbuf_fill_chksum() to copy data - into a pbuf and at the same time calculating the checksum for that data - - 2010-04-29: Simon Goldschmidt - * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying - 2-byte-aligned IP addresses and MAC addresses - - 2010-04-28: Patch by Bill Auerbach - * ip.c: Inline generating IP checksum to save a function call - - 2010-04-14: Simon Goldschmidt - * tcpip.h/.c, timers.c: Added an overridable define to get informed when the - tcpip_thread processes messages or timeouts to implement a watchdog. - - 2010-03-28: Simon Goldschmidt - * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing - fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-03-27: Simon Goldschmidt - * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ - etharp_query to prevent unnecessary function calls (inspired by - patch #7135). - - 2010-03-20: Simon Goldschmidt - * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code - since the linker cannot do this automatically to save space. - - 2010-03-20: Simon Goldschmidt - * opt.h, etharp.c/.h: Added support for static ARP table entries - - 2010-03-14: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum - when creating TCP segments, not when (re-)transmitting them. - - 2010-03-07: Simon Goldschmidt - * sockets.c: bug #28775 (select/event_callback: only check select_cb_list - on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. - This should speed up receiving data on sockets as the select code in - event_callback is only executed when select is waiting. - - 2010-03-06: Simon Goldschmidt - * tcp_out.c: task #7013 (Create option to have all packets delivered to - netif->output in one piece): Always copy to try to create single pbufs - in tcp_write. - - 2010-03-06: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv - by not allocating a netbuf): added function netconn_recv_tcp_pbuf() - for tcp netconns to receive pbufs, not netbufs; use that function - for tcp sockets. - - 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt - * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: - Work on tcp_enqueue: Don't waste memory when chaining segments, - added option TCP_OVERSIZE to prevent creating many small pbufs when - calling tcp_write with many small blocks of data. Instead, pbufs are - allocated larger than needed and the space is used for later calls to - tcp_write. - - 2010-02-21: Simon Goldschmidt - * stats.c/.h: Added const char* name to mem- and memp-stats for easier - debugging. - - 2010-02-21: Simon Goldschmidt - * tcp.h (and usages), added tcp_impl.h: Splitted API and internal - implementation of tcp to make API usage cleare to application programmers - - 2010-02-14: Simon Goldschmidt/Stephane Lesage - * ip_addr.h: Improved some defines working on ip addresses, added faster - macro to copy addresses that cannot be NULL - - 2010-02-13: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- - blocking send operation) - - 2010-02-12: Simon Goldschmidt - * sockets.c/.h: Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - 2010-02-12: Simon Goldschmidt - * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated - memory): added autoip_set_struct() and dhcp_set_struct() to let autoip - and dhcp work with user-allocated structs instead of callin mem_malloc - - 2010-02-12: Simon Goldschmidt/Jeff Barber - * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has - SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT - - 2010-02-12: Simon Goldschmidt - * sys layer: task #10139 (Prefer statically allocated memory): converted - mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; - converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX - to let sys.h use binary semaphores instead of mutexes - as before) - - 2010-02-09: Simon Goldschmidt (Simon Kallweit) - * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 - (Restart system timeout handling) - - 2010-02-09: Simon Goldschmidt - * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into - netif.c) - loopif does not have to be created by the port any more, - just define LWIP_HAVE_LOOPIF to 1. - - 2010-02-08: Simon Goldschmidt - * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa - inet_ntoa_r/ipaddr_ntoa_r - - 2010-02-08: Simon Goldschmidt - * netif.h: Added netif_s/get_igmp_mac_filter() macros - - 2010-02-05: Simon Goldschmidt - * netif.h: Added function-like macros to get/set the hostname on a netif - - 2010-02-04: Simon Goldschmidt - * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to - make changing the actual implementation behind the typedef easier. - - 2010-02-01: Simon Goldschmidt - * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool - for allocating memory when getaddrinfo() is called. - - 2010-01-31: Simon Goldschmidt - * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse - them once instead of parsing for every option. This also removes - the need for mem_malloc from dhcp_recv and makes it possible to - correctly retrieve the BOOTP file. - - 2010-01-30: simon Goldschmidt - * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect - the sockets array. - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, api_msg.c, sockets.c: Added except set support in select - (patch #6860) - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: - Add non-blocking support for connect (partly from patch #6860), - plus many cleanups in socket & netconn API. - - 2010-01-27: Simon Goldschmidt - * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding - to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 - - 2010-01-26: Simon Goldschmidt - * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. - - 2010-01-14: Simon Goldschmidt - * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback - by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() - - 2010-01-13: Simon Goldschmidt - * mem.c: The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - (patch #6966 and bug #26133) - - 2010-01-10: Simon Goldschmidt (Bill Auerbach) - * opt.h, memp.c: patch #6822 (Add option to place memory pools in - separate arrays) - - 2010-01-10: Simon Goldschmidt - * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define - LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) - - 2009-12-31: Simon Goldschmidt - * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h - added timers.c/.h: Separated timer implementation from semaphore/mbox - implementation, moved timer implementation to timers.c/.h, timers are - now only called from tcpip_thread or by explicitly checking them. - (TASK#7235) - - 2009-12-27: Simon Goldschmidt - * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option - LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) - - - ++ Bugfixes: - - 2011-04-20: Simon Goldschmidt - * sys_arch.txt: sys_arch_timeouts() is not needed any more. - - 2011-04-13: Simon Goldschmidt - * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by - using ports in the IANA private/dynamic range (49152 through 65535). - - 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: - * etharp.h/.c: Fixed broken VLAN support. - - 2011-03-27: Simon Goldschmidt - * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp - pcbs) by checking if the pcb was bound (local_port != 0). - - 2011-03-27: Simon Goldschmidt - * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) - - 2011-03-27: Simon Goldschmidt - * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and - raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. - - 2011-03-27: Simon Goldschmidt - * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route - is present never times out) by starting retransmission timer before checking - route. - - 2011-03-22: Simon Goldschmidt - * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only - calling sio_read_abort() if the file descriptor is valid. - - 2011-03-14: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect - more than once can render a socket useless) since it mainly involves changing - "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. - - 2011-03-13: Simon Goldschmidt - * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing - err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: - use EALRADY instead of -1 - - 2011-03-13: Simon Goldschmidt - * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the - connection has been aborted by err_tcp (since this is not a normal closing - procedure). - - 2011-03-13: Simon Goldschmidt - * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind - with pcb->state != CLOSED - - 2011-02-17: Simon Goldschmidt - * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in - documentation - - 2011-02-17: Simon Goldschmidt - * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. - - 2011-01-24: Simon Goldschmidt - * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems - - 2010-12-02: Simon Goldschmidt - * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. - - 2010-11-23: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for - LWIP_SO_RCVBUF and ioctl/FIONREAD. - - 2010-11-23: Simon Goldschmidt - * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at - least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. - - 2010-11-23: Simon Goldschmidt - * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after - refusing 'refused_data' again. - - 2010-11-22: Simon Goldschmidt - * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS - after a successful nonblocking connection. - - 2010-11-22: Simon Goldschmidt - * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr - must be sent link-local - - 2010-11-22: Simon Goldschmidt - * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for - LWIP_TIMERS==0 - - 2010-11-20: Simon Goldschmidt - * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number - - 2010-11-20: Simon Goldschmidt - * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to - resemble other stacks. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else - no-copy TCP writes will never succeed. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does - not match documentation: return ERR_ARG instead of ERR_VAL if not - initialized or wrong argument. - - 2010-10-20: Simon Goldschmidt - * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 - - 2010-10-05: Simon Goldschmidt - * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when - replugging the network cable after an AutoIP address was assigned. - - 2010-08-10: Simon Goldschmidt - * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs - - 2010-08-03: Simon Goldschmidt - * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) - - 2010-08-01: Simon Goldschmidt (patch by Greg Renda) - * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big - endian architectures) - - 2010-07-28: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP - disabled. - - 2010-07-27: Simon Goldschmidt - * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no - harm but never did anything - - 2010-07-21: Simon Goldschmidt - * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not - add IP options) - - 2010-07-16: Kieran Mansley - * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator - - 2010-07-10: Simon Goldschmidt - * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options - - 2010-06-30: Simon Goldschmidt - * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in - netconn_delete) - - 2010-06-28: Kieran Mansley - * timers.c remove unportable printing of C function pointers - - 2010-06-24: Simon Goldschmidt - * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag - NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading - - 2010-06-24: Simon Goldschmidt - * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly - implemented shutdown at socket level. - - 2010-06-21: Simon Goldschmidt - * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has - problems with zero-copy DMA MACs) by adding custom pbufs and implementing - custom pbufs that reference other (original) pbufs. Additionally set - IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. - - 2010-06-15: Simon Goldschmidt - * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses - - 2010-06-14: Simon Goldschmidt - * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses - - 2010-06-12: Simon Goldschmidt - * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop - state - - 2010-05-17: Simon Goldschmidt - * netdb.c: Correctly NULL-terminate h_addr_list - - 2010-05-16: Simon Goldschmidt - * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent - "symbol already defined" i.e. when linking to winsock - - 2010-05-05: Simon Goldschmidt - * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may - overflow) - - 2010-04-21: Simon Goldschmidt - * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening - connection) - - 2010-03-28: Luca Ceresoli - * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers - - 2010-03-27: Luca Ceresoli - * mib2.c: patch #7130: remove meaningless const qualifiers - - 2010-03-26: Simon Goldschmidt - * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too - - 2010-03-26: Simon Goldschmidt - * various files: Fixed compiling with different options disabled (TCP/UDP), - triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled - - 2010-03-25: Simon Goldschmidt - * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly - - 2010-03-25: Simon Goldschmidt - * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side - overrunning our rcv_wnd in ooseq case. - - 2010-03-22: Simon Goldschmidt - * tcp.c: tcp_listen() did not copy the pcb's prio. - - 2010-03-19: Simon Goldschmidt - * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set - - 2010-03-14: Simon Goldschmidt - * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports - where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h - and basing PBUF_LINK_HLEN on it. - - 2010-03-08: Simon Goldschmidt - * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections - when assiging routable address): when checking incoming packets and - aborting existing connection on address change, filter out link-local - addresses. - - 2010-03-06: Simon Goldschmidt - * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING - - 2010-03-06: Simon Goldschmidt - * ipv4/ip.c: Don't try to forward link-local addresses - - 2010-03-06: Simon Goldschmidt - * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- - addresses to gw - - 2010-03-05: Simon Goldschmidt - * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type - and state. - - 2010-03-05: Simon Goldschmidt - * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split - into multiple calls to tcp_write. - - 2010-02-21: Simon Goldschmidt - * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep - the implementation of DNS_USES_STATIC_BUF==1) - - 2010-02-20: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement - close() vs. shutdown(). Now the application does not get any more - recv callbacks after calling tcp_close(). Added tcp_shutdown(). - - 2010-02-19: Simon Goldschmidt - * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent - confusion with realloc() - - 2010-02-15: Simon Goldschmidt/Stephane Lesage - * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK - (fixes bug #28899) - - 2010-02-14: Simon Goldschmidt - * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with - LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and - admin-status of a netif are up - - 2010-02-14: Simon Goldschmidt - * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet - reception and is not really necessary - - 2010-02-14: Simon Goldschmidt - * etharp.c/.h: Fixed ARP input processing: only add a new entry if a - request was directed as us (RFC 826, Packet Reception), otherwise - only update existing entries; internalized some functions - - 2010-02-14: Simon Goldschmidt - * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be - disabled on netif used for PPPoE) by adding a new netif flag - (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet - device but prevents usage of ARP (so that ethernet_input can be used - for PPPoE). - - 2010-02-12: Simon Goldschmidt - * netif.c: netif_set_link_up/down: only do something if the link state - actually changes - - 2010-02-12: Simon Goldschmidt/Stephane Lesage - * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking - connect) - - 2010-02-12: Simon Goldschmidt - * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) - - 2010-02-09: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 - (recv() makes receive window update for data that wasn't received by - application) - - 2010-02-09: Simon Goldschmidt/Stephane Lesage - * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out - or any netconn_recv() error) - - 2010-02-09: Simon Goldschmidt - * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) - - 2010-02-09: Simon Goldschmidt - * netif.c: For loopback packets, adjust the stats- and snmp-counters - for the loopback netif. - - 2010-02-08: Simon Goldschmidt - * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity - since they are not used anywhere else. - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats - (patch from bug #28798) - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and - another bug when LWIP_RAND() returns zero. - - 2010-02-04: Simon Goldschmidt - * nearly every file: Use macros defined in ip_addr.h (some of them new) - to work with IP addresses (preparation for bug #27352 - Change ip_addr - from struct to typedef (u32_t) - and better code). - - 2010-01-31: Simon Goldschmidt - * netif.c: Don't call the link-callback from netif_set_up/down() since - this invalidly retriggers DHCP. - - 2010-01-29: Simon Goldschmidt - * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the - portability file inet.h and its contents from the stack: moved htonX- - functions to def.h (and the new def.c - they are not ipv4 dependent), - let inet.h depend on ip_addr.h and not the other way round. - This fixes bug #28732. - - 2010-01-28: Kieran Mansley - * tcp.c: Ensure ssthresh >= 2*MSS - - 2010-01-27: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv - callback can lead to accessing unallocated memory. As a consequence, - ERR_ABRT means the application has called tcp_abort()! - - 2010-01-25: Simon Goldschmidt - * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY - not implemented in SNMP): write-only or not-accessible are still - returned by getnext (though not by get) - - 2010-01-24: Simon Goldschmidt - * snmp: Renamed the private mib node from 'private' to 'mib_private' to - not use reserved C/C++ keywords - - 2010-01-23: Simon Goldschmidt - * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less - than 1 ms - - 2010-01-21: Simon Goldschmidt - * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called - if tcp_enqueue fails) both in raw- and netconn-API - - 2010-01-19: Simon Goldschmidt - * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp - - 2010-01-18: Iordan Neshev/Simon Goldschmidt - * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some - bugfix backports from 2.4.x. - - 2010-01-18: Simon Goldschmidt - * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong - - 2010-01-17: Simon Goldschmidt - * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): - task #10102: "netconn: clean up conn->err threading issues" by adding - error return value to struct api_msg_msg - - 2010-01-17: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() - to return err_t (bugs #27709 and #28087) - - 2010-01-14: Simon Goldschmidt - * ...: Use typedef for function prototypes throughout the stack. - - 2010-01-13: Simon Goldschmidt - * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive - window = 0) by correctly draining recvmbox/acceptmbox - - 2010-01-11: Simon Goldschmidt - * pap.c: Fixed bug #13315 (PPP PAP authentication can result in - erroneous callbacks) by copying the code from recent pppd - - 2010-01-10: Simon Goldschmidt - * raw.c: Fixed bug #28506 (raw_bind should filter received packets) - - 2010-01-10: Simon Goldschmidt - * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) - - 2010-01-08: Simon Goldschmidt - * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) - - 2010-01-08: Simon Goldschmidt - * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string - passed to dns_local_addhost() might be volatile - - 2010-01-07: Simon Goldschmidt - * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too - - 2010-01-06: Simon Goldschmidt - * netdb.h: Fixed bug #28496: missing include guards in netdb.h - - 2009-12-31: Simon Goldschmidt - * many ppp files: Reorganised PPP source code from ucip structure to pppd - structure to easily compare our code against the pppd code (around v2.3.1) - - 2009-12-27: Simon Goldschmidt - * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted - unit test - - -(STABLE-1.3.2) - - ++ New features: - - 2009-10-27 Simon Goldschmidt/Stephan Lesage - * netifapi.c/.h: Added netifapi_netif_set_addr() - - 2009-10-07 Simon Goldschmidt/Fabian Koch - * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to - support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) - - 2009-08-26 Simon Goldschmidt/Simon Kallweit - * slipif.c/.h: bug #26397: SLIP polling support - - 2009-08-25 Simon Goldschmidt - * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), - New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. - - 2009-08-25 Simon Goldschmidt - * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) - - 2009-08-24 Jakob Stoklund Olesen - * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond - to netif_set_link_up(). - - 2009-08-23 Simon Goldschmidt - * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state - to a human-readable string. - - ++ Bugfixes: - - 2009-12-24: Kieran Mansley - * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing - (BUG#28241) - - 2009-12-06: Simon Goldschmidt - * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can - be statically allocated (like in ucip) - - 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) - * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT - - 2009-12-03: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit - could have non-zero length - - 2009-12-02: Simon Goldschmidt - * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting - tcp_input_pcb until after calling the pcb's callbacks - - 2009-11-29: Simon Goldschmidt - * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- - sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code - - 2009-11-29: Simon Goldschmidt - * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by - queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty - - 2009-11-26: Simon Goldschmidt - * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending - segment - - 2009-11-26: Simon Goldschmidt - * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle - algorithm at PCB level - - 2009-11-22: Simon Goldschmidt - * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent - - 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) - * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when - reusing time-wait pcb - - 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) - * sockets.c: Fixed bug #28062: Data received directly after accepting - does not wake up select - - 2009-11-11: Simon Goldschmidt - * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) - - 2009-10-30: Simon Goldschmidt - * opt.h: Increased default value for TCP_MSS to 536, updated default - value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. - - 2009-10-28: Kieran Mansley - * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code - to follow algorithm from TCP/IP Illustrated - - 2009-10-27: Kieran Mansley - * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK - - 2009-10-25: Simon Goldschmidt - * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if - pcb->recv is NULL to keep rcv_wnd correct) - - 2009-10-25: Simon Goldschmidt - * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state - - 2009-10-23: Simon Goldschmidt (David Empson) - * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes - - 2009-10-21: Simon Goldschmidt - * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and - trailing 1 byte len (SYN/FIN) - - 2009-10-21: Simon Goldschmidt - * tcp_out.c: Fixed bug #27315: zero window probe and FIN - - 2009-10-19: Simon Goldschmidt - * dhcp.c/.h: Minor code simplification (don't store received pbuf, change - conditional code to assert where applicable), check pbuf length before - testing for valid reply - - 2009-10-19: Simon Goldschmidt - * dhcp.c: Removed most calls to udp_connect since they aren't necessary - when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. - - 2009-10-16: Simon Goldschmidt - * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop - valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is - enabled - - 2009-10-15: Simon Goldschmidt (Oleg Tyshev) - * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit - - 2009-10-15: Simon Goldschmidt - * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() - timeout - - 2009-10-15: Simon Goldschmidt - * autoip.c: Fixed bug #27704: autoip starts with wrong address - LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead - of network byte order - - 2009-10-11 Simon Goldschmidt (Jörg Kesten) - * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments - which are not consecutive when retransmitting unacked segments - - 2009-10-09 Simon Goldschmidt - * opt.h: Fixed default values of some stats to only be enabled if used - Fixes bug #27338: sys_stats is defined when NO_SYS = 1 - - 2009-08-30 Simon Goldschmidt - * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK - function" by checking for loopback before calling ip_frag - - 2009-08-25 Simon Goldschmidt - * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27078: Possible memory leak in pppInit() - - 2009-08-23 Simon Goldschmidt - * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result - is error. - - 2009-08-23 Simon Goldschmidt - * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF - Fixed wrong parenthesis, added check in init.c - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms - - 2009-08-23 Simon Goldschmidt - * many ppp files: bug #27267: Added include to string.h where needed - - 2009-08-23 Simon Goldschmidt - * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) - - -(STABLE-1.3.1) - - ++ New features: - - 2009-05-10 Simon Goldschmidt - * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option - LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only - one pbuf to help MACs that don't support scatter-gather DMA. - - 2009-05-09 Simon Goldschmidt - * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming - ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - - 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen - * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive - extended info about the currently received packet. - - 2009-04-27 Simon Goldschmidt - * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 - - 2009-04-25 Simon Goldschmidt - * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next - bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). - - 2009-04-21 Simon Goldschmidt - * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static - hosts table. New configuration options DNS_LOCAL_HOSTLIST and - DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined - as an external function for lookup. - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for - TCP timestamp options, off by default. Rework tcp_enqueue() to - take option flags rather than specified option data - - 2009-02-18 Simon Goldschmidt - * cc.h: Added printf formatter for size_t: SZT_F - - 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) - * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast - pings - - 2009-02-12 Simon Goldschmidt - * init.h: Added LWIP_VERSION to get the current version of the stack - - 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) - * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead - of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc - is otherwise used) - - 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) - * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() - is only used by UDPLITE at present, so conditionalise it. - - 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) - * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP - "seed" address. This should reduce AUTOIP conflicts if - LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. - - 2008-10-02 Jonathan Larmour and Rishi Khan - * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking - socket. - - 2008-06-30 Simon Goldschmidt - * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from - interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows - mem_free to run between mem_malloc iterations. Added illegal counter for - mem stats. - - 2008-06-27 Simon Goldschmidt - * stats.h/.c, some other files: patch #6483: stats module improvement: - Added defines to display each module's statistic individually, added stats - defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. - - 2008-06-17 Simon Goldschmidt - * err.h: patch #6459: Made err_t overridable to use a more efficient type - (define LWIP_ERR_T in cc.h) - - 2008-06-17 Simon Goldschmidt - * slipif.c: patch #6480: Added a configuration option for slipif for symmetry - to loopif - - 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) - * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly - modified version of patch # 6370: Moved loopif code to netif.c so that - loopback traffic is supported on all netifs (all local IPs). - Added option to limit loopback packets for each netifs. - - - ++ Bugfixes: - 2009-08-12 Kieran Mansley - * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when - out of window or out of order properly - - 2009-08-12 Kieran Mansley - * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 - - 2009-07-28 Simon Goldschmidt - * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s - - 2009-07-27 Kieran Mansley - * api.h api_msg.h netdb.h sockets.h: add missing #include directives - - 2009-07-09 Kieran Mansley - * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for - recv_avail and don't increment counters until message successfully - sent to mbox - - 2009-06-25 Kieran Mansley - * api_msg.c api.h: BUG26722: initialise netconn write variables - in netconn_alloc - - 2009-06-25 Kieran Mansley - * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set - - 2009-06-25 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct - simultaneous close behaviour, and make snd_nxt have the same meaning - as in the RFCs. - - 2009-05-12 Simon Goldschmidt - * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on - arp_table / uses etharp_query" by adding etharp_gratuitous() - - 2009-05-12 Simon Goldschmidt - * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options - to the IP header (used by igmp_ip_output_if) - - 2009-05-06 Simon Goldschmidt - * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if - defined) for SWAP_BYTES_IN_WORD to speed up checksumming. - - 2009-05-05 Simon Goldschmidt - * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() - to crash - - 2009-05-04 Simon Goldschmidt - * init.c: snmp was not initialized in lwip_init() - - 2009-05-04 Frédéric Bernon - * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. - - 2009-05-03 Simon Goldschmidt - * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full - (and unsent->next == NULL) - - 2009-05-02 Simon Goldschmidt - * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after - 1.3.0 in CVS only) - fixes compilation of ppp_oe.c - - 2009-05-02 Simon Goldschmidt - * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields - - 2009-05-01 Simon Goldschmidt - * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets - - 2009-05-01 Simon Goldschmidt - * ppp.c: bug #24228: Memory corruption with PPP and DHCP - - 2009-04-29 Frédéric Bernon - * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the - SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception - of broadcast packets even when this option wasn't set. Port maintainers - which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. - If you want this option also filter broadcast on recv operations, you also - have to set IP_SOF_BROADCAST_RECV=1 in opt.h. - - 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen - * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and - DHCP/AUTOIP cooperation - - 2009-04-25 Simon Goldschmidt, Oleg Tyshev - * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd - Fixed by sorting the unsent and unacked queues (segments are inserted at the - right place in tcp_output and tcp_rexmit). - - 2009-04-25 Simon Goldschmidt - * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation - when debugging": memp_sizes contained the wrong sizes (including sanity - regions); memp pools for MEM_USE_POOLS were too small - - 2009-04-24 Simon Goldschmidt, Frédéric Bernon - * inet.c: patch #6765: Fix a small problem with the last changes (incorrect - behavior, with with ip address string not ended by a '\0', a space or a - end of line) - - 2009-04-19 Simon Goldschmidt - * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, - pcb->err is called, not pcb->connected (with an error code). - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with - no-copy-tcpwrite": deallocate option data, only concat segments with same flags - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated - in the header pbuf, not the data pbuf) - - 2009-04-18 Simon Goldschmidt - * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() - - 2009-04-15 Simon Goldschmidt - * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp - - 2009-04-15 Simon Goldschmidt - * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in - - 2009-04-15 Simon Goldschmidt - * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function - ip_hinted_output() (for smaller code mainly) - - 2009-04-15 Simon Goldschmidt - * inet.c: patch #6765: Supporting new line characters in inet_aton() - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; - Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu - is big enough in dhcp_start - - 2009-04-15 Simon Goldschmidt - * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak - - 2009-04-15 Simon Goldschmidt - * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY - - 2009-04-15 Simon Goldschmidt - * sockets.c: bug #26121: set_errno can be overridden - - 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) - * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when - LWIP_TCP==0 - - 2009-04-09 Kieran Mansley (patch from Roy Lee ) - * tcp.h: Patch#6802 Add do-while-clauses to those function like - macros in tcp.h - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window - updates are calculated and sent (BUG20515) - - * tcp_in.c: cope with SYN packets received during established states, - and retransmission of initial SYN. - - * tcp_out.c: set push bit correctly when tcp segments are merged - - 2009-03-27 Kieran Mansley - * tcp_out.c set window correctly on probes (correcting change made - yesterday) - - 2009-03-26 Kieran Mansley - * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping - connections where no reset required (bug #25622) - - * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes - (bug #20779) - - 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) - * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be - too small depending on MEM_ALIGNMENT - - 2009-02-16 Simon Goldschmidt - * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; - converted size argument of netconn_write to 'size_t' - - 2009-02-16 Simon Goldschmidt - * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host - by moving accept callback function pointer to TCP_PCB_COMMON - - 2009-02-12 Simon Goldschmidt - * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" - option) - - 2009-02-11 Simon Goldschmidt - * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) - - 2009-02-11 Simon Goldschmidt - * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: - RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) - - 2009-02-10 Simon Goldschmidt - * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: - Accepts_pending is decrease on a corresponding listen pcb when a connection - in state SYN_RCVD is close. - - 2009-01-28 Jonathan Larmour - * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run - out of pool pbufs. - - 2008-12-19 Simon Goldschmidt - * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 - - 2008-12-10 Tamas Somogyi, Frédéric Bernon - * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and - port uses deleted netbuf. - - 2008-10-18 Simon Goldschmidt - * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length - in tcp_parseopt - - 2008-10-15 Simon Goldschmidt - * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers - by packing the struct ip_reass_helper. - - 2008-10-03 David Woodhouse, Jonathan Larmour - * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. - - 2008-10-02 Jonathan Larmour - * dns.c: Hard-code structure sizes, to avoid issues on some compilers where - padding is included. - - 2008-09-30 Jonathan Larmour - * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an - assertion check that addrlen isn't NULL. - - 2008-09-30 Jonathan Larmour - * tcp.c: Fix bug #24227, wrong error message in tcp_bind. - - 2008-08-26 Simon Goldschmidt - * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and - inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h - - 2008-08-14 Simon Goldschmidt - * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when - tcp_close returns != ERR_OK) - - 2008-07-08 Frédéric Bernon - * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters - in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). - - 2008-06-24 Jonathan Larmour - * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused - if tcp_seg_copy fails. - - 2008-06-17 Simon Goldschmidt - * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) - and created defines for swapping bytes and folding u32 to u16. - - 2008-05-30 Kieran Mansley - * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd - rather than rcv_ann_wnd when deciding if packets are in-window. - Contributed by - - 2008-05-30 Kieran Mansley - * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow - passing as function pointers when MEM_LIBC_MALLOC is defined. - - 2008-05-09 Jonathan Larmour - * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to - stop it being treated as a fatal error. - - 2008-04-15 Simon Goldschmidt - * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP - (flag now cleared) - - 2008-03-27 Simon Goldschmidt - * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free - from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 - in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs - or heap memory from interrupt context - - 2008-03-26 Simon Goldschmidt - * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote - host sent a zero mss as TCP option. - - -(STABLE-1.3.0) - - ++ New features: - - 2008-03-10 Jonathan Larmour - * inet_chksum.c: Allow choice of one of the sample algorithms to be - made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. - - 2008-01-22 Frédéric Bernon - * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in - TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. - - 2008-01-14 Frédéric Bernon - * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable - to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the - tcp_recv callback (see rawapi.txt). - - 2008-01-14 Frédéric Bernon, Marc Chaland - * ip.c: Integrate patch #6369" ip_input : checking before realloc". - - 2008-01-12 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::sem per netconn::op_completed like suggested for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-12 Frédéric Bernon - * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, - DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues - sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 - "Add return value to sys_mbox_post". tcpip_callback is always defined as - "blocking" ("block" parameter = 1). - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-05 Frédéric Bernon - * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: - Introduce changes for task #7490 "Add return value to sys_mbox_post" with some - modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which - indicate the number of pointers query by the mailbox. There is three defines - in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the - netconn::acceptmbox. Port maintainers, you can decide to just add this new - parameter in your implementation, but to ignore it to keep the previous behavior. - The new sys_mbox_trypost function return a value to know if the mailbox is - full or if the message is posted. Take a look to sys_arch.txt for more details. - This new function is used in tcpip_input (so, can be called in an interrupt - context since the function is not blocking), and in recv_udp and recv_raw. - - 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, - tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the - "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add - documentation in the rawapi.txt file. - - 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer - - 2007-12-31 Frédéric Bernon, Luca Ceresoli - * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets - in autoip". The change in etharp_raw could be removed, since all calls to - etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be - wrong in the future. - - 2007-12-30 Frédéric Bernon, Tom Evans - * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address - Filtering" reported by Tom Evans. - - 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, - sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API - applications have to call 'tcp_accepted(pcb)' in their accept callback to - keep accepting new connections. - - 2007-12-13 Frédéric Bernon - * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" - by err_t type. Add a new err_t code "ERR_INPROGRESS". - - 2007-12-12 Frédéric Bernon - * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles - are the one which have ram usage. - - 2007-12-05 Frédéric Bernon - * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static - set of variables (=0) or a local one (=1). In this last case, your port should - provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" - which have to do a copy of "h" and return a pointer ont the "per-thread" copy. - - 2007-12-03 Simon Goldschmidt - * ip.c: ip_input: check if a packet is for inp first before checking all other - netifs on netif_list (speeds up packet receiving in most cases) - - 2007-11-30 Simon Goldschmidt - * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access - UDP: move a (connected) pcb selected for input to the front of the list of - pcbs so that it is found faster next time. Same for RAW pcbs that have eaten - a packet. - - 2007-11-28 Simon Goldschmidt - * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS - - 2007-11-25 Simon Goldschmidt - * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy - algorithm. - - 2007-11-24 Simon Goldschmidt - * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c - to the new file netdb.c; included lwip_getaddrinfo. - - 2007-11-21 Simon Goldschmidt - * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss - based on the MTU of the netif used to send. Enabled by default. Disable by - setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. - - 2007-11-19 Frédéric Bernon - * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name - received match the name query), implement DNS_USES_STATIC_BUF (the place where - copy dns payload to parse the response), return an error if there is no place - for a new query, and fix some minor problems. - - 2007-11-16 Simon Goldschmidt - * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c - removed files: core/inet.c, core/inet6.c - Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into - inet and chksum part; changed includes in all lwIP files as appropriate - - 2007-11-16 Simon Goldschmidt - * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential - dns resolver function for netconn api (netconn_gethostbyname) and socket api - (gethostbyname/gethostbyname_r). - - 2007-11-15 Jim Pettinato, Frédéric Bernon - * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name - requests with RAW api interface. Initialization is done in lwip_init() with - build time options. DNS timer is added in tcpip_thread context. DHCP can set - DNS server ip addresses when options are received. You need to set LWIP_DNS=1 - in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get - some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" - list with points to improve. - - 2007-11-06 Simon Goldschmidt - * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly - enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status - for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. - - 2007-11-06 Simon Goldschmidt - * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include - core header files in api.h (ip/tcp/udp/raw.h) to hide the internal - implementation from netconn api applications. - - 2007-11-03 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & - RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled - by default). Netconn API users can use the netconn_recv_bufsize macro to access - it. This is a first release which have to be improve for TCP. Note it used the - netconn::recv_avail which need to be more "thread-safe" (note there is already - the problem for FIONREAD with lwip_ioctl/ioctlsocket). - - 2007-11-01 Frédéric Bernon, Marc Chaland - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: - Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api - layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api - layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. - Note that previous "copy" parameter for "write" APIs is now called "apiflags". - - 2007-10-24 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than - TCP_EVENT_xxx macros to get a code more readable. It could also help to remove - some code (like we have talk in "patch #5919 : Create compile switch to remove - select code"), but it could be done later. - - 2007-10-08 Simon Goldschmidt - * many files: Changed initialization: many init functions are not needed any - more since we now rely on the compiler initializing global and static - variables to zero! - - 2007-10-06 Simon Goldschmidt - * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY - to enqueue the received pbufs so that multiple packets can be reassembled - simultaneously and no static reassembly buffer is needed. - - 2007-10-05 Simon Goldschmidt - * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so - all netifs (or ports) can use it. - - 2007-10-05 Frédéric Bernon - * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the - common function to reduce a little bit the footprint (for all functions using - only the "netif" parameter). - - 2007-10-03 Frédéric Bernon - * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, - netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce - a little bit the footprint (for all functions using only the "netif" parameter). - - 2007-09-15 Frédéric Bernon - * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF - option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for - netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for - IP_MULTICAST_TTL and IP_MULTICAST_IF. - - 2007-09-10 Frédéric Bernon - * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles - even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() - each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can - decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but - call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() - or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. - This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside - snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only - when it's queried (any direct call to "sysuptime" is changed by a call to - snmp_get_sysuptime). - - 2007-09-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, - and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags - if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). - igmp_report_groups() is now called inside netif_set_link_up() (need to have - LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait - the next query message to receive the matching multicast streams). - - 2007-09-08 Frédéric Bernon - * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains - IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). - Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). - Enable to access to these fields with LWIP_TCP=0. - - 2007-09-05 Frédéric Bernon - * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, - ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option - LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). - Be careful, disabling ICMP make your product non-compliant to RFC1122, but - help to reduce footprint, and to reduce "visibility" on the Internet. - - 2007-09-05 Frédéric Bernon, Bill Florac - * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list - for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new - parameters have to be provided: a task name, and a task stack size. For this - one, since it's platform dependant, you could define the best one for you in - your lwipopts.h. For port maintainers, you can just add these new parameters - in your sys_arch.c file, and but it's not mandatory, use them in your OS - specific functions. - - 2007-09-05 Frédéric Bernon - * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings - inside init.c for task #7142 "Sanity check user-configurable values". - - 2007-09-04 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by - memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the - value). It will avoid potential fragmentation problems, use a counter to know - how many times a group is used on an netif, and free it when all applications - leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity - check if LWIP_IGMP!=0). - - 2007-09-03 Frédéric Bernon - * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". - Initialize igmp_mac_filter to NULL in netif_add (this field should be set in - the netif's "init" function). Use the "imr_interface" field (for socket layer) - and/or the "interface" field (for netconn layer), for join/leave operations. - The igmp_join/leavegroup first parameter change from a netif to an ipaddr. - This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). - - 2007-08-30 Frédéric Bernon - * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions - from api/api_lib". Now netbuf API is independant of netconn, and can be used - with other API (application based on raw API, or future "socket2" API). Ports - maintainers just have to add src/api/netbuf.c in their makefile/projects. - - 2007-08-30 Frédéric Bernon, Jonathan Larmour - * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check - user-configurable values". - - 2007-08-29 Frédéric Bernon - * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. - igmp_start is call inside netif_add. Now, igmp initialization is in the same - spirit than the others modules. Modify some IGMP debug traces. - - 2007-08-29 Frédéric Bernon - * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" - Add lwip_init function to regroup all modules initializations, and to provide - a place to add code for task #7142 "Sanity check user-configurable values". - Ports maintainers should remove direct initializations calls from their code, - and add init.c in their makefiles. Note that lwip_init() function is called - inside tcpip_init, but can also be used by raw api users since all calls are - disabled when matching options are disabled. Also note that their is new options - in opt.h, you should configure in your lwipopts.h (they are enabled per default). - - 2007-08-26 Marc Boucher - * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL - since they can under certain circumstances be called with an invalid conn - pointer after the connection has been closed (and conn has been freed). - - 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) - * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". - Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. - - 2007-08-22 Frédéric Bernon - * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK - to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. - - 2007-08-22 Frédéric Bernon - * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & - ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the - name is tcpip_input (we keep the name of 1.2.0 function). - - 2007-08-17 Jared Grubb - * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool - settings into new memp_std.h and optional user file lwippools.h. This adds - more dynamic mempools, and allows the user to create an arbitrary number of - mempools for mem_malloc. - - 2007-08-16 Marc Boucher - * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; - otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely - close the connection. - - 2007-08-16 Marc Boucher - * sockets.c: lwip_accept(): check netconn_peer() error return. - - 2007-08-16 Marc Boucher - * mem.c, mem.h: Added mem_calloc(). - - 2007-08-16 Marc Boucher - * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) - for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG - and starving other message types. - Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API - - 2007-08-16 Marc Boucher - * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf - type and flgs (later renamed to flags). - Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. - Improved lwip_recvfrom(). TCP push now propagated. - - 2007-08-16 Marc Boucher - * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global - provided by etharp. - - 2007-08-16 Marc Boucher - * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, - etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: - Added PPPoE support and various PPP improvements. - - 2007-07-25 Simon Goldschmidt - * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, - making netbuf_copy_partial use this function. - - 2007-07-25 Simon Goldschmidt - * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with - 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and - other stacks. - - 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) - * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add - a link callback in the netif struct, and functions to handle it. Be carefull - for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) - if you want to be sure to be compatible with future changes... - - 2007-06-30 Frédéric Bernon - * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. - - 2007-06-21 Simon Goldschmidt - * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both - LWIP_AUTOIP =0 and =1 to remove redundant code. - - 2007-06-21 Simon Goldschmidt - * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option - MEM_USE_POOLS to use 4 pools with different sized elements instead of a - heap. This both prevents memory fragmentation and gives a higher speed - at the cost of more memory consumption. Turned off by default. - - 2007-06-21 Simon Goldschmidt - * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of - netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into - int to be able to send a bigger buffer than 64K with one time (mainly - used from lwip_send). - - 2007-06-21 Simon Goldschmidt - * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write - into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. - - 2007-06-21 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in - netconn_write from api_lib.c to api_msg.c to also prevent multiple context- - changes on low memory or empty send-buffer. - - 2007-06-18 Simon Goldschmidt - * etharp.c, etharp.h: Changed etharp to use a defined hardware address length - of 6 to avoid loading netif->hwaddr_len every time (since this file is only - used for ethernet and struct eth_addr already had a defined length of 6). - - 2007-06-17 Simon Goldschmidt - * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets - to disable UDP checksum generation on transmit. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid - pointers or parameters, and let the possibility to redefined it in cc.h. Use - this macro to check "conn" parameter in api_msg.c functions. - - 2007-06-11 Simon Goldschmidt - * sockets.c, sockets.h: Added UDP lite support for sockets - - 2007-06-10 Simon Goldschmidt - * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled - by default) to switch off UDP-Lite support if not needed (reduces udp.c code - size) - - 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) - * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: - AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and - LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt - (see TODO mark in the source code). - - 2007-06-09 Simon Goldschmidt - * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for - etharp_output() to match netif->output so etharp_output() can be used - directly as netif->output to save one function call. - - 2007-06-08 Simon Goldschmidt - * netif.h, ethernetif.c, slipif.c, loopif.c: Added define - NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, - added initialization of those to ethernetif, slipif and loopif. - - 2007-05-18 Simon Goldschmidt - * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF - (defaulting to off for now) that can be set to 0 to send fragmented - packets by passing PBUF_REFs down the stack. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP - connections, such present in patch #5959. - - 2007-05-23 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx - code in only one part... - - 2007-05-18 Simon Goldschmidt - * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp - elements to overflow. This is achieved by adding some bytes before and after - each pool element (increasing their size, of course), filling them with a - prominent value and checking them on freeing the element. - Set it to 2 to also check every element in every pool each time memp_malloc() - or memp_free() is called (slower but more helpful). - - 2007-05-10 Simon Goldschmidt - * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for - PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce - code size. - - 2007-05-11 Frédéric Bernon - * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: - Include a function pointer instead of a table index in the message to reduce - footprint. Disable some part of lwip_send and lwip_sendto if some options are - not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). - - 2007-05-10 Simon Goldschmidt - * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus - \ extern "C" {' in all header files. Now you can write your application using - the lwIP stack in C++ and simply #include the core files. Note I have left - out the netif/ppp/*h header files for now, since I don't know which files are - included by applications and which are for internal use only. - - 2007-05-09 Simon Goldschmidt - * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library - memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for - situations where some compilers might inline the copy and save a function - call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). - - 2007-05-08 Simon Goldschmidt - * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) - to be overriden in case the C-library malloc implementation is not protected - against concurrent access. - - 2007-05-04 Simon Goldschmidt (Atte Kojo) - * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending - multiple packets to the same host. - - 2007-05-04 Frédéric Bernon, Jonathan Larmour - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible - to corrupt remote addr/port connection state". Reduce problems "not enought memory" with - netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between - sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. - Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, - these fields are now renamed "addr" & "port". - - 2007-04-11 Jonathan Larmour - * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new - sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return - with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro - by the port in sys_arch.h if desired. - - 2007-04-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API - allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp - clients, using new functions from netifapi.h. Disable as default (no port change to do). - - 2007-04-05 Frédéric Bernon - * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. - - 2007-04-04 Simon Goldschmidt - * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) - use this for and architecture-independent form to tell the compiler you intentionally - are not using this variable. Can be overriden in cc.h. - - 2007-03-28 Frédéric Bernon - * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to - define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded - string, point on one of your's ethernetif field, or alloc a string you will free yourself). - It will be used by DHCP to register a client hostname, but can also be use when you call - snmp_set_sysname. - - 2007-03-28 Frédéric Bernon - * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to - initialize a network interface's flag with. It tell this interface is an ethernet - device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility - Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). - - 2007-03-26 Frédéric Bernon, Jonathan Larmour - * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build - time if you only use PPP or SLIP. The default is enable. Note we don't have to call - etharp_init in your port's initilization sequence if you use tcpip.c, because this call - is done in tcpip_init function. - - 2007-03-22 Frédéric Bernon - * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the - new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in - your lwipopts.h. More, unused counters are not defined in the stats structs, and not - display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined - but never used. Fix msg_in.c with the correct #if test for a stat display. - - 2007-03-21 Kieran Mansley - * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). - Provides callback on netif up/down state change. - - 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, - ip.c, netif.h, tcpip.c, opt.h: - New configuration option LWIP_IGMP to enable IGMP processing. Based on only one - filter per all network interfaces. Declare a new function in netif to enable to - control the MAC filter (to reduce lwIP traffic processing). - - 2007-03-11 Frédéric Bernon - * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can - be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this - unless you know what you're doing (default are RFC1122 compliant). Note - that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. - - 2007-03-08 Frédéric Bernon - * tcp.h: Keepalive values can be configured at compile time, but don't change - this unless you know what you're doing (default are RFC1122 compliant). - - 2007-03-08 Frédéric Bernon - * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: - Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO - on UDP sockets/netconn. - - 2007-03-08 Simon Goldschmidt - * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. - - 2007-03-06 Frédéric Bernon - * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: - Implement SO_RCVTIMEO on UDP sockets/netconn. - - 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) - * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated - on the stack and remove the API msg type from memp - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * sockets.h, sockets.c: Move socket initialization to new - lwip_socket_init() function. - NOTE: this changes the API with ports. Ports will have to be - updated to call lwip_socket_init() now. - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * api_lib.c: Use memcpy in netbuf_copy_partial. - - - ++ Bug fixes: - - 2008-03-17 Frédéric Bernon, Ed Kerekes - * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have - some problems to fill the IP header on some targets, use now the - ip.h macros to do it). - - 2008-03-13 Frédéric Bernon - * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using - (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a - TCP connection caused a crash. Note that using (lwip_)recvfrom - like this is a bit slow and that using (lwip)getpeername is the - good lwip way to do it (so, using recv is faster on tcp sockets). - - 2008-03-12 Frédéric Bernon, Jonathan Larmour - * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's - recv_raw() does not consume data", and the ping sample (with - LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom - returned the IP payload, without the IP header). - - 2008-03-04 Jonathan Larmour - * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors - and/or warnings on some systems where mem_size_t and size_t differ. - * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. - - 2008-03-04 Kieran Mansley (contributions by others) - * Numerous small compiler error/warning fixes from contributions to - mailing list after 1.3.0 release candidate made. - - 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) - * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. - - 2008-01-15 Kieran Mansley - * tcp_out.c: BUG20511. Modify persist timer to start when we are - prevented from sending by a small send window, not just a zero - send window. - - 2008-01-09 Jonathan Larmour - * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid - conflict with Linux system headers. - - 2008-01-06 Jonathan Larmour - * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP - address entirely on receiving a DHCPNAK, and restarting discovery. - - 2007-12-21 Simon Goldschmidt - * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail - is not protected" by using new macros for interlocked access to modify/test - netconn->recv_avail. - - 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) - * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) - - 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling - of silly window avoidance and prevent lwIP from shrinking the window) - - 2007-12-04 Simon Goldschmidt - * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last - data packet was lost): add assert that all segment lists are empty in - tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED - state from LAST_ACK in tcp_process - - 2007-12-02 Simon Goldschmidt - * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET - If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now - has to be set to 0 in lwipopts.h - - 2007-12-02 Simon Goldschmidt - * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always - allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen - netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. - This is a fix for thread-safety and allocates all items needed for a netconn - when the netconn is created. - - 2007-11-30 Simon Goldschmidt - * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple - netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed - to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same - port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) - - 2007-11-27 Simon Goldschmidt - * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by - letting ip_route only use netifs that are up. - - 2007-11-27 Simon Goldschmidt - * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF - and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and - sockets block most operations once they have seen a fatal error. - - 2007-11-27 Simon Goldschmidt - * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the - netif to send as an argument (to be able to send on netifs that are down). - - 2007-11-26 Simon Goldschmidt - * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs - arrive out-of-order - - 2007-11-21 Simon Goldschmidt - * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early - Fixed the nagle algorithm; nagle now also works for all raw API applications - and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' - - 2007-11-12 Frédéric Bernon - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most - of the netconn_peer and netconn_addr processing is done inside tcpip_thread - context in do_getaddr. - - 2007-11-10 Simon Goldschmidt - * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can - happen any time). Now the packet simply isn't enqueued when out of memory. - - 2007-11-01 Simon Goldschmidt - * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or - TCP_MSS if that is smaller) as long as no MSS option is received from the - remote host. - - 2007-11-01 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) - is now based on TCP_MSS instead of pcb->mss (on passive open now effectively - sending our configured TCP_MSS instead of the one received). - - 2007-11-01 Simon Goldschmidt - * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was - calculated based on the configured TCP_MSS, not on the MSS option received - with SYN+ACK. - - 2007-10-09 Simon Goldschmidt - * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too - short and also was generated wrong if checksum coverage != tot_len; - receive: checksum was calculated wrong if checksum coverage != tot_len - - 2007-10-08 Simon Goldschmidt - * mem.c: lfree was not updated in mem_realloc! - - 2007-10-07 Frédéric Bernon - * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential - crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: - this change cause an API breakage for netconn_addr, since a parameter - type change. Any compiler should cause an error without any changes in - yours netconn_peer calls (so, it can't be a "silent change"). It also - reduce a little bit the footprint for socket layer (lwip_getpeername & - lwip_getsockname use now a common lwip_getaddrname function since - netconn_peer & netconn_addr have the same parameters). - - 2007-09-20 Simon Goldschmidt - * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) - by checking tcp_tw_pcbs also - - 2007-09-19 Simon Goldschmidt - * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) - - 2007-09-15 Mike Kleshov - * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) - - 2007-09-06 Frédéric Bernon - * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove - it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which - already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" - if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. - - 2007-08-30 Frédéric Bernon - * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, - and fix some coding style. - - 2007-08-28 Frédéric Bernon - * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any - kind of packets. These packets are considered like Ethernet packets (payload - pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets - are considered like IP packets (payload pointing to iphdr). - - 2007-08-27 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error - problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state - and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). - - 2007-08-24 Kieran Mansley - * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy - compiler (Paradigm C++) - - 2007-08-09 Frédéric Bernon, Bill Florac - * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. - Introduce IGMP_STATS to centralize statistics management. - - 2007-08-09 Frédéric Bernon, Bill Florac - * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast - packet on a udp pcb binded on an netif's IP address, and not on "any". - - 2007-08-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. - This is mainly on using lookup/lookfor, and some coding styles... - - 2007-07-26 Frédéric Bernon (and "thedoctor") - * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. - - 2007-07-25 Simon Goldschmidt - * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if - tcp_output fails in tcp_close, the code in do_close_internal gets simpler - (tcp_output is called again later from tcp timers). - - 2007-07-25 Simon Goldschmidt - * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old - copy_from_pbuf, which illegally modified the given pbuf. - - 2007-07-25 Simon Goldschmidt - * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: - changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). - - 2007-07-24 Simon Goldschmidt - * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the - correct state (must be CLOSED). - - 2007-07-13 Thomas Taranowski (commited by Jared Grubb) - * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed - allocation. It now returns NULL. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in - all error cases. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, - because current code doesn't follow rawapi.txt documentation. - - 2007-07-13 Kieran Mansley - * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in - out of sequence processing of received packets - - 2007-07-03 Simon Goldschmidt - * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an - assumption is made that this pbuf is in one piece (i.e. not chained). These - assumptions clash with the possibility of converting to fully pool-based - pbuf implementations, where PBUF_RAM pbufs might be chained. - - 2007-07-03 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems - when closing tcp netconns: removed conn->sem, less context switches when - closing, both netconn_close and netconn_delete should safely close tcp - connections. - - 2007-07-02 Simon Goldschmidt - * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, - tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) - to cache ARP table indices with each pcb instead of single-entry cache for - the complete stack. - - 2007-07-02 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent - warnings when assigning to smaller types. - - 2007-06-28 Simon Goldschmidt - * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. - - 2007-06-28 Simon Goldschmidt - * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if - a segment contained chained pbufs) - - 2007-06-28 Frédéric Bernon - * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute - a "pseudo-random" value based on netif's MAC and some autoip fields. It's always - possible to define this macro in your own lwipopts.h to always use C library's - rand(). Note that autoip_create_rand_addr doesn't use this macro. - - 2007-06-28 Frédéric Bernon - * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option - LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications - in api_lib/api_msg (use pointers and not type with table, etc...) - - 2007-06-26 Simon Goldschmidt - * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload - for udp packets with no matching pcb. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match - could get udp input packets if the remote side matched. - - 2007-06-13 Simon Goldschmidt - * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get - changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. - - 2007-06-13 Simon Goldschmidt - * api_msg.c: pcb_new sets conn->err if protocol is not implemented - -> netconn_new_..() does not allocate a new connection for unsupported - protocols. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * api_lib.c: change return expression in netconn_addr and netconn_peer, because - conn->err was reset to ERR_OK without any reasons (and error was lost)... - - 2007-06-13 Frédéric Bernon, Matthias Weisser - * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename - MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid - some macro names collision with some OS macros. - - 2007-06-11 Simon Goldschmidt - * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, - create checksum over the complete packet. On RX, if it's < 8 (and not 0), - discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both - UDP & UDP Lite. - - 2007-06-11 Srinivas Gollakota & Oleg Tyshev - * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" - where TCP flags wasn't initialized in tcp_keepalive. - - 2007-06-03 Simon Goldschmidt - * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function - registered, p->payload was modified without modifying p->len if sending - icmp_dest_unreach() (had no negative effect but was definitively wrong). - - 2007-06-03 Simon Goldschmidt - * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp - re-used the input pbuf even if that didn't have enough space to include the - link headers. Now the space is tested and a new pbuf is allocated for the - echo response packet if the echo request pbuf isn't big enough. - - 2007-06-01 Simon Goldschmidt - * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. - - 2007-05-23 Frédéric Bernon - * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only - allocated by do_listen if success) and netconn_accept errors handling. In - most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" - by ASSERT, except for netconn_delete. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return - an error code if it's impossible to fetch a pbuf on a TCP connection (and not - directly close the recvmbox). - - 2007-05-22 Simon Goldschmidt - * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of - bound but unconnected (and non-listening) tcp_pcbs. - - 2007-05-22 Frédéric Bernon - * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only - used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of - sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features - like "sys_timeout" in their application threads. - - 2007-05-22 Frédéric Bernon - * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see - which parameters are used by which do_xxx function, and to avoid "misusing" - parameters (patch #5938). - - 2007-05-22 Simon Goldschmidt - * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: - changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto - is only 8 bits wide. This affects the api, as there, the protocol was - u16_t, too. - - 2007-05-18 Simon Goldschmidt - * memp.c: addition to patch #5913: smaller pointer was returned but - memp_memory was the same size -> did not save memory. - - 2007-05-16 Simon Goldschmidt - * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns - != ERR_OK. - - 2007-05-16 Simon Goldschmidt - * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same - as the one of the netif used for sending to prevent sending from old - addresses after a netif address gets changed (partly fixes bug #3168). - - 2007-05-16 Frédéric Bernon - * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work - with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in - tcpip_init) because we have to be sure that network interfaces are already - added (mac filter is updated only in igmp_init for the moment). - - 2007-05-16 Simon Goldschmidt - * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls - into sys_arch_sem_wait calls to prevent timers from running while waiting - for the heap. This fixes bug #19167. - - 2007-05-13 Simon Goldschmidt - * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines - for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from - tcp.h to sockets.h. - - 2007-05-07 Simon Goldschmidt - * mem.c: Another attempt to fix bug #17922. - - 2007-05-04 Simon Goldschmidt - * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() - implementation so that it can be reused (don't allocate the target - pbuf inside pbuf_copy()). - - 2007-05-04 Simon Goldschmidt - * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem - to save a little RAM (next pointer of memp is not used while not in pool). - - 2007-05-03 "maq" - * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. - (patch #3574). - - 2007-04-23 Simon Goldschmidt - * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results - in NULL reference for incoming TCP packets". Loopif has to be configured - (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() - (multithreading environments, e.g. netif->input() = tcpip_input()) or - putting packets on a list that is fed to the stack by calling loopif_poll() - (single-thread / NO_SYS / polling environment where e.g. - netif->input() = ip_input). - - 2007-04-17 Jonathan Larmour - * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold - the difference between two u16_t's. - * sockets.h: FD_SETSIZE needs to match number of sockets, which is - MEMP_NUM_NETCONN in sockets.c right now. - - 2007-04-12 Jonathan Larmour - * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). - - 2007-04-12 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission - timer is reset to fix bug#19434, with help from Oleg Tyshev. - - 2007-04-11 Simon Goldschmidt - * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than - previously thought need to be copied (everything but PBUF_ROM!). Cleaned up - pbuf.c: removed functions no needed any more (by etharp). - - 2007-04-11 Kieran Mansley - * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix - "Constant is long" warnings with 16bit compilers. Contributed by - avatar@mmlab.cse.yzu.edu.tw - - 2007-04-05 Frédéric Bernon, Jonathan Larmour - * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on - the mailbox is active". Now, the post is only done during a connect, and do_send, - do_write and do_join_leave_group don't do anything if a previous error was signaled. - - 2007-04-03 Frédéric Bernon - * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output - packets. See patch #5834. - - 2007-03-30 Frédéric Bernon - * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add - missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. - - 2007-03-30 Frédéric Bernon - * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with - others environment defines (these were too "generic"). - - 2007-03-28 Frédéric Bernon - * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call - result and can cause a crash. lwip_send now check netbuf_ref result. - - 2007-03-28 Simon Goldschmidt - * sockets.c Remove "#include " from sockets.c to avoid multiple - definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is - defined. This is the way it should have been already (looking at - doc/sys_arch.txt) - - 2007-03-28 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + - IP and TCP headers *and* physical link headers - - 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) - * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause - to send some garbage. It is not a definitive solution, but the patch does solve - the problem for most cases. - - 2007-03-22 Frédéric Bernon - * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). - - 2007-03-22 Frédéric Bernon - * api_lib.c: somes resources couldn't be freed if there was errors during - netconn_new_with_proto_and_callback. - - 2007-03-22 Frédéric Bernon - * ethernetif.c: update netif->input calls to check return value. In older ports, - it's a good idea to upgrade them, even if before, there could be another problem - (access to an uninitialized mailbox). - - 2007-03-21 Simon Goldschmidt - * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed - by casting to unsigned). - - 2007-03-21 Frédéric Bernon - * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from - api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a - dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. - Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a - faster and more reliable communication between api_lib and tcpip. - - 2007-03-21 Frédéric Bernon - * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. - - 2007-03-21 Frédéric Bernon - * api_msg.c, igmp.c, igmp.h: Fix C++ style comments - - 2007-03-21 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + - IP and TCP headers - - 2007-03-21 Kieran Mansley - * Fix all uses of pbuf_header to check the return value. In some - cases just assert if it fails as I'm not sure how to fix them, but - this is no worse than before when they would carry on regardless - of the failure. - - 2007-03-21 Kieran Mansley - * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and - comment out missing header include in icmp.c - - 2007-03-20 Frédéric Bernon - * memp.h, stats.c: Fix stats_display function where memp_names table wasn't - synchronized with memp.h. - - 2007-03-20 Frédéric Bernon - * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, - tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with - network interfaces. Also fix a compiler warning. - - 2007-03-20 Kieran Mansley - * udp.c: Only try and use pbuf_header() to make space for headers if - not a ROM or REF pbuf. - - 2007-03-19 Frédéric Bernon - * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() - and api_msg_post(). - - 2007-03-19 Frédéric Bernon - * Remove unimplemented "memp_realloc" function from memp.h. - - 2007-03-11 Simon Goldschmidt - * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused - memory corruption. - - 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) - * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 - (missing `const' qualifier in socket functions), to get more compatible to - standard POSIX sockets. - - 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) - * sockets.c: Add asserts inside bind, connect and sendto to check input - parameters. Remove excessive set_errno() calls after get_socket(), because - errno is set inside of get_socket(). Move last sock_set_errno() inside - lwip_close. - - 2007-03-09 Simon Goldschmidt - * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory - was allocated too small. - - 2007-03-06 Simon Goldschmidt - * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect - the stack from concurrent access. - - 2007-03-06 Frédéric Bernon, Dmitry Potapov - * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy - call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). - - 2007-03-06 Simon Goldschmidt - * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files - if IP_FRAG == 0 and IP_REASSEMBLY == 0 - - 2007-03-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration - option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. - Allow to do ARP processing for incoming packets inside tcpip_thread - (protecting ARP layer against concurrent access). You can also disable - old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. - Older ports have to use tcpip_ethinput. - - 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) - * err.h, err.c: fixed compiler warning "initialization dircards qualifiers - from pointer target type" - - 2007-03-05 Frédéric Bernon - * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, - ETHARP_TRUST_IP_MAC, review SO_REUSE) - - 2007-03-04 Frédéric Bernon - * api_msg.c: Remove some compiler warnings : parameter "pcb" was never - referenced. - - 2007-03-04 Frédéric Bernon - * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from - Dmitry Potapov). - The api_msg struct stay on the stack (not moved to netconn struct). - - 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) - * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if - SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) - Also fixed cast warning in pbuf_alloc() - - 2007-03-04 Simon Goldschmidt - * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt - existing pbuf chain when enqueuing multiple pbufs to a pending ARP request - - 2007-03-03 Frédéric Bernon - * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" - It is static, and never used in udp.c except udp_init(). - - 2007-03-02 Simon Goldschmidt - * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from - tcpip_thread() to tcpip_init(). This way, raw API connections can be - initialized before tcpip_thread is running (e.g. before OS is started) - - 2007-03-02 Frédéric Bernon - * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call - interval. - - 2007-02-28 Kieran Mansley - * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved - outside the region of the pbuf by pbuf_header() - - 2007-02-28 Kieran Mansley - * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero - when supplied timeout is also non-zero - -(STABLE-1.2.0) - - 2006-12-05 Leon Woestenberg - * CHANGELOG: Mention STABLE-1.2.0 release. - - ++ New features: - - 2006-12-01 Christiaan Simons - * mem.h, opt.h: Added MEM_LIBC_MALLOC option. - Note this is a workaround. Currently I have no other options left. - - 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) - * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define - to include/lwip/opt.h. - * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. - Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. - * opt.h: Add above new options. - - 2006-08-18 Christiaan Simons - * tcp_{in,out}.c: added SNMP counters. - * ipv4/ip.c: added SNMP counters. - * ipv4/ip_frag.c: added SNMP counters. - - 2006-08-08 Christiaan Simons - * etharp.{c,h}: added etharp_find_addr() to read - (stable) ethernet/IP address pair from ARP table - - 2006-07-14 Christiaan Simons - * mib_structs.c: added - * include/lwip/snmp_structs.h: added - * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct - - 2006-07-06 Christiaan Simons - * snmp/asn1_{enc,dec}.c added - * snmp/mib2.c added - * snmp/msg_{in,out}.c added - * include/lwip/snmp_asn1.h added - * include/lwip/snmp_msg.h added - * doc/snmp_agent.txt added - - 2006-03-29 Christiaan Simons - * inet.c, inet.h: Added platform byteswap support. - Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and - optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. - - ++ Bug fixes: - - 2006-11-30 Christiaan Simons - * dhcp.c: Fixed false triggers of request_timeout. - - 2006-11-28 Christiaan Simons - * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. - - 2006-10-11 Christiaan Simons - * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: - Partially accepted patch #5449 for ANSI C compatibility / build fixes. - * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol - identifier from 170 to 136 (bug #17574). - - 2006-10-10 Christiaan Simons - * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. - - 2006-08-17 Christiaan Simons - * udp.c: Fixed bug #17200, added check for broadcast - destinations for PCBs bound to a unicast address. - - 2006-08-07 Christiaan Simons - * api_msg.c: Flushing TCP output in do_close() (bug #15926). - - 2006-06-27 Christiaan Simons - * api_msg.c: Applied patch for cold case (bug #11135). - In accept_function() ensure newconn->callback is always initialized. - - 2006-06-15 Christiaan Simons - * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), - facilitate printing of mem_size_t and u16_t statistics. - - 2006-06-14 Christiaan Simons - * api_msg.c: Applied patch #5146 to handle allocation failures - in accept() by Kevin Lawson. - - 2006-05-26 Christiaan Simons - * api_lib.c: Removed conn->sem creation and destruction - from netconn_write() and added sys_sem_new to netconn_new_*. - -(STABLE-1_1_1) - - 2006-03-03 Christiaan Simons - * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap - access and added pbuf_alloc() return value checks. - - 2006-01-01 Leon Woestenberg - * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is - now handled by the checksum routine properly. - - 2006-02-27 Leon Woestenberg - * pbuf.c: Fix alignment; pbuf_init() would not work unless - pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) - - 2005-12-20 Leon Woestenberg - * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch - submitted by Mitrani Hiroshi. - - 2005-12-15 Christiaan Simons - * inet.c: Disabled the added summing routine to preserve code space. - - 2005-12-14 Leon Woestenberg - * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. - Added Curt McDowell's optimized checksumming routine for future - inclusion. Need to create test case for unaliged, aligned, odd, - even length combination of cases on various endianess machines. - - 2005-12-09 Christiaan Simons - * inet.c: Rewrote standard checksum routine in proper portable C. - - 2005-11-25 Christiaan Simons - * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. - * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, - u32_t, s32_t typedefs. This solves most debug word-length assumes. - - 2005-07-17 Leon Woestenberg - * inet.c: Fixed unaligned 16-bit access in the standard checksum - routine by Peter Jolasson. - * slipif.c: Fixed implementation assumption of single-pbuf datagrams. - - 2005-02-04 Leon Woestenberg - * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. - * tcp_{out|in}.c: Applied patch fixing unaligned access. - - 2005-01-04 Leon Woestenberg - * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. - - 2005-01-03 Leon Woestenberg - * udp.c: UDP pcb->recv() was called even when it was NULL. - -(STABLE-1_1_0) - - 2004-12-28 Leon Woestenberg - * etharp.*: Disabled multiple packets on the ARP queue. - This clashes with TCP queueing. - - 2004-11-28 Leon Woestenberg - * etharp.*: Fixed race condition from ARP request to ARP timeout. - Halved the ARP period, doubled the period counts. - ETHARP_MAX_PENDING now should be at least 2. This prevents - the counter from reaching 0 right away (which would allow - too little time for ARP responses to be received). - - 2004-11-25 Leon Woestenberg - * dhcp.c: Decline messages were not multicast but unicast. - * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. - Do not try hard to insert arbitrary packet's source address, - etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. - etharp_query() now always DOES call ETHARP_TRY_HARD so that users - querying an address will see it appear in the cache (DHCP could - suffer from this when a server invalidly gave an in-use address.) - * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are - comparing network addresses (identifiers), not the network masks - themselves. - * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given - IP address actually belongs to the network of the given interface. - - 2004-11-24 Kieran Mansley - * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. - -(STABLE-1_1_0-RC1) - - 2004-10-16 Kieran Mansley - * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, - even if one is already pending, if the rcv_wnd is above a threshold - (currently TCP_WND/2). This avoids waiting for a timer to expire to send a - delayed ACK in order to open the window if the stack is only receiving data. - - 2004-09-12 Kieran Mansley - * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. - - 2004-08-20 Tony Mountifield - * etharp.c: Make sure the first pbuf queued on an ARP entry - is properly ref counted. - - 2004-07-27 Tony Mountifield - * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler - warnings about comparison. - * pbuf.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. Closed an unclosed comment. - * tcp.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. - * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). - * inet.c: Added a couple of casts to quiet the compiler. - No need to test isascii(c) before isdigit(c) or isxdigit(c). - - 2004-07-22 Tony Mountifield - * inet.c: Made data types consistent in inet_ntoa(). - Added casts for return values of checksum routines, to pacify compiler. - * ip_frag.c, tcp_out.c, sockets.c, pbuf.c - Small corrections to some debugging statements, to pacify compiler. - - 2004-07-21 Tony Mountifield - * etharp.c: Removed spurious semicolon and added missing end-of-comment. - * ethernetif.c Updated low_level_output() to match prototype for - netif->linkoutput and changed low_level_input() similarly for consistency. - * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype - of raw_recv() in raw.h and so avoid compiler error. - * sockets.c: Added trivial (int) cast to keep compiler happier. - * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. - -(STABLE-1_0_0) - - ++ Changes: - - 2004-07-05 Leon Woestenberg - * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure - your cc.h file defines this either 1 or 0. If non-defined, - defaults to 1. - * .c: Added and includes where used. - * etharp.c: Made some array indices unsigned. - - 2004-06-27 Leon Woestenberg - * netif.*: Added netif_set_up()/down(). - * dhcp.c: Changes to restart program flow. - - 2004-05-07 Leon Woestenberg - * etharp.c: In find_entry(), instead of a list traversal per candidate, do a - single-pass lookup for different candidates. Should exploit locality. - - 2004-04-29 Leon Woestenberg - * tcp*.c: Cleaned up source comment documentation for Doxygen processing. - * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. - * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by - the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. - - ++ Bug fixes: - - 2004-04-27 Leon Woestenberg - * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution - suggested by Timmy Brolin. Fix for 32-bit processors that cannot access - non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix - is to prefix the 14-bit Ethernet headers with two padding bytes. - - 2004-04-23 Leon Woestenberg - * ip_addr.c: Fix in the ip_addr_isbroadcast() check. - * etharp.c: Fixed the case where the packet that initiates the ARP request - is not queued, and gets lost. Fixed the case where the packets destination - address is already known; we now always queue the packet and perform an ARP - request. - -(STABLE-0_7_0) - - ++ Bug fixes: - - * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. - * Fixed TCP bug in dequeueing of FIN from out of order segment queue. - * Fixed two possible NULL references in rare cases. - -(STABLE-0_6_6) - - ++ Bug fixes: - - * Fixed DHCP which did not include the IP address in DECLINE messages. - - ++ Changes: - - * etharp.c has been hauled over a bit. - -(STABLE-0_6_5) - - ++ Bug fixes: - - * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. - * Packets sent from ARP queue had invalid source hardware address. - - ++ Changes: - - * Pass-by ARP requests do now update the cache. - - ++ New features: - - * No longer dependent on ctype.h. - * New socket options. - * Raw IP pcb support. - -(STABLE-0_6_4) - - ++ Bug fixes: - - * Some debug formatters and casts fixed. - * Numereous fixes in PPP. - - ++ Changes: - - * DEBUGF now is LWIP_DEBUGF - * pbuf_dechain() has been re-enabled. - * Mentioned the changed use of CVS branches in README. - -(STABLE-0_6_3) - - ++ Bug fixes: - - * Fixed pool pbuf memory leak in pbuf_alloc(). - Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. - Reported by Savin Zlobec. - - * PBUF_POOL chains had their tot_len field not set for non-first - pbufs. Fixed in pbuf_alloc(). - - ++ New features: - - * Added PPP stack contributed by Marc Boucher - - ++ Changes: - - * Now drops short packets for ICMP/UDP/TCP protocols. More robust. - - * ARP queueuing now queues the latest packet instead of the first. - This is the RFC recommended behaviour, but can be overridden in - lwipopts.h. - -(0.6.2) - - ++ Bugfixes: - - * TCP has been fixed to deal with the new use of the pbuf->ref - counter. - - * DHCP dhcp_inform() crash bug fixed. - - ++ Changes: - - * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed - pbuf_refresh(). This has sped up pbuf pool operations considerably. - Implemented by David Haas. - -(0.6.1) - - ++ New features: - - * The packet buffer implementation has been enhanced to support - zero-copy and copy-on-demand for packet buffers which have their - payloads in application-managed memory. - Implemented by David Haas. - - Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy - if an outgoing packet can be directly sent on the link, or perform - a copy-on-demand when necessary. - - The application can safely assume the packet is sent, and the RAM - is available to the application directly after calling udp_send() - or similar function. - - ++ Bugfixes: - - * ARP_QUEUEING should now correctly work for all cases, including - PBUF_REF. - Implemented by Leon Woestenberg. - - ++ Changes: - - * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer - to a '0.0.0.0' IP address. - - * The packet buffer implementation is changed. The pbuf->ref counter - meaning has changed, and several pbuf functions have been - adapted accordingly. - - * netif drivers have to be changed to set the hardware address length field - that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). - See the contrib/ports/c16x cs8900 driver as a driver example. - - * netif's have a dhcp field that must be initialized to NULL by the driver. - See the contrib/ports/c16x cs8900 driver as a driver example. - -(0.5.x) This file has been unmaintained up to 0.6.1. All changes are - logged in CVS but have not been explained here. - -(0.5.3) Changes since version 0.5.2 - - ++ Bugfixes: - - * memp_malloc(MEMP_API_MSG) could fail with multiple application - threads because it wasn't protected by semaphores. - - ++ Other changes: - - * struct ip_addr now packed. - - * The name of the time variable in arp.c has been changed to ctime - to avoid conflicts with the time() function. - -(0.5.2) Changes since version 0.5.1 - - ++ New features: - - * A new TCP function, tcp_tmr(), now handles both TCP timers. - - ++ Bugfixes: - - * A bug in tcp_parseopt() could cause the stack to hang because of a - malformed TCP option. - - * The address of new connections in the accept() function in the BSD - socket library was not handled correctly. - - * pbuf_dechain() did not update the ->tot_len field of the tail. - - * Aborted TCP connections were not handled correctly in all - situations. - - ++ Other changes: - - * All protocol header structs are now packed. - - * The ->len field in the tcp_seg structure now counts the actual - amount of data, and does not add one for SYN and FIN segments. - -(0.5.1) Changes since version 0.5.0 - - ++ New features: - - * Possible to run as a user process under Linux. - - * Preliminary support for cross platform packed structs. - - * ARP timer now implemented. - - ++ Bugfixes: - - * TCP output queue length was badly initialized when opening - connections. - - * TCP delayed ACKs were not sent correctly. - - * Explicit initialization of BSS segment variables. - - * read() in BSD socket library could drop data. - - * Problems with memory alignment. - - * Situations when all TCP buffers were used could lead to - starvation. - - * TCP MSS option wasn't parsed correctly. - - * Problems with UDP checksum calculation. - - * IP multicast address tests had endianess problems. - - * ARP requests had wrong destination hardware address. - - ++ Other changes: - - * struct eth_addr changed from u16_t[3] array to u8_t[6]. - - * A ->linkoutput() member was added to struct netif. - - * TCP and UDP ->dest_* struct members where changed to ->remote_*. - - * ntoh* macros are now null definitions for big endian CPUs. - -(0.5.0) Changes since version 0.4.2 - - ++ New features: - - * Redesigned operating system emulation layer to make porting easier. - - * Better control over TCP output buffers. - - * Documenation added. - - ++ Bugfixes: - - * Locking issues in buffer management. - - * Bugfixes in the sequential API. - - * IP forwarding could cause memory leakage. This has been fixed. - - ++ Other changes: - - * Directory structure somewhat changed; the core/ tree has been - collapsed. - -(0.4.2) Changes since version 0.4.1 - - ++ New features: - - * Experimental ARP implementation added. - - * Skeleton Ethernet driver added. - - * Experimental BSD socket API library added. - - ++ Bugfixes: - - * In very intense situations, memory leakage could occur. This has - been fixed. - - ++ Other changes: - - * Variables named "data" and "code" have been renamed in order to - avoid name conflicts in certain compilers. - - * Variable++ have in appliciable cases been translated to ++variable - since some compilers generate better code in the latter case. - -(0.4.1) Changes since version 0.4 - - ++ New features: - - * TCP: Connection attempts time out earlier than data - transmissions. Nagle algorithm implemented. Push flag set on the - last segment in a burst. - - * UDP: experimental support for UDP-Lite extensions. - - ++ Bugfixes: - - * TCP: out of order segments were in some cases handled incorrectly, - and this has now been fixed. Delayed acknowledgements was broken - in 0.4, has now been fixed. Binding to an address that is in use - now results in an error. Reset connections sometimes hung an - application; this has been fixed. - - * Checksum calculation sometimes failed for chained pbufs with odd - lengths. This has been fixed. - - * API: a lot of bug fixes in the API. The UDP API has been improved - and tested. Error reporting and handling has been - improved. Logical flaws and race conditions for incoming TCP - connections has been found and removed. - - * Memory manager: alignment issues. Reallocating memory sometimes - failed, this has been fixed. - - * Generic library: bcopy was flawed and has been fixed. - - ++ Other changes: - - * API: all datatypes has been changed from generic ones such as - ints, to specified ones such as u16_t. Functions that return - errors now have the correct type (err_t). - - * General: A lot of code cleaned up and debugging code removed. Many - portability issues have been fixed. - - * The license was changed; the advertising clause was removed. - - * C64 port added. - - * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri - Kosunen, Mikael Caleres, and Frits Wilmink for reporting and - fixing bugs! - -(0.4) Changes since version 0.3.1 - - * Memory management has been radically changed; instead of - allocating memory from a shared heap, memory for objects that are - rapidly allocated and deallocated is now kept in pools. Allocation - and deallocation from those memory pools is very fast. The shared - heap is still present but is used less frequently. - - * The memory, memory pool, and packet buffer subsystems now support - 4-, 2-, or 1-byte alignment. - - * "Out of memory" situations are handled in a more robust way. - - * Stack usage has been reduced. - - * Easier configuration of lwIP parameters such as memory usage, - TTLs, statistics gathering, etc. All configuration parameters are - now kept in a single header file "lwipopts.h". - - * The directory structure has been changed slightly so that all - architecture specific files are kept under the src/arch - hierarchy. - - * Error propagation has been improved, both in the protocol modules - and in the API. - - * The code for the RTXC architecture has been implemented, tested - and put to use. - - * Bugs have been found and corrected in the TCP, UDP, IP, API, and - the Internet checksum modules. - - * Bugs related to porting between a 32-bit and a 16-bit architecture - have been found and corrected. - - * The license has been changed slightly to conform more with the - original BSD license, including the advertisement clause. - -(0.3.1) Changes since version 0.3 - - * Fix of a fatal bug in the buffer management. Pbufs with allocated - RAM never returned the RAM when the pbuf was deallocated. - - * TCP congestion control, window updates and retransmissions did not - work correctly. This has now been fixed. - - * Bugfixes in the API. - -(0.3) Changes since version 0.2 - - * New and improved directory structure. All include files are now - kept in a dedicated include/ directory. - - * The API now has proper error handling. A new function, - netconn_err(), now returns an error code for the connection in - case of errors. - - * Improvements in the memory management subsystem. The system now - keeps a pointer to the lowest free memory block. A new function, - mem_malloc2() tries to allocate memory once, and if it fails tries - to free some memory and retry the allocation. - - * Much testing has been done with limited memory - configurations. lwIP now does a better job when overloaded. - - * Some bugfixes and improvements to the buffer (pbuf) subsystem. - - * Many bugfixes in the TCP code: - - - Fixed a bug in tcp_close(). - - - The TCP receive window was incorrectly closed when out of - sequence segments was received. This has been fixed. - - - Connections are now timed-out of the FIN-WAIT-2 state. - - - The initial congestion window could in some cases be too - large. This has been fixed. - - - The retransmission queue could in some cases be screwed up. This - has been fixed. - - - TCP RST flag now handled correctly. - - - Out of sequence data was in some cases never delivered to the - application. This has been fixed. - - - Retransmitted segments now contain the correct acknowledgment - number and advertised window. - - - TCP retransmission timeout backoffs are not correctly computed - (ala BSD). After a number of retransmissions, TCP now gives up - the connection. - - * TCP connections now are kept on three lists, one for active - connections, one for listening connections, and one for - connections that are in TIME-WAIT. This greatly speeds up the fast - timeout processing for sending delayed ACKs. - - * TCP now provides proper feedback to the application when a - connection has been successfully set up. - - * More comments have been added to the code. The code has also been - somewhat cleaned up. - -(0.2) Initial public release. diff --git a/components/lwip/lwip/COPYING b/components/lwip/lwip/COPYING deleted file mode 100644 index e23898b5e..000000000 --- a/components/lwip/lwip/COPYING +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - - diff --git a/components/lwip/lwip/FILES b/components/lwip/lwip/FILES deleted file mode 100644 index e6e09989d..000000000 --- a/components/lwip/lwip/FILES +++ /dev/null @@ -1,5 +0,0 @@ -src/ - The source code for the lwIP TCP/IP stack. -doc/ - The documentation for lwIP. -test/ - Some code to test whether the sources do what they should. - -See also the FILES file in each subdirectory. diff --git a/components/lwip/lwip/README b/components/lwip/lwip/README deleted file mode 100644 index 0884d27be..000000000 --- a/components/lwip/lwip/README +++ /dev/null @@ -1,100 +0,0 @@ -INTRODUCTION - -lwIP is a small independent implementation of the TCP/IP protocol -suite that has been developed by Adam Dunkels at the Computer and -Networks Architectures (CNA) lab at the Swedish Institute of Computer -Science (SICS). - -The focus of the lwIP TCP/IP implementation is to reduce the RAM usage -while still having a full scale TCP. This making lwIP suitable for use -in embedded systems with tens of kilobytes of free RAM and room for -around 40 kilobytes of code ROM. - - -FEATURES - - * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over - multiple network interfaces - * ICMP (Internet Control Message Protocol) for network maintenance and debugging - * IGMP (Internet Group Management Protocol) for multicast traffic management - * MLD (Multicast listener discovery for IPv6). Aims to be compliant with - RFC 2710. No support for MLDv2 - * ND (Neighbor discovery and stateless address autoconfiguration for IPv6). - Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - (Address autoconfiguration) - * UDP (User Datagram Protocol) including experimental UDP-lite extensions - * TCP (Transmission Control Protocol) with congestion control, RTT estimation - and fast recovery/fast retransmit - * raw/native API for enhanced performance - * Optional Berkeley-like socket API - * DNS (Domain names resolver) - - -APPLICATIONS - - * HTTP server with SSI and CGI - * SNMPv2c agent with MIB compiler (Simple Network Management Protocol) - * SNTP (Simple network time protocol) - * NetBIOS name service responder - * MDNS (Multicast DNS) responder - * iPerf server implementation - - -LICENSE - -lwIP is freely available under a BSD license. - - -DEVELOPMENT - -lwIP has grown into an excellent TCP/IP stack for embedded devices, -and developers using the stack often submit bug fixes, improvements, -and additions to the stack to further increase its usefulness. - -Development of lwIP is hosted on Savannah, a central point for -software development, maintenance and distribution. Everyone can -help improve lwIP by use of Savannah's interface, Git and the -mailing list. A core team of developers will commit changes to the -Git source tree. - -The lwIP TCP/IP stack is maintained in the 'lwip' Git module and -contributions (such as platform ports) are in the 'contrib' Git module. - -See doc/savannah.txt for details on Git server access for users and -developers. - -The current Git trees are web-browsable: - http://git.savannah.gnu.org/cgit/lwip.git - http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git - -Submit patches and bugs via the lwIP project page: - http://savannah.nongnu.org/projects/lwip/ - -Continuous integration builds (GCC, clang): - https://travis-ci.org/yarrick/lwip-merged - - -DOCUMENTATION - -Self documentation of the source code is regularly extracted from the current -Git sources and is available from this web page: - http://www.nongnu.org/lwip/ - -There is now a constantly growing wiki about lwIP at - http://lwip.wikia.com/wiki/LwIP_Wiki - -Also, there are mailing lists you can subscribe at - http://savannah.nongnu.org/mail/?group=lwip -plus searchable archives: - http://lists.nongnu.org/archive/html/lwip-users/ - http://lists.nongnu.org/archive/html/lwip-devel/ - -lwIP was originally written by Adam Dunkels: - http://dunkels.com/adam/ - -Reading Adam's papers, the files in docs/, browsing the source code -documentation and browsing the mailing list archives is a good way to -become familiar with the design of lwIP. - -Adam Dunkels -Leon Woestenberg diff --git a/components/lwip/lwip/UPGRADING b/components/lwip/lwip/UPGRADING deleted file mode 100644 index 60a04385d..000000000 --- a/components/lwip/lwip/UPGRADING +++ /dev/null @@ -1,243 +0,0 @@ -This file lists major changes between release versions that require -ports or applications to be changed. Use it to update a port or an -application written for an older version of lwIP to correctly work -with newer versions. - - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(2.0.2) - - ++ Application changes: - - * slipif: The way to pass serial port number has changed. netif->num is not - supported any more, netif->state is interpreted as an u8_t port number now - (it's not a POINTER to an u8_t any more!) - -(2.0.1) - - ++ Application changes: - - * UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific - netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare - ip_current_netif() to the desired netif for every packet. - See bug #49662 for an explanation. - -(2.0.0) - - ++ Application changes: - - * Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of - "ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif - has to be set "up" before starting the DHCP client - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). - * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); - supports SNMPv2c (experimental v3 support) - * Moved some core applications from contrib repository to src/apps (and include/lwip/apps) - - +++ Raw API: - * Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/ - tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb - - +++ Socket API: - * Added an implementation for posix sendmsg() - * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram - - ++ Port changes - - +++ new files: - * MANY new and moved files! - * Added src/Filelists.mk for use in Makefile projects - * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" - to let abc.h only contain the actual application programmer's API - - +++ sys layer: - * Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than - the traditional message passing (although with LWIP_COMPAT_MUTEX you are still - open to priority inversion, so this is not recommended any more) - * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread - instead of using one per netconn (these semaphores are used even with core locking - enabled as some longer lasting functions like big writes still need to delay) - * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() - in def.h (to be overridden in cc.h) instead of config - options for netbiosns, httpd, dns, etc. ... - * New abstraction for hton* and ntoh* functions in def.h. - To override them, use the following in cc.h: - #define lwip_htons(x) - #define lwip_htonl(x) - - +++ new options: - * TODO - - +++ new pools: - * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools - that share memp.c code but do not have to be made global via lwippools.h - * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc. - * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item - is now available - - * Signature of LWIP_HOOK_VLAN_SET macro was changed - - * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) - or to move buffers to dedicated memory using compiler attributes - - * Standard C headers are used to define sized types and printf formatters - (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler - does not support these) - - - ++ Major bugfixes/improvements - - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Major rewrite of PPP (incl. keep-up with apache pppd) - see doc/ppp.txt for an upgrading how-to - * Major rewrite of SNMP (incl. MIB parser) - * Fixed timing issues that might have lead to losing a DHCP lease - * Made rx processing path more robust against crafted errors - * TCP window scaling support - * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) - * made DNS client more robust - * support PBUF_REF for RX packets - * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate - threads each (needs LWIP_NETCONN_SEM_PER_THREAD) - * Moved and reordered stats (mainly memp/mib2) - -(1.4.0) - - ++ Application changes: - - * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for - compatibility to old applications, but will be removed in the future). - - * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() - - +++ Raw API: - * Changed the semantics of tcp_close() (since it was rather a - shutdown before): Now the application does *NOT* get any calls to the recv - callback (aside from NULL/closed) after calling tcp_close() - - * When calling tcp_abort() from a raw API TCP callback function, - make sure you return ERR_ABRT to prevent accessing unallocated memory. - (ERR_ABRT now means the applicaiton has called tcp_abort!) - - +++ Netconn API: - * Changed netconn_receive() and netconn_accept() to return - err_t, not a pointer to new data/netconn. - - +++ Socket API: - * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they - now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. - - * Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - +++ all APIs: - * correctly implemented SO(F)_REUSEADDR - - ++ Port changes - - +++ new files: - - * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: - - * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains - the actual application programmer's API - - * Separated timer implementation from sys.h/.c, moved to timers.h/.c; - Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you - still want to use your own timer implementation for NO_SYS==0 (as before). - - +++ sys layer: - - * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ - sys_sem_t; - - * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - - * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use - binary semaphores instead of mutexes - as before) - - +++ new options: - - * Don't waste memory when chaining segments, added option TCP_OVERSIZE to - prevent creating many small pbufs when calling tcp_write with many small - blocks of data. Instead, pbufs are allocated larger than needed and the - space is used for later calls to tcp_write. - - * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs - in tcp_write/udp_send. - - * Added an additional option LWIP_ETHERNET to support ethernet without ARP - (necessary for pure PPPoE) - - * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may - be used to place these pools into user-defined memory by using external - declaration. - - * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT - - +++ new pools: - - * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, - so MEMP_NUM_NETDB has to be set accordingly. - - * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so - MEMP_NUM_LOCALHOSTLIST has to be set accordingly. - - * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have - to be set accordingly. - - * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES - has to be set accordingly - - * Integrated loopif into netif.c - loopif does not have to be created by the - port any more, just define LWIP_HAVE_LOOPIF to 1. - - * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined - in cc.h, e.g. used by igmp) - - * Added printf-formatter X8_F to printf u8_t as hex - - * The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - - * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work - with user-allocated structs instead of calling mem_malloc - - * Added const char* name to mem- and memp-stats for easier debugging. - - * Calculate the TCP/UDP checksum while copying to only fetch data once: - Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum - - * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to - more than one pcb. - - * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned - off any more, if this is set to 0, only one packet (the most recent one) is - queued (like demanded by RFC 1122). - - - ++ Major bugfixes/improvements - - * Implemented tcp_shutdown() to only shut down one end of a connection - * Implemented shutdown() at socket- and netconn-level - * Added errorset support to select() + improved select speed overhead - * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) - * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 - * Use macros defined in ip_addr.h to work with IP addresses - * Implemented many nonblocking socket/netconn functions - * Fixed ARP input processing: only add a new entry if a request was directed as us - * mem_realloc() to mem_trim() to prevent confusion with realloc() - * Some improvements for AutoIP (don't route/forward link-local addresses, don't break - existing connections when assigning a routable address) - * Correctly handle remote side overrunning our rcv_wnd in ooseq case - * Removed packing from ip_addr_t, the packed version is now only used in protocol headers - * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 - * Added support for static ARP table entries - -(STABLE-1.3.2) - - * initial version of this file diff --git a/components/lwip/lwip/doc/FILES b/components/lwip/lwip/doc/FILES deleted file mode 100644 index e58857508..000000000 --- a/components/lwip/lwip/doc/FILES +++ /dev/null @@ -1,9 +0,0 @@ -doxygen/ - Configuration files and scripts to create the lwIP doxygen source - documentation (found at http://www.nongnu.org/lwip/) - -savannah.txt - How to obtain the current development source code. -contrib.txt - How to contribute to lwIP as a developer. -rawapi.txt - The documentation for the core API of lwIP. - Also provides an overview about the other APIs and multithreading. -sys_arch.txt - The documentation for a system abstraction layer of lwIP. -ppp.txt - Documentation of the PPP interface for lwIP. diff --git a/components/lwip/lwip/doc/NO_SYS_SampleCode.c b/components/lwip/lwip/doc/NO_SYS_SampleCode.c deleted file mode 100644 index f0af6600b..000000000 --- a/components/lwip/lwip/doc/NO_SYS_SampleCode.c +++ /dev/null @@ -1,122 +0,0 @@ -void -eth_mac_irq() -{ - /* Service MAC IRQ here */ - - /* Allocate pbuf from pool (avoid using heap in interrupts) */ - struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL); - - if(p != NULL) { - /* Copy ethernet frame into pbuf */ - pbuf_take(p, eth_data, eth_data_count); - - /* Put in a queue which is processed in main loop */ - if(!queue_try_put(&queue, p)) { - /* queue is full -> packet loss */ - pbuf_free(p); - } - } -} - -static err_t -netif_output(struct netif *netif, struct pbuf *p) -{ - LINK_STATS_INC(link.xmit); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - } - - lock_interrupts(); - pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0); - /* Start MAC transmit here */ - unlock_interrupts(); - - return ERR_OK; -} - -static void -netif_status_callback(struct netif *netif) -{ - printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); -} - -static err_t -netif_init(struct netif *netif) -{ - netif->linkoutput = netif_output; - netif->output = etharp_output; - netif->output_ip6 = ethip6_output; - netif->mtu = ETHERNET_MTU; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; - MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000); - - SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr)); - netif->hwaddr_len = sizeof(netif->hwaddr); - - return ERR_OK; -} - -void -main(void) -{ - struct netif netif; - - lwip_init(); - - netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input); - netif.name[0] = 'e'; - netif.name[1] = '0'; - netif_create_ip6_linklocal_address(&netif, 1); - netif.ip6_autoconfig_enabled = 1; - netif_set_status_callback(&netif, netif_status_callback); - netif_set_default(&netif); - netif_set_up(&netif); - - /* Start DHCP and HTTPD */ - dhcp_start(&netif ); - httpd_init(); - - while(1) { - /* Check link state, e.g. via MDIO communication with PHY */ - if(link_state_changed()) { - if(link_is_up()) { - netif_set_link_up(&netif); - } else { - netif_set_link_down(&netif); - } - } - - /* Check for received frames, feed them to lwIP */ - lock_interrupts(); - struct pbuf* p = queue_try_get(&queue); - unlock_interrupts(); - - if(p != NULL) { - LINK_STATS_INC(link.recv); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); - } - - if(netif.input(p, &netif) != ERR_OK) { - pbuf_free(p); - } - } - - /* Cyclic lwIP timers check */ - sys_check_timeouts(); - - /* your application goes here */ - } -} diff --git a/components/lwip/lwip/doc/contrib.txt b/components/lwip/lwip/doc/contrib.txt deleted file mode 100644 index 6f0d7bc51..000000000 --- a/components/lwip/lwip/doc/contrib.txt +++ /dev/null @@ -1,58 +0,0 @@ -1 Introduction - -This document describes some guidelines for people participating -in lwIP development. - -2 How to contribute to lwIP - -Here is a short list of suggestions to anybody working with lwIP and -trying to contribute bug reports, fixes, enhancements, platform ports etc. -First of all as you may already know lwIP is a volunteer project so feedback -to fixes or questions might often come late. Hopefully the bug and patch tracking -features of Savannah help us not lose users' input. - -2.1 Source code style: - -1. do not use tabs. -2. indentation is two spaces per level (i.e. per tab). -3. end debug messages with a trailing newline (\n). -4. one space between keyword and opening bracket. -5. no space between function and opening bracket. -6. one space and no newline before opening curly braces of a block. -7. closing curly brace on a single line. -8. spaces surrounding assignment and comparisons. -9. don't initialize static and/or global variables to zero, the compiler takes care of that. -10. use current source code style as further reference. - -2.2 Source code documentation style: - -1. JavaDoc compliant and Doxygen compatible. -2. Function documentation above functions in .c files, not .h files. - (This forces you to synchronize documentation and implementation.) -3. Use current documentation style as further reference. - -2.3 Bug reports and patches: - -1. Make sure you are reporting bugs or send patches against the latest - sources. (From the latest release and/or the current Git sources.) -2. If you think you found a bug make sure it's not already filed in the - bugtracker at Savannah. -3. If you have a fix put the patch on Savannah. If it is a patch that affects - both core and arch specific stuff please separate them so that the core can - be applied separately while leaving the other patch 'open'. The preferred way - is to NOT touch archs you can't test and let maintainers take care of them. - This is a good way to see if they are used at all - the same goes for unix - netifs except tapif. -4. Do not file a bug and post a fix to it to the patch area. Either a bug report - or a patch will be enough. - If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. -5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other - trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you - change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than - if it's not to the point and long :) so the chances for it to be applied are greater. - -2.4 Platform porters: - -1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and - you think it could benefit others[1] you might want discuss this on the mailing list. You - can also ask for Git access to submit and maintain your port in the contrib Git module. diff --git a/components/lwip/lwip/doc/doxygen/generate.bat b/components/lwip/lwip/doc/doxygen/generate.bat deleted file mode 100644 index 99afb124b..000000000 --- a/components/lwip/lwip/doc/doxygen/generate.bat +++ /dev/null @@ -1 +0,0 @@ -doxygen lwip.Doxyfile diff --git a/components/lwip/lwip/doc/doxygen/generate.sh b/components/lwip/lwip/doc/doxygen/generate.sh deleted file mode 100755 index 89344b0e8..000000000 --- a/components/lwip/lwip/doc/doxygen/generate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -doxygen lwip.Doxyfile diff --git a/components/lwip/lwip/doc/doxygen/lwip.Doxyfile b/components/lwip/lwip/doc/doxygen/lwip.Doxyfile deleted file mode 100644 index 95fa363b4..000000000 --- a/components/lwip/lwip/doc/doxygen/lwip.Doxyfile +++ /dev/null @@ -1,2505 +0,0 @@ -# Doxyfile 1.8.11 - -# 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 = "lwIP" - -# 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 = "2.0.3" - -# 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 = "Lightweight IP stack" - -# With the PROJECT_LOGO tag one can specify a logo or an 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 = output - -# 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 - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = 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, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, 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 = 8 - -# 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 (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), 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 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 - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = 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. If 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 = YES - -# 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 = YES - -# 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 = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# 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 SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# 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. Note that -# this will also influence the order of the classes in the class list. -# 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 = NO - -# 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 ... \endif and \cond -# ... \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. 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 - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = 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. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = main_page.h ../../src - -# 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. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# 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, *.pyw, *.f90, *.f, *.for, *.tcl, -# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.inc \ - *.m \ - *.mm \ - *.dox - -# 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 = ../../src/include/netif/ppp/polarssl - -# 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: -# -# -# -# where is the value of the INPUT_FILTER tag, and 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. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -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. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -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 = main_page.h - -#--------------------------------------------------------------------------- -# 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 = NO - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate 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 -# generated with the -Duse-libclang=ON option for CMake. -# 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 = NO - -# 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 additional user-defined -# cascading style sheets that are 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 therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). 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 style sheet 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 YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# 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 = lwip.chm - -# 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. Furthermore it -# enables the Previous and Next buttons. -# 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 style sheets (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 - -# If 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 pre-rendered 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 + S -# (what the is depends on the OS and browser, but it is typically -# , /