From 8342e948c6739ee09494f438a3e97761b10a4d79 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 10 Oct 2019 16:13:24 +0200 Subject: [PATCH 001/120] meta-digi-dey: bump distro version to 2.6-r3 Signed-off-by: Arturo Buzarra --- README.md | 2 +- meta-digi-dey/conf/distro/dey.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c93029719..fc9a0a04f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Digi Embedded Yocto (DEY) 2.6 -## Release 2.6-r2 +## Release 2.6-r3 This document provides information about Digi Embedded Yocto, Digi International's professional embedded Yocto development environment. diff --git a/meta-digi-dey/conf/distro/dey.conf b/meta-digi-dey/conf/distro/dey.conf index 2b1380cb3..bd700e6d7 100644 --- a/meta-digi-dey/conf/distro/dey.conf +++ b/meta-digi-dey/conf/distro/dey.conf @@ -1,6 +1,6 @@ DISTRO = "dey" DISTRO_NAME = "Digi Embedded Yocto" -DISTRO_VERSION = "2.6-r2" +DISTRO_VERSION = "2.6-r3" DISTRO_CODENAME = "thud" SDK_VENDOR = "-deysdk" SDK_VERSION := "${@'${DISTRO_VERSION}'}" From 224c4fc4183f70503dee25053e7b5ca45e0f432e Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 1 Oct 2019 17:01:17 +0200 Subject: [PATCH 002/120] qualcomm.sh: generalize to select correct board data file Generalize script to select the correct board data file to load into the wireless chip depending on the Regulatory Domain configuration whether it is a variation of 'bdwlan30.bin' or 'fakeboar.bin'. If 'bdwlan30_US.bin' or 'bdwlan30_World.bin' files are found in the firmware directory, the script will create two symlinks, 'bdwlan30.bin and 'utfbd30.bin', pointing to either one of those files. If no 'bdwlan30_*.bin' files are found, but 'fakeboar_US.bin' or 'fakeboar_World.bin' is, it will create a single symlink, 'fakeboar.bin', pointing to either one of those files. In the case a QCA6574 community driver is loaded, 'board.bin' symlink will be updated. If no 'fakeboard_*.bin' files are found either, the script will exit. https://jira.digi.com/browse/DEL-6773 Signed-off-by: Gonzalo Ruiz --- .../kernel-module-qualcomm/qualcomm.sh | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh index d2097595c..2a8980b9a 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh @@ -80,14 +80,33 @@ esac ( cd "${FIRMWARE_DIR}" - BDATA_SOURCE="bdwlan30_US.bin" + if [ -f "bdwlan30_US.bin" ] || [ -f "bdwlan30_World.bin" ]; then + BDATA_US="bdwlan30_US.bin" + BDATA_WW="bdwlan30_World.bin" + BDATA_LINK="bdwlan30.bin" + UTFBDATA_LINK="utfbd30.bin" + elif [ -f "fakeboar_US.bin" ] || [ -f "fakeboar_World.bin" ]; then + BDATA_US="fakeboar_US.bin" + BDATA_WW="fakeboar_World.bin" + # Use different links for propietary and community drivers + if [ -f "board.bin" ]; then + BDATA_LINK="board.bin" + else + BDATA_LINK="fakeboar.bin" + fi + else + log "5" "[ERROR] Could not locate board data files" + exit 1 + fi + + BDATA_SOURCE="${BDATA_US}" case "${REGULATORY_DOMAIN}" in ${US_CODE}) log "5" "Setting US wireless region";; ${WW_CODE}|${JP_CODE}) - if [ -f "bdwlan30_World.bin" ]; then + if [ -f "${BDATA_WW}" ]; then log "5" "Setting WW (world wide) wireless region" - BDATA_SOURCE="bdwlan30_World.bin" + BDATA_SOURCE="${BDATA_WW}" else log "5" "[WARN] No WW (worldwide) board data file, using US" fi @@ -98,12 +117,16 @@ esac log "5" "[WARN] Invalid region code, using US";; esac - # We don't want to rewrite NAND every time we boot so only - # change the links if they are wrong. - BDATA_LINK="bdwlan30.bin" - UTFBDATA_LINK="utfbd30.bin" - if [ ! -e "${BDATA_LINK}" ] || ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"; then + # When defined, update the links only if they are wrong so we don't + # rewrite the internal memory every time we boot + if [ -n "${BDATA_LINK}" ] && + ([ ! -f "${BDATA_LINK}" ] || + ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"); then ln -sf "${BDATA_SOURCE}" "${BDATA_LINK}" + fi + if [ -n "${UTFBDATA_LINK}" ] && + ([ ! -f "${UTFBDATA_LINK}" ] || + ! cmp -s "${UTFBDATA_LINK}" "${BDATA_SOURCE}"); then ln -sf "${BDATA_SOURCE}" "${UTFBDATA_LINK}" fi ) From 9c392c5b7c57f9789981c9f21956f711db855f51 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 1 Oct 2019 17:13:03 +0200 Subject: [PATCH 003/120] firmware-qualcomm: rename BDF to 'fakeboar_US.bin' Rename board data file loaded on qca6574 wireless chips to 'fakeboar_US.bin'. A symlink named 'fakeboar.bin' will be created by 'qualcomm.sh' selecting either this file or the WorlWide variant: 'fakeboar_World.bin'. - fakeboard_US.bin (e1db4a300b58776f8abd8588beadc09e) https://jira.digi.com/browse/DEL-6773 Signed-off-by: Gonzalo Ruiz --- .../firmware-qualcomm/firmware-qualcomm.bb | 10 +++++----- .../{fakeboar.bin => fakeboar_US.bin} | Bin 2 files changed, 5 insertions(+), 5 deletions(-) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/{fakeboar.bin => fakeboar_US.bin} (100%) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 474713043..73101f768 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -27,21 +27,21 @@ FW_QCA6564_WIFI_PROPRIETARY = " \ FW_QCA6574_WIFI_PROPRIETARY = " \ file://LICENCE.atheros_firmware \ file://qca6574_proprietary/qwlan30.bin \ - file://qca6574_proprietary/fakeboar.bin \ + file://qca6574_proprietary/fakeboar_US.bin \ file://qca6574_proprietary/otp.bin \ file://qca6574_proprietary/utf.bin \ " # Firmware files for QCA6574 (Qualcomm community driver) # NOTE: the community file 'board.bin' must be substituted by proprietary -# 'fakeboar.bin' +# 'fakeboar_US.bin' FW_QCA6574_WIFI_COMMUNITY = " \ file://qca6574_community/board-2.bin \ file://qca6574_community/firmware-4.bin \ file://qca6574_community/firmware-6.bin \ file://qca6574_community/notice_ath10k_firmware-4.txt \ file://qca6574_community/notice_ath10k_firmware-6.txt \ - file://qca6574_proprietary/fakeboar.bin \ + file://qca6574_proprietary/fakeboar_US.bin \ " FW_QUALCOMM_WIFI ?= "${FW_QCA6564_WIFI_PROPRIETARY}" @@ -72,8 +72,8 @@ do_install() { install -m 0644 ${FW_WIFI_FILES} ${D}${WIFI_FW_PATH} if [ "${QUALCOMM_WIFI_DRIVER}" = "community" ]; then # If using community driver, create symlink 'board.bin' to - # proprietary 'fakeboar.bin' - ln -s fakeboar.bin ${D}${WIFI_FW_PATH}/board.bin + # proprietary 'fakeboar_US.bin' + ln -s fakeboar_US.bin ${D}${WIFI_FW_PATH}/board.bin else if [ "${FW_QUALCOMM_WIFI}" = "${FW_QCA6574_WIFI_PROPRIETARY}" ]; then ln -s qwlan30.bin ${D}${WIFI_FW_PATH}/athwlan.bin diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin similarity index 100% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin From f3692de0c55c6dd57933a25ec7312f44b876458d Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 3 Oct 2019 17:04:24 +0200 Subject: [PATCH 004/120] pulseaudio: let systemd know the PID of the pulseaudio daemon Otherwise, systemd will have to guess the PID of the service's main process. It guesses right most of the time, but sometimes it chooses the PID of the original pulseaudio process instead of the daemon that gets forked off. This caused the daemon to stop immediately after starting, breaking other apps that require the pulseaudio server to be running. Since the PID file is created in a user-specific runtime directory (and the service is meant for the whole system), modify the wrapper script to create a symlink to the PID file in a place where it can be obtained by systemd. https://jira.digi.com/browse/DEL-6795 Signed-off-by: Gabriel Valcazar --- .../recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init | 3 +++ .../pulseaudio/pulseaudio/pulseaudio-system.service | 1 + 2 files changed, 4 insertions(+) diff --git a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init index 14096506d..46a31676b 100644 --- a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init +++ b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init @@ -9,3 +9,6 @@ export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus pulseaudio --start + +# Create a symlink to the daemon's PID file in a more accesible directory +ln -sf $XDG_RUNTIME_DIR/pulse/pid /run/pulse.pid diff --git a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-system.service b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-system.service index f1fa28d69..8a7f8cc0b 100644 --- a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-system.service +++ b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-system.service @@ -4,6 +4,7 @@ After=dbus.service [Service] Type=forking +PIDFile=/run/pulse.pid ExecStart=/etc/pulseaudio-init ExecStop=kill -HUP $MAINPID From 5424fb89db132b346c9a9c519331f2a880d48d83 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Fri, 4 Oct 2019 09:30:17 +0200 Subject: [PATCH 005/120] pulseaudio-init: cosmetic: add curly braces to variable expansions Signed-off-by: Gabriel Valcazar --- .../recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init index 46a31676b..22284ceee 100644 --- a/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init +++ b/meta-digi-dey/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio-init @@ -6,9 +6,9 @@ [ -f "/etc/profile.d/weston.sh" ] && source /etc/profile.d/weston.sh [ -f "/etc/X11/Xsession.d/13xdgbasedirs.sh" ] && source /etc/X11/Xsession.d/13xdgbasedirs.sh -export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus +export DBUS_SESSION_BUS_ADDRESS=unix:path=${XDG_RUNTIME_DIR}/bus pulseaudio --start # Create a symlink to the daemon's PID file in a more accesible directory -ln -sf $XDG_RUNTIME_DIR/pulse/pid /run/pulse.pid +ln -sf ${XDG_RUNTIME_DIR}/pulse/pid /run/pulse.pid From 9c7c5e5bfb165a414f18fdb9442d6bee086d9699 Mon Sep 17 00:00:00 2001 From: Hector Bujanda Date: Thu, 17 Oct 2019 11:33:50 +0200 Subject: [PATCH 006/120] mca_tool: update checksums for build 1.19 This new version improves mca_fw_update algorithms. https://jira.digi.com/browse/DEL-6801 Signed-off-by: Hector Bujanda --- .../mca/{mca-tool_1.18.bb => mca-tool_1.19.bb} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename meta-digi-arm/recipes-digi/mca/{mca-tool_1.18.bb => mca-tool_1.19.bb} (61%) diff --git a/meta-digi-arm/recipes-digi/mca/mca-tool_1.18.bb b/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb similarity index 61% rename from meta-digi-arm/recipes-digi/mca/mca-tool_1.18.bb rename to meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb index d410e90fb..635c49933 100644 --- a/meta-digi-arm/recipes-digi/mca/mca-tool_1.18.bb +++ b/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb @@ -8,13 +8,13 @@ PKGNAME = "mca_tool" # ARM tarball SRC_URI_arm = "${DIGI_PKG_SRC}/${PKGNAME}-${PV}-${TUNE_ARCH}.tar.gz;name=arm" -SRC_URI[arm.md5sum] = "aa2037b93dadafe160824f7d63dd8582" -SRC_URI[arm.sha256sum] = "7dbc07672d5cce52e3ec611a1bcef1b6c0aed278fbcd6a150b3f528d8da66065" +SRC_URI[arm.md5sum] = "f677ccb2b6b627838c028f2281aa5b8c" +SRC_URI[arm.sha256sum] = "180ad5cdb9ddce7980db8019e9e710fcabde39ed896614f3ec8a05fedeb479f1" # AARCH64 tarball SRC_URI_aarch64 = "${DIGI_PKG_SRC}/${PKGNAME}-${PV}-${TUNE_ARCH}.tar.gz;name=aarch64" -SRC_URI[aarch64.md5sum] = "40d8113353daf8e426597c289f6659d8" -SRC_URI[aarch64.sha256sum] = "a0f7d8bae72f9dcdb1102bcf3e42a4b66d4f66b4bef43f80a4fd63282562a9d4" +SRC_URI[aarch64.md5sum] = "183966e276383585048b85bfdf38fb49" +SRC_URI[aarch64.sha256sum] = "e7d0f375bd50b2f1936ba4770e64e8dc8f14af39cee4a85e26e4a22843a5638a" S = "${WORKDIR}/${PKGNAME}-${PV}" From 2a0636760ecdb6b2b528ae7296962d4c7c53dccc Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 17 Oct 2019 11:42:56 +0200 Subject: [PATCH 007/120] systemd: decrease timeout when stopping services In very rare cases, random services would hang when powering off the system, causing the poweroff process to stall for 90 seconds before timing out the stop job. To avoid this behaviour, minimize the effect of these random freezes by decreasing the timeout. The default services in our system take well under 15 seconds to stop gracefully, so we can guarantee that a timeout will never happen under normal circumstances. https://jira.digi.com/browse/DEL-6794 Signed-off-by: Gabriel Valcazar --- .../systemd/systemd-conf.bbappend | 7 +++++ ...ce-default-stop-timeout-to-15-second.patch | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 meta-digi-dey/recipes-core/systemd/systemd-conf.bbappend create mode 100644 meta-digi-dey/recipes-core/systemd/systemd-conf/0001-system.conf-reduce-default-stop-timeout-to-15-second.patch diff --git a/meta-digi-dey/recipes-core/systemd/systemd-conf.bbappend b/meta-digi-dey/recipes-core/systemd/systemd-conf.bbappend new file mode 100644 index 000000000..f0a949fef --- /dev/null +++ b/meta-digi-dey/recipes-core/systemd/systemd-conf.bbappend @@ -0,0 +1,7 @@ +# Copyright (C) 2019 by Digi International Inc. + +FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" + +SRC_URI += "\ + file://0001-system.conf-reduce-default-stop-timeout-to-15-second.patch \ +" diff --git a/meta-digi-dey/recipes-core/systemd/systemd-conf/0001-system.conf-reduce-default-stop-timeout-to-15-second.patch b/meta-digi-dey/recipes-core/systemd/systemd-conf/0001-system.conf-reduce-default-stop-timeout-to-15-second.patch new file mode 100644 index 000000000..0b210dfd8 --- /dev/null +++ b/meta-digi-dey/recipes-core/systemd/systemd-conf/0001-system.conf-reduce-default-stop-timeout-to-15-second.patch @@ -0,0 +1,29 @@ +From: Gabriel Valcazar +Date: Thu, 17 Oct 2019 09:45:31 +0200 +Subject: [PATCH] system.conf: reduce default stop timeout to 15 seconds + +We currently don't have any services that, under normal circumstances, take +over 10 seconds to stop. In exceptional cases where services hang when stopping +due to unknown circumstances, make the timeout happen earlier to avoid stalling +the entire poweroff process for 90 seconds. + +https://jira.digi.com/browse/DEL-6794 + +Signed-off-by: Gabriel Valcazar +--- + src/core/system.conf.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/core/system.conf.in b/src/core/system.conf.in +index f0a59a7..c25257d 100644 +--- a/src/core/system.conf.in ++++ b/src/core/system.conf.in +@@ -35,6 +35,8 @@ + #DefaultStandardError=inherit + #DefaultTimeoutStartSec=90s + #DefaultTimeoutStopSec=90s ++# Digi-specific ++DefaultTimeoutStopSec=15s + #DefaultRestartSec=100ms + #DefaultStartLimitIntervalSec=10s + #DefaultStartLimitBurst=5 From 4df8f37ec4a4b961f587acfa4783c4d638af66f9 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 23 Oct 2019 09:53:50 +0200 Subject: [PATCH 008/120] imx-gpu-viv: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 Update to v6.2.4.p4.4 https://jira.digi.com/browse/DEL-6823 Signed-off-by: Arturo Buzarra --- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch32.bb | 8 -------- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch64.bb | 8 -------- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb | 8 ++++++++ .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb | 8 ++++++++ 4 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch32.bb delete mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch64.bb create mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb create mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch32.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch32.bb deleted file mode 100644 index 8761a980f..000000000 --- a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch32.bb +++ /dev/null @@ -1,8 +0,0 @@ -require imx-gpu-viv-v6.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" - -SRC_URI[md5sum] = "db096170c024aee88c48dd5b627e54b9" -SRC_URI[sha256sum] = "aa53c15c34b7af3b05876a0dfe4046ed4b864464d1bc9f10dcc0978e448f12a2" - -COMPATIBLE_MACHINE = "(mx6q|mx6dl|mx6sx|mx6sl|mx7ulp)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch64.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch64.bb deleted file mode 100644 index 66e2da76f..000000000 --- a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.2-aarch64.bb +++ /dev/null @@ -1,8 +0,0 @@ -require imx-gpu-viv-v6.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" - -SRC_URI[md5sum] = "fd50ff48725e6dd44aab2e08aeb87717" -SRC_URI[sha256sum] = "a36cea6116f3e04ef0fbaf880965eed71b093a065e25c91b2b494df0f944792b" - -COMPATIBLE_MACHINE = "(mx8)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb new file mode 100644 index 000000000..1872bcb1d --- /dev/null +++ b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb @@ -0,0 +1,8 @@ +require imx-gpu-viv-v6.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" + +SRC_URI[md5sum] = "6964c366e3998c60ca1dae5d3e2da33c" +SRC_URI[sha256sum] = "9cf5528a0ad8c53b2bcba236cb6861f5ef0c0c0735b3de5bab1ed0697be7b770" + +COMPATIBLE_MACHINE = "(mx6q|mx6dl|mx6sx|mx6sl|mx7ulp)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb new file mode 100644 index 000000000..8ea001d1f --- /dev/null +++ b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb @@ -0,0 +1,8 @@ +require imx-gpu-viv-v6.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" + +SRC_URI[md5sum] = "0868b86e5368d35fb4f3eac89b67c43b" +SRC_URI[sha256sum] = "527cdef23d5c9980fcecd5404c42950bfb7af947ae7bd84483fef073703e0686" + +COMPATIBLE_MACHINE = "(mx8)" From e31a868507b249ad6e699670e3221b5a0ed3d087 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 23 Oct 2019 10:26:26 +0200 Subject: [PATCH 009/120] imx-gpu-g2d: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 Update to v6.2.4.p4.4. https://jira.digi.com/browse/DEL-6823 Signed-off-by: Arturo Buzarra --- ...gpu-g2d_6.2.4.p4.2.bb => imx-gpu-g2d_6.2.4.p4.4.bb} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename meta-digi-dey/recipes-graphics/imx-gpu-g2d/{imx-gpu-g2d_6.2.4.p4.2.bb => imx-gpu-g2d_6.2.4.p4.4.bb} (70%) diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.2.bb b/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb similarity index 70% rename from meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.2.bb rename to meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb index b9688af78..f00fe067b 100644 --- a/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.2.bb +++ b/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb @@ -5,7 +5,7 @@ DESCRIPTION = "GPU G2D library and apps for i.MX with 2D GPU and no DPU" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" +LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" DEPENDS += "libgal-imx" PROVIDES += "virtual/libg2d" @@ -13,10 +13,10 @@ PROVIDES += "virtual/libg2d" FSLBIN_NAME = "${PN}-${PV}-${TARGET_ARCH}" SRC_URI = "${FSL_MIRROR}/${FSLBIN_NAME}.bin;name=${TARGET_ARCH};fsl-eula=true" -SRC_URI[aarch64.md5sum] = "a2d9e2b0f373a14bb41621a1cded3112" -SRC_URI[aarch64.sha256sum] = "b5bd824386c30fbe167a529344a3e6f7c87adf9e9bdd4184680e28968d1e9853" -SRC_URI[arm.md5sum] = "83777eac2bcd959894ca964f9cb5c9a0" -SRC_URI[arm.sha256sum] = "2210c5590a822a764838dfdefed08c882c70c14dc29fba04c255cee8b4df5196" +SRC_URI[aarch64.md5sum] = "813675d610456050d23d13c383bfd272" +SRC_URI[aarch64.sha256sum] = "49443d34469a2464fc8d9ad412507a2da70154e79aa49803d64b23564ea61cb7" +SRC_URI[arm.md5sum] = "606909745143d7f7cb12f3f30af8946a" +SRC_URI[arm.sha256sum] = "a028fbbceb51e61662210bce7a4e50812d354bce54ba8e1d3a3af59338471ef1" S="${WORKDIR}/${FSLBIN_NAME}" From 99cfd06c9dea1b486a9ee164531479580e9d5543 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 23 Oct 2019 10:31:17 +0200 Subject: [PATCH 010/120] firmware-imx: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 Update to v8.4. https://jira.digi.com/browse/DEL-6823 Signed-off-by: Arturo Buzarra --- .../{firmware-imx_8.3.bb => firmware-imx_8.4.bb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename meta-digi-arm/recipes-bsp/firmware-imx/{firmware-imx_8.3.bb => firmware-imx_8.4.bb} (94%) diff --git a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.3.bb b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb similarity index 94% rename from meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.3.bb rename to meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb index 599efb4df..f3f0d3e3e 100644 --- a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.3.bb +++ b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb @@ -6,14 +6,14 @@ SUMMARY = "Freescale IMX firmware" DESCRIPTION = "Freescale IMX firmware such as for the VPU" SECTION = "base" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" +LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" PE = "1" SRC_URI = "${FSL_MIRROR}/firmware-imx-${PV}.bin;fsl-eula=true " -SRC_URI[md5sum] = "776c7fa64a6e96d9f0d9cd50bbf79ffc" -SRC_URI[sha256sum] = "48e4b9e4064930e2b6cd7f20f39177c8f4c5ef1a296f2ebc6ed422412ab56681" +SRC_URI[md5sum] = "d2d02f96dad4fb8350696eaa979d50e1" +SRC_URI[sha256sum] = "0bd050d5fceb7829201d33b19948b5717db106e3b676a777488c24130eba54b9" inherit fsl-eula-unpack allarch From ca9e743af85f38217c43ed7e45fb2d62115a3bd3 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 30 Oct 2019 11:15:33 +0100 Subject: [PATCH 011/120] imx-seco: add recipe to sync with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 This imx-seco recipe manages now the NXP IMX SECO firmware, it was removed from the firmware-imx recipe. https://jira.digi.com/browse/DEL-6823 Signed-off-by: Arturo Buzarra --- .../firmware-imx/firmware-imx_8.4.bb | 5 ---- .../imx-mkimage/imx-boot_0.2.bbappend | 2 +- .../recipes-bsp/imx-seco/imx-seco_2.3.1.bb | 30 +++++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb diff --git a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb index f3f0d3e3e..24bf14a09 100644 --- a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb +++ b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb @@ -75,12 +75,7 @@ do_deploy () { install -m 0644 ${S}/firmware/hdmi/cadence/hdmitxfw.bin ${DEPLOYDIR} install -m 0644 ${S}/firmware/hdmi/cadence/hdmirxfw.bin ${DEPLOYDIR} install -m 0644 ${S}/firmware/hdmi/cadence/dpfw.bin ${DEPLOYDIR} - # Deploy seco - install -m 0644 ${S}/firmware/seco/mx8qm-ahab-container.img ${DEPLOYDIR} - elif [ "${IS_MX8}" = "8qx" ]; then - # Deploy seco - install -m 0644 ${S}/firmware/seco/mx8qx-ahab-container.img ${DEPLOYDIR} fi } diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend index d308ac393..06155b0a1 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend @@ -8,7 +8,7 @@ SRCREV = "abd6ce551a7b81fc6953d32d92b24a4a1d4b214e" FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI_append_ccimx8x = " file://0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch" -IMX_EXTRA_FIRMWARE_ccimx8x = "digi-sc-firmware" +IMX_EXTRA_FIRMWARE_ccimx8x = "digi-sc-firmware imx-seco" DEPENDS_append_ccimx8x = " coreutils-native" diff --git a/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb new file mode 100644 index 000000000..bedaa7d2b --- /dev/null +++ b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb @@ -0,0 +1,30 @@ +# Copyright 2019 NXP + +SUMMARY = "NXP i.MX SECO firmware" +DESCRIPTION = "NXP IMX SECO firmware" +SECTION = "base" +LICENSE = "Proprietary" +LIC_FILES_CHKSUM = "file://COPYING;md5=fb0303e4ee8b0e71c094171e2272bd44" + +inherit fsl-eula-unpack deploy + +SRC_URI = "${FSL_MIRROR}/${PN}-${PV}.bin;fsl-eula=true " + +SRC_URI[md5sum] = "cf8d6bbf93f0aa6e1049f1098a0f7e0f" +SRC_URI[sha256sum] = "b429ac58b2ea1771b3fdf7ae87bf1d37ccaf596bde01a5ecccae27b2145f6824" + +do_compile[noexec] = "1" + +do_install[noexec] = "1" + +SECO_FIRMWARE_NAME ?= "mx8qm-ahab-container.img" +SECO_FIRMWARE_NAME_mx8qm = "mx8qm-ahab-container.img" +SECO_FIRMWARE_NAME_mx8qxp = "mx8qx-ahab-container.img" + +addtask deploy after do_install +do_deploy () { + # Deploy i.MX8 SECO firmware files + install -m 0644 ${S}/firmware/seco/${SECO_FIRMWARE_NAME} ${DEPLOYDIR} +} + +COMPATIBLE_MACHINE = "(mx8qm|mx8qxp)" From af4630615e3280b027e5124491b0cd9c57501aa0 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 6 Nov 2019 15:24:18 +0100 Subject: [PATCH 012/120] packagegroup-dey-qt: add QtQuickControls package with QML support for CC6UL Added QtQuickControls package on framebuffer images for ConnectCore 6UL platform to improve the user experience. It is not added to X11 images due to size limitations. https://jira.digi.com/browse/CC6UL-1108 Signed-off-by: Arturo Buzarra --- .../recipes-graphics/packagegroups/packagegroup-dey-qt.bb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-graphics/packagegroups/packagegroup-dey-qt.bb b/meta-digi-dey/recipes-graphics/packagegroups/packagegroup-dey-qt.bb index e0922e4a3..4a5171676 100644 --- a/meta-digi-dey/recipes-graphics/packagegroups/packagegroup-dey-qt.bb +++ b/meta-digi-dey/recipes-graphics/packagegroups/packagegroup-dey-qt.bb @@ -28,7 +28,7 @@ QT5_RDEPENDS_imxgpu2d = "${@bb.utils.contains('DISTRO_FEATURES', 'x11','${QT5_RD 'qtbase qtbase-plugins', d)}" QT5_RDEPENDS_imxpxp = "${@bb.utils.contains('DISTRO_FEATURES', 'x11','${QT5_RDEPENDS_common}', \ - 'qtbase qtbase-examples qtbase-plugins', d)}" + 'qtbase qtbase-examples qtbase-plugins qtquickcontrols2 qtquickcontrols2-qmlplugins', d)}" QT5_RDEPENDS_imxgpu3d = " \ ${QT5_RDEPENDS_common} \ From 6b5cd9465b9e17d9a4c3e583b2aea9c0cf093da4 Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Fri, 8 Nov 2019 09:59:03 +0100 Subject: [PATCH 013/120] libdigiapix: Update CCIMX8X conf file with new PWM and GPIO settings Signed-off-by: Mike Engel https://jira.digi.com/browse/DEL-6807 --- .../libdigiapix-git/ccimx8x-sbc-pro/libdigiapix.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8x-sbc-pro/libdigiapix.conf b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8x-sbc-pro/libdigiapix.conf index 5dc776e25..021aa99ca 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8x-sbc-pro/libdigiapix.conf +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8x-sbc-pro/libdigiapix.conf @@ -10,8 +10,8 @@ USER_LED0 = 223 # USER_LED1 - MCA_IO10 USER_LED1 = 215 -# USER BUTTON - MCA_IO05 -USER_BUTTON = 210 +# USER BUTTON - MCA_IO07 +USER_BUTTON = 212 [I2C] @@ -25,7 +25,7 @@ DEFAULT_SPI = 32766,0 [PWM] -# MCA PWM1 channel 0 on Expansion connector (MCA_IO5) +# MCA PWM2 channel 0 on Expansion connector (MCA_IO7) DEFAULT_PWM = 7,0 [ADC] From 869378d9d7243b663299958ef304f9a8e73832a7 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 5 Nov 2019 11:25:59 +0100 Subject: [PATCH 014/120] recipes-digi: remove cryptoauth-openssl-engine recipe This package has not been supported since OpenSSL was updated to v1.1.x, and it has been deprecated by Microchip. https://jira.digi.com/browse/DEL-6826 Signed-off-by: Gabriel Valcazar --- ...ons-to-the-cryptoauth-OpenSSL-engine.patch | 228 ------------------ .../cryptoauth-openssl-engine_git.bb | 37 --- 2 files changed, 265 deletions(-) delete mode 100644 meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine/0001-Digi-modifications-to-the-cryptoauth-OpenSSL-engine.patch delete mode 100644 meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine_git.bb diff --git a/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine/0001-Digi-modifications-to-the-cryptoauth-OpenSSL-engine.patch b/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine/0001-Digi-modifications-to-the-cryptoauth-OpenSSL-engine.patch deleted file mode 100644 index cc4f1196e..000000000 --- a/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine/0001-Digi-modifications-to-the-cryptoauth-OpenSSL-engine.patch +++ /dev/null @@ -1,228 +0,0 @@ -From: Gabriel Valcazar -Date: Fri, 27 Apr 2018 13:24:49 +0200 -Subject: [PATCH] Digi modifications to the cryptoauth OpenSSL engine - -https://jira.digi.com/browse/DEL-5592 - -Signed-off-by: Gabriel Valcazar ---- - Makefile | 1 + - cryptoauthlib/Makefile | 40 +++++++++++++++------------ - cryptoauthlib/lib/atca_cfgs.c | 16 +++++++++-- - cryptoauthlib/lib/openssl/eccx08_eckey_meth.c | 16 +++++------ - cryptoauthlib/lib/openssl/eccx08_engine.h | 4 +++ - 5 files changed, 49 insertions(+), 28 deletions(-) - create mode 100644 Makefile - -diff --git a/Makefile b/Makefile -new file mode 100644 -index 0000000..3025439 ---- /dev/null -+++ b/Makefile -@@ -0,0 +1 @@ -+include cryptoauthlib/Makefile -diff --git a/cryptoauthlib/Makefile b/cryptoauthlib/Makefile -index 399db53..b2596bb 100644 ---- a/cryptoauthlib/Makefile -+++ b/cryptoauthlib/Makefile -@@ -1,8 +1,11 @@ - .PHONY: all libcryptoauth libateccssl libpkcs11 dist install clean - --OPTIONS := ATCAPRINTF ATCA_HAL_KIT_CDC ENGINE_DYNAMIC_SUPPORT USE_ECCX08 ECC_DEBUG -+OPTIONS := ATCAPRINTF ATCA_HAL_I2C ENGINE_DYNAMIC_SUPPORT USE_ECCX08 ECC_DEBUG - --SYSTEM_INCLUDES := /usr/include -+SYSTEM_INCLUDES := $(DESTDIR)/usr/include -+ -+TARGET_ARCH = Linux -+TARGET_HAL = I2C - - # Check platform - ifeq ($(OS),Windows_NT) -@@ -38,7 +41,7 @@ endif - endif - - ifeq ($(uname_S),Linux) --CFLAGS += -g -O1 -m64 -Wall -fPIC $(addprefix -D,$(OPTIONS)) -+CFLAGS += -g -O1 -Wall -fPIC $(addprefix -D,$(OPTIONS)) - TARGET_ARCH := Linux - endif - # ifeq ($(uname_S),Darwin) -@@ -55,32 +58,32 @@ endif - # CCFLAGS += -D ARM - # endif - --OPENSSLDIR = /usr/include/openssl -+OPENSSLDIR = $(DESTDIR)/usr/include/openssl - --OUTDIR := $(abspath .build) -+OUTDIR := $(abspath cryptoauthlib/.build) - - DEPFLAGS = -MT $@ -MMD -MP -MF $(OUTDIR)/$*.d - ARFLAGS = rcs - - - # Wildcard all the sources and headers --SOURCES := $(call FIND,lib,*.c) --INCLUDE := $(sort $(dir $(call FIND, lib, *.h))) -+SOURCES := $(call FIND,cryptoauthlib/lib,*.c) -+INCLUDE := $(sort $(dir $(call FIND, cryptoauthlib/lib, *.h))) - - # Gather OpenSSL Engine objects --LIBATECCSSL_OBJECTS := $(filter $(abspath lib/openssl)/%, $(SOURCES)) -+LIBATECCSSL_OBJECTS := $(filter $(abspath cryptoauthlib/lib/openssl)/%, $(SOURCES)) - # Example if statically linking in the certificate definition - #LIBATECCSSL_OBJECTS += cert_def_1_signer.c cert_def_2_signer.c - LIBATECCSSL_OBJECTS := $(addprefix $(OUTDIR)/,$(notdir $(LIBATECCSSL_OBJECTS:.c=.o))) - - # Gather PKCS11 Objects --LIBPKCS11_OBJECTS := $(filter $(abspath lib/pkcs11)/%, $(SOURCES)) -+LIBPKCS11_OBJECTS := $(filter $(abspath cryptoauthlib/lib/pkcs11)/%, $(SOURCES)) - LIBPKCS11_OBJECTS := $(addprefix $(OUTDIR)/,$(notdir $(LIBPKCS11_OBJECTS:.c=.o))) - - # Gather libcryptoauth objects --LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath lib/hal)/%, $(SOURCES)) --LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath lib/pkcs11)/%, $(LIBCRYPTOAUTH_OBJECTS)) --LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath lib/openssl)/%, $(LIBCRYPTOAUTH_OBJECTS)) -+LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath cryptoauthlib/lib/hal)/%, $(SOURCES)) -+LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath cryptoauthlib/lib/pkcs11)/%, $(LIBCRYPTOAUTH_OBJECTS)) -+LIBCRYPTOAUTH_OBJECTS := $(filter-out $(abspath cryptoauthlib/lib/openssl)/%, $(LIBCRYPTOAUTH_OBJECTS)) - LIBCRYPTOAUTH_OBJECTS += atca_hal.c - - ifeq ($(TARGET_ARCH),Windows) -@@ -101,9 +104,9 @@ LIBCRYPTOAUTH_OBJECTS += hal_linux_kit_cdc.c kit_protocol.c - endif - endif - --TEST_SOURCES := $(call FIND,test,*.c) -+TEST_SOURCES := $(call FIND,cryptoauthlib/test,*.c) - #TEST_INCLUDE := $(sort $(dir $(call FIND, test, *.h))) --TEST_INCLUDE := $(abspath .) -+TEST_INCLUDE := $(abspath cryptoauthlib/.) - TEST_OBJECTS := $(addprefix $(OUTDIR)/,$(notdir $(TEST_SOURCES:.c=.o))) - - LIBCRYPTOAUTH_OBJECTS := $(addprefix $(OUTDIR)/,$(notdir $(LIBCRYPTOAUTH_OBJECTS:.c=.o))) -@@ -126,7 +129,7 @@ $(OUTDIR)/libcryptoauth.a: $(LIBCRYPTOAUTH_OBJECTS) | $(OUTDIR) - $(AR) $(ARFLAGS) $@ $(LIBCRYPTOAUTH_OBJECTS) - - $(OUTDIR)/libateccssl.so: $(LIBATECCSSL_OBJECTS) $(LIBCRYPTOAUTH_OBJECTS) | $(OUTDIR) -- $(LD) -dll -shared $(LIBATECCSSL_OBJECTS) $(LIBCRYPTOAUTH_OBJECTS) -o $@ -lcrypto -lrt -+ $(CC) -dll -shared $(LIBATECCSSL_OBJECTS) $(LIBCRYPTOAUTH_OBJECTS) -o $@ -lcrypto -lrt - - $(OUTDIR)/test: $(OUTDIR)/libateccssl.so $(TEST_OBJECTS) | $(OUTDIR) - $(CC) -o $@ $(TEST_OBJECTS) -L$(OUTDIR) -lateccssl -lcrypto -lssl -@@ -142,7 +145,10 @@ libcryptoauth: $(OUTDIR)/libcryptoauth.a | $(OUTDIR) - all: $(LIBCRYPTOAUTH_OBJECTS) $(LIBATECCSSL_OBJECTS) $(LIBPKCS11_OBJECTS) | $(OUTDIR) - - test: $(OUTDIR)/test | $(OUTDIR) -- env LD_LIBRARY_PATH=$(OUTDIR) $(OUTDIR)/test -+ -+install: libateccssl | $(OUTDIR) -+ install -d $(DESTDIR)/usr/lib/ssl/engines -+ install -m 0755 $(OUTDIR)/libateccssl.so $(DESTDIR)/usr/lib/ssl/engines - - clean: -- rm -r $(OUTDIR) -+ rm -rf $(OUTDIR) -diff --git a/cryptoauthlib/lib/atca_cfgs.c b/cryptoauthlib/lib/atca_cfgs.c -index a8f6b68..5775f91 100644 ---- a/cryptoauthlib/lib/atca_cfgs.c -+++ b/cryptoauthlib/lib/atca_cfgs.c -@@ -47,14 +47,24 @@ - - /* if the number of these configurations grows large, we can #ifdef them based on required device support */ - -+/* Default I2C configuration */ -+#ifndef ATCA_HAL_I2C_BUS -+#define ATCA_HAL_I2C_BUS 0 -+#warning "Using default value for ATCA_HAL_I2C_BUS: 0" -+#endif -+ -+#ifndef ATCA_HAL_I2C_SPEED -+#define ATCA_HAL_I2C_SPEED 400000 -+#warning "Using default value for ATCA_HAL_I2C_SPEED: 400000" -+#endif -+ - /** \brief default configuration for an ECCx08A device */ - ATCAIfaceCfg cfg_ateccx08a_i2c_default = { - .iface_type = ATCA_I2C_IFACE, - .devtype = ATECC508A, - .atcai2c.slave_address = 0xC0, -- .atcai2c.bus = 2, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -+ .atcai2c.bus = ATCA_HAL_I2C_BUS, -+ .atcai2c.baud = ATCA_HAL_I2C_SPEED, - .wake_delay = 1500, - .rx_retries = 20 - }; -diff --git a/cryptoauthlib/lib/openssl/eccx08_eckey_meth.c b/cryptoauthlib/lib/openssl/eccx08_eckey_meth.c -index a857a92..f79a98f 100644 ---- a/cryptoauthlib/lib/openssl/eccx08_eckey_meth.c -+++ b/cryptoauthlib/lib/openssl/eccx08_eckey_meth.c -@@ -818,7 +818,7 @@ int eccx08_pmeth_selector(ENGINE *e, EVP_PKEY_METHOD **pkey_meth, - #if ATCA_OPENSSL_OLD_API - /* These are from the OpenSSL 1.1.x API */ - --static void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth, -+static void ECCX08_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth, - int(**pinit) (EVP_PKEY_CTX *ctx)) - { - if (pmeth && pinit) -@@ -827,7 +827,7 @@ static void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth, - } - } - --static void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth, -+static void ECCX08_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth, - int(**pkeygen_init) (EVP_PKEY_CTX *ctx), - int(**pkeygen) (EVP_PKEY_CTX *ctx, - EVP_PKEY *pkey)) -@@ -845,7 +845,7 @@ static void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth, - } - } - --static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, -+static void ECCX08_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, - int(**psign_init) (EVP_PKEY_CTX *ctx), - int(**psign) (EVP_PKEY_CTX *ctx, - unsigned char *sig, size_t *siglen, -@@ -865,7 +865,7 @@ static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, - } - } - --static void EVP_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth, -+static void ECCX08_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth, - int(**pderive_init) (EVP_PKEY_CTX *ctx), - int(**pderive) (EVP_PKEY_CTX *ctx, - unsigned char *key, -@@ -951,10 +951,10 @@ int eccx08_pkey_meth_init(void) - EVP_PKEY_meth_copy(eccx08_pkey_meth, defaults); - - /* Retain default methods we'll be replacing */ -- EVP_PKEY_meth_get_init(defaults, &eccx08_pkey_def_f.init); -- EVP_PKEY_meth_get_keygen(defaults, &eccx08_pkey_def_f.keygen_init, &eccx08_pkey_def_f.keygen); -- EVP_PKEY_meth_get_sign(defaults, &eccx08_pkey_def_f.sign_init, &eccx08_pkey_def_f.sign); -- EVP_PKEY_meth_get_derive(defaults, &eccx08_pkey_def_f.derive_init, &eccx08_pkey_def_f.derive); -+ ECCX08_PKEY_meth_get_init(defaults, &eccx08_pkey_def_f.init); -+ ECCX08_PKEY_meth_get_keygen(defaults, &eccx08_pkey_def_f.keygen_init, &eccx08_pkey_def_f.keygen); -+ ECCX08_PKEY_meth_get_sign(defaults, &eccx08_pkey_def_f.sign_init, &eccx08_pkey_def_f.sign); -+ ECCX08_PKEY_meth_get_derive(defaults, &eccx08_pkey_def_f.derive_init, &eccx08_pkey_def_f.derive); - - /* Replace those we need to intercept */ - EVP_PKEY_meth_set_init(eccx08_pkey_meth, eccx08_pkey_ec_init); -diff --git a/cryptoauthlib/lib/openssl/eccx08_engine.h b/cryptoauthlib/lib/openssl/eccx08_engine.h -index 0df331f..90f9673 100644 ---- a/cryptoauthlib/lib/openssl/eccx08_engine.h -+++ b/cryptoauthlib/lib/openssl/eccx08_engine.h -@@ -52,6 +52,10 @@ - - /* Configuration options */ - -+#define ATCA_OPENSSL_ENGINE_STATIC_CONFIG (0) -+#define ATCA_OPENSSL_ENGINE_ENABLE_RAND (1) -+#define ATCA_OPENSSL_ENGINE_ENABLE_SHA256 (1) -+ - /** \brief Advertize RNG to OpenSSL*/ - #ifndef ATCA_OPENSSL_ENGINE_ENABLE_RAND - #define ATCA_OPENSSL_ENGINE_ENABLE_RAND (0) diff --git a/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine_git.bb b/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine_git.bb deleted file mode 100644 index 073184dc8..000000000 --- a/meta-digi-dey/recipes-digi/cryptoauth-openssl-engine/cryptoauth-openssl-engine_git.bb +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2018 Digi International Inc. - -SUMMARY = "Microchip CryptoAuthentication OpenSSL engine" -SECTION = "libs" -LICENSE = "MICROCHIP_ENGINE_LICENSE" -LIC_FILES_CHKSUM = "file://LICENSE;md5=3fdaa96f37898a0641820700bbf5f7b8" - -SRCBRANCH = "master" -SRCREV = "a69a4f92af6bee9cb13035c2f859912744796380" - -GIT_URI ?= "git://github.com/MicrochipTech/cryptoauth-openssl-engine.git;protocol=https" - -SRC_URI = " \ - ${GIT_URI};nobranch=1 \ - file://0001-Digi-modifications-to-the-cryptoauth-OpenSSL-engine.patch \ -" - -S = "${WORKDIR}/git" - -I2C_BUS ?= "0" -I2C_BUS_ccimx6qpsbc = "1" - -I2C_SPEED ?= "100000" - -CFLAGS += "-DATCA_HAL_I2C_BUS=${I2C_BUS} -DATCA_HAL_I2C_SPEED=${I2C_SPEED}" - -do_install() { - oe_runmake DESTDIR=${D} install -} - -DEPENDS += "openssl" - -TARGET_CC_ARCH += "${LDFLAGS}" -FILES_${PN} += "${libdir}/ssl/engines/libateccssl.so" - -PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" From 73352a83a24b03f54f1cf683c23898bcb9ef1746 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 7 Nov 2019 16:56:57 +0100 Subject: [PATCH 015/120] libp11: add recipe for v0.4.10 This is the version Microchip recommends to use in for the newer cryptoauthlib with pkcs11 support. This recipe was backported from the zeus branch of meta-openembedded. https://jira.digi.com/browse/DEL-6826 Signed-off-by: Gabriel Valcazar --- .../recipes-support/libp11/libp11_0.4.10.bb | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 meta-digi-dey/recipes-support/libp11/libp11_0.4.10.bb diff --git a/meta-digi-dey/recipes-support/libp11/libp11_0.4.10.bb b/meta-digi-dey/recipes-support/libp11/libp11_0.4.10.bb new file mode 100644 index 000000000..b40223e8a --- /dev/null +++ b/meta-digi-dey/recipes-support/libp11/libp11_0.4.10.bb @@ -0,0 +1,26 @@ +SUMMARY = "Library for using PKCS" +DESCRIPTION = "\ +Libp11 is a library implementing a small layer on top of PKCS \ +make using PKCS" +HOMEPAGE = "https://github.com/OpenSC/libp11" +BUGTRACKER = "https://github.com/OpenSC/libp11/issues" +SECTION = "Development/Libraries" +LICENSE = "LGPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=fad9b3332be894bab9bc501572864b29" +DEPENDS = "libtool openssl" + +SRC_URI = "git://github.com/OpenSC/libp11.git" +SRCREV = "973d31f3f58d5549ddd8b1f822ce8f72186f9d68" + +S = "${WORKDIR}/git" + +inherit autotools pkgconfig + +EXTRA_OECONF = "--disable-static" + +do_install_append () { + rm -rf ${D}${docdir}/${BPN} +} + +FILES_${PN} += "${libdir}/engines*/pkcs11.so" +FILES_${PN}-dev += "${libdir}/engines*/libpkcs11${SOLIBSDEV}" From 3fc4ae7218d6b9fa05eca86471e97a37b5a2424b Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 7 Nov 2019 16:52:06 +0100 Subject: [PATCH 016/120] cryptoauthlib: update to 30/7/2019 pkcs11 release This version is based on the 20190517 master release, with the addition of pkcs11 provisioning support. The source code now has cmake files, so we don't need as many code customizations as we used to. Revamp the recipe and its patches. https://jira.digi.com/browse/DEL-6826 https://jira.digi.com/browse/DEL-6835 Signed-off-by: Gabriel Valcazar --- ...m-the-cryptoauth-engine-repo-to-the-.patch | 404 - ...rs-to-be-able-to-modify-default-I2C-.patch | 63 + ...02-Remove-unused-HAL-implementations.patch | 13459 ---------------- ...y-version-number-to-CMake-VERSION-pr.patch | 30 + ...-cmd-processor-application-along-wit.patch | 50 - ...mplate-configuration-file-to-its-int.patch | 84 + ...ry-code-from-cryptochip-cmd-processo.patch | 454 - ...all-pkg-config-file-and-header-files.patch | 82 + .../cryptoauthlib/cryptoauthlib_git.bb | 28 +- 9 files changed, 272 insertions(+), 14382 deletions(-) delete mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-Port-changes-from-the-cryptoauth-engine-repo-to-the-.patch create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-lib-add-parameters-to-be-able-to-modify-default-I2C-.patch delete mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-Remove-unused-HAL-implementations.patch create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch delete mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-Build-cryptochip-cmd-processor-application-along-wit.patch create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-pkcs11-rename-template-configuration-file-to-its-int.patch delete mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-Remove-unnecessary-code-from-cryptochip-cmd-processo.patch create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-lib-install-pkg-config-file-and-header-files.patch diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-Port-changes-from-the-cryptoauth-engine-repo-to-the-.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-Port-changes-from-the-cryptoauth-engine-repo-to-the-.patch deleted file mode 100644 index 8c6261b34..000000000 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-Port-changes-from-the-cryptoauth-engine-repo-to-the-.patch +++ /dev/null @@ -1,404 +0,0 @@ -From: Gabriel Valcazar -Date: Wed, 14 Feb 2018 17:30:49 +0100 -Subject: [PATCH 1/2] Port changes from the cryptoauth engine repo to the - library repo - -Incorporate makefiles to be able to build cryptoauthlib as well as the changes -Digi has done in the atmel-cryptoauth-openssl-engine repo (except for -our modifications in the HAL section, which are not needed anymore). Update -package configuration version to 1.3, remove OpenSSL engine dependencies and -fix an infinite recursion that happened when cleaning the project. - -https://jira.digi.com/browse/DEL-5591 - -Signed-off-by: Gabriel Valcazar -Signed-off-by: Isaac Hermida ---- - Makefile | 32 +++++++++++++++++ - Makefile.generic | 22 ++++++++++++ - ecc-test-main.c | 71 +++++++++++++++++++++++++++++++++++++ - lib/Makefile | 46 ++++++++++++++++++++++++ - lib/atca_cfgs.c | 16 +++++++-- - lib/atcacert/Makefile | 1 + - lib/basic/Makefile | 1 + - lib/crypto/Makefile | 1 + - lib/crypto/hashes/Makefile | 1 + - lib/cryptoauthlib.pc | 11 ++++++ - lib/hal/Makefile | 1 + - lib/host/Makefile | 1 + - lib/jwt/Makefile | 1 + - lib/tls/Makefile | 1 + - test/Makefile | 15 ++++++++ - test/atcacert/Makefile | 1 + - test/jwt/Makefile | 1 + - test/sha-byte-test-vectors/Makefile | 1 + - test/tls/Makefile | 1 + - 19 files changed, 222 insertions(+), 3 deletions(-) - create mode 100644 Makefile - create mode 100644 Makefile.generic - create mode 100644 ecc-test-main.c - create mode 100644 lib/Makefile - create mode 100644 lib/atcacert/Makefile - create mode 100644 lib/basic/Makefile - create mode 100644 lib/crypto/Makefile - create mode 100644 lib/crypto/hashes/Makefile - create mode 100644 lib/cryptoauthlib.pc - create mode 100644 lib/hal/Makefile - create mode 100644 lib/host/Makefile - create mode 100644 lib/jwt/Makefile - create mode 100644 lib/tls/Makefile - create mode 100644 test/Makefile - create mode 100644 test/atcacert/Makefile - create mode 100644 test/jwt/Makefile - create mode 100644 test/sha-byte-test-vectors/Makefile - create mode 100644 test/tls/Makefile - -diff --git a/Makefile b/Makefile -new file mode 100644 -index 000000000000..a471428ad12c ---- /dev/null -+++ b/Makefile -@@ -0,0 +1,32 @@ -+CWD:= $(shell pwd) -+CFLAGS+= -I. -I../.. -fPIC -g -O0 -+SRC:= $(wildcard *.c) -+export CFLAGS -+ -+SUBDIRS= lib test -+ -+.PHONY: tgt_lib tgt_test clean -+ -+all: tgt_lib tgt_test ecc-test -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -o $@ -c $< -+ -+tgt_lib: -+ make -w -C lib -+ -+tgt_test: -+ make -w -C test -+ -+ecc-test: tgt_lib tgt_test -+ $(CC) -c ecc-test-main.c $(CFLAGS) $(LDFLAGS) -I ./lib/ -I ./test/ -+ $(CC) -o ecc-test-main ecc-test-main.o $(LDFLAGS) test/tls/atcatls_tests.o -L lib -L test -lm -lc -lrt -lcryptoauth -lunity -+ -+install: -+ for a in $(SUBDIRS); do $(MAKE) -C $$a $@; done -+ install -d $(DESTDIR)/usr/bin -+ install -m 0755 ecc-test-main $(DESTDIR)/usr/bin/ -+ -+clean: -+ rm -f *.o *.a ecc-test-main -+ $(foreach subdir,$(basename $(SUBDIRS)),$(MAKE) -w -C $(subdir) clean;) -diff --git a/Makefile.generic b/Makefile.generic -new file mode 100644 -index 000000000000..f6a0d67c708c ---- /dev/null -+++ b/Makefile.generic -@@ -0,0 +1,22 @@ -+CWD:= $(shell pwd) -+CFLAGS+= -I. -I.. -I../.. -I../../.. -I../../../.. -I../../lib -I../lib -fPIC -g -O0 -DATCA_HAL_I2C -DATCAPRINTF -+SRC:= $(wildcard *.c) -+export CFLAGS -+ -+DIRECTORIES= $(shell find . -maxdepth 1 ! -path . -type d) -+SUBDIRS= $(DIRECTORIES) -+ -+.PHONY: clean tgt_local -+ -+MODULES= $(patsubst %.c,%.o,$(SRC)) -+ -+all: $(MODULES) tgt_local -+ $(foreach subdir,$(basename $(SUBDIRS)),$(MAKE) -w -C $(subdir);) -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -o $@ -c $< -+ -+clean: -+ rm -f *.o *.a -+ $(foreach subdir,$(basename $(SUBDIRS)),$(MAKE) -w -C $(subdir) clean;) -+ -diff --git a/ecc-test-main.c b/ecc-test-main.c -new file mode 100644 -index 000000000000..032bc4bc2b5a ---- /dev/null -+++ b/ecc-test-main.c -@@ -0,0 +1,71 @@ -+/** \file ecc-test-main.c -+ * \brief Used to launch CryptoAuthLib tests for TLS -+ * -+ * Copyright (c) 2015 Atmel Corporation. All rights reserved. -+ * -+ * \atmel_crypto_device_library_license_start -+ * -+ * \page License -+ * -+ * 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 Atmel nor the names of its contributors may be used to endorse -+ * or promote products derived from this software without specific prior written permission. -+ * -+ * 4. This software may only be redistributed and used in connection with an -+ * Atmel integrated circuit. -+ * -+ * 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. -+*/ -+ -+//#include "ssl.h" -+#include -+#include -+#include -+#include -+#include -+ -+#define ATCA_HAL_I2C -+ -+// Get a pointer to the default configuration based on the compiler switch -+#ifdef ATCA_HAL_KIT_CDC -+ATCAIfaceCfg* pCfg = &cfg_ecc508_kitcdc_default; -+#elif defined(ATCA_HAL_KIT_HID) -+ATCAIfaceCfg* pCfg = &cfg_ecc508_kithid_default; -+#elif defined(ATCA_HAL_I2C) -+ATCAIfaceCfg* pCfg = &cfg_ateccx08a_i2c_default; -+#endif -+ -+ -+/** \brief Main function for running ATECC508 tests. -+ * Use this test program to ensure that the Engine can communicate to your ATECC508 -+ * -+ * \return For success return 0 -+ */ -+int main() -+{ -+ uint8_t runTests = true; -+ -+ if (runTests) -+ { -+ atcatls_test_runner(pCfg); -+ } -+ return 0; -+} -diff --git a/lib/Makefile b/lib/Makefile -new file mode 100644 -index 000000000000..e8c89380a43c ---- /dev/null -+++ b/lib/Makefile -@@ -0,0 +1,46 @@ -+CWD:=$(shell pwd) -+SRC:=$(wildcard *.c) -+ -+DIRECTORIES=$(shell find . -maxdepth 1 ! -path . -type d) -+SUBDIRS=$(DIRECTORIES) -+ -+.PHONY: clean -+ -+MODULES=$(patsubst %.c,%.o,$(SRC)) -+#O_FILES=$(shell find . -name \*.o) -+O_FILES=$(wildcard **/**/*.o) -+O_FILES+=$(wildcard **/*.o) -+LIBNAME=libcryptoauth -+ -+INCLUDE_PATH = "$(DESTDIR)/usr/include/cryptoauthlib" -+ -+all: $(MODULES) -+ - $(foreach subdir,$(basename $(SUBDIRS)),$(shell make -w -C $(subdir))) -+ @echo "OFILES: $(O_FILES)" -+ $(AR) -r $(LIBNAME).a $(MODULES) $(O_FILES) -+ $(RANLIB) $(LIBNAME).a -+ -+.PHONY: install -+install: $(LIBNAME).a -+ install -d $(DESTDIR)/usr/lib/pkgconfig -+ install -m 0644 $(LIBNAME).a $(DESTDIR)/usr/lib/ -+ install -m 0644 cryptoauthlib.pc $(DESTDIR)/usr/lib/pkgconfig/ -+ -+ install -d $(INCLUDE_PATH)/atcacert $(INCLUDE_PATH)/basic $(INCLUDE_PATH)/hal $(INCLUDE_PATH)/tls -+ install -m 0644 atcacert/*.h $(INCLUDE_PATH)/atcacert -+ install -m 0644 basic/*.h $(INCLUDE_PATH)/basic -+ install -m 0644 hal/*.h $(INCLUDE_PATH)/hal -+ install -m 0644 tls/*.h $(INCLUDE_PATH)/tls -+ install -m 0644 *.h $(INCLUDE_PATH) -+ -+ install -d $(INCLUDE_PATH)/crypto/hashes -+ install -m 0644 crypto/*.h $(INCLUDE_PATH)/crypto -+ install -m 0644 crypto/hashes/*.h $(INCLUDE_PATH)/crypto/hashes -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -o $@ -c $< -+ -+clean: -+ rm -f *.o *.a -+ $(foreach subdir,$(basename $(SUBDIRS)),$(MAKE) -w -C $(subdir) clean;) -+ -diff --git a/lib/atca_cfgs.c b/lib/atca_cfgs.c -index b8de8e8ede7f..4cbd305724d4 100644 ---- a/lib/atca_cfgs.c -+++ b/lib/atca_cfgs.c -@@ -40,14 +40,24 @@ - - /* if the number of these configurations grows large, we can #ifdef them based on required device support */ - -+/* Default I2C configuration */ -+#ifndef ATCA_HAL_I2C_BUS -+#define ATCA_HAL_I2C_BUS 0 -+#warning "Using default value for ATCA_HAL_I2C_BUS: 0" -+#endif -+ -+#ifndef ATCA_HAL_I2C_SPEED -+#define ATCA_HAL_I2C_SPEED 400000 -+#warning "Using default value for ATCA_HAL_I2C_SPEED: 400000" -+#endif -+ - /** \brief default configuration for an ECCx08A device */ - ATCAIfaceCfg cfg_ateccx08a_i2c_default = { - .iface_type = ATCA_I2C_IFACE, - .devtype = ATECC508A, - .atcai2c.slave_address = 0xC0, -- .atcai2c.bus = 2, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -+ .atcai2c.bus = ATCA_HAL_I2C_BUS, -+ .atcai2c.baud = ATCA_HAL_I2C_SPEED, - .wake_delay = 1500, - .rx_retries = 20 - }; -diff --git a/lib/atcacert/Makefile b/lib/atcacert/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/atcacert/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/basic/Makefile b/lib/basic/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/basic/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/crypto/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/crypto/hashes/Makefile b/lib/crypto/hashes/Makefile -new file mode 100644 -index 000000000000..0356cb8c0cd5 ---- /dev/null -+++ b/lib/crypto/hashes/Makefile -@@ -0,0 +1 @@ -+include ../../../Makefile.generic -diff --git a/lib/cryptoauthlib.pc b/lib/cryptoauthlib.pc -new file mode 100644 -index 000000000000..001a02c1c341 ---- /dev/null -+++ b/lib/cryptoauthlib.pc -@@ -0,0 +1,11 @@ -+prefix=/usr -+exec_prefix=${prefix} -+libdir=${exec_prefix}/lib -+includedir=${prefix}/include -+ -+Name: cryptoauthlib -+Description: Atmel Cryptochip library for ATECC508A -+Version:1.3 -+ -+Libs: -L${libdir} -lcryptoauth -+Cflags: -I${includedir} -I${includedir}/cryptoauthlib -I${includedir}/cryptoauthlib/tls -diff --git a/lib/hal/Makefile b/lib/hal/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/hal/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/host/Makefile b/lib/host/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/host/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/jwt/Makefile b/lib/jwt/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/jwt/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/lib/tls/Makefile b/lib/tls/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/lib/tls/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/test/Makefile b/test/Makefile -new file mode 100644 -index 000000000000..5de9ef42a46b ---- /dev/null -+++ b/test/Makefile -@@ -0,0 +1,15 @@ -+LIBNAME= libunity -+LIB= $(LIBNAME).a -+AR+= r -+ -+include ../Makefile.generic -+ -+tgt_local: -+ $(CC) -o unity.o -c unity.c -+ $(AR) $(LIB) unity.o -+ -+ecc-test: tgt_local -+ $(CC) -c ecc-test-main.c $(CFLAGS) -I. -I.. -+ $(CC) -o ecc-test-main ecc-test-main.o ../test/tls/atcatls_tests.o -Lcryptoauthlib/lib -lcryptoauth -Lcryptoauthlib/test -lunity -lm -lc -lrt -+ -+install: ; -diff --git a/test/atcacert/Makefile b/test/atcacert/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/test/atcacert/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/test/jwt/Makefile b/test/jwt/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/test/jwt/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic -diff --git a/test/sha-byte-test-vectors/Makefile b/test/sha-byte-test-vectors/Makefile -new file mode 100644 -index 000000000000..78d24559879f ---- /dev/null -+++ b/test/sha-byte-test-vectors/Makefile -@@ -0,0 +1 @@ -+empty_target: ; -diff --git a/test/tls/Makefile b/test/tls/Makefile -new file mode 100644 -index 000000000000..aa3e01644e15 ---- /dev/null -+++ b/test/tls/Makefile -@@ -0,0 +1 @@ -+include ../../Makefile.generic diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-lib-add-parameters-to-be-able-to-modify-default-I2C-.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-lib-add-parameters-to-be-able-to-modify-default-I2C-.patch new file mode 100644 index 000000000..da95dff95 --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0001-lib-add-parameters-to-be-able-to-modify-default-I2C-.patch @@ -0,0 +1,63 @@ +From: Gabriel Valcazar +Date: Thu, 31 Oct 2019 11:49:06 +0100 +Subject: [PATCH 1/6] lib: add parameters to be able to modify default I2C bus + index and speed + +https://jira.digi.com/browse/DEL-6826 + +Signed-off-by: Gabriel Valcazar +--- + lib/CMakeLists.txt | 8 ++++++++ + lib/atca_cfgs.c | 15 +++++++++++++-- + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt +index 9816ed1..b198d1f 100644 +--- a/lib/CMakeLists.txt ++++ b/lib/CMakeLists.txt +@@ -66,6 +66,14 @@ add_definitions(-DATCA_HAL_I2C) + set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${TWI_SRC}) + endif(LINUX AND ATCA_HAL_I2C) + ++if(ATCA_HAL_I2C_BUS) ++add_definitions(-DATCA_HAL_I2C_BUS=${ATCA_HAL_I2C_BUS}) ++endif(ATCA_HAL_I2C_BUS) ++ ++if(ATCA_HAL_I2C_SPEED) ++add_definitions(-DATCA_HAL_I2C_SPEED=${ATCA_HAL_I2C_SPEED}) ++endif(ATCA_HAL_I2C_SPEED) ++ + if(ATCA_HAL_CUSTOM) + add_definitions(-DATCA_HAL_CUSTOM) + endif() +diff --git a/lib/atca_cfgs.c b/lib/atca_cfgs.c +index a79e02b..60727f7 100644 +--- a/lib/atca_cfgs.c ++++ b/lib/atca_cfgs.c +@@ -37,13 +37,24 @@ + + /* if the number of these configurations grows large, we can #ifdef them based on required device support */ + ++/* Default I2C configuration */ ++#ifndef ATCA_HAL_I2C_BUS ++#define ATCA_HAL_I2C_BUS 0 ++#warning "Using default value for ATCA_HAL_I2C_BUS: 0" ++#endif ++ ++#ifndef ATCA_HAL_I2C_SPEED ++#define ATCA_HAL_I2C_SPEED 400000 ++#warning "Using default value for ATCA_HAL_I2C_SPEED: 400000" ++#endif ++ + /** \brief default configuration for an ECCx08A device */ + ATCAIfaceCfg cfg_ateccx08a_i2c_default = { + .iface_type = ATCA_I2C_IFACE, + .devtype = ATECC608A, + .atcai2c.slave_address = 0xC0, +- .atcai2c.bus = 1, +- .atcai2c.baud = 400000, ++ .atcai2c.bus = ATCA_HAL_I2C_BUS, ++ .atcai2c.baud = ATCA_HAL_I2C_SPEED, + //.atcai2c.baud = 100000, + .wake_delay = 1500, + .rx_retries = 20 diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-Remove-unused-HAL-implementations.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-Remove-unused-HAL-implementations.patch deleted file mode 100644 index b9a56fdda..000000000 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-Remove-unused-HAL-implementations.patch +++ /dev/null @@ -1,13459 +0,0 @@ -From: Gabriel Valcazar -Date: Mon, 19 Feb 2018 10:48:50 +0100 -Subject: [PATCH 2/2] Remove unused HAL implementations - -When building the library, all HAL implementations get compiled, leading to -failures due to missing Windows header files. The official README states that -only the necessary HAL implementations should be included in a project, so keep -the Linux userpace I2C HAL and remove everything else. - -https://jira.digi.com/browse/DEL-5591 - -Signed-off-by: Gabriel Valcazar ---- - lib/hal/hal_at90usb1287_i2c_asf.c | 520 ---------------------------- - lib/hal/hal_at90usb1287_i2c_asf.h | 64 ---- - lib/hal/hal_at90usb1287_timer_asf.c | 79 ----- - lib/hal/hal_i2c_bitbang.c | 518 ---------------------------- - lib/hal/hal_i2c_bitbang.h | 78 ----- - lib/hal/hal_linux_kit_cdc.c | 428 ----------------------- - lib/hal/hal_linux_kit_cdc.h | 67 ---- - lib/hal/hal_linux_kit_hid.c | 429 ----------------------- - lib/hal/hal_linux_kit_hid.h | 62 ---- - lib/hal/hal_pic32mx695f512h_i2c.c | 510 --------------------------- - lib/hal/hal_pic32mx695f512h_i2c.h | 74 ---- - lib/hal/hal_pic32mx695f512h_timer.c | 106 ------ - lib/hal/hal_sam4s_i2c_asf.c | 667 ------------------------------------ - lib/hal/hal_sam4s_i2c_asf.h | 67 ---- - lib/hal/hal_sam4s_timer_asf.c | 86 ----- - lib/hal/hal_samb11_i2c_asf.c | 485 -------------------------- - lib/hal/hal_samb11_i2c_asf.h | 60 ---- - lib/hal/hal_samb11_timer_asf.c | 78 ----- - lib/hal/hal_samd21_i2c_asf.c | 572 ------------------------------- - lib/hal/hal_samd21_i2c_asf.h | 63 ---- - lib/hal/hal_samd21_i2c_start.c | 545 ----------------------------- - lib/hal/hal_samd21_i2c_start.h | 64 ---- - lib/hal/hal_samd21_timer_asf.c | 79 ----- - lib/hal/hal_samd21_timer_start.c | 80 ----- - lib/hal/hal_samg55_i2c_asf.c | 661 ----------------------------------- - lib/hal/hal_samg55_i2c_asf.h | 67 ---- - lib/hal/hal_samg55_timer_asf.c | 86 ----- - lib/hal/hal_samv71_i2c_asf.c | 583 ------------------------------- - lib/hal/hal_samv71_i2c_asf.h | 63 ---- - lib/hal/hal_samv71_timer_asf.c | 79 ----- - lib/hal/hal_swi_bitbang.c | 347 ------------------- - lib/hal/hal_swi_bitbang.h | 76 ---- - lib/hal/hal_swi_uart.c | 527 ---------------------------- - lib/hal/hal_swi_uart.h | 62 ---- - lib/hal/hal_win_kit_cdc.c | 556 ------------------------------ - lib/hal/hal_win_kit_cdc.h | 58 ---- - lib/hal/hal_win_kit_hid.c | 469 ------------------------- - lib/hal/hal_win_kit_hid.h | 64 ---- - lib/hal/hal_win_timer.c | 86 ----- - lib/hal/hal_xmega_a3bu_i2c_asf.c | 520 ---------------------------- - lib/hal/hal_xmega_a3bu_i2c_asf.h | 64 ---- - lib/hal/hal_xmega_a3bu_timer_asf.c | 78 ----- - lib/hal/i2c_bitbang_samd21.c | 262 -------------- - lib/hal/i2c_bitbang_samd21.h | 195 ----------- - lib/hal/kit_phy.h | 62 ---- - lib/hal/kit_protocol.c | 430 ----------------------- - lib/hal/kit_protocol.h | 77 ----- - lib/hal/swi_bitbang_samd21.c | 272 --------------- - lib/hal/swi_bitbang_samd21.h | 148 -------- - lib/hal/swi_uart_at90usb1287_asf.c | 260 -------------- - lib/hal/swi_uart_at90usb1287_asf.h | 83 ----- - lib/hal/swi_uart_samd21_asf.c | 238 ------------- - lib/hal/swi_uart_samd21_asf.h | 84 ----- - lib/hal/swi_uart_samd21_start.c | 208 ----------- - lib/hal/swi_uart_samd21_start.h | 80 ----- - lib/hal/swi_uart_xmega_a3bu_asf.c | 258 -------------- - lib/hal/swi_uart_xmega_a3bu_asf.h | 83 ----- - 57 files changed, 12967 deletions(-) - delete mode 100644 lib/hal/hal_at90usb1287_i2c_asf.c - delete mode 100644 lib/hal/hal_at90usb1287_i2c_asf.h - delete mode 100644 lib/hal/hal_at90usb1287_timer_asf.c - delete mode 100644 lib/hal/hal_i2c_bitbang.c - delete mode 100644 lib/hal/hal_i2c_bitbang.h - delete mode 100644 lib/hal/hal_linux_kit_cdc.c - delete mode 100644 lib/hal/hal_linux_kit_cdc.h - delete mode 100644 lib/hal/hal_linux_kit_hid.c - delete mode 100644 lib/hal/hal_linux_kit_hid.h - delete mode 100644 lib/hal/hal_pic32mx695f512h_i2c.c - delete mode 100644 lib/hal/hal_pic32mx695f512h_i2c.h - delete mode 100644 lib/hal/hal_pic32mx695f512h_timer.c - delete mode 100644 lib/hal/hal_sam4s_i2c_asf.c - delete mode 100644 lib/hal/hal_sam4s_i2c_asf.h - delete mode 100644 lib/hal/hal_sam4s_timer_asf.c - delete mode 100644 lib/hal/hal_samb11_i2c_asf.c - delete mode 100644 lib/hal/hal_samb11_i2c_asf.h - delete mode 100644 lib/hal/hal_samb11_timer_asf.c - delete mode 100644 lib/hal/hal_samd21_i2c_asf.c - delete mode 100644 lib/hal/hal_samd21_i2c_asf.h - delete mode 100644 lib/hal/hal_samd21_i2c_start.c - delete mode 100644 lib/hal/hal_samd21_i2c_start.h - delete mode 100644 lib/hal/hal_samd21_timer_asf.c - delete mode 100644 lib/hal/hal_samd21_timer_start.c - delete mode 100644 lib/hal/hal_samg55_i2c_asf.c - delete mode 100644 lib/hal/hal_samg55_i2c_asf.h - delete mode 100644 lib/hal/hal_samg55_timer_asf.c - delete mode 100644 lib/hal/hal_samv71_i2c_asf.c - delete mode 100644 lib/hal/hal_samv71_i2c_asf.h - delete mode 100644 lib/hal/hal_samv71_timer_asf.c - delete mode 100644 lib/hal/hal_swi_bitbang.c - delete mode 100644 lib/hal/hal_swi_bitbang.h - delete mode 100644 lib/hal/hal_swi_uart.c - delete mode 100644 lib/hal/hal_swi_uart.h - delete mode 100644 lib/hal/hal_win_kit_cdc.c - delete mode 100644 lib/hal/hal_win_kit_cdc.h - delete mode 100644 lib/hal/hal_win_kit_hid.c - delete mode 100644 lib/hal/hal_win_kit_hid.h - delete mode 100644 lib/hal/hal_win_timer.c - delete mode 100644 lib/hal/hal_xmega_a3bu_i2c_asf.c - delete mode 100644 lib/hal/hal_xmega_a3bu_i2c_asf.h - delete mode 100644 lib/hal/hal_xmega_a3bu_timer_asf.c - delete mode 100644 lib/hal/i2c_bitbang_samd21.c - delete mode 100644 lib/hal/i2c_bitbang_samd21.h - delete mode 100644 lib/hal/kit_phy.h - delete mode 100644 lib/hal/kit_protocol.c - delete mode 100644 lib/hal/kit_protocol.h - delete mode 100644 lib/hal/swi_bitbang_samd21.c - delete mode 100644 lib/hal/swi_bitbang_samd21.h - delete mode 100644 lib/hal/swi_uart_at90usb1287_asf.c - delete mode 100644 lib/hal/swi_uart_at90usb1287_asf.h - delete mode 100644 lib/hal/swi_uart_samd21_asf.c - delete mode 100644 lib/hal/swi_uart_samd21_asf.h - delete mode 100644 lib/hal/swi_uart_samd21_start.c - delete mode 100644 lib/hal/swi_uart_samd21_start.h - delete mode 100644 lib/hal/swi_uart_xmega_a3bu_asf.c - delete mode 100644 lib/hal/swi_uart_xmega_a3bu_asf.h - -diff --git a/lib/hal/hal_at90usb1287_i2c_asf.c b/lib/hal/hal_at90usb1287_i2c_asf.c -deleted file mode 100644 -index 878d82e48470..000000000000 ---- a/lib/hal/hal_at90usb1287_i2c_asf.c -+++ /dev/null -@@ -1,520 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for AT90USB1287 I2C over ASF drivers. -- * -- * Prerequisite: Add I2C Master Polled/Interrupt support to application in Atmel Studio -- * this HAL implementation assumes you've included the ASF I2C libraries in your project, otherwise, -- * the HAL layer will not compile because the ASF I2C drivers are a dependency -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "hal_at90usb1287_i2c_asf.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --static twi_master_options_t config_i2c_master; -- -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the prior knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- -- // if every PORT was a likely candidate bus, then would need to initialize the entire array to all PORT n numbers. -- // As an optimization and making discovery safer, make assumptions about bus-num / PORT map based on AT90USB1287 -- // If you were using a raw XMEGA on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- // -- -- i2c_buses[0] = 0; /* AT90USB1287 has only one I2C Port */ -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- // build an info command -- packet.param1 = INFO_MODE_REVISION; -- packet.param2 = 0; -- -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x08; slaveAddress <= 0x77; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- deleteATCADevice(&device); -- -- return ATCA_SUCCESS; --} -- -- -- -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - pointer to interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- config_i2c_master.speed = cfg->atcai2c.baud; -- config_i2c_master.chip = 0x50; -- config_i2c_master.baud_reg = TWI_CLOCK_RATE(sysclk_get_cpu_hz(), cfg->atcai2c.baud); -- -- i2c_hal_data[bus]->i2c_master_instance = (int*)&TWBR; -- -- sysclk_enable_peripheral_clock((i2c_hal_data[bus]->i2c_master_instance)); -- twi_master_init((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_STATUS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C send over ASF -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address, // TWI slave bus address -- .buffer = txdata, // transfer data source buffer -- .length = txlength, // transfer data size (bytes) -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.length = txlength; -- -- if (twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for ASF I2C -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address, // TWI slave bus address -- .buffer = rxdata, // transfer data source buffer -- .length = *rxlength, // transfer data size (bytes) -- }; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief method to change the bus speed of I2C -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ -- --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- config_i2c_master.speed = speed; -- config_i2c_master.baud_reg = TWI_CLOCK_RATE(sysclk_get_cpu_hz(), speed); -- -- /*twi_reset();*/ -- -- twi_master_init((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !STATUS_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send the wake by writing to an address of 0x00 -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = 0x00, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 0 // transfer data size (bytes) -- }; -- -- -- // Send the 00 address as the wake pulse -- twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet); // part will NACK, so don't check for status -- -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- packet.chip = cfg->atcai2c.slave_address; -- packet.length = 4; -- packet.buffer = data; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 1 // transfer data size (bytes) -- }; -- -- data[0] = 0x02; // idle word address value -- if (twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; -- --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 1 // transfer data size (bytes) -- }; -- -- data[0] = 0x01; // sleep word address value -- if (twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- -- if (i2c_bus_ref_ct > 0) -- { -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- } -- else -- { -- return ATCA_EXECUTION_ERROR; -- } -- -- if (hal->ref_ct <= 0) -- { -- return ATCA_EXECUTION_ERROR; -- } -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- twi_reset(); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_at90usb1287_i2c_asf.h b/lib/hal/hal_at90usb1287_i2c_asf.h -deleted file mode 100644 -index 82ef65e314e7..000000000000 ---- a/lib/hal/hal_at90usb1287_i2c_asf.h -+++ /dev/null -@@ -1,64 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for AT90USB1287 I2C over ASF drivers. -- * -- * Prerequisite: add I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_AT90USB1287_I2C_ASF_H_ --#define HAL_AT90USB1287_I2C_ASF_H_ -- --#include --#include "twi_megarf.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- -- --#define MAX_I2C_BUSES 1 // AT90USB1287 has only 1 PORT that can be configured as I2C -- --/** \brief this is the hal_data for ATCA HAL created using ASF -- */ --typedef struct atcaI2Cmaster --{ -- /*twi_master_t*/ int* i2c_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ --#endif /* HAL_AT90USB1287_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_at90usb1287_timer_asf.c b/lib/hal/hal_at90usb1287_timer_asf.c -deleted file mode 100644 -index bd6260f5b11a..000000000000 ---- a/lib/hal/hal_at90usb1287_timer_asf.c -+++ /dev/null -@@ -1,79 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for AT90USB1287 timer/delay over ASF drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of microseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_i2c_bitbang.c b/lib/hal/hal_i2c_bitbang.c -deleted file mode 100644 -index d25cc9887e03..000000000000 ---- a/lib/hal/hal_i2c_bitbang.c -+++ /dev/null -@@ -1,518 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for I2C bit banging. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "atca_device.h" --#include "hal_i2c_bitbang.h" -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief These methods define the hardware abstraction layer for -- * communicating with a CryptoAuth device using I2C bit banging. -- @{ */ -- --/** -- * \brief Logical to physical bus mapping structure. -- */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; //!< map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; //!< total in-use count across buses -- -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the prior knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- -- i2c_discover_buses(i2c_buses, max_buses); -- -- return ATCA_SUCCESS; -- --} -- -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief This function creates a Start condition and sends the I2C -- * address. -- * -- * \param[in] RorW I2C_READ for reading, I2C_WRITE for writing. -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --static ATCA_STATUS hal_i2c_send_slave_address(ATCAIface iface, uint8_t RorW) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- uint8_t sla = cfg->atcai2c.slave_address | RorW; -- -- i2c_send_start(); -- -- status = i2c_send_byte(sla); -- if (status != ATCA_SUCCESS) -- { -- i2c_send_stop(); -- } -- -- return status; --} -- --/** -- * \brief hal_i2c_init manages requests to initialize a physical -- * interface. It manages use counts so when an interface has -- * released the physical layer, it will disable the interface for -- * some other use. You can have multiple ATCAIFace instances using -- * the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and -- * ATCAIFace is abstracted from the physical details. -- */ -- --/** -- * \brief Initialize an I2C interface using given config. -- * -- * \param[in] hal opaque pointer to HAL data -- * \param[in] cfg interface configuration -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- int bus = cfg->atcai2c.bus; //!< 0-based logical bus number -- -- if (i2c_bus_ref_ct == 0) //!< power up state, no i2c buses will have been used -- -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; //!< total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- //! if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t)); -- i2c_hal_data[bus]->ref_ct = 1; //!< buses are shared, this is the first instance -- -- //! assign GPIO pins -- i2c_hal_data[bus]->pin_sda = i2c_buses_default.pin_sda[bus]; -- i2c_hal_data[bus]->pin_scl = i2c_buses_default.pin_scl[bus]; -- -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- i2c_enable(); -- -- //! store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- //! otherwise, another interface already initialized the bus, so this interface will share it and any different -- //! cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- -- -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_STATUS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of Send byte(s) via I2C. -- * -- * \param[in] iface interface of the logical device to send data to -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- int bus = cfg->atcai2c.bus; -- -- txdata[0] = 0x03; //!< Word Address Value = Command -- txlength++; //!< count Word Address byte towards txlength -- -- //! Set I2C pins -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- -- do -- { -- //! Address the device and indicate that bytes are to be written -- status = hal_i2c_send_slave_address(iface, I2C_WRITE); -- if (status != ATCA_SUCCESS) -- { -- break; -- } -- -- //! Send the remaining bytes -- status = i2c_send_bytes(txlength, txdata); -- } -- while (0); -- -- //! Send STOP regardless of i2c_status -- i2c_send_stop(); -- -- return status; --} -- --/** -- * \brief HAL implementation of Receive byte(s) via I2C. -- * -- * \param[in] iface interface of the logical device to receive data -- * from -- * \param[in] rxdata pointer to where bytes will be received -- * \param[in] rxlength pointer to expected number of receive bytes to -- * request -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_RX_TIMEOUT; -- -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint8_t count; -- -- //! Set I2C pins -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- -- while (retries-- > 0 && status != ATCA_SUCCESS) -- { -- //! Address the device and indicate that bytes are to be read -- status = hal_i2c_send_slave_address(iface, I2C_READ); -- if (status == ATCA_SUCCESS) -- { -- //! Receive count byte -- i2c_receive_byte(rxdata); -- count = rxdata[0]; -- if ((count < ATCA_RSP_SIZE_MIN) || (count > *rxlength)) -- { -- i2c_send_stop(); -- status = ATCA_INVALID_SIZE; -- break; -- } -- -- //! Receive the remaining bytes -- i2c_receive_bytes(count - 1, &rxdata[1]); -- } -- } -- if (status == ATCA_TX_TIMEOUT) -- { -- status = ATCA_RX_NO_RESPONSE; -- } -- -- return status; --} -- -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_WAKE_FAILED; -- -- int bus = cfg->atcai2c.bus; -- uint8_t response[4] = { 0x00, 0x00, 0x00, 0x00 }; -- uint8_t expected_response[4] = { 0x04, 0x11, 0x33, 0x43 }; -- uint16_t response_size = sizeof(response); -- -- //! Set I2C pins -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- -- //! Generate Wake Token -- i2c_send_wake_token(); -- -- //! Wait tWHI + tWLO -- atca_delay_us(cfg->wake_delay); -- -- //! Receive Wake Response -- status = hal_i2c_receive(iface, response, &response_size); -- if (status == ATCA_SUCCESS) -- { -- //! Compare response with expected_response -- if (memcmp(response, expected_response, 4) != 0) -- { -- status = ATCA_WAKE_FAILED; -- } -- } -- -- return status; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- int bus = cfg->atcai2c.bus; -- -- //! Set I2C pins -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- -- //! Address the device and indicate that bytes are to be written -- status = hal_i2c_send_slave_address(iface, I2C_WRITE); -- if (status == ATCA_SUCCESS) -- { -- status = i2c_send_byte(0x02); //!< Word Address Value = Idle -- i2c_send_stop(); -- } -- -- return status; --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- int bus = cfg->atcai2c.bus; -- -- //! Set I2C pins -- i2c_set_pin(i2c_hal_data[bus]->pin_sda, i2c_hal_data[bus]->pin_scl); -- -- //! Address the device and indicate that bytes are to be written -- status = hal_i2c_send_slave_address(iface, I2C_WRITE); -- if (status == ATCA_SUCCESS) -- { -- status = i2c_send_byte(0x01); //!< Word Address Value = Sleep -- i2c_send_stop(); -- } -- -- return status; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- i2c_set_pin(i2c_hal_data[hal->bus_index]->pin_sda, i2c_hal_data[hal->bus_index]->pin_scl); -- i2c_disable(); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -\ No newline at end of file -diff --git a/lib/hal/hal_i2c_bitbang.h b/lib/hal/hal_i2c_bitbang.h -deleted file mode 100644 -index 02b33f83babf..000000000000 ---- a/lib/hal/hal_i2c_bitbang.h -+++ /dev/null -@@ -1,78 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for I2C bit banging. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_I2C_BITBANG_H_ --#define HAL_I2C_BITBANG_H_ -- -- -- -- -- --#if BOARD == AT88CK9000 --# include "i2c_bitbang_at88ck9000.h" --#endif -- --#if (SAMD21 == 1) --#include "i2c_bitbang_samd21.h" --#endif -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief These methods define the hardware abstraction layer for -- * communicating with a CryptoAuth device using I2C bit banging. -- @{ */ -- --/** -- * \brief This enumeration lists flags for I2C read or write addressing. -- */ --enum i2c_read_write_flag --{ -- I2C_WRITE = (uint8_t)0x00, //!< write command flag -- I2C_READ = (uint8_t)0x01 //!< read command flag --}; -- --/** -- * \brief This is the hal_data for ATCA HAL. -- */ --typedef struct atcaI2Cmaster --{ -- uint32_t pin_sda; -- uint32_t pin_scl; -- int ref_ct; -- //! for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --/** @} */ -- --#endif /* HAL_AT88CK900X_I2C_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_linux_kit_cdc.c b/lib/hal/hal_linux_kit_cdc.c -deleted file mode 100644 -index 232cefc93b97..000000000000 ---- a/lib/hal/hal_linux_kit_cdc.c -+++ /dev/null -@@ -1,428 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Linux using kit protocol over a USB CDC device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include "atca_hal.h" --#include "kit_phy.h" --#include "hal_linux_kit_cdc.h" --#include "kit_protocol.h" -- --#include --#include --#include --#include --#include --#include --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// File scope macros --#ifndef __cplusplus --#define max(a, b) (((a) > (b)) ? (a) : (b)) --#define min(a, b) (((a) < (b)) ? (a) : (b)) --#endif -- --// File scope globals --atcacdc_t _gCdc; -- -- -- --char *dev = "/dev/ttyACM0"; // default device, Atmel CryptoAuth %n --//char *dev = "/dev/ttyATCA0"; // default device, Atmel CryptoAuth %n --int speed = B115200; -- --/** \brief discover cdc buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge.This function is currently not implemented. -- * \param[in] cdc_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- -- */ -- --ATCA_STATUS hal_cdc_discover_buses(int cdc_buses[], int max_buses) --{ -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_cdc_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- return ATCA_UNIMPLEMENTED; --} -- -- -- --/** \brief HAL implementation of Kit USB CDC init -- * -- * this discovery assumes a udev rule is active which renames the ATCK101 CDC device as a ttyATCA%n -- * the udev rule is: -- * -- * SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2122", MODE:="0777", SYMLINK+="ttyATCA%n" -- * -- * \param[in] hal pointer to HAL specific data that is maintained by this HAL -- * \param[in] cfg pointer to HAL specific configuration data that is used to initialize this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_init(void* hal, ATCAIfaceCfg* cfg) --{ -- ATCAHAL_t *phal = NULL; -- struct termios serialTermios; -- uint32_t i = 0; -- uint32_t index = 0; -- int fd; -- -- // Check the input variables -- if ((hal == NULL) || (cfg == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Cast the hal to the ATCAHAL_t structure -- phal = (ATCAHAL_t*)hal; -- -- // Initialize the _gCdc structure -- memset(&_gCdc, 0, sizeof(_gCdc)); -- for (i = 0; i < CDC_DEVICES_MAX; i++) -- { -- _gCdc.kits[i].read_handle = INVALID_HANDLE_VALUE; -- _gCdc.kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- _gCdc.num_kits_found = 0; -- -- // Get the read & write handles -- // todo: perform an actual discovery here... -- if ( (fd = open(dev, O_RDWR | O_NOCTTY)) < 0) -- { -- printf("Failed to open %s ret:%02X\n", dev, fd); -- return ATCA_COMM_FAIL; -- } -- index++; -- // Save the results of this discovery of CDC -- if (index > 0) -- { -- _gCdc.num_kits_found = 1; -- phal->hal_data = &_gCdc; -- } -- -- tcgetattr(fd, &serialTermios); -- cfsetispeed(&serialTermios, speed); -- cfsetospeed(&serialTermios, speed); -- cfmakeraw(&serialTermios); -- -- serialTermios.c_cflag |= CS8 | CLOCAL | CREAD; -- serialTermios.c_iflag = 0; -- serialTermios.c_oflag = 0; -- serialTermios.c_lflag = 0; -- // serialTermios.c_cc[VMIN] = 1; -- // serialTermios.c_cc[VTIME] = 0; -- -- tcsetattr(fd, TCSANOW, &serialTermios); -- -- _gCdc.kits[0].read_handle = fd; -- _gCdc.kits[0].write_handle = fd; -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of Kit USB CDC post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_post_init(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- atcacdc_t* phaldat = atgetifacehaldat(iface); -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- //int cdcid = cfg->atcauart.port; -- int i = 0; -- -- // Init all kit USB devices -- for (i = 0; i < phaldat->num_kits_found; i++) -- { -- // Set the port -- cfg->atcauart.port = i; -- // Perform the kit protocol init -- status = kit_init(iface); -- if (status != ATCA_SUCCESS) -- { -- return status; -- } -- } -- -- return status; --} -- --/** \brief HAL implementation of kit protocol send .It is called by the top layer. -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_send(ATCAIface iface, const char* txdata, int txlength) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int cdcid = cfg->atcauart.port; -- atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface); -- size_t bytesWritten = 0; -- --#ifdef KIT_DEBUG -- printf("--> %s", txdata); --#endif -- // Verify the input parameters -- if ((txdata == NULL) || (pCdc == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Verify the write handle -- if (pCdc->kits[cdcid].write_handle == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Write the bytes to the specified com port -- bytesWritten = write(pCdc->kits[cdcid].write_handle, txdata, txlength); -- -- return status; --} -- --/** \brief HAL implementation of kit protocol receive data.It is called by the top layer. -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxsize) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int cdcid = cfg->atcauart.port; -- atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface); -- uint8_t buffer[CDC_BUFFER_MAX] = { 0 }; -- bool continue_read = true; -- int bytes_read = 0; -- uint16_t total_bytes = 0; -- char* location = NULL; -- int bytes_remain = 0; -- int bytes_to_cpy = 0; -- -- do -- { -- // Verify the input variables -- if ((rxdata == NULL) || (rxsize == NULL) || (pCdc == NULL)) -- { -- status = ATCA_BAD_PARAM; -- break; -- } -- // Verify the write handle -- if (pCdc->kits[cdcid].read_handle == INVALID_HANDLE_VALUE) -- { -- status = ATCA_COMM_FAIL; -- break; -- } -- // Read all of the bytes -- while (continue_read == true) -- { -- bytes_read = read(pCdc->kits[cdcid].read_handle, buffer, CDC_BUFFER_MAX); -- -- // Find the location of the '\n' character in read buffer -- // todo: generalize this read... it only applies if there is an ascii protocol with an of \n and if the exists -- location = strchr((char*)&buffer[0], '\n'); -- if (location == NULL) -- { -- // Copy all of the bytes -- bytes_to_cpy = bytes_read; -- } -- else -- { -- // Copy only the bytes remaining in the read buffer to the -- bytes_to_cpy = (uint8_t)(location - (char*)buffer) + 1; -- // The response has been received, stop receiving more data -- continue_read = false; -- } -- // Protect rxdata from overwriting, this will have the result of truncating the returned bytes -- // Remaining space in rxdata -- bytes_remain = (*rxsize - total_bytes); -- // Use the minimum between number of bytes read and remaining space -- bytes_to_cpy = min(bytes_remain, bytes_to_cpy); -- -- // Copy the received data -- memcpy(&rxdata[total_bytes], &buffer[0], bytes_to_cpy); -- total_bytes += bytes_to_cpy; -- } -- -- } -- while (0); -- -- *rxsize = total_bytes; --#ifdef KIT_DEBUG -- printf("<-- %s", rxdata); --#endif -- return status; --} -- --/** \brief Number of USB CDC devices found -- * \param[out] num_found -- * \return ATCA_STATUS -- */ --ATCA_STATUS hal_kit_phy_num_found(int8_t* num_found) --{ -- *num_found = _gCdc.num_kits_found; -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of kit protocol send over USB CDC -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_send(ATCAIface iface, uint8_t* txdata, int txlength) --{ -- // Call the hal_kit_send() function that will call hal_phy_send() implemented below -- return kit_send(iface, txdata, txlength); --} -- --/** \brief HAL implementation of kit protocol receive over USB CDC -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize) --{ -- // Call the hal_kit_receive() function that will call hal_phy_receive() implemented below -- return kit_receive(iface, rxdata, rxsize); --} -- --/** \brief Call the wake for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_wake(ATCAIface iface) --{ -- // Call the hal_kit_wake() function that will call hal_phy_send() and hal_phy_receive() -- return kit_wake(iface); --} -- --/** \brief Call the idle for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code.S -- */ --ATCA_STATUS hal_kit_cdc_idle(ATCAIface iface) --{ -- // Call the hal_kit_idle() function that will call hal_phy_send() and hal_phy_receive() -- return kit_idle(iface); --} -- --/** \brief Call the sleep for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_sleep(ATCAIface iface) --{ -- // Call the hal_kit_sleep() function that will call hal_phy_send() and hal_phy_receive() -- return kit_sleep(iface); --} -- --/** \brief Close the physical port for CDC over USB CDC -- * \param[in] hal_data The hardware abstraction data specific to this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_release(void* hal_data) --{ -- int i = 0; -- atcacdc_t* phaldat = (atcacdc_t*)hal_data; -- -- if ((hal_data == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Close all kit USB devices -- for (i = 0; i < phaldat->num_kits_found; i++) -- { -- if (phaldat->kits[i].read_handle != INVALID_HANDLE_VALUE) -- { -- close(phaldat->kits[i].read_handle); -- phaldat->kits[i].read_handle = INVALID_HANDLE_VALUE; -- } -- -- if (phaldat->kits[i].write_handle != INVALID_HANDLE_VALUE) -- { -- close(phaldat->kits[i].write_handle); -- phaldat->kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- } -- return ATCA_SUCCESS; --} -- --/** \brief discover cdc buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge.This function is currently not implemented. -- * \param[in] cdc_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- -- */ --ATCA_STATUS hal_kit_cdc_discover_buses(int cdc_buses[], int max_buses) --{ -- // TODO: Implement -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_kit_cdc_discover_devices(int busNum, ATCAIfaceCfg *cfg, int *found) --{ -- // TODO: Implement -- *found = 0; -- return ATCA_UNIMPLEMENTED; --} --/** @} */ -diff --git a/lib/hal/hal_linux_kit_cdc.h b/lib/hal/hal_linux_kit_cdc.h -deleted file mode 100644 -index c0dcf4ab9801..000000000000 ---- a/lib/hal/hal_linux_kit_cdc.h -+++ /dev/null -@@ -1,67 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Linux using kit protocol over a USB CDC device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_LINUX_KIT_CDC_H_ --#define HAL_LINUX_KIT_CDC_H_ -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// Kit USB defines --#define CDC_DEVICES_MAX 10 //! Maximum number of supported Kit USB devices --#define CDC_BUFFER_MAX 1024 //! Maximum number of bytes read per port read -- -- --// Each device that is found will have a read handle and a write handle --typedef int HANDLE; --#define INVALID_HANDLE_VALUE ((int)(-1)) --typedef struct cdc_device --{ -- HANDLE read_handle; //! The kit USB read file handle -- HANDLE write_handle; //! The kit USB write file handle --} cdc_device_t; -- -- --// A structure to hold CDC information --typedef struct atcacdc --{ -- cdc_device_t kits[CDC_DEVICES_MAX]; -- int8_t num_kits_found; --} atcacdc_t; -- --/** @} */ -- --#endif /* HAL_LINUX_KIT_CDC_H_ */ -- -diff --git a/lib/hal/hal_linux_kit_hid.c b/lib/hal/hal_linux_kit_hid.c -deleted file mode 100644 -index 960d18c7ddea..000000000000 ---- a/lib/hal/hal_linux_kit_hid.c -+++ /dev/null -@@ -1,429 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Linux using kit protocol over a USB HID device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include -- --#include "atca_hal.h" --#include "hal_linux_kit_hid.h" --#include "hal/kit_protocol.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// File scope globals --atcahid_t _gHid; -- --/** \brief discover hid buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge.This function is currently not implemented. -- * \param[in] cdc_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_kit_hid_discover_buses(int hid_buses[], int max_buses) --{ -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number.This function is currently not implemented. -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_kit_hid_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief HAL implementation of Kit USB HID init -- * \param[in] hal pointer to HAL specific data that is maintained by this HAL -- * \param[in] cfg pointer to HAL specific configuration data that is used to initialize this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_init(void* hal, ATCAIfaceCfg* cfg) --{ -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- int status = 0; -- struct udev *udev = NULL; -- struct udev_enumerate *enumerate = NULL; -- struct udev_list_entry *list = NULL; -- struct udev_list_entry *list_entry = NULL; -- struct udev_device *syspath_device = NULL; -- struct udev_device *device = NULL; -- int i = 0; -- char hid_filter[20]; -- char device_hid[20]; -- FILE *file_descriptor = NULL; -- int index = 0; -- -- // Check the input variables -- if ((cfg == NULL) || (phal == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Initialize the _gHid structure -- memset(&_gHid, 0, sizeof(_gHid)); -- for (i = 0; i < HID_DEVICES_MAX; i++) -- { -- _gHid.kits[i].read_handle = NULL; -- _gHid.kits[i].write_handle = NULL; -- } -- -- _gHid.num_kits_found = 0; -- -- // Create the udev object -- udev = udev_new(); -- if (udev == NULL) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Create the enumerate object -- enumerate = udev_enumerate_new(udev); -- if (enumerate == NULL) -- { -- // Free the udev object -- udev_unref(udev); -- -- return ATCA_COMM_FAIL; -- } -- -- // Create the list of available USB devices -- status = udev_enumerate_add_match_subsystem(enumerate, "hidraw"); -- if (status >= 0) -- { -- status = udev_enumerate_scan_devices(enumerate); -- if (status >= 0) -- { -- list = udev_enumerate_get_list_entry(enumerate); -- } -- } -- -- // Create the HID filter string -- memset(hid_filter, 0, sizeof(hid_filter)); -- sprintf(hid_filter, "vid_%04x&pid_%04x", cfg->atcahid.vid, cfg->atcahid.pid); -- -- // Find the available kit USB devices -- udev_list_entry_foreach(list_entry, list) -- { -- // Get the udev device -- syspath_device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); -- device = udev_device_get_parent_with_subsystem_devtype(syspath_device, "usb", "usb_device"); -- -- // Create the device HID string -- memset(device_hid, 0, sizeof(device_hid)); -- sprintf(device_hid, "vid_%s&pid_%s", -- udev_device_get_sysattr_value(device, "idVendor"), -- udev_device_get_sysattr_value(device, "idProduct")); -- -- // Determine if this is the correct kit USB device -- if (strcasecmp(device_hid, hid_filter) == 0) -- { -- // Open the kit USB device for reading and writing -- if (_gHid.kits[index].read_handle != NULL) -- { -- fclose(_gHid.kits[index].read_handle); -- } -- if (_gHid.kits[index].write_handle != NULL) -- { -- fclose(_gHid.kits[index].write_handle); -- } -- -- file_descriptor = fopen(udev_device_get_devnode(syspath_device), "rb+"); -- if (file_descriptor != NULL) -- { -- _gHid.kits[index].read_handle = file_descriptor; -- _gHid.kits[index].write_handle = file_descriptor; -- -- // Increment the opened kit USB device index -- index++; -- --#ifdef KIT_DEBUG -- printf("Kit USB Device Node: %s\n", udev_device_get_devnode(syspath_device)); -- printf(" Manufacturer %s (%s)\n", -- udev_device_get_sysattr_value(device, "manufacturer"), -- udev_device_get_sysattr_value(device, "product")); -- printf(" VID/PID: %s %s\n", -- udev_device_get_sysattr_value(device, "idVendor"), -- udev_device_get_sysattr_value(device, "idProduct")); --#endif // KIT_DEBUG -- } -- else -- { --#ifdef KIT_DEBUG -- printf("fopen(\"%s\") failed with errno=%d\n", -- udev_device_get_devnode(syspath_device), -- errno); --#endif // KIT_DEBUG -- } -- } -- -- // Free the udev device object -- udev_device_unref(syspath_device); -- } -- -- // Save the results of this discovery of HID -- if (index > 0) -- { -- _gHid.num_kits_found = index; -- phal->hal_data = &_gHid; -- } -- -- // Free the enumerator object -- udev_enumerate_unref(enumerate); -- -- // Free the udev object -- udev_unref(udev); -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of Kit HID post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_post_init(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- atcahid_t* pHid = atgetifacehaldat(iface); -- ATCAIfaceCfg *pCfg = atgetifacecfg(iface); -- int i = 0; -- -- if ((pHid == NULL) || (pCfg == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Perform the kit protocol init -- for (i = 0; i < pHid->num_kits_found; i++) -- { -- status = kit_init(iface); -- if (status != ATCA_SUCCESS) -- { -- BREAK(status, "kit_init() Failed"); -- } -- } -- -- return status; --} -- --/** \brief HAL implementation of send over Kit protocol.This function is called by the top layer. -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_send(ATCAIface iface, uint8_t* txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- atcahid_t* pHid = (atcahid_t*)atgetifacehaldat(iface); -- size_t bytes_written = 0; -- -- if ((txdata == NULL) || (cfg == NULL) || (pHid == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pHid->kits[cfg->atcahid.idx].write_handle == NULL) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Send the data to the kit USB device -- if (txlength > 0) -- { -- bytes_written = fwrite(txdata, sizeof(uint8_t), txlength, -- pHid->kits[cfg->atcahid.idx].write_handle); -- if (bytes_written != txlength) -- { -- clearerr(pHid->kits[cfg->atcahid.idx].write_handle); -- return ATCA_TX_FAIL; -- } -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of kit protocol receive.This function is called by the top layer. -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_receive(ATCAIface iface, uint8_t* rxdata, int* rxsize) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- atcahid_t* pHid = (atcahid_t*)atgetifacehaldat(iface); -- bool continue_read = true; -- size_t bytes_read = 0; -- size_t total_bytes_read = 0; -- -- if ((rxdata == NULL) || (rxsize == NULL) || (cfg == NULL) || (pHid == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pHid->kits[cfg->atcahid.idx].read_handle == NULL) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Receive the data from the kit USB device -- do -- { -- bytes_read = fread(&rxdata[total_bytes_read], sizeof(uint8_t), 1, -- pHid->kits[cfg->atcahid.idx].read_handle); -- if (ferror(pHid->kits[cfg->atcahid.idx].read_handle) != 0) -- { -- clearerr(pHid->kits[cfg->atcahid.idx].read_handle); -- return ATCA_RX_FAIL; -- } -- -- total_bytes_read += bytes_read; -- -- // Check if the kit protocol message has been received -- if (strstr((char*)rxdata, "\n") != NULL) -- { -- continue_read = false; -- } -- } -- while (continue_read == true); -- -- // Save the total bytes read -- *rxsize = total_bytes_read; -- -- return ATCA_SUCCESS; --} -- --/** \brief Number of USB HID devices found -- * \param[out] num_found -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_num_found(int8_t* num_found) --{ -- *num_found = _gHid.num_kits_found; -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of kit protocol send over USB HID -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_send(ATCAIface iface, uint8_t* txdata, int txlength) --{ -- // Call the kit_send() function that will call phy_send() implemented below -- return kit_send(iface, txdata, txlength); --} -- --/** \brief HAL implementation of send over USB HID -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize) --{ -- // Call the kit_receive() function that will call phy_receive() implemented below -- return kit_receive(iface, rxdata, rxsize); --} -- --/** \brief Call the wake for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_wake(ATCAIface iface) --{ -- // Call the kit_wake() function that will call phy_send() and phy_receive() -- return kit_wake(iface); --} -- --/** \brief Call the idle for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_idle(ATCAIface iface) --{ -- // Call the kit_idle() function that will call phy_send() and phy_receive() -- return kit_idle(iface); --} -- --/** \brief Call the sleep for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_sleep(ATCAIface iface) --{ -- // Call the kit_sleep() function that will call phy_send() and phy_receive() -- return kit_sleep(iface); --} -- --/** \brief Close the physical port for HID -- * \param[in] hal_data The hardware abstraction data specific to this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_release(void* hal_data) --{ -- atcahid_t* phaldat = (atcahid_t*)hal_data; -- int i = 0; -- -- if (phaldat == NULL) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Close all kit USB devices -- for (i = 0; i < phaldat->num_kits_found; i++) -- { -- if (_gHid.kits[i].read_handle != NULL) -- { -- fclose(_gHid.kits[i].read_handle); -- _gHid.kits[i].read_handle = NULL; -- _gHid.kits[i].write_handle = NULL; -- } -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_linux_kit_hid.h b/lib/hal/hal_linux_kit_hid.h -deleted file mode 100644 -index 649aab556668..000000000000 ---- a/lib/hal/hal_linux_kit_hid.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Linux using kit protocol over a USB HID device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_LINUX_KIT_HID_H_ --#define HAL_LINUX_KIT_HID_H_ -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// Kit USB defines --#define HID_DEVICES_MAX 10 //! Maximum number of supported Kit USB devices --#define HID_PACKET_MAX 512 //! Maximum number of bytes for a HID send/receive packet (typically 64) -- --// Each device that is found will have a read handle and a write handle --typedef struct hid_device --{ -- FILE *read_handle; //! The kit USB read file handle -- FILE *write_handle; //! The kit USB write file handle --} hid_device_t; -- -- --// A structure to hold HID information --typedef struct atcahid --{ -- hid_device_t kits[HID_DEVICES_MAX]; -- int8_t num_kits_found; --} atcahid_t; -- --/** @} */ --#endif /* HAL_LINUX_KIT_HID_H_ */ -diff --git a/lib/hal/hal_pic32mx695f512h_i2c.c b/lib/hal/hal_pic32mx695f512h_i2c.c -deleted file mode 100644 -index 730d782d7e51..000000000000 ---- a/lib/hal/hal_pic32mx695f512h_i2c.c -+++ /dev/null -@@ -1,510 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for PIC32MX695F512H I2C over plib drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the xxx I2C primitives to set up the interface. -- * -- * Prerequisite: -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include -- --#include "hal/atca_hal.h" --#include "hal/hal_pic32mx695f512h_i2c.h" -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** -- * \brief -- * Logical to physical bus mapping structure -- */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --//twi_options_t opt_twi_master; -- -- --/****** I2C Driver implementation *******/ --static bool StartTransfer(I2C_MODULE i2c_id, bool restart) --{ -- I2C_STATUS status; -- -- // Send the Start (or Restart) signal -- if (restart) -- { -- I2CRepeatStart(i2c_id); -- } -- else -- { -- // Wait for the bus to be idle, then start the transfer -- while (!I2CBusIsIdle(i2c_id)) -- { -- ; -- } -- -- if (I2CStart(i2c_id) != I2C_SUCCESS) -- { -- //DBPRINTF("Error: Bus collision during transfer Start\n"); -- return FALSE; -- } -- } -- -- // Wait for the signal to complete -- do -- { -- status = I2CGetStatus(i2c_id); -- } -- -- while (!(status & I2C_START)); -- -- return TRUE; --} -- --static bool TransmitOneByte(I2C_MODULE i2c_id, uint8_t data) --{ -- // Wait for the transmitter to be ready -- while (!I2CTransmitterIsReady(i2c_id)) -- { -- ; -- } -- -- // Transmit the byte -- if (I2CSendByte(i2c_id, data) == I2C_MASTER_BUS_COLLISION) -- { -- //DBPRINTF("Error: I2C Master Bus Collision\n"); -- return FALSE; -- } -- -- // Wait for the transmission to finish -- while (!I2CTransmissionHasCompleted(i2c_id)) -- { -- ; -- } -- -- return TRUE; --} -- --static uint8_t ReceiveOneByte(I2C_MODULE i2c_id, bool ack) --{ -- uint8_t data; -- -- // Enable I2C receive -- I2CReceiverEnable(i2c_id, TRUE); -- -- // Wait until 1-byte is fully received -- while (!I2CReceivedDataIsAvailable(i2c_id)) -- { -- ; -- } -- -- // Save the byte received -- data = I2CGetByte(i2c_id); -- -- // Perform acknowledgement sequence -- I2CAcknowledgeByte(i2c_id, ack); -- -- // Wait until acknowledgement is successfully sent -- while (!I2CAcknowledgeHasCompleted(i2c_id)) -- { -- ; -- } -- -- return data; --} -- --static void StopTransfer(I2C_MODULE i2c_id) --{ -- I2C_STATUS status; -- -- // Send the Stop signal -- I2CStop(i2c_id); -- -- // Wait for the signal to complete -- do -- { -- status = I2CGetStatus(i2c_id); -- } -- -- while (!(status & I2C_STOP)); --} -- --void i2c_write(I2C_MODULE i2c_id, uint8_t address, uint8_t *data, int len) --{ -- uint8_t i2cBuffer[len + 1]; -- int i; -- -- i2cBuffer[0] = address | 0x00; -- memcpy(&i2cBuffer[1], data, len); -- -- if (!StartTransfer(i2c_id, FALSE)) -- { -- return; -- } -- for (i = 0; i < len + 1; i++) -- { -- if (!TransmitOneByte(i2c_id, i2cBuffer[i])) -- { -- break; -- } -- } -- -- StopTransfer(i2c_id); --} -- --void i2c_read(I2C_MODULE i2c_id, uint8_t address, uint8_t *data, uint16_t len) --{ -- uint16_t i; -- -- if (!StartTransfer(i2c_id, FALSE)) -- { -- return; -- } -- -- if (!TransmitOneByte(i2c_id, (address | 0x01))) -- { -- return; -- } -- -- for (i = 0; i < len; i++) -- { -- if (i < len - 1) // send ACK -- { -- data[i] = ReceiveOneByte(i2c_id, TRUE); -- } -- else // send NACK -- { -- data[i] = ReceiveOneByte(i2c_id, FALSE); -- } -- } -- -- StopTransfer(i2c_id); --} --/****************************************/ -- -- --/** -- * \brief -- * This HAL implementation assumes you've included the Plib libraries in your project, otherwise, -- * the HAL layer will not compile because the Plib drivers are a dependency -- */ -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge.This function is currently not implemented. -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number.This function is currently not implemented. -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- return ATCA_UNIMPLEMENTED; --} -- --/** -- * \brief -- * hal_i2c_init manages requests to initialize a physical interface. It manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** -- * \brief initialize an I2C interface using given config -- * -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- int i; -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- -- { -- for (i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- //// if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t)); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- switch (bus) -- { --// case 0: --// i2c_hal_data[bus]->id = I2C0; --// break; -- case 1: -- i2c_hal_data[bus]->id = I2C1; -- break; --// case 2: --// i2c_hal_data[bus]->id = I2C2; --// break; -- case 3: -- i2c_hal_data[bus]->id = I2C3; -- break; -- } -- -- // Set the I2C baudrate -- I2CSetFrequency(i2c_hal_data[bus]->id, GetPeripheralClock(), cfg->atcai2c.baud); -- -- // Enable the I2C bus -- I2CEnable(i2c_hal_data[bus]->id, TRUE); -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief HAL implementation of I2C post init -- * -- * \param[in] iface instance -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C send over ASF -- * -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- -- i2c_write(i2c_hal_data[bus]->id, cfg->atcai2c.slave_address, txdata, txlength); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C receive function for ASF I2C -- * -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- i2c_read(i2c_hal_data[bus]->id, cfg->atcai2c.slave_address, rxdata, *rxlength); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief method to change the bus speed of I2C -- * -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- // Disable the I2C bus -- I2CEnable(i2c_hal_data[bus]->id, FALSE); -- -- // Set the I2C baudrate -- I2CSetFrequency(i2c_hal_data[bus]->id, GetPeripheralClock(), speed); -- -- // Enable the I2C bus -- I2CEnable(i2c_hal_data[bus]->id, TRUE); --} -- --/** -- * \brief wake up CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to wakeup -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint32_t bdrt = cfg->atcai2c.baud; -- -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send 0x00 as wake pulse -- i2c_write(i2c_hal_data[bus]->id, 0x00, NULL, NULL); -- -- atca_delay_ms(3); // wait tWHI + tWLO which is configured based on device type and configuration structure -- //atca_delay_us(cfg->wake_delay); -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, cfg->atcai2c.baud); -- } -- -- i2c_read(i2c_hal_data[bus]->id, cfg->atcai2c.slave_address, data, 4); -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief idle CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to idle -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x02; // idle word address value -- -- i2c_write(i2c_hal_data[bus]->id, cfg->atcai2c.slave_address, data, 1); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief sleep CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to sleep -- * -- * \return ATCA_SUCESS -- */ --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x01; // idle word address value -- -- i2c_write(i2c_hal_data[bus]->id, cfg->atcai2c.slave_address, data, 1); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief manages reference count on given bus and releases resource if no more refences exist -- * -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * -- * \return ATCA_SUCESS -- */ --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- I2CEnable(hal->id, FALSE); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -\ No newline at end of file -diff --git a/lib/hal/hal_pic32mx695f512h_i2c.h b/lib/hal/hal_pic32mx695f512h_i2c.h -deleted file mode 100644 -index 1b242168b43d..000000000000 ---- a/lib/hal/hal_pic32mx695f512h_i2c.h -+++ /dev/null -@@ -1,74 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for PIC32MX695F512H I2C over xxx drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the xxx I2C primitives to set up the interface. -- * -- * Prerequisite: -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_PIC32MX695F512H_I2C_ASF_H_ --#define HAL_PIC32MX695F512H_I2C_ASF_H_ -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// Clock Constants --#define GetSystemClock() (80000000ul) --#define GetPeripheralClock() (GetSystemClock() / (1 << OSCCONbits.PBDIV)) --#define GetInstructionClock() (GetSystemClock()) -- --#define MAX_I2C_BUSES 4 // PIC32MX695F512H has 4 TWI -- --/** -- * \brief this is the hal_data for ATCA HAL -- */ --typedef struct atcaI2Cmaster --{ -- I2C_MODULE id; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void i2c_write(I2C_MODULE i2c_id, uint8_t address, uint8_t *data, int len); --void i2c_read(I2C_MODULE i2c_id, uint8_t address, uint8_t *data, uint16_t len); -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ -- --#endif /* HAL_PIC32MX695F512H_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_pic32mx695f512h_timer.c b/lib/hal/hal_pic32mx695f512h_timer.c -deleted file mode 100644 -index b4963d2d31a8..000000000000 ---- a/lib/hal/hal_pic32mx695f512h_timer.c -+++ /dev/null -@@ -1,106 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for PIC32MX695F512H timer/delay routine -- * -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include -- --#include "hal/atca_hal.h" -- -- --/* ASF already have delay_us and delay_ms - see delay.h */ -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- -- --#define CPU_CLOCK (80000000UL) --#define us_SCALE ((CPU_CLOCK / 2) / 1000000) -- -- --void delay_us(UINT32 delay) --{ -- UINT32 startCnt = ReadCoreTimer(); -- UINT32 waitCnt = delay * us_SCALE; -- -- while ((ReadCoreTimer() - startCnt) < waitCnt) -- { -- ; -- } -- --} -- -- -- -- --/****************************************/ -- --/** -- * \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- delay_us(delay); --} -- --/** -- * \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- atca_delay_us(delay * 10); --} -- --/** -- * \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * -- * \param[in] delay number of milliseconds to delay -- */ --void atca_delay_ms(uint32_t delay) --{ -- -- atca_delay_us(delay * 1000); -- --} -- --/** @} */ -\ No newline at end of file -diff --git a/lib/hal/hal_sam4s_i2c_asf.c b/lib/hal/hal_sam4s_i2c_asf.c -deleted file mode 100644 -index 619de4d1b6a4..000000000000 ---- a/lib/hal/hal_sam4s_i2c_asf.c -+++ /dev/null -@@ -1,667 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAM4S I2C over ASF drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the ASF I2C primitives to set up the interface. -- * -- * Prerequisite: add "TWI - Two-Wire Interface (Common API) (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "hal_sam4s_i2c_asf.h" --#include "atca_device.h" -- -- -- --//!< Uncomment when debugging --/*#define DEBUG_HAL*/ -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** -- * \brief -- * Logical to physical bus mapping structure -- */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --twi_master_options_t opt_twi_master; -- -- --#ifdef DEBUG_HAL --static void print_array(uint8_t *data, uint32_t data_size) --{ -- uint32_t n; -- -- for (n = 0; n < data_size; n++) -- { -- printf("%.2x ", data[n]); -- if (((n + 1) % 16) == 0) -- { -- printf("\r\n"); -- if ((n + 1) != data_size) -- { -- printf(" "); -- } -- } -- } -- if (data_size % 16 != 0) -- { -- printf("\r\n"); -- } --} --#endif -- --/** -- * \brief -- * This HAL implementation assumes you've included the ASF TWI libraries in your project, otherwise, -- * the HAL layer will not compile because the ASF TWI drivers are a dependency -- */ -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- /* logical bus numbers 0-2 map to the SAM4S i2c buses: -- ID_TWI0 -- ID_TWI1 -- -- TWS0 bus will respond on the SAM4S Xplained Pro board -- -- */ -- int i; -- -- i2c_buses[0] = 0; --#if MAX_I2C_BUSES == 2 -- i2c_buses[1] = -1; --#endif -- return ATCA_SUCCESS; -- --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- if (busNum < 0) -- { -- return ATCA_COMM_FAIL; -- } -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- //hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief -- * hal_i2c_init manages requests to initialize a physical interface. It manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** -- * \brief initialize an I2C interface using given config -- * -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t)); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- switch (bus) -- { -- case 0: -- i2c_hal_data[bus]->twi_id = ID_TWI0; -- i2c_hal_data[bus]->twi_master_instance = TWI0; -- break; -- case 1: -- i2c_hal_data[bus]->twi_id = ID_TWI1; -- i2c_hal_data[bus]->twi_master_instance = TWI1; -- // configure TWI1 pins -- gpio_configure_pin(PIO_PB4_IDX, (PIO_PERIPH_A | PIO_PULLUP)); -- gpio_configure_pin(PIO_PB5_IDX, (PIO_PERIPH_A | PIO_PULLUP)); -- // disable JTAG -- MATRIX->CCFG_SYSIO |= (1 << 4) | (1 << 5); -- break; -- } -- -- pmc_enable_periph_clk(i2c_hal_data[bus]->twi_id); -- -- opt_twi_master.master_clk = sysclk_get_cpu_hz(); -- opt_twi_master.speed = cfg->atcai2c.baud; -- opt_twi_master.smbus = 0; -- -- twi_master_init(i2c_hal_data[bus]->twi_master_instance, &opt_twi_master); -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief HAL implementation of I2C post init -- * -- * \param[in] iface instance -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C send over ASF -- * -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ --#ifdef DEBUG_HAL -- printf("hal_i2c_send()\r\n"); -- -- printf("\r\nCommand Packet (size:0x%.8x)\r\n", (uint32_t)txlength); -- printf("Count : %.2x\r\n", txdata[1]); -- printf("Opcode : %.2x\r\n", txdata[2]); -- printf("Param1 : %.2x\r\n", txdata[3]); -- printf("Param2 : "); print_array(&txdata[4], 2); -- if (txdata[1] > 7) -- { -- printf("Data : "); print_array(&txdata[6], txdata[1] - 7); -- } -- printf("CRC : "); print_array(&txdata[txdata[1] - 1], 2); -- printf("\r\n"); --#endif -- -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- -- twi_package_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = (void*)txdata, -- .length = (uint32_t)txlength //(uint32_t)txdata[1] -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C receive function for ASF I2C -- * -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ --#ifdef DEBUG_HAL -- printf("hal_i2c_receive()\r\n"); --#endif -- -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t status = !TWI_SUCCESS; -- -- twi_package_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = (void*)rxdata, -- .length = (uint32_t)*rxlength -- }; -- -- while (retries-- > 0 && status != TWI_SUCCESS) -- { -- status = twi_master_read(i2c_hal_data[bus]->twi_master_instance, &packet); -- } -- if (status != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- --#ifdef DEBUG_HAL -- printf("\r\nResponse Packet (size:0x%.4x)\r\n", rxlength); -- printf("Count : %.2x\r\n", rxdata[0]); -- if (rxdata[0] > 3) -- { -- printf("Data : "); print_array(&rxdata[1], rxdata[0] - 3); -- printf("CRC : "); print_array(&rxdata[rxdata[0] - 2], 2); -- } -- printf("\r\n"); --#endif -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief method to change the bus speed of I2C -- * -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- -- pmc_enable_periph_clk(i2c_hal_data[bus]->twi_id); -- -- opt_twi_master.master_clk = sysclk_get_cpu_hz(); -- opt_twi_master.speed = speed; -- opt_twi_master.smbus = 0; -- -- twi_master_init(i2c_hal_data[bus]->twi_master_instance, &opt_twi_master); --} -- --/** -- * \brief wake up CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to wakeup -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !TWI_SUCCESS; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- // if not already at 100kHz, change it -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send 0x00 as wake pulse -- twi_write_byte(i2c_hal_data[bus]->twi_master_instance, 0x00); -- -- // rounded up to the nearest ms -- atca_delay_ms(((uint32_t)cfg->wake_delay + (1000 - 1)) / 1000); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- twi_package_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = (void*)data, -- .length = 4 -- }; -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- -- while (retries-- > 0 && status != TWI_SUCCESS) -- { -- status = twi_master_read(i2c_hal_data[bus]->twi_master_instance, &packet); -- } -- if (status != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief idle CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to idle -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x02; // idle word address value -- -- twi_package_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = (void*)data, -- .length = 1 -- }; -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief sleep CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to sleep -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x01; // sleep word address value -- -- twi_package_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = (void*)data, -- .length = 1 -- }; -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief manages reference count on given bus and releases resource if no more refences exist -- * -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- // set to default i2c bus -- if (hal->bus_index > MAX_I2C_BUSES - 1) -- { -- hal->bus_index = 0; -- } -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- twi_reset(hal->twi_master_instance); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_sam4s_i2c_asf.h b/lib/hal/hal_sam4s_i2c_asf.h -deleted file mode 100644 -index dea016a08be9..000000000000 ---- a/lib/hal/hal_sam4s_i2c_asf.h -+++ /dev/null -@@ -1,67 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAM4S I2C over ASF drivers. -- * -- * Prerequisite: add "TWI - Two-Wire Interface (Common API) (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAM4S_I2C_ASF_H_ --#define HAL_SAM4S_I2C_ASF_H_ -- --#include -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --#define MAX_I2C_BUSES 2 // SAM4S has 2 TWI -- --/** -- * \brief this is the hal_data for ATCA HAL -- */ --typedef struct atcaI2Cmaster --{ -- uint32_t twi_id; -- Twi * twi_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ -- --#endif /* HAL_SAM4S_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_sam4s_timer_asf.c b/lib/hal/hal_sam4s_timer_asf.c -deleted file mode 100644 -index c3c937c25252..000000000000 ---- a/lib/hal/hal_sam4s_timer_asf.c -+++ /dev/null -@@ -1,86 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAM4S I2C over ASF drivers. -- * -- * Prerequisite: add "Delay routines (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- -- --/* ASF already have delay_us and delay_ms - see delay.h */ -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** -- * \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** -- * \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** -- * \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * -- * \param[in] delay number of milliseconds to delay -- */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_samb11_i2c_asf.c b/lib/hal/hal_samb11_i2c_asf.c -deleted file mode 100644 -index aa12364e62c7..000000000000 ---- a/lib/hal/hal_samb11_i2c_asf.c -+++ /dev/null -@@ -1,485 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMB11 I2C over ASF drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the ASF I2C primitives to set up the interface. -- * -- * Prerequisite: add I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include -- --#include "atca_hal.h" --#include "hal_samb11_i2c_asf.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --static struct i2c_master_config config_i2c_master; -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- i2c_buses[0] = 0; // b11 bus for xplained pro dev board over EXT1 -- i2c_buses[1] = 1; // b11 bus for MR510CA -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] found number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // build an info command -- packet.param1 = INFO_MODE_REVISION; -- packet.param2 = 0; -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** \brief -- - this HAL implementation assumes you've included the ASF I2C libraries in your project, otherwise, -- the HAL layer will not compile because the ASF I2C drivers are a dependency * -- */ -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- i2c_master_get_config_defaults(&config_i2c_master); -- -- switch (bus) -- { -- case 0: -- config_i2c_master.pin_number_pad0 = PIN_LP_GPIO_8; -- config_i2c_master.pin_number_pad1 = PIN_LP_GPIO_9; -- config_i2c_master.pinmux_sel_pad0 = PINMUX_LP_GPIO_8_MUX2_I2C0_SDA; -- config_i2c_master.pinmux_sel_pad1 = PINMUX_LP_GPIO_9_MUX2_I2C0_SCL; -- i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), I2C0, &config_i2c_master); -- break; -- case 1: -- config_i2c_master.pin_number_pad0 = PIN_LP_GPIO_14; -- config_i2c_master.pin_number_pad1 = PIN_LP_GPIO_15; -- config_i2c_master.pinmux_sel_pad0 = PINMUX_LP_GPIO_14_MUX4_I2C1_SDA; -- config_i2c_master.pinmux_sel_pad1 = PINMUX_LP_GPIO_15_MUX4_I2C1_SCL; -- i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), I2C1, &config_i2c_master); -- break; -- } -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- -- i2c_enable((i2c_hal_data[bus]->i2c_master_instance).hw); -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C send over ASF -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = txlength, -- .data = txdata, -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.data_length = txlength; -- -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for ASF I2C -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = *rxlength, -- .data = rxdata, -- }; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = i2c_master_read_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- // Send the wake by writing to an address of 0x00 -- struct i2c_master_packet packet = { -- .address = 0x00, -- .data_length = 0, -- .data = &data[0], -- }; -- -- // Send the 00 address as the wake pulse -- i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); // part will NACK, so don't check for status -- -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- packet.address = cfg->atcai2c.slave_address >> 1; -- packet.data_length = 4; -- packet.data = data; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = i2c_master_read_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = 1, -- .data = &data[0], -- }; -- -- data[0] = 0x02; // idle word address value -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; -- --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = 1, -- .data = data, -- }; -- -- data[0] = 0x01; // sleep word address value -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more references exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- i2c_master_reset(&(hal->i2c_master_instance)); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_samb11_i2c_asf.h b/lib/hal/hal_samb11_i2c_asf.h -deleted file mode 100644 -index 0c2243a3c703..000000000000 ---- a/lib/hal/hal_samb11_i2c_asf.h -+++ /dev/null -@@ -1,60 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMB11 I2C over ASF drivers. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAMB11_I2C_ASF_H_ --#define HAL_SAMB11_I2C_ASF_H_ -- --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --#define MAX_I2C_BUSES 2 // SAMB11 has up to 2 I2C address that can be configured as I2C -- --/** \brief this is the hal_data for ATCA HAL for ASF -- */ --typedef struct atcaI2Cmaster --{ -- struct i2c_master_module i2c_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --/** @} */ --#endif /* HAL_SAMB11_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_samb11_timer_asf.c b/lib/hal/hal_samb11_timer_asf.c -deleted file mode 100644 -index dd0a21fea7ee..000000000000 ---- a/lib/hal/hal_samb11_timer_asf.c -+++ /dev/null -@@ -1,78 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMB11 timer/delay over ASF drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_samd21_i2c_asf.c b/lib/hal/hal_samd21_i2c_asf.c -deleted file mode 100644 -index 841a1fb9125e..000000000000 ---- a/lib/hal/hal_samd21_i2c_asf.c -+++ /dev/null -@@ -1,572 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 I2C over ASF drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the ASF I2C primitives to set up the interface. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include -- --#include "atca_hal.h" --#include "hal_samd21_i2c_asf.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --static struct i2c_master_config config_i2c_master; -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- -- /* if every SERCOM was a likely candidate bus, then would need to initialize the entire array to all SERCOM n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / SERCOM map based on D21 Xplained Pro board -- * If you were using a raw D21 on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ --#ifdef __SAMR21G18A__ -- i2c_buses[0] = 1; // default r21 for xplained pro dev board --#else -- i2c_buses[0] = 2; // default d21 for xplained pro dev board --#endif -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] found number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs608[1][4] = { { 0x00, 0x00, 0x60, 0x01 } }; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(&packet, 0x00, sizeof(packet)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- -- if ( (status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs608) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs608[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC608A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM I2C libraries in your project, otherwise, -- the HAL layer will not compile because the ASF I2C drivers are a dependency * -- */ -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- i2c_master_get_config_defaults(&config_i2c_master); --#ifdef __SAMR21G18A__ -- if (bus == 1) -- { -- config_i2c_master.pinmux_pad0 = PINMUX_PA16C_SERCOM1_PAD0; -- config_i2c_master.pinmux_pad1 = PINMUX_PA17C_SERCOM1_PAD1; -- } --#endif --#ifdef __SAMD21G18A__ -- if (bus == 0) -- { -- // This is to support SAMW25 configs, where the WINC1500 is on SERCOM2 -- config_i2c_master.pinmux_pad0 = PINMUX_PA08C_SERCOM0_PAD0; -- config_i2c_master.pinmux_pad1 = PINMUX_PA09C_SERCOM0_PAD1; -- } --#endif -- -- // config_i2c_master.buffer_timeout = 10000; -- config_i2c_master.baud_rate = cfg->atcai2c.baud / 1000; -- -- switch (bus) -- { -- case 0: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM0, &config_i2c_master); break; -- case 1: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM1, &config_i2c_master); break; -- case 2: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM2, &config_i2c_master); break; -- case 3: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM3, &config_i2c_master); break; -- case 4: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM4, &config_i2c_master); break; -- case 5: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM5, &config_i2c_master); break; -- } -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- i2c_master_enable(&(i2c_hal_data[bus]->i2c_master_instance)); -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C send over ASF -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = txlength, -- .data = txdata, -- .ten_bit_address = false, -- .high_speed = false, -- .hs_master_code = 0x0, -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.data_length = txlength; -- -- // statusCode = i2c_master_write_packet_wait(&i2c_master_instance, &packet); -- //if ( i2c_master_write_packet_wait_no_stop( &(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for ASF I2C -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = *rxlength, -- .data = rxdata, -- .ten_bit_address = false, -- .high_speed = false, -- .hs_master_code = 0x0, -- }; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = i2c_master_read_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- if (atCheckCrc(packet.data) != ATCA_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief method to change the bus speec of I2C -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ -- --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- config_i2c_master.buffer_timeout = 10000; -- config_i2c_master.baud_rate = speed / 1000; -- -- i2c_master_disable(&(i2c_hal_data[bus]->i2c_master_instance)); -- -- switch (bus) -- { -- case 0: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM0, &config_i2c_master); break; -- case 1: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM1, &config_i2c_master); break; -- case 2: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM2, &config_i2c_master); break; -- case 3: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM3, &config_i2c_master); break; -- case 4: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM4, &config_i2c_master); break; -- case 5: i2c_master_init(&(i2c_hal_data[bus]->i2c_master_instance), SERCOM5, &config_i2c_master); break; -- } -- -- i2c_master_enable(&(i2c_hal_data[bus]->i2c_master_instance)); --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !STATUS_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send the wake by writing to an address of 0x00 -- struct i2c_master_packet packet = { -- .address = 0x00, -- .data_length = 0, -- .data = &data[0], -- .ten_bit_address = false, -- .high_speed = false, -- .hs_master_code = 0x0, -- }; -- -- // Send the 00 address as the wake pulse -- i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); // part will NACK, so don't check for status -- -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- packet.address = cfg->atcai2c.slave_address >> 1; -- packet.data_length = 4; -- packet.data = data; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = i2c_master_read_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = 1, -- .data = &data[0], -- .ten_bit_address = false, -- .high_speed = false, -- .hs_master_code = 0x0, -- }; -- -- data[0] = 0x02; // idle word address value -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; -- --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct i2c_master_packet packet = { -- .address = cfg->atcai2c.slave_address >> 1, -- .data_length = 1, -- .data = &data[0], -- .ten_bit_address = false, -- .high_speed = false, -- .hs_master_code = 0x0, -- }; -- -- data[0] = 0x01; // sleep word address value -- if (i2c_master_write_packet_wait(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- i2c_master_reset(&(hal->i2c_master_instance)); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_samd21_i2c_asf.h b/lib/hal/hal_samd21_i2c_asf.h -deleted file mode 100644 -index b8ff14d0123d..000000000000 ---- a/lib/hal/hal_samd21_i2c_asf.h -+++ /dev/null -@@ -1,63 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 I2C over ASF drivers. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAMD21_I2C_ASF_H_ --#define HAL_SAMD21_I2C_ASF_H_ -- --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- -- --#define MAX_I2C_BUSES 6 // SAMD21 has up to 6 SERCOMS that can be configured as I2C -- --/** \brief this is the hal_data for ATCA HAL for ASF SERCOM -- */ --typedef struct atcaI2Cmaster --{ -- struct i2c_master_module i2c_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ --#endif /* HAL_SAMD21_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_samd21_i2c_start.c b/lib/hal/hal_samd21_i2c_start.c -deleted file mode 100644 -index 5bade0768ef0..000000000000 ---- a/lib/hal/hal_samd21_i2c_start.c -+++ /dev/null -@@ -1,545 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 I2C over START drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the START I2C primitives to set up the interface. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- #include --#include --#include --#include --#include --#include "atca_hal.h" --#include "atca_device.h" --#include "hal_samd21_i2c_start.h" --#include "peripheral_gclk_config.h" -- --#include "atca_start_config.h" --#include "atca_start_iface.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses -- --/* Notes: -- - this HAL implementation assumes you've included the Atmel START SERCOM I2C libraries in your project, otherwise, -- the HAL layer will not compile because the START I2C drivers are a dependency * -- */ -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- -- /* if every SERCOM was a likely candidate bus, then would need to initialize the entire array to all SERCOM n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / SERCOM map based on D21 Xplained Pro board -- * If you were using a raw D21 on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ --#ifdef __SAMR21G18A__ -- i2c_buses[0] = 1; // default r21 for xplained pro dev board --#else -- i2c_buses[0] = 2; // default d21 for xplained pro dev board --#endif -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] found number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs608[1][4] = { { 0x00, 0x00, 0x60, 0x01 } }; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(&packet, 0x00, sizeof(packet)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- -- for (i = 0; i < (int)sizeof(revs608) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs608[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC608A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- -- -- --/** \brief -- - this HAL implementation assumes you've included the START Twi libraries in your project, otherwise, -- the HAL layer will not compile because the START TWI drivers are a dependency * -- */ -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- uint32_t freq_constant; // I2C frequency configuration constant in kHz -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- // store I2C baudrate in kHz -- freq_constant = cfg->atcai2c.baud / 1000; -- -- switch (bus) -- { -- case 0: break; -- case 1: break; -- case 2: memcpy(&(i2c_hal_data[bus]->i2c_master_instance), &I2C_0, sizeof(struct i2c_m_sync_desc)); break; -- case 3: break; -- case 4: break; -- case 5: break; -- } -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- -- // set I2C baudrate and enable I2C module -- i2c_m_sync_set_baudrate(&(i2c_hal_data[bus]->i2c_master_instance), CONF_GCLK_SERCOM2_CORE_FREQUENCY / 1000, freq_constant); -- i2c_m_sync_enable(&(i2c_hal_data[bus]->i2c_master_instance)); -- -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C send over START -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- struct _i2c_m_msg packet = { -- .addr = cfg->atcai2c.slave_address >> 1, -- .buffer = txdata, -- .flags = I2C_M_SEVEN | I2C_M_STOP, -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.len = txlength; -- -- if (i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != I2C_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for START I2C -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !I2C_OK; -- -- struct _i2c_m_msg packet = { -- .addr = cfg->atcai2c.slave_address >> 1, -- .len = *rxlength, -- .buffer = rxdata, -- .flags = I2C_M_SEVEN | I2C_M_RD | I2C_M_STOP, -- }; -- -- while (retries-- > 0 && status != I2C_OK) -- { -- status = i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- if (status != I2C_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief method to change the bus speec of I2C -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ -- --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint32_t freq_constant; // I2C frequency configuration constant -- -- // disable I2C module -- i2c_m_sync_disable(&(i2c_hal_data[bus]->i2c_master_instance)); -- -- // store I2C baudrate in kHz -- freq_constant = speed / 1000; -- -- // set I2C baudrate and enable I2C module -- i2c_m_sync_set_baudrate(&(i2c_hal_data[bus]->i2c_master_instance), CONF_GCLK_SERCOM2_CORE_FREQUENCY / 1000, freq_constant); -- i2c_m_sync_enable(&(i2c_hal_data[bus]->i2c_master_instance)); --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !I2C_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- { -- change_i2c_speed(iface, 100000); -- } -- -- // send the wake by writing to an address of 0x00 -- struct _i2c_m_msg packet = { -- .addr = 0x00, -- .len = 0, -- .buffer = NULL, -- .flags = I2C_M_SEVEN | I2C_M_STOP, -- }; -- -- // Send the 00 address as the wake pulse -- status = i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet); // part will NACK, so don't check for status -- -- delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- // receive the wake up response -- packet.addr = cfg->atcai2c.slave_address >> 1; -- packet.len = 4; -- packet.buffer = data; -- packet.flags = I2C_M_SEVEN | I2C_M_RD | I2C_M_STOP; -- -- while (retries-- > 0 && status != I2C_OK) -- { -- status = i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet); -- } -- -- if (status == I2C_OK) -- { -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- // compare received data with expected value -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct _i2c_m_msg packet = { -- .addr = cfg->atcai2c.slave_address >> 1, -- .len = 1, -- .buffer = &data[0], -- .flags = I2C_M_SEVEN | I2C_M_STOP, -- }; -- -- data[0] = 0x02; // idle word address value -- -- if (i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != I2C_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- struct _i2c_m_msg packet = { -- .addr = cfg->atcai2c.slave_address >> 1, -- .len = 1, -- .buffer = &data[0], -- .flags = I2C_M_SEVEN | I2C_M_STOP, -- }; -- -- data[0] = 0x01; // sleep word address value -- -- if (i2c_m_sync_transfer(&(i2c_hal_data[bus]->i2c_master_instance), &packet) != I2C_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- //if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- i2c_m_sync_disable(&(hal->i2c_master_instance)); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_samd21_i2c_start.h b/lib/hal/hal_samd21_i2c_start.h -deleted file mode 100644 -index 08a50093dd9a..000000000000 ---- a/lib/hal/hal_samd21_i2c_start.h -+++ /dev/null -@@ -1,64 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 I2C over START drivers. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAMD21_I2C_START_H_ --#define HAL_SAMD21_I2C_START_H_ -- --#include "atmel_start.h" --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --#define MAX_I2C_BUSES 6 // SAMD21 has up to 6 SERCOMS that can be configured as I2C -- --/** \brief this is the hal_data for ATCA HAL for Atmel START SERCOM -- */ --typedef struct atcaI2Cmaster --{ -- struct i2c_m_sync_desc i2c_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ -- --#endif /* HAL_SAMD21_I2C_START_H_ */ -diff --git a/lib/hal/hal_samd21_timer_asf.c b/lib/hal/hal_samd21_timer_asf.c -deleted file mode 100644 -index ba191e400f3c..000000000000 ---- a/lib/hal/hal_samd21_timer_asf.c -+++ /dev/null -@@ -1,79 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 timer/delay over ASF drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_samd21_timer_start.c b/lib/hal/hal_samd21_timer_start.c -deleted file mode 100644 -index 1204331466ab..000000000000 ---- a/lib/hal/hal_samd21_timer_start.c -+++ /dev/null -@@ -1,80 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 I2C over START drivers. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of microseconds to delay -- */ -- --void atca_delay_us(uint32_t delay) --{ -- // use START supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ -- --void atca_delay_10us(uint32_t delay) --{ -- // use START supplied delay -- delay_us(delay * 10); --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --void atca_delay_ms(uint32_t delay) --{ -- // use START supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_samg55_i2c_asf.c b/lib/hal/hal_samg55_i2c_asf.c -deleted file mode 100644 -index 37a7ddd9348d..000000000000 ---- a/lib/hal/hal_samg55_i2c_asf.c -+++ /dev/null -@@ -1,661 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMG55 I2C over ASF drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the ASF I2C primitives to set up the interface. -- * -- * Prerequisite: add "TWI - Two-Wire Interface (Common API) (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "atca_device.h" --#include "hal_samg55_i2c_asf.h" -- -- --//!< Uncomment when debugging --/*#define DEBUG_HAL*/ -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** -- * \brief -- * Logical to physical bus mapping structure -- */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --twi_options_t opt_twi_master; -- -- --#ifdef DEBUG_HAL --static void print_array(uint8_t *data, uint32_t data_size) --{ -- uint32_t n; -- -- for (n = 0; n < data_size; n++) -- { -- printf("%.2x ", data[n]); -- if (((n + 1) % 16) == 0) -- { -- printf("\r\n"); -- if ((n + 1) != data_size) -- { -- printf(" "); -- } -- } -- } -- if (data_size % 16 != 0) -- { -- printf("\r\n"); -- } --} --#endif -- --/** -- * \brief -- * This HAL implementation assumes you've included the ASF TWI libraries in your project, otherwise, -- * the HAL layer will not compile because the ASF TWI drivers are a dependency -- */ -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- /* logical bus numbers 0-2 map to the samG55 i2c buses: -- */ -- i2c_buses[0] = 0; -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- if (busNum < 0) -- { -- return ATCA_COMM_FAIL; -- } -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief -- * hal_i2c_init manages requests to initialize a physical interface. It manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** -- * \brief initialize an I2C interface using given config -- * -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- //// if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t)); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- switch (bus) -- { -- case 0: -- i2c_hal_data[bus]->twi_id = ID_FLEXCOM4; -- i2c_hal_data[bus]->twi_master_instance = TWI4; -- break; -- case 1: -- i2c_hal_data[bus]->twi_id = FLEXCOM6; -- i2c_hal_data[bus]->twi_master_instance = TWI6; -- break; -- } -- -- flexcom_enable((Flexcom*)i2c_hal_data[bus]->twi_id); -- flexcom_set_opmode((Flexcom*)i2c_hal_data[bus]->twi_id, FLEXCOM_TWI); -- -- opt_twi_master.master_clk = sysclk_get_cpu_hz(); -- opt_twi_master.speed = cfg->atcai2c.baud; -- opt_twi_master.smbus = 0; -- -- twi_master_init(i2c_hal_data[bus]->twi_master_instance, &opt_twi_master); -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief HAL implementation of I2C post init -- * -- * \param[in] iface instance -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C send over ASF -- * -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ --#ifdef DEBUG_HAL -- printf("hal_i2c_send()\r\n"); -- -- printf("\r\nCommand Packet (size:0x%.8x)\r\n", (uint32_t)txlength); -- printf("Count : %.2x\r\n", txdata[1]); -- printf("Opcode : %.2x\r\n", txdata[2]); -- printf("Param1 : %.2x\r\n", txdata[3]); -- printf("Param2 : "); print_array(&txdata[4], 2); -- if (txdata[1] > 7) -- { -- printf("Data : "); print_array(&txdata[6], txdata[1] - 7); -- } -- printf("CRC : "); print_array(&txdata[txdata[1] - 1], 2); -- printf("\r\n"); --#endif -- -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- -- twi_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = txdata, -- .length = (uint32_t)txlength //(uint32_t)txdata[1] -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief HAL implementation of I2C receive function for ASF I2C -- * -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ --#ifdef DEBUG_HAL -- printf("hal_i2c_receive()\r\n"); --#endif -- -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t status = !TWI_SUCCESS; -- -- twi_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = rxdata, -- .length = (uint32_t)*rxlength -- }; -- -- while (retries-- > 0 && status != TWI_SUCCESS) -- { -- status = twi_master_read(i2c_hal_data[bus]->twi_master_instance, &packet); -- } -- if (status != TWI_SUCCESS) -- { -- if (retries <= 0) -- { -- return ATCA_TOO_MANY_COMM_RETRIES; -- } -- -- return ATCA_COMM_FAIL; -- } -- --#ifdef DEBUG_HAL -- printf("\r\nResponse Packet (size:0x%.4x)\r\n", rxlength); -- printf("Count : %.2x\r\n", rxdata[0]); -- if (rxdata[0] > 3) -- { -- printf("Data : "); print_array(&rxdata[1], rxdata[0] - 3); -- printf("CRC : "); print_array(&rxdata[rxdata[0] - 2], 2); -- } -- printf("\r\n"); --#endif -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief method to change the bus speed of I2C -- * -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- -- pmc_enable_periph_clk(i2c_hal_data[bus]->twi_id); -- -- opt_twi_master.master_clk = sysclk_get_cpu_hz(); -- opt_twi_master.speed = speed; -- opt_twi_master.smbus = 0; -- -- twi_master_init(i2c_hal_data[bus]->twi_master_instance, &opt_twi_master); --} -- --/** -- * \brief wake up CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to wakeup -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- //set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !TWI_SUCCESS; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- // if not already at 100kHz, change it -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send 0x00 as wake pulse -- twi_write_byte(i2c_hal_data[bus]->twi_master_instance, 0x00); -- -- // rounded up to the nearest ms -- atca_delay_ms(((uint32_t)cfg->wake_delay + (1000 - 1)) / 1000); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- twi_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = data, -- .length = 4 -- }; -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- -- while (retries-- > 0 && status != TWI_SUCCESS) -- { -- status = twi_master_read(i2c_hal_data[bus]->twi_master_instance, &packet); -- } -- if (status != TWI_SUCCESS) -- { -- if (retries <= 0) -- { -- return ATCA_TOO_MANY_COMM_RETRIES; -- } -- -- return ATCA_COMM_FAIL; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief idle CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to idle -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- // set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x02; // idle word address value -- -- twi_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = data, -- .length = 1 -- }; -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief sleep CryptoAuth device using I2C bus -- * -- * \param[in] iface interface to logical device to sleep -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- //// set to default i2c bus -- if (cfg->atcai2c.bus > MAX_I2C_BUSES - 1) -- { -- cfg->atcai2c.bus = 0; -- } -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- data[0] = 0x01; // sleep word address value -- -- twi_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, -- .addr = { 0 }, -- .addr_length = 0, -- .buffer = data, -- .length = 1 -- }; -- -- if (twi_master_write(i2c_hal_data[bus]->twi_master_instance, &packet) != TWI_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief manages reference count on given bus and releases resource if no more refences exist -- * -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- // set to default i2c bus -- if (hal->bus_index > MAX_I2C_BUSES - 1) -- { -- hal->bus_index = 0; -- } -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- twi_reset(hal->twi_master_instance); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_samg55_i2c_asf.h b/lib/hal/hal_samg55_i2c_asf.h -deleted file mode 100644 -index a3c545c72d43..000000000000 ---- a/lib/hal/hal_samg55_i2c_asf.h -+++ /dev/null -@@ -1,67 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMG55 I2C over ASF drivers. -- * -- * Prerequisite: add "TWI - Two-Wire Interface (Common API) (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAMG55_I2C_ASF_H_ --#define HAL_SAMG55_I2C_ASF_H_ -- --#include -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --#define MAX_I2C_BUSES 2 // SAMG55 has 2 TWI -- --/** -- * \brief this is the hal_data for ATCA HAL -- */ --typedef struct atcaI2Cmaster --{ -- uint32_t twi_id; -- Twi * twi_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ -- --#endif /* HAL_SAMG55_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_samg55_timer_asf.c b/lib/hal/hal_samg55_timer_asf.c -deleted file mode 100644 -index 6b5a27ce1dbf..000000000000 ---- a/lib/hal/hal_samg55_timer_asf.c -+++ /dev/null -@@ -1,86 +0,0 @@ --/** -- * \file -- * \brief -- * -- * Prerequisite: add "Delay routines (service)" module to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- -- --/* ASF already have delay_us and delay_ms - see delay.h */ -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** -- * \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** -- * \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** -- * \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * -- * \param[in] delay number of milliseconds to delay -- */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_samv71_i2c_asf.c b/lib/hal/hal_samv71_i2c_asf.c -deleted file mode 100644 -index 7da38807d998..000000000000 ---- a/lib/hal/hal_samv71_i2c_asf.c -+++ /dev/null -@@ -1,583 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMV71 I2C over ASF drivers. -- * -- * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C -- * implementation. Part 2 is the ASF I2C primitives to set up the interface. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include -- --#include "atca_hal.h" --#include "hal_samv71_i2c_asf.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- /* logical bus numbers 0-2 map to the V71 i2c buses: -- ID_TWIHS0 -- ID_TWIHS1 -- ID_TWIHS2 -- -- until ASF driver supports timeouts, only the TWIHS0 bus will respond on the SAMV71 Xplained Pro board -- otherwise, driver hangs on waiting for txready. -- for( i = 0; i < MAX_I2C_BUSES && i < max_buses; i++ ) -- i2c_buses[i] = i; -- */ -- i2c_buses[0] = 0; --#if MAX_I2C_BUSES == 3 -- i2c_buses[1] = -1; -- i2c_buses[2] = -1; --#endif -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] bus_num Logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg Pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] found Number of devices found on this bus -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slave_address = 0x01; -- ATCADevice device; -- ATCAIface discover_iface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs608[1][4] = { { 0x00, 0x00, 0x60, 0x01 } }; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = bus_num, -- .atcai2c.baud = 400000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- ATCAHAL_t hal; -- -- if (bus_num < 0) -- { -- return ATCA_COMM_FAIL; -- } -- -- hal_i2c_init(&hal, &discoverCfg); -- device = newATCADevice(&discoverCfg); -- discover_iface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slave_address = 0x07; slave_address <= 0x78; slave_address++) -- { -- discoverCfg.atcai2c.slave_address = slave_address << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discover_iface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(&packet, 0x00, sizeof(packet)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discover_iface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discover_iface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < (int)sizeof(revs608) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs608[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC608A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < (int)sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discover_iface); -- } -- -- // hal_i2c_release(&hal); -- -- return ATCA_SUCCESS; --} -- --/** \brief -- - this HAL implementation assumes you've included the ASF Twi libraries in your project, otherwise, -- the HAL layer will not compile because the ASF TWI drivers are a dependency * -- */ -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- twihs_options_t twi_options; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- /* Configure the options of TWI driver */ -- twi_options.master_clk = sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV; -- twi_options.speed = cfg->atcai2c.baud; -- -- switch (bus) -- { -- case 0: /* Enable the peripheral clock for TWI */ -- pmc_enable_periph_clk(ID_TWIHS0); -- if (twihs_master_init(TWIHS0, &twi_options) != TWIHS_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- i2c_hal_data[bus]->twi_module = (uint32_t)TWIHS0; -- break; -- -- case 1: /* Enable the peripheral clock for TWI */ -- pmc_enable_periph_clk(ID_TWIHS1); -- if (twihs_master_init(TWIHS1, &twi_options) != TWIHS_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- i2c_hal_data[bus]->twi_module = (uint32_t)TWIHS1; -- break; -- -- case 2: /* Enable the peripheral clock for TWI */ -- pmc_enable_periph_clk(ID_TWIHS2); -- if (twihs_master_init(TWIHS2, &twi_options) != TWIHS_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- i2c_hal_data[bus]->twi_module = (uint32_t)TWIHS2; -- break; -- } -- -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- -- --/** \brief HAL implementation of I2C send over ASF -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- twihs_packet_t packet = { -- .addr[0] = 0, -- .addr[1] = 0, -- .addr_length = 0, //very important, since cryptoauthdevices do not require addressing; -- .chip = cfg->atcai2c.slave_address >> 1, -- .buffer = txdata, -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.length = txlength; -- -- if (twihs_master_write(twihs_device, &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for ASF I2C -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- twihs_packet_t packet = { -- .chip = cfg->atcai2c.slave_address >> 1, // use 7-bit address -- .buffer = rxdata, -- .length = *rxlength -- }; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- if (twihs_master_read(twihs_device, &packet) != TWIHS_SUCCESS) -- { -- status = ATCA_COMM_FAIL; -- } -- else -- { -- status = ATCA_SUCCESS; -- } -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief method to change the bus speed of I2C -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- // if necessary, revert baud rate to what came in. -- if (twihs_set_speed(twihs_device, speed, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint16_t rxlength; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !STATUS_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- -- { -- if (twihs_set_speed(twihs_device, 100000, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL) -- { -- return ATCA_COMM_FAIL; -- } -- } -- -- twihs_packet_t packet = { -- .addr[0] = 0, -- .addr[1] = 0, -- .addr_length = 0, //very important, since cryptoauthdevices do not require addressing; -- .chip = cfg->atcai2c.slave_address >> 1, -- .buffer = &data[0], -- .length = 1 -- }; -- -- twihs_master_write(twihs_device, &packet); -- -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- // look for wake response -- rxlength = 4; -- memset(data, 0x00, rxlength); -- status = hal_i2c_receive(iface, data, &rxlength); -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- if (twihs_set_speed(twihs_device, bdrt, sysclk_get_cpu_hz() / CONFIG_SYSCLK_DIV) == FAIL) -- { -- return ATCA_COMM_FAIL; -- } -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- data[0] = 0x02; // idle word address value -- -- twihs_packet_t packet = { -- .addr[0] = 0, -- .addr[1] = 0, -- .addr_length = 0, //very important, since cryptoauthdevices do not require addressing; -- .chip = cfg->atcai2c.slave_address >> 1, -- .buffer = data, -- }; -- -- packet.length = 1; -- -- if (twihs_master_write(twihs_device, &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- data[0] = 0x01; // sleep word address value -- -- twihs_packet_t packet = { -- .addr[0] = 0, -- .addr[1] = 0, -- .addr_length = 0, //very important, since cryptoauthdevices do not require addressing; -- .chip = cfg->atcai2c.slave_address >> 1, -- .buffer = data, -- }; -- -- packet.length = 1; -- -- if (twihs_master_write(twihs_device, &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- int bus = hal->bus_index; -- Twihs *twihs_device = (Twihs*)(i2c_hal_data[bus]->twi_module); -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[bus] != NULL) -- { -- twihs_disable_master_mode(twihs_device); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_samv71_i2c_asf.h b/lib/hal/hal_samv71_i2c_asf.h -deleted file mode 100644 -index 7efcb52b8b17..000000000000 ---- a/lib/hal/hal_samv71_i2c_asf.h -+++ /dev/null -@@ -1,63 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMV71 I2C over ASF drivers. -- * -- * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SAMV71_I2C_ASF_H_ --#define HAL_SAMV71_I2C_ASF_H_ -- --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- -- --#define MAX_I2C_BUSES 3 -- --/** \brief this is the hal_data for ATCA HAL for ASF SERCOM -- */ --typedef struct atcaI2Cmaster --{ -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; -- uint32_t twi_module; --} ATCAI2CMaster_t; -- --ATCA_STATUS change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ --#endif /* HAL_SAMD21_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_samv71_timer_asf.c b/lib/hal/hal_samv71_timer_asf.c -deleted file mode 100644 -index 1090a2d26f70..000000000000 ---- a/lib/hal/hal_samv71_timer_asf.c -+++ /dev/null -@@ -1,79 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 timer/delay over ASF drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_swi_bitbang.c b/lib/hal/hal_swi_bitbang.c -deleted file mode 100644 -index 412b393d9bd0..000000000000 ---- a/lib/hal/hal_swi_bitbang.c -+++ /dev/null -@@ -1,347 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SWI bit banging. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "hal_swi_bitbang.h" --#include "atca_device.h" -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief These methods define the hardware abstraction layer for -- * communicating with a CryptoAuth device using SWI bit banging. -- @{ */ -- --/** -- * \brief Logical to physical bus mapping structure. -- */ --ATCASWIMaster_t *swi_hal_data[MAX_SWI_BUSES]; //!< map logical, 0-based bus number to index --int swi_bus_ref_ct = 0; //!< total in-use count across buses -- --/** \brief discover swi buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application.This function is currently not supported. -- * of the a-priori knowledge -- * \param[in] swi_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_swi_discover_buses(int swi_buses[], int max_buses) --{ -- -- return ATCA_UNIMPLEMENTED; -- --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number.This function is curently not supported. -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_swi_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- return ATCA_UNIMPLEMENTED; -- --} -- -- -- --/** -- * \brief hal_swi_init manages requests to initialize a physical -- * interface. It manages use counts so when an interface has -- * released the physical layer, it will disable the interface for -- * some other use. You can have multiple ATCAIFace instances using -- * the same bus, and you can have multiple ATCAIFace instances on -- * multiple swi buses, so hal_swi_init manages these things and -- * ATCAIFace is abstracted from the physical details. -- */ -- --/** -- * \brief Initialize an SWI interface using given config. -- * -- * \param[in] hal opaque pointer to HAL data -- * \param[in] cfg interface configuration -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_swi_init(void *hal, ATCAIfaceCfg *cfg) --{ -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- int bus = cfg->atcaswi.bus; //!< 0-based logical bus number -- -- if (swi_bus_ref_ct == 0) //!< power up state, no swi buses will have been used -- -- { -- for (int i = 0; i < MAX_SWI_BUSES; i++) -- { -- swi_hal_data[i] = NULL; -- } -- } -- swi_bus_ref_ct++; //!< total across buses -- -- if (bus >= 0 && bus < MAX_SWI_BUSES) -- { -- //! if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (swi_hal_data[bus] == NULL) -- { -- swi_hal_data[bus] = malloc(sizeof(ATCASWIMaster_t)); -- -- //! assign GPIO pin -- swi_hal_data[bus]->pin_sda = swi_buses_default.pin_sda[bus]; -- -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- swi_enable(); -- -- //! store this for use during the release phase -- swi_hal_data[bus]->bus_index = bus; -- } -- else -- { -- //! otherwise, another interface already initialized the bus, any different -- //! cfg parameters will be ignored...first one to initialize this sets the configuration -- } -- -- phal->hal_data = swi_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** -- * \brief HAL implementation of SWI post init. -- * -- * \param[in] iface ATCAIface instance -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_swi_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** -- * \brief Send byte(s) via SWI. -- * -- * \param[in] iface interface of the logical device to send data to -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_swi_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- int bus = cfg->atcaswi.bus; -- -- //! Skip the Word Address data as SWI doesn't use it -- txdata++; -- -- //! Set SWI pin -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- -- //! Send Command Flag -- swi_send_byte(SWI_FLAG_CMD); -- -- //! Send the remaining bytes -- swi_send_bytes(txlength, txdata); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief Receive byte(s) via SWI. -- * -- * \param[in] iface interface of the logical device to receive data -- * from -- * \param[out] rxdata pointer to where bytes will be received -- * \param[in] rxlength pointer to expected number of receive bytes to -- * request -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_swi_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_RX_TIMEOUT; -- -- int bus = cfg->atcaswi.bus; -- int retries = cfg->rx_retries; -- uint16_t count; -- -- //! Set SWI pin -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- -- while (retries-- > 0 && status != ATCA_SUCCESS) -- { -- swi_send_byte(SWI_FLAG_TX); -- -- status = swi_receive_bytes(*rxlength, rxdata); -- if (status == ATCA_RX_FAIL) -- { -- count = rxdata[0]; -- if ((count < ATCA_RSP_SIZE_MIN) || (count > *rxlength)) -- { -- status = ATCA_INVALID_SIZE; -- break; -- } -- else -- { -- status = ATCA_SUCCESS; -- } -- } -- else if (status == ATCA_RX_TIMEOUT) -- { -- status = ATCA_RX_NO_RESPONSE; -- } -- } -- -- return status; --} -- --/** -- * \brief Send Wake flag via SWI. -- * -- * \param[in] iface interface of the logical device to wake up -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_swi_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- ATCA_STATUS status = ATCA_WAKE_FAILED; -- -- int bus = cfg->atcaswi.bus; -- uint8_t response[4] = { 0x00, 0x00, 0x00, 0x00 }; -- uint8_t expected_response[4] = { 0x04, 0x11, 0x33, 0x43 }; -- uint16_t rxlength = sizeof(response); -- -- //! Set SWI pin -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- -- //! Generate Wake Token -- swi_send_wake_token(); -- -- //! Wait tWHI + tWLO -- atca_delay_us(cfg->wake_delay); -- -- status = hal_swi_receive(iface, response, &rxlength); -- if (status == ATCA_SUCCESS) -- { -- //! Compare response with expected_response -- if (memcmp(response, expected_response, 4) != 0) -- { -- status = ATCA_WAKE_FAILED; -- } -- } -- -- return status; --} -- --/** -- * \brief Send Idle flag via SWI. -- * -- * \param[in] iface interface of the logical device to idle -- * -- * \return ATCA_SUCCES -- */ --ATCA_STATUS hal_swi_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- int bus = cfg->atcaswi.bus; -- -- //! Set SWI pin -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- -- swi_send_byte(SWI_FLAG_IDLE); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief Send Sleep flag via SWI. -- * -- * \param[in] iface interface of the logical device to sleep -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_swi_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- -- int bus = cfg->atcaswi.bus; -- -- //! Set SWI pin -- swi_set_pin(swi_hal_data[bus]->pin_sda); -- -- swi_send_byte(SWI_FLAG_SLEEP); -- -- return ATCA_SUCCESS; --} -- --/** -- * \brief Manages reference count on given bus and releases resource if -- * no more reference(s) exist. -- * -- * \param[in] hal_data opaque pointer to hal data structure - known only -- * to the HAL implementation -- * -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_swi_release(void *hal_data) --{ -- ATCASWIMaster_t *hal = (ATCASWIMaster_t*)hal_data; -- -- swi_bus_ref_ct--; //!< track total SWI instances -- -- //! if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && swi_hal_data[hal->bus_index] != NULL) -- { -- swi_set_pin(swi_hal_data[hal->bus_index]->pin_sda); -- swi_disable(); -- free(swi_hal_data[hal->bus_index]); -- swi_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -\ No newline at end of file -diff --git a/lib/hal/hal_swi_bitbang.h b/lib/hal/hal_swi_bitbang.h -deleted file mode 100644 -index b981a6fc99ff..000000000000 ---- a/lib/hal/hal_swi_bitbang.h -+++ /dev/null -@@ -1,76 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SWI bit banging. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SWI_BITBANG_H_ --#define HAL_SWI_BITBANG_H_ -- -- --#if BOARD == AT88CK9000 --#include "swi_bitbang_at88ck9000.h" --#endif -- --#if (SAMD21 == 1) --#include "swi_bitbang_samd21.h" --#endif -- -- -- --/** -- * \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief These methods define the hardware abstraction layer for -- * communicating with a CryptoAuth device using SWI bit banging. -- @{ */ -- --/** -- * \brief This enumeration lists flags for SWI. -- */ --enum swi_flag --{ -- SWI_FLAG_CMD = (uint8_t)0x77, //!< flag preceding a command -- SWI_FLAG_TX = (uint8_t)0x88, //!< flag requesting a response -- SWI_FLAG_IDLE = (uint8_t)0xBB, //!< flag requesting to go into Idle mode -- SWI_FLAG_SLEEP = (uint8_t)0xCC //!< flag requesting to go into Sleep mode --}; -- --/** -- * \brief This is the hal_data for ATCA HAL. -- */ --typedef struct atcaSWImaster --{ -- uint8_t pin_sda; -- //! for conveniences during interface release phase -- int bus_index; --} ATCASWIMaster_t; -- --/** @} */ -- --#endif /* HAL_SWI_BITBANG_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_swi_uart.c b/lib/hal/hal_swi_uart.c -deleted file mode 100644 -index f379d9abcd5e..000000000000 ---- a/lib/hal/hal_swi_uart.c -+++ /dev/null -@@ -1,527 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SWI over UART drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" --#include "hal_swi_uart.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using SWI Interface. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCASWIMaster_t *swi_hal_data[MAX_SWI_BUSES]; // map logical, 0-based bus number to index --int swi_bus_ref_ct = 0; // total in-use count across buses -- --#ifdef DEBUG_HAL --static void print_array(uint8_t *data, uint32_t data_size) --{ -- // printf("%.4x\r\n", data_size); -- -- uint32_t n; -- -- for (n = 0; n < data_size; n++) -- { -- printf("%.2x ", data[n]); -- if (((n + 1) % 16) == 0) -- { -- printf("\r\n"); -- if ((n + 1) != data_size) -- { -- printf(" "); -- } -- } -- } -- if (data_size % 16 != 0) -- { -- printf("\r\n"); -- } --} --#endif -- -- --/** \brief discover swi buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] swi_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_swi_discover_buses(int swi_buses[], int max_buses) --{ -- swi_uart_discover_buses(swi_buses, max_buses); -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_swi_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- unsigned int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_SWI_IFACE, -- .devtype = ATECC508A, -- .atcaswi.bus = busNum, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- // build an info command -- packet.param1 = INFO_MODE_REVISION; -- packet.param2 = 0; -- -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_swi_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- return status; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- -- hal_swi_idle(discoverIface); -- } -- -- deleteATCADevice(&device); -- -- return ATCA_SUCCESS; --} -- --/** \brief hal_swi_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple swi buses, so hal_swi_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an SWI interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcaswi.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (swi_bus_ref_ct == 0) // power up state, no swi buses will have been used -- { -- for (int i = 0; i < MAX_SWI_BUSES; i++) -- { -- swi_hal_data[i] = NULL; -- } -- swi_bus_ref_ct++; // total across buses become 1 -- } -- -- if (bus >= 0 && bus < MAX_SWI_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (swi_hal_data[bus] == NULL) -- { -- swi_hal_data[bus] = malloc(sizeof(ATCASWIMaster_t) ); -- // store this for use during the release phase -- swi_hal_data[bus]->bus_index = bus; -- // initialize UART module for SWI interface -- swi_uart_init(swi_hal_data[bus]); -- } -- else -- { -- // otherwise, another interface already initialized the bus, any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- } -- phal->hal_data = swi_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of SWI post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_swi_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of SWI send one byte over UART -- * \param[in] iface instance -- * \param[in] data bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_send_flag(ATCAIface iface, uint8_t data) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcaswi.bus; -- uint8_t bit_mask, bit_data; -- -- for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) -- { -- // Send one byte that represent one bit, 0x7F for one or 0x7D for zero -- // The LSB (least significant bit) is sent first. -- bit_data = (bit_mask & data) ? 0x7F : 0x7D; -- status |= swi_uart_send_byte(swi_hal_data[bus], bit_data); -- -- } -- if (status != ATCA_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- else -- { -- return ATCA_SUCCESS; -- } --} -- --/** \brief HAL implementation of SWI send command over UART -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- --#ifdef DEBUG_HAL -- printf("hal_swi_send()\r\n"); -- -- printf("\r\nCommand Packet (size:0x%.4x)\r\n", txlength); -- printf("Count : %.2x\r\n", txdata[1]); -- printf("Opcode : %.2x\r\n", txdata[2]); -- printf("Param1 : %.2x\r\n", txdata[3]); -- printf("Param2 : "); print_array(&txdata[4], 2); -- if (txdata[1] > 7) -- { -- printf("Data : "); print_array(&txdata[6], txdata[1] - 7); -- } -- printf("CRC : "); print_array(&txdata[txdata[1] - 1], 2); -- printf("\r\n"); --#endif -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcaswi.bus; -- uint8_t i, bit_mask, bit_data; -- -- //Skip the Word Address data as SWI doesn't use it -- txdata++; -- -- status = hal_swi_send_flag(iface, SWI_FLAG_CMD); -- if (status == ATCA_SUCCESS) -- { -- for (i = 0; i < txlength; i++) -- { -- for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) -- { -- // Send one byte that represent one bit, 0x7F for one or 0x7D for zero -- // The LSB (least significant bit) is sent first. -- bit_data = (bit_mask & *txdata) ? 0x7F : 0x7D; -- status = swi_uart_send_byte(swi_hal_data[bus], bit_data); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_COMM_FAIL; -- } -- } -- txdata++; -- } -- return ATCA_SUCCESS; -- } -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of SWI receive function over UART -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ --#ifdef DEBUG_HAL -- printf("hal_swi_receive()\r\n"); --#endif -- ATCA_STATUS status = ATCA_COMM_FAIL; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcaswi.bus; -- int retries = cfg->rx_retries; -- uint8_t bit_mask, *head_buff, bit_data; -- uint16_t i = 0; -- -- while ((status != ATCA_SUCCESS) && (retries >= 0x00)) -- { -- retries--; -- head_buff = rxdata; -- -- status = hal_swi_send_flag(iface, SWI_FLAG_TX); -- -- // Set SWI to receive mode. -- swi_uart_mode(swi_hal_data[bus], RECEIVE_MODE); --#ifdef SAMD21_ASF -- RX_DELAY --#else -- atca_delay_us(RX_DELAY); // Must be configured to sync with response from device --#endif -- if (status == ATCA_SUCCESS) -- { -- for (i = 0; i < *rxlength; i++) -- { -- *head_buff = 0x00; -- for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) -- { -- bit_data = 0; -- status = swi_uart_receive_byte(swi_hal_data[bus], &bit_data); -- if ((i == 0) && (bit_mask == 1) && (status != ATCA_SUCCESS)) -- { -- break; -- } -- // Sometimes bit data from device is stretched -- // When the device sends a "one" bit, it is read as 0x7E or 0x7F. -- // When the device sends a "zero" bit, it is read as 0x7A, 0x7B, or 7D. -- if ((bit_data ^ 0x7F) < 2) -- { -- // Received "one" bit. -- *head_buff |= bit_mask; -- } -- } -- if ((i == 0) && (bit_mask == 1) && (status != ATCA_SUCCESS)) -- { -- break; -- } -- head_buff++; -- } -- // Set SWI to transmit mode. -- swi_uart_mode(swi_hal_data[bus], TRANSMIT_MODE); -- atca_delay_us(TX_DELAY); // Must be configured to sync with response from device -- } -- // The Response shorter than expected -- if ((i >= 4) && (status == ATCA_TIMEOUT)) -- { -- status = ATCA_SUCCESS; -- } -- } --#ifdef DEBUG_HAL -- printf("\r\nResponse Packet (size:0x%.4x)\r\n", *rxlength); -- printf("Count : %.2x\r\n", rxdata[0]); -- if (rxdata[0] > 3) -- { -- printf("Data : "); print_array(&rxdata[1], rxdata[0] - 3); -- printf("CRC : "); print_array(&rxdata[rxdata[0] - 2], 2); -- } -- printf("\r\n"); --#endif -- return status; --} -- -- --/** \brief wake up CryptoAuth device using SWI interface -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_wake(ATCAIface iface) --{ --#ifdef DEBUG_HAL -- printf("hal_swi_wake()\r\n"); --#endif -- ATCA_STATUS status = ATCA_COMM_FAIL; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcaswi.bus; -- int retries = cfg->rx_retries; -- uint16_t datalength = 4; -- uint8_t data[4] = { 0x00, 0x00, 0x00, 0x00 }, expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- while ((status != ATCA_SUCCESS) && (retries >= 0x00)) -- { -- retries--; -- // Change baudrate to 115200 to get low signal more than 60us -- swi_uart_setbaud(swi_hal_data[bus], 115200); -- // Send byte 0x00 -- status = swi_uart_send_byte(swi_hal_data[bus], SWI_WAKE_TOKEN); -- // Change baudrate back to 230400 -- swi_uart_setbaud(swi_hal_data[bus], 230400); -- } -- -- if (!status) -- { -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- status = hal_swi_receive(iface, data, &datalength); -- } -- -- if ((retries == 0x00) && (status != ATCA_SUCCESS) ) -- { -- return ATCA_TIMEOUT; -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using SWI interface -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_idle(ATCAIface iface) --{ -- return hal_swi_send_flag(iface, SWI_FLAG_IDLE); --} -- --/** \brief sleep CryptoAuth device using SWI interface -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_sleep(ATCAIface iface) --{ -- return hal_swi_send_flag(iface, SWI_FLAG_SLEEP); --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_swi_release(void *hal_data) --{ -- ATCASWIMaster_t *hal = (ATCASWIMaster_t*)hal_data; -- -- swi_bus_ref_ct--; // track total SWI instances -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && swi_hal_data[hal->bus_index] != NULL) -- { -- swi_uart_deinit(swi_hal_data[hal->bus_index]); -- free(swi_hal_data[hal->bus_index]); -- swi_hal_data[hal->bus_index] = NULL; -- } -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_swi_uart.h b/lib/hal/hal_swi_uart.h -deleted file mode 100644 -index 75274a7d4f2e..000000000000 ---- a/lib/hal/hal_swi_uart.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SWI over UART drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_SWI_UART_H_ --#define HAL_SWI_UART_H_ -- --#ifdef SAMD21_START -- #include "swi_uart_samd21_start.h" --#elif defined (SAMD21_ASF) -- #include "swi_uart_samd21_asf.h" --#elif defined (XMEGA_ASF) -- #include "swi_uart_xmega_a3bu_asf.h" --#elif defined (AT90USB_ASF) -- #include "swi_uart_at90usb1287_asf.h" --#endif -- -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using SWI interface. -- * -- @{ */ --#define SWI_WAKE_TOKEN ((uint8_t)0x00) //!< flag preceding a command --#define SWI_FLAG_CMD ((uint8_t)0x77) //!< flag preceding a command --#define SWI_FLAG_TX ((uint8_t)0x88) //!< flag requesting a response --#define SWI_FLAG_IDLE ((uint8_t)0xBB) //!< flag requesting to go into Idle mode --#define SWI_FLAG_SLEEP ((uint8_t)0xCC) //!< flag requesting to go into Sleep mode -- --ATCA_STATUS hal_swi_send_flag(ATCAIface iface, uint8_t flag); -- --/** @} */ --#endif /* HAL_SWI_UART_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_win_kit_cdc.c b/lib/hal/hal_win_kit_cdc.c -deleted file mode 100644 -index be3664f3df3b..000000000000 ---- a/lib/hal/hal_win_kit_cdc.c -+++ /dev/null -@@ -1,556 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Windows using kit protocol over a USB CDC device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --//#include "atca_basic.h" --#include "atca_hal.h" --#include "kit_phy.h" --#include "hal_win_kit_cdc.h" --#include "kit_protocol.h" -- --#include --#include --#include --#include -- -- --// File scope globals --atcacdc_t _gCdc; -- -- -- --/** \brief HAL implementation of Kit USB CDC init -- * \param[in] hal pointer to HAL specific data that is maintained by this HAL -- * \param[in] cfg pointer to HAL specific configuration data that is used to initialize this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_init(void* hal, ATCAIfaceCfg* cfg) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAHAL_t *phal = NULL; -- GUID *pcdc_guid = NULL; -- HDEVINFO dev_info; -- SP_DEVINFO_DATA dev_data; -- DWORD device_index = 0; -- DWORD required_size = 0; -- HKEY reg_key; -- DWORD reg_type = 0; -- TCHAR reg_data[256]; -- TCHAR cdc_data[256]; -- BOOL result = FALSE; -- LONG reg_result = 0; -- DCB dcb_settings; -- COMMTIMEOUTS comm_timeouts; -- int i = 0; -- int index = 0; -- -- // Check the input variables -- if ((hal == NULL) || (cfg == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Cast the hal to the ATCAHAL_t strucure -- phal = (ATCAHAL_t*)hal; -- -- // Initialize the _gCdc structure -- memset(&_gCdc, 0, sizeof(_gCdc)); -- for (i = 0; i < CDC_DEVICES_MAX; i++) -- { -- _gCdc.kits[i].read_handle = INVALID_HANDLE_VALUE; -- _gCdc.kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- -- _gCdc.num_kits_found = 0; -- -- // Get the number of available GUIDs -- result = SetupDiClassGuidsFromName(_T("Ports"), NULL, 0, &required_size); -- if (required_size == 0) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Allocated the memory the GUID list -- pcdc_guid = malloc(required_size * sizeof(GUID)); -- -- // Get the number of available GUIDs -- result = SetupDiClassGuidsFromName(_T("Ports"), pcdc_guid, required_size, &required_size); -- if (result == TRUE) -- { -- //Query the devices -- dev_info = SetupDiGetClassDevs(pcdc_guid, NULL, NULL, DIGCF_PRESENT); -- if (dev_info != INVALID_HANDLE_VALUE) -- { -- // Initialize the dev_data object -- memset(&dev_data, 0, sizeof(SP_DEVINFO_DATA)); -- dev_data.cbSize = sizeof(SP_DEVINFO_DATA); -- -- while (SetupDiEnumDeviceInfo(dev_info, device_index, &dev_data)) -- { -- // Get the USB CDC friendly name -- required_size = sizeof(reg_data); -- result = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_FRIENDLYNAME, ®_type, -- (PBYTE)reg_data, required_size, &required_size); -- if (result == TRUE) -- { -- // Determine if this is the correct kit USB CDC device -- if ((_tcsstr(reg_data, _T("AT90USB"))) || -- (_tcsstr(reg_data, _T("XPLAINED"))) || -- (_tcsstr(reg_data, _T("Class ASF")))) -- { -- // Get the registry key for the kit USB CDC device -- reg_key = SetupDiOpenDevRegKey(dev_info, &dev_data, DICS_FLAG_GLOBAL, -- 0, DIREG_DEV, KEY_QUERY_VALUE); -- if (reg_key != INVALID_HANDLE_VALUE) -- { -- // Get the port used with this kit USB CDC device -- required_size = sizeof(reg_data); -- reg_result = RegQueryValueEx(reg_key, _T("PortName"), NULL, NULL, -- (LPBYTE)reg_data, &required_size); -- if (reg_result == ERROR_SUCCESS) -- { -- _sntprintf_s(cdc_data, sizeof(cdc_data) / sizeof(cdc_data[0]), _TRUNCATE, _T("\\\\.\\%s"), reg_data); -- -- // Open the kit USB device for reading and writing -- if (_gCdc.kits[index].read_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(_gCdc.kits[index].read_handle); -- } -- _gCdc.kits[index].read_handle = INVALID_HANDLE_VALUE; -- _gCdc.kits[index].write_handle = INVALID_HANDLE_VALUE; -- -- _gCdc.kits[index].read_handle = CreateFile(cdc_data, -- GENERIC_READ | GENERIC_WRITE, -- 0, -- NULL, -- OPEN_EXISTING, -- FILE_ATTRIBUTE_NORMAL, -- NULL); -- _gCdc.kits[index].write_handle = _gCdc.kits[index].read_handle; -- -- if (_gCdc.kits[index].read_handle != INVALID_HANDLE_VALUE) -- { -- // Get the comm settings -- dcb_settings.DCBlength = sizeof(DCB); -- result = GetCommState(_gCdc.kits[index].read_handle, &dcb_settings); -- if (result == FALSE) -- { -- continue; -- } -- -- // Set the comm settings -- dcb_settings.BaudRate = cfg->atcauart.baud; -- dcb_settings.ByteSize = cfg->atcauart.wordsize; -- dcb_settings.StopBits = cfg->atcauart.stopbits; -- -- switch (cfg->atcauart.parity) -- { -- case 0: dcb_settings.Parity = EVENPARITY; -- case 1: dcb_settings.Parity = ODDPARITY; -- case 2: dcb_settings.Parity = NOPARITY; -- default: dcb_settings.Parity = NOPARITY; -- } -- -- result = SetCommState(_gCdc.kits[index].read_handle, &dcb_settings); -- if (result == FALSE) -- { -- continue; -- } -- -- // Set the comm timeout settings -- comm_timeouts.ReadIntervalTimeout = 3; -- comm_timeouts.ReadTotalTimeoutMultiplier = 3; -- comm_timeouts.ReadTotalTimeoutConstant = 2; -- comm_timeouts.WriteTotalTimeoutMultiplier = 3; -- comm_timeouts.WriteTotalTimeoutConstant = 2; -- -- SetCommTimeouts(_gCdc.kits[index].read_handle, &comm_timeouts); -- } -- -- // Increment the opened kit USB device index -- index++; -- } -- -- // Close the registry key -- RegCloseKey(reg_key); -- } -- } -- } -- -- // Break the while loop, if the maximum number of supported -- // kit USB devices have been found -- if (index == CDC_DEVICES_MAX) -- { -- break; -- } -- -- // Increment the device member index -- device_index++; -- } -- } -- -- // Delete device info now that we're done -- SetupDiDestroyDeviceInfoList(dev_info); -- } -- -- // Free allocated memory -- free(pcdc_guid); -- -- // Save the results of this discovery of HID -- if (index > 0) -- { -- _gCdc.num_kits_found = index; -- phal->hal_data = &_gCdc; -- return status; -- } -- return ATCA_NO_DEVICES; --} -- --/** \brief discover all CDC kits available.This function is currently not implemented. -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_cdc_discover_buses(int i2c_buses[], int max_buses) --{ -- // TODO: This should be set to the com port index(s) -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number.This function is currently not implemented. -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_cdc_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- // TODO: Add kitg protocol calls to discover all devices -- return ATCA_UNIMPLEMENTED; --} -- -- --/** \brief HAL implementation of Kit USB CDC post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_post_init(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- atcacdc_t* pHalDat = atgetifacehaldat(iface); -- ATCAIfaceCfg *pCfg = atgetifacecfg(iface); -- int i = 0; -- -- do -- { -- // Check the pointers -- if (pHalDat == NULL || pCfg == NULL) -- { -- status = ATCA_BAD_PARAM; -- BREAK(status, "NULL pointers in hal_kit_cdc_post_init"); -- } -- // Init all kit USB devices -- for (i = 0; i < pHalDat->num_kits_found; i++) -- { -- // Set the port -- pCfg->atcauart.port = i; -- // Perform the kit protocol init -- status = kit_init(iface); -- if (status != ATCA_SUCCESS) -- { -- BREAK(status, "kit_init() Failed"); -- } -- } -- } -- while (0); -- return status; --} -- --/** \brief HAL implementation of kit protocol send .It is called by the top layer. -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_send(ATCAIface iface, const char* txdata, int txlength) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int cdcid = cfg->atcauart.port; -- atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface); -- uint8_t buffer[CDC_BUFFER_MAX]; -- DWORD bytes_to_send = 0; -- DWORD bytes_left = 0; -- DWORD bytes_sent = 0; -- BOOL result = FALSE; -- -- if ((txdata == NULL) || (pCdc == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pCdc->kits[cdcid].write_handle == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- bytes_left = txlength; -- -- while (bytes_left > 0) -- { -- memset(buffer, 0, CDC_BUFFER_MAX); -- -- if (bytes_left >= CDC_BUFFER_MAX) -- { -- bytes_to_send = CDC_BUFFER_MAX; -- } -- else -- { -- bytes_to_send = bytes_left; -- } -- -- memcpy(&buffer[0], &txdata[(txlength - bytes_left)], bytes_to_send); -- -- result = WriteFile(pCdc->kits[cdcid].write_handle, buffer, bytes_to_send, &bytes_sent, NULL); -- if (result == FALSE) -- { -- return ATCA_TX_FAIL; -- } -- -- bytes_left -= bytes_sent; -- } -- return status; --} -- -- --/** \brief HAL implementation of kit protocol receive data.It is called by the top layer. -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxsize) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int cdcid = cfg->atcauart.port; -- atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface); -- uint8_t buffer[CDC_BUFFER_MAX] = { 0 }; -- BOOL continue_read = TRUE; -- DWORD bytes_read = 0; -- DWORD total_bytes = 0; -- BOOL result = true; -- uint8_t* location = NULL; -- int bytes_remain = 0; -- int bytes_to_copy = 0; -- int size_adjust = 0; -- -- // Verify the input variables -- if ((rxdata == NULL) || (rxsize == NULL) || (pCdc == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pCdc->kits[cdcid].read_handle == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- DWORD start_time_ms = GetTickCount(); -- while (continue_read == true) -- { -- // If the CDC port disappears while trying to read, ReadFile will continue to report -- // success and return 0 bytes. Same as when we're waiting for a reply. This lets the -- // operation timeout. -- if (GetTickCount() - start_time_ms > 3000) -- { -- // Close handles to force a quicker failure. -- CloseHandle(pCdc->kits[cdcid].read_handle); -- pCdc->kits[cdcid].read_handle = INVALID_HANDLE_VALUE; -- pCdc->kits[cdcid].write_handle = INVALID_HANDLE_VALUE; -- return ATCA_COMM_FAIL; -- } -- -- result = ReadFile(pCdc->kits[cdcid].read_handle, buffer, CDC_BUFFER_MAX, &bytes_read, NULL); -- if (result == FALSE) -- { -- return ATCA_RX_FAIL; -- } -- -- // Find the location of the '\n' character in read buffer -- // todo: generalize this read... it only applies if there is an ascii protocol with an of \n and if the exists -- location = strchr((char*)&buffer[0], '\n'); -- if (location == NULL) -- { -- // Copy all of the bytes -- bytes_to_copy = bytes_read; -- } -- else -- { -- // Copy only the bytes remaining in the read buffer to the -- bytes_to_copy = (int)(location - (char*)buffer); -- -- // The response has been received, stop receiving more data -- continue_read = false; -- } -- // Protect rxdata from overwriting, this will have the result of truncating the returned bytes -- // Remaining space in rxdata -- bytes_remain = (*rxsize - total_bytes); -- // Use the minimum between number of bytes read and remaining space -- bytes_to_copy = min(bytes_remain, bytes_to_copy); -- -- // Copy the received data -- memcpy(&rxdata[total_bytes], &buffer[0], bytes_to_copy); -- total_bytes += bytes_to_copy - size_adjust; -- } -- *rxsize = total_bytes; -- return ATCA_SUCCESS; --} -- --/** \brief Number of USB CDC devices found -- * \param[out] num_found Number of USB CDC devices found returned here -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_kit_phy_num_found(int8_t* num_found) --{ -- *num_found = _gCdc.num_kits_found; -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of kit protocol send over USB CDC -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_send(ATCAIface iface, uint8_t* txdata, int txlength) --{ -- // Call the hal_kit_send() function that will call hal_phy_send() implemented below -- return kit_send(iface, txdata, txlength); --} -- --/** \brief HAL implementation of kit protocol receive over USB CDC -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize) --{ -- // Call the hal_kit_receive() function that will call hal_phy_receive() implemented below -- return kit_receive(iface, rxdata, rxsize); --} -- --/** \brief Call the wake for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_wake(ATCAIface iface) --{ -- // Call the hal_kit_wake() function that will call hal_phy_send() and hal_phy_receive() -- return kit_wake(iface); --} -- --/** \brief Call the idle for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_idle(ATCAIface iface) --{ -- // Call the hal_kit_idle() function that will call hal_phy_send() and hal_phy_receive() -- return kit_idle(iface); --} -- --/** \brief Call the sleep for kit protocol over USB CDC -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_sleep(ATCAIface iface) --{ -- // Call the hal_kit_sleep() function that will call hal_phy_send() and hal_phy_receive() -- return kit_sleep(iface); --} -- --/** \brief Close the physical port for CDC -- * \param[in] hal_data The hardware abstraction data specific to this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_cdc_release(void* hal_data) --{ -- int i = 0; -- atcacdc_t* phaldat = (atcacdc_t*)hal_data; -- -- if ((hal_data == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Close all kit USB devices -- for (i = 0; i < phaldat->num_kits_found; i++) -- { -- if (phaldat->kits[i].read_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(phaldat->kits[i].read_handle); -- phaldat->kits[i].read_handle = INVALID_HANDLE_VALUE; -- phaldat->kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- } -- return ATCA_SUCCESS; --} -- --/** \brief discover cdc buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge.This function is currently not implemented. -- * \param[in] cdc_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ -- --ATCA_STATUS hal_kit_cdc_discover_buses(int cdc_buses[], int max_buses) --{ -- // TODO: Implement -- return ATCA_UNIMPLEMENTED; --} -- -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_kit_cdc_discover_devices(int busNum, ATCAIfaceCfg *cfg, int *found) --{ -- // TODO: Implement -- *found = 0; -- return ATCA_UNIMPLEMENTED; --} -\ No newline at end of file -diff --git a/lib/hal/hal_win_kit_cdc.h b/lib/hal/hal_win_kit_cdc.h -deleted file mode 100644 -index 8970d54965e2..000000000000 ---- a/lib/hal/hal_win_kit_cdc.h -+++ /dev/null -@@ -1,58 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Windows using kit protocol over a USB CDC device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_WIN_KIT_CDC_H_ --#define HAL_WIN_KIT_CDC_H_ -- --#include -- --// Kit USB defines --#define CDC_DEVICES_MAX 10 //! Maximum number of supported Kit USB devices --#define CDC_BUFFER_MAX 1024 //! Maximum number of bytes read per port read -- -- --// Each device that is found will have a read handle and a write handle --typedef struct cdc_device --{ -- HANDLE read_handle; //! The kit USB read file handle -- HANDLE write_handle; //! The kit USB write file handle --} cdc_device_t; -- -- --// A structure to hold CDC information --typedef struct atcacdc --{ -- cdc_device_t kits[CDC_DEVICES_MAX]; -- int8_t num_kits_found; --} atcacdc_t; -- --#endif /* HAL_WIN_KIT_CDC_H_ */ -- -diff --git a/lib/hal/hal_win_kit_hid.c b/lib/hal/hal_win_kit_hid.c -deleted file mode 100644 -index 44b52120bbee..000000000000 ---- a/lib/hal/hal_win_kit_hid.c -+++ /dev/null -@@ -1,469 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Windows using kit protocol over a USB HID device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include "atca_hal.h" --#include "hal_win_kit_hid.h" --#include "kit_protocol.h" --#include "kit_phy.h" --#include --#include --#include --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// File scope globals --atcahid_t _gHid; -- --// The HID GUID filter --#define HID_GUID { 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } -- -- -- --/** \brief HAL implementation of Kit USB HID init -- * \param[in] hal pointer to HAL specific data that is maintained by this HAL -- * \param[in] cfg pointer to HAL specific configuration data that is used to initialize this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_init(void* hal, ATCAIfaceCfg* cfg) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAHAL_t *phal = NULL; -- GUID hid_guid = HID_GUID; -- HDEVINFO dev_info; -- SP_DEVICE_INTERFACE_DATA dev_data; -- PSP_DEVICE_INTERFACE_DETAIL_DATA dev_detail_data; -- DWORD required_size = 0; -- BOOL result = FALSE; -- DWORD device_index = 0; -- int i = 0; -- int index = 0; -- TCHAR hid_filter[32]; -- -- // Check the input variables -- if ((hal == NULL) || (cfg == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Cast the hal to the ATCAHAL_t strucure -- phal = (ATCAHAL_t*)hal; -- -- // Initialize the _gHid structure -- memset(&_gHid, 0, sizeof(_gHid)); -- for (i = 0; i < HID_DEVICES_MAX; i++) -- { -- _gHid.kits[i].read_handle = INVALID_HANDLE_VALUE; -- _gHid.kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- -- _gHid.num_kits_found = 0; -- -- // Initialize the GUID --// UuidFromString(cfg->atcahid.guid, &hid_guid); -- -- // Query the devices -- dev_info = SetupDiGetClassDevs(&hid_guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); -- if (dev_info == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- // Initialize the dev_data object -- memset(&dev_data, 0, sizeof(SP_DEVICE_INTERFACE_DATA)); -- dev_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); -- -- // Construct the filter string -- memset(hid_filter, 0, sizeof(hid_filter)); -- _stprintf(hid_filter, _T("vid_%04x&pid_%04x"), cfg->atcahid.vid, cfg->atcahid.pid); -- -- // Find the Atmel kit USB devices -- while (SetupDiEnumDeviceInterfaces(dev_info, NULL, &hid_guid, device_index, &dev_data)) -- { -- // Get the required buffer size of the detailed data -- SetupDiGetDeviceInterfaceDetail(dev_info, &dev_data, NULL, 0, &required_size, NULL); -- -- // Allocate the required space for the detailed interface data -- dev_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(required_size); -- -- // Retrieve the detailed interface data -- dev_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); -- result = SetupDiGetDeviceInterfaceDetail(dev_info, &dev_data, dev_detail_data, -- required_size, &required_size, NULL); -- -- // Determine if this is the correct kit USB device -- -- if (_tcsstr(dev_detail_data->DevicePath, hid_filter) != NULL) -- { -- // Open the kit USB device for reading and writing -- if (_gHid.kits[index].read_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(_gHid.kits[index].read_handle); -- } -- if (_gHid.kits[index].write_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(_gHid.kits[index].write_handle); -- } -- -- _gHid.kits[index].read_handle = CreateFile(dev_detail_data->DevicePath, -- GENERIC_READ, -- (FILE_SHARE_READ | FILE_SHARE_WRITE), -- NULL, -- OPEN_EXISTING, -- 0, -- NULL); -- _gHid.kits[index].write_handle = CreateFile(dev_detail_data->DevicePath, -- GENERIC_WRITE, -- (FILE_SHARE_READ | FILE_SHARE_WRITE), -- NULL, -- OPEN_EXISTING, -- 0, -- NULL); -- -- // Increment the opened kit USB device index -- index++; -- } -- // Deallocate the required space for the detailed interface data -- free(dev_detail_data); -- -- // Break the while loop, if the maximum number of supported -- // kit USB devices have been found -- if (index == HID_DEVICES_MAX) -- { -- break; -- } -- -- // Increment the device member index -- device_index++; -- } -- -- // Delete device info now that we're done -- SetupDiDestroyDeviceInfoList(dev_info); -- -- // Save the results of this discovery of HID -- if (index > 0) -- { -- _gHid.num_kits_found = index; -- phal->hal_data = &_gHid; -- } -- return status; --} -- -- --/** \brief discover all HID kits available.This function is currently not implemented. -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] cdc_buses an array of logical bus numbers -- * \param[in] max_buses maximum number of buses the app wants to attempt to discover -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_kit_hid_discover_buses(int cdc_buses[], int max_buses) --{ -- // TODO: This should be set to the com port index(s) -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number.This function is currently not implemented. -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_UNIMPLEMENTED -- */ --ATCA_STATUS hal_kit_hid_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- // TODO: Add kitg protocol calls to discover all devices -- return ATCA_UNIMPLEMENTED; --} -- --/** \brief HAL implementation of Kit HID post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_post_init(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- atcahid_t* pHid = atgetifacehaldat(iface); -- ATCAIfaceCfg *pCfg = atgetifacecfg(iface); -- int i = 0; -- -- do -- { -- // Check the pointers -- if (pHid == NULL || pCfg == NULL) -- { -- status = ATCA_BAD_PARAM; -- BREAK(status, "NULL pointers in hal_kit_hid_post_init"); -- } -- // Init all kit USB HID devices -- for (i = 0; i < pHid->num_kits_found; i++) -- { -- // Perform the kit protocol init -- status = kit_init(iface); -- if (status != ATCA_SUCCESS) -- { -- BREAK(status, "kit_init() Failed"); -- } -- } -- -- } -- while (0); -- return status; --} -- --/** \brief HAL implementation of kit protocol send .It is called by the top layer. -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_send(ATCAIface iface, const char* txdata, int txlength) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int hidid = cfg->atcahid.idx; -- atcahid_t* pHid = (atcahid_t*)atgetifacehaldat(iface); -- uint8_t buffer[HID_PACKET_MAX]; -- DWORD bytes_to_send = 0; -- DWORD bytes_left = 0; -- DWORD bytes_sent = 0; -- BOOL result = FALSE; -- -- if ((txdata == NULL) || (pHid == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pHid->kits[hidid].write_handle == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- bytes_left = txlength; -- -- while (bytes_left > 0) -- { -- memset(buffer, 0, (HID_PACKET_MAX)); -- -- if (bytes_left >= cfg->atcahid.packetsize) -- { -- bytes_to_send = cfg->atcahid.packetsize; -- } -- else -- { -- bytes_to_send = bytes_left; -- } -- -- memcpy(&buffer[1], &txdata[(txlength - bytes_left)], bytes_to_send); -- -- result = WriteFile(pHid->kits[hidid].write_handle, buffer, (cfg->atcahid.packetsize + 1), &bytes_sent, NULL); -- if (result == FALSE) -- { -- return ATCA_TX_FAIL; -- } -- -- bytes_left -= bytes_to_send; -- } -- return status; --} -- --/** \brief HAL implementation of kit protocol receive data.It is called by the top layer. -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxsize) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int hidid = cfg->atcahid.idx; -- atcahid_t* pHid = (atcahid_t*)atgetifacehaldat(iface); -- uint8_t buffer[HID_PACKET_MAX] = { 0 }; -- BOOL continue_read = TRUE; -- DWORD bytes_read = 0; -- DWORD total_bytes = 0; -- BOOL result = true; -- char* location = NULL; -- int bytes_remain = 0; -- int bytes_to_cpy = 0; -- int size_adjust = 0; -- -- // Verify the input variables -- if ((rxdata == NULL) || (rxsize == NULL) || (pHid == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- if (pHid->kits[hidid].read_handle == INVALID_HANDLE_VALUE) -- { -- return ATCA_COMM_FAIL; -- } -- -- while (continue_read == true) -- { -- result = ReadFile(pHid->kits[hidid].read_handle, buffer, (cfg->atcahid.packetsize + 1), &bytes_read, NULL); -- if (result == false) -- { -- return ATCA_RX_FAIL; -- } -- // Find the location of the '\n' character in read buffer -- // todo: generalize this read... it only applies if there is an ascii protocol with an of \n and if the exists -- location = strchr((char*)&buffer[1], '\n'); -- if (location == NULL) -- { -- // Copy all of the bytes -- bytes_to_cpy = bytes_read; -- // An extra byte is prepended to HID communication -- size_adjust = 1; -- } -- else -- { -- // Copy only the bytes remaining in the read buffer to the -- bytes_to_cpy = (uint8_t)(location - (char*)buffer); -- size_adjust = 0; -- // The response has been received, stop receiving more data -- continue_read = false; -- } -- // Protect rxdata from overwriting, this will have the result of truncating the returned bytes -- // Remaining space in rxdata -- bytes_remain = (*rxsize - total_bytes); -- // Use the minimum between number of bytes read and remaining space -- bytes_to_cpy = min(bytes_remain, bytes_to_cpy); -- -- // Copy the received data -- memcpy(&rxdata[total_bytes], &buffer[1], bytes_to_cpy); -- total_bytes += bytes_to_cpy - size_adjust; -- } -- *rxsize = total_bytes; -- return ATCA_SUCCESS; --} -- --/** \brief Number of USB HID devices found -- * \param[out] num_found -- * \return SUCCESS -- */ --ATCA_STATUS kit_phy_num_found(int8_t* num_found) --{ -- *num_found = _gHid.num_kits_found; -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of kit protocol send over USB HID -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_send(ATCAIface iface, uint8_t* txdata, int txlength) --{ -- // Call the kit_send() function that will call phy_send() implemented below -- return kit_send(iface, txdata, txlength); --} -- --/** \brief HAL implementation of send over USB HID -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize) --{ -- // Call the kit_receive() function that will call phy_receive() implemented below -- return kit_receive(iface, rxdata, rxsize); --} -- --/** \brief Call the wake for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_wake(ATCAIface iface) --{ -- // Call the kit_wake() function that will call phy_send() and phy_receive() -- return kit_wake(iface); --} -- --/** \brief Call the idle for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_idle(ATCAIface iface) --{ -- // Call the kit_idle() function that will call phy_send() and phy_receive() -- return kit_idle(iface); --} -- --/** \brief Call the sleep for kit protocol over USB HID -- * \param[in] iface ATCAIface instance that is the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_sleep(ATCAIface iface) --{ -- // Call the kit_sleep() function that will call phy_send() and phy_receive() -- return kit_sleep(iface); --} -- --/** \brief Close the physical port for HID -- * \param[in] hal_data The hardware abstraction data specific to this HAL -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_kit_hid_release(void* hal_data) --{ -- int i = 0; -- atcahid_t* phaldat = (atcahid_t*)hal_data; -- -- if ((hal_data == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Close all kit USB devices -- for (i = 0; i < phaldat->num_kits_found; i++) -- { -- if (phaldat->kits[i].read_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(phaldat->kits[i].read_handle); -- phaldat->kits[i].read_handle = INVALID_HANDLE_VALUE; -- } -- -- if (phaldat->kits[i].write_handle != INVALID_HANDLE_VALUE) -- { -- CloseHandle(phaldat->kits[i].write_handle); -- phaldat->kits[i].write_handle = INVALID_HANDLE_VALUE; -- } -- } -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_win_kit_hid.h b/lib/hal/hal_win_kit_hid.h -deleted file mode 100644 -index e3523272d33a..000000000000 ---- a/lib/hal/hal_win_kit_hid.h -+++ /dev/null -@@ -1,64 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for Windows using kit protocol over a USB HID device. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_WIN_KIT_HID_H_ --#define HAL_WIN_KIT_HID_H_ -- --#include -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// Kit USB defines --#define HID_DEVICES_MAX 10 //! Maximum number of supported Kit USB devices --#define HID_PACKET_MAX 512 //! Maximum number of bytes for a HID send/receive packet (typically 64) -- --// Each device that is found will have a read handle and a write handle --typedef struct hid_device --{ -- HANDLE read_handle; //! The kit USB read file handle -- HANDLE write_handle; //! The kit USB write file handle --} hid_device_t; -- -- --// A structure to hold HID information --typedef struct atcahid --{ -- hid_device_t kits[HID_DEVICES_MAX]; -- int8_t num_kits_found; --} atcahid_t; -- --/** @} */ --#endif /* HAL_WIN_KIT_HID_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_win_timer.c b/lib/hal/hal_win_timer.c -deleted file mode 100644 -index 71c431b4354b..000000000000 ---- a/lib/hal/hal_win_timer.c -+++ /dev/null -@@ -1,86 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for windows timer functions. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of microseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // divide by 1000 to convert us to ms -- // todo: use a timer with us accuracy -- long ms = (long)(delay / 1.0e3 + 0.5); // Miliseconds -- -- // use Windows supplied delay -- Sleep(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // divide by 100 to convert 10's of us to ms -- // todo: use a timer with us accuracy -- long ms = (long)(delay / 1.0e2 + 0.5); // Miliseconds -- -- // use Windows supplied delay -- Sleep(delay); --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use Windows supplied delay -- Sleep(delay); --} -- --/** @} */ -diff --git a/lib/hal/hal_xmega_a3bu_i2c_asf.c b/lib/hal/hal_xmega_a3bu_i2c_asf.c -deleted file mode 100644 -index 2d8fa71c9b21..000000000000 ---- a/lib/hal/hal_xmega_a3bu_i2c_asf.c -+++ /dev/null -@@ -1,520 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for XMEGA-A3BU I2C over ASF drivers. -- * -- * Prerequisite: add I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include --#include "atca_hal.h" --#include "hal_xmega_a3bu_i2c_asf.h" --#include "atca_device.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- --/** \brief logical to physical bus mapping structure */ --ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index --int i2c_bus_ref_ct = 0; // total in-use count across buses --static twi_master_options_t config_i2c_master; -- -- --/** \brief discover i2c buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] i2c_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) --{ -- -- /* if every PORT was a likely candidate bus, then would need to initialize the entire array to all PORT n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / PORT map based on XMEGA-A3BU Xplained Pro board -- * If you were using a raw XMEGA on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ -- i2c_buses[0] = 2; // default xmega-a3bu for xplained dev board -- -- return ATCA_SUCCESS; --} -- --/** \brief discover any CryptoAuth devices on a given logical bus number -- * \param[in] busNum - logical bus number on which to look for CryptoAuth devices -- * \param[out] cfg[] - pointer to head of an array of interface config structures which get filled in by this method -- * \param[out] *found - number of devices found on this bus -- * \return ATCA_SUCCESS -- */ -- --ATCA_STATUS hal_i2c_discover_devices(int busNum, ATCAIfaceCfg cfg[], int *found) --{ -- ATCAIfaceCfg *head = cfg; -- uint8_t slaveAddress = 0x01; -- ATCADevice device; -- ATCAIface discoverIface; -- ATCACommand command; -- ATCAPacket packet; -- ATCA_STATUS status; -- uint8_t revs508[1][4] = { { 0x00, 0x00, 0x50, 0x00 } }; -- uint8_t revs108[1][4] = { { 0x80, 0x00, 0x10, 0x01 } }; -- uint8_t revs204[3][4] = { { 0x00, 0x02, 0x00, 0x08 }, -- { 0x00, 0x02, 0x00, 0x09 }, -- { 0x00, 0x04, 0x05, 0x00 } }; -- int i; -- -- /** \brief default configuration, to be reused during discovery process */ -- ATCAIfaceCfg discoverCfg = { -- .iface_type = ATCA_I2C_IFACE, -- .devtype = ATECC508A, -- .atcai2c.slave_address = 0x07, -- .atcai2c.bus = busNum, -- .atcai2c.baud = 400000, -- //.atcai2c.baud = 100000, -- .wake_delay = 800, -- .rx_retries = 3 -- }; -- -- // build an info command -- packet.param1 = INFO_MODE_REVISION; -- packet.param2 = 0; -- -- device = newATCADevice(&discoverCfg); -- discoverIface = atGetIFace(device); -- command = atGetCommands(device); -- -- // iterate through all addresses on given i2c bus -- // all valid 7-bit addresses go from 0x07 to 0x78 -- for (slaveAddress = 0x07; slaveAddress <= 0x78; slaveAddress++) -- { -- discoverCfg.atcai2c.slave_address = slaveAddress << 1; // turn it into an 8-bit address which is what the rest of the i2c HAL is expecting when a packet is sent -- -- // wake up device -- // If it wakes, send it a dev rev command. Based on that response, determine the device type -- // BTW - this will wake every cryptoauth device living on the same bus (ecc508a, sha204a) -- -- if (hal_i2c_wake(discoverIface) == ATCA_SUCCESS) -- { -- (*found)++; -- memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg)); -- -- memset(packet.data, 0x00, sizeof(packet.data)); -- -- // get devrev info and set device type accordingly -- atInfo(command, &packet); -- if ((status = atGetExecTime(packet.opcode, command)) != ATCA_SUCCESS) -- { -- continue; -- } -- -- // send the command -- if ( (status = atsend(discoverIface, (uint8_t*)&packet, packet.txsize)) != ATCA_SUCCESS) -- { -- printf("packet send error\r\n"); -- continue; -- } -- -- // delay the appropriate amount of time for command to execute -- atca_delay_ms((command->execution_time_msec) + 1); -- -- // receive the response -- if ( (status = atreceive(discoverIface, &(packet.data[0]), &(packet.rxsize) )) != ATCA_SUCCESS) -- { -- continue; -- } -- -- if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS) -- { -- printf("command response error\r\n"); -- continue; -- } -- -- // determine device type from common info and dev rev response byte strings -- for (i = 0; i < sizeof(revs508) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs508[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC508A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs204) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs204[i], 4) == 0) -- { -- discoverCfg.devtype = ATSHA204A; -- break; -- } -- } -- -- for (i = 0; i < sizeof(revs108) / 4; i++) -- { -- if (memcmp(&packet.data[1], &revs108[i], 4) == 0) -- { -- discoverCfg.devtype = ATECC108A; -- break; -- } -- } -- -- atca_delay_ms(15); -- // now the device type is known, so update the caller's cfg array element with it -- head->devtype = discoverCfg.devtype; -- head++; -- } -- -- hal_i2c_idle(discoverIface); -- } -- -- deleteATCADevice(&device); -- -- return ATCA_SUCCESS; --} -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF I2C libraries in your project, otherwise, -- the HAL layer will not compile because the ASF I2C drivers are a dependency * -- */ -- --/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface -- * has released the physical layer, it will disable the interface for some other use. -- * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on -- * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. -- */ -- --/** \brief initialize an I2C interface using given config -- * \param[in] hal - opaque ptr to HAL data -- * \param[in] cfg - interface configuration -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) --{ -- int bus = cfg->atcai2c.bus; // 0-based logical bus number -- ATCAHAL_t *phal = (ATCAHAL_t*)hal; -- -- if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used -- { -- for (int i = 0; i < MAX_I2C_BUSES; i++) -- { -- i2c_hal_data[i] = NULL; -- } -- } -- -- i2c_bus_ref_ct++; // total across buses -- -- if (bus >= 0 && bus < MAX_I2C_BUSES) -- { -- // if this is the first time this bus and interface has been created, do the physical work of enabling it -- if (i2c_hal_data[bus] == NULL) -- { -- i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); -- i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance -- -- config_i2c_master.speed = cfg->atcai2c.baud; -- config_i2c_master.chip = 0x50; -- config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), cfg->atcai2c.baud); -- switch (bus) -- { -- case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break; -- //case 1: i2c_hal_data[bus]->i2c_master_instance = &TWID; break; // for XMEGA-A1 -- case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break; -- //case 3: i2c_hal_data[bus]->i2c_master_instance = &TWIF; break; // for XMEGA-A1 -- } -- -- twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); -- // store this for use during the release phase -- i2c_hal_data[bus]->bus_index = bus; -- twi_master_enable(i2c_hal_data[bus]->i2c_master_instance); -- } -- else -- { -- // otherwise, another interface already initialized the bus, so this interface will share it and any different -- // cfg parameters will be ignored...first one to initialize this sets the configuration -- i2c_hal_data[bus]->ref_ct++; -- } -- -- phal->hal_data = i2c_hal_data[bus]; -- -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief HAL implementation of I2C post init -- * \param[in] iface instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS hal_i2c_post_init(ATCAIface iface) --{ -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C send over ASF -- * \param[in] iface instance -- * \param[in] txdata pointer to space to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address -- .buffer = txdata, // transfer data source buffer -- .length = txlength, // transfer data size (bytes) -- }; -- -- // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format -- -- // other device types that don't require i/o tokens on the front end of a command need a different hal_i2c_send and wire it up instead of this one -- // this covers devices such as ATSHA204A and ATECCx08A that require a word address value pre-pended to the packet -- // txdata[0] is using _reserved byte of the ATCAPacket -- txdata[0] = 0x03; // insert the Word Address Value, Command token -- txlength++; // account for word address value byte. -- packet.length = txlength; -- -- if (twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief HAL implementation of I2C receive function for ASF I2C -- * \param[in] iface instance -- * \param[out] rxdata pointer to space to receive the data -- * \param[in] rxlength ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- int status = !STATUS_OK; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address -- .buffer = rxdata, // transfer data source buffer -- .length = *rxlength, // transfer data size (bytes) -- }; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief method to change the bus speec of I2C -- * \param[in] iface interface on which to change bus speed -- * \param[in] speed baud rate (typically 100000 or 400000) -- */ -- --void change_i2c_speed(ATCAIface iface, uint32_t speed) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- -- config_i2c_master.speed = speed; -- config_i2c_master.speed_reg = TWI_BAUD(sysclk_get_cpu_hz(), speed); -- -- twi_master_disable(i2c_hal_data[bus]->i2c_master_instance); -- -- switch (bus) -- { -- case 0: i2c_hal_data[bus]->i2c_master_instance = &TWIC; break; -- case 2: i2c_hal_data[bus]->i2c_master_instance = &TWIE; break; -- } -- -- twi_master_setup((i2c_hal_data[bus]->i2c_master_instance), &config_i2c_master); -- -- twi_master_enable(i2c_hal_data[bus]->i2c_master_instance); --} -- --/** \brief wake up CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to wakeup -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_wake(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- int retries = cfg->rx_retries; -- uint32_t bdrt = cfg->atcai2c.baud; -- int status = !STATUS_OK; -- uint8_t data[4], expected[4] = { 0x04, 0x11, 0x33, 0x43 }; -- -- if (bdrt != 100000) // if not already at 100KHz, change it -- { -- change_i2c_speed(iface, 100000); -- } -- -- // Send the wake by writing to an address of 0x00 -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = 0x00, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 0 // transfer data size (bytes) -- }; -- -- -- // Send the 00 address as the wake pulse -- twi_master_write(i2c_hal_data[bus]->i2c_master_instance, &packet); // part will NACK, so don't check for status -- -- atca_delay_us(cfg->wake_delay); // wait tWHI + tWLO which is configured based on device type and configuration structure -- -- packet.chip = cfg->atcai2c.slave_address >> 1; -- packet.length = 4; -- packet.buffer = data; -- -- while (retries-- > 0 && status != STATUS_OK) -- { -- status = twi_master_read(i2c_hal_data[bus]->i2c_master_instance, &packet); -- } -- -- if (status != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- // if necessary, revert baud rate to what came in. -- if (bdrt != 100000) -- { -- change_i2c_speed(iface, bdrt); -- } -- -- if (memcmp(data, expected, 4) == 0) -- { -- return ATCA_SUCCESS; -- } -- -- return ATCA_COMM_FAIL; --} -- --/** \brief idle CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to idle -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_idle(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 1 // transfer data size (bytes) -- }; -- -- data[0] = 0x02; // idle word address value -- if (twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; -- --} -- --/** \brief sleep CryptoAuth device using I2C bus -- * \param[in] iface interface to logical device to sleep -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_sleep(ATCAIface iface) --{ -- ATCAIfaceCfg *cfg = atgetifacecfg(iface); -- int bus = cfg->atcai2c.bus; -- uint8_t data[4]; -- -- twi_package_t packet = { -- .addr_length = 0, // TWI slave memory address data size -- .chip = cfg->atcai2c.slave_address >> 1, // TWI slave bus address -- .buffer = &data[0], // transfer data source buffer -- .length = 1 // transfer data size (bytes) -- }; -- -- data[0] = 0x01; // sleep word address value -- if (twi_master_write((i2c_hal_data[bus]->i2c_master_instance), &packet) != STATUS_OK) -- { -- return ATCA_COMM_FAIL; -- } -- -- return ATCA_SUCCESS; --} -- --/** \brief manages reference count on given bus and releases resource if no more refences exist -- * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ -- --ATCA_STATUS hal_i2c_release(void *hal_data) --{ -- ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; -- -- i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging -- -- // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release -- if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) -- { -- twi_master_disable(hal->i2c_master_instance); -- free(i2c_hal_data[hal->bus_index]); -- i2c_hal_data[hal->bus_index] = NULL; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/hal_xmega_a3bu_i2c_asf.h b/lib/hal/hal_xmega_a3bu_i2c_asf.h -deleted file mode 100644 -index 4617c739245d..000000000000 ---- a/lib/hal/hal_xmega_a3bu_i2c_asf.h -+++ /dev/null -@@ -1,64 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for XMEGA-A3BU I2C over ASF drivers. -- * -- * Prerequisite: add I2C Master Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef HAL_XMEGA_A3BU_I2C_ASF_H_ --#define HAL_XMEGA_A3BU_I2C_ASF_H_ -- --#include --#include "twi_master.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * using I2C driver of ASF. -- * -- @{ */ -- -- --#define MAX_I2C_BUSES 4 // XMEGA A3BU has up to 4 PORT that can be configured as I2C -- --/** \brief this is the hal_data for ATCA HAL created using ASF -- */ --typedef struct atcaI2Cmaster --{ -- twi_master_t i2c_master_instance; -- int ref_ct; -- // for conveniences during interface release phase -- int bus_index; --} ATCAI2CMaster_t; -- --void change_i2c_speed(ATCAIface iface, uint32_t speed); -- --/** @} */ --#endif /* HAL_XMEGA_A3BU_I2C_ASF_H_ */ -\ No newline at end of file -diff --git a/lib/hal/hal_xmega_a3bu_timer_asf.c b/lib/hal/hal_xmega_a3bu_timer_asf.c -deleted file mode 100644 -index e2f4a4337e03..000000000000 ---- a/lib/hal/hal_xmega_a3bu_timer_asf.c -+++ /dev/null -@@ -1,78 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer for SAMD21 timer/delay over ASF drivers. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "atca_hal.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief This function delays for a number of microseconds. -- * -- * \param[in] delay number of 0.001 milliseconds to delay -- */ --void atca_delay_us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay); --} -- --/** \brief This function delays for a number of tens of microseconds. -- * -- * \param[in] delay number of 0.01 milliseconds to delay -- */ --void atca_delay_10us(uint32_t delay) --{ -- // use ASF supplied delay -- delay_us(delay * 10); -- --} -- --/** \brief This function delays for a number of milliseconds. -- * -- * You can override this function if you like to do -- * something else in your system while delaying. -- * \param[in] delay number of milliseconds to delay -- */ -- --/* ASF already has delay_ms - see delay.h */ --void atca_delay_ms(uint32_t delay) --{ -- // use ASF supplied delay -- delay_ms(delay); --} -- --/** @} */ -diff --git a/lib/hal/i2c_bitbang_samd21.c b/lib/hal/i2c_bitbang_samd21.c -deleted file mode 100644 -index 0cdac42912b9..000000000000 ---- a/lib/hal/i2c_bitbang_samd21.c -+++ /dev/null -@@ -1,262 +0,0 @@ --/** -- * \file -- * \brief Hardware Interface Functions - I2C bit-bang for SAMd21 -- * \author Atmel Crypto Group -- * \date November 18, 2015 -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "i2c_bitbang_samd21.h" --#define DEFAULT_I2C_BUS 2 -- -- --I2CBuses i2c_buses_default = { -- { EXT3_PIN_3, EXT3_PIN_9, EXT3_PIN_I2C_SDA, EXT3_PIN_13, EXT2_PIN_3, EXT2_PIN_5, EXT2_PIN_7, EXT2_PIN_9, EXT2_PIN_13, EXT2_PIN_15, EXT2_PIN_17, EXT1_PIN_3, EXT1_PIN_5, EXT1_PIN_7, EXT1_PIN_9, EXT1_PIN_13, EXT1_PIN_15, EXT1_PIN_17 }, -- { EXT3_PIN_7, EXT3_PIN_10, EXT3_PIN_I2C_SCL, EXT3_PIN_14, EXT2_PIN_4, EXT2_PIN_6, EXT2_PIN_8, EXT2_PIN_10, EXT2_PIN_14, EXT2_PIN_16, EXT2_PIN_18, EXT1_PIN_4, EXT1_PIN_6, EXT1_PIN_8, EXT1_PIN_10, EXT1_PIN_14, EXT1_PIN_16, EXT1_PIN_18 } --}; -- --uint8_t pin_sda, pin_scl; -- --void i2c_discover_buses(int i2c_bitbang_buses[], int max_buses) --{ -- -- i2c_bitbang_buses[0] = DEFAULT_I2C_BUS; -- --} -- --void i2c_set_pin(uint8_t sda, uint8_t scl) --{ -- pin_sda = sda; -- pin_scl = scl; --} -- --void i2c_enable(void) --{ -- I2C_ENABLE(); -- I2C_DATA_HIGH(); -- I2C_CLOCK_HIGH(); --} -- --void i2c_disable(void) --{ -- I2C_DISABLE(); --} -- -- --void i2c_send_start(void) --{ -- //! Set clock high in case we re-start. -- I2C_CLOCK_HIGH(); -- I2C_SET_OUTPUT_HIGH(); -- I2C_DATA_LOW(); -- I2C_HOLD_DELAY(); -- I2C_CLOCK_LOW(); --} -- --void i2c_send_ack(uint8_t ack) --{ -- if (ack) -- { -- I2C_SET_OUTPUT_LOW(); //!< Low data line indicates an ACK. -- while (I2C_DATA_IN()) -- { -- ; -- } -- } -- else -- { -- I2C_SET_OUTPUT_HIGH(); //!< High data line indicates a NACK. -- while (!I2C_DATA_IN()) -- { -- ; -- } -- } -- -- //! Clock out acknowledgment. -- I2C_CLOCK_HIGH(); -- I2C_CLOCK_DELAY_SEND_ACK(); -- I2C_CLOCK_LOW(); --} -- --void i2c_send_stop(void) --{ -- I2C_SET_OUTPUT_LOW(); -- I2C_CLOCK_DELAY_WRITE_LOW(); -- I2C_CLOCK_HIGH(); -- I2C_HOLD_DELAY(); -- I2C_DATA_HIGH(); --} -- -- --void i2c_send_wake_token(void) --{ -- I2C_DATA_LOW(); -- delay_us(80); -- I2C_DATA_HIGH(); --} -- --ATCA_STATUS i2c_send_byte(uint8_t i2c_byte) --{ -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- uint8_t i; -- -- DISABLE_INTERRUPT(); -- -- //! This avoids spikes but adds an if condition. -- //! We could parametrize the call to I2C_SET_OUTPUT -- //! and translate the msb to OUTSET or OUTCLR, -- //! but then the code would become target specific. -- if (i2c_byte & 0x80) -- { -- I2C_SET_OUTPUT_HIGH(); -- } -- else -- { -- I2C_SET_OUTPUT_LOW(); -- } -- -- //! Send 8 bits of data. -- for (i = 0; i < 8; i++) -- { -- I2C_CLOCK_LOW(); -- if (i2c_byte & 0x80) -- { -- I2C_DATA_HIGH(); -- } -- else -- { -- I2C_DATA_LOW(); -- } -- I2C_CLOCK_DELAY_WRITE_LOW(); -- -- //! Clock out the data bit. -- I2C_CLOCK_HIGH(); -- -- //! Shifting while clock is high compensates for the time it -- //! takes to evaluate the bit while clock is low. -- //! That way, the low and high time of the clock pin is -- //! almost equal. -- i2c_byte <<= 1; -- I2C_CLOCK_DELAY_WRITE_HIGH(); -- } -- //! Clock in last data bit. -- I2C_CLOCK_LOW(); -- -- //! Set data line to be an input. -- I2C_SET_INPUT(); -- -- I2C_CLOCK_DELAY_READ_LOW(); -- //! Wait for the ack. -- I2C_CLOCK_HIGH(); -- for (i = 0; i < I2C_ACK_TIMEOUT; i++) -- { -- if (!I2C_DATA_IN()) -- { -- status = ATCA_SUCCESS; -- I2C_CLOCK_DELAY_READ_HIGH(); -- break; -- } -- } -- I2C_CLOCK_LOW(); -- -- ENABLE_INTERRUPT(); -- -- return status; --} -- --ATCA_STATUS i2c_send_bytes(uint8_t count, uint8_t *data) --{ -- ATCA_STATUS status = ATCA_TX_TIMEOUT; -- -- uint8_t i; -- -- for (i = 0; i < count; i++) -- { -- status = i2c_send_byte(data[i]); -- if (status != ATCA_SUCCESS) -- { -- if (i > 0) -- { -- status = ATCA_TX_FAIL; -- } -- break; -- } -- } -- -- return status; --} -- --uint8_t i2c_receive_one_byte(uint8_t ack) --{ -- uint8_t i2c_byte; -- uint8_t i; -- -- DISABLE_INTERRUPT(); -- -- I2C_SET_INPUT(); -- for (i = 0x80, i2c_byte = 0; i; i >>= 1) -- { -- I2C_CLOCK_HIGH(); -- I2C_CLOCK_DELAY_READ_HIGH(); -- if (I2C_DATA_IN()) -- { -- i2c_byte |= i; -- } -- I2C_CLOCK_LOW(); -- if (i > 1) -- { -- //! We don't need to delay after the last bit because -- //! it takes time to switch the pin to output for acknowledging. -- I2C_CLOCK_DELAY_READ_LOW(); -- } -- } -- i2c_send_ack(ack); -- -- ENABLE_INTERRUPT(); -- -- return i2c_byte; --} -- --void i2c_receive_byte(uint8_t *data) --{ -- *data = i2c_receive_one_byte(1); --} -- --void i2c_receive_bytes(uint8_t count, uint8_t *data) --{ -- while (--count) -- { -- *data++ = i2c_receive_one_byte(1); -- } -- *data = i2c_receive_one_byte(0); -- -- i2c_send_stop(); --} -\ No newline at end of file -diff --git a/lib/hal/i2c_bitbang_samd21.h b/lib/hal/i2c_bitbang_samd21.h -deleted file mode 100644 -index 00fc7977e305..000000000000 ---- a/lib/hal/i2c_bitbang_samd21.h -+++ /dev/null -@@ -1,195 +0,0 @@ --/** -- * \file -- * \brief definitions for bit-banged I2C -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef I2C_BITBANG_SAMD21_H_ --#define I2C_BITBANG_SAMD21_H_ -- --#include "atca_status.h" --#include -- -- --#define MAX_I2C_BUSES 18 //The MAX_I2C_BUSES is the number of free pins in samd21 xplained pro -- -- --typedef struct --{ -- uint8_t pin_sda[MAX_I2C_BUSES]; -- uint8_t pin_scl[MAX_I2C_BUSES]; --} I2CBuses; -- --extern I2CBuses i2c_buses_default; -- --extern uint8_t pin_sda; --extern uint8_t pin_scl; -- --# define I2C_ENABLE() { struct port_config pin_conf; \ -- port_get_config_defaults(&pin_conf); \ -- pin_conf.direction = PORT_PIN_DIR_OUTPUT_WTH_READBACK; \ -- port_pin_set_config(pin_sda, &pin_conf); \ -- pin_conf.direction = PORT_PIN_DIR_OUTPUT; \ -- port_pin_set_config(pin_scl, &pin_conf); } --# define I2C_DISABLE() { struct port_config pin_conf; \ -- port_get_config_defaults(&pin_conf); \ -- pin_conf.direction = PORT_PIN_DIR_INPUT; \ -- pin_conf.input_pull = PORT_PIN_PULL_UP; \ -- port_pin_set_config(pin_sda, &pin_conf); \ -- port_pin_set_config(pin_scl, &pin_conf); } --# define I2C_CLOCK_LOW() port_pin_set_output_level(pin_scl, false) --# define I2C_CLOCK_HIGH() port_pin_set_output_level(pin_scl, true) --# define I2C_DATA_LOW() port_pin_set_output_level(pin_sda, false) --# define I2C_DATA_HIGH() port_pin_set_output_level(pin_sda, true) --# define I2C_DATA_IN() port_pin_get_input_level(pin_sda) --# define I2C_SET_OUTPUT() { struct port_config pin_conf; \ -- port_get_config_defaults(&pin_conf); \ -- pin_conf.direction = PORT_PIN_DIR_OUTPUT_WTH_READBACK; \ -- port_pin_set_config(pin_sda, &pin_conf); } --# define I2C_SET_OUTPUT_HIGH() { I2C_SET_OUTPUT(); I2C_DATA_HIGH(); } --# define I2C_SET_OUTPUT_LOW() { I2C_SET_OUTPUT(); I2C_DATA_LOW(); } --# define I2C_SET_INPUT() { struct port_config pin_conf; \ -- port_get_config_defaults(&pin_conf); \ -- pin_conf.direction = PORT_PIN_DIR_INPUT; \ -- port_pin_set_config(pin_sda, &pin_conf); } --# define DISABLE_INTERRUPT() cpu_irq_disable() --# define ENABLE_INTERRUPT() cpu_irq_enable() -- -- --#define I2C_CLOCK_DELAY_WRITE_LOW() delay_us(1) --#define I2C_CLOCK_DELAY_WRITE_HIGH() delay_us(1) --#define I2C_CLOCK_DELAY_READ_LOW() delay_us(1) --#define I2C_CLOCK_DELAY_READ_HIGH() delay_us(1) --#define I2C_CLOCK_DELAY_SEND_ACK() delay_us(1) --//! This delay is inserted to make the Start and Stop hold time at least 250 ns. --#define I2C_HOLD_DELAY() delay_us(1) -- -- -- -- --//! loop count when waiting for an acknowledgment --#define I2C_ACK_TIMEOUT (4) -- -- --/** -- * \brief Set I2C data and clock pin. -- * Other functions will use these pins. -- * -- * \param[in] sda definition of GPIO pin to be used as data pin -- * \param[in] scl definition of GPIO pin to be used as clock pin -- */ --void i2c_set_pin(uint8_t sda, uint8_t scl); -- -- --/** -- * \brief Assigns the logical bus number for discovering the devices -- * -- * -- * \param[in] i2c_bitbang_buses The logical bus numbers are assigned to the variables. -- * \param[in] max_buses Maximum number of bus used for discovering. -- */ -- --void i2c_discover_buses(int i2c_bitbang_buses[], int max_buses); -- --/** -- * \brief Configure GPIO pins for I2C clock and data as output. -- */ --void i2c_enable(void); -- --/** -- * \brief Configure GPIO pins for I2C clock and data as input. -- */ --void i2c_disable(void); -- -- --/** -- * \brief Send a START condition. -- */ --void i2c_send_start(void); -- --/** -- * \brief Send an ACK or NACK (after receive). -- * -- * \param[in] ack 0: NACK, else: ACK -- */ --void i2c_send_ack(uint8_t ack); -- --/** -- * \brief Send a STOP condition. -- */ --void i2c_send_stop(void); -- --/** -- * \brief Send a Wake Token. -- */ --void i2c_send_wake_token(void); -- --/** -- * \brief Send one byte. -- * -- * \param[in] i2c_byte byte to write -- * -- * \return ATCA_STATUS -- */ --ATCA_STATUS i2c_send_byte(uint8_t i2c_byte); -- --/** -- * \brief Send a number of bytes. -- * -- * \param[in] count number of bytes to send -- * \param[in] data pointer to buffer containing bytes to send -- * -- * \return ATCA_STATUS -- */ --ATCA_STATUS i2c_send_bytes(uint8_t count, uint8_t *data); -- --/** -- * \brief Receive one byte (MSB first). -- * -- * \param[in] ack 0:NACK, else:ACK -- * -- * \return Number of bytes received -- */ --uint8_t i2c_receive_one_byte(uint8_t ack); -- --/** -- * \brief Receive one byte and send ACK. -- * -- * \param[out] data pointer to received byte -- */ --void i2c_receive_byte(uint8_t *data); -- --/** -- * \brief Receive a number of bytes. -- * -- * \param[out] data pointer to receive buffer -- * \param[in] count number of bytes to receive -- */ --void i2c_receive_bytes(uint8_t count, uint8_t *data); -- --#endif /* I2C_BITBANG_SAMD21_H_ */ -\ No newline at end of file -diff --git a/lib/hal/kit_phy.h b/lib/hal/kit_phy.h -deleted file mode 100644 -index f0b6ecd35f90..000000000000 ---- a/lib/hal/kit_phy.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/** -- * \file -- * \brief ATCA Hardware abstraction layer physical send & receive function definitions. -- * -- * This is included for kit protocol implementations. -- * It is included in the kit protocol callback to actually send and recieve bytes. -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef KIT_PHY_H_ --#define KIT_PHY_H_ -- --#include "cryptoauthlib.h" -- -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --#ifdef __cplusplus --extern "C" { --#endif -- --ATCA_STATUS kit_phy_num_found(int8_t* num_found); --ATCA_STATUS kit_phy_send(ATCAIface iface, const char *txdata, int txlength); --ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxlength); -- --#ifdef __cplusplus --} --#endif -- --/** @} */ -- --#endif /* ATCA_HAL_PHY_H_ */ -diff --git a/lib/hal/kit_protocol.c b/lib/hal/kit_protocol.c -deleted file mode 100644 -index 55f8708d1d94..000000000000 ---- a/lib/hal/kit_protocol.c -+++ /dev/null -@@ -1,430 +0,0 @@ --/** -- * \file -- * -- * \brief Microchip Crypto Auth hardware interface object -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "kit_phy.h" --#include "kit_protocol.h" --#include "basic/atca_helpers.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- -- --/** \brief HAL implementation of kit protocol init. This function calls back to the physical protocol to send the bytes -- * \param[in] iface instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_init(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- uint8_t kitstatus = 0; -- char address[] = "board:device(00)\n"; -- int addresssize = sizeof(address); -- char reply[KIT_RX_WRAP_SIZE + 4]; -- int replysize = sizeof(reply); -- uint8_t rxdata[2]; -- int rxsize = sizeof(rxdata); -- char selectaddress[KIT_MSG_SIZE]; -- int selectaddresssize = sizeof(selectaddress); -- char selectaddresspre[] = "s:physical:select("; -- char selectaddresspost[] = ")\n"; -- int copysize = 0; -- -- // Send the address bytes -- status = kit_phy_send(iface, address, addresssize); -- -- // Receive the reply to address "...(C0)\n" -- memset(reply, 0, replysize); -- status = kit_phy_receive(iface, reply, &replysize); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_GEN_FAIL; -- } -- -- if (replysize == 4) -- { -- // Probably an error -- status = kit_parse_rsp(reply, replysize, &kitstatus, rxdata, &rxsize); -- if (status != ATCA_SUCCESS) -- { -- return status; -- } -- if (kitstatus != 0) -- { -- return ATCA_NO_DEVICES; -- } -- } -- rxsize = 2; -- memcpy(rxdata, strchr(reply, '(') + 1, rxsize); -- -- // Send the select address bytes -- memset(selectaddress, 0, selectaddresssize); -- copysize = sizeof(selectaddresspre); -- memcpy(&selectaddress[0], selectaddresspre, copysize); -- memcpy(&selectaddress[(copysize - 1)], rxdata, rxsize); -- copysize = (sizeof(selectaddresspre) + rxsize); -- memcpy(&selectaddress[(copysize - 1)], selectaddresspost, sizeof(selectaddresspost)); -- copysize = (sizeof(selectaddresspre) + rxsize + sizeof(selectaddresspost)); -- status = kit_phy_send(iface, selectaddress, copysize); -- -- // Receive the reply to select address "00()\n" -- memset(reply, 0, replysize); -- status = kit_phy_receive(iface, reply, &replysize); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_GEN_FAIL; -- } -- -- return status; --} -- --/** \brief HAL implementation of kit protocol send. This function calls back to the physical protocol to send the bytes -- * \param[in] iface instance -- * \param[in] txdata pointer to bytes to send -- * \param[in] txlength number of bytes to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_send(ATCAIface iface, const uint8_t* txdata, int txlength) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- int nkitbuf = txlength * 2 + KIT_TX_WRAP_SIZE; -- char* pkitbuf = NULL; -- -- // Check the pointers -- if ((txdata == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- // Wrap in kit protocol -- pkitbuf = malloc(nkitbuf); -- memset(pkitbuf, 0, nkitbuf); -- status = kit_wrap_cmd(&txdata[1], txlength, pkitbuf, &nkitbuf); -- if (status != ATCA_SUCCESS) -- { -- free(pkitbuf); -- return ATCA_GEN_FAIL; -- } -- // Send the bytes -- status = kit_phy_send(iface, pkitbuf, nkitbuf); -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("\nKit Write: %s", pkitbuf); --#endif -- -- // Free the bytes -- free(pkitbuf); -- -- return status; --} -- --/** \brief HAL implementation to receive bytes and unwrap from kit protocol. This function calls back to the physical protocol to receive the bytes -- * \param[in] iface instance -- * \param[in] rxdata pointer to space to receive the data -- * \param[inout] rxsize ptr to expected number of receive bytes to request -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- uint8_t kitstatus = 0; -- int nkitbuf = 0; -- int dataSize = 0; -- char* pkitbuf = NULL; -- -- // Check the pointers -- if ((rxdata == NULL) || (rxsize == NULL)) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Adjust the read buffer size -- dataSize = *rxsize; -- nkitbuf = dataSize * 2 + KIT_RX_WRAP_SIZE; -- pkitbuf = malloc(nkitbuf); -- memset(pkitbuf, 0, nkitbuf); -- -- // Receive the bytes -- status = kit_phy_receive(iface, pkitbuf, &nkitbuf); -- if (status != ATCA_SUCCESS) -- { -- free(pkitbuf); -- return ATCA_GEN_FAIL; -- } -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("Kit Read: %s\r", pkitbuf); --#endif -- -- // Unwrap from kit protocol -- memset(rxdata, 0, *rxsize); -- status = kit_parse_rsp(pkitbuf, nkitbuf, &kitstatus, rxdata, &dataSize); -- *rxsize = dataSize; -- -- // Free the bytes -- free(pkitbuf); -- -- return status; --} -- --/** \brief Call the wake for kit protocol -- * \param[in] iface the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_wake(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- uint8_t kitstatus = 0; -- char wake[] = "s:w()\n"; -- int wakesize = sizeof(wake); -- char reply[KIT_RX_WRAP_SIZE + 4]; -- int replysize = sizeof(reply); -- uint8_t rxdata[10]; -- int rxsize = sizeof(rxdata); -- -- // Send the bytes -- status = kit_phy_send(iface, wake, wakesize); -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("\nKit Write: %s", wake); --#endif -- -- // Receive the reply to wake "00(04...)\n" -- memset(reply, 0, replysize); -- status = kit_phy_receive(iface, reply, &replysize); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_GEN_FAIL; -- } -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("Kit Read: %s\n", reply); --#endif -- -- // Unwrap from kit protocol -- memset(rxdata, 0, rxsize); -- status = kit_parse_rsp(reply, replysize, &kitstatus, rxdata, &rxsize); -- -- return status; --} -- --/** \brief Call the idle for kit protocol -- * \param[in] iface the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_idle(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- uint8_t kitstatus = 0; -- char idle[] = "s:i()\n"; -- int idlesize = sizeof(idle); -- char reply[KIT_RX_WRAP_SIZE]; -- int replysize = sizeof(reply); -- uint8_t rxdata[10]; -- int rxsize = sizeof(rxdata); -- -- // Send the bytes -- status = kit_phy_send(iface, idle, idlesize); -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("\nKit Write: %s", idle); --#endif -- -- // Receive the reply to sleep "00()\n" -- memset(reply, 0, replysize); -- status = kit_phy_receive(iface, reply, &replysize); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_GEN_FAIL; -- } -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("Kit Read: %s\r", reply); --#endif -- -- // Unwrap from kit protocol -- memset(rxdata, 0, rxsize); -- status = kit_parse_rsp(reply, replysize, &kitstatus, rxdata, &rxsize); -- -- return status; --} -- --/** \brief Call the sleep for kit protocol -- * \param[in] iface the interface object to send the bytes over -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_sleep(ATCAIface iface) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- uint8_t kitstatus = 0; -- -- char sleep[] = "s:s()\n"; -- int sleepsize = sizeof(sleep); -- char reply[KIT_RX_WRAP_SIZE]; -- int replysize = sizeof(reply); -- uint8_t rxdata[10]; -- int rxsize = sizeof(rxdata); -- -- // Send the bytes -- status = kit_phy_send(iface, sleep, sleepsize); -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("\nKit Write: %s", sleep); --#endif -- -- // Receive the reply to sleep "00()\n" -- memset(reply, 0, replysize); -- status = kit_phy_receive(iface, reply, &replysize); -- if (status != ATCA_SUCCESS) -- { -- return ATCA_GEN_FAIL; -- } -- --#ifdef KIT_DEBUG -- // Print the bytes -- printf("Kit Read: %s\r", reply); --#endif -- -- // Unwrap from kit protocol -- memset(rxdata, 0, rxsize); -- status = kit_parse_rsp(reply, replysize, &kitstatus, rxdata, &rxsize); -- -- return status; --} -- --/** \brief Wrap binary bytes in ascii kit protocol -- * \param[in] txdata pointer to the binary data to wrap -- * \param[in] txlen length of the binary data to wrap -- * \param[out] pkitcmd pointer to binary data converted to ascii kit protocol -- * \param[inout] nkitcmd pointer to the size of the binary data converted to ascii kit protocol -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_wrap_cmd(const uint8_t* txdata, int txlen, char* pkitcmd, int* nkitcmd) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- char cmdpre[] = "s:t("; // sha:talk( -- char cmdpost[] = ")\n"; --// char* pkitcmd = NULL; -- int cmdAsciiLen = txlen * 2; -- int cmdlen = txlen * 2 + sizeof(cmdpre) + sizeof(cmdpost) + 1; -- int cpylen = 0; -- int cpyindex = 0; -- -- // Check the variables -- if (txdata == NULL || pkitcmd == NULL || nkitcmd == NULL) -- { -- return ATCA_BAD_PARAM; -- } -- if (*nkitcmd > cmdlen) -- { -- return ATCA_BAD_PARAM; -- } -- -- // Wrap in kit protocol -- memset(pkitcmd, 0, *nkitcmd); -- -- // Copy the prefix -- cpylen = (int)strlen(cmdpre); -- memcpy(&pkitcmd[cpyindex], cmdpre, cpylen); -- cpyindex += cpylen; -- -- // Copy the ascii binary bytes -- status = atcab_bin2hex_(txdata, txlen, &pkitcmd[cpyindex], &cmdAsciiLen, false); -- if (status != ATCA_SUCCESS) -- { -- return status; -- } -- cpyindex += cmdAsciiLen; -- -- // Copy the postfix -- cpylen = (int)strlen(cmdpost); -- memcpy(&pkitcmd[cpyindex], cmdpost, cpylen); -- cpyindex += cpylen; -- -- *nkitcmd = cpyindex; -- -- return status; --} -- --/** \brief Parse the response ascii from the kit -- * \param[out] pkitbuf pointer to ascii kit protocol data to parse -- * \param[in] nkitbuf length of the ascii kit protocol data -- * \param[in] kitstatus status of the ascii device -- * \param[in] rxdata pointer to the binary data buffer -- * \param[in] datasize size of the pointer to the binary data buffer -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS kit_parse_rsp(const char* pkitbuf, int nkitbuf, uint8_t* kitstatus, uint8_t* rxdata, int* datasize) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- int statusId = 0; -- int dataId = 3; -- int binSize = 1; -- int asciiDataSize = 0; -- char* endDataPtr = 0; -- -- // First get the kit status -- status = atcab_hex2bin(&pkitbuf[statusId], 2, kitstatus, &binSize); -- if (status != ATCA_SUCCESS) -- { -- return status; -- } -- -- // Next get the binary data bytes -- endDataPtr = strchr((char*)pkitbuf, ')'); -- if (endDataPtr < (&pkitbuf[dataId])) -- { -- return ATCA_GEN_FAIL; -- } -- asciiDataSize = (int)(endDataPtr - (&pkitbuf[dataId])); -- status = atcab_hex2bin(&pkitbuf[dataId], asciiDataSize, rxdata, datasize); -- if (status != ATCA_SUCCESS) -- { -- return status; -- } -- -- return ATCA_SUCCESS; --} -- --/** @} */ -diff --git a/lib/hal/kit_protocol.h b/lib/hal/kit_protocol.h -deleted file mode 100644 -index 84f7fee454cb..000000000000 ---- a/lib/hal/kit_protocol.h -+++ /dev/null -@@ -1,77 +0,0 @@ --/** -- * \file -- * -- * \brief Atmel Crypto Auth hardware interface object -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef KIT_PROTOCOL_H_ --#define KIT_PROTOCOL_H_ -- --#include "cryptoauthlib.h" -- --// Define this for debugging communication --//#define KIT_DEBUG -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --// The number of bytes to wrap a command in kit protocol. sizeof("s:t()\n") --#define KIT_TX_WRAP_SIZE (7) -- --// The number of bytes to wrap a response in kit protocol. sizeof("00()\n") --#define KIT_MSG_SIZE (32) --#define KIT_RX_WRAP_SIZE (KIT_MSG_SIZE + 6) -- --#ifdef __cplusplus --extern "C" { --#endif -- --ATCA_STATUS kit_init(ATCAIface iface); -- --ATCA_STATUS kit_send(ATCAIface iface, const uint8_t* txdata, int txlength); --ATCA_STATUS kit_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize); -- --ATCA_STATUS kit_wrap_cmd(const uint8_t* txdata, int txlength, char* pkitbuf, int* nkitbuf); --ATCA_STATUS kit_parse_rsp(const char* pkitbuf, int nkitbuf, uint8_t* kitstatus, uint8_t* rxdata, int* nrxdata); -- --ATCA_STATUS kit_wake(ATCAIface iface); --ATCA_STATUS kit_idle(ATCAIface iface); --ATCA_STATUS kit_sleep(ATCAIface iface); -- --#ifdef __cplusplus --} --#endif -- --/** @} */ -- --#endif // KIT_PROTOCOL_H -diff --git a/lib/hal/swi_bitbang_samd21.c b/lib/hal/swi_bitbang_samd21.c -deleted file mode 100644 -index 3c540109cb4c..000000000000 ---- a/lib/hal/swi_bitbang_samd21.c -+++ /dev/null -@@ -1,272 +0,0 @@ --/** -- * \file -- * \brief Hardware Interface Functions - SWI bit-banged -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "swi_bitbang_samd21.h" -- -- -- -- -- --SWIBuses swi_buses_default = { -- { EXT3_PIN_3, EXT3_PIN_9, EXT3_PIN_I2C_SDA, EXT3_PIN_13, EXT2_PIN_3, EXT2_PIN_5, EXT2_PIN_7, EXT2_PIN_9, EXT2_PIN_13, EXT2_PIN_15, EXT2_PIN_17, EXT1_PIN_3, EXT1_PIN_5, EXT1_PIN_7, EXT1_PIN_9, EXT1_PIN_13, EXT1_PIN_15, EXT1_PIN_17, EXT3_PIN_7, EXT3_PIN_10, EXT3_PIN_I2C_SCL, EXT3_PIN_14, EXT2_PIN_4, EXT2_PIN_6, EXT2_PIN_8, EXT2_PIN_10, EXT2_PIN_14, EXT2_PIN_16, EXT2_PIN_18, EXT1_PIN_4, EXT1_PIN_6, EXT1_PIN_8, EXT1_PIN_10, EXT1_PIN_14, EXT1_PIN_16, EXT1_PIN_18 } -- --}; -- -- --//! declaration of the variable indicating which pin the selected device is connected to --static uint8_t device_pin; -- -- --void swi_set_pin(uint8_t id) --{ -- device_pin = id; --} -- -- -- --void swi_enable(void) --{ -- struct port_config pin_conf; -- -- port_get_config_defaults(&pin_conf); -- pin_conf.direction = PORT_PIN_DIR_OUTPUT; -- port_pin_set_config(device_pin, &pin_conf); --} -- --void swi_disable(void) --{ -- struct port_config pin_conf; -- -- port_get_config_defaults(&pin_conf); -- port_pin_set_config(device_pin, &pin_conf); --} -- -- --void swi_set_signal_pin(uint8_t is_high) --{ -- if (is_high) -- { -- port_pin_set_output_level(device_pin, true); -- } -- else -- { -- port_pin_set_output_level(device_pin, false); -- } --} -- --void swi_send_wake_token(void) --{ -- swi_set_signal_pin(0); -- delay_us(60); -- swi_set_signal_pin(1); --} -- --void swi_send_bytes(uint8_t count, uint8_t *buffer) --{ -- uint8_t i, bit_mask; -- struct port_config pin_conf; -- -- port_get_config_defaults(&pin_conf); -- pin_conf.direction = PORT_PIN_DIR_OUTPUT; -- port_pin_set_config(device_pin, &pin_conf); -- -- //! Wait turn around time. -- RX_TX_DELAY; -- cpu_irq_disable(); -- -- -- for (i = 0; i < count; i++) -- { -- for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) -- { -- if (bit_mask & buffer[i]) //!< Send Logic 1 (7F) -- { -- port_pin_set_output_level(device_pin, false); -- BIT_DELAY_1L; -- port_pin_set_output_level(device_pin, true); -- BIT_DELAY_7; -- } -- else //!< Send Logic 0 (7D) -- { -- port_pin_set_output_level(device_pin, false); -- BIT_DELAY_1L; -- port_pin_set_output_level(device_pin, true); -- BIT_DELAY_1H; -- port_pin_set_output_level(device_pin, false); -- BIT_DELAY_1L; -- port_pin_set_output_level(device_pin, true); -- BIT_DELAY_5; -- } -- } -- } -- cpu_irq_enable(); -- -- -- --} -- -- --void swi_send_byte(uint8_t byte) --{ -- swi_send_bytes(1, &byte); -- --} -- -- -- -- --ATCA_STATUS swi_receive_bytes(uint8_t count, uint8_t *buffer) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- uint8_t i; -- uint8_t bit_mask; -- uint8_t pulse_count; -- uint16_t timeout_count; -- struct port_config pin_conf; -- -- -- port_get_config_defaults(&pin_conf); -- port_pin_set_config(device_pin, &pin_conf); -- -- -- cpu_irq_disable(); -- //! Receive bits and store in buffer. -- for (i = 0; i < count; i++) -- { -- buffer[i] = 0; -- for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) -- { -- pulse_count = 0; -- -- -- timeout_count = START_PULSE_TIME_OUT; -- //! Detect start bit. -- -- while (--timeout_count > 0) -- { -- //! Wait for falling edge. -- if (port_pin_get_input_level(device_pin) == 0) -- { -- -- break; -- } -- } -- if (timeout_count == 0) -- { -- status = ATCA_RX_TIMEOUT; -- break; -- } -- -- timeout_count = START_PULSE_TIME_OUT; -- -- do -- { -- //! Wait for rising edge. -- if (port_pin_get_input_level(device_pin) != 0) -- { -- pulse_count = 1; -- -- break; -- } -- } -- while (--timeout_count > 0); -- -- if (pulse_count == 0) -- { -- status = ATCA_RX_TIMEOUT; -- break; -- } -- -- //! let's just wait the maximum time for the falling edge of a zero bit -- //! to arrive after we have detected the rising edge of the start bit. -- timeout_count = ZERO_PULSE_TIME_OUT; -- -- //! Detect possible edge indicating zero bit. -- do -- { -- if (port_pin_get_input_level(device_pin) == 0) -- { -- pulse_count = 2; -- break; -- } -- } -- while (--timeout_count > 0); -- -- -- //! Wait for rising edge of zero pulse before returning. Otherwise we might interpret -- //! its rising edge as the next start pulse. -- if (pulse_count == 2) -- { -- timeout_count = ZERO_PULSE_TIME_OUT; -- -- do -- { -- if (port_pin_get_input_level(device_pin) != 0) -- { -- break; -- } -- } -- -- while (timeout_count-- > 0); -- -- } -- //! Update byte at current buffer index. -- else -- //! received "one" bit -- { -- buffer[i] |= bit_mask; -- } -- } -- -- -- if (status != ATCA_SUCCESS) -- { -- break; -- } -- } -- -- if (status == ATCA_RX_TIMEOUT) -- { -- if (i > 0) -- { -- //! Indicate that we timed out after having received at least one byte. -- status = ATCA_RX_FAIL; -- } -- } -- -- cpu_irq_enable(); -- -- -- return status; --} -\ No newline at end of file -diff --git a/lib/hal/swi_bitbang_samd21.h b/lib/hal/swi_bitbang_samd21.h -deleted file mode 100644 -index b6d20f6153ba..000000000000 ---- a/lib/hal/swi_bitbang_samd21.h -+++ /dev/null -@@ -1,148 +0,0 @@ --/** -- * \file -- * \brief Hardware Interface Functions - SWI bit-banged -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef SWI_BITBANG_SAMD21_H_ --#define SWI_BITBANG_SAMD21_H_ -- --#include "atca_status.h" --#include -- -- --#define MAX_SWI_BUSES 36 //!< SAMD21 xplainned pro has 36 free GPIO pins available -- -- --typedef struct --{ -- uint32_t pin_sda[MAX_SWI_BUSES]; --} SWIBuses; -- --extern SWIBuses swi_buses_default; -- -- --/** -- * \name Macros for Bit-Banged SWI Timing -- * -- * Times to drive bits at 230.4 kbps. -- @{ */ -- --//! delay macro for width of one pulse (start pulse or zero pulse) --//! should be 4.34 us, is 4.05 us -- --#define BIT_DELAY_1L delay_us(3) --//! should be 4.34 us, is 4.05us --#define BIT_DELAY_1H delay_us(3) -- --//! time to keep pin high for five pulses plus stop bit (used to bit-bang CryptoAuth 'zero' bit) --//! should be 26.04 us, is 26.92 us --#define BIT_DELAY_5 delay_us(26) // considering pin set delay -- --//! time to keep pin high for seven bits plus stop bit (used to bit-bang CryptoAuth 'one' bit) --//! should be 34.72 us, is 35.13 us --#define BIT_DELAY_7 delay_us(34) // considering pin set delay -- --//! turn around time when switching from receive to transmit --//! should be 15 us, is 15.58 us --#define RX_TX_DELAY delay_us(15) -- -- --//! Lets set the timeout value for start pulse detection to the uint8_t maximum. --//! This value is decremented while waiting for the falling edge of a start pulse. --#define START_PULSE_TIME_OUT (600) -- --//! Maximum time between rising edge of start pulse --//! and falling edge of zero pulse is 8.6 us. Therefore, a value of 40 (around 15 us) --//! gives ample time to detect a zero pulse and also leaves enough time to detect --//! the following start pulse. --//! This value is decremented while waiting for the falling edge of a zero pulse. --#define ZERO_PULSE_TIME_OUT (40) -- --/** @} */ -- -- --/** -- * \brief Set SWI signal pin. -- * Other functions will use this pin. -- * -- * \param[in] id definition of GPIO pin to be used -- */ --void swi_set_pin(uint8_t id); -- -- -- --/** -- * \brief Configure GPIO pin for SWI signal as output. -- */ --void swi_enable(void); -- --/** -- * \brief Configure GPIO pin for SWI signal as input. -- */ --void swi_disable(void); -- --/** -- * \brief Set signal pin Low or High. -- * -- * \param[in] is_high 0: Low, else: High. -- */ --void swi_set_signal_pin(uint8_t is_high); -- --/** -- * \brief Send a Wake Token. -- */ --void swi_send_wake_token(void); -- --/** -- * \brief Send a number of bytes.This function should not be called directly ,instead should use hal_swi_send() which call this function. -- * -- * \param[in] count number of bytes to send. -- * \param[in] buffer pointer to buffer containing bytes to send -- */ --void swi_send_bytes(uint8_t count, uint8_t *buffer); -- --/** -- * \brief Send one byte. -- * -- * \param[in] byte byte to send -- */ --void swi_send_byte(uint8_t byte); -- --/** -- * \brief Receive a number of bytes.This function should not be called directly ,instead should use hal_swi_receive() which call this function. -- * -- * \param[in] count number of bytes to receive -- * \param[out] buffer pointer to receive buffer -- * -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_receive_bytes(uint8_t count, uint8_t *buffer); -- -- --#endif /* SWI_BITBANG_SAMD21_H_ */ -\ No newline at end of file -diff --git a/lib/hal/swi_uart_at90usb1287_asf.c b/lib/hal/swi_uart_at90usb1287_asf.c -deleted file mode 100644 -index 68efbf61eec5..000000000000 ---- a/lib/hal/swi_uart_at90usb1287_asf.c -+++ /dev/null -@@ -1,260 +0,0 @@ --/** -- * \file -- * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over AT90USB1287 UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "usart_serial.h" --#include "swi_uart_at90usb1287_asf.h" --#include "basic/atca_helpers.h" -- --/*#define DEBUG_PIN*/ -- --#ifdef DEBUG_PIN -- #define DEBUG_PIN_1 IOPORT_CREATE_PIN(PORTB, 0) -- #define DEBUG_PIN_2 IOPORT_CREATE_PIN(PORTB, 1) --#endif -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief usart configuration struct */ --static usart_serial_options_t config_usart; --/** \brief sysclk_get_per_hz value */ --static uint32_t u32sysclk; -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --/** \brief Implementation of SWI UART init. -- * \param[in] instance instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance) --{ --#ifdef DEBUG_PIN -- ioport_init(); -- ioport_set_pin_dir(DEBUG_PIN_1, IOPORT_DIR_OUTPUT); -- ioport_set_pin_dir(DEBUG_PIN_2, IOPORT_DIR_OUTPUT); -- gpio_set_pin_high(DEBUG_PIN_1); -- gpio_set_pin_high(DEBUG_PIN_2); --#endif -- ATCA_STATUS status = ATCA_SUCCESS; -- -- //Save sysclk_get_per_hz value -- u32sysclk = sysclk_get_source_clock_hz(); -- // Set data size to 7 -- config_usart.charlength = USART_CHSIZE_7BIT_gc; -- // Set parity to no parity -- config_usart.paritytype = USART_PMODE_DISABLED_gc; -- // Set data byte to one stopbit -- config_usart.stopbits = false; -- // Set baudrate to 230400 -- config_usart.baudrate = 230400; -- -- switch (instance->bus_index) -- { -- case 0: instance->usart_instance = &USARTA1; break; // AT90USB1287 has only 1 UART channel which maps to ATMEGARF's UART 1 -- } -- status = usart_serial_init(instance->usart_instance, &config_usart); -- return status; --} -- --/** \brief Implementation of SWI UART deinit. -- * \param[in] instance instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- instance->usart_instance = NULL; -- return status; --} -- --/** \brief implementation of SWI UART change baudrate. -- * \param[in] instance instance -- * \param[in] baudrate (typically 230400 , 160000 or 115200) -- */ --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate) --{ -- /*usart_double_baud_enable(instance->usart_instance);*/ -- // Set baudrate for UART module -- usart_set_baudrate(instance->usart_instance, baudrate, u32sysclk); --} -- -- --/** \brief implementation of SWI UART change mode. -- * \param[in] instance instance -- * \param[in] mode (TRANSMIT_MODE or RECEIVE_MODE) -- */ --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode) --{ -- switch (mode) -- { -- case TRANSMIT_MODE: -- swi_uart_setbaud(instance, 230400); -- break; -- case RECEIVE_MODE: -- //Reset UART RX buffer. -- usart_rx_disable(instance->usart_instance); -- usart_rx_enable(instance->usart_instance); -- break; -- default: -- break; -- } -- --} -- --/** \brief discover UART buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] swi_uart_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- */ --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses) --{ -- /* if every PORT was a likely candidate bus, then would need to initialize the entire array to all PORT n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / PORT map based on AT90USB1287 -- * If you were using a raw XMEGA on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ -- swi_uart_buses[0] = 0; // AT90USB1287 supports single UART channel --} -- --/** \brief HAL implementation of SWI UART send byte over ASF. This function send one byte over UART -- * \param[in] instance instance -- * \param[in] data byte to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data) --{ -- int8_t timeout = 0x7F; -- bool data_reg_empty = false; -- ATCA_STATUS status = ATCA_EXECUTION_ERROR /*ATCA_CMD_FAIL*/; -- -- // Send one byte over UART module --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_1); --#endif -- -- // Send one byte over UART module -- timeout = 0x7F; -- -- while ((timeout > 0) && (data_reg_empty == false)) -- { -- data_reg_empty = usart_data_register_is_empty(instance->usart_instance); -- timeout--; -- } -- -- if (data_reg_empty) -- { -- usart_serial_putchar(instance->usart_instance, data); -- while (!usart_tx_is_complete(instance->usart_instance)) -- { -- ; -- } -- usart_clear_tx_complete(instance->usart_instance); -- status = ATCA_SUCCESS; -- } -- --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_1); --#endif -- if (timeout > 0) -- { -- return status; -- } -- else -- { -- return ATCA_TIMEOUT; -- } --} -- --/** \brief HAL implementation of SWI UART receive bytes over ASF. This function receive one byte over UART -- * \param[in] instance instance -- * \param[inout] data pointer to space to receive the data -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data) --{ -- int8_t timeout, retries = 0x2; // This retry is used to compensate the baudrate that do not match when receiving response -- -- *data = 0xFF; -- bool rx_complete = false; -- ATCA_STATUS status = ATCA_EXECUTION_ERROR /*ATCA_CMD_FAIL*/; --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_2); --#endif -- // Receive one byte over UART module -- while ((retries > 0) && (status != ATCA_SUCCESS)) -- { -- timeout = 0x7F; retries--; -- while ((timeout > 0) && (rx_complete == false)) -- { -- rx_complete = usart_rx_is_complete(instance->usart_instance); -- timeout--; -- } -- -- if (rx_complete) -- { -- usart_serial_getchar(instance->usart_instance, data); -- //if ((*data == 0x7D) || (*data == 0x7F)) -- if ((*data >= 0x70) && (*data <= 0x7F)) -- { -- status = ATCA_SUCCESS; -- } -- else -- { -- status = ATCA_EXECUTION_ERROR /*ATCA_CMD_FAIL*/; -- } -- } -- } --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_2); --#endif -- if (timeout > 0) -- { -- return status; -- } -- else -- { -- return ATCA_TIMEOUT; -- } --} -- --/** @} */ -diff --git a/lib/hal/swi_uart_at90usb1287_asf.h b/lib/hal/swi_uart_at90usb1287_asf.h -deleted file mode 100644 -index 2b11b2467937..000000000000 ---- a/lib/hal/swi_uart_at90usb1287_asf.h -+++ /dev/null -@@ -1,83 +0,0 @@ --/** -- * \file -- * \brief ATMEGA's ATCA Hardware abstraction layer for SWI interface over AT90USB1287 UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef SWI_UART_AT90USB1287_ASF_H --#define SWI_UART_AT90USB1287_ASF_H -- --#include --#include "cryptoauthlib.h" --#include "serial.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --#define MAX_SWI_BUSES 1 // AT90USB1287 has only 1 port -- --#define RECEIVE_MODE 0 // UART Receive mode, RX enabled --#define TRANSMIT_MODE 1 // UART Transmit mode, RX disabled --#define RX_DELAY 10 // Delay before responses come --#define TX_DELAY 90 // Delay before new flag is sent -- --/** \brief this is the hal_data for ATCA HAL for SWI UART -- */ --typedef struct atcaSWImaster --{ -- // struct usart_module for Atmel SWI interface -- usart_if usart_instance; -- // for conveniences during interface release phase -- int bus_index; --} ATCASWIMaster_t; -- -- --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance); --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance); --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate); --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode); --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses); -- --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data); --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data); -- --/** @} */ -- --#endif // SWI_UART_AT90USB1287_ASF_H -diff --git a/lib/hal/swi_uart_samd21_asf.c b/lib/hal/swi_uart_samd21_asf.c -deleted file mode 100644 -index 1a5b698381e0..000000000000 ---- a/lib/hal/swi_uart_samd21_asf.c -+++ /dev/null -@@ -1,238 +0,0 @@ --/** -- * \file -- * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "swi_uart_samd21_asf.h" --#include "basic/atca_helpers.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief usart configuration struct */ --static struct usart_config config_usart; --struct port_config pin_conf; //for DEBUG purpose -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --/** \brief Implementation of SWI UART init. -- * \param[in] instance instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance) --{ --#ifdef DEBUG_PIN -- port_get_config_defaults(&pin_conf); -- pin_conf.direction = PORT_PIN_DIR_OUTPUT; -- port_pin_set_config(DEBUG_PIN_1, &pin_conf); -- port_pin_set_config(DEBUG_PIN_2, &pin_conf); -- port_pin_set_output_level(DEBUG_PIN_1, HIGH); -- port_pin_set_output_level(DEBUG_PIN_2, HIGH); --#endif -- -- ATCA_STATUS status = ATCA_SUCCESS; -- usart_get_config_defaults(&config_usart); -- // Set data size to 7 -- config_usart.character_size = USART_CHARACTER_SIZE_7BIT; -- // Set parity to no parity -- config_usart.parity = USART_PARITY_NONE; -- // Set data byte to one stopbit -- config_usart.stopbits = USART_STOPBITS_1; -- // Set baudrate to 230400 -- config_usart.baudrate = 230400; --#ifdef __SAMD21J18A__ -- config_usart.mux_setting = EXT3_UART_SERCOM_MUX_SETTING; -- config_usart.pinmux_pad0 = EXT3_UART_SERCOM_PINMUX_PAD0; -- config_usart.pinmux_pad1 = EXT3_UART_SERCOM_PINMUX_PAD1; -- config_usart.pinmux_pad2 = EXT3_UART_SERCOM_PINMUX_PAD2; -- config_usart.pinmux_pad3 = EXT3_UART_SERCOM_PINMUX_PAD3; --#endif --#ifdef __SAMR21G18A__ -- config_usart.mux_setting = EXT1_UART_SERCOM_MUX_SETTING; -- config_usart.pinmux_pad0 = EXT1_UART_SERCOM_PINMUX_PAD0; -- config_usart.pinmux_pad1 = EXT1_UART_SERCOM_PINMUX_PAD1; -- config_usart.pinmux_pad2 = EXT1_UART_SERCOM_PINMUX_PAD2; -- config_usart.pinmux_pad3 = EXT1_UART_SERCOM_PINMUX_PAD3; --#endif -- switch (instance->bus_index) -- { -- case 0: status = usart_init(&(instance->usart_instance), SERCOM0, &config_usart); break; -- case 1: status = usart_init(&(instance->usart_instance), SERCOM1, &config_usart); break; -- case 2: status = usart_init(&(instance->usart_instance), SERCOM2, &config_usart); break; -- case 3: status = usart_init(&(instance->usart_instance), SERCOM3, &config_usart); break; -- case 4: status = usart_init(&(instance->usart_instance), SERCOM4, &config_usart); break; -- case 5: status = usart_init(&(instance->usart_instance), SERCOM5, &config_usart); break; -- } -- usart_enable(&(instance->usart_instance)); -- return status; --} -- --/** \brief Implementation of SWI UART deinit. -- * \param[in] instance instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- usart_reset(&(instance->usart_instance)); -- return status; --} -- --/** \brief implementation of SWI UART change baudrate. -- * \param[in] instance instance -- * \param[in] baudrate (typically 230400 , 160000 or 115200) -- */ --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate) --{ -- // Disable UART module -- usart_disable(&(instance->usart_instance)); -- // Set baudrate for UART module -- config_usart.baudrate = baudrate; -- switch (instance->bus_index) -- { -- case 0: usart_init(&(instance->usart_instance), SERCOM0, &config_usart); break; -- case 1: usart_init(&(instance->usart_instance), SERCOM1, &config_usart); break; -- case 2: usart_init(&(instance->usart_instance), SERCOM2, &config_usart); break; -- case 3: usart_init(&(instance->usart_instance), SERCOM3, &config_usart); break; -- case 4: usart_init(&(instance->usart_instance), SERCOM4, &config_usart); break; -- case 5: usart_init(&(instance->usart_instance), SERCOM5, &config_usart); break; -- } -- usart_enable(&(instance->usart_instance)); --} -- -- --/** \brief implementation of SWI UART change mode. -- * \param[in] instance instance -- * \param[in] mode (TRANSMIT_MODE or RECEIVE_MODE) -- */ --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode) --{ -- usart_disable(&(instance->usart_instance)); -- // Do nothing as the available time is not enough for setting the baudrate in ASF -- usart_enable(&(instance->usart_instance)); --} -- --/** \brief discover UART buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] swi_uart_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- */ --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses) --{ -- /* if every SERCOM was a likely candidate bus, then would need to initialize the entire array to all SERCOM n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / SERCOM map based on SAMD21 Xplained Pro board -- * If you were using a raw SAMD21 on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ -- swi_uart_buses[0] = 4; // default samd21 for xplained dev board --} -- -- --/** \brief HAL implementation of SWI UART send byte over ASF. This function send one byte over UART -- * \param[in] instance instance -- * \param[in] data number of byte to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data) --{ -- int8_t retries = 90; -- uint16_t bitdata = (uint16_t)data; -- -- // Send one byte over UART module --#ifdef DEBUG_PIN -- port_pin_toggle_output_level(DEBUG_PIN_1); --#endif -- -- while ((retries > 0) && (usart_write_wait(&(instance->usart_instance), bitdata) != STATUS_OK)) -- { -- retries--; -- } -- --#ifdef DEBUG_PIN -- port_pin_toggle_output_level(DEBUG_PIN_1); --#endif -- -- if (retries <= 0x00) -- { -- return ATCA_TIMEOUT; -- } -- else -- { -- return ATCA_SUCCESS; -- } --} -- --/** \brief HAL implementation of SWI UART receive bytes over ASF. This function receive one byte over UART -- * \param[in] instance instance -- * \param[out] data pointer to space to receive the data -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data) --{ -- uint8_t retries = 100; // This retry is used to compensate the baudrate that do not match when receiving response -- uint16_t bitdata = 0x00; -- --#ifdef DEBUG_PIN -- port_pin_toggle_output_level(DEBUG_PIN_2); --#endif -- // Receive one byte over UART module -- while ((retries > 0) && (usart_read_wait(&(instance->usart_instance), &bitdata) != STATUS_OK)) -- { -- retries--; -- } -- --#ifdef DEBUG_PIN -- port_pin_toggle_output_level(DEBUG_PIN_2); --#endif -- -- *data = bitdata; -- if (retries <= 0x00) -- { -- return ATCA_TIMEOUT; -- } -- else -- { -- return ATCA_SUCCESS; -- } --} -- --/** @} */ -diff --git a/lib/hal/swi_uart_samd21_asf.h b/lib/hal/swi_uart_samd21_asf.h -deleted file mode 100644 -index eb518a3430fd..000000000000 ---- a/lib/hal/swi_uart_samd21_asf.h -+++ /dev/null -@@ -1,84 +0,0 @@ --/** -- * \file -- * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef SWI_UART_SAMD21_ASF_H_ --#define SWI_UART_SAMD21_ASF_H_ -- --#include --#include "cryptoauthlib.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --#define MAX_SWI_BUSES 6 // SAMD21 has up to 6 SERCOMS that can be configured as UART -- --#define RECEIVE_MODE 0 // UART Receive mode, RX enabled --#define TRANSMIT_MODE 1 // UART Transmit mode, RX disabled --#define RX_DELAY { volatile uint8_t delay = 90; while (delay--) { __asm__ (""); } } --#define TX_DELAY 90 -- --#define DEBUG_PIN_1 EXT2_PIN_5 --#define DEBUG_PIN_2 EXT2_PIN_6 --/** \brief this is the hal_data for ATCA HAL for ASF SERCOM -- */ --typedef struct atcaSWImaster --{ -- // struct usart_module for Atmel SWI interface -- struct usart_module usart_instance; -- // for conveniences during interface release phase -- int bus_index; --} ATCASWIMaster_t; -- -- --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance); --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance); --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate); --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode); --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses); -- --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data); --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data); -- --/** @} */ -- --#endif // SWI_UART_ASF_H -diff --git a/lib/hal/swi_uart_samd21_start.c b/lib/hal/swi_uart_samd21_start.c -deleted file mode 100644 -index 0bf4650afaa0..000000000000 ---- a/lib/hal/swi_uart_samd21_start.c -+++ /dev/null -@@ -1,208 +0,0 @@ --/** -- * \file -- * -- * \brief Atmel Crypto Auth hardware interface object -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "swi_uart_samd21_start.h" --#include "basic/atca_helpers.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief -- - this HAL implementation assumes you've included the START SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the START UART drivers are a dependency * -- */ -- --/** \brief HAL implementation of SWI UART init. -- * \param[in] instance instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- instance->USART_SWI = USART_1; -- -- status |= usart_sync_set_mode(&(instance->USART_SWI), USART_MODE_ASYNCHRONOUS); -- // Set data size to 7 -- status |= usart_sync_set_character_size(&(instance->USART_SWI), USART_CHARACTER_SIZE_7BITS); -- // Set parity to no parity -- status |= usart_sync_set_parity(&(instance->USART_SWI), USART_PARITY_NONE); -- // Set data byte to one stopbit -- status |= usart_sync_set_stopbits(&(instance->USART_SWI), USART_STOP_BITS_ONE); -- // Set baudrate to 230400 -- status |= usart_sync_set_baud_rate(&(instance->USART_SWI), 230400); -- // Enable SWI UART -- status |= usart_sync_enable(&(instance->USART_SWI)); -- return status; --} -- --/** \brief HAL implementation of SWI UART deinit. -- * \param[in] instance instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- usart_sync_disable(&(instance->USART_SWI)); -- -- return status; --} -- --/** \brief HAL implementation of SWI UART change baudrate. -- * \param[in] instance instance -- * \param[in] baudrate (typically 230400 or 115200) -- */ --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate) --{ -- // Set baudrate for UART module -- delay_us(50); -- usart_sync_set_baud_rate(&(instance->USART_SWI), baudrate); -- --} -- -- --/** \brief HAL implementation of SWI UART change mode. -- * \param[in] instance instance -- * \param[in] mode (TRANSMIT_MODE or RECEIVE_MODE) -- */ --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode) --{ -- -- usart_sync_disable(&(instance->USART_SWI)); -- -- if (mode == TRANSMIT_MODE) -- { -- // Set baudrate to 230400 -- usart_sync_set_baud_rate(&(instance->USART_SWI), 230400); -- // Disable Receiver -- hri_sercomusart_clear_CTRLB_RXEN_bit(&(instance->USART_SWI.device.hw)); -- hri_sercomusart_set_CTRLB_TXEN_bit(&(instance->USART_SWI.device.hw)); -- } -- else if (mode == RECEIVE_MODE) -- { -- // Set baudrate to 160000 -- usart_sync_set_baud_rate(&(instance->USART_SWI), 160000); -- // Enable Receiver -- hri_sercomusart_clear_CTRLB_TXEN_bit(&(instance->USART_SWI.device.hw)); -- hri_sercomusart_set_CTRLB_RXEN_bit(&(instance->USART_SWI.device.hw)); -- } -- usart_sync_enable(&(instance->USART_SWI)); -- instance->bus_index &= 0x07; --} -- --/** \brief discover UART buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] swi_uart_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- */ --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses) --{ -- /* if every SERCOM was a likely candidate bus, then would need to initialize the entire array to all SERCOM n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / SERCOM map based on SAMD21 Xplained Pro board -- * If you were using a raw SAMD21 on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ -- swi_uart_buses[0] = 4; // default samd21 for xplained dev board --} -- --/** \brief HAL implementation of SWI UART send byte over ASF. This function send one byte over UART -- * \param[in] instance instance -- * \param[in] data number of byte to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data) --{ -- uint8_t retries = 2; -- int32_t byte_sent = 0; -- --#ifdef DEBUG_PIN -- gpio_toggle_pin_level(PA20); --#endif -- // Send one byte over UART module -- while ((retries > 0) && (byte_sent < 1)) -- { -- byte_sent = io_write(&(instance->USART_SWI.io), &data, 1); -- retries--; -- } --#ifdef DEBUG_PIN -- gpio_toggle_pin_level(PA20); --#endif -- if (byte_sent <= 0) -- { -- return ATCA_TIMEOUT; -- } -- else -- { -- return ATCA_SUCCESS; -- } --} -- --/** \brief HAL implementation of SWI UART receive bytes over ASF. This function receive one byte over UART -- * \param[in] instance instance -- * \param[out] data pointer to space to receive the data -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data) --{ -- int32_t byte_sent = 0; -- uint8_t retries = 2; -- --#ifdef DEBUG_PIN -- gpio_toggle_pin_level(PA21); --#endif -- // Receive one byte over UART module -- while ((retries > 0) && (byte_sent < 1)) -- { -- byte_sent = io_read(&(instance->USART_SWI.io), data, 1); -- retries--; -- } --#ifdef DEBUG_PIN -- gpio_toggle_pin_level(PA21); --#endif -- if (byte_sent <= 0) -- { -- return ATCA_TIMEOUT; -- } -- else -- { -- return ATCA_SUCCESS; -- } --} -- --/** @} */ -diff --git a/lib/hal/swi_uart_samd21_start.h b/lib/hal/swi_uart_samd21_start.h -deleted file mode 100644 -index e039228ef7c3..000000000000 ---- a/lib/hal/swi_uart_samd21_start.h -+++ /dev/null -@@ -1,80 +0,0 @@ --/** -- * \file -- * -- * \brief Atmel Crypto Auth hardware interface object -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef SWI_UART_SAMD21_START_H_ --#define SWI_UART_SAMD21_START_H_ -- --#include --#include --#include "atmel_start.h" --#include "cryptoauthlib.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --#define MAX_SWI_BUSES 6 // SAMD21 has up to 6 SERCOMS that can be configured as UART -- --#define RECEIVE_MODE 0 // UART Receive mode, RX enabled --#define TRANSMIT_MODE 1 // UART Transmit mode, RX disabled --#define RX_DELAY 10 --#define TX_DELAY 93 --/** \brief this is the hal_data for ATCA HAL for ASF SERCOM -- */ --typedef struct atcaSWImaster --{ -- // struct usart_module for Atmel SWI interface -- struct usart_sync_descriptor USART_SWI; -- // for conveniences during interface release phase -- int bus_index; --} ATCASWIMaster_t; -- --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance); --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance); --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate); --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode); --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses); -- --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data); --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data); --/** @} */ -- --#endif // SWI_UART_ASF_H -diff --git a/lib/hal/swi_uart_xmega_a3bu_asf.c b/lib/hal/swi_uart_xmega_a3bu_asf.c -deleted file mode 100644 -index 26785cd795ee..000000000000 ---- a/lib/hal/swi_uart_xmega_a3bu_asf.c -+++ /dev/null -@@ -1,258 +0,0 @@ --/** -- * \file -- * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over XMEGA UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#include --#include --#include "swi_uart_xmega_a3bu_asf.h" --#include "basic/atca_helpers.h" -- --#define DEBUG_PIN 1 -- --#ifdef DEBUG_PIN -- #define DEBUG_PIN_1 IOPORT_CREATE_PIN(PORTB, 0) -- #define DEBUG_PIN_2 IOPORT_CREATE_PIN(PORTB, 1) --#endif --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- --/** \brief usart configuration struct */ --static usart_serial_options_t config_usart; --/** \brief sysclk_get_per_hz value */ --static uint32_t u32sysclk; -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF SERCOM UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --/** \brief Implementation of SWI UART init. -- * \param[in] instance instance -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance) --{ --#ifdef DEBUG_PIN -- ioport_init(); -- ioport_set_pin_dir(DEBUG_PIN_1, IOPORT_DIR_OUTPUT); -- ioport_set_pin_dir(DEBUG_PIN_2, IOPORT_DIR_OUTPUT); -- gpio_set_pin_high(DEBUG_PIN_1); -- gpio_set_pin_high(DEBUG_PIN_2); --#endif -- ATCA_STATUS status = ATCA_SUCCESS; -- -- //Save sysclk_get_per_hz value -- u32sysclk = sysclk_get_per_hz(); -- // Set data size to 7 -- config_usart.charlength = USART_CHSIZE_7BIT_gc; -- // Set parity to no parity -- config_usart.paritytype = USART_PMODE_DISABLED_gc; -- // Set data byte to one stopbit -- config_usart.stopbits = false; -- // Set baudrate to 230400 -- config_usart.baudrate = 230400; -- -- switch (instance->bus_index) -- { -- case 0: instance->usart_instance = &USARTC0; break; -- case 1: instance->usart_instance = &USARTC1; break; -- case 2: instance->usart_instance = &USARTD0; break; -- case 3: instance->usart_instance = &USARTD1; break; -- case 4: instance->usart_instance = &USARTE0; break; -- case 5: instance->usart_instance = &USARTF0; break; -- } -- status = usart_serial_init(instance->usart_instance, &config_usart); -- return status; --} -- --/** \brief Implementation of SWI UART deinit. -- * \param[in] instance instance -- * \return ATCA_SUCCESS -- */ --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance) --{ -- ATCA_STATUS status = ATCA_SUCCESS; -- -- instance->usart_instance = NULL; -- return status; --} -- --/** \brief implementation of SWI UART change baudrate. -- * \param[in] instance instance -- * \param[in] baudrate (typically 230400 , 160000 or 115200) -- */ --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate) --{ -- // Set baudrate for UART module -- usart_set_baudrate(instance->usart_instance, baudrate, u32sysclk); --} -- -- --/** \brief implementation of SWI UART change mode. -- * \param[in] instance instance -- * \param[in] mode (TRANSMIT_MODE or RECEIVE_MODE) -- */ --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode) --{ -- switch (mode) -- { -- case TRANSMIT_MODE: -- usart_set_baudrate(instance->usart_instance, 230400, u32sysclk); -- break; -- case RECEIVE_MODE: -- //Reset UART RX buffer. -- usart_rx_disable(instance->usart_instance); -- usart_rx_enable(instance->usart_instance); -- break; -- default: -- break; -- } -- --} -- --/** \brief discover UART buses available for this hardware -- * this maintains a list of logical to physical bus mappings freeing the application -- * of the a-priori knowledge -- * \param[in] swi_uart_buses - an array of logical bus numbers -- * \param[in] max_buses - maximum number of buses the app wants to attempt to discover -- */ --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses) --{ -- /* if every PORT was a likely candidate bus, then would need to initialize the entire array to all PORT n numbers. -- * As an optimization and making discovery safer, make assumptions about bus-num / PORT map based on XMEGA-A3BU Xplained board -- * If you were using a raw XMEGA on your own board, you would supply your own bus numbers based on your particular hardware configuration. -- */ -- swi_uart_buses[0] = 4; // default xmega-a3bu for xplained dev board --} -- --/** \brief HAL implementation of SWI UART send byte over ASF. This function send one byte over UART -- * \param[in] instance instance -- * \param[in] data byte to send -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data) --{ -- int8_t timeout = 0x7F; -- bool data_reg_empty = false; -- ATCA_STATUS status = ATCA_COMM_FAIL; -- -- // Send one byte over UART module --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_1); --#endif -- // Send one byte over UART module -- timeout = 0x7F; -- while ((timeout > 0) && (data_reg_empty == false)) -- { -- data_reg_empty = usart_data_register_is_empty(instance->usart_instance); -- timeout--; -- } -- if (data_reg_empty) -- { -- usart_put(instance->usart_instance, data); -- while (!usart_tx_is_complete(instance->usart_instance)) -- { -- ; -- } -- usart_clear_tx_complete(instance->usart_instance); -- status = ATCA_SUCCESS; -- } --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_1); --#endif -- if (timeout > 0) -- { -- return status; -- } -- else -- { -- return ATCA_TIMEOUT; -- } --} -- --/** \brief HAL implementation of SWI UART receive bytes over ASF. This function receive one byte over UART -- * \param[in] instance instance -- * \param[out] data pointer to space to receive the data -- * \return ATCA_SUCCESS on success, otherwise an error code. -- */ --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data) --{ -- int8_t timeout, retries = 0x2; // This retry is used to compensate the baudrate that do not match when receiving response -- -- *data = 0xFF; -- bool rx_complete = false; -- ATCA_STATUS status = ATCA_COMM_FAIL; --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_2); --#endif -- // Receive one byte over UART module -- while ((retries > 0) && (status != ATCA_SUCCESS)) -- { -- timeout = 0x7F; retries--; -- while ((timeout > 0) && (rx_complete == false)) -- { -- rx_complete = usart_rx_is_complete(instance->usart_instance); -- timeout--; -- } -- -- if (rx_complete) -- { -- *data = usart_get(instance->usart_instance); -- if ((*data >= 0x70) && (*data <= 0x7F)) -- { -- status = ATCA_SUCCESS; -- } -- else -- { -- status = ATCA_COMM_FAIL; -- } -- } -- } --#ifdef DEBUG_PIN -- gpio_toggle_pin(DEBUG_PIN_2); --#endif -- if (timeout > 0) -- { -- return status; -- } -- else -- { -- return ATCA_TIMEOUT; -- } --} -- --/** @} */ -diff --git a/lib/hal/swi_uart_xmega_a3bu_asf.h b/lib/hal/swi_uart_xmega_a3bu_asf.h -deleted file mode 100644 -index e9bfffc58fc6..000000000000 ---- a/lib/hal/swi_uart_xmega_a3bu_asf.h -+++ /dev/null -@@ -1,83 +0,0 @@ --/** -- * \file -- * \brief ATXMEGA's ATCA Hardware abstraction layer for SWI interface over XMEGA UART drivers. -- * -- * Prerequisite: add UART Polled support to application in Atmel Studio -- * -- * \copyright (c) 2017 Microchip Technology Inc. and its subsidiaries. -- * You may use this software and any derivatives exclusively with -- * Microchip products. -- * -- * \page License -- * -- * (c) 2017 Microchip Technology Inc. and its subsidiaries. You may use this -- * software and any derivatives exclusively with Microchip products. -- * -- * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -- * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -- * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A -- * PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION -- * WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. -- * -- * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, -- * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND -- * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS -- * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -- * FULLEST EXTENT ALLOWED BY LAW, MICROCHIPS TOTAL LIABILITY ON ALL CLAIMS IN -- * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -- * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -- * -- * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE -- * TERMS. -- */ -- --#ifndef SWI_UART_XMEGA_A3BU_ASF_H_ --#define SWI_UART_XMEGA_A3BU_ASF_H_ -- --#include --#include "cryptoauthlib.h" --#include "serial.h" -- --/** \defgroup hal_ Hardware abstraction layer (hal_) -- * -- * \brief -- * These methods define the hardware abstraction layer for communicating with a CryptoAuth device -- * -- @{ */ -- -- --/** \brief -- - this HAL implementation assumes you've included the ASF UART libraries in your project, otherwise, -- the HAL layer will not compile because the ASF UART drivers are a dependency * -- */ -- --#define MAX_SWI_BUSES 6 // XMEGA A3BU has up to 6 ports -- --#define RECEIVE_MODE 0 // UART Receive mode, RX enabled --#define TRANSMIT_MODE 1 // UART Transmit mode, RX disabled --#define RX_DELAY 10 // Delay before responses come --#define TX_DELAY 90 // Delay before new flag is sent -- --/** \brief this is the hal_data for ATCA HAL for SWI UART -- */ --typedef struct atcaSWImaster --{ -- // struct usart_module for Atmel SWI interface -- usart_if usart_instance; -- // for conveniences during interface release phase -- int bus_index; --} ATCASWIMaster_t; -- -- --ATCA_STATUS swi_uart_init(ATCASWIMaster_t *instance); --ATCA_STATUS swi_uart_deinit(ATCASWIMaster_t *instance); --void swi_uart_setbaud(ATCASWIMaster_t *instance, uint32_t baudrate); --void swi_uart_mode(ATCASWIMaster_t *instance, uint8_t mode); --void swi_uart_discover_buses(int swi_uart_buses[], int max_buses); -- --ATCA_STATUS swi_uart_send_byte(ATCASWIMaster_t *instance, uint8_t data); --ATCA_STATUS swi_uart_receive_byte(ATCASWIMaster_t *instance, uint8_t *data); -- --/** @} */ -- --#endif // SWI_UART_XMEGA_A3BU_ASF_H diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch new file mode 100644 index 000000000..031d2033e --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch @@ -0,0 +1,30 @@ +From: Gabriel Valcazar +Date: Mon, 4 Nov 2019 16:11:48 +0100 +Subject: [PATCH 2/6] lib: apply library version number to CMake VERSION + property + +This way, CMake will generate a shared library with the version number and an +additional symlink without it. This avoids bitbake errors that appear when +creating *-dev packages, as Yocto development packages should only include +the soname symlinks instead of the actual library file. + +https://jira.digi.com/browse/DEL-6826 + +Signed-off-by: Gabriel Valcazar +--- + lib/CMakeLists.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt +index b198d1f..88533f1 100644 +--- a/lib/CMakeLists.txt ++++ b/lib/CMakeLists.txt +@@ -93,6 +93,8 @@ endif() + + add_library(cryptoauth ${CRYPTOAUTH_SRC} ${ATCACERT_DEF_SRC}) + ++set_property(TARGET cryptoauth PROPERTY VERSION "${VERSION}") ++ + set_property(TARGET cryptoauth PROPERTY C_STANDARD 99) + + if(ATCA_PRINTF) diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-Build-cryptochip-cmd-processor-application-along-wit.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-Build-cryptochip-cmd-processor-application-along-wit.patch deleted file mode 100644 index e25c35d85..000000000 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-Build-cryptochip-cmd-processor-application-along-wit.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Gabriel Valcazar -Date: Mon, 26 Feb 2018 11:42:50 +0100 -Subject: [PATCH 1/2] Build cryptochip-cmd-processor application along with the - library - -This new test application is more complete than ecc-test-main. It includes a -command line with different test runs for the chip's basic functionality, -helper functions, certificate functions and allows the configuration to be -read, among other things. - -Hardcode the app to use the ATECC508A and remove all code that is specific for -other chips. - -https://jira.digi.com/browse/DEL-5763 - -Signed-off-by: Gabriel Valcazar ---- - Makefile | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index a471428..c57b1bf 100644 ---- a/Makefile -+++ b/Makefile -@@ -7,7 +7,7 @@ SUBDIRS= lib test - - .PHONY: tgt_lib tgt_test clean - --all: tgt_lib tgt_test ecc-test -+all: tgt_lib tgt_test ecc-test cmd-processor - - %.o: %.c - $(CC) $(CFLAGS) -o $@ -c $< -@@ -22,11 +22,15 @@ ecc-test: tgt_lib tgt_test - $(CC) -c ecc-test-main.c $(CFLAGS) $(LDFLAGS) -I ./lib/ -I ./test/ - $(CC) -o ecc-test-main ecc-test-main.o $(LDFLAGS) test/tls/atcatls_tests.o -L lib -L test -lm -lc -lrt -lcryptoauth -lunity - -+cmd-processor: tgt_lib tgt_test -+ $(CC) -o cryptochip-cmd-processor test/*.o $(LDFLAGS) test/*/*.o -L lib -L test -lcryptoauth -+ - install: - for a in $(SUBDIRS); do $(MAKE) -C $$a $@; done - install -d $(DESTDIR)/usr/bin - install -m 0755 ecc-test-main $(DESTDIR)/usr/bin/ -+ install -m 0755 cryptochip-cmd-processor $(DESTDIR)/usr/bin - - clean: -- rm -f *.o *.a ecc-test-main -+ rm -f *.o *.a ecc-test-main cryptochip-cmd-processor - $(foreach subdir,$(basename $(SUBDIRS)),$(MAKE) -w -C $(subdir) clean;) diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-pkcs11-rename-template-configuration-file-to-its-int.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-pkcs11-rename-template-configuration-file-to-its-int.patch new file mode 100644 index 000000000..a92d49e14 --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0003-pkcs11-rename-template-configuration-file-to-its-int.patch @@ -0,0 +1,84 @@ +From: Gabriel Valcazar +Date: Thu, 7 Nov 2019 13:43:53 +0100 +Subject: [PATCH 3/6] pkcs11: rename template configuration file to its + intended name + +Otherwise, users will need to manually rename the file in the rootfs to use +the pkcs11 feature. + +https://jira.digi.com/browse/DEL-6835 + +Signed-off-by: Gabriel Valcazar +--- + CMakeLists.txt | 4 ++-- + app/pkcs11/0.conf | 19 +++++++++++++++++++ + app/pkcs11/slot.conf.tmpl | 19 ------------------- + 3 files changed, 21 insertions(+), 21 deletions(-) + create mode 100644 app/pkcs11/0.conf + delete mode 100644 app/pkcs11/slot.conf.tmpl + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9326fd1..00214d3 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -80,8 +80,8 @@ install(CODE " + install(DIRECTORY DESTINATION ${DEFAULT_STORE_PATH}) + install(CODE "execute_process(COMMAND chmod 1777 ${DEFAULT_STORE_PATH})") + install(CODE " +- if(NOT EXISTS ${DEFAULT_STORE_PATH}/slot.conf.tmpl) +- file(INSTALL ${PROJECT_SOURCE_DIR}/app/pkcs11/slot.conf.tmpl ++ if(NOT EXISTS ${DEFAULT_STORE_PATH}/0.conf) ++ file(INSTALL ${PROJECT_SOURCE_DIR}/app/pkcs11/0.conf + DESTINATION ${DEFAULT_STORE_PATH}) + endif() + ") +diff --git a/app/pkcs11/0.conf b/app/pkcs11/0.conf +new file mode 100644 +index 0000000..b637abd +--- /dev/null ++++ b/app/pkcs11/0.conf +@@ -0,0 +1,19 @@ ++# Reserved Configuration for a device ++# The objects in this file will be created and marked as undeletable ++# These are processed in order. Configuration parameters must be comma ++# delimited and may not contain spaces ++ ++interface = i2c,0xB0 ++freeslots = 1,2,3 ++ ++# Slot 0 is the primary private key ++object = private,device,0 ++ ++# Slot 10 is the certificate data for the device's public key ++#object = certificate,device,10 ++ ++# Slot 12 is the intermedate/signer certificate data ++#object = certificate,signer,12 ++ ++# Slot 15 is a public key ++object = public,root,15 +diff --git a/app/pkcs11/slot.conf.tmpl b/app/pkcs11/slot.conf.tmpl +deleted file mode 100644 +index b637abd..0000000 +--- a/app/pkcs11/slot.conf.tmpl ++++ /dev/null +@@ -1,19 +0,0 @@ +-# Reserved Configuration for a device +-# The objects in this file will be created and marked as undeletable +-# These are processed in order. Configuration parameters must be comma +-# delimited and may not contain spaces +- +-interface = i2c,0xB0 +-freeslots = 1,2,3 +- +-# Slot 0 is the primary private key +-object = private,device,0 +- +-# Slot 10 is the certificate data for the device's public key +-#object = certificate,device,10 +- +-# Slot 12 is the intermedate/signer certificate data +-#object = certificate,signer,12 +- +-# Slot 15 is a public key +-object = public,root,15 diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-Remove-unnecessary-code-from-cryptochip-cmd-processo.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-Remove-unnecessary-code-from-cryptochip-cmd-processo.patch deleted file mode 100644 index cd9f30cf1..000000000 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-Remove-unnecessary-code-from-cryptochip-cmd-processo.patch +++ /dev/null @@ -1,454 +0,0 @@ -From: Gabriel Valcazar -Date: Fri, 23 Feb 2018 13:50:29 +0100 -Subject: [PATCH 2/2] Remove unnecessary code from cryptochip-cmd-processor - -Some test commands apply to chips other than the ATECC508A, and can cause -errors when used incorrectly. Remove all code that doesn't apply to our -platforms. - -https://jira.digi.com/browse/DEL-5763 - -Signed-off-by: Gabriel Valcazar ---- - test/cmd-processor.c | 348 ++------------------------------------------------- - 1 file changed, 13 insertions(+), 335 deletions(-) - -diff --git a/test/cmd-processor.c b/test/cmd-processor.c -index c8c60e0..592157e 100644 ---- a/test/cmd-processor.c -+++ b/test/cmd-processor.c -@@ -92,10 +92,6 @@ static void sernum(void); - static void discover(void); - static void select_device(ATCADeviceType device_type); - static int run_test(void* fptest); --static void select_204(void); --static void select_108(void); --static void select_508(void); --static void select_608(void); - static void run_basic_tests(void); - static void run_unit_tests(void); - static void run_otpzero_tests(void); -@@ -103,20 +99,11 @@ static void run_helper_tests(void); - static void help(void); - static int parse_cmd(const char *command); - static void run_all_tests(void); --static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider); --static void set_clock_divider_m0(void); --static void set_clock_divider_m1(void); --static void set_clock_divider_m2(void); - - static const char* argv[] = { "manual", "-v" }; - static t_menu_info mas_menu_info[] = - { - { "help", "Display Menu", help }, -- { "discover", "Discover Buses and Devices", discover }, -- { "204", "Set Target Device to ATECC204A", select_204 }, -- { "108", "Set Target Device to ATECC108A", select_108 }, -- { "508", "Set Target Device to ATECC508A", select_508 }, -- { "608", "Set Target Device to ATECC608A", select_608 }, - { "info", "Get the Chip Revision", info }, - { "sernum", "Get the Chip Serial Number", sernum }, - { "basic", "Run Basic Test on Selected Device", run_basic_tests }, -@@ -135,12 +122,9 @@ static t_menu_info mas_menu_info[] = - { "cio", "Run Unit Test on Cert I/O", (fp_menu_handler)certio_unit_tests }, - #endif - #ifdef TEST_SW_CRYPTO -- { "crypto", "Run Unit Tests for Software Crypto Functions", atca_crypto_sw_tests }, -+ { "crypto", "Run Unit Tests for Software Crypto Functions", (fp_menu_handler)atca_crypto_sw_tests }, - #endif - { "all", "Run all unit tests, locking as needed.", run_all_tests }, -- { "clkdivm0", "Set ATECC608A to ClockDivider M0(0x00)", set_clock_divider_m0}, -- { "clkdivm1", "Set ATECC608A to ClockDivider M1(0x05)", set_clock_divider_m1}, -- { "clkdivm2", "Set ATECC608A to ClockDivider M2(0x0D)", set_clock_divider_m2}, - { NULL, NULL, NULL }, - }; - -@@ -160,6 +144,8 @@ int main(int argc, char* argv[]) - return 1; - } - -+ select_device(ATECC508A); -+ - while (true) - { - printf("$ "); -@@ -230,96 +216,13 @@ static void help(void) - } - } - --static void select_204(void) --{ -- select_device(ATSHA204A); --} --static void select_108(void) --{ -- select_device(ATECC108A); --} --static void select_508(void) --{ -- select_device(ATECC508A); --} --static void select_608(void) --{ -- select_device(ATECC608A); --} -- --static void update_chip_mode(uint8_t* chip_mode, uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) --{ -- if (i2c_user_extra_add != 0xFF) -- { -- *chip_mode &= ~ATCA_CHIPMODE_I2C_ADDRESS_FLAG; -- *chip_mode |= i2c_user_extra_add & ATCA_CHIPMODE_I2C_ADDRESS_FLAG; -- } -- if (ttl_enable != 0xFF) -- { -- *chip_mode &= ~ATCA_CHIPMODE_TTL_ENABLE_FLAG; -- *chip_mode |= ttl_enable & ATCA_CHIPMODE_TTL_ENABLE_FLAG; -- } -- if (watchdog != 0xFF) -- { -- *chip_mode &= ~ATCA_CHIPMODE_WATCHDOG_MASK; -- *chip_mode |= watchdog & ATCA_CHIPMODE_WATCHDOG_MASK; -- } -- if (clock_divider != 0xFF) -- { -- *chip_mode &= ~ATCA_CHIPMODE_CLOCK_DIV_MASK; -- *chip_mode |= clock_divider & ATCA_CHIPMODE_CLOCK_DIV_MASK; -- } --} -- --static ATCA_STATUS check_clock_divider(void) --{ -- ATCA_STATUS status; -- uint8_t chip_mode = 0; -- -- if (gCfg->devtype != ATECC608A) -- { -- printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); -- return ATCA_GEN_FAIL; -- } -- -- // Update the actual ATECC608A chip mode so it takes effect immediately -- status = atcab_init(gCfg); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_init() failed with ret=0x%08X\r\n", status); -- return status; -- } -- -- do -- { -- // Read current config values -- status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, ATCA_CHIPMODE_OFFSET, &chip_mode, 1); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); -- break; -- } -- -- // Update the ATECC608A test config data so all the unit tests will run with the new chip mode -- update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], 0xFF, 0xFF, chip_mode & ATCA_CHIPMODE_WATCHDOG_MASK, chip_mode & ATCA_CHIPMODE_CLOCK_DIV_MASK); -- -- } while (0); -- -- atcab_release(); -- return status; --} -- - static void run_basic_tests(void) - { -- if (gCfg->devtype == ATECC608A) -- check_clock_divider(); - run_test(RunAllBasicTests); - } - - static void run_unit_tests(void) - { -- if (gCfg->devtype == ATECC608A) -- check_clock_divider(); - run_test(RunAllFeatureTests); - } - static void run_otpzero_tests(void) -@@ -453,37 +356,6 @@ static ATCA_STATUS do_randoms(void) - - return status; - } --static void discover(void) --{ -- ATCAIfaceCfg ifaceCfgs[10]; -- int i; -- const char *devname[] = { "ATSHA204A", "ATECC108A", "ATECC508A", "ATECC608A" }; // indexed by ATCADeviceType -- -- for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) -- { -- ifaceCfgs[i].devtype = ATCA_DEV_UNKNOWN; -- ifaceCfgs[i].iface_type = ATCA_UNKNOWN_IFACE; -- } -- -- printf("Searching..."); -- atcab_cfg_discover(ifaceCfgs, sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); -- for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) -- { -- if (ifaceCfgs[i].devtype != ATCA_DEV_UNKNOWN) -- { -- printf("Found %s ", devname[ifaceCfgs[i].devtype]); -- if (ifaceCfgs[i].iface_type == ATCA_I2C_IFACE) -- { -- printf("@ bus %d addr %02x", ifaceCfgs[i].atcai2c.bus, ifaceCfgs[i].atcai2c.slave_address); -- } -- if (ifaceCfgs[i].iface_type == ATCA_SWI_IFACE) -- { -- printf("@ bus %d", ifaceCfgs[i].atcaswi.bus); -- } -- printf("\r\n"); -- } -- } --} - static void info(void) - { - ATCA_STATUS status; -@@ -636,18 +508,7 @@ static ATCA_STATUS get_serial_no(uint8_t *sernum) - - static void select_device(ATCADeviceType device_type) - { -- ATCA_STATUS status; -- -- status = set_test_config(device_type); -- -- if (status == ATCA_SUCCESS) -- { -- printf("Device Selected.\r\n"); -- } -- else -- { -- printf("IFace Cfg are NOT available\r\n"); -- } -+ set_test_config(device_type); - } - - static int run_test(void* fptest) -@@ -670,9 +531,6 @@ static void run_all_tests(void) - bool is_data_locked = false; - int fails = 0; - -- if (gCfg->devtype == ATECC608A) -- check_clock_divider(); -- - status = is_device_locked(LOCK_ZONE_CONFIG, &is_config_locked); - if (status != ATCA_SUCCESS) - { -@@ -814,204 +672,24 @@ static ATCA_STATUS set_test_config(ATCADeviceType deviceType) - gCfg->devtype = ATCA_DEV_UNKNOWN; - gCfg->iface_type = ATCA_UNKNOWN_IFACE; - -- switch (deviceType) -- { -- case ATSHA204A: --#if defined(ATCA_HAL_I2C) -- *gCfg = cfg_atsha204a_i2c_default; --#elif defined(ATCA_HAL_SWI) -- *gCfg = cfg_atsha204a_swi_default; --#elif defined(ATCA_HAL_KIT_HID) -- *gCfg = cfg_atsha204a_kithid_default; --#elif defined(ATCA_HAL_KIT_CDC) -- *gCfg = cfg_atsha204a_kitcdc_default; --#elif defined(ATCA_HAL_CUSTOM) -- *gCfg = g_cfg_atsha204a_custom; --#else --#error "HAL interface is not selected"; --#endif -- break; -- -- case ATECC108A: --#if defined(ATCA_HAL_I2C) -- *gCfg = cfg_ateccx08a_i2c_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_SWI) -- *gCfg = cfg_ateccx08a_swi_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_KIT_HID) -- *gCfg = cfg_ateccx08a_kithid_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_KIT_CDC) -- *gCfg = cfg_ateccx08a_kitcdc_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_CUSTOM) -- *gCfg = g_cfg_atecc108a_custom; --#else --#error "HAL interface is not selected"; --#endif -- break; -- -- case ATECC508A: --#if defined(ATCA_HAL_I2C) -- *gCfg = cfg_ateccx08a_i2c_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_SWI) -- *gCfg = cfg_ateccx08a_swi_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_KIT_HID) -- *gCfg = cfg_ateccx08a_kithid_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_KIT_CDC) -- *gCfg = cfg_ateccx08a_kitcdc_default; -- gCfg->devtype = deviceType; --#elif defined(ATCA_HAL_CUSTOM) -- *gCfg = g_cfg_atecc508a_custom; --#else --#error "HAL interface is not selected"; --#endif -- break; -- -- case ATECC608A: - #if defined(ATCA_HAL_I2C) -- *gCfg = cfg_ateccx08a_i2c_default; -- gCfg->devtype = deviceType; -+ *gCfg = cfg_ateccx08a_i2c_default; -+ gCfg->devtype = deviceType; - #elif defined(ATCA_HAL_SWI) -- *gCfg = cfg_ateccx08a_swi_default; -- gCfg->devtype = deviceType; -+ *gCfg = cfg_ateccx08a_swi_default; -+ gCfg->devtype = deviceType; - #elif defined(ATCA_HAL_KIT_HID) -- *gCfg = cfg_ateccx08a_kithid_default; -- gCfg->devtype = deviceType; -+ *gCfg = cfg_ateccx08a_kithid_default; -+ gCfg->devtype = deviceType; - #elif defined(ATCA_HAL_KIT_CDC) -- *gCfg = cfg_ateccx08a_kitcdc_default; -- gCfg->devtype = deviceType; -+ *gCfg = cfg_ateccx08a_kitcdc_default; -+ gCfg->devtype = deviceType; - #elif defined(ATCA_HAL_CUSTOM) -- *gCfg = g_cfg_atecc608a_custom; -+ *gCfg = g_cfg_atecc508a_custom; - #else - #error "HAL interface is not selected"; - #endif -- break; -- -- default: -- //device type wasn't found, return with error -- return ATCA_GEN_FAIL; -- } -- -- #ifdef ATCA_RASPBERRY_PI_3 -- gCfg->atcai2c.bus = 1; -- #endif - - return ATCA_SUCCESS; - } - --static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) --{ -- ATCA_STATUS status; -- uint8_t config_word[ATCA_WORD_SIZE]; -- bool is_config_locked = false; -- -- if (gCfg->devtype != ATECC608A) -- { -- printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); -- return ATCA_GEN_FAIL; -- } -- -- status = is_device_locked(LOCK_ZONE_CONFIG, &is_config_locked); -- if (status != ATCA_SUCCESS) -- { -- printf("is_device_locked() failed with ret=0x%08X\r\n", status); -- return status; -- } -- -- if (is_config_locked) -- { -- printf("Current device is config locked. Can't change clock divider. "); -- } -- -- // Update the actual ATECC608A chip mode so it takes effect immediately -- status = atcab_init(gCfg); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_init() failed with ret=0x%08X\r\n", status); -- return status; -- } -- -- do -- { -- // Read current config values -- status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); -- break; -- } -- -- if (is_config_locked) -- { -- printf("Currently set to 0x%02X.\r\n", (int)(config_word[3] >> 3)); -- status = ATCA_GEN_FAIL; -- break; -- } -- -- // Update ChipMode -- update_chip_mode(&config_word[3], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); -- -- // Write config values back to chip -- status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_write_bytes_zone() failed with ret=0x%08X\r\n", status); -- break; -- } -- -- // Put to sleep so new values take effect -- status = atcab_wakeup(); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_wakeup() failed with ret=0x%08X\r\n", status); -- break; -- } -- status = atcab_sleep(); -- if (status != ATCA_SUCCESS) -- { -- printf("atcab_sleep() failed with ret=0x%08X\r\n", status); -- break; -- } -- -- // Update the ATECC608A test config data so all the unit tests will run with the new chip mode -- update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); -- -- } while (0); -- -- atcab_release(); -- return status; --} -- --static void set_clock_divider_m0(void) --{ -- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M0); -- if (status == ATCA_SUCCESS) -- { -- printf("Set device to clock divider M0 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M0 >> 3); -- } --} -- --static void set_clock_divider_m1(void) --{ -- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M1); -- if (status == ATCA_SUCCESS) -- { -- printf("Set device to clock divider M1 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M1 >> 3); -- } --} -- --static void set_clock_divider_m2(void) --{ -- // Additionally set watchdog to long settings (~13s) as some commands -- // can't complete in time on the faster watchdog setting. -- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_LONG, ATCA_CHIPMODE_CLOCK_DIV_M2); -- if (status == ATCA_SUCCESS) -- { -- printf("Set device to clock divider M2 (0x%02X) and watchdog to 13s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M2 >> 3); -- } --} -\ No newline at end of file diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-lib-install-pkg-config-file-and-header-files.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-lib-install-pkg-config-file-and-header-files.patch new file mode 100644 index 000000000..82f33a002 --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0004-lib-install-pkg-config-file-and-header-files.patch @@ -0,0 +1,82 @@ +From: Gabriel Valcazar +Date: Thu, 7 Nov 2019 14:16:53 +0100 +Subject: [PATCH 4/6] lib: install pkg-config file and header files + +These are needed to be able to develop using cryptoauthlib. + +https://jira.digi.com/browse/DEL-6826 + +Signed-off-by: Gabriel Valcazar +--- + CMakeLists.txt | 15 +++++++++++++++ + lib/CMakeLists.txt | 4 ++++ + lib/cryptoauthlib.pc.in | 11 +++++++++++ + 3 files changed, 30 insertions(+) + create mode 100644 lib/cryptoauthlib.pc.in + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 00214d3..f95736d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -33,6 +33,10 @@ set(DEFAULT_CONF_PATH "${CMAKE_INSTALL_FULL_SYSCONFDIR}/${PROJECT_NAME}" CACHE + STRING "The default location of ${PROJECT_NAME}.conf") + set(DEFAULT_STORE_PATH "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/${PROJECT_NAME}" CACHE + STRING "The default location of the filestore directory") ++set(DEFAULT_PKGCONFIG_PATH "${DEFAULT_LIB_PATH}/pkgconfig" CACHE ++ STRING "The default location of the library's pkg-config file") ++set(DEFAULT_INCLUDE_PATH "${CMAKE_INSTALL_FULL_INCLUDEDIR}" CACHE ++ STRING "The default location of the library's header files") + endif() + + set(DEFAULT_CONF_FILE_NAME "${PROJECT_NAME}.conf" CACHE +@@ -49,6 +53,9 @@ endif() + # Set up a default configuration file to install + configure_file(${PROJECT_SOURCE_DIR}/app/pkcs11/cryptoauthlib.conf.in ${PROJECT_BINARY_DIR}/${DEFAULT_CONF_FILE_NAME}) + ++# Set up the pkg-config file ++configure_file(${PROJECT_SOURCE_DIR}/lib/${PROJECT_NAME}.pc.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc @ONLY) ++ + message(STATUS "Building Configuration: ${CMAKE_BUILD_TYPE}") + + # Packaging +@@ -86,3 +93,11 @@ install(CODE " + endif() + ") + ++install(DIRECTORY DESTINATION ${DEFAULT_PKGCONFIG_PATH}) ++install(CODE " ++ if(NOT EXISTS ${DEFAULT_PKGCONFIG_PATH}/${PROJECT_NAME}.pc) ++ file(INSTALL ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc ++ DESTINATION ${DEFAULT_PKGCONFIG_PATH}) ++ endif() ++ ") ++ +diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt +index 88533f1..d4749ec 100644 +--- a/lib/CMakeLists.txt ++++ b/lib/CMakeLists.txt +@@ -128,3 +128,7 @@ endif() + if(DEFAULT_LIB_PATH) + install(TARGETS ${PROJECT_NAME} DESTINATION ${DEFAULT_LIB_PATH}) + endif() ++ ++if(DEFAULT_INCLUDE_PATH) ++install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DESTINATION "${DEFAULT_INCLUDE_PATH}" FILES_MATCHING PATTERN "*.h") ++endif() +diff --git a/lib/cryptoauthlib.pc.in b/lib/cryptoauthlib.pc.in +new file mode 100644 +index 0000000..e682913 +--- /dev/null ++++ b/lib/cryptoauthlib.pc.in +@@ -0,0 +1,11 @@ ++prefix=/usr ++exec_prefix=${prefix} ++libdir=@CMAKE_INSTALL_FULL_LIBDIR@ ++includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ ++ ++Name: @PROJECT_NAME@ ++Description: Atmel Cryptochip library for ATECC508A ++Version: @VERSION@ ++ ++Libs: -L${libdir} -lcryptoauth ++Cflags: -I${includedir} -I${includedir}/@PROJECT_NAME@ diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb index 1ba3edc2b..d1b361806 100644 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb @@ -1,21 +1,20 @@ -# Copyright (C) 2017, 2018 Digi International Inc. +# Copyright (C) 2017-2019 Digi International Inc. SUMMARY = "Microchip CryptoAuthentication Library" SECTION = "libs" LICENSE = "MICROCHIP_CRYPTOAUTHLIB_LICENSE" -LIC_FILES_CHKSUM = "file://license.txt;endline=19;md5=5bcd26c644867b127c2cce82960fae7b" +LIC_FILES_CHKSUM = "file://license.txt;md5=84f2905dc39d2f8cdffb00af6f9e6d4e" -SRCBRANCH = "master" -SRCREV = "c6da3358a102c10d954372598c6efef8ad84c9ee" +SRCREV = "a0007d2f6c42fddab5dca1575e0f404788829ddc" GIT_URI ?= "git://github.com/MicrochipTech/cryptoauthlib.git;protocol=https" SRC_URI = " \ ${GIT_URI};nobranch=1 \ - file://0001-Port-changes-from-the-cryptoauth-engine-repo-to-the-.patch \ - file://0002-Remove-unused-HAL-implementations.patch \ - file://0003-Build-cryptochip-cmd-processor-application-along-wit.patch \ - file://0004-Remove-unnecessary-code-from-cryptochip-cmd-processo.patch \ + file://0001-lib-add-parameters-to-be-able-to-modify-default-I2C-.patch \ + file://0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch \ + file://0003-pkcs11-rename-template-configuration-file-to-its-int.patch \ + file://0004-lib-install-pkg-config-file-and-header-files.patch \ " S = "${WORKDIR}/git" @@ -27,17 +26,16 @@ I2C_BUS_ccimx8x = "0" I2C_SPEED ?= "100000" -CFLAGS += "-DATCA_HAL_I2C_BUS=${I2C_BUS} -DATCA_HAL_I2C_SPEED=${I2C_SPEED}" +EXTRA_OECMAKE += "-DATCA_HAL_I2C_BUS=${I2C_BUS} -DATCA_HAL_I2C_SPEED=${I2C_SPEED}" -do_patch[prefuncs] = "change_line_endings" +inherit cmake -change_line_endings() { - find ${S} -type f -name '*.[ch]' -print0 | xargs -0 sed -i -e 's/\r//g' +do_install_append() { + # Rename the folder containing the header files to be more package-specific + mv ${D}${includedir}/lib ${D}${includedir}/cryptoauthlib } -do_install() { - oe_runmake DESTDIR=${D} install -} +RDEPENDS_${PN} = "libp11" PACKAGE_ARCH = "${MACHINE_ARCH}" COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" From 3e8321b63ce4cb4b7b70798f1575586c2b8fb601 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 12 Nov 2019 11:44:05 +0100 Subject: [PATCH 017/120] cryptoauthlib: add cryptoauthlib-test package This adds the same example application that was used for the old version of the library, but it has been separated into a proper package this time. Recommend said package when installing the library. https://jira.digi.com/browse/DEL-6826 Signed-off-by: Gabriel Valcazar --- .../0005-test-add-CMakeLists.txt.patch | 96 ++++ ...nnecessary-code-from-cryptoauth_test.patch | 470 ++++++++++++++++++ .../cryptoauthlib/cryptoauthlib_git.bb | 14 +- 3 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0005-test-add-CMakeLists.txt.patch create mode 100644 meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0006-Remove-unnecessary-code-from-cryptoauth_test.patch diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0005-test-add-CMakeLists.txt.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0005-test-add-CMakeLists.txt.patch new file mode 100644 index 000000000..2a6eb5d44 --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0005-test-add-CMakeLists.txt.patch @@ -0,0 +1,96 @@ +From: Gabriel Valcazar +Date: Thu, 7 Nov 2019 16:36:35 +0100 +Subject: [PATCH 5/6] test: add CMakeLists.txt + +This file was ported form the master branch to be able to compile the +cryptoauth_test app. Additional installation instructions were added as well. + +Move the ATCA_HAL_I2C build option to the root CMake file to enable it for both +the library and the test app. + +https://jira.digi.com/browse/DEL-6826 + +Signed-off-by: Gabriel Valcazar +--- + CMakeLists.txt | 3 +++ + lib/CMakeLists.txt | 1 - + test/CMakeLists.txt | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 47 insertions(+), 1 deletion(-) + create mode 100644 test/CMakeLists.txt + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 429c06c..a490557 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,9 @@ + cmake_minimum_required(VERSION 2.6.4) + project (cryptoauthlib) + ++# Enable the I2C build option at a global level by default to use it for both the library and the test app ++option(ATCA_HAL_I2C "Include the I2C Hal Driver - Linux & MCU only" ON) ++ + # Set the current release version + set(VERSION "2018.10.26") + set(VERSION_MAJOR 2028) +diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt +index 88533f1..6a00f7c 100644 +--- a/lib/CMakeLists.txt ++++ b/lib/CMakeLists.txt +@@ -3,7 +3,6 @@ project(cryptoauth) + + # Various Options for Build + option(ATCA_HAL_KIT_HID "Include the HID HAL Driver") +-option(ATCA_HAL_I2C "Include the I2C Hal Driver - Linux & MCU only" ON) + option(ATCA_HAL_CUSTOM "Include support for Custom/Plug-in Hal Driver" ON) + option(ATCA_PRINTF "Enable Debug print statements in library") + option(ATCA_PKCS11 "Build PKCS11 Library") +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +new file mode 100644 +index 0000000..7155f38 +--- /dev/null ++++ b/test/CMakeLists.txt +@@ -0,0 +1,44 @@ ++cmake_minimum_required(VERSION 2.6.4) ++project (cryptoauth_test) ++ ++file(GLOB TEST_ATCACERT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "atcacert/*.c") ++file(GLOB TEST_JWT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "jwt/*.c") ++file(GLOB TEST_TNG_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "tng/*.c") ++file(GLOB TEST_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c") ++ ++if(ATCA_HAL_KIT_HID) ++add_definitions(-DATCA_HAL_KIT_HID) ++endif(ATCA_HAL_KIT_HID) ++ ++if(ATCA_HAL_KIT_CDC) ++add_definitions(-DATCA_HAL_KIT_CDC) ++endif(ATCA_HAL_KIT_CDC) ++ ++if(ATCA_HAL_I2C) ++add_definitions(-DATCA_HAL_I2C) ++endif(ATCA_HAL_I2C) ++ ++if(ATCA_HAL_CUSTOM) ++add_definitions(-DATCA_HAL_CUSTOM) ++endif() ++ ++add_executable(cryptoauth_test ${TEST_SRC} ${TEST_TNG_SRC} ${TEST_JWT_SRC} ${TEST_ATCACERT_SRC}) ++ ++include_directories(cryptoauth_test ${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../lib) ++ ++target_link_libraries(cryptoauth_test cryptoauth) ++ ++if(UNIX) ++target_link_libraries(cryptoauth_test pthread) ++endif() ++ ++set(DEFAULT_BIN_PATH "${CMAKE_INSTALL_FULL_BINDIR}" CACHE ++ STRING "The default absolute test app path") ++ ++install(DIRECTORY DESTINATION ${DEFAULT_BIN_PATH}) ++install(CODE " ++ if(NOT EXISTS ${DEFAULT_BIN_PATH}/cryptoauth_test) ++ file(INSTALL ${PROJECT_BINARY_DIR}/cryptoauth_test ++ DESTINATION ${DEFAULT_BIN_PATH}) ++ endif() ++ ") diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0006-Remove-unnecessary-code-from-cryptoauth_test.patch b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0006-Remove-unnecessary-code-from-cryptoauth_test.patch new file mode 100644 index 000000000..b30dc4204 --- /dev/null +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib/0006-Remove-unnecessary-code-from-cryptoauth_test.patch @@ -0,0 +1,470 @@ +From: Gabriel Valcazar +Date: Thu, 31 Oct 2019 16:15:30 +0100 +Subject: [PATCH 6/6] Remove unnecessary code from cryptoauth_test + +Some test commands apply to chips other than the ATECC508A, and can cause +errors when used incorrectly. Remove all code that doesn't apply to our +platforms. + +https://jira.digi.com/browse/DEL-6826 + +Signed-off-by: Gabriel Valcazar +--- + test/cmd-processor.c | 360 ++------------------------------------------------- + 1 file changed, 12 insertions(+), 348 deletions(-) + +diff --git a/test/cmd-processor.c b/test/cmd-processor.c +index c0f819f..07ecf2a 100644 +--- a/test/cmd-processor.c ++++ b/test/cmd-processor.c +@@ -61,13 +61,8 @@ static void lock_config(void); + static void lock_data(void); + static void info(void); + static void sernum(void); +-static void discover(void); + static void select_device(ATCADeviceType device_type); + static int run_test(void* fptest); +-static void select_204(void); +-static void select_108(void); +-static void select_508(void); +-static void select_608(void); + static void run_basic_tests(void); + static void run_unit_tests(void); + static void run_otpzero_tests(void); +@@ -75,10 +70,6 @@ static void run_helper_tests(void); + static void help(void); + static int parse_cmd(const char *command); + static void run_all_tests(void); +-static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider); +-static void set_clock_divider_m0(void); +-static void set_clock_divider_m1(void); +-static void set_clock_divider_m2(void); + static void tng22_tests(void); + static void tngtn_tests(void); + +@@ -87,11 +78,6 @@ static const char* argv[] = { "manual", "-v" }; + static t_menu_info mas_menu_info[] = + { + { "help", "Display Menu", help }, +- { "discover", "Discover Buses and Devices", discover }, +- { "204", "Set Target Device to ATSHA204A", select_204 }, +- { "108", "Set Target Device to ATECC108A", select_108 }, +- { "508", "Set Target Device to ATECC508A", select_508 }, +- { "608", "Set Target Device to ATECC608A", select_608 }, + { "info", "Get the Chip Revision", info }, + { "sernum", "Get the Chip Serial Number", sernum }, + { "rand", "Generate Some Random Numbers", (fp_menu_handler)do_randoms }, +@@ -107,9 +93,6 @@ static t_menu_info mas_menu_info[] = + { "unit", "Run Unit Test on Selected Device", run_unit_tests }, + { "otpzero", "Zero Out OTP Zone", run_otpzero_tests }, + { "util", "Run Helper Function Tests", run_helper_tests }, +- { "clkdivm0", "Set ATECC608A to ClockDivider M0(0x00)", set_clock_divider_m0 }, +- { "clkdivm1", "Set ATECC608A to ClockDivider M1(0x05)", set_clock_divider_m1 }, +- { "clkdivm2", "Set ATECC608A to ClockDivider M2(0x0D)", set_clock_divider_m2 }, + #endif + #ifndef DO_NOT_TEST_CERT + { "cd", "Run Unit Tests on Cert Data", (fp_menu_handler)certdata_unit_tests }, +@@ -130,6 +113,8 @@ int main(int argc, char* argv[]) + { + char buffer[1024]; + ++ select_device(ATECC508A); ++ + while (true) + { + printf("$ "); +@@ -202,101 +187,13 @@ static void help(void) + } + } + +-static void select_204(void) +-{ +- select_device(ATSHA204A); +-} +-static void select_108(void) +-{ +- select_device(ATECC108A); +-} +-static void select_508(void) +-{ +- select_device(ATECC508A); +-} +-static void select_608(void) +-{ +- select_device(ATECC608A); +-} +- +-static void update_chip_mode(uint8_t* chip_mode, uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) +-{ +- if (i2c_user_extra_add != 0xFF) +- { +- *chip_mode &= ~ATCA_CHIPMODE_I2C_ADDRESS_FLAG; +- *chip_mode |= i2c_user_extra_add & ATCA_CHIPMODE_I2C_ADDRESS_FLAG; +- } +- if (ttl_enable != 0xFF) +- { +- *chip_mode &= ~ATCA_CHIPMODE_TTL_ENABLE_FLAG; +- *chip_mode |= ttl_enable & ATCA_CHIPMODE_TTL_ENABLE_FLAG; +- } +- if (watchdog != 0xFF) +- { +- *chip_mode &= ~ATCA_CHIPMODE_WATCHDOG_MASK; +- *chip_mode |= watchdog & ATCA_CHIPMODE_WATCHDOG_MASK; +- } +- if (clock_divider != 0xFF) +- { +- *chip_mode &= ~ATCA_CHIPMODE_CLOCK_DIV_MASK; +- *chip_mode |= clock_divider & ATCA_CHIPMODE_CLOCK_DIV_MASK; +- } +-} +- +-static ATCA_STATUS check_clock_divider(void) +-{ +- ATCA_STATUS status; +- uint8_t chip_mode = 0; +- +- if (gCfg->devtype != ATECC608A) +- { +- printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); +- return ATCA_GEN_FAIL; +- } +- +- // Update the actual ATECC608A chip mode so it takes effect immediately +- status = atcab_init(gCfg); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_init() failed with ret=0x%08X\r\n", status); +- return status; +- } +- +- do +- { +- // Read current config values +- status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, ATCA_CHIPMODE_OFFSET, &chip_mode, 1); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); +- break; +- } +- +- // Update the ATECC608A test config data so all the unit tests will run with the new chip mode +- update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], 0xFF, 0xFF, chip_mode & ATCA_CHIPMODE_WATCHDOG_MASK, chip_mode & ATCA_CHIPMODE_CLOCK_DIV_MASK); +- +- } +- while (0); +- +- atcab_release(); +- return status; +-} +- + static void run_basic_tests(void) + { +- if (gCfg->devtype == ATECC608A) +- { +- check_clock_divider(); +- } + run_test(RunAllBasicTests); + } + + static void run_unit_tests(void) + { +- if (gCfg->devtype == ATECC608A) +- { +- check_clock_divider(); +- } + run_test(RunAllFeatureTests); + } + static void run_otpzero_tests(void) +@@ -431,38 +328,6 @@ static ATCA_STATUS do_randoms(void) + + return status; + } +- +-static void discover(void) +-{ +- ATCAIfaceCfg ifaceCfgs[10]; +- int i; +- const char *devname[] = { "ATSHA204A", "ATECC108A", "ATECC508A", "ATECC608A" }; // indexed by ATCADeviceType +- +- for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) +- { +- ifaceCfgs[i].devtype = ATCA_DEV_UNKNOWN; +- ifaceCfgs[i].iface_type = ATCA_UNKNOWN_IFACE; +- } +- +- printf("Searching...\r\n"); +- atcab_cfg_discover(ifaceCfgs, sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); +- for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) +- { +- if (ifaceCfgs[i].devtype != ATCA_DEV_UNKNOWN) +- { +- printf("Found %s ", devname[ifaceCfgs[i].devtype]); +- if (ifaceCfgs[i].iface_type == ATCA_I2C_IFACE) +- { +- printf("@ bus %d addr %02x", ifaceCfgs[i].atcai2c.bus, ifaceCfgs[i].atcai2c.slave_address); +- } +- if (ifaceCfgs[i].iface_type == ATCA_SWI_IFACE) +- { +- printf("@ bus %d", ifaceCfgs[i].atcaswi.bus); +- } +- printf("\r\n"); +- } +- } +-} + static void info(void) + { + ATCA_STATUS status; +@@ -640,18 +505,7 @@ static ATCA_STATUS get_serial_no(uint8_t *sernum) + + static void select_device(ATCADeviceType device_type) + { +- ATCA_STATUS status; +- +- status = set_test_config(device_type); +- +- if (status == ATCA_SUCCESS) +- { +- printf("Device Selected.\r\n"); +- } +- else +- { +- printf("IFace Cfg are NOT available\r\n"); +- } ++ set_test_config(device_type); + } + + static int run_test(void* fptest) +@@ -674,11 +528,6 @@ static void run_all_tests(void) + bool is_data_locked = false; + int fails = 0; + +- if (gCfg->devtype == ATECC608A) +- { +- check_clock_divider(); +- } +- + info(); + sernum(); + do_randoms(); +@@ -826,212 +675,27 @@ static ATCA_STATUS set_test_config(ATCADeviceType deviceType) + gCfg->devtype = ATCA_DEV_UNKNOWN; + gCfg->iface_type = ATCA_UNKNOWN_IFACE; + +- switch (deviceType) +- { +- case ATSHA204A: +-#if defined(ATCA_HAL_I2C) +- *gCfg = cfg_atsha204a_i2c_default; +-#elif defined(ATCA_HAL_SWI) +- *gCfg = cfg_atsha204a_swi_default; +-#elif defined(ATCA_HAL_KIT_HID) +- *gCfg = cfg_atsha204a_kithid_default; +-#elif defined(ATCA_HAL_KIT_CDC) +- *gCfg = cfg_atsha204a_kitcdc_default; +-#elif defined(ATCA_HAL_CUSTOM) +- *gCfg = g_cfg_atsha204a_custom; +-#else +-#error "HAL interface is not selected"; +-#endif +- break; +- +- case ATECC108A: + #if defined(ATCA_HAL_I2C) +- *gCfg = cfg_ateccx08a_i2c_default; +- gCfg->devtype = deviceType; ++ *gCfg = cfg_ateccx08a_i2c_default; ++ gCfg->devtype = deviceType; + #elif defined(ATCA_HAL_SWI) +- *gCfg = cfg_ateccx08a_swi_default; +- gCfg->devtype = deviceType; ++ *gCfg = cfg_ateccx08a_swi_default; ++ gCfg->devtype = deviceType; + #elif defined(ATCA_HAL_KIT_HID) +- *gCfg = cfg_ateccx08a_kithid_default; +- gCfg->devtype = deviceType; ++ *gCfg = cfg_ateccx08a_kithid_default; ++ gCfg->devtype = deviceType; + #elif defined(ATCA_HAL_KIT_CDC) +- *gCfg = cfg_ateccx08a_kitcdc_default; +- gCfg->devtype = deviceType; ++ *gCfg = cfg_ateccx08a_kitcdc_default; ++ gCfg->devtype = deviceType; + #elif defined(ATCA_HAL_CUSTOM) +- *gCfg = g_cfg_atecc108a_custom; ++ *gCfg = g_cfg_atecc508a_custom; + #else + #error "HAL interface is not selected"; + #endif +- break; +- +- case ATECC508A: +-#if defined(ATCA_HAL_I2C) +- *gCfg = cfg_ateccx08a_i2c_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_SWI) +- *gCfg = cfg_ateccx08a_swi_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_KIT_HID) +- *gCfg = cfg_ateccx08a_kithid_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_KIT_CDC) +- *gCfg = cfg_ateccx08a_kitcdc_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_CUSTOM) +- *gCfg = g_cfg_atecc508a_custom; +-#else +-#error "HAL interface is not selected"; +-#endif +- break; +- +- case ATECC608A: +-#if defined(ATCA_HAL_I2C) +- *gCfg = cfg_ateccx08a_i2c_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_SWI) +- *gCfg = cfg_ateccx08a_swi_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_KIT_HID) +- *gCfg = cfg_ateccx08a_kithid_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_KIT_CDC) +- *gCfg = cfg_ateccx08a_kitcdc_default; +- gCfg->devtype = deviceType; +-#elif defined(ATCA_HAL_CUSTOM) +- *gCfg = g_cfg_atecc608a_custom; +-#else +-#error "HAL interface is not selected"; +-#endif +- break; +- +- default: +- //device type wasn't found, return with error +- return ATCA_GEN_FAIL; +- } +- +- #ifdef ATCA_RASPBERRY_PI_3 +- gCfg->atcai2c.bus = 1; +- #endif + + return ATCA_SUCCESS; + } + +-static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) +-{ +- ATCA_STATUS status; +- uint8_t config_word[ATCA_WORD_SIZE]; +- bool is_config_locked = false; +- +- if (gCfg->devtype != ATECC608A) +- { +- printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); +- return ATCA_GEN_FAIL; +- } +- +- status = is_device_locked(LOCK_ZONE_CONFIG, &is_config_locked); +- if (status != ATCA_SUCCESS) +- { +- printf("is_device_locked() failed with ret=0x%08X\r\n", status); +- return status; +- } +- +- if (is_config_locked) +- { +- printf("Current device is config locked. Can't change clock divider. "); +- } +- +- // Update the actual ATECC608A chip mode so it takes effect immediately +- status = atcab_init(gCfg); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_init() failed with ret=0x%08X\r\n", status); +- return status; +- } +- +- do +- { +- // Read current config values +- status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); +- break; +- } +- +- if (is_config_locked) +- { +- printf("Currently set to 0x%02X.\r\n", (int)(config_word[3] >> 3)); +- status = ATCA_GEN_FAIL; +- break; +- } +- +- // Update ChipMode +- update_chip_mode(&config_word[3], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); +- +- // Write config values back to chip +- status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_write_bytes_zone() failed with ret=0x%08X\r\n", status); +- break; +- } +- +- // Put to sleep so new values take effect +- status = atcab_wakeup(); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_wakeup() failed with ret=0x%08X\r\n", status); +- break; +- } +- status = atcab_sleep(); +- if (status != ATCA_SUCCESS) +- { +- printf("atcab_sleep() failed with ret=0x%08X\r\n", status); +- break; +- } +- +- // Update the ATECC608A test config data so all the unit tests will run with the new chip mode +- update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); +- +- } +- while (0); +- +- atcab_release(); +- return status; +-} +- +-static void set_clock_divider_m0(void) +-{ +- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M0); +- +- if (status == ATCA_SUCCESS) +- { +- printf("Set device to clock divider M0 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M0 >> 3); +- } +-} +- +-static void set_clock_divider_m1(void) +-{ +- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M1); +- +- if (status == ATCA_SUCCESS) +- { +- printf("Set device to clock divider M1 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M1 >> 3); +- } +-} +- +-static void set_clock_divider_m2(void) +-{ +- // Additionally set watchdog to long settings (~13s) as some commands +- // can't complete in time on the faster watchdog setting. +- ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_LONG, ATCA_CHIPMODE_CLOCK_DIV_M2); +- +- if (status == ATCA_SUCCESS) +- { +- printf("Set device to clock divider M2 (0x%02X) and watchdog to 13s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M2 >> 3); +- } +-} +- + static void tng22_tests(void) + { + ATCA_STATUS status; diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb index d1b361806..846c8f15c 100644 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb @@ -15,6 +15,8 @@ SRC_URI = " \ file://0002-lib-apply-library-version-number-to-CMake-VERSION-pr.patch \ file://0003-pkcs11-rename-template-configuration-file-to-its-int.patch \ file://0004-lib-install-pkg-config-file-and-header-files.patch \ + file://0005-test-add-CMakeLists.txt.patch \ + file://0006-Remove-unnecessary-code-from-cryptoauth_test.patch \ " S = "${WORKDIR}/git" @@ -26,16 +28,26 @@ I2C_BUS_ccimx8x = "0" I2C_SPEED ?= "100000" -EXTRA_OECMAKE += "-DATCA_HAL_I2C_BUS=${I2C_BUS} -DATCA_HAL_I2C_SPEED=${I2C_SPEED}" +EXTRA_OECMAKE += "-DATCA_HAL_I2C_BUS=${I2C_BUS} -DATCA_HAL_I2C_SPEED=${I2C_SPEED} -DBUILD_TESTS=on" inherit cmake do_install_append() { # Rename the folder containing the header files to be more package-specific mv ${D}${includedir}/lib ${D}${includedir}/cryptoauthlib + + # Remove RPATH from the executable + chrpath -d ${D}${bindir}/cryptoauth_test + chmod +x ${D}${bindir}/cryptoauth_test } +PACKAGES =+ "${PN}-test" + +FILES_${PN}-test = "${bindir}/cryptoauth_test" + RDEPENDS_${PN} = "libp11" +RDEPENDS_${PN}-test = "${PN}" +RRECOMMENDS_${PN} = "${PN}-test" PACKAGE_ARCH = "${MACHINE_ARCH}" COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" From f6697af5d1d9ae68964ab2daaf8c4cfe2a8894f8 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 12 Nov 2019 12:01:23 +0100 Subject: [PATCH 018/120] openssl: modify patch to load pkcs11 engine instead of cryptochip engine The previous patch was outdated, but now that we have a working PKCS11 engine and the cryptochip supports it, update the patch with the new engine info. https://jira.digi.com/browse/DEL-6835 Signed-off-by: Gabriel Valcazar --- ...nf-to-automatically-load-the-cryptoc.patch | 41 ------------------- ...nf-to-automatically-load-the-pkcs11-.patch | 40 ++++++++++++++++++ .../openssl/openssl_%.bbappend | 2 +- 3 files changed, 41 insertions(+), 42 deletions(-) delete mode 100644 meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-cryptoc.patch create mode 100644 meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-pkcs11-.patch diff --git a/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-cryptoc.patch b/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-cryptoc.patch deleted file mode 100644 index bf843d0d6..000000000 --- a/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-cryptoc.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Arturo Buzarra -Date: Thu, 31 Jan 2019 18:01:02 +0100 -Subject: [PATCH] Modify openssl.cnf to automatically load the cryptochip - engine - -https://jira.digi.com/browse/DEL-5592 - -Signed-off-by: Gabriel Valcazar -Signed-off-by: Arturo Buzarra ---- - apps/openssl.cnf | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/apps/openssl.cnf b/apps/openssl.cnf -index 6df2878d50..762582f4d0 100644 ---- a/apps/openssl.cnf -+++ b/apps/openssl.cnf -@@ -3,6 +3,8 @@ - # This is mostly being used for generation of certificate requests. - # - -+openssl_conf = openssl_init -+ - # Note that you can include other files from the main configuration - # file using the .include directive. - #.include filename -@@ -348,3 +350,14 @@ ess_cert_id_chain = no # Must the ESS cert id chain be included? - # (optional, default: no) - ess_cert_id_alg = sha1 # algorithm to compute certificate - # identifier (optional, default: sha1) -+ -+[ openssl_init ] -+engines = engine_section -+ -+[ engine_section ] -+ateccx08 = ateccx08_config -+ -+[ ateccx08_config ] -+engine_id = ateccx08 -+dynamic_path = /usr/lib/ssl/engines/libateccssl.so -+init = 0 diff --git a/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-pkcs11-.patch b/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-pkcs11-.patch new file mode 100644 index 000000000..51b599551 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/openssl/openssl/0001-Modify-openssl.cnf-to-automatically-load-the-pkcs11-.patch @@ -0,0 +1,40 @@ +From: Gabriel Valcazar +Date: Tue, 12 Nov 2019 12:00:07 +0100 +Subject: [PATCH] Modify openssl.cnf to automatically load the pkcs11 engine + +https://jira.digi.com/browse/DEL-6835 + +Signed-off-by: Gabriel Valcazar +--- + apps/openssl.cnf | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/apps/openssl.cnf b/apps/openssl.cnf +index 4acca4b..2261048 100644 +--- a/apps/openssl.cnf ++++ b/apps/openssl.cnf +@@ -7,6 +7,8 @@ + # file using the .include directive. + #.include filename + ++openssl_conf = openssl_init ++ + # This definition stops the following lines choking if HOME isn't + # defined. + HOME = . +@@ -348,3 +350,15 @@ ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) + ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) ++ ++[ openssl_init ] ++engines = engine_section ++ ++[ engine_section ] ++pkcs11 = pkcs11_config ++ ++[ pkcs11_config ] ++engine_id = pkcs11 ++dynamic_path = /usr/lib/engines-1.1/pkcs11.so ++MODULE_PATH = /usr/lib/libcryptoauth.so.2018.10.26 ++init = 0 diff --git a/meta-digi-dey/recipes-connectivity/openssl/openssl_%.bbappend b/meta-digi-dey/recipes-connectivity/openssl/openssl_%.bbappend index f8db537bf..e87c828c6 100644 --- a/meta-digi-dey/recipes-connectivity/openssl/openssl_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/openssl/openssl_%.bbappend @@ -3,7 +3,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" CRYPTOCHIP_COMMON_PATCHES = " \ - file://0001-Modify-openssl.cnf-to-automatically-load-the-cryptoc.patch \ + file://0001-Modify-openssl.cnf-to-automatically-load-the-pkcs11-.patch \ " SRC_URI_remove = " \ From d2e6b5c1b7d2b2939eb6cd65613f805d49847c60 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Fri, 15 Nov 2019 09:32:41 +0100 Subject: [PATCH 019/120] firmware_qualcomm: update US Board Data File Update file: - fakeboar_US.bin (f74a835871d9c12f116312ff54927b39) This file was generated by calibrating 10 CC8X SOMs (version 0x4) and merging their resulting BDF files into a Golden file. Target powers table is also updated to improve performance on 2.4GHz band. Reference calibration file is: - bdwlan30.bin (8a558fa38dacee7038f04c1b10ec69a5) located at 'cnss_proc/wlan/fw/target/pcie_dst/qc6174/' from tag r10007.1 on qca6574au-le-2-2-1_qca_oem repo. https://jira.digi.com/browse/DEL-6852 Signed-off-by: Gonzalo Ruiz (cherry picked from commit a332ff445f46cf116e330cb1e059d9e59c2fca42) --- .../qca6574_proprietary/fakeboar_US.bin | Bin 8124 -> 8124 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin index d51ffbe4422066839f62fa7adc6e96d3a26d831d..8d48bbef5abdcb1042fee4503f31bbb1e5fc8c08 100644 GIT binary patch literal 8124 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 O`8KT!D%fug=zjq&a|nk3 From 8210d73d3467015277f1026b474bcc0fec2b7a96 Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Mon, 25 Nov 2019 12:57:09 +0100 Subject: [PATCH 020/120] digi-sc-firmware: update to v1.2.5.1 This adds power management optimizations for the SCU Signed-off-by: Francisco Gil --- ...{digi-sc-firmware_1.2.5.bb => digi-sc-firmware_1.2.5.1.bb} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename meta-digi-arm/recipes-bsp/digi-sc-firmware/{digi-sc-firmware_1.2.5.bb => digi-sc-firmware_1.2.5.1.bb} (89%) diff --git a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.bb b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb similarity index 89% rename from meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.bb rename to meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb index e496ee6d0..26aefaa7c 100644 --- a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.bb +++ b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb @@ -11,8 +11,8 @@ inherit pkgconfig deploy SRC_URI = "${DIGI_PKG_SRC}/${PN}-${PV}.tar.gz" -SRC_URI[md5sum] = "4a1a7a99cda9e55388d1c491011853c6" -SRC_URI[sha256sum] = "852cdd37d37905b08cfdc4b753ce33b7364749065bac91d78cc2292481e6d6a7" +SRC_URI[md5sum] = "6b6ee8074b7145a2f0c1fae74f4a7941" +SRC_URI[sha256sum] = "e6b9ef3e6db879d55072c177685ef24cbb9075c78f3537d8bcdbdede1ad8cc51" S = "${WORKDIR}/${PN}-${PV}" From be0fe088e39a97c7dbbba62851555b17d970df79 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 28 Nov 2019 13:54:42 +0100 Subject: [PATCH 021/120] sdk: add platform and image names to the default SDK installation path Since the final image name is not available in a global scope, append it to the default installation path in the SDK extraction script once it has been packaged. The new default installation path format is: /opt/dey/// https://jira.digi.com/browse/DEL-5264 Signed-off-by: Gabriel Valcazar --- meta-digi-dey/classes/dey-image.bbclass | 17 +++++++++++++---- meta-digi-dey/conf/distro/dey.conf | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/meta-digi-dey/classes/dey-image.bbclass b/meta-digi-dey/classes/dey-image.bbclass index a7679ca67..04690e451 100644 --- a/meta-digi-dey/classes/dey-image.bbclass +++ b/meta-digi-dey/classes/dey-image.bbclass @@ -34,15 +34,18 @@ DEY_IMAGE_INSTALLER ?= "0" inherit ${@oe.utils.conditional("DEY_IMAGE_INSTALLER", "1", "dey-image-installer", "", d)} # -# Create a dey-version file when populating the toolchain/SDK +# Create a dey-version file when populating the toolchain/SDK and modify the +# default SDK installation path so it includes the proper 'IMAGE_BASENAME' +# value. # # 'SDK_POSTPROCESS_COMMAND' variable is originally defined in populate_sdk_base # class: poky/meta/classes/populate_sdk_base.bbclass -# It is redefined here to be able to tweak the resulting SDK before packaging, -# using the proper 'IMAGE_BASENAME' value. +# It is redefined here to be able to tweak the resulting SDK before and after +# packaging, using the proper 'IMAGE_BASENAME' value. # SDK_PREPACKAGING_COMMAND ?= "toolchain_create_sdk_dey_version" -SDK_POSTPROCESS_COMMAND = " create_sdk_files; check_sdk_sysroots; ${SDK_PREPACKAGING_COMMAND}; tar_sdk; ${SDK_PACKAGING_COMMAND} " +SDK_POSTPACKAGING_COMMAND ?= "toolchain_modify_default_path" +SDK_POSTPROCESS_COMMAND = " create_sdk_files; check_sdk_sysroots; ${SDK_PREPACKAGING_COMMAND}; tar_sdk; ${SDK_PACKAGING_COMMAND} ${SDK_POSTPACKAGING_COMMAND}; " # This function creates a DEY version information file fakeroot toolchain_create_sdk_dey_version() { @@ -56,3 +59,9 @@ fakeroot toolchain_create_sdk_dey_version() { } toolchain_create_sdk_dey_version[vardepsexclude] = "DATETIME" +# This function appends IMAGE_BASENAME to the default installation path +fakeroot toolchain_modify_default_path() { + sed -i -e 's#^DEFAULT_INSTALL_DIR="${SDKPATH}"#DEFAULT_INSTALL_DIR="${SDKPATH}/${IMAGE_BASENAME}"#g' \ + ${SDKDEPLOYDIR}/${TOOLCHAIN_OUTPUTNAME}.sh +} + diff --git a/meta-digi-dey/conf/distro/dey.conf b/meta-digi-dey/conf/distro/dey.conf index bd700e6d7..b8bff7a3b 100644 --- a/meta-digi-dey/conf/distro/dey.conf +++ b/meta-digi-dey/conf/distro/dey.conf @@ -70,7 +70,7 @@ PREFERRED_VERSION_libsoc = "git" PREFERRED_PROVIDER_opencl-headers ?= "imx-gpu-viv" SDK_NAME = "${DISTRO}-${TCLIBC}-${SDK_ARCH}-${IMAGE_BASENAME}-${TUNE_PKGARCH}" -SDKPATH = "/opt/${DISTRO}/${SDK_VERSION}" +SDKPATH = "/opt/${DISTRO}/${SDK_VERSION}/${MACHINE}" DISTRO_EXTRA_RDEPENDS += " ${POKY_DEFAULT_EXTRA_RDEPENDS}" DISTRO_EXTRA_RRECOMMENDS += " ${POKY_DEFAULT_EXTRA_RRECOMMENDS}" From 2db75582360d9de1b5e5348b6ba0cd844e6a8dbe Mon Sep 17 00:00:00 2001 From: Jose Diaz de Grenu Date: Mon, 2 Dec 2019 15:23:28 +0100 Subject: [PATCH 022/120] sysinfo: add OTP values The values of the OTP can be relevant for some issues. Signed-off-by: Jose Diaz de Grenu --- .../recipes-digi/sysinfo/sysinfo/sysinfo | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo index 1f85877fb..02bc7c06b 100755 --- a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo +++ b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo @@ -229,6 +229,25 @@ make_report(){ fi printf "\n\n" + echo "--------------------------------------" + echo "- -" + echo "- OTP values -" + echo "- -" + echo "--------------------------------------" + echo "" + if [ -d /sys/fsl_otp ]; then + for f in /sys/fsl_otp/*; do + echo -e "$f:\t$(cat $f)" + done + echo "" + fi + for d in /sys/bus/nvmem/devices/*; do + [ -e $d ] || continue + echo "$d:" + hexdump -C $d/nvmem + echo "" + done + echo "--------------------------------------" echo "- -" echo "- TrustFence -" From b242ee1a9341dcb2cb1438b19f7f1cc74947961d Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 3 Dec 2019 15:42:23 +0100 Subject: [PATCH 023/120] qualcomm.sh: get mount point to remount from /proc/mounts Obtain the mount point of the filesystem to remount as 'read-write' from /proc/mounts to avoid issues related to df output wrapping on a second line when the device filesystem name is too long. When the script finishes, remount the filesystem as 'read-only' if that was the original access permission. https://jira.digi.com/browse/DEL-6760 https://jira.digi.com/browse/DEL-5854 Signed-off-by: Gonzalo Ruiz --- .../kernel-module-qualcomm/qualcomm.sh | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh index 2a8980b9a..bd3eae9b5 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh @@ -21,6 +21,34 @@ log() { printf "<$1>qca65x4: $2\n" >/dev/kmsg } +# Get the permissions of the filesystem containing the given path +get_filesystem_access() { + [ -z "${1}" ] && return + + fs_device="$(df ${1} | awk 'NR==2 { print $1 }')" + fs_access="$(awk -v dev="${fs_device}" '$0 ~ dev { print substr($4,1,2) }' < /proc/mounts)" + echo ${fs_access} +} + +# Get the mount point of the filesystem containing the given path +get_filesystem_mount_point() { + [ -z "${1}" ] && return + + fs_device="$(df ${1} | awk 'NR==2 { print $1 }')" + fs_mount_point="$(awk -v dev="${fs_device}" '$0 ~ dev { print $2 }' < /proc/mounts)" + echo ${fs_mount_point} +} + +# Remount the filesystem containing the given path as 'read-write' if it was +# mounted as 'read-only'. +set_filesystem_rw_access() { + [ -z "${1}" ] && return + + if [ "$(get_filesystem_access ${1})" = "ro" ]; then + mount -o remount,rw $(get_filesystem_mount_point ${1}) + fi +} + # Do nothing if the wireless node does not exist on the device tree [ -d "/proc/device-tree/wireless" ] || exit 0 @@ -30,6 +58,7 @@ grep -qws 'wlan' /proc/modules && exit 0 FIRMWARE_DIR="/lib/firmware" MACFILE="${FIRMWARE_DIR}/wlan/wlan_mac.bin" TMP_MACFILE="$(mktemp -t wlan_mac.XXXXXX)" +FS_ORIGINAL_ACCESS="$(get_filesystem_access ${FIRMWARE_DIR})" # Read the MACs from DeviceTree. We can have up to four wireless interfaces # The only required one is wlan0 that is mapped with device tree mac address @@ -47,12 +76,7 @@ done # Override the MAC firmware file only if the MAC file has changed. if ! cmp -s ${TMP_MACFILE} ${MACFILE}; then - if [ ! -w ${MACFILE} ]; then - mount_point="$(df $(dirname "${MACFILE}") | awk '!/^Filesystem/{ print $6 }')" - log "6" "[INFO] ${MACFILE} is not writable, remounting '${mount_point}' as rw" - mount -o remount,rw ${mount_point} - fi - + set_filesystem_rw_access ${FIRMWARE_DIR} cp ${TMP_MACFILE} ${MACFILE} || log "3" "[ERROR] Could not create ${MACFILE}" fi rm -f "${TMP_MACFILE}" @@ -139,3 +163,9 @@ modprobe wlan # Verify the interface is present [ -d "/sys/class/net/wlan0" ] || log "3" "[ERROR] Loading wlan module" + +# Restore the filesystem with the original access permissions if it has been +# changed inside the script. +if [ "$(get_filesystem_access ${FIRMWARE_DIR})" != "${FS_ORIGINAL_ACCESS}" ]; then + mount -o remount,${FS_ORIGINAL_ACCESS} $(get_filesystem_mount_point ${FIRMWARE_DIR}) +fi From 0692252b880d99ef95857e757c3a23b4d4a1d5c4 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 3 Dec 2019 15:48:24 +0100 Subject: [PATCH 024/120] qualcomm.sh: remount filesystem as 'rw' to create symlinks Also remount the root filesystem as 'rw' when the symlinks need to be updated. https://jira.digi.com/browse/DEL-6760 Signed-off-by: Gonzalo Ruiz --- .../kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh index bd3eae9b5..1e3b9ced5 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh @@ -146,11 +146,13 @@ esac if [ -n "${BDATA_LINK}" ] && ([ ! -f "${BDATA_LINK}" ] || ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"); then + set_filesystem_rw_access ${FIRMWARE_DIR} ln -sf "${BDATA_SOURCE}" "${BDATA_LINK}" fi if [ -n "${UTFBDATA_LINK}" ] && ([ ! -f "${UTFBDATA_LINK}" ] || ! cmp -s "${UTFBDATA_LINK}" "${BDATA_SOURCE}"); then + set_filesystem_rw_access ${FIRMWARE_DIR} ln -sf "${BDATA_SOURCE}" "${UTFBDATA_LINK}" fi ) From a114391ae9653f7640f04e2b601a91075678584e Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 12 Dec 2019 12:02:16 +0100 Subject: [PATCH 025/120] Use https instead of ftp when accessing the Digi support folders Update the README as well to reflect this change, since the ftp protocol might be blocked in some corporate networks. https://jira.digi.com/browse/DEL-6880 Signed-off-by: Gabriel Valcazar --- README.md | 4 ++-- meta-digi-arm/conf/layer.conf | 2 +- meta-digi-dey/conf/layer.conf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fc9a0a04f..afa831b3a 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ Documentation is available online at https://www.digi.com/resources/documentatio # Downloads -* Demo images: ftp://ftp1.digi.com/support/digiembeddedyocto/2.6/r2/images/ -* Software Development Kit (SDK): ftp://ftp1.digi.com/support/digiembeddedyocto/2.6/r2/sdk/ +* Demo images: https://ftp1.digi.com/support/digiembeddedyocto/2.6/r2/images/ +* Software Development Kit (SDK): https://ftp1.digi.com/support/digiembeddedyocto/2.6/r2/sdk/ # Release Changelog diff --git a/meta-digi-arm/conf/layer.conf b/meta-digi-arm/conf/layer.conf index d400f808d..332cd6334 100644 --- a/meta-digi-arm/conf/layer.conf +++ b/meta-digi-arm/conf/layer.conf @@ -23,6 +23,6 @@ LICENSE_PATH += "${LAYERDIR}/custom-licenses" DIGI_LOG_GIT ?= "git://log-sln-git.digi.com/" DIGI_MTK_GIT ?= "git://stash.digi.com/" DIGI_GIT ?= "${DIGI_LOG_GIT}" -DIGI_PKG_SRC ?= "ftp://ftp1.digi.com/support/digiembeddedyocto/source" +DIGI_PKG_SRC ?= "https://ftp1.digi.com/support/digiembeddedyocto/source" DIGI_GITHUB_GIT ?= "git://github.com/digi-embedded" diff --git a/meta-digi-dey/conf/layer.conf b/meta-digi-dey/conf/layer.conf index 3cb92d433..3fd8b6d7a 100644 --- a/meta-digi-dey/conf/layer.conf +++ b/meta-digi-dey/conf/layer.conf @@ -26,7 +26,7 @@ DIGI_EULA_FILE = "${LAYERDIR}/DIGI_EULA" DIGI_OPEN_EULA_FILE = "${LAYERDIR}/DIGI_OPEN_EULA" # Digi mirror for packages vanished upstream -DIGI_MIRROR ?= "ftp://ftp1.digi.com/support/digiembeddedyocto/mirror/" +DIGI_MIRROR ?= "https://ftp1.digi.com/support/digiembeddedyocto/mirror/" MIRRORS += "\ ftp://.*/.* ${DIGI_MIRROR} \n \ http://.*/.* ${DIGI_MIRROR} \n \ From a5d6f02ea0b3e72dda6999fa14c5120fd151ec7f Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Thu, 2 Jan 2020 12:25:43 +0100 Subject: [PATCH 026/120] python-xbee: fix mispelled license name Clean up this warning on build: python3-xbee: No generic license file exists for: MPL2.0 in any provider Signed-off-by: Javier Viguera --- meta-digi-dey/recipes-devtools/python3-xbee/python3-xbee.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-devtools/python3-xbee/python3-xbee.inc b/meta-digi-dey/recipes-devtools/python3-xbee/python3-xbee.inc index 48022327f..9ab2020b6 100644 --- a/meta-digi-dey/recipes-devtools/python3-xbee/python3-xbee.inc +++ b/meta-digi-dey/recipes-devtools/python3-xbee/python3-xbee.inc @@ -3,7 +3,7 @@ SUMMARY = "Python library to interact with Digi International's XBee radio frequency modules." HOMEPAGE = "https://github.com/digidotcom/python-xbee" -LICENSE = "MPL2.0" +LICENSE = "MPL-2.0" PYPI_PACKAGE = "digi-xbee" From da46ed4a07d22741f2b0151227de805c7211dd06 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Thu, 2 Jan 2020 17:03:40 +0100 Subject: [PATCH 027/120] imx-gst1.0-plugin: fix build using MUSL C library Signed-off-by: Javier Viguera --- ...lugin-fix-build-using-MUSL-C-library.patch | 36 +++++++++++++++++++ .../gstreamer/imx-gst1.0-plugin_%.bbappend | 7 ++-- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin/0002-imx-gst1.0-plugin-fix-build-using-MUSL-C-library.patch diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin/0002-imx-gst1.0-plugin-fix-build-using-MUSL-C-library.patch b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin/0002-imx-gst1.0-plugin-fix-build-using-MUSL-C-library.patch new file mode 100644 index 000000000..e9f7dc60b --- /dev/null +++ b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin/0002-imx-gst1.0-plugin-fix-build-using-MUSL-C-library.patch @@ -0,0 +1,36 @@ +From: Javier Viguera +Date: Thu, 2 Jan 2020 16:49:51 +0100 +Subject: [PATCH] imx-gst1.0-plugin: fix build using MUSL C library + +Signed-off-by: Javier Viguera +--- + tools/gplay2/gplay2.c | 1 - + tools/grecorder/grecorder.c | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/gplay2/gplay2.c b/tools/gplay2/gplay2.c +index 3fa056a86307..a6e5db5535d2 100755 +--- a/tools/gplay2/gplay2.c ++++ b/tools/gplay2/gplay2.c +@@ -26,7 +26,6 @@ + */ + + +-#include + #include + #include + #include +diff --git a/tools/grecorder/grecorder.c b/tools/grecorder/grecorder.c +index 1fec19f900fe..dc912d36e056 100644 +--- a/tools/grecorder/grecorder.c ++++ b/tools/grecorder/grecorder.c +@@ -24,7 +24,9 @@ + #include + #include + #include ++#include + #define __USE_LARGEFILE64 ++#define _GNU_SOURCE # For MUSL statvfs64 + #include + + #include "recorder_engine.h" diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_%.bbappend b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_%.bbappend index 90696801e..1e1c8de7e 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_%.bbappend +++ b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_%.bbappend @@ -1,6 +1,9 @@ -# Copyright (C) 2016-2018 Digi International +# Copyright (C) 2016-2020 Digi International Inc. FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" -SRC_URI += "file://0001-gstimxv4l2-map-dev-video1-to-dev-fb0.patch" +SRC_URI += " \ + file://0001-gstimxv4l2-map-dev-video1-to-dev-fb0.patch \ + file://0002-imx-gst1.0-plugin-fix-build-using-MUSL-C-library.patch \ +" SRC_URI_append_ccimx6 = " file://0002-imx_2d_device_g2d-define-a-G2D_AMPHION_INTERLACED-ma.patch" From 0aa52b8a6e477dc3af2cc1dacf697ec996922428 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Thu, 2 Jan 2020 17:30:24 +0100 Subject: [PATCH 028/120] imx-codec: skip 'file-rdeps' QA check when building with MUSL Otherwise there are QA check failures: package imx-codec-test-bin requires librt.so.1, but no providers found in RDEPENDS_imx-codec-test-bin? [file-rdeps] package imx-codec-test-bin requires libc.so.6(GLIBC_2.4), but no providers found in RDEPENDS_imx-codec-test-bin? [file-rdeps] ... This is due to the 'imx-codec-test-bin' package containing NXP-provided pre-built binaries that are compiled with GLIBC. Signed-off-by: Javier Viguera --- meta-digi-dey/recipes-multimedia/imx-codec/imx-codec.inc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec.inc b/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec.inc index c14866db3..aed38adec 100644 --- a/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec.inc +++ b/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec.inc @@ -49,6 +49,11 @@ python __set_insane_skip() { if p == 'imx-codec-test-bin': # FIXME: includes the DUT .so files so we need to deploy those d.setVar("INSANE_SKIP_%s" % p, "ldflags textrel libdir") + + # Skip 'file-rdeps' for builds with MUSL C library + overrides = d.getVar("OVERRIDES").split(":") + if "libc-musl" in overrides: + d.appendVar("INSANE_SKIP_%s" % p, " file-rdeps") else: d.setVar("INSANE_SKIP_%s" % p, "ldflags textrel") } From 21945b1807b32a0108b4c3ea1ccae6ac54a5b191 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Fri, 3 Jan 2020 15:02:36 +0100 Subject: [PATCH 029/120] xbee: add missing inherits These classes needs to be inherited so the different init services (sysv, systemd) execute the script on boot. Signed-off-by: Javier Viguera --- meta-digi-dey/recipes-connectivity/xbee/xbee.bb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb index 8bf090b99..7f733be7e 100644 --- a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb +++ b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb @@ -12,6 +12,8 @@ SRC_URI = " \ " S = "${WORKDIR}" +inherit systemd update-rc.d + do_install() { install -d ${D}${sysconfdir}/init.d/ install -m 0755 ${WORKDIR}/xbee-init ${D}${sysconfdir}/ From 07f1fa88f24fb497326093be9d7485721217d74f Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 7 Jan 2020 13:48:59 +0100 Subject: [PATCH 030/120] vulkan-demos: add vulkan-validationlayers as a runtime dependency This package needs to be installed in the rootfs for the demos to work. Reported-by: Alfonso Martin Rey Signed-off-by: Gabriel Valcazar --- meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend | 3 +++ 1 file changed, 3 insertions(+) diff --git a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend index a11dfbd09..a86a22fef 100644 --- a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend +++ b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend @@ -1,3 +1,6 @@ DEPENDS_remove = "vulkan" DEPENDS_append = " vulkan-headers vulkan-loader" + +# The vulkan-validationlayers package is necessary for the demos to work +RDEPENDS_${PN} = "vulkan-validationlayers" From 38014d59dea316a8ea41202a9a526c4af760799c Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Wed, 8 Jan 2020 15:47:44 +0100 Subject: [PATCH 031/120] xbee-init: fix xbee systemd service not executed on boot The systemd class adds by default packages named ${PN} to the SYSTEMD_PACKAGES variable, but in our case the package name is '${PN}-init', so it needs to be added explicitly. Signed-off-by: Javier Viguera --- meta-digi-dey/recipes-connectivity/xbee/xbee.bb | 1 + 1 file changed, 1 insertion(+) diff --git a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb index 7f733be7e..2c463c543 100644 --- a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb +++ b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb @@ -36,6 +36,7 @@ INITSCRIPT_PACKAGES += "${PN}-init" INITSCRIPT_NAME_${PN}-init = "xbee-init" INITSCRIPT_PARAMS_${PN}-init = "start 19 2 3 4 5 . stop 21 0 1 6 ." +SYSTEMD_PACKAGES = "${PN}-init" SYSTEMD_SERVICE_${PN}-init = "xbee-init.service" PACKAGE_ARCH = "${MACHINE_ARCH}" From 580317486e418cc09a0c84e479c8607b14a57a8e Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:08:03 +0200 Subject: [PATCH 032/120] meta-digi-arm: add support for ConnectCore 8M Nano DVK platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 45 +++ .../conf/machine/include/ccimx8mn.inc | 58 ++++ .../conf/machine/include/digi-defaults.inc | 1 + .../conf/machine/include/imx-digi-base.inc | 2 + sdk/build-github.sh | 5 +- sdk/build.sh | 3 +- sdk/config/ccimx8mn-dvk/bblayers.conf.sample | 22 ++ sdk/config/ccimx8mn-dvk/conf-notes.txt | 18 ++ sdk/config/ccimx8mn-dvk/local.conf.sample | 266 ++++++++++++++++++ 9 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 meta-digi-arm/conf/machine/ccimx8mn-dvk.conf create mode 100644 meta-digi-arm/conf/machine/include/ccimx8mn.inc create mode 100644 sdk/config/ccimx8mn-dvk/bblayers.conf.sample create mode 100644 sdk/config/ccimx8mn-dvk/conf-notes.txt create mode 100644 sdk/config/ccimx8mn-dvk/local.conf.sample diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf new file mode 100644 index 000000000..b76dd0eb6 --- /dev/null +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -0,0 +1,45 @@ +#@TYPE: Machine +#@NAME: ConnectCore 8M Nano Development Kit. +#@DESCRIPTION: Machine configuration for Digi's ConnectCore 8M Nano DVK. + +# Include the machine configuration for Digi's ConnectCore 8M Nano module. +include conf/machine/include/ccimx8mn.inc + +# Wireless external module +WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" + +# Wireless p2p interface +WLAN_P2P_INTERFACE ?= "p2p0" + +# Firmware +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6564-bt', '', d)}" +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6564-wifi', '', d)}" + +# U-Boot configurations +# Last one is the default (the one the symlinks point at) +UBOOT_CONFIG ??= "ccimx8mn_dvk" +UBOOT_CONFIG[ccimx8mn_dvk] = "ccimx8mn_dvk_defconfig,,u-boot-dtb.${UBOOT_SUFFIX}" +SPL_BINARY = "spl/u-boot-spl.bin" + +# Set u-boot DTB +UBOOT_DTB_NAME = "ccimx8mn-dvk.dtb" + +KERNEL_DEVICETREE ?= " \ + digi/ccimx8mn-dvk-wb.dtb \ + digi/ccimx8mn-dvk.dtb \ +" + +SERIAL_CONSOLES ?= "115200;ttymxc2" + +# Bluetooth tty +BT_TTY ?= "ttymxc1" + +# XBee2 +XBEE_RESET_N_GPIO ?= "8" +XBEE_SLEEP_RQ_GPIO ?= "7" + +# U-Boot script to be copied to the boot image +BOOT_SCRIPTS = "boot.scr:boot.scr" + +# Flash image types +IMAGE_FSTYPES ?= "boot.vfat ext4 sdcard tar.bz2 recovery.vfat" diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc new file mode 100644 index 000000000..5a370becb --- /dev/null +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -0,0 +1,58 @@ +#@TYPE: Machine +#@NAME: ConnectCore 8M Nano module. +#@DESCRIPTION: Machine configuration for Digi's ConnectCore 8M Nano module. + +DIGI_FAMILY = "ccimx8mn" +MACHINEOVERRIDES =. "mx8:mx8m:mx8mn:ccimx8m:${DIGI_FAMILY}:" + +include conf/machine/include/imx-digi-base.inc +include conf/machine/include/arm/arch-arm64.inc + +# Platform u-boot settings +UBOOT_PREFIX = "imx-boot" +UBOOT_SUFFIX = "bin" + +# The bootloader image that gets flashed consists of U-Boot and several fw binaries +EXTRA_IMAGEDEPENDS = "imx-boot" +BOOTLOADER_IMAGE_RECIPE = "imx-boot" +BOOTLOADER_SEEK = "32" +BOOTABLE_FILENAME = "${UBOOT_PREFIX}-${MACHINE}.bin" +SDIMG_BOOTLOADER = "${DEPLOY_DIR_IMAGE}/${BOOTABLE_FILENAME}" + +# Linux kernel configuration +KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" + +# Wireless external module +WIRELESS_MODULE ?= "" + +# Firmware +MACHINE_FIRMWARE ?= "firmware-imx-sdma firmware-imx-easrc" + +MACHINE_EXTRA_RDEPENDS += " \ + e2fsprogs-mke2fs \ + e2fsprogs-resize2fs \ + mca-tool \ + parted \ + u-boot-fw-utils \ + xbee-init \ +" + +MACHINE_EXTRA_RRECOMMENDS += " \ + ${MACHINE_FIRMWARE} \ + ${WIRELESS_MODULE} \ + cryptodev-module \ + cryptoauthlib \ +" + +MACHINE_FEATURES += "accel-graphics accel-video wifi bluetooth cryptochip" + +# AARCH64 doesn't support self-extracting zImage +KERNEL_IMAGETYPE = "Image.gz" + +VIRTUAL-RUNTIME_init_manager ?= "systemd" +VIRTUAL-RUNTIME_initscripts ?= "initscripts" + +# Adding 'wayland' along with 'x11' enables the xwayland backend +# Vulkan is necessary for wayland to build +DISTRO_FEATURES_append = " wayland vulkan systemd pam" +DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" diff --git a/meta-digi-arm/conf/machine/include/digi-defaults.inc b/meta-digi-arm/conf/machine/include/digi-defaults.inc index 0063dbc43..91bbe0bfc 100644 --- a/meta-digi-arm/conf/machine/include/digi-defaults.inc +++ b/meta-digi-arm/conf/machine/include/digi-defaults.inc @@ -13,6 +13,7 @@ PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg" # ------------------------------------------------- # ccimx6ul 4.14, 4.20 2017.03 # ccimx8x 4.14 2018.03, 2017.03 (both packaged in imx-boot) +# ccimx8mn 4.14 2018.03 (packaged in imx-boot) # # Help variables used in recipes diff --git a/meta-digi-arm/conf/machine/include/imx-digi-base.inc b/meta-digi-arm/conf/machine/include/imx-digi-base.inc index f3474b6e3..a3d181250 100644 --- a/meta-digi-arm/conf/machine/include/imx-digi-base.inc +++ b/meta-digi-arm/conf/machine/include/imx-digi-base.inc @@ -28,6 +28,7 @@ MACHINEOVERRIDES_EXTENDER_mx6q = "imxfbdev:imxipu:imxvpu:imxvpucnm:imxgpu:imxg MACHINEOVERRIDES_EXTENDER_mx6dl = "imxfbdev:imxipu:imxpxp:imxvpu:imxvpucnm:imxgpu:imxgpu2d:imxdpublit:imxgpu3d:imxepdc" MACHINEOVERRIDES_EXTENDER_mx6ul = "imxfbdev:imxpxp" MACHINEOVERRIDES_EXTENDER_mx8qxp = "imxdrm:imxdpu:imxgpu:imxgpu2d:imxgpu3d" +MACHINEOVERRIDES_EXTENDER_mx8mn = "imxdrm:imxgpu:imxgpu3d" # Sub-architecture support MACHINE_SOCARCH_SUFFIX ?= "" @@ -37,6 +38,7 @@ MACHINE_SOCARCH_SUFFIX_mx6ul = "-mx6ul" MACHINE_SOCARCH_SUFFIX_mx8qxp = "-mx8qxp" MACHINE_SOCARCH_SUFFIX_mx8dxp = "-mx8dxp" MACHINE_SOCARCH_SUFFIX_mx8dx = "-mx8dx" +MACHINE_SOCARCH_SUFFIX_mx8mn = "-mx8mn" MACHINE_ARCH_FILTER = "virtual/kernel" MACHINE_SOCARCH_FILTER_append_imxvpu = " imx-vpu libimxvpuapi imx-codec imx-vpuwrap imx-parser" diff --git a/sdk/build-github.sh b/sdk/build-github.sh index fbb5750cb..5bda75c98 100755 --- a/sdk/build-github.sh +++ b/sdk/build-github.sh @@ -3,7 +3,7 @@ # # build-github.sh # -# Copyright (C) 2015-2018 by Digi International Inc. +# Copyright (C) 2015-2019 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ set -e -AVAILABLE_PLATFORMS="ccimx8x-sbc-pro ccimx8x-sbc-express ccimx6qpsbc ccimx6sbc ccimx6ulsbc ccimx6ulstarter" +AVAILABLE_PLATFORMS="ccimx8mn-dvk ccimx8x-sbc-pro ccimx8x-sbc-express ccimx6qpsbc ccimx6sbc ccimx6ulsbc ccimx6ulstarter" MANIFEST_URL="https://github.com/digi-embedded/dey-manifest.git" @@ -121,6 +121,7 @@ while read _pl _tgt; do # the fly with underscores. eval "${_pl//-/_}_tgt=\"${_tgt//,/ }\"" done<<-_EOF_ + ccimx8mn-dvk dey-image-qt ccimx8x-sbc-pro dey-image-qt ccimx8x-sbc-express dey-image-qt ccimx6qpsbc dey-image-qt diff --git a/sdk/build.sh b/sdk/build.sh index 43177f2ce..835129d7b 100755 --- a/sdk/build.sh +++ b/sdk/build.sh @@ -3,7 +3,7 @@ # # build.sh # -# Copyright (C) 2013-2018 by Digi International Inc. +# Copyright (C) 2013-2019 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -171,6 +171,7 @@ while read _pl _var _tgt; do eval "${_pl//-/_}_var=\"${_var//,/ }\"" eval "${_pl//-/_}_tgt=\"${_tgt//,/ }\"" done<<-_EOF_ + ccimx8mn-dvk DONTBUILDVARIANTS dey-image-qt,dey-image-aws ccimx8x-sbc-pro DONTBUILDVARIANTS dey-image-qt,dey-image-aws ccimx8x-sbc-express DONTBUILDVARIANTS dey-image-qt,dey-image-aws ccimx6qpsbc DONTBUILDVARIANTS dey-image-qt,dey-image-aws diff --git a/sdk/config/ccimx8mn-dvk/bblayers.conf.sample b/sdk/config/ccimx8mn-dvk/bblayers.conf.sample new file mode 100644 index 000000000..bc2ef9645 --- /dev/null +++ b/sdk/config/ccimx8mn-dvk/bblayers.conf.sample @@ -0,0 +1,22 @@ +# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +POKY_BBLAYERS_CONF_VERSION = "2" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-poky \ + ##OEROOT##/meta-yocto-bsp \ + ##DIGIBASE##/meta-openembedded/meta-oe \ + ##DIGIBASE##/meta-openembedded/meta-python \ + ##DIGIBASE##/meta-openembedded/meta-networking \ + ##DIGIBASE##/meta-openembedded/meta-webserver \ + ##DIGIBASE##/meta-qt5 \ + ##DIGIBASE##/meta-swupdate \ + ##DIGIBASE##/meta-freescale \ + ##DIGIBASE##/meta-fsl-demos \ + ##DIGIBASE##/meta-digi/meta-digi-arm \ + ##DIGIBASE##/meta-digi/meta-digi-dey \ + " diff --git a/sdk/config/ccimx8mn-dvk/conf-notes.txt b/sdk/config/ccimx8mn-dvk/conf-notes.txt new file mode 100644 index 000000000..6085b7217 --- /dev/null +++ b/sdk/config/ccimx8mn-dvk/conf-notes.txt @@ -0,0 +1,18 @@ +Digi Embedded Yocto provides the following image recipes: + + * dey-image-qt: graphical QT image + + By default the image is XWayland-based so it provides a full Weston + desktop environment. + + To compile the image for the framebuffer (instead of XWayland) add + the following line to the project's conf/local.conf: + + DISTRO_FEATURES_remove = "x11 wayland vulkan" + + * dey-image-aws: console-only image supporting Amazon Web Services IoT + + This image includes the AWS Greengrass Core and an AWS IoT platform + example application. For more information on AWS support in Digi + Embedded Yocto see the online documentation. + diff --git a/sdk/config/ccimx8mn-dvk/local.conf.sample b/sdk/config/ccimx8mn-dvk/local.conf.sample new file mode 100644 index 000000000..be7803074 --- /dev/null +++ b/sdk/config/ccimx8mn-dvk/local.conf.sample @@ -0,0 +1,266 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. More adventurous users can look at local.conf.extended +# which contains other examples of configuration which can be placed in this file +# but new users likely won't need any of them initially. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +# You need to select a specific machine to target the build with. There are a selection +# of emulated machines available which can boot and run in the QEMU emulator: +# +#MACHINE ?= "qemuarm" +#MACHINE ?= "qemuarm64" +#MACHINE ?= "qemumips" +#MACHINE ?= "qemumips64" +#MACHINE ?= "qemuppc" +#MACHINE ?= "qemux86" +#MACHINE ?= "qemux86-64" +# +# There are also the following hardware board target machines included for +# demonstration purposes: +# +#MACHINE ?= "beaglebone-yocto" +#MACHINE ?= "genericx86" +#MACHINE ?= "genericx86-64" +#MACHINE ?= "mpc8315e-rdb" +#MACHINE ?= "edgerouter" +# +# This sets the default machine to be qemux86 if no other machine is selected: +#MACHINE ??= "qemux86" + +MACHINE = "ccimx8mn-dvk" + +# +# Use Digi's internal git repositories +# +#DIGI_INTERNAL_GIT ?= "1" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "dey" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to rpm: +PACKAGE_CLASSES ?= "package_rpm" + +# +# SDK target architecture +# +# This variable specifies the architecture to build SDK items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686 and x86_64 +#SDKMACHINE ?= "i686" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-mklibs' to reduce shared library files size for an image +# - 'image-prelink' in order to prelink the filesystem image +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +USER_CLASSES ?= "buildstats image-mklibs image-prelink" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. It can also +# run tests against any SDK that are built. To enable this uncomment these lines. +# See classes/test{image,sdk}.bbclass for further details. +#IMAGE_CLASSES += "testimage testsdk" +#TESTIMAGE_AUTO_qemuall = "1" + +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necesary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS ??= "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + ABORT,${TMPDIR},100M,1K \ + ABORT,${DL_DIR},100M,1K \ + ABORT,${SSTATE_DIR},100M,1K \ + ABORT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + +# +# Yocto Project SState Mirror +# +# The Yocto Project has prebuilt artefacts available for its releases, you can enable +# use of these by uncommenting the following line. This will mean the build uses +# the network to check for artefacts at the start of builds, which does slow it down +# equally, it will also speed up the builds by not having to build things if they are +# present in the cache. It assumes you can download something faster than you can build it +# which will depend on your network. +# +#SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/2.5/PATH;downloadfilename=PATH" + +# +# Qemu configuration +# +# By default qemu will build with a builtin VNC server where graphical output can be +# seen. The two lines below enable the SDL backend too. By default libsdl2-native will +# be built, if you want to use your host's libSDL instead of the minimal libsdl built +# by libsdl2-native then uncomment the ASSUME_PROVIDED line below. +PACKAGECONFIG_append_pn-qemu-native = " sdl" +PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl" +#ASSUME_PROVIDED += "libsdl2-native" + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "1" + +# +# Enable local PR server +# +PRSERV_HOST = "localhost:0" + +# +# Some libraries and packages are covered by NXP EULA +# +#ACCEPT_FSL_EULA = "1" From 6130059988beb4aa0fb4d98ecdc1b0609b8c0b29 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:11:42 +0200 Subject: [PATCH 033/120] uboot: add support to ConnectCore 8M Nano DVK platform Add initial support cloned from ccimx8x-sbc-pro. https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../u-boot/u-boot-dey/ccimx8mn-dvk/boot.txt | 48 ++++++ .../ccimx8mn-dvk/install_linux_fw_sd.txt | 142 ++++++++++++++++++ .../recipes-bsp/u-boot/u-boot-dey_2018.03.bb | 4 +- 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/boot.txt create mode 100644 meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/install_linux_fw_sd.txt diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/boot.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/boot.txt new file mode 100644 index 000000000..469c583de --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/boot.txt @@ -0,0 +1,48 @@ +# +# U-Boot bootscript for EMMC/SD images created by Yocto. +# + +# Set SOC type to "imx8mn" if not already defined by U-Boot +if test ! -n "${soc_type}"; then + setenv soc_type "imx8mn" +fi + +# +# Set device tree filename depending on the board ID (if defined) +# +if test -n "${board_id}"; then + setenv fdt_file cc${soc_type}-dvk-id${board_id}.dtb +else + # + # Set device tree filename depending on the hardware capabilities + # + if test -n "${module_ram}"; then + setexpr module_has_wifi ${hwid_2} \& 10000 + setexpr module_has_wifi ${module_has_wifi} / 10000 + setexpr module_has_bt ${hwid_2} \& 20000 + setexpr module_has_bt ${module_has_bt} / 20000 + + if test "${module_has_wifi}" = "1" && + test "${module_has_bt}" = "1"; then + setenv fdt_file cc${soc_type}-dvk-wb.dtb + else + setenv fdt_file cc${soc_type}-dvk.dtb + fi + fi +fi + +# Get the UUID of the configured boot partition. +part uuid mmc ${mmcbootdev}:${mmcpart} bootpart +# Check the boot source. +if test "${bootpart}" = "${part1_uuid}"; then + # We are booting from the eMMC using 'linux'. + true +elif test "${bootpart}" = "${part2_uuid}"; then + # We are booting from the eMMC using 'recovery'. + setenv boot_initrd true + setenv initrd_file uramdisk-recovery.img +else + # We are booting from the SD card. + setenv mmcroot /dev/mmcblk${mmcbootdev}p2 +fi +dboot linux mmc ${mmcbootdev}:${mmcpart} diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/install_linux_fw_sd.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/install_linux_fw_sd.txt new file mode 100644 index 000000000..b662264ff --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8mn-dvk/install_linux_fw_sd.txt @@ -0,0 +1,142 @@ +# +# U-Boot script for installing Linux images created by Yocto from the SD +# card into the eMMC +# + +echo "############################################################" +echo "# Linux firmware install from micro SD #" +echo "############################################################" +echo "" +echo " This process will erase your eMMC and will install a new" +echo " U-Boot and Linux firmware images on the eMMC." +echo "" +echo " Press CTRL+C now if you wish to abort or wait 10 seconds" +echo " to continue." + +sleep 10 +if test $? -eq 1; then + echo "Aborted by user."; + exit; +fi + +setenv INSTALL_UBOOT_FILENAME imx-boot-ccimx8mn-dvk.bin; +setenv INSTALL_MMCDEV 1 +setenv INSTALL_LINUX_FILENAME dey-image-qt-##GRAPHICAL_BACKEND##-ccimx8mn-dvk.boot.vfat +setenv INSTALL_RECOVERY_FILENAME dey-image-qt-##GRAPHICAL_BACKEND##-ccimx8mn-dvk.recovery.vfat +setenv INSTALL_ROOTFS_FILENAME dey-image-qt-##GRAPHICAL_BACKEND##-ccimx8mn-dvk.ext4 + +# Check for presence of firmware files on the SD card +for install_f in ${INSTALL_UBOOT_FILENAME} ${INSTALL_LINUX_FILENAME} ${INSTALL_RECOVERY_FILENAME} ${INSTALL_ROOTFS_FILENAME}; do + if test ! -e mmc ${INSTALL_MMCDEV} ${install_f}; then + echo "ERROR: Could not find file ${install_f}"; + install_abort=1; + fi; +done +if test -n "${install_abort}"; then + echo "Aborted."; + exit; +fi + +# Skip user confirmation for U-Boot update +setenv forced_update 1 + +# Set bootdelay to zero so that firmware update is run immediately after +# the first reset. +setenv bootdelay 0 + +# Set target MMC device index to eMMC +setenv mmcdev 0 + +# Update U-Boot +echo "" +echo "" +echo ">> Installing U-Boot boot loader (target will reset)" +echo "" +echo "" +update uboot mmc ${INSTALL_MMCDEV} fat ${INSTALL_UBOOT_FILENAME} +if test $? -eq 1; then + echo "[ERROR] Failed to update U-Boot boot loader!"; + echo ""; + echo "Aborted."; + exit; +fi + +# Set 'bootcmd' to the second part of the script that will +# - Reset environment to defaults +# - Save the environment +# - Force on-the-fly updates to avoid possible verification errors +# - Partition the eMMC user data area for Linux +# - Update the 'linux' partition +# - Update the 'recovery' partition +# - Update the 'rootfs' partition +# - Configure recovery to wipe 'update' partition +# - Disable on-the-fly updates +# - Run 'recovery' and let the system boot after +setenv bootcmd " + env default -a; + saveenv; + setenv otf-update yes; + echo \"\"; + echo \"\"; + echo \">> Creating Linux partition table on the eMMC\"; + echo \"\"; + echo \"\"; + run partition_mmc_linux; + if test \$? -eq 1; then + echo \"[ERROR] Failed to create Linux partition table!\"; + echo \"\"; + echo \"Aborted.\"; + exit; + fi; + echo \"\"; + echo \"\"; + echo \">> Installing Linux kernel and device tree files\"; + echo \"\"; + echo \"\"; + update linux mmc ${INSTALL_MMCDEV} fat ${INSTALL_LINUX_FILENAME}; + if test \$? -eq 1; then + echo \"[ERROR] Failed to update linux partition!\"; + echo \"\"; + echo \"Aborted.\"; + exit; + fi; + echo \"\"; + echo \"\"; + echo \">> Installing recovery\"; + echo \"\"; + echo \"\"; + update recovery mmc ${INSTALL_MMCDEV} fat ${INSTALL_RECOVERY_FILENAME}; + if test \$? -eq 1; then + echo \"[ERROR] Failed to update recovery partition!\"; + echo \"\"; + echo \"Aborted.\"; + exit; + fi; + echo \"\"; + echo \"\"; + echo \">> Installing Linux root file system\"; + echo \"\"; + echo \"\"; + update rootfs mmc ${INSTALL_MMCDEV} fat ${INSTALL_ROOTFS_FILENAME}; + if test \$? -eq 1; then + echo \"[ERROR] Failed to update rootfs partition!\"; + echo \"\"; + echo \"Aborted.\"; + exit; + fi; + echo \"\"; + setenv boot_recovery yes; + setenv recovery_command wipe_update; + setenv otf-update; + saveenv; + echo \"\"; + echo \"\"; + echo \">> Firmware installation complete. Rebooting into recovery mode for final deployment.\"; + echo \"\"; + echo \"\"; + sleep 1; + reset; +" + +saveenv +reset diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2018.03.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2018.03.bb index 2f4fa5aab..efe133157 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2018.03.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2018.03.bb @@ -1,8 +1,8 @@ -# Copyright (C) 2019 Digi International +# Copyright (C) 2019,2020 Digi International require digi-u-boot.inc SRCBRANCH = "v2018.03/master" SRCREV = "${AUTOREV}" -COMPATIBLE_MACHINE = "(ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx8x|ccimx8m)" From 9ce3f4730f75f520f4fd0dfac4fb23d8a0b4655c Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:14:07 +0200 Subject: [PATCH 034/120] u-boot-fw-utils: add support for ConnectCore 8M Nano DVK platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../u-boot/u-boot-fw-utils/ccimx8mn/fw_env.config | 7 +++++++ .../recipes-bsp/u-boot/u-boot-fw-utils_%.bbappend | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils/ccimx8mn/fw_env.config diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils/ccimx8mn/fw_env.config b/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils/ccimx8mn/fw_env.config new file mode 100644 index 000000000..040cd8e30 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils/ccimx8mn/fw_env.config @@ -0,0 +1,7 @@ +# Configuration file for fw_(printenv/setenv) utility. +# Up to two entries are valid, in this case the redundant +# environment sector is assumed present. + +# Device name Offset Size +/dev/mmcblk0boot1 0x1C0000 0x4000 +/dev/mmcblk0boot1 0x1E0000 0x4000 diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils_%.bbappend b/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils_%.bbappend index 195bc2a01..a6197e0f7 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils_%.bbappend +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils_%.bbappend @@ -82,5 +82,3 @@ pkg_postinst_ontarget_${PN}() { ${CONFIG_FILE} fi } - -COMPATIBLE_MACHINE = "(ccimx6$|ccimx6ul|ccimx8x)" From 7d54990e57f08af4eb8c67f1c320cf590e540ffb Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:29:10 +0200 Subject: [PATCH 035/120] modemmanager: add support to ConnectCore 8M Nano DVK platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../ccimx8mn/78-mm-digi-xbee-cellular.rules | 10 ++++++++++ .../ccimx8mn/80-mm-net-device-blacklist.rules | 12 ++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules create mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules new file mode 100644 index 000000000..f4b484c18 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules @@ -0,0 +1,10 @@ +ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" + +# By default, ModemManager expects a default baudrate of 57600bps. Different +# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. + +# ModemManager documentation states that the best practice is to use the DEVPATH +# this way rather than other rules such as KERNEL, so be careful when modifying +DEVPATH=="/devices/platform/30a60000.serial/tty/ttymxc3", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" + +LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules new file mode 100644 index 000000000..113069765 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules @@ -0,0 +1,12 @@ +ACTION!="add|change|move|bind", GOTO="mm_net_device_blacklist_end" + +# ModemManager documentation states that the best practice is to use the DEVPATH +# this way rather than other rules such as KERNEL, so be careful when modifying + +# Remove Ethernet interfaces from ModemManager probing +SUBSYSTEM=="net", DEVPATH=="/devices/platform/30be0000.ethernet*", ENV{ID_MM_CANDIDATE}="0", ENV{ID_MM_DEVICE_IGNORE}="1" + +# Remove MMC interfaces from ModemManager probing +SUBSYSTEM=="net", DEVPATH=="/devices/platform/30b40000.mmc*", ENV{ID_MM_CANDIDATE}="0", ENV{ID_MM_DEVICE_IGNORE}="1" + +LABEL="mm_net_device_blacklist_end" From b90c05c33653e247fbbd5f6889d25fb93c91b6b8 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:31:20 +0200 Subject: [PATCH 036/120] cryptoauthlib: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../recipes-digi/cryptoauthlib/cryptoauthlib_git.bb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb index 846c8f15c..43a41a7e0 100644 --- a/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb +++ b/meta-digi-arm/recipes-digi/cryptoauthlib/cryptoauthlib_git.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2019 Digi International Inc. +# Copyright (C) 2017-2020 Digi International Inc. SUMMARY = "Microchip CryptoAuthentication Library" SECTION = "libs" @@ -25,6 +25,7 @@ I2C_BUS = "" I2C_BUS_ccimx6qpsbc = "1" I2C_BUS_ccimx6ul = "0" I2C_BUS_ccimx8x = "0" +I2C_BUS_ccimx8mn = "0" I2C_SPEED ?= "100000" @@ -50,4 +51,4 @@ RDEPENDS_${PN}-test = "${PN}" RRECOMMENDS_${PN} = "${PN}-test" PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x|ccimx8m)" From d53a6adb43c890cb5728b826bf093f0c26462eb2 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:33:25 +0200 Subject: [PATCH 037/120] linux: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- meta-digi-arm/recipes-kernel/linux/linux-dey_4.14.bb | 4 ++-- meta-digi-arm/recipes-kernel/linux/linux-imx-headers_4.14.bb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_4.14.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_4.14.bb index bfa3cd0de..2e0a739f1 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_4.14.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_4.14.bb @@ -1,5 +1,5 @@ -# Copyright (C) 2019 Digi International +# Copyright (C) 2019,2020 Digi International require recipes-kernel/linux/linux-dey.inc -COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-arm/recipes-kernel/linux/linux-imx-headers_4.14.bb b/meta-digi-arm/recipes-kernel/linux/linux-imx-headers_4.14.bb index 5e834e8f6..0689a2ae5 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-imx-headers_4.14.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-imx-headers_4.14.bb @@ -1,5 +1,5 @@ -# Copyright (C) 2019 Digi International +# Copyright (C) 2019,2020 Digi International require recipes-kernel/linux/linux-imx-headers.inc -COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx8m)" From 4d5028fcc8c58eefbbb88e50e958af1321498950 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:36:31 +0200 Subject: [PATCH 038/120] libdigiapix: add support to ConnectCore 8M Nano DVK platform Add initial support cloned from ccimx8x-sbc-pro. https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../ccimx8mn-dvk/libdigiapix.conf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf new file mode 100644 index 000000000..632987f1c --- /dev/null +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf @@ -0,0 +1,36 @@ +[board] +model = Digi International ConnectCore 8M Nano DVK. + +[GPIO] + +# USER LED1 - MCA_IO12 +USER_LED = 505 +USER_LED1 = 505 + +# USER_LED2 - MCA_IO18 +USER_LED2 = 511 + +# USER_LED3 - GPIO2_IO19 +USER_LED3 = 51 + +# USER BUTTON1 - MCA_IO10 +USER_BUTTON = 503 +USER_BUTTON1 = 503 + +# USER BUTTON2 - GPIO2_IO20 +USER_BUTTON2 = 52 + +[I2C] + +# I2C-4 on Expansion connector. +DEFAULT_I2C_BUS = 4 + +[PWM] + +# PWM0 channel 2 on XBEE1 connector (MCA_IO15) +DEFAULT_PWM = 0,2 + +[ADC] + +# ADC_IN0 on Expansion connector +DEFAULT_ADC = 0,0 From 99dde8c678f9ddfb1fdd657e4f77601ac20c545a Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:37:56 +0200 Subject: [PATCH 039/120] xbee: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- meta-digi-dey/recipes-connectivity/xbee/xbee.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb index 2c463c543..26e796859 100644 --- a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb +++ b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2019 Digi International Inc. +# Copyright (C) 2019,2020 Digi International Inc. SUMMARY = "Digi XBee initialization" DESCRIPTION = "Initialization scripts for XBee hardware of Digi boards" @@ -40,4 +40,4 @@ SYSTEMD_PACKAGES = "${PN}-init" SYSTEMD_SERVICE_${PN}-init = "xbee-init.service" PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx8x|ccimx8m)" From 8e853e76d19a366415e494e91f47793d91c8833b Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:39:44 +0200 Subject: [PATCH 040/120] busybox: add support to ccimx8mn platform Add initial support cloned from ccimx8x-sbc-pro. https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../busybox/busybox/ccimx8mn/acpid.map | 3 + .../busybox/busybox/ccimx8mn/standby | 116 ++++++++++++++++++ .../busybox/busybox/ccimx8mn/standby-actions | 64 ++++++++++ 3 files changed, 183 insertions(+) create mode 100644 meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/acpid.map create mode 100755 meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby create mode 100644 meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby-actions diff --git a/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/acpid.map b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/acpid.map new file mode 100644 index 000000000..f3940541e --- /dev/null +++ b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/acpid.map @@ -0,0 +1,3 @@ +#s_type n_type(hex) s_code n_code value description +EV_KEY 0x01 KEY_SLEEP 142 1 pswitch-standby +EV_KEY 0x01 KEY_POWER 116 1 pswitch-poweroff diff --git a/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby new file mode 100755 index 000000000..e86e1c0a1 --- /dev/null +++ b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby @@ -0,0 +1,116 @@ +#!/bin/sh +#=============================================================================== +# +# standby +# +# Copyright (C) 2020 by Digi International Inc. +# All rights reserved. +# +# 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. +# +# +# !Description: suspend system to RAM +# +#=============================================================================== + +scriptname="$(basename $(readlink -f ${0}))" +syspower="/sys/power/state" +lockfile="/var/lock/${scriptname}.lock" +lockfd="9" + +BT_INIT="/etc/init.d/bluetooth-init" +BT_DAEMON="/etc/init.d/bluetooth" +NM_DAEMON="/etc/init.d/networkmanager" + +usage() { + printf "\nSuspend system to RAM memory\n" + printf "\nUsage: ${scriptname} [OPTIONS]\n + -h Show this help + \n" +} + +suspend_interfaces() { + # Stop NetworkManager before suspend + ${NM_DAEMON} stop + + # Suspend wireless interfaces + if [ -d "/proc/device-tree/wireless" ]; then + for i in $(sed -ne 's,^\(wlan[0-9]\)=.*,\1,g;T;p' /var/run/ifstate | sort -r); do + ifdown "${i}" && RESUME_IFACES="${RESUME_IFACES:+${RESUME_IFACES} }${i}" + done + grep -qs '^wlan' /proc/modules && rmmod wlan + fi + + # Suspend bluetooth interface + if [ -d "/proc/device-tree/bluetooth" ]; then + hciconfig hci0 2>&1 | grep -qs UP && up_bt_on_resume="1" + ${BT_DAEMON} stop >/dev/null + ${BT_INIT} stop >/dev/null + fi +} + +resume_interfaces() { + # Resume wireless interfaces + if [ -d "/proc/device-tree/wireless" ]; then + # Trigger wireless module loading event, and wait until the interface exists + udevadm trigger --action=add --attr-match="modalias=sdio:c00v0271d050A" + timeout -t 5 sh -c "while [ ! -d /sys/class/net/wlan0 ]; do sleep .2; done" 2>/dev/null + + # Bring up the interfaces that were bring down on suspend + for i in $(echo ${RESUME_IFACES} | tr ' ' '\n' | sort); do + grep -qs "^${i}" /var/run/ifstate || ifup "${i}" + done + fi + + # Resume bluetooth interface + if [ -d "/proc/device-tree/bluetooth" ]; then + if [ -n "${up_bt_on_resume}" ]; then + ${BT_INIT} start >/dev/null + ${BT_DAEMON} start >/dev/null + fi + fi + + # Resume NetworkManager after suspend + ${NM_DAEMON} start +} + +enter_critical_section() { + # Create lock file + eval "exec ${lockfd}>${lockfile}" + + # Acquire the lock in non blocking mode. Otherwise, additional calls + # to the script will be queued and the system will endlessly go in + # and out of suspend to ram + flock -n "${lockfd}" || exit 0 +} + +exit_critical_section() { + # Release the lock + flock -u "${lockfd}" +} + +while getopts "h" c; do + case "${c}" in + h) usage; exit;; + esac +done + +if [ -f "${syspower}" ]; then + # Avoid running multiple instances of this script in parallel + enter_critical_section + + # Pre-suspend actions + suspend_interfaces + + # Suspend the device + printf "mem" > ${syspower} + + # Post-resume actions + resume_interfaces + + exit_critical_section +else + printf "\n[ERROR] File ${syspower} not found\n\n" +fi diff --git a/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby-actions b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby-actions new file mode 100644 index 000000000..987e9d3b4 --- /dev/null +++ b/meta-digi-dey/recipes-core/busybox/busybox/ccimx8mn/standby-actions @@ -0,0 +1,64 @@ +#!/bin/sh +#=============================================================================== +# +# standby-actions +# +# Copyright (C) 2020 by Digi International Inc. +# All rights reserved. +# +# 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. +# +# +# !Description: manage interfaces before suspending and after resuming from +# suspend +# +#=============================================================================== + +if [ "${1}" == "pre" ]; then + # Stop NetworkManager before suspend + systemctl stop NetworkManager + + # Suspend wireless interfaces + if [ -d "/proc/device-tree/wireless" ]; then + for i in $(sed -ne 's,^\(wlan[0-9]\)=.*,\1,g;T;p' /var/run/ifstate | sort -r); do + ifdown "${i}" && RESUME_IFACES="${RESUME_IFACES:+${RESUME_IFACES} }${i}" + done + + echo ${RESUME_IFACES} > /tmp/suspend_wlan_ifaces + grep -qs '^wlan' /proc/modules && rmmod wlan + fi + + # Suspend bluetooth interface + if [ -d "/proc/device-tree/bluetooth" ]; then + hciconfig hci0 2>&1 | grep -qs UP && touch /tmp/up_bt_on_resume + systemctl stop bluetooth + systemctl stop bluetooth-init + fi +elif [ "${1}" == "post" ]; then + # Resume wireless interfaces + if [ -d "/proc/device-tree/wireless" ]; then + # Trigger wireless module loading event, and wait until the interface exists + udevadm trigger --action=add --attr-match="modalias=sdio:c00v0271d050A" + timeout -t 5 sh -c "while [ ! -d /sys/class/net/wlan0 ]; do sleep .2; done" 2>/dev/null + + # Bring up the interfaces that were brought down on suspend + for i in $(cat /tmp/suspend_wlan_ifaces | tr ' ' '\n' | sort); do + grep -qs "^${i}" /var/run/ifstate || ifup "${i}" + done + rm -f /tmp/suspend_wlan_ifaces + fi + + # Resume NetworkManager after suspend + systemctl start NetworkManager + + # Resume bluetooth interface + if [ -d "/proc/device-tree/bluetooth" ]; then + if [ -e "/tmp/up_bt_on_resume" ]; then + systemctl start bluetooth-init + systemctl start bluetooth + rm -f /tmp/up_bt_on_resume + fi + fi +fi From cece2ee9842448a29b6d47213bb8683ec44f84e1 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:40:43 +0200 Subject: [PATCH 041/120] wpa-supplicant: add support to ccimx8mn platform Add initial support cloned from ccimx8x-sbc-pro. https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../ccimx8mn/wpa_supplicant.conf-sane | 18 ++++++++++++++++++ .../ccimx8mn/wpa_supplicant_p2p.conf | 8 ++++++++ 2 files changed, 26 insertions(+) create mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane create mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane new file mode 100644 index 000000000..c58546a06 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane @@ -0,0 +1,18 @@ +ctrl_interface=/var/run/wpa_supplicant +ctrl_interface_group=0 +fast_reauth=1 +update_config=1 + +ap_scan=1 + +# Static scheduled scan interval time in seconds +# +# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On +# occassions, fixing the interval time is helpful, for example on DFS channels. +#sched_scan_interval=2 + +network={ + scan_ssid=1 + ssid="" + key_mgmt=NONE +} diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf new file mode 100644 index 000000000..d4fba6e05 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf @@ -0,0 +1,8 @@ +ctrl_interface=/var/run/wpa_supplicant +update_config=1 +device_name=ccimx8mn-p2p +manufacturer=QCA +model_name=McK +device_type=1-0050F204-1 +config_methods=display keypad push_button +persistent_reconnect=1 From 017c2d0964cd0338fc101a9fac11497cd12b96bd Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 11:29:23 +0100 Subject: [PATCH 042/120] wpa_supplicant: unify config file for all platforms WPA and P2P configuration files are basically the same between all platforms, so we remove all duplicated files to use a common file and modify it in the recipe logic. Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/ccimx6qpsbc.conf | 1 + meta-digi-arm/conf/machine/ccimx6sbc.conf | 3 +++ meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 10 -------- .../conf/machine/ccimx8x-sbc-express.conf | 10 -------- .../conf/machine/ccimx8x-sbc-pro.conf | 10 -------- .../conf/machine/include/ccimx6ul.inc | 1 + .../conf/machine/include/ccimx8mn.inc | 7 ++++++ .../conf/machine/include/ccimx8x.inc | 7 ++++++ .../ccimx6qpsbc/wpa_supplicant.conf-sane | 18 --------------- .../ccimx6qpsbc/wpa_supplicant_p2p.conf | 8 ------- .../ccimx6sbc/wpa_supplicant_p2p.conf | 2 +- .../ccimx6ul/wpa_supplicant.conf-sane | 18 --------------- .../ccimx6ul/wpa_supplicant_p2p.conf | 8 ------- .../ccimx8mn/wpa_supplicant.conf-sane | 18 --------------- .../ccimx8x/wpa_supplicant.conf-sane | 18 --------------- .../ccimx8x/wpa_supplicant_p2p.conf | 8 ------- .../wpa-supplicant/wpa_supplicant.conf-sane | 22 +++++++----------- .../{ccimx8mn => }/wpa_supplicant_p2p.conf | 2 +- .../wpa-supplicant/wpa-supplicant_%.bbappend | 23 ++++++++++++++++++- 19 files changed, 51 insertions(+), 143 deletions(-) delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant.conf-sane delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant_p2p.conf delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant.conf-sane delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant_p2p.conf delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant.conf-sane delete mode 100644 meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant_p2p.conf rename meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/{ccimx8mn => }/wpa_supplicant_p2p.conf (82%) diff --git a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf index 334639e36..9696a2445 100644 --- a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf @@ -10,6 +10,7 @@ WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-mod # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" +WLAN_P2P_DEVICE_NAME ?= "ccimx6qp-p2p" MACHINE_EXTRA_RRECOMMENDS += " \ cryptoauthlib \ diff --git a/meta-digi-arm/conf/machine/ccimx6sbc.conf b/meta-digi-arm/conf/machine/ccimx6sbc.conf index 5d399b38e..afb4d2515 100644 --- a/meta-digi-arm/conf/machine/ccimx6sbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6sbc.conf @@ -5,6 +5,9 @@ # Contains the ConnectCore 6 module. include conf/machine/include/ccimx6.inc +# Wireless p2p interface +WLAN_P2P_DEVICE_NAME ?= "ccimx6-p2p" + # Firmware MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1' , 'firmware-atheros-ar3k', '', d)}" MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1' , 'firmware-atheros-ath6kl', '', d)}" diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf index b76dd0eb6..7850be6ba 100644 --- a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -5,16 +5,6 @@ # Include the machine configuration for Digi's ConnectCore 8M Nano module. include conf/machine/include/ccimx8mn.inc -# Wireless external module -WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" - -# Wireless p2p interface -WLAN_P2P_INTERFACE ?= "p2p0" - -# Firmware -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6564-bt', '', d)}" -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6564-wifi', '', d)}" - # U-Boot configurations # Last one is the default (the one the symlinks point at) UBOOT_CONFIG ??= "ccimx8mn_dvk" diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf index 0d7f05cab..3884f0242 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf @@ -5,16 +5,6 @@ # Include the machine configuration for Digi's ConnectCore 8X module. include conf/machine/include/ccimx8x.inc -# Wireless external module -WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" - -# Wireless p2p interface -WLAN_P2P_INTERFACE ?= "p2p0" - -# Firmware -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6574-bt', '', d)}" -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6574-wifi', '', d)}" - # U-Boot configurations # Last one is the default (the one the symlinks point at) UBOOT_CONFIG ??= "ccimx8x_sbc_express2GB ccimx8x_sbc_express1GB" diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf index 6a5191ad3..875384504 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf @@ -5,16 +5,6 @@ # Include the machine configuration for Digi's ConnectCore 8X module. include conf/machine/include/ccimx8x.inc -# Wireless external module -WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" - -# Wireless p2p interface -WLAN_P2P_INTERFACE ?= "p2p0" - -# Firmware -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6574-bt', '', d)}" -MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6574-wifi', '', d)}" - # U-Boot configurations # Last one is the default (the one the symlinks point at) UBOOT_CONFIG ??= "ccimx8x_sbc_pro512MB ccimx8x_sbc_pro1GB ccimx8x_sbc_pro2GB" diff --git a/meta-digi-arm/conf/machine/include/ccimx6ul.inc b/meta-digi-arm/conf/machine/include/ccimx6ul.inc index fda7ce35d..c848046f5 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6ul.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6ul.inc @@ -18,6 +18,7 @@ WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-mod # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" +WLAN_P2P_DEVICE_NAME ?= "ccimx6ul-p2p" # Firmware MACHINE_FIRMWARE ?= "firmware-imx-sdma" diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc index 5a370becb..617add729 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8mn.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -24,9 +24,16 @@ KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" # Wireless external module WIRELESS_MODULE ?= "" +WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" + +# Wireless p2p interface +WLAN_P2P_INTERFACE ?= "p2p0" +WLAN_P2P_DEVICE_NAME ?= "ccimx8mn-p2p" # Firmware MACHINE_FIRMWARE ?= "firmware-imx-sdma firmware-imx-easrc" +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6564-bt', '', d)}" +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6564-wifi', '', d)}" MACHINE_EXTRA_RDEPENDS += " \ e2fsprogs-mke2fs \ diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index 0caea5a08..ea765ec12 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -31,9 +31,16 @@ KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8x_defconfig" # Wireless external module WIRELESS_MODULE ?= "" +WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" + +# Wireless p2p interface +WLAN_P2P_INTERFACE ?= "p2p0" +WLAN_P2P_DEVICE_NAME ?= "ccimx8x-p2p" # Firmware MACHINE_FIRMWARE ?= "firmware-imx-vpu-imx8 firmware-imx-sdma" +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_BT', '1', 'firmware-qualcomm-qca6574-bt', '', d)}" +MACHINE_FIRMWARE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'firmware-qualcomm-qca6574-wifi', '', d)}" MACHINE_EXTRA_RDEPENDS += " \ e2fsprogs-mke2fs \ diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant.conf-sane deleted file mode 100644 index c58546a06..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant.conf-sane +++ /dev/null @@ -1,18 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=0 -fast_reauth=1 -update_config=1 - -ap_scan=1 - -# Static scheduled scan interval time in seconds -# -# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On -# occassions, fixing the interval time is helpful, for example on DFS channels. -#sched_scan_interval=2 - -network={ - scan_ssid=1 - ssid="" - key_mgmt=NONE -} diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant_p2p.conf deleted file mode 100644 index c6d16f32d..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6qpsbc/wpa_supplicant_p2p.conf +++ /dev/null @@ -1,8 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -update_config=1 -device_name=ccimx6qp-p2p -manufacturer=QCA -model_name=McK -device_type=1-0050F204-1 -config_methods=display keypad push_button -persistent_reconnect=1 diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6sbc/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6sbc/wpa_supplicant_p2p.conf index c1146257f..36d8277bf 100644 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6sbc/wpa_supplicant_p2p.conf +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6sbc/wpa_supplicant_p2p.conf @@ -1,6 +1,6 @@ ctrl_interface=/var/run/wpa_supplicant ctrl_interface_group=0 -device_name=ccimx6-p2p +device_name=##WLAN_P2P_DEVICE_NAME## device_type=10-0050F204-5 config_methods=virtual_push_button keypad display pin persistent_reconnect=1 diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant.conf-sane deleted file mode 100644 index c58546a06..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant.conf-sane +++ /dev/null @@ -1,18 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=0 -fast_reauth=1 -update_config=1 - -ap_scan=1 - -# Static scheduled scan interval time in seconds -# -# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On -# occassions, fixing the interval time is helpful, for example on DFS channels. -#sched_scan_interval=2 - -network={ - scan_ssid=1 - ssid="" - key_mgmt=NONE -} diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant_p2p.conf deleted file mode 100644 index 30a6699e6..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx6ul/wpa_supplicant_p2p.conf +++ /dev/null @@ -1,8 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -update_config=1 -device_name=ccimx6ul-p2p -manufacturer=QCA -model_name=McK -device_type=1-0050F204-1 -config_methods=display keypad push_button -persistent_reconnect=1 diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane deleted file mode 100644 index c58546a06..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant.conf-sane +++ /dev/null @@ -1,18 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=0 -fast_reauth=1 -update_config=1 - -ap_scan=1 - -# Static scheduled scan interval time in seconds -# -# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On -# occassions, fixing the interval time is helpful, for example on DFS channels. -#sched_scan_interval=2 - -network={ - scan_ssid=1 - ssid="" - key_mgmt=NONE -} diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant.conf-sane deleted file mode 100644 index c58546a06..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant.conf-sane +++ /dev/null @@ -1,18 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=0 -fast_reauth=1 -update_config=1 - -ap_scan=1 - -# Static scheduled scan interval time in seconds -# -# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On -# occassions, fixing the interval time is helpful, for example on DFS channels. -#sched_scan_interval=2 - -network={ - scan_ssid=1 - ssid="" - key_mgmt=NONE -} diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant_p2p.conf deleted file mode 100644 index af04ee92b..000000000 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8x/wpa_supplicant_p2p.conf +++ /dev/null @@ -1,8 +0,0 @@ -ctrl_interface=/var/run/wpa_supplicant -update_config=1 -device_name=ccimx8x-p2p -manufacturer=QCA -model_name=McK -device_type=1-0050F204-1 -config_methods=display keypad push_button -persistent_reconnect=1 diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant.conf-sane b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant.conf-sane index ac94bd5c7..c58546a06 100644 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant.conf-sane +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant.conf-sane @@ -3,22 +3,16 @@ ctrl_interface_group=0 fast_reauth=1 update_config=1 -## -- Example MANAGED network -ap_scan=1 # MANAGED mode +ap_scan=1 + +# Static scheduled scan interval time in seconds +# +# The wpa-supplicant dynamically adjusts the scheduled scan time interval. On +# occassions, fixing the interval time is helpful, for example on DFS channels. +#sched_scan_interval=2 + network={ scan_ssid=1 ssid="" key_mgmt=NONE } - -# -- SoftAP mode -# ap_scan=2 -# network={ -# ssid="ath6kl-ap" -# mode=2 -# frequency=2412 -# key_mgmt=WPA-PSK -# proto=RSN -# pairwise=CCMP -# psk="12345678" -# } diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant_p2p.conf similarity index 82% rename from meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf rename to meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant_p2p.conf index d4fba6e05..b3ba3b1f7 100644 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/ccimx8mn/wpa_supplicant_p2p.conf +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant/wpa_supplicant_p2p.conf @@ -1,6 +1,6 @@ ctrl_interface=/var/run/wpa_supplicant update_config=1 -device_name=ccimx8mn-p2p +device_name=##WLAN_P2P_DEVICE_NAME## manufacturer=QCA model_name=McK device_type=1-0050F204-1 diff --git a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend index 7867dd56c..8fc798194 100644 --- a/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2019 Digi International. +# Copyright (C) 2013-2020 Digi International. FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" @@ -12,6 +12,27 @@ SRC_URI += " \ do_install_append() { install -m 600 ${WORKDIR}/wpa_supplicant_p2p.conf ${D}${sysconfdir}/wpa_supplicant_p2p.conf + sed -i -e "s,##WLAN_P2P_DEVICE_NAME##,${WLAN_P2P_DEVICE_NAME},g" \ + ${D}${sysconfdir}/wpa_supplicant_p2p.conf +} + +do_install_append_ccimx6sbc() { + # Customize supplicant file + cat <>${D}${sysconfdir}/wpa_supplicant.conf + +# -- SoftAP mode +# ap_scan=2 +# network={ +# ssid="ath6kl-ap" +# mode=2 +# frequency=2412 +# key_mgmt=WPA-PSK +# proto=RSN +# pairwise=CCMP +# psk="12345678" +# } + +EOF } PACKAGE_ARCH = "${MACHINE_ARCH}" From bc5a22f88380721c618af7f333f4dd672d65e380 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:41:58 +0200 Subject: [PATCH 043/120] bluez5: add support to ccimx8mn platform Add initial support cloned from ccimx8x-sbc-pro. https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../bluez/bluez5-5.50/ccimx8mn/bluetooth-init | 69 +++++++++++++++++++ .../bluez/bluez5-5.50/ccimx8mn/main.conf | 12 ++++ .../bluez/bluez5_5.50.bbappend | 3 +- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/bluetooth-init create mode 100644 meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/main.conf diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/bluetooth-init b/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/bluetooth-init new file mode 100644 index 000000000..01f57c95f --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/bluetooth-init @@ -0,0 +1,69 @@ +#!/bin/sh +#=============================================================================== +# +# Copyright (C) 2018,2019 by Digi International Inc. +# All rights reserved. +# +# 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. +# +# +# !Description: Initialize bluetooth hardware +# +#=============================================================================== + +bluetooth_init() { + # Get MAC address from the device tree. Use a default value if it has not been set. + BT_MACADDR="$(hexdump -ve '1/1 "%02X" ":"' /proc/device-tree/bluetooth/mac-address 2>/dev/null | sed 's/:$//g')" + if [ -z "${BT_MACADDR}" ] || [ "${BT_MACADDR}" = "00:00:00:00:00:00" ]; then + BT_MACADDR="00:04:F3:FF:FF:BB" + fi + + # Start the Bluetooth driver and bring up the interface + HCIATTACH_LOG="/var/log/hciattach.log" + + for RETRY in $(seq 1 5) + do + killproc hciattach + modprobe btdigi + if hciattach ttyBt qca ${BT_RATE:-3000000} -t30 ${BT_FLOW:-flow} unused ${BT_MACADDR} >${HCIATTACH_LOG} 2>&1; then + return + fi + rmmod btdigi + sleep 1 + done + BT_ERROR="FAIL (hciattach)" +} + +# Source function library +. /etc/init.d/functions + +case "$1" in + start) + if [ -d "/proc/device-tree/bluetooth" ]; then + if [ "$(tr -d '\0' 2>/dev/null Date: Thu, 9 Jan 2020 12:47:10 +0100 Subject: [PATCH 044/120] bluez5: unify config file for all platforms Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/ccimx6qpsbc.conf | 3 +++ meta-digi-arm/conf/machine/ccimx6sbc.conf | 3 +++ meta-digi-arm/conf/machine/include/ccimx6ul.inc | 3 +++ meta-digi-arm/conf/machine/include/ccimx8mn.inc | 3 +++ meta-digi-arm/conf/machine/include/ccimx8x.inc | 3 +++ .../bluez/bluez5-5.50/ccimx8x/main.conf | 12 ------------ .../bluez/bluez5/ccimx6qpsbc/main.conf | 12 ------------ .../bluez/bluez5/ccimx6sbc/main.conf | 2 +- .../bluez/bluez5/ccimx6ul/main.conf | 12 ------------ .../bluez/{bluez5-5.50/ccimx8mn => bluez5}/main.conf | 2 +- .../recipes-connectivity/bluez/bluez5_5.41.bbappend | 2 ++ .../recipes-connectivity/bluez/bluez5_5.50.bbappend | 2 ++ 12 files changed, 21 insertions(+), 38 deletions(-) delete mode 100644 meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8x/main.conf delete mode 100644 meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6qpsbc/main.conf delete mode 100644 meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6ul/main.conf rename meta-digi-dey/recipes-connectivity/bluez/{bluez5-5.50/ccimx8mn => bluez5}/main.conf (91%) diff --git a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf index 9696a2445..e78ba5f7f 100644 --- a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf @@ -37,6 +37,9 @@ KERNEL_DEVICETREE ?= " \ SERIAL_CONSOLES ?= "115200;ttymxc3" +# Bluetooth interface +BT_DEVICE_NAME ?= "cc6qp" + # Bluetooth tty BT_TTY ?= "ttymxc1" diff --git a/meta-digi-arm/conf/machine/ccimx6sbc.conf b/meta-digi-arm/conf/machine/ccimx6sbc.conf index afb4d2515..bd8423913 100644 --- a/meta-digi-arm/conf/machine/ccimx6sbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6sbc.conf @@ -38,6 +38,9 @@ KERNEL_DEVICETREE ?= " \ SERIAL_CONSOLES ?= "115200;ttymxc3" +# Bluetooth interface +BT_DEVICE_NAME ?= "cc6" + # Bluetooth tty BT_TTY ?= "ttymxc1" diff --git a/meta-digi-arm/conf/machine/include/ccimx6ul.inc b/meta-digi-arm/conf/machine/include/ccimx6ul.inc index c848046f5..78a6cb40d 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6ul.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6ul.inc @@ -12,6 +12,9 @@ include conf/machine/include/tune-cortexa7.inc UBOOT_PREFIX = "u-boot" UBOOT_SUFFIX = "imx" +# Bluetooth interface +BT_DEVICE_NAME ?= "cc6ul" + # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc index 617add729..1e768b50a 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8mn.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -22,6 +22,9 @@ SDIMG_BOOTLOADER = "${DEPLOY_DIR_IMAGE}/${BOOTABLE_FILENAME}" # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" +# Bluetooth interface +BT_DEVICE_NAME ?= "cc8mn" + # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index ea765ec12..323f3cfe8 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -29,6 +29,9 @@ RAM_CONFIGS = "1.2GHz_512MB_16bit 1.2GHz_1GB_16bit 1.2GHz_1GB_32bit 1.2GHz_2GB_3 # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8x_defconfig" +# Bluetooth interface +BT_DEVICE_NAME ?= "cc8x" + # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8x/main.conf b/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8x/main.conf deleted file mode 100644 index 1fae07f0e..000000000 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8x/main.conf +++ /dev/null @@ -1,12 +0,0 @@ -[General] - -# Default adapter name -# Defaults to 'BlueZ X.YZ' -Name = cc8x - -[Policy] - -# AutoEnable defines option to enable all controllers when they are found. -# This includes adapters present on start as well as adapters that are plugged -# in later on. Defaults to 'false'. -AutoEnable=true diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6qpsbc/main.conf b/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6qpsbc/main.conf deleted file mode 100644 index 332d38fad..000000000 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6qpsbc/main.conf +++ /dev/null @@ -1,12 +0,0 @@ -[General] - -# Default adapter name -# Defaults to 'BlueZ X.YZ' -Name = cc6qp - -[Policy] - -# AutoEnable defines option to enable all controllers when they are found. -# This includes adapters present on start as well as adapters that are plugged -# in later on. Defaults to 'false'. -AutoEnable=true diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6sbc/main.conf b/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6sbc/main.conf index c0908f0b2..69561c2c8 100644 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6sbc/main.conf +++ b/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6sbc/main.conf @@ -2,7 +2,7 @@ # Default adapter name # Defaults to 'BlueZ X.YZ' -Name = cc6 +Name = ##BT_DEVICE_NAME## #[Policy] diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6ul/main.conf b/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6ul/main.conf deleted file mode 100644 index e3c0cacbc..000000000 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5/ccimx6ul/main.conf +++ /dev/null @@ -1,12 +0,0 @@ -[General] - -# Default adapter name -# Defaults to 'BlueZ X.YZ' -Name = cc6ul - -[Policy] - -# AutoEnable defines option to enable all controllers when they are found. -# This includes adapters present on start as well as adapters that are plugged -# in later on. Defaults to 'false'. -AutoEnable=true diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/main.conf b/meta-digi-dey/recipes-connectivity/bluez/bluez5/main.conf similarity index 91% rename from meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/main.conf rename to meta-digi-dey/recipes-connectivity/bluez/bluez5/main.conf index 6420f4b8b..404154322 100644 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5-5.50/ccimx8mn/main.conf +++ b/meta-digi-dey/recipes-connectivity/bluez/bluez5/main.conf @@ -2,7 +2,7 @@ # Default adapter name # Defaults to 'BlueZ X.YZ' -Name = cc8mn +Name = ##BT_DEVICE_NAME## [Policy] diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.41.bbappend b/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.41.bbappend index f85360423..d188cd039 100644 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.41.bbappend +++ b/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.41.bbappend @@ -40,6 +40,8 @@ do_install_append() { install -d ${D}${systemd_unitdir}/system/ install -m 0644 ${WORKDIR}/bluetooth-init.service ${D}${systemd_unitdir}/system/bluetooth-init.service install -m 0644 ${WORKDIR}/main.conf ${D}${sysconfdir}/bluetooth/ + sed -i -e "s,##BT_DEVICE_NAME##,${BT_DEVICE_NAME},g" \ + ${D}${sysconfdir}/bluetooth/main.conf if [ -n "${@bb.utils.contains('PACKAGECONFIG', 'experimental', 'experimental', '', d)}" ]; then sed -i '/^SSD_OPTIONS/a SSD_OPTIONS="${SSD_OPTIONS} --experimental"' ${D}${INIT_D_DIR}/bluetooth fi diff --git a/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.50.bbappend b/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.50.bbappend index 0d8bbb09b..64f5d498f 100644 --- a/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.50.bbappend +++ b/meta-digi-dey/recipes-connectivity/bluez/bluez5_5.50.bbappend @@ -33,6 +33,8 @@ do_install_append() { install -d ${D}${systemd_unitdir}/system/ install -m 0644 ${WORKDIR}/bluetooth-init.service ${D}${systemd_unitdir}/system/bluetooth-init.service install -m 0644 ${WORKDIR}/main.conf ${D}${sysconfdir}/bluetooth/ + sed -i -e "s,##BT_DEVICE_NAME##,${BT_DEVICE_NAME},g" \ + ${D}${sysconfdir}/bluetooth/main.conf # Staging bluetooth internal headers and libs to allow other recipes # to link against them From 88706035c0bef59675164e0d402e6fc5068a08b4 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:45:57 +0200 Subject: [PATCH 045/120] firmware-qualcomm: add support to ccimx8mn platform Add initial support cloned from ccimx6ul (QCA6564). https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../firmware-qualcomm/firmware-qualcomm.bb | 4 ++-- .../firmware-qualcomm/ccimx8mn/bdwlan30_US.bin | Bin 0 -> 8124 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8mn/bdwlan30_US.bin diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 73101f768..81a850754 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2018 Digi International. +# Copyright (C) 2016-2020 Digi International. SUMMARY = "Qualcomm firmware files for Digi's platforms." SECTION = "base" @@ -92,4 +92,4 @@ FILES_${PN}-${QCA_MODEL}-bt = "/lib/firmware/qca" FILES_${PN}-${QCA_MODEL}-wifi = "/lib/firmware" PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8mn/bdwlan30_US.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8mn/bdwlan30_US.bin new file mode 100644 index 0000000000000000000000000000000000000000..e923f41b675424bf1472a4f4e58d5f73d48d8108 GIT binary patch literal 8124 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 EZxr%@b^rhX literal 0 HcmV?d00001 From e262caa33892eb61b23725cfa6d0f0c624f8b02b Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:47:38 +0200 Subject: [PATCH 046/120] swu-images: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../files/ccimx8mn/preinstall_swu.sh | 83 +++++++++++++++++++ .../swu-images/files/ccimx8mn/sw-description | 20 +++++ meta-digi-dey/recipes-digi/swu-images/swu.inc | 4 +- 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh create mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh new file mode 100644 index 000000000..ddd61b789 --- /dev/null +++ b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh @@ -0,0 +1,83 @@ +#!/bin/sh +#=============================================================================== +# +# preinstall_swu.sh +# +# Copyright (C) 2018 by Digi International Inc. +# All rights reserved. +# +# 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. +# +# !Description: SWUpdate pre-install script to open the virtual mapped device +# +# SWUpdate calls this script before installing the image. +# +#=============================================================================== + +# Functions. +#------------------------------------------------------------------------------ +# Function - psplash_message +# +# Shows the given message in the psplash screen. +# +# @param ${1} - Message to show. +#------------------------------------------------------------------------------ +psplash_message() { + echo "MSG ${1}" > /tmp/psplash_fifo + sleep 0.2 +} + +#------------------------------------------------------------------------------ +# Function - psplash_progress +# +# Sets the psplash progress bar percentage to the given one. +# +# @param ${1} - Progress percentage. +#------------------------------------------------------------------------------ +psplash_progress() { + echo "PROGRESS ${1}" > /tmp/psplash_fifo + sleep 0.2 +} + +#------------------------------------------------------------------------------ +# Function - log +# +# Prints the given text in the console. +# +# @param ${1} - Text to print. +#------------------------------------------------------------------------------ +log() { + echo "[FW UPDATE] ${1}" +} + +#------------------------------------------------------------------------------ +# Function - log_error +# +# Prints the given text in the console as an error. +# +# @param ${1} - Error text to print. +#------------------------------------------------------------------------------ +log_error() { + log "[ERROR] ${1}" + psplash_message "ERROR: ${1}" + psplash_progress "0" +} + +# Main +#------------------------------------------------------------------------------ +# Check if encrypted device is already open. +if [ -b /dev/mapper/cryptroot ]; then + exit 0 +fi + +rootfs_block="/dev/mmcblk0p$(fdisk -l /dev/mmcblk0 | sed -ne "s,^[^0-9]*\([0-9]\+\).*\.*,\1,g;T;p")" + +# Open LUKS encrypted device +trustfence-tool ${rootfs_block} cryptroot +if [ "$?" != "0" ]; then + log_error "Error executing the firmware update, cannot open virtual device" + exit 1 +fi + diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description new file mode 100644 index 000000000..cde521bf2 --- /dev/null +++ b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description @@ -0,0 +1,20 @@ +software = +{ + version = "##SW_VERSION##"; + + images: ( + { + filename = "##BOOTIMG_NAME##"; + device = "##BOOT_DEV##"; + type = "raw"; + sha256 = "@##BOOTIMG_NAME##"; + }, + { + filename = "##ROOTIMG_NAME##"; + device = "##ROOTFS_DEV##"; + type = "raw"; + sha256 = "@##ROOTIMG_NAME##"; + } + ); + ##PREINSTALL_SCRIPT## +} diff --git a/meta-digi-dey/recipes-digi/swu-images/swu.inc b/meta-digi-dey/recipes-digi/swu-images/swu.inc index 391bc4685..48bd622d1 100644 --- a/meta-digi-dey/recipes-digi/swu-images/swu.inc +++ b/meta-digi-dey/recipes-digi/swu-images/swu.inc @@ -1,4 +1,4 @@ -# Copyright (C) 2016, 2017 Digi International Inc. +# Copyright (C) 2016-2020 Digi International Inc. SUMMARY = "Generate update package for SWUpdate" SECTION = "base" LICENSE = "GPL-2.0" @@ -8,6 +8,7 @@ SRC_URI = "file://sw-description" SRC_URI_append_ccimx6 = " ${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), 'file://preinstall_swu.sh', '')}" SRC_URI_append_ccimx6ul = " ${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), '', 'file://preinstall_swu.sh')}" SRC_URI_append_ccimx8x = " ${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), 'file://preinstall_swu.sh', '')}" +SRC_URI_append_ccimx8m = " ${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), 'file://preinstall_swu.sh', '')}" inherit swupdate @@ -36,6 +37,7 @@ PREINST_SCRIPT_DESC = "" PREINST_SCRIPT_DESC_ccimx6 = "${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), '${PREINST_SCRIPT_TEMPLATE}', '')}" PREINST_SCRIPT_DESC_ccimx6ul = "${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), '', '${PREINST_SCRIPT_TEMPLATE}')}" PREINST_SCRIPT_DESC_ccimx8x = "${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), '${PREINST_SCRIPT_TEMPLATE}', '')}" +PREINST_SCRIPT_DESC_ccimx8m = "${@oe.utils.ifelse(d.getVar('TRUSTFENCE_INITRAMFS_IMAGE', True), '${PREINST_SCRIPT_TEMPLATE}', '')}" python () { img_fstypes = d.getVar('BOOTFS_EXT', True) + " " + d.getVar('ROOTFS_EXT', True) From d2cecd68efb223cd42a76fccbcec9b294b3fedf3 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 12:58:35 +0100 Subject: [PATCH 047/120] swu-images: unify script files for the different platforms Signed-off-by: Arturo Buzarra --- .../swu-images/files/ccimx6/preinstall_swu.sh | 83 ------------------- .../swu-images/files/ccimx8mn/sw-description | 20 ----- .../files/ccimx8x/preinstall_swu.sh | 83 ------------------- .../swu-images/files/ccimx8x/sw-description | 20 ----- .../files/{ccimx8mn => }/preinstall_swu.sh | 0 .../files/{ccimx6 => }/sw-description | 0 6 files changed, 206 deletions(-) delete mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx6/preinstall_swu.sh delete mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description delete mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/preinstall_swu.sh delete mode 100644 meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/sw-description rename meta-digi-dey/recipes-digi/swu-images/files/{ccimx8mn => }/preinstall_swu.sh (100%) rename meta-digi-dey/recipes-digi/swu-images/files/{ccimx6 => }/sw-description (100%) diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx6/preinstall_swu.sh b/meta-digi-dey/recipes-digi/swu-images/files/ccimx6/preinstall_swu.sh deleted file mode 100644 index 8723cfc11..000000000 --- a/meta-digi-dey/recipes-digi/swu-images/files/ccimx6/preinstall_swu.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh -#=============================================================================== -# -# preinstall_swu.sh -# -# Copyright (C) 2017 by Digi International Inc. -# All rights reserved. -# -# 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. -# -# !Description: SWUpdate pre-install script to open the virtual mapped device -# -# SWUpdate calls this script before installing the image. -# -#=============================================================================== - -# Functions. -#------------------------------------------------------------------------------ -# Function - psplash_message -# -# Shows the given message in the psplash screen. -# -# @param ${1} - Message to show. -#------------------------------------------------------------------------------ -psplash_message() { - echo "MSG ${1}" > /tmp/psplash_fifo - sleep 0.2 -} - -#------------------------------------------------------------------------------ -# Function - psplash_progress -# -# Sets the psplash progress bar percentage to the given one. -# -# @param ${1} - Progress percentage. -#------------------------------------------------------------------------------ -psplash_progress() { - echo "PROGRESS ${1}" > /tmp/psplash_fifo - sleep 0.2 -} - -#------------------------------------------------------------------------------ -# Function - log -# -# Prints the given text in the console. -# -# @param ${1} - Text to print. -#------------------------------------------------------------------------------ -log() { - echo "[FW UPDATE] ${1}" -} - -#------------------------------------------------------------------------------ -# Function - log_error -# -# Prints the given text in the console as an error. -# -# @param ${1} - Error text to print. -#------------------------------------------------------------------------------ -log_error() { - log "[ERROR] ${1}" - psplash_message "ERROR: ${1}" - psplash_progress "0" -} - -# Main -#------------------------------------------------------------------------------ -# Check if encrypted device is already open. -if [ -b /dev/mapper/cryptroot ]; then - exit 0 -fi - -rootfs_block="/dev/mmcblk0p$(fdisk -l /dev/mmcblk0 | sed -ne "s,^[^0-9]*\([0-9]\+\).*\.*,\1,g;T;p")" - -# Open LUKS encrypted device -trustfence-tool ${rootfs_block} cryptroot -if [ "$?" != "0" ]; then - log_error "Error executing the firmware update, cannot open virtual device" - exit 1 -fi - diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description deleted file mode 100644 index cde521bf2..000000000 --- a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/sw-description +++ /dev/null @@ -1,20 +0,0 @@ -software = -{ - version = "##SW_VERSION##"; - - images: ( - { - filename = "##BOOTIMG_NAME##"; - device = "##BOOT_DEV##"; - type = "raw"; - sha256 = "@##BOOTIMG_NAME##"; - }, - { - filename = "##ROOTIMG_NAME##"; - device = "##ROOTFS_DEV##"; - type = "raw"; - sha256 = "@##ROOTIMG_NAME##"; - } - ); - ##PREINSTALL_SCRIPT## -} diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/preinstall_swu.sh b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/preinstall_swu.sh deleted file mode 100644 index ddd61b789..000000000 --- a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/preinstall_swu.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh -#=============================================================================== -# -# preinstall_swu.sh -# -# Copyright (C) 2018 by Digi International Inc. -# All rights reserved. -# -# 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. -# -# !Description: SWUpdate pre-install script to open the virtual mapped device -# -# SWUpdate calls this script before installing the image. -# -#=============================================================================== - -# Functions. -#------------------------------------------------------------------------------ -# Function - psplash_message -# -# Shows the given message in the psplash screen. -# -# @param ${1} - Message to show. -#------------------------------------------------------------------------------ -psplash_message() { - echo "MSG ${1}" > /tmp/psplash_fifo - sleep 0.2 -} - -#------------------------------------------------------------------------------ -# Function - psplash_progress -# -# Sets the psplash progress bar percentage to the given one. -# -# @param ${1} - Progress percentage. -#------------------------------------------------------------------------------ -psplash_progress() { - echo "PROGRESS ${1}" > /tmp/psplash_fifo - sleep 0.2 -} - -#------------------------------------------------------------------------------ -# Function - log -# -# Prints the given text in the console. -# -# @param ${1} - Text to print. -#------------------------------------------------------------------------------ -log() { - echo "[FW UPDATE] ${1}" -} - -#------------------------------------------------------------------------------ -# Function - log_error -# -# Prints the given text in the console as an error. -# -# @param ${1} - Error text to print. -#------------------------------------------------------------------------------ -log_error() { - log "[ERROR] ${1}" - psplash_message "ERROR: ${1}" - psplash_progress "0" -} - -# Main -#------------------------------------------------------------------------------ -# Check if encrypted device is already open. -if [ -b /dev/mapper/cryptroot ]; then - exit 0 -fi - -rootfs_block="/dev/mmcblk0p$(fdisk -l /dev/mmcblk0 | sed -ne "s,^[^0-9]*\([0-9]\+\).*\.*,\1,g;T;p")" - -# Open LUKS encrypted device -trustfence-tool ${rootfs_block} cryptroot -if [ "$?" != "0" ]; then - log_error "Error executing the firmware update, cannot open virtual device" - exit 1 -fi - diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/sw-description b/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/sw-description deleted file mode 100644 index cde521bf2..000000000 --- a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8x/sw-description +++ /dev/null @@ -1,20 +0,0 @@ -software = -{ - version = "##SW_VERSION##"; - - images: ( - { - filename = "##BOOTIMG_NAME##"; - device = "##BOOT_DEV##"; - type = "raw"; - sha256 = "@##BOOTIMG_NAME##"; - }, - { - filename = "##ROOTIMG_NAME##"; - device = "##ROOTFS_DEV##"; - type = "raw"; - sha256 = "@##ROOTIMG_NAME##"; - } - ); - ##PREINSTALL_SCRIPT## -} diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh b/meta-digi-dey/recipes-digi/swu-images/files/preinstall_swu.sh similarity index 100% rename from meta-digi-dey/recipes-digi/swu-images/files/ccimx8mn/preinstall_swu.sh rename to meta-digi-dey/recipes-digi/swu-images/files/preinstall_swu.sh diff --git a/meta-digi-dey/recipes-digi/swu-images/files/ccimx6/sw-description b/meta-digi-dey/recipes-digi/swu-images/files/sw-description similarity index 100% rename from meta-digi-dey/recipes-digi/swu-images/files/ccimx6/sw-description rename to meta-digi-dey/recipes-digi/swu-images/files/sw-description From 8cc2e3f7f6d81826474cef2ad472d91f26b03a7e Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:48:54 +0200 Subject: [PATCH 048/120] qtbase: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- meta-digi-dey/recipes-qt/qt5/qtbase/ccimx8mn/qt5.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 meta-digi-dey/recipes-qt/qt5/qtbase/ccimx8mn/qt5.sh diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase/ccimx8mn/qt5.sh b/meta-digi-dey/recipes-qt/qt5/qtbase/ccimx8mn/qt5.sh new file mode 100644 index 000000000..16c8e26d7 --- /dev/null +++ b/meta-digi-dey/recipes-qt/qt5/qtbase/ccimx8mn/qt5.sh @@ -0,0 +1,9 @@ +#!/bin/sh +export QT_QPA_PLATFORM="wayland" + +[ -f "/etc/profile.d/weston.sh" ] && return + +export QT_QPA_PLATFORM="xcb" + +# Use EGLFS platform plugin for images without XWayland and X11 +[ -f "/etc/xserver-nodm/Xserver" ] || export QT_QPA_PLATFORM="eglfs" From fce4f44e68ae1cd8d969e00114a5e77cd5968fcc Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 18 Oct 2019 09:53:10 +0200 Subject: [PATCH 049/120] kernel-module-qualcomm: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6806 Signed-off-by: Arturo Buzarra --- .../kernel-module-qualcomm/kernel-module-qualcomm.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index e8d568787..db2f73598 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 Digi International. +# Copyright (C) 2016-2020 Digi International. SUMMARY = "Qualcomm's wireless driver for qca65xx" DESCRIPTION = "qcacld-2.0 module" @@ -84,4 +84,4 @@ FILES_${PN} += " \ ${base_libdir}/firmware/wlan/qcom_cfg.ini \ " -COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x|ccimx8m)" From dd723df5763da4bff547a1278d14d4b8b3df0fba Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 10:38:29 +0100 Subject: [PATCH 050/120] hostapd: add support for the ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../recipes-connectivity/hostapd/hostapd_%.bbappend | 8 +++++++- .../packagegroups/packagegroup-dey-wireless.bb | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend b/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend index 30f44dfea..664d135ef 100644 --- a/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 Digi International. +# Copyright (C) 2016-2020 Digi International. FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" @@ -9,6 +9,7 @@ SRC_URI_append = " \ SRC_URI_append_ccimx6ul = " file://hostapd_wlan1.conf" SRC_URI_append_ccimx6qpsbc = " file://hostapd_wlan1.conf" SRC_URI_append_ccimx8x = " file://hostapd_wlan1.conf" +SRC_URI_append_ccimx8mn = " file://hostapd_wlan1.conf" SYSTEMD_SERVICE_${PN}_append = " hostapd@.service" @@ -37,6 +38,11 @@ do_install_append_ccimx8x() { install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} } +do_install_append_ccimx8mn() { + # Install custom hostapd_IFACE.conf file + install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} +} + pkg_postinst_ontarget_${PN}() { # Exit if there is no wireless hardware available if [ ! -e /proc/device-tree/wireless/mac-address ]; then diff --git a/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb b/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb index d4e779518..9676323a1 100644 --- a/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb +++ b/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb @@ -1,5 +1,5 @@ # -# Copyright (C) 2012-2019 Digi International. +# Copyright (C) 2012-2020 Digi International. # SUMMARY = "Wireless packagegroup for DEY image" @@ -17,3 +17,4 @@ RDEPENDS_${PN} = "\ RDEPENDS_${PN}_append_ccimx6ul = " hostapd" RDEPENDS_${PN}_append_ccimx6qpsbc = " hostapd" RDEPENDS_${PN}_append_ccimx8x = " hostapd" +RDEPENDS_${PN}_append_ccimx8mn = " hostapd" From 6d23ee1fe710c4095346874d152c2d405234f429 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 14:20:26 +0100 Subject: [PATCH 051/120] hostapd: generalize recipe to reduce the overhead when adding a new platform Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/ccimx6qpsbc.conf | 1 + meta-digi-arm/conf/machine/ccimx6sbc.conf | 2 ++ .../conf/machine/include/ccimx6ul.inc | 1 + .../conf/machine/include/ccimx8mn.inc | 1 + .../conf/machine/include/ccimx8x.inc | 1 + .../hostapd/hostapd_%.bbappend | 28 ++++--------------- .../packagegroup-dey-wireless.bb | 6 ++-- 7 files changed, 13 insertions(+), 27 deletions(-) diff --git a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf index e78ba5f7f..e49bc3ff9 100644 --- a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf @@ -7,6 +7,7 @@ include conf/machine/include/ccimx6.inc # Wireless external module WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" +HAS_WIFI_VIRTWLANS = "true" # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" diff --git a/meta-digi-arm/conf/machine/ccimx6sbc.conf b/meta-digi-arm/conf/machine/ccimx6sbc.conf index bd8423913..66237eac9 100644 --- a/meta-digi-arm/conf/machine/ccimx6sbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6sbc.conf @@ -5,6 +5,8 @@ # Contains the ConnectCore 6 module. include conf/machine/include/ccimx6.inc +HAS_WIFI_VIRTWLANS = "false" + # Wireless p2p interface WLAN_P2P_DEVICE_NAME ?= "ccimx6-p2p" diff --git a/meta-digi-arm/conf/machine/include/ccimx6ul.inc b/meta-digi-arm/conf/machine/include/ccimx6ul.inc index 78a6cb40d..5465cebfc 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6ul.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6ul.inc @@ -18,6 +18,7 @@ BT_DEVICE_NAME ?= "cc6ul" # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" +HAS_WIFI_VIRTWLANS = "true" # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc index 1e768b50a..32905e6e1 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8mn.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -28,6 +28,7 @@ BT_DEVICE_NAME ?= "cc8mn" # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" +HAS_WIFI_VIRTWLANS = "true" # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index 323f3cfe8..e1f2c67e1 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -35,6 +35,7 @@ BT_DEVICE_NAME ?= "cc8x" # Wireless external module WIRELESS_MODULE ?= "" WIRELESS_MODULE_append = " ${@oe.utils.conditional('HAVE_WIFI', '1', 'kernel-module-qualcomm', '', d)}" +HAS_WIFI_VIRTWLANS = "true" # Wireless p2p interface WLAN_P2P_INTERFACE ?= "p2p0" diff --git a/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend b/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend index 664d135ef..00b57b508 100644 --- a/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/hostapd/hostapd_%.bbappend @@ -5,11 +5,8 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI_append = " \ file://hostapd_wlan0.conf \ file://hostapd@.service \ + ${@oe.utils.conditional('HAS_WIFI_VIRTWLANS', 'true', 'file://hostapd_wlan1.conf', '', d)} \ " -SRC_URI_append_ccimx6ul = " file://hostapd_wlan1.conf" -SRC_URI_append_ccimx6qpsbc = " file://hostapd_wlan1.conf" -SRC_URI_append_ccimx8x = " file://hostapd_wlan1.conf" -SRC_URI_append_ccimx8mn = " file://hostapd_wlan1.conf" SYSTEMD_SERVICE_${PN}_append = " hostapd@.service" @@ -21,26 +18,11 @@ do_install_append() { # Install interface-specific systemd service install -m 0644 ${WORKDIR}/hostapd@.service ${D}${systemd_unitdir}/system/ sed -i -e 's,@SBINDIR@,${sbindir},g' -e 's,@SYSCONFDIR@,${sysconfdir},g' ${D}${systemd_unitdir}/system/hostapd@.service -} -do_install_append_ccimx6ul() { - # Install custom hostapd_IFACE.conf file - install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} -} - -do_install_append_ccimx6qpsbc() { - # Install custom hostapd_IFACE.conf file - install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} -} - -do_install_append_ccimx8x() { - # Install custom hostapd_IFACE.conf file - install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} -} - -do_install_append_ccimx8mn() { - # Install custom hostapd_IFACE.conf file - install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} + if ${HAS_WIFI_VIRTWLANS}; then + # Install custom hostapd_IFACE.conf file + install -m 0644 ${WORKDIR}/hostapd_wlan1.conf ${D}${sysconfdir} + fi } pkg_postinst_ontarget_${PN}() { diff --git a/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb b/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb index 9676323a1..369d627c4 100644 --- a/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb +++ b/meta-digi-dey/recipes-connectivity/packagegroups/packagegroup-dey-wireless.bb @@ -8,13 +8,11 @@ inherit packagegroup RDEPENDS_${PN} = "\ crda \ + hostapd \ iw \ wpa-supplicant \ wpa-supplicant-cli \ wpa-supplicant-passphrase \ " -RDEPENDS_${PN}_append_ccimx6ul = " hostapd" -RDEPENDS_${PN}_append_ccimx6qpsbc = " hostapd" -RDEPENDS_${PN}_append_ccimx8x = " hostapd" -RDEPENDS_${PN}_append_ccimx8mn = " hostapd" +RDEPENDS_${PN}_remove_ccimx6sbc = "hostapd" From 12a6db421ca45f28e11838091bec3ea6ea48e59c Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 10:46:28 +0100 Subject: [PATCH 052/120] alsa-state: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../alsa-state/alsa-state.bbappend | 4 +- .../alsa-state/ccimx8mn/asound.conf | 9 + .../alsa-state/ccimx8mn/asound.state | 1148 +++++++++++++++++ 3 files changed, 1159 insertions(+), 2 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.conf create mode 100644 meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.state diff --git a/meta-digi-arm/recipes-bsp/alsa-state/alsa-state.bbappend b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state.bbappend index 591606f34..695f9fd07 100644 --- a/meta-digi-arm/recipes-bsp/alsa-state/alsa-state.bbappend +++ b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state.bbappend @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2018 Digi International. +# Copyright (C) 2013-2020 Digi International. FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" @@ -11,8 +11,8 @@ SRC_URI_append_ccimx6 = " \ " SRC_URI_append_ccimx6ul = " file://asound.state" - SRC_URI_append_ccimx8x = " file://asound.state" +SRC_URI_append_ccimx8m = " file://asound.state" do_install_append_ccimx6() { ln -sf asound.micro_play.state ${D}${localstatedir}/lib/alsa/asound.state diff --git a/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.conf b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.conf new file mode 100644 index 000000000..11c4cbba0 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.conf @@ -0,0 +1,9 @@ +pcm.imxmax98088 { + type hw + card 0 +} +ctl.imxmax98088 { + type hw + card 0 +} +ctl.!default imxmax98088 diff --git a/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.state b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.state new file mode 100644 index 000000000..07076e3ac --- /dev/null +++ b/meta-digi-arm/recipes-bsp/alsa-state/alsa-state/ccimx8mn/asound.state @@ -0,0 +1,1148 @@ +state.imxmax98088 { + control.1 { + iface MIXER + name 'Headphone Volume' + value.0 18 + value.1 18 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 31' + dbmin -6700 + dbmax 300 + dbvalue.0 -1100 + dbvalue.1 -1100 + } + } + control.2 { + iface MIXER + name 'Speaker Volume' + value.0 16 + value.1 16 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 31' + dbmin -6200 + dbmax 800 + dbvalue.0 -1000 + dbvalue.1 -1000 + } + } + control.3 { + iface MIXER + name 'Receiver Volume' + value.0 16 + value.1 16 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 31' + dbmin -6200 + dbmax 800 + dbvalue.0 -1000 + dbvalue.1 -1000 + } + } + control.4 { + iface MIXER + name 'Headphone Switch' + value.0 true + value.1 true + comment { + access 'read write' + type BOOLEAN + count 2 + } + } + control.5 { + iface MIXER + name 'Speaker Switch' + value.0 true + value.1 true + comment { + access 'read write' + type BOOLEAN + count 2 + } + } + control.6 { + iface MIXER + name 'Receiver Switch' + value.0 true + value.1 true + comment { + access 'read write' + type BOOLEAN + count 2 + } + } + control.7 { + iface MIXER + name 'MIC1 Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 31' + } + } + control.8 { + iface MIXER + name 'MIC2 Volume' + value 15 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 31' + } + } + control.9 { + iface MIXER + name 'MIC1 Boost Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 2' + dbmin 0 + dbmax 3000 + dbvalue.0 0 + } + } + control.10 { + iface MIXER + name 'MIC2 Boost Volume' + value 1 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 2' + dbmin 0 + dbmax 3000 + dbvalue.0 2000 + } + } + control.11 { + iface MIXER + name 'INA Volume' + value 4 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.12 { + iface MIXER + name 'INB Volume' + value 4 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.13 { + iface MIXER + name 'ADCL Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.14 { + iface MIXER + name 'ADCR Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.15 { + iface MIXER + name 'ADCL Boost Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 3' + } + } + control.16 { + iface MIXER + name 'ADCR Boost Volume' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 3' + } + } + control.17 { + iface MIXER + name 'EQ1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.18 { + iface MIXER + name 'EQ2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.19 { + iface MIXER + name 'EX Limiter Mode' + value Off + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Off + item.1 '100Hz' + item.2 '400Hz' + item.3 '600Hz' + item.4 '800Hz' + item.5 '1000Hz' + item.6 '200-400Hz' + item.7 '400-600Hz' + item.8 '400-800Hz' + } + } + control.20 { + iface MIXER + name 'EX Limiter Threshold' + value '0.6' + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 '0.6' + item.1 '1.2' + item.2 '1.8' + item.3 '2.4' + item.4 '3.0' + item.5 '3.6' + item.6 '4.2' + item.7 '4.8' + } + } + control.21 { + iface MIXER + name 'DAI1 Filter Mode' + value Music + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Voice + item.1 Music + } + } + control.22 { + iface MIXER + name 'DAI1 DAC Filter' + value Off + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Off + item.1 'fc=258/fs=16k' + item.2 'fc=500/fs=16k' + item.3 'fc=258/fs=8k' + item.4 'fc=500/fs=8k' + item.5 'fc=200' + } + } + control.23 { + iface MIXER + name 'DAI1 ADC Filter' + value Off + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Off + item.1 'fc=258/fs=16k' + item.2 'fc=500/fs=16k' + item.3 'fc=258/fs=8k' + item.4 'fc=500/fs=8k' + item.5 'fc=200' + } + } + control.24 { + iface MIXER + name 'DAI2 DC Block Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.25 { + iface MIXER + name 'ALC Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.26 { + iface MIXER + name 'ALC Threshold' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.27 { + iface MIXER + name 'ALC Multiband' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.28 { + iface MIXER + name 'ALC Release Time' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.29 { + iface MIXER + name 'PWR Limiter Threshold' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.30 { + iface MIXER + name 'PWR Limiter Weight' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.31 { + iface MIXER + name 'PWR Limiter Time1' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.32 { + iface MIXER + name 'PWR Limiter Time2' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.33 { + iface MIXER + name 'THD Limiter Threshold' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 15' + } + } + control.34 { + iface MIXER + name 'THD Limiter Time' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.35 { + iface MIXER + name 'REC Output Mode' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.36 { + iface MIXER + name 'Right ADC Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.37 { + iface MIXER + name 'Right ADC Mixer MIC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.38 { + iface MIXER + name 'Right ADC Mixer INA1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.39 { + iface MIXER + name 'Right ADC Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.40 { + iface MIXER + name 'Right ADC Mixer INB1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.41 { + iface MIXER + name 'Right ADC Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.42 { + iface MIXER + name 'Left ADC Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.43 { + iface MIXER + name 'Left ADC Mixer MIC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.44 { + iface MIXER + name 'Left ADC Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.45 { + iface MIXER + name 'Left ADC Mixer INA2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.46 { + iface MIXER + name 'Left ADC Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.47 { + iface MIXER + name 'Left ADC Mixer INB2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.48 { + iface MIXER + name 'Right REC Mixer Left DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.49 { + iface MIXER + name 'Right REC Mixer Right DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.50 { + iface MIXER + name 'Right REC Mixer Left DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.51 { + iface MIXER + name 'Right REC Mixer Right DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.52 { + iface MIXER + name 'Right REC Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.53 { + iface MIXER + name 'Right REC Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.54 { + iface MIXER + name 'Right REC Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.55 { + iface MIXER + name 'Right REC Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.56 { + iface MIXER + name 'Right REC Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.57 { + iface MIXER + name 'Right REC Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.58 { + iface MIXER + name 'Left REC Mixer Left DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.59 { + iface MIXER + name 'Left REC Mixer Right DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.60 { + iface MIXER + name 'Left REC Mixer Left DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.61 { + iface MIXER + name 'Left REC Mixer Right DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.62 { + iface MIXER + name 'Left REC Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.63 { + iface MIXER + name 'Left REC Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.64 { + iface MIXER + name 'Left REC Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.65 { + iface MIXER + name 'Left REC Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.66 { + iface MIXER + name 'Left REC Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.67 { + iface MIXER + name 'Left REC Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.68 { + iface MIXER + name 'Right SPK Mixer Left DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.69 { + iface MIXER + name 'Right SPK Mixer Right DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.70 { + iface MIXER + name 'Right SPK Mixer Left DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.71 { + iface MIXER + name 'Right SPK Mixer Right DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.72 { + iface MIXER + name 'Right SPK Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.73 { + iface MIXER + name 'Right SPK Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.74 { + iface MIXER + name 'Right SPK Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.75 { + iface MIXER + name 'Right SPK Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.76 { + iface MIXER + name 'Right SPK Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.77 { + iface MIXER + name 'Right SPK Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.78 { + iface MIXER + name 'Left SPK Mixer Left DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.79 { + iface MIXER + name 'Left SPK Mixer Right DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.80 { + iface MIXER + name 'Left SPK Mixer Left DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.81 { + iface MIXER + name 'Left SPK Mixer Right DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.82 { + iface MIXER + name 'Left SPK Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.83 { + iface MIXER + name 'Left SPK Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.84 { + iface MIXER + name 'Left SPK Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.85 { + iface MIXER + name 'Left SPK Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.86 { + iface MIXER + name 'Left SPK Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.87 { + iface MIXER + name 'Left SPK Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.88 { + iface MIXER + name 'Right HP Mixer Left DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.89 { + iface MIXER + name 'Right HP Mixer Right DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.90 { + iface MIXER + name 'Right HP Mixer Left DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.91 { + iface MIXER + name 'Right HP Mixer Right DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.92 { + iface MIXER + name 'Right HP Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.93 { + iface MIXER + name 'Right HP Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.94 { + iface MIXER + name 'Right HP Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.95 { + iface MIXER + name 'Right HP Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.96 { + iface MIXER + name 'Right HP Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.97 { + iface MIXER + name 'Right HP Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.98 { + iface MIXER + name 'Left HP Mixer Left DAC1 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.99 { + iface MIXER + name 'Left HP Mixer Right DAC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.100 { + iface MIXER + name 'Left HP Mixer Left DAC2 Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.101 { + iface MIXER + name 'Left HP Mixer Right DAC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.102 { + iface MIXER + name 'Left HP Mixer MIC1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.103 { + iface MIXER + name 'Left HP Mixer MIC2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.104 { + iface MIXER + name 'Left HP Mixer INA1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.105 { + iface MIXER + name 'Left HP Mixer INA2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.106 { + iface MIXER + name 'Left HP Mixer INB1 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.107 { + iface MIXER + name 'Left HP Mixer INB2 Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } +} From a93a05a8af7efb626aad9b09dccbed8251f34b57 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 10:49:01 +0100 Subject: [PATCH 053/120] init-ifupdown: add support for ccimx8x platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../init-ifupdown/init-ifupdown_1.0.bbappend | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend b/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend index d64563721..6a3fd7d0e 100644 --- a/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend +++ b/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2019 Digi International Inc. +# Copyright (C) 2013-2020 Digi International Inc. FILESEXTRAPATHS_prepend := "${THISDIR}/${BP}:" @@ -33,6 +33,12 @@ SRC_URI_append_ccimx8x = "\ file://virtwlans \ " +SRC_URI_append_ccimx8mn = "\ + file://interfaces.wlan1.static \ + file://interfaces.wlan1.dhcp \ + file://virtwlans \ +" + SYSTEMD_SERVICE_${PN} = "ifupdown.service" WPA_DRIVER ?= "nl80211" @@ -116,6 +122,11 @@ do_install_append_ccimx8x() { install_wlan1 } +do_install_append_ccimx8mn() { + install_virtwlans + install_wlan1 +} + # Disable wireless interfaces on first boot for non-wireless variants pkg_postinst_ontarget_${PN}() { if [ ! -d "/proc/device-tree/wireless" ]; then From 1fd0e8d6d88d5cd16c935e346b9cccbe9e80ba5c Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 16:48:33 +0100 Subject: [PATCH 054/120] init-ifupdown: generalize recipe to avoid redefinitions Signed-off-by: Arturo Buzarra --- .../init-ifupdown/init-ifupdown_1.0.bbappend | 57 +++++-------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend b/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend index 6a3fd7d0e..0a84fd155 100644 --- a/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend +++ b/meta-digi-dey/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend @@ -7,36 +7,19 @@ INITSCRIPT_PARAMS = "start 03 2 3 4 5 . stop 80 0 6 1 ." inherit systemd +WIFI_VIRTWLANS_FILES = " \ + file://interfaces.wlan1.static \ + file://interfaces.wlan1.dhcp \ + file://virtwlans \ +" + SRC_URI_append = " \ file://ifupdown.service \ file://interfaces.br0.example \ file://interfaces.p2p \ file://p2plink \ file://resolv \ -" - -SRC_URI_append_ccimx6qpsbc = "\ - file://interfaces.wlan1.static \ - file://interfaces.wlan1.dhcp \ - file://virtwlans \ -" - -SRC_URI_append_ccimx6ul = "\ - file://interfaces.wlan1.static \ - file://interfaces.wlan1.dhcp \ - file://virtwlans \ -" - -SRC_URI_append_ccimx8x = "\ - file://interfaces.wlan1.static \ - file://interfaces.wlan1.dhcp \ - file://virtwlans \ -" - -SRC_URI_append_ccimx8mn = "\ - file://interfaces.wlan1.static \ - file://interfaces.wlan1.dhcp \ - file://virtwlans \ + ${@oe.utils.conditional('HAS_WIFI_VIRTWLANS', 'true', '${WIFI_VIRTWLANS_FILES}', '', d)} \ " SYSTEMD_SERVICE_${PN} = "ifupdown.service" @@ -75,6 +58,12 @@ do_install_append() { sed -i -e "s,##WPA_DRIVER##,${WPA_DRIVER},g" ${D}${sysconfdir}/network/interfaces cat ${WORKDIR}/interfaces.br0.example >> ${D}${sysconfdir}/network/interfaces + + # Install virtual wlans files + if ${HAS_WIFI_VIRTWLANS}; then + install_virtwlans + install_wlan1 + fi } install_virtwlans() { @@ -107,26 +96,6 @@ install_wlan1() { sed -i -e "s,##WLAN1_PRE_DOWN_ACTION##,${WLAN1_PRE_DOWN_ACTION},g" ${D}${sysconfdir}/network/interfaces } -do_install_append_ccimx6qpsbc() { - install_virtwlans - install_wlan1 -} - -do_install_append_ccimx6ul() { - install_virtwlans - install_wlan1 -} - -do_install_append_ccimx8x() { - install_virtwlans - install_wlan1 -} - -do_install_append_ccimx8mn() { - install_virtwlans - install_wlan1 -} - # Disable wireless interfaces on first boot for non-wireless variants pkg_postinst_ontarget_${PN}() { if [ ! -d "/proc/device-tree/wireless" ]; then From 16933ff6b244ceb4d1e5d3920636a412fff22b00 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 10:50:52 +0100 Subject: [PATCH 055/120] mca-tool: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb b/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb index 635c49933..0feeeb68d 100644 --- a/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb +++ b/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 Digi International. +# Copyright (C) 2016-2020 Digi International. SUMMARY = "MCA firmware management tool" SECTION = "console/tools" @@ -22,4 +22,4 @@ inherit bin_package INSANE_SKIP_${PN} = "already-stripped" -COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx8m)" From 52e8a3e007c9bd1987a90c6c2784a49a5e2cf552 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 10:55:40 +0100 Subject: [PATCH 056/120] dey-examples: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../recipes-digi/dey-examples/dey-examples-adc-cmp.bb | 4 ++-- .../dey-examples/dey-examples-cryptochip.bb | 4 ++-- .../recipes-digi/dey-examples/dey-examples-v4l2.bb | 4 ++-- .../packagegroups/packagegroup-dey-examples.bb | 10 ++++++++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-adc-cmp.bb b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-adc-cmp.bb index 1e996de50..eda8ff25d 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-adc-cmp.bb +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-adc-cmp.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2018 Digi International. +# Copyright (C) 2017-2020 Digi International. SUMMARY = "DEY examples: Analog Comparator test application" SECTION = "examples" @@ -15,4 +15,4 @@ do_install() { } PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-cryptochip.bb b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-cryptochip.bb index 685ba4fc4..3a0aecb07 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-cryptochip.bb +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-cryptochip.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2019, Digi International Inc. +# Copyright (C) 2017-2020, Digi International Inc. require recipes-digi/dey-examples/dey-examples-src.inc @@ -18,4 +18,4 @@ do_install() { } PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6qpsbc|ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-v4l2.bb b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-v4l2.bb index f233abfbe..d10a2a52d 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-v4l2.bb +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-v4l2.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2018 Digi International. +# Copyright (C) 2013-2020 Digi International. SUMMARY = "DEY examples: V4L2 test application" SECTION = "examples" @@ -24,4 +24,4 @@ do_install() { PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6$|ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx6$|ccimx8x|ccimx8m)" diff --git a/meta-digi-dey/recipes-digi/packagegroups/packagegroup-dey-examples.bb b/meta-digi-dey/recipes-digi/packagegroups/packagegroup-dey-examples.bb index 2e428dea3..8668c9b82 100644 --- a/meta-digi-dey/recipes-digi/packagegroups/packagegroup-dey-examples.bb +++ b/meta-digi-dey/recipes-digi/packagegroups/packagegroup-dey-examples.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2019, Digi International Inc. +# Copyright (C) 2013-2020, Digi International Inc. SUMMARY = "DEY examples packagegroup" @@ -38,4 +38,10 @@ RDEPENDS_${PN}_append_ccimx8x = "\ dey-examples-v4l2 \ " -COMPATIBLE_MACHINE = "(ccimx6$|ccimx6ul|ccimx8x)" +RDEPENDS_${PN}_append_ccimx8m = "\ + dey-examples-adc-cmp \ + dey-examples-tamper \ + dey-examples-v4l2 \ +" + +COMPATIBLE_MACHINE = "(ccimx6$|ccimx6ul|ccimx8x|ccimx8m)" From 188df6fee31a15a2dfbbe321f6430b3faada7968 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 11:12:56 +0100 Subject: [PATCH 057/120] recovery-initramfs: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../recipes-core/images/dey-image-recovery-initramfs.bb | 3 ++- meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb b/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb index a568846e8..7ce5d3949 100644 --- a/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb +++ b/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2017, Digi International Inc. +# Copyright (C) 2016-2020, Digi International Inc. DESCRIPTION = "Recovery initramfs image" LICENSE = "MIT" @@ -16,6 +16,7 @@ PACKAGE_INSTALL = " \ PACKAGE_INSTALL_append_ccimx6 = " e2fsprogs-mke2fs" PACKAGE_INSTALL_append_ccimx6ul = " mtd-utils-ubifs" PACKAGE_INSTALL_append_ccimx8x = " e2fsprogs-mke2fs" +PACKAGE_INSTALL_append_ccimx8mn = " e2fsprogs-mke2fs" # Do not pollute the initrd image with rootfs features IMAGE_FEATURES = "" diff --git a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb index 119339830..46b69834f 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb +++ b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb @@ -56,3 +56,4 @@ FILES_${PN} = "/" RDEPENDS_${PN}_append_ccimx6sbc = " cryptsetup" RDEPENDS_${PN}_append_ccimx6qpsbc = " cryptsetup" RDEPENDS_${PN}_append_ccimx8x = " cryptsetup" +RDEPENDS_${PN}_append_ccimx8mn = " cryptsetup" From d430cc3bab99f5c7597bc8508a541669cfcea52e Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 17:13:46 +0100 Subject: [PATCH 058/120] recovery-initramfs: generalize recipe to avoid redefinitions Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/include/ccimx6.inc | 2 ++ meta-digi-arm/conf/machine/include/ccimx6ul.inc | 2 ++ meta-digi-arm/conf/machine/include/ccimx8mn.inc | 2 ++ meta-digi-arm/conf/machine/include/ccimx8x.inc | 2 ++ .../recipes-core/images/dey-image-recovery-initramfs.bb | 7 ++----- meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb | 5 +---- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/meta-digi-arm/conf/machine/include/ccimx6.inc b/meta-digi-arm/conf/machine/include/ccimx6.inc index 0e4240e1a..a426af847 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6.inc @@ -15,6 +15,8 @@ UBOOT_SUFFIX = "imx" # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm/configs/ccimx6sbc_defconfig" +STORAGE_MEDIA = "mmc" + # Wireless external module WIRELESS_MODULE ?= "" diff --git a/meta-digi-arm/conf/machine/include/ccimx6ul.inc b/meta-digi-arm/conf/machine/include/ccimx6ul.inc index 5465cebfc..96349cf22 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6ul.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6ul.inc @@ -12,6 +12,8 @@ include conf/machine/include/tune-cortexa7.inc UBOOT_PREFIX = "u-boot" UBOOT_SUFFIX = "imx" +STORAGE_MEDIA = "mtd" + # Bluetooth interface BT_DEVICE_NAME ?= "cc6ul" diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc index 32905e6e1..4f947eb48 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8mn.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -22,6 +22,8 @@ SDIMG_BOOTLOADER = "${DEPLOY_DIR_IMAGE}/${BOOTABLE_FILENAME}" # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" +STORAGE_MEDIA = "mmc" + # Bluetooth interface BT_DEVICE_NAME ?= "cc8mn" diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index e1f2c67e1..873296c9f 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -29,6 +29,8 @@ RAM_CONFIGS = "1.2GHz_512MB_16bit 1.2GHz_1GB_16bit 1.2GHz_1GB_32bit 1.2GHz_2GB_3 # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8x_defconfig" +STORAGE_MEDIA = "mmc" + # Bluetooth interface BT_DEVICE_NAME ?= "cc8x" diff --git a/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb b/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb index 7ce5d3949..15cc4481e 100644 --- a/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb +++ b/meta-digi-dey/recipes-core/images/dey-image-recovery-initramfs.bb @@ -5,6 +5,8 @@ LICENSE = "MIT" PACKAGE_INSTALL = " \ busybox \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mmc', 'e2fsprogs-mke2fs', '', d)} \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mtd', 'mtd-utils-ubifs', '', d)} \ psplash \ recovery-initramfs \ swupdate \ @@ -13,11 +15,6 @@ PACKAGE_INSTALL = " \ wipe \ " -PACKAGE_INSTALL_append_ccimx6 = " e2fsprogs-mke2fs" -PACKAGE_INSTALL_append_ccimx6ul = " mtd-utils-ubifs" -PACKAGE_INSTALL_append_ccimx8x = " e2fsprogs-mke2fs" -PACKAGE_INSTALL_append_ccimx8mn = " e2fsprogs-mke2fs" - # Do not pollute the initrd image with rootfs features IMAGE_FEATURES = "" IMAGE_LINGUAS = "" diff --git a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb index 46b69834f..25e3e9e3a 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb +++ b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb @@ -53,7 +53,4 @@ PACKAGES = "${PN}" FILES_${PN} = "/" -RDEPENDS_${PN}_append_ccimx6sbc = " cryptsetup" -RDEPENDS_${PN}_append_ccimx6qpsbc = " cryptsetup" -RDEPENDS_${PN}_append_ccimx8x = " cryptsetup" -RDEPENDS_${PN}_append_ccimx8mn = " cryptsetup" +RDEPENDS_${PN}_append = "${@bb.utils.contains('STORAGE_MEDIA', 'mmc', ' cryptsetup', '', d)}" From 9c21f10698d30dbb01992dae375d72e3b5e481d0 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 11:19:10 +0100 Subject: [PATCH 059/120] meta-digi-dey: sysinfo: adapt script to CC8M platforms https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo index 02bc7c06b..4a542fd84 100755 --- a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo +++ b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo @@ -3,7 +3,7 @@ # # sysinfo # -# Copyright (C) 2016-2018 by Digi International Inc. +# Copyright (C) 2016-2020 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -289,7 +289,7 @@ BOARD_ID="$(cat /proc/device-tree/digi,carrierboard,id | tr -d '\0')" if grep -qs '\' /proc/device-tree/compatible; then MCA_NODE="/sys/bus/i2c/devices/0-007e" -elif grep -qs '\' /proc/device-tree/compatible; then +elif grep -qs '\' /proc/device-tree/compatible; then MCA_NODE="/sys/bus/i2c/devices/0-0063" fi if [ -d "$MCA_NODE" ]; then From 95c636d327f99178b0cce6587ae566cd95b637a4 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 11:20:40 +0100 Subject: [PATCH 060/120] trustfence-initramfs: add support for ccimx8mn platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../trustfence/trustfence-initramfs.bb | 8 +- .../ccimx8mn/trustfence-initramfs-init | 81 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb index b4060ba2c..442a45125 100644 --- a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb +++ b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2016, 2017 Digi International Inc. +# Copyright (C) 2016-2020 Digi International Inc. SUMMARY = "Trustfence initramfs required files" LICENSE = "GPL-2.0" @@ -39,5 +39,9 @@ RDEPENDS_${PN}_append_ccimx8x = " \ cryptsetup \ " +RDEPENDS_${PN}_append_ccimx8m = " \ + cryptsetup \ +" + PACKAGE_ARCH = "${MACHINE_ARCH}" -COMPATIBLE_MACHINE = "(ccimx6|ccimx6ul|ccimx8x)" \ No newline at end of file +COMPATIBLE_MACHINE = "(ccimx6|ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init new file mode 100644 index 000000000..9fdd4fc89 --- /dev/null +++ b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init @@ -0,0 +1,81 @@ +#!/bin/sh +#=============================================================================== +# +# trustfence-initramfs-init +# +# Copyright (C) 2020 by Digi International Inc. +# All rights reserved. +# +# 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. +# +# +# !Description: Init script for Trustfence initramfs +# +#=============================================================================== + +POWEROFF_TIME="10" + +error() { + [ "${#}" != "0" ] && printf "\n[ERROR]: %s\n\n" "${1}" + echo "The system will poweroff in ${POWEROFF_TIME} seconds" + sleep "${POWEROFF_TIME}" + sync && poweroff -f +} + +# Main +#------------------------------------------------------------------------------ +# Setup the environment. +export PATH=/bin:/sbin:/usr/bin:/usr/sbin + +mkdir -p /proc /sys /dev +mount -t proc proc /proc +mount -t sysfs sysfs /sys +mount -t devtmpfs devtmpfs /dev + +# Set kernel console loglevel +LOGLEVEL="$(sysctl -n kernel.printk)" +sysctl -q -w kernel.printk=4 + +for arg in $(cat /proc/cmdline); do + case "${arg}" in + init=*|rescue=1|root=*) eval ${arg};; + esac +done + +# Translate "PARTUUID=..." to real device +root="$(findfs ${root})" + +# Jump to a rescue shell if requested +if [ -n "${rescue}" ]; then + # Expand console and respawn if exited + while true; do + setsid cttyhack sh -l + sleep 1 + done +fi + +# Open LUKS encrypted device +if trustfence-tool ${root} cryptroot; then + # Reset root variable to the decrypted mapped device + root="/dev/mapper/cryptroot" +else + error "unable to open encrypted partition." +fi + +# Mount mapped device +mkdir -p /newroot +FSTYPE="$(blkid ${root} | sed -e 's,.*TYPE="\([^"]\+\)".*,\1,g')" +mount ${FSTYPE:+-t ${FSTYPE}} ${root} /newroot + +# +# Clean-up and do the switch_root to the final rootfs +# +# - restore previous kernel console loglevel +# - umount virtual filesystems +# +[ -n "${LOGLEVEL}" ] && sysctl -q -w kernel.printk="${LOGLEVEL}" +mount --move /dev /newroot/dev +umount /sys /proc +exec switch_root /newroot ${init:-/sbin/init} From 3c5fd58866a54b1534c3d5f2107aee6fcbb36efa Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 18:37:22 +0100 Subject: [PATCH 061/120] trusfence-initramfs: generalize recipe to avoid redefinitions Signed-off-by: Arturo Buzarra --- .../trustfence/trustfence-initramfs.bb | 27 +++---- .../ccimx6/trustfence-initramfs-init | 81 ------------------- .../ccimx8mn/trustfence-initramfs-init | 81 ------------------- ...mfs-init => trustfence-initramfs-init_mmc} | 0 ...mfs-init => trustfence-initramfs-init_mtd} | 0 5 files changed, 9 insertions(+), 180 deletions(-) delete mode 100644 meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6/trustfence-initramfs-init delete mode 100644 meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init rename meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/{ccimx8x/trustfence-initramfs-init => trustfence-initramfs-init_mmc} (100%) rename meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/{ccimx6ul/trustfence-initramfs-init => trustfence-initramfs-init_mtd} (100%) diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb index 442a45125..b5d7ac002 100644 --- a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb +++ b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs.bb @@ -5,13 +5,18 @@ LICENSE = "GPL-2.0" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" SRC_URI = " \ - file://trustfence-initramfs-init \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mmc', 'file://trustfence-initramfs-init_mmc', '', d)} \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mtd', 'file://trustfence-initramfs-init_mtd', '', d)} \ " S = "${WORKDIR}" do_install() { - install -m 0755 trustfence-initramfs-init ${D}/init + if [ "${STORAGE_MEDIA}" = "mmc" ]; then + install -m 0755 trustfence-initramfs-init_mmc ${D}/init + else + install -m 0755 trustfence-initramfs-init_mtd ${D}/init + fi } # Do not create debug/devel packages @@ -21,27 +26,13 @@ FILES_${PN} = "/" # Runtime packages used in 'trustfence-initramfs-init' RDEPENDS_${PN} = " \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mmc', 'cryptsetup', '', d)} \ + ${@bb.utils.contains('STORAGE_MEDIA', 'mtd', 'mtd-utils-ubifs', '', d)} \ trustfence-tool \ util-linux-findfs \ wipe \ u-boot-fw-utils \ " -RDEPENDS_${PN}_append_ccimx6 = " \ - cryptsetup \ -" - -RDEPENDS_${PN}_append_ccimx6ul = " \ - mtd-utils-ubifs \ -" - -RDEPENDS_${PN}_append_ccimx8x = " \ - cryptsetup \ -" - -RDEPENDS_${PN}_append_ccimx8m = " \ - cryptsetup \ -" - PACKAGE_ARCH = "${MACHINE_ARCH}" COMPATIBLE_MACHINE = "(ccimx6|ccimx6ul|ccimx8x|ccimx8m)" diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6/trustfence-initramfs-init b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6/trustfence-initramfs-init deleted file mode 100644 index 3d763a48c..000000000 --- a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6/trustfence-initramfs-init +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -#=============================================================================== -# -# trustfence-initramfs-init -# -# Copyright (C) 2016, 2017 by Digi International Inc. -# All rights reserved. -# -# 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. -# -# -# !Description: Init script for Trustfence initramfs -# -#=============================================================================== - -POWEROFF_TIME="10" - -error() { - [ "${#}" != "0" ] && printf "\n[ERROR]: %s\n\n" "${1}" - echo "The system will poweroff in ${POWEROFF_TIME} seconds" - sleep "${POWEROFF_TIME}" - sync && poweroff -f -} - -# Main -#------------------------------------------------------------------------------ -# Setup the environment. -export PATH=/bin:/sbin:/usr/bin:/usr/sbin - -mkdir -p /proc /sys /dev -mount -t proc proc /proc -mount -t sysfs sysfs /sys -mount -t devtmpfs devtmpfs /dev - -# Set kernel console loglevel -LOGLEVEL="$(sysctl -n kernel.printk)" -sysctl -q -w kernel.printk=4 - -for arg in $(cat /proc/cmdline); do - case "${arg}" in - init=*|rescue=1|root=*) eval ${arg};; - esac -done - -# Translate "PARTUUID=..." to real device -root="$(findfs ${root})" - -# Jump to a rescue shell if requested -if [ -n "${rescue}" ]; then - # Expand console and respawn if exited - while true; do - setsid cttyhack sh -l - sleep 1 - done -fi - -# Open LUKS encrypted device -if trustfence-tool ${root} cryptroot; then - # Reset root variable to the decrypted mapped device - root="/dev/mapper/cryptroot" -else - error "unable to open encrypted partition." -fi - -# Mount mapped device -mkdir -p /newroot -FSTYPE="$(blkid ${root} | sed -e 's,.*TYPE="\([^"]\+\)".*,\1,g')" -mount ${FSTYPE:+-t ${FSTYPE}} ${root} /newroot - -# -# Clean-up and do the switch_root to the final rootfs -# -# - restore previous kernel console loglevel -# - umount virtual filesystems -# -[ -n "${LOGLEVEL}" ] && sysctl -q -w kernel.printk="${LOGLEVEL}" -mount --move /dev /newroot/dev -umount /sys /proc -exec switch_root /newroot ${init:-/sbin/init} diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init deleted file mode 100644 index 9fdd4fc89..000000000 --- a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8mn/trustfence-initramfs-init +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -#=============================================================================== -# -# trustfence-initramfs-init -# -# Copyright (C) 2020 by Digi International Inc. -# All rights reserved. -# -# 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. -# -# -# !Description: Init script for Trustfence initramfs -# -#=============================================================================== - -POWEROFF_TIME="10" - -error() { - [ "${#}" != "0" ] && printf "\n[ERROR]: %s\n\n" "${1}" - echo "The system will poweroff in ${POWEROFF_TIME} seconds" - sleep "${POWEROFF_TIME}" - sync && poweroff -f -} - -# Main -#------------------------------------------------------------------------------ -# Setup the environment. -export PATH=/bin:/sbin:/usr/bin:/usr/sbin - -mkdir -p /proc /sys /dev -mount -t proc proc /proc -mount -t sysfs sysfs /sys -mount -t devtmpfs devtmpfs /dev - -# Set kernel console loglevel -LOGLEVEL="$(sysctl -n kernel.printk)" -sysctl -q -w kernel.printk=4 - -for arg in $(cat /proc/cmdline); do - case "${arg}" in - init=*|rescue=1|root=*) eval ${arg};; - esac -done - -# Translate "PARTUUID=..." to real device -root="$(findfs ${root})" - -# Jump to a rescue shell if requested -if [ -n "${rescue}" ]; then - # Expand console and respawn if exited - while true; do - setsid cttyhack sh -l - sleep 1 - done -fi - -# Open LUKS encrypted device -if trustfence-tool ${root} cryptroot; then - # Reset root variable to the decrypted mapped device - root="/dev/mapper/cryptroot" -else - error "unable to open encrypted partition." -fi - -# Mount mapped device -mkdir -p /newroot -FSTYPE="$(blkid ${root} | sed -e 's,.*TYPE="\([^"]\+\)".*,\1,g')" -mount ${FSTYPE:+-t ${FSTYPE}} ${root} /newroot - -# -# Clean-up and do the switch_root to the final rootfs -# -# - restore previous kernel console loglevel -# - umount virtual filesystems -# -[ -n "${LOGLEVEL}" ] && sysctl -q -w kernel.printk="${LOGLEVEL}" -mount --move /dev /newroot/dev -umount /sys /proc -exec switch_root /newroot ${init:-/sbin/init} diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8x/trustfence-initramfs-init b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/trustfence-initramfs-init_mmc similarity index 100% rename from meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx8x/trustfence-initramfs-init rename to meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/trustfence-initramfs-init_mmc diff --git a/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6ul/trustfence-initramfs-init b/meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/trustfence-initramfs-init_mtd similarity index 100% rename from meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/ccimx6ul/trustfence-initramfs-init rename to meta-digi-dey/recipes-core/trustfence/trustfence-initramfs/trustfence-initramfs-init_mtd From 82926285249116b6e5032cd75c4fe51786695488 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 14:12:11 +0100 Subject: [PATCH 062/120] qtbase: Use upstreamed patches instead of custom NXP ones. These patches were copied from meta-fsl-bsp-release layer, but with the latest versions throws a compilation issue with the ccimx8mn platform. However the upstreamed patches works fine. Signed-off-by: Arturo Buzarra --- ...d-error-when-egl-headers-need-platfo.patch | 30 ------------------- .../qt5/qtbase/0014-Add-IMX-GPU-support.patch | 22 -------------- .../qtbase/0015-Add-eglfs-to-IMX-GPU.patch | 13 -------- ...-Configure-eglfs-with-egl-pkg-config.patch | 13 -------- 4 files changed, 78 deletions(-) delete mode 100644 meta-digi-dey/recipes-qt/qt5/qtbase/0001-egl.prf-Fix-build-error-when-egl-headers-need-platfo.patch delete mode 100644 meta-digi-dey/recipes-qt/qt5/qtbase/0014-Add-IMX-GPU-support.patch delete mode 100644 meta-digi-dey/recipes-qt/qt5/qtbase/0015-Add-eglfs-to-IMX-GPU.patch delete mode 100644 meta-digi-dey/recipes-qt/qt5/qtbase/0016-Configure-eglfs-with-egl-pkg-config.patch diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase/0001-egl.prf-Fix-build-error-when-egl-headers-need-platfo.patch b/meta-digi-dey/recipes-qt/qt5/qtbase/0001-egl.prf-Fix-build-error-when-egl-headers-need-platfo.patch deleted file mode 100644 index c99c04704..000000000 --- a/meta-digi-dey/recipes-qt/qt5/qtbase/0001-egl.prf-Fix-build-error-when-egl-headers-need-platfo.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 3f9703fecd670b36030e1093466f6d11b370c19f Mon Sep 17 00:00:00 2001 -From: Yuqing Zhu -Date: Mon, 27 Mar 2017 15:33:35 +0800 -Subject: [PATCH] egl.prf: Fix build error when egl headers need platform - definition - -Gain the value through pkg-config and pass it through QMAKE_CFLAGS_EGL. - -Signed-off-by: Yuqing Zhu ---- - mkspecs/features/egl.prf | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/mkspecs/features/egl.prf b/mkspecs/features/egl.prf -index 9fa0c9e..85d5852 100644 ---- a/mkspecs/features/egl.prf -+++ b/mkspecs/features/egl.prf -@@ -1,3 +1,9 @@ -+# egl headers need a definition -+PKG_CONFIG = $$pkgConfigExecutable() -+PKGCONFIG_CFLAGS = $$system($$PKG_CONFIG --cflags egl) -+PKGCONFIG_CFLAGS = $$find(PKGCONFIG_CFLAGS, ^-D.*) -+QMAKE_CFLAGS_EGL = $$PKGCONFIG_CFLAGS -+ - INCLUDEPATH += $$QMAKE_INCDIR_EGL - LIBS_PRIVATE += $$QMAKE_LIBS_EGL - QMAKE_CFLAGS += $$QMAKE_CFLAGS_EGL --- -1.9.1 - diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase/0014-Add-IMX-GPU-support.patch b/meta-digi-dey/recipes-qt/qt5/qtbase/0014-Add-IMX-GPU-support.patch deleted file mode 100644 index 370a2fc8a..000000000 --- a/meta-digi-dey/recipes-qt/qt5/qtbase/0014-Add-IMX-GPU-support.patch +++ /dev/null @@ -1,22 +0,0 @@ -From bd9d14bbb7cc121d97d7f9e3b49509d8491a9aaa Mon Sep 17 00:00:00 2001 -From: Tom Hochstein -Date: Tue, 2 May 2017 22:17:34 -0500 - ---- - mkspecs/linux-oe-g++/qmake.conf | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/mkspecs/linux-oe-g++/qmake.conf b/mkspecs/linux-oe-g++/qmake.conf -index 30d31ed..7a93f2b 100644 ---- a/mkspecs/linux-oe-g++/qmake.conf -+++ b/mkspecs/linux-oe-g++/qmake.conf -@@ -38,5 +38,9 @@ isEmpty(QMAKE_QT_CONFIG):QMAKE_QT_CONFIG = $$(OE_QMAKE_QT_CONFIG) - - include(../oe-device-extra.pri) - -+QMAKE_LIBS_EGL += -lEGL -+QMAKE_LIBS_OPENGL_ES2 += -lEGL -lGLESv2 -+QMAKE_LIBS_OPENVG += -lEGL -lOpenVG -+ - load(device_config) - load(qt_config) diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase/0015-Add-eglfs-to-IMX-GPU.patch b/meta-digi-dey/recipes-qt/qt5/qtbase/0015-Add-eglfs-to-IMX-GPU.patch deleted file mode 100644 index 794fa6222..000000000 --- a/meta-digi-dey/recipes-qt/qt5/qtbase/0015-Add-eglfs-to-IMX-GPU.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: git/mkspecs/linux-oe-g++/qmake.conf -=================================================================== ---- git.orig/mkspecs/linux-oe-g++/qmake.conf 2016-12-14 17:03:17.000000000 -0600 -+++ git/mkspecs/linux-oe-g++/qmake.conf 2016-12-14 17:06:23.000000000 -0600 -@@ -39,6 +39,8 @@ - - include(../oe-device-extra.pri) - -+EGLFS_DEVICE_INTEGRATION = eglfs_viv -+ - QMAKE_LIBS_EGL += -lEGL - QMAKE_LIBS_OPENGL_ES2 += -lEGL -lGLESv2 - QMAKE_LIBS_OPENVG += -lEGL -lOpenVG diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase/0016-Configure-eglfs-with-egl-pkg-config.patch b/meta-digi-dey/recipes-qt/qt5/qtbase/0016-Configure-eglfs-with-egl-pkg-config.patch deleted file mode 100644 index a245d79aa..000000000 --- a/meta-digi-dey/recipes-qt/qt5/qtbase/0016-Configure-eglfs-with-egl-pkg-config.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: git/src/plugins/platforms/eglfs/eglfs-plugin.pro -=================================================================== ---- git.orig/src/plugins/platforms/eglfs/eglfs-plugin.pro 2017-01-04 16:54:05.000000000 -0600 -+++ git/src/plugins/platforms/eglfs/eglfs-plugin.pro 2017-01-04 16:56:25.000000000 -0600 -@@ -2,6 +2,8 @@ - - QT += platformsupport-private eglfs_device_lib-private - -+CONFIG += egl -+ - SOURCES += $$PWD/qeglfsmain.cpp - - OTHER_FILES += $$PWD/eglfs.json From d394091a1b2d036e17a172c117a22de18a9626e9 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 17:12:07 +0100 Subject: [PATCH 063/120] meta-digi-arm: ccimx8x: unify kernel defconfig for i.MX8 platforms Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/include/ccimx8x.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index 873296c9f..20a37aacc 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -27,7 +27,7 @@ SDIMG_BOOTLOADER = "${DEPLOY_DIR_IMAGE}/${BOOTABLE_FILENAME}" RAM_CONFIGS = "1.2GHz_512MB_16bit 1.2GHz_1GB_16bit 1.2GHz_1GB_32bit 1.2GHz_2GB_32bit" # Linux kernel configuration -KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8x_defconfig" +KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" STORAGE_MEDIA = "mmc" From 0f7195b35934f44aec4c62d69d3581bf4237c7a9 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 26 Dec 2019 17:13:24 +0100 Subject: [PATCH 064/120] imx-m4-demos: sync recipe with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 Signed-off-by: Arturo Buzarra --- meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos-2.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos-2.inc b/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos-2.inc index f35d6dc74..af6ac93b5 100644 --- a/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos-2.inc +++ b/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos-2.inc @@ -22,6 +22,7 @@ SCR = "SCR-${SOC}-m4-demo.txt" do_deploy () { # Install the demo binaries cp ${D}/* ${DEPLOYDIR}/ + chmod 0644 ${DEPLOYDIR}/* } addtask deploy after do_install From 9da5aac0633b6e2b48e100b79969e405248873dc Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 27 Dec 2019 11:45:30 +0100 Subject: [PATCH 065/120] firmware-imx: remove custom do_deploy support to use upstream version For the i.MX8M processors, the do_deploy support is provided by the upstream recipe firmware-imx-8m. https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/machine/include/ccimx8mn.inc | 3 +++ .../recipes-bsp/firmware-imx/firmware-imx_8.4.bb | 11 +---------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/meta-digi-arm/conf/machine/include/ccimx8mn.inc b/meta-digi-arm/conf/machine/include/ccimx8mn.inc index 4f947eb48..dc58b519f 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8mn.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8mn.inc @@ -19,6 +19,9 @@ BOOTLOADER_SEEK = "32" BOOTABLE_FILENAME = "${UBOOT_PREFIX}-${MACHINE}.bin" SDIMG_BOOTLOADER = "${DEPLOY_DIR_IMAGE}/${BOOTABLE_FILENAME}" +# Set LPDDR4 FIRMWARE +DDR_FIRMWARE_NAME = "lpddr4_pmu_train_1d_imem.bin lpddr4_pmu_train_1d_dmem.bin lpddr4_pmu_train_2d_imem.bin lpddr4_pmu_train_2d_dmem.bin" + # Linux kernel configuration KERNEL_DEFCONFIG ?= "arch/arm64/configs/ccimx8_defconfig" diff --git a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb index 24bf14a09..34bafa842 100644 --- a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb +++ b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb @@ -61,16 +61,7 @@ inherit deploy addtask deploy before do_build after do_install do_deploy () { # Deploy i.MX8 related firmware files - if [ "${IS_MX8}" = "8m" ]; then - # Deploy ddr/synopsys - for ddr_firmware in ${DDR_FIRMWARE_NAME}; do - install -m 0644 ${S}/firmware/ddr/synopsys/${ddr_firmware} ${DEPLOYDIR} - done - - # Deploy hdmi/cadence - install -m 0644 ${S}/firmware/hdmi/cadence/signed_dp_imx8m.bin ${DEPLOYDIR} - install -m 0644 ${S}/firmware/hdmi/cadence/signed_hdmi_imx8m.bin ${DEPLOYDIR} - elif [ "${IS_MX8}" = "8qm" ]; then + if [ "${IS_MX8}" = "8qm" ]; then # Deploy hdmi/cadence install -m 0644 ${S}/firmware/hdmi/cadence/hdmitxfw.bin ${DEPLOYDIR} install -m 0644 ${S}/firmware/hdmi/cadence/hdmirxfw.bin ${DEPLOYDIR} From 712fa3f96aa8065e6f0db228703690c99d628cc5 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 27 Dec 2019 13:34:55 +0100 Subject: [PATCH 066/120] imx-boot: add support to ConnectCore 8M Nano platform https://jira.digi.com/browse/DEL-6911 Signed-off-by: Arturo Buzarra --- .../recipes-bsp/imx-atf/imx-atf_2.0.bb | 4 +- .../imx-mkimage/imx-boot_0.2.bbappend | 147 +++++++++++++----- .../imx-mkimage/imx-mkimage_%.bbappend | 4 +- .../recipes-bsp/u-boot/digi-u-boot.inc | 27 ++++ 4 files changed, 139 insertions(+), 43 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb index 12cd3096f..0e1b49156 100644 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb @@ -10,10 +10,10 @@ inherit fsl-eula-unpack pkgconfig deploy PV = "2.0+git${SRCPV}" ATF_SRC ?= "git://source.codeaurora.org/external/imx/imx-atf.git;protocol=https" -SRCBRANCH = "imx_4.14.98_2.1.0" +SRCBRANCH = "imx_4.14.98_2.2.0" SRC_URI = "${ATF_SRC};branch=${SRCBRANCH}" -SRCREV = "727cf896a4c79d152dae4537e28400c747bf39b9" +SRCREV = "1355c5d12d75c9c7bdd08826796096bab519b3d5" S = "${WORKDIR}/git" diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend index 06155b0a1..23f467b14 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend @@ -2,8 +2,8 @@ inherit boot-artifacts # Use the v4.14 latest BSP branch -SRCBRANCH = "imx_4.14.98_2.1.0" -SRCREV = "abd6ce551a7b81fc6953d32d92b24a4a1d4b214e" +SRCBRANCH = "imx_4.14.98_2.2.0" +SRCREV = "c00cd78d2e80178171d2d7f8d0d1ce6e2ea41ac5" FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI_append_ccimx8x = " file://0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch" @@ -16,7 +16,9 @@ DEPENDS_append_ccimx8x = " coreutils-native" # output. Note that this aggregation replaces the aggregation # that would otherwise be done in the image build as controlled # by IMAGE_BOOTFILES_DEPENDS and IMAGE_BOOTFILES in image_types_fsl.bbclass -IMX_M4_DEMOS = "imx-m4-demos" +IMX_M4_DEMOS = "" +IMX_M4_DEMOS_mx8qm = "imx-m4-demos" +IMX_M4_DEMOS_mx8qxp = "imx-m4-demos" # This package aggregates output deployed by other packages, # so set the appropriate dependencies @@ -35,11 +37,19 @@ do_populate_lic[depends] += " \ firmware-imx:do_populate_lic \ " ATF_MACHINE_NAME_mx8qxp = "bl31-imx8qx.bin" +ATF_MACHINE_NAME_mx8mn = "bl31-imx8mn.bin" + +# 8MQ/8MM/8MN share the same soc folder +BOOT_STAGING_mx8mn = "${S}/iMX8M" + +SOC_TARGET_mx8mn = "iMX8MN" IMXBOOT_TARGETS_ccimx8x = "${@bb.utils.contains('UBOOT_CONFIG', 'fspi', 'flash_flexspi', \ 'flash flash_regression_linux_m4', d)}" -do_compile () { +IMXBOOT_TARGETS_ccimx8mn = "${@bb.utils.contains('UBOOT_CONFIG', 'fspi', 'flash_evk_flexspi', 'flash_spl_uboot', d)}" + +compile_mx8x() { bbnote 8QX boot binary build cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_srtm_demo.bin ${BOOT_STAGING}/m40_tcm.bin cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_srtm_demo.bin ${BOOT_STAGING}/m4_image.bin @@ -51,63 +61,103 @@ do_compile () { for ramc in ${RAM_CONFIGS}; do cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/${SC_FIRMWARE_NAME}-${ramc} ${BOOT_STAGING}/ done +} +compile_mx8m() { + bbnote 8MQ/8MM/8MN boot binary build + cp ${DEPLOY_DIR_IMAGE}/signed_*_imx8m.bin ${BOOT_STAGING} + cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/u-boot-spl.bin-${MACHINE}-${UBOOT_CONFIG} ${BOOT_STAGING}/u-boot-spl.bin + cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/${UBOOT_DTB_NAME} ${BOOT_STAGING}/fsl-imx8mn-evk.dtb + cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/u-boot-nodtb.bin-${MACHINE}-${UBOOT_CONFIG} ${BOOT_STAGING}/u-boot-nodtb.bin + + cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/mkimage_uboot ${BOOT_STAGING}/ + cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/${ATF_MACHINE_NAME} ${BOOT_STAGING}/bl31.bin + + for ddr_firmware in ${DDR_FIRMWARE_NAME}; do + cp ${DEPLOY_DIR_IMAGE}/${ddr_firmware} ${BOOT_STAGING} + done +} + +do_compile () { + compile_${SOC_FAMILY} # mkimage for i.MX8 for type in ${UBOOT_CONFIG}; do - RAM_SIZE="$(echo ${type} | sed -e 's,.*[a-z]\+\([0-9]\+[M|G]B\)$,\1,g')" - for ramc in ${RAM_CONFIGS}; do - if echo "${ramc}" | grep -qs "${RAM_SIZE}"; then - # Match U-Boot memory size and and SCFW memory configuration - cd ${BOOT_STAGING} - ln -sf u-boot-${type}.bin u-boot.bin - ln -sf ${SC_FIRMWARE_NAME}-${ramc} scfw_tcm.bin - cd - - for target in ${IMXBOOT_TARGETS}; do - bbnote "building ${SOC_TARGET} - ${ramc} - ${target}" - make SOC=${SOC_TARGET} ${target} - if [ -e "${BOOT_STAGING}/flash.bin" ]; then - cp ${BOOT_STAGING}/flash.bin ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} - fi - SCFWBUILT="yes" - done - rm ${BOOT_STAGING}/scfw_tcm.bin - rm ${BOOT_STAGING}/u-boot.bin - # Remove u-boot-atf.bin and u-boot-hash.bin so they get generated with the next iteration's U-Boot - rm ${BOOT_STAGING}/u-boot-atf.bin - rm ${BOOT_STAGING}/u-boot-hash.bin + if [ "${SOC_TARGET}" = "iMX8QX" ]; then + RAM_SIZE="$(echo ${type} | sed -e 's,.*[a-z]\+\([0-9]\+[M|G]B\)$,\1,g')" + for ramc in ${RAM_CONFIGS}; do + if echo "${ramc}" | grep -qs "${RAM_SIZE}"; then + # Match U-Boot memory size and and SCFW memory configuration + cd ${BOOT_STAGING} + ln -sf u-boot-${type}.bin u-boot.bin + ln -sf ${SC_FIRMWARE_NAME}-${ramc} scfw_tcm.bin + cd - + for target in ${IMXBOOT_TARGETS}; do + bbnote "building ${SOC_TARGET} - ${ramc} - ${target}" + make SOC=${SOC_TARGET} ${target} + if [ -e "${BOOT_STAGING}/flash.bin" ]; then + cp ${BOOT_STAGING}/flash.bin ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} + fi + SCFWBUILT="yes" + done + rm ${BOOT_STAGING}/scfw_tcm.bin + rm ${BOOT_STAGING}/u-boot.bin + # Remove u-boot-atf.bin and u-boot-hash.bin so they get generated with the next iteration's U-Boot + rm ${BOOT_STAGING}/u-boot-atf.bin + rm ${BOOT_STAGING}/u-boot-hash.bin + fi + done + else + # mkimage for i.MX8M + for target in ${IMXBOOT_TARGETS}; do + bbnote "building ${SOC_TARGET} - ${target}" + make SOC=${SOC_TARGET} ${target} + if [ -e "${BOOT_STAGING}/flash.bin" ]; then + cp ${BOOT_STAGING}/flash.bin ${S}/${UBOOT_PREFIX}-${MACHINE}.bin-${target} fi - done + done + fi done # Check that SCFW was built at least once - if [ "${SCFWBUILT}" != "yes" ]; then + if [ "${SOC_TARGET}" = "iMX8QX" and "${SCFWBUILT}" != "yes" ]; then bbfatal "SCFW was not built!" fi } +# ConnectCore 8M Nano does not have different binaries +UBOOT_RAM_COMBINATIONS_ccimx8mn = "" + do_install () { install -d ${D}/boot - for ramc in ${UBOOT_RAM_COMBINATIONS}; do + if [ "${UBOOT_RAM_COMBINATIONS}" = "" ]; then for target in ${IMXBOOT_TARGETS}; do - install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} ${D}/boot/ + install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}.bin-${target} ${D}/boot/ done - done + else + for ramc in ${UBOOT_RAM_COMBINATIONS}; do + for target in ${IMXBOOT_TARGETS}; do + install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} ${D}/boot/ + done + done + fi } do_deploy () { install -d ${DEPLOYDIR}/${BOOT_TOOLS} # copy the tool mkimage to deploy path and sc fw, dcd and uboot - install -m 0644 ${BOOT_STAGING}/mx8qx-ahab-container.img ${DEPLOYDIR}/${BOOT_TOOLS} - install -m 0644 ${BOOT_STAGING}/m40_tcm.bin ${DEPLOYDIR}/${BOOT_TOOLS} - install -m 0644 ${BOOT_STAGING}/m4_image.bin ${DEPLOYDIR}/${BOOT_TOOLS} + if [ "${SOC_TARGET}" = "iMX8QX" ]; then + install -m 0644 ${BOOT_STAGING}/mx8qx-ahab-container.img ${DEPLOYDIR}/${BOOT_TOOLS} + install -m 0644 ${BOOT_STAGING}/m40_tcm.bin ${DEPLOYDIR}/${BOOT_TOOLS} + install -m 0644 ${BOOT_STAGING}/m4_image.bin ${DEPLOYDIR}/${BOOT_TOOLS} + fi install -m 0755 ${S}/${TOOLS_NAME} ${DEPLOYDIR}/${BOOT_TOOLS} # copy makefile (soc.mak) for reference install -m 0644 ${BOOT_STAGING}/soc.mak ${DEPLOYDIR}/${BOOT_TOOLS} # copy the generated boot image to deploy path - for ramc in ${UBOOT_RAM_COMBINATIONS}; do + if [ "${UBOOT_RAM_COMBINATIONS}" = "" ]; then IMAGE_IMXBOOT_TARGET="" for target in ${IMXBOOT_TARGETS}; do # Use first "target" as IMAGE_IMXBOOT_TARGET @@ -115,15 +165,34 @@ do_deploy () { IMAGE_IMXBOOT_TARGET="$target" echo "Set boot target as $IMAGE_IMXBOOT_TARGET" fi - install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} ${DEPLOYDIR} + install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}.bin-${target} ${DEPLOYDIR} done cd ${DEPLOYDIR} - ln -sf ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${IMAGE_IMXBOOT_TARGET} ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin + ln -sf ${UBOOT_PREFIX}-${MACHINE}.bin-${IMAGE_IMXBOOT_TARGET} ${UBOOT_PREFIX}-${MACHINE}.bin # Link to default bootable U-Boot filename. It gets overwritten # on every loop so the only last RAM_CONFIG will survive. - ln -sf ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${IMAGE_IMXBOOT_TARGET} ${BOOTABLE_FILENAME} + ln -sf ${UBOOT_PREFIX}-${MACHINE}.bin-${IMAGE_IMXBOOT_TARGET} ${BOOTABLE_FILENAME} cd - - done + else + for ramc in ${UBOOT_RAM_COMBINATIONS}; do + IMAGE_IMXBOOT_TARGET="" + for target in ${IMXBOOT_TARGETS}; do + # Use first "target" as IMAGE_IMXBOOT_TARGET + if [ "$IMAGE_IMXBOOT_TARGET" = "" ]; then + IMAGE_IMXBOOT_TARGET="$target" + echo "Set boot target as $IMAGE_IMXBOOT_TARGET" + fi + install -m 0644 ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} ${DEPLOYDIR} + done + cd ${DEPLOYDIR} + ln -sf ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${IMAGE_IMXBOOT_TARGET} ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin + # Link to default bootable U-Boot filename. It gets overwritten + # on every loop so the only last RAM_CONFIG will survive. + ln -sf ${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${IMAGE_IMXBOOT_TARGET} ${BOOTABLE_FILENAME} + cd - + done + fi + } -COMPATIBLE_MACHINE = "(ccimx8x)" +COMPATIBLE_MACHINE = "(ccimx8x|ccimx8mn)" diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend index 0782c7f6a..110a95c8e 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend @@ -1,5 +1,5 @@ # Copyright (C) 2018,2019 Digi International, Inc. # Use the v4.14 ga BSP branch -SRCBRANCH = "imx_4.14.98_2.1.0" -SRCREV = "abd6ce551a7b81fc6953d32d92b24a4a1d4b214e" +SRCBRANCH = "imx_4.14.98_2.2.0" +SRCREV = "c00cd78d2e80178171d2d7f8d0d1ce6e2ea41ac5" diff --git a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc index b3acff935..83a50c979 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc @@ -179,3 +179,30 @@ do_deploy_append_ccimx8x() { mv ${DEPLOYDIR}/u-boot* ${DEPLOYDIR}/${BOOT_TOOLS}/ mv ${DEPLOYDIR}/${UBOOT_SYMLINK}-* ${DEPLOYDIR}/${BOOT_TOOLS}/ } + +do_deploy_append_ccimx8mn() { + # Move all U-Boot artifacts to the imx-boot-tools folder + # U-Boot images are not bootable on the i.MX8M + install -d ${DEPLOYDIR}/${BOOT_TOOLS} + mv ${DEPLOYDIR}/u-boot-spl* ${DEPLOYDIR}/${BOOT_TOOLS}/ + + # Deploy the mkimage, u-boot-nodtb.bin and ccimx8mn-dvk.dtb for mkimage to generate boot binary + if [ -n "${UBOOT_CONFIG}" ] + then + for config in ${UBOOT_MACHINE}; do + i=$(expr $i + 1); + for type in ${UBOOT_CONFIG}; do + j=$(expr $j + 1); + if [ $j -eq $i ] + then + install -d ${DEPLOYDIR}/${BOOT_TOOLS} + install -m 0777 ${B}/${config}/arch/arm/dts/${UBOOT_DTB_NAME} ${DEPLOYDIR}/${BOOT_TOOLS} + install -m 0777 ${B}/${config}/tools/mkimage ${DEPLOYDIR}/${BOOT_TOOLS}/mkimage_uboot + install -m 0777 ${B}/${config}/u-boot-nodtb.bin ${DEPLOYDIR}/${BOOT_TOOLS}/u-boot-nodtb.bin-${MACHINE}-${UBOOT_CONFIG} + fi + done + unset j + done + unset i + fi +} From 41156ef05fa6a2cbed7022c870f4d25641788907 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 27 Dec 2019 10:39:00 +0100 Subject: [PATCH 067/120] imx-atf: Disable Cortex-M7 debug console The Cortex-M7 uses the UART4 as debug console, and it is shared with the Cortex-A53. This commit disables it for the ConnectCore 8M Nano DVK board to avoid conflicts. Signed-off-by: Arturo Buzarra --- ...0001-imx8mn-Disable-M7-debug-console.patch | 32 +++++++++++++++++++ .../recipes-bsp/imx-atf/imx-atf_2.0.bb | 2 ++ 2 files changed, 34 insertions(+) create mode 100644 meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0001-imx8mn-Disable-M7-debug-console.patch diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0001-imx8mn-Disable-M7-debug-console.patch b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0001-imx8mn-Disable-M7-debug-console.patch new file mode 100644 index 000000000..c492f8758 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0001-imx8mn-Disable-M7-debug-console.patch @@ -0,0 +1,32 @@ +From: Arturo Buzarra +Date: Fri, 27 Dec 2019 09:42:48 +0100 +Subject: [PATCH] imx8mn: Disable M7 debug console + +The Cortex-M7 uses the UART4 as debug console, and it is +shared with the Cortex-A53. + +Signed-off-by: Arturo Buzarra +--- + plat/imx/imx8mn/imx8mn_bl31_setup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/plat/imx/imx8mn/imx8mn_bl31_setup.c b/plat/imx/imx8mn/imx8mn_bl31_setup.c +index 57db28a..a36c2d5 100644 +--- a/plat/imx/imx8mn/imx8mn_bl31_setup.c ++++ b/plat/imx/imx8mn/imx8mn_bl31_setup.c +@@ -242,11 +242,12 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + #endif + bl31_tzc380_setup(); + + /* Assign M7 to domain 1 */ + mmio_write_32(IMX_RDC_BASE + 0x204, 0x1); +- mmio_write_32(IMX_RDC_BASE + 0x518, 0xfc); ++ /* Uncomment to use the M7 debug console (shared with A53 UART4) */ ++ /*mmio_write_32(IMX_RDC_BASE + 0x518, 0xfc);*/ + mmio_write_32(IMX_RDC_BASE + 0x5A4, 0xf3); + } + + void bl31_plat_arch_setup(void) + { +-- + diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb index 0e1b49156..2d66351bf 100644 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb @@ -15,6 +15,8 @@ SRCBRANCH = "imx_4.14.98_2.2.0" SRC_URI = "${ATF_SRC};branch=${SRCBRANCH}" SRCREV = "1355c5d12d75c9c7bdd08826796096bab519b3d5" +SRC_URI_append_ccimx8mn = " file://0001-imx8mn-Disable-M7-debug-console.patch" + S = "${WORKDIR}/git" BOOT_TOOLS = "imx-boot-tools" From 1fb65f0864899f80ead38458739936f65102baa8 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 30 Dec 2019 16:49:56 +0100 Subject: [PATCH 068/120] qtbase: apply imxgpu2d patches to imx8mn platforms as well The .bbappend file in meta-freescale only applies these patches to platforms with imxqpu2d, but they are necessary to build framebuffer images for the ccimx8mn. Using the same approach as NXP in meta-fsl-bsp-release (applying the patches to imxgpu platforms) duplicates the patches for platforms that are both imxgpu and imxgpu2d, so append them for imx8mn platforms exclusively. While at it, remove a patch that is no longer necessary, since the latest versions of qtbase already have the patch's change in them. Signed-off-by: Gabriel Valcazar --- meta-digi-dey/recipes-qt/qt5/qtbase_%.bbappend | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/meta-digi-dey/recipes-qt/qt5/qtbase_%.bbappend b/meta-digi-dey/recipes-qt/qt5/qtbase_%.bbappend index 8b78e6616..3e243fdf1 100644 --- a/meta-digi-dey/recipes-qt/qt5/qtbase_%.bbappend +++ b/meta-digi-dey/recipes-qt/qt5/qtbase_%.bbappend @@ -8,6 +8,17 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" SRC_URI_append = " file://qt5.sh" +# Technically, we should add the following patches to imxgpu platforms, but +# doing so duplicates them for imxgpu2d platforms and causes build errors. +# As of now, the only SoC that is imxgpu and not imxgpu2d is the i.MX8MN, so +# append the patches to that SoC only. +SRC_URI_append_mx8mn = " \ + file://0014-Add-IMX-GPU-support.patch \ + file://0001-egl.prf-Fix-build-error-when-egl-headers-need-platfo.patch \ +" + +SRC_URI_remove_imxgpu3d = "file://0016-Configure-eglfs-with-egl-pkg-config.patch" + PACKAGECONFIG_GL_imxpxp = "gles2" PACKAGECONFIG_GL_imxgpu2d = "${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'gl', '', d)}" PACKAGECONFIG_GL_imxgpu3d = "gles2" From 28f07acf99a157f0e7aeb51bd70b2b652f486d26 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 30 Dec 2019 16:56:55 +0100 Subject: [PATCH 069/120] imx-gpu-viv-v6: remove kernel-module-imx-gpu-viv dependency This dependency was originally removed in commit eafa8684a3ccdbad39a3fcf8cf0b6d6d79d11c5c, but it was erroneously put back in commit 793e901678bb68f289a951be1d2e1a0f7d8face9 when updating the recipe using the one in meta-fsl-bsp-release as reference. Instead of removing the line containing the dependency, in order to avoid the same situation from happening in the future, comment it out and add an explanation about why we're removing it. Signed-off-by: Gabriel Valcazar --- meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv-v6.inc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv-v6.inc b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv-v6.inc index 9b00659b6..849648aa3 100644 --- a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv-v6.inc +++ b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv-v6.inc @@ -300,7 +300,9 @@ FILES_libegl-imx-dev = "${includedir}/EGL ${includedir}/KHR ${libdir}/pkgconfig/ FILES_libgal-imx = "${libdir}/libGAL${SOLIBS} ${libdir}/libGAL_egl${SOLIBS}" FILES_libgal-imx-dev = "${libdir}/libGAL${SOLIBSDEV} ${includedir}/HAL" -RDEPENDS_libgal-imx += "kernel-module-imx-gpu-viv" +# Digi custom change: we include the imx-gpu-viv driver as built-in in the +# kernel, so this dependency isn't necessary +#RDEPENDS_libgal-imx += "kernel-module-imx-gpu-viv" RPROVIDES_libgal-imx += "libgal-imx" INSANE_SKIP_libgal-imx += "build-deps" From 6974e3fd93b2643992de8df0f1d02b924ade48a5 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 18:44:45 +0100 Subject: [PATCH 070/120] build.sh: move downloads folder outside of the projects If we want to share the downloads folder between projects we need to move it outside to don't remove it. Signed-off-by: Arturo Buzarra --- sdk/build.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sdk/build.sh b/sdk/build.sh index 835129d7b..f0fa9e6a8 100755 --- a/sdk/build.sh +++ b/sdk/build.sh @@ -184,6 +184,7 @@ _EOF_ YOCTO_IMGS_DIR="${WORKSPACE}/images" YOCTO_INST_DIR="${WORKSPACE}/digi-yocto-sdk.$(echo ${DY_REVISION} | tr '/' '_')" +YOCTO_DOWNLOAD_DIR="${WORKSPACE}/downloads" YOCTO_PROJ_DIR="${WORKSPACE}/projects" CPUS="$(grep -c processor /proc/cpuinfo)" @@ -212,8 +213,16 @@ if pushd ${YOCTO_INST_DIR}; then popd fi -# Create projects and build +# Clean downloads directory +if [ "${DY_RM_DOWNLOADS}" = "true" ]; then + printf "\n[INFO] Removing the downloads folder.\n" + rm -rf ${YOCTO_DOWNLOAD_DIR} +fi + +# Clean images and projects folders rm -rf ${YOCTO_IMGS_DIR} ${YOCTO_PROJ_DIR} + +# Create projects and build for platform in ${DY_PLATFORMS}; do # The variables _var|tgt got their dashes converted to # underscores, so we must convert also the ones in ${platform}. @@ -236,7 +245,7 @@ for platform in ${DY_PLATFORMS}; do export TEMPLATECONF="${TEMPLATECONF:+${TEMPLATECONF}/${platform}}" MKP_PAGER="" . ${YOCTO_INST_DIR}/mkproject.sh -p ${platform} ${MACHINES_LAYER} ${_this_var_arg} <<< "y" # Set a common DL_DIR and SSTATE_DIR for all platforms - sed -i -e "/^#DL_DIR ?=/cDL_DIR ?= \"${YOCTO_PROJ_DIR}/downloads\"" \ + sed -i -e "/^#DL_DIR ?=/cDL_DIR ?= \"${YOCTO_DOWNLOAD_DIR}\"" \ -e "/^#SSTATE_DIR ?=/cSSTATE_DIR ?= \"${YOCTO_PROJ_DIR}/sstate-cache\"" \ conf/local.conf # Set the DISTRO and remove 'meta-digi-dey' layer if distro is not DEY based From cdd1ca5ce7feb4fcef1fd44fe125bfa360beb75b Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 9 Jan 2020 18:45:22 +0100 Subject: [PATCH 071/120] build.sh: show local.conf information on build time Signed-off-by: Arturo Buzarra --- sdk/build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/build.sh b/sdk/build.sh index f0fa9e6a8..de92967ce 100755 --- a/sdk/build.sh +++ b/sdk/build.sh @@ -273,6 +273,9 @@ for platform in ${DY_PLATFORMS}; do if [ "${DY_MFG_IMAGE}" = "true" ] && ! grep -qs "meta-digi-mfg" conf/bblayers.conf; then sed -i -e "/meta-digi-dey/a\ ${YOCTO_INST_DIR}/sources/meta-digi-mfg \\\\" conf/bblayers.conf fi + printf "\n[INFO] Show customized local.conf.\n" + cat conf/local.conf + for target in ${platform_targets}; do printf "\n[INFO] Building the ${target} target.\n" time bitbake ${target} $(swu_recipe_name ${target}) From b7b7d0110b440eb9af9488cff36eb75010897e7c Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 7 Jan 2020 16:07:11 +0100 Subject: [PATCH 072/120] imx-atf: add patch to fix the ccimx8mn hanging on suspend/resume The LPDDR4 retention code is executed as part of the suspend/resume process. When resuming, this code writes to a register that doesn't exist on the i.MX8MN, causing the system to freeze before control is returned to Linux. Add a patch that introduces a compile-time check for the SoC type to avoid performing the write operation on the i.MX8MN. https://jira.digi.com/browse/DEL-6914 Signed-off-by: Gabriel Valcazar --- ...e-the-lpddr4-retention-flow-for-imx8.patch | 26 +++++++++++++++++++ .../recipes-bsp/imx-atf/imx-atf_2.0.bb | 5 +++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch new file mode 100644 index 000000000..df11dbefc --- /dev/null +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch @@ -0,0 +1,26 @@ +From: Jacky Bai +Date: Wed, 23 Oct 2019 13:44:28 +0800 +Subject: [PATCH] plat: imx8m: update the lpddr4 retention flow for imx8mn + +for i.MX8MN, it can only support 16bit DDR, so +it is not necessary to config the DDR_SS_GPR register. + +Signed-off-by: Jacky Bai +--- + plat/imx/common/imx8m/lpddr4_retention.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/plat/imx/common/imx8m/lpddr4_retention.c b/plat/imx/common/imx8m/lpddr4_retention.c +index 8cc44c8..dbec3d5 100644 +--- a/plat/imx/common/imx8m/lpddr4_retention.c ++++ b/plat/imx/common/imx8m/lpddr4_retention.c +@@ -184,7 +184,9 @@ void lpddr4_exit_retention(void) + + /* before write Dynamic reg, sw_done should be 0 */ + mmio_write_32(DDRC_SWCTL(0), 0x00000000); ++#if !defined(PLAT_imx8mn) + mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */ ++#endif + mmio_write_32(DDRC_DFIMISC(0), 0x00000000); + + /* dram phy re-init */ diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb index 2d66351bf..4eceeb7bd 100644 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb @@ -15,7 +15,10 @@ SRCBRANCH = "imx_4.14.98_2.2.0" SRC_URI = "${ATF_SRC};branch=${SRCBRANCH}" SRCREV = "1355c5d12d75c9c7bdd08826796096bab519b3d5" -SRC_URI_append_ccimx8mn = " file://0001-imx8mn-Disable-M7-debug-console.patch" +SRC_URI_append_ccimx8mn = " \ + file://0001-imx8mn-Disable-M7-debug-console.patch \ + file://0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch \ +" S = "${WORKDIR}/git" From 400110aaf9d15af3525506c51443224164230b5d Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 10 Jan 2020 08:48:11 +0100 Subject: [PATCH 073/120] modemmanager: remove support to serial XBee cellular devices Serial support to XBee cellular devices is deprecated since the recommended communication protocol is USB, so we remove the udev rules that supported these devices. Signed-off-by: Arturo Buzarra --- .../ccimx6/78-mm-digi-xbee-cellular.rules | 11 ----------- .../ccimx6ul/78-mm-digi-xbee-cellular.rules | 11 ----------- .../ccimx8mn/78-mm-digi-xbee-cellular.rules | 10 ---------- .../78-mm-digi-xbee-cellular.rules | 10 ---------- .../ccimx8x-sbc-pro/78-mm-digi-xbee-cellular.rules | 10 ---------- .../modemmanager/modemmanager_%.bbappend | 6 +----- 6 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6/78-mm-digi-xbee-cellular.rules delete mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6ul/78-mm-digi-xbee-cellular.rules delete mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules delete mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-express/78-mm-digi-xbee-cellular.rules delete mode 100644 meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-pro/78-mm-digi-xbee-cellular.rules diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6/78-mm-digi-xbee-cellular.rules deleted file mode 100644 index 9f999dd1c..000000000 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6/78-mm-digi-xbee-cellular.rules +++ /dev/null @@ -1,11 +0,0 @@ -ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" - -# By default, ModemManager expects a default baudrate of 57600bps. Different -# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. - -# ModemManager documentation states that the best practice is to use the DEVPATH -# this way rather than other rules such as KERNEL, so be careful when modifying -DEVPATH=="/devices/soc0/soc.0/2100000.aips-bus/21f4000.serial/tty/ttymxc4", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" -DEVPATH=="/devices/soc0/soc/2100000.aips-bus/21f4000.serial/tty/ttymxc4", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" - -LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6ul/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6ul/78-mm-digi-xbee-cellular.rules deleted file mode 100644 index 31fbcc68e..000000000 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx6ul/78-mm-digi-xbee-cellular.rules +++ /dev/null @@ -1,11 +0,0 @@ -ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" - -# By default, ModemManager expects a default baudrate of 57600bps. Different -# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. - -# ModemManager documentation states that the best practice is to use the DEVPATH -# this way rather than other rules such as KERNEL, so be careful when modifying -DEVPATH=="/devices/platform/soc/2100000.aips-bus/21e8000.serial/tty/ttymxc1", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" -DEVPATH=="/devices/soc0/soc/2100000.aips-bus/21e8000.serial/tty/ttymxc1", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" - -LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules deleted file mode 100644 index f4b484c18..000000000 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/78-mm-digi-xbee-cellular.rules +++ /dev/null @@ -1,10 +0,0 @@ -ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" - -# By default, ModemManager expects a default baudrate of 57600bps. Different -# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. - -# ModemManager documentation states that the best practice is to use the DEVPATH -# this way rather than other rules such as KERNEL, so be careful when modifying -DEVPATH=="/devices/platform/30a60000.serial/tty/ttymxc3", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" - -LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-express/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-express/78-mm-digi-xbee-cellular.rules deleted file mode 100644 index 9ab0f5998..000000000 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-express/78-mm-digi-xbee-cellular.rules +++ /dev/null @@ -1,10 +0,0 @@ -ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" - -# By default, ModemManager expects a default baudrate of 57600bps. Different -# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. - -# ModemManager documentation states that the best practice is to use the DEVPATH -# this way rather than other rules such as KERNEL, so be careful when modifying -DEVPATH=="/devices/platform/5a060000.serial/tty/ttyLP0", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" - -LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-pro/78-mm-digi-xbee-cellular.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-pro/78-mm-digi-xbee-cellular.rules deleted file mode 100644 index b7fa7fab3..000000000 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8x-sbc-pro/78-mm-digi-xbee-cellular.rules +++ /dev/null @@ -1,10 +0,0 @@ -ACTION!="add|change|move", GOTO="mm_digi_xbee_cellular_modem_end" - -# By default, ModemManager expects a default baudrate of 57600bps. Different -# baudrates may be used by setting the ID_MM_TTY_BAUDRATE udev tag. - -# ModemManager documentation states that the best practice is to use the DEVPATH -# this way rather than other rules such as KERNEL, so be careful when modifying -DEVPATH=="/devices/platform/5a800000.i2c/i2c-0/0-0063/mca-cc8x-uart/tty/ttyMCA0", ENV{ID_MM_PLATFORM_DRIVER_PROBE}="1", ENV{ID_MM_PHYSDEV_UID}="Digi XBee Cellular" - -LABEL="mm_digi_xbee_cellular_modem_end" diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_%.bbappend b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_%.bbappend index 8469412aa..5d4bdc0e8 100644 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_%.bbappend @@ -3,7 +3,6 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI += " \ - file://78-mm-digi-xbee-cellular.rules \ file://80-mm-net-device-blacklist.rules \ file://late-modems-scan.service \ file://late-modems-scan.timer \ @@ -15,11 +14,8 @@ SRC_URI += " \ PACKAGECONFIG_remove = " polkit" do_install_append() { - # Install udev rules for XBee cellular - install -d ${D}${nonarch_base_libdir}/udev/rules.d - install -m 0644 ${WORKDIR}/78-mm-digi-xbee-cellular.rules ${D}${nonarch_base_libdir}/udev/rules.d/ - # Install udev rules for ModemManager blacklist devices + install -d ${D}${nonarch_base_libdir}/udev/rules.d install -m 0644 ${WORKDIR}/80-mm-net-device-blacklist.rules ${D}${nonarch_base_libdir}/udev/rules.d/ # Install systemd service for scanning late modems From 9f889c587fe3b4d031e5d257c2ce1f17a9be8dce Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Fri, 10 Jan 2020 09:22:38 +0100 Subject: [PATCH 074/120] gstreamer: change machine override for plugins to 'imxgpu' Some architectures like i.MX8M Nano don't have imxgpu2d but still need some of the Gstreamer plugins. For example, gstreamer1.0-plugins-bad-meta provides the xwayland sink which would otherwise not be available for platforms without gpu2d. Signed-off-by: Hector Palacios --- .../packagegroups/packagegroup-dey-gstreamer.bb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-multimedia/packagegroups/packagegroup-dey-gstreamer.bb b/meta-digi-dey/recipes-multimedia/packagegroups/packagegroup-dey-gstreamer.bb index 7eb4206dc..29ab48764 100644 --- a/meta-digi-dey/recipes-multimedia/packagegroups/packagegroup-dey-gstreamer.bb +++ b/meta-digi-dey/recipes-multimedia/packagegroups/packagegroup-dey-gstreamer.bb @@ -30,7 +30,7 @@ MACHINE_GSTREAMER_1_0_PKGS_ccimx6ul = " \ " MACHINE_GSTREAMER_1_0_EXTRA_INSTALL ?= "" -MACHINE_GSTREAMER_1_0_EXTRA_INSTALL_imxgpu2d ?= " \ +MACHINE_GSTREAMER_1_0_EXTRA_INSTALL_imxgpu ?= " \ gstreamer1.0-plugins-bad-meta \ gstreamer1.0-plugins-ugly-meta \ gstreamer1.0-rtsp-server-meta \ From f276827fd89f696488adc5a20362d99e53e4506b Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Fri, 10 Jan 2020 12:23:18 +0100 Subject: [PATCH 075/120] gstreamer: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.2.0 Update SRCBRANCH in most recipes and SRCREV for gstreamer1.0-plugins-good. update imx-gst1.0-plugin to v4.5.0. Signed-off-by: Gabriel Valcazar --- .../gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb | 2 +- .../gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb | 2 +- .../gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb | 4 ++-- .../recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb | 2 +- ...{imx-gst1.0-plugin_4.4.7.bb => imx-gst1.0-plugin_4.5.0.bb} | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) rename meta-digi-dey/recipes-multimedia/gstreamer/{imx-gst1.0-plugin_4.4.7.bb => imx-gst1.0-plugin_4.5.0.bb} (97%) diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb index faf07b248..3a02bb05b 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb @@ -41,7 +41,7 @@ SRC_URI_remove = "file://0001-Prepend-PKG_CONFIG_SYSROOT_DIR-to-pkg-config-outpu EXTRA_OECONF_remove = "WAYLAND_PROTOCOLS_SYSROOT_DIR=${RECIPE_SYSROOT}" GST1.0-PLUGINS-BAD_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-bad.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.00_1908_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-BAD_SRC};branch=${SRCBRANCH} \ diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb index 2f5f47aed..b7deda83a 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb @@ -24,7 +24,7 @@ PACKAGECONFIG[gio-unix-2.0] = "" EXTRA_OECONF_append = " --disable-opengl --enable-wayland" GST1.0-PLUGINS-BASE_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-base.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.00_1908_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-BASE_SRC};branch=${SRCBRANCH} \ diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb index 1b9c35857..f3bbf7bf5 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb @@ -8,12 +8,12 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343 \ DEPENDS += "libdrm" GST1.0-PLUGINS-GOOD_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-good.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.00_1908_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-GOOD_SRC};branch=${SRCBRANCH} \ " -SRCREV = "36d46a8a9a7dcf173f9a0a0145b6cfa44f879670" +SRCREV = "6aa0b5632a610ea09278624826fb312db9f7b1b9" EXTRA_AUTORECONF = "" PACKAGECONFIG_append = " vpx" diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb index 6369454f2..b8b17d054 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6762ed442b3822387a51c92d928ead0d \ # Use i.MX fork of GST for customizations GST1.0_SRC ?= "gitsm://source.codeaurora.org/external/imx/gstreamer.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.00_1908_L4.14.98" SRC_URI = " ${GST1.0_SRC};branch=${SRCBRANCH}" SRCREV = "d42548da09724ad8cc1aa4f1944607920be2f4c0" diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.4.7.bb b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb similarity index 97% rename from meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.4.7.bb rename to meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb index 42f4a959e..efec52a32 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.4.7.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb @@ -21,12 +21,12 @@ LIC_FILES_CHKSUM = "file://COPYING-LGPL-2;md5=5f30f0716dfdd0d91eb439ebec522ec2 \ file://COPYING-LGPL-2.1;md5=fbc093901857fcd118f065f900982c24" IMXGST_SRC ?= "git://source.codeaurora.org/external/imx/imx-gst1.0-plugin.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.00_1908_L4.14.98" SRC_URI = "${IMXGST_SRC};branch=${SRCBRANCH} \ file://0001-imx-gst1.0-plugin-Update-KERNEL_VERSION-check.patch \ " -SRCREV = "aeebe91727c3228723015cd3086c449ea23e1a5d" +SRCREV = "516d7ac1d7b129adc37645403887079e6cdfc7a3" S = "${WORKDIR}/git" From c959a88393bb28c36fbb8a75f7e11299b0fd5d98 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Wed, 15 Jan 2020 18:05:48 +0100 Subject: [PATCH 076/120] udev-extraconf: create /dev/ttyXBee symlink to XBee uart https://jira.digi.com/browse/DEL-6903 Signed-off-by: Javier Viguera --- meta-digi-arm/conf/machine/ccimx6qpsbc.conf | 3 +++ meta-digi-arm/conf/machine/ccimx6sbc.conf | 3 +++ meta-digi-arm/conf/machine/ccimx6ulsbc.conf | 3 +++ meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 1 + meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf | 1 + .../recipes-core/udev/udev-extraconf_1.1.bbappend | 8 ++++++++ 6 files changed, 19 insertions(+) diff --git a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf index e49bc3ff9..c033e6f50 100644 --- a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf @@ -44,6 +44,9 @@ BT_DEVICE_NAME ?= "cc6qp" # Bluetooth tty BT_TTY ?= "ttymxc1" +# XBee +XBEE_TTY ?= "ttymxc4" + # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" diff --git a/meta-digi-arm/conf/machine/ccimx6sbc.conf b/meta-digi-arm/conf/machine/ccimx6sbc.conf index 66237eac9..ea98b6b24 100644 --- a/meta-digi-arm/conf/machine/ccimx6sbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6sbc.conf @@ -46,6 +46,9 @@ BT_DEVICE_NAME ?= "cc6" # Bluetooth tty BT_TTY ?= "ttymxc1" +# XBee +XBEE_TTY ?= "ttymxc4" + # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" diff --git a/meta-digi-arm/conf/machine/ccimx6ulsbc.conf b/meta-digi-arm/conf/machine/ccimx6ulsbc.conf index 9df9a23d7..f633e8cd8 100644 --- a/meta-digi-arm/conf/machine/ccimx6ulsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6ulsbc.conf @@ -35,6 +35,9 @@ SERIAL_CONSOLES ?= "115200;ttymxc4" # Bluetooth tty BT_TTY ?= "ttymxc0" +# XBee +XBEE_TTY ?= "ttymxc1" + # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf index 7850be6ba..2b2706544 100644 --- a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -27,6 +27,7 @@ BT_TTY ?= "ttymxc1" # XBee2 XBEE_RESET_N_GPIO ?= "8" XBEE_SLEEP_RQ_GPIO ?= "7" +XBEE_TTY ?= "ttymxc3" # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf index 875384504..76b687507 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf @@ -28,6 +28,7 @@ BT_TTY ?= "ttyLP1" # XBee XBEE_RESET_N_GPIO ?= "220" XBEE_SLEEP_RQ_GPIO ?= "216" +XBEE_TTY ?= "ttyMCA0" # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" diff --git a/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend b/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend index 2657a90d9..caa40f64f 100644 --- a/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend +++ b/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend @@ -22,6 +22,14 @@ do_install_append() { >> ${D}${sysconfdir}/udev/rules.d/localextra.rules fi + # XBee TTY symlink + if [ -n "${XBEE_TTY}" ]; then + printf "%s\n%s\n" \ + "# Symlink to the XBee tty" \ + "KERNEL==\"${XBEE_TTY}\", MODE=\"0660\", GROUP=\"tty\", SYMLINK+=\"ttyXBee\"" \ + >> ${D}${sysconfdir}/udev/rules.d/localextra.rules + fi + install -d ${D}${sysconfdir}/modprobe.d install -m 0644 ${WORKDIR}/blacklist.conf ${D}${sysconfdir}/modprobe.d } From 44487faf6c42713ab351306d0c58385da290cb96 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 13:21:04 +0100 Subject: [PATCH 077/120] fsl-eula-unpack: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update the license file checksum https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- meta-digi-arm/classes/fsl-eula-unpack.bbclass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-arm/classes/fsl-eula-unpack.bbclass b/meta-digi-arm/classes/fsl-eula-unpack.bbclass index e33ed07c9..588fd3db9 100644 --- a/meta-digi-arm/classes/fsl-eula-unpack.bbclass +++ b/meta-digi-arm/classes/fsl-eula-unpack.bbclass @@ -6,7 +6,7 @@ # # SRC_URI = "${FSL_MIRROR}/firmware-imx-${PV};fsl-eula=true" -LIC_FILES_CHKSUM_append = " file://${FSL_EULA_FILE};md5=72c0f70181bb6e83eee6aab8de12a9f3" +LIC_FILES_CHKSUM_append = " file://${FSL_EULA_FILE};md5=fd4b227530cd88a82af6a5982cfb724d" LIC_FILES_CHKSUM[vardepsexclude] += "FSL_EULA_FILE" From acdcaf5a4546861d3c6953a991502c3fc424b594 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 13:22:37 +0100 Subject: [PATCH 078/120] imx-digi-base: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update the values of the MACHINE_SOCARCH_FILTER variable with the ones in meta-fsl-bsp-release's imx-base.inc. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../conf/machine/include/imx-digi-base.inc | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/meta-digi-arm/conf/machine/include/imx-digi-base.inc b/meta-digi-arm/conf/machine/include/imx-digi-base.inc index a3d181250..1423e092e 100644 --- a/meta-digi-arm/conf/machine/include/imx-digi-base.inc +++ b/meta-digi-arm/conf/machine/include/imx-digi-base.inc @@ -41,14 +41,40 @@ MACHINE_SOCARCH_SUFFIX_mx8dx = "-mx8dx" MACHINE_SOCARCH_SUFFIX_mx8mn = "-mx8mn" MACHINE_ARCH_FILTER = "virtual/kernel" -MACHINE_SOCARCH_FILTER_append_imxvpu = " imx-vpu libimxvpuapi imx-codec imx-vpuwrap imx-parser" -MACHINE_SOCARCH_FILTER_append_imxgpu2d = " virtual/libopenvg virtual/libgles1 virtual/libgles2 virtual/egl virtual/mesa virtual/libgl virtual/libg2d cairo pango" -MACHINE_SOCARCH_FILTER_append_imxpxp = " imx-codec imx-parser" +MACHINE_SOCARCH_FILTER_append_imxvpu = " \ + imx-codec \ + imx-vpu \ + imx-vpuwrap \ + libimxvpuapi \ +" +MACHINE_SOCARCH_FILTER_append_imxgpu = " \ + virtual/egl \ + virtual/mesa \ + virtual/libg2d \ + libgal-imx \ + virtual/libopenvg \ + cairo \ + opencv \ + pango \ +" + +MACHINE_SOCARCH_FILTER_append_imxgpu3d = " \ + virtual/libgl \ + virtual/libgles1 \ + virtual/libgles2 \ +" +MACHINE_SOCARCH_FILTER_append_mx6q = " \ + virtual/opencl-icd \ + opencl-headers \ +" MACHINE_SOCARCH_FILTER_append_mx8 = " \ virtual/libopenvx \ virtual/opencl-icd \ opencl-headers \ " +MACHINE_SOCARCH_FILTER_append_imxpxp = " \ + imx-codec \ +" INHERIT += "fsl-dynamic-packagearch" From 530d9c0e9734c5d4295ac0183f0a7b2978ac5b2e Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 13:25:12 +0100 Subject: [PATCH 079/120] firmware-imx: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v8.4.1. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../{firmware-imx_8.4.bb => firmware-imx_8.4.1.bb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename meta-digi-arm/recipes-bsp/firmware-imx/{firmware-imx_8.4.bb => firmware-imx_8.4.1.bb} (93%) diff --git a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.1.bb similarity index 93% rename from meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb rename to meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.1.bb index 34bafa842..f9f044f8a 100644 --- a/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.bb +++ b/meta-digi-arm/recipes-bsp/firmware-imx/firmware-imx_8.4.1.bb @@ -6,14 +6,14 @@ SUMMARY = "Freescale IMX firmware" DESCRIPTION = "Freescale IMX firmware such as for the VPU" SECTION = "base" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" PE = "1" SRC_URI = "${FSL_MIRROR}/firmware-imx-${PV}.bin;fsl-eula=true " -SRC_URI[md5sum] = "d2d02f96dad4fb8350696eaa979d50e1" -SRC_URI[sha256sum] = "0bd050d5fceb7829201d33b19948b5717db106e3b676a777488c24130eba54b9" +SRC_URI[md5sum] = "70bdefdd7fb58f782237acf4c648f5cd" +SRC_URI[sha256sum] = "f04b2deb4f126e6b6cd4460462292acd72183b9f799e3b873fb390ff0f18eb55" inherit fsl-eula-unpack allarch From c6c19be947168c481672914aa80cf17b9e85ae8b Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 13:32:41 +0100 Subject: [PATCH 080/120] imx-atf: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update SRCBRANCH and SRCREV. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb index 4eceeb7bd..4f697d4e6 100644 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb @@ -10,10 +10,10 @@ inherit fsl-eula-unpack pkgconfig deploy PV = "2.0+git${SRCPV}" ATF_SRC ?= "git://source.codeaurora.org/external/imx/imx-atf.git;protocol=https" -SRCBRANCH = "imx_4.14.98_2.2.0" +SRCBRANCH = "imx_4.14.98_2.3.0" SRC_URI = "${ATF_SRC};branch=${SRCBRANCH}" -SRCREV = "1355c5d12d75c9c7bdd08826796096bab519b3d5" +SRCREV = "09c5cc994634060ad7dfef4620866838d19694a4" SRC_URI_append_ccimx8mn = " \ file://0001-imx8mn-Disable-M7-debug-console.patch \ From 47131586c0ba7d15befba2a1a25898758b0aaa1d Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 13:33:09 +0100 Subject: [PATCH 081/120] Revert "imx-atf: add patch to fix the ccimx8mn hanging on suspend/resume" The patch is no longer needed as it was merged upstream. This reverts commit b7b7d0110b440eb9af9488cff36eb75010897e7c. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- ...e-the-lpddr4-retention-flow-for-imx8.patch | 26 ------------------- .../recipes-bsp/imx-atf/imx-atf_2.0.bb | 5 +--- 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch deleted file mode 100644 index df11dbefc..000000000 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf/0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Jacky Bai -Date: Wed, 23 Oct 2019 13:44:28 +0800 -Subject: [PATCH] plat: imx8m: update the lpddr4 retention flow for imx8mn - -for i.MX8MN, it can only support 16bit DDR, so -it is not necessary to config the DDR_SS_GPR register. - -Signed-off-by: Jacky Bai ---- - plat/imx/common/imx8m/lpddr4_retention.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/plat/imx/common/imx8m/lpddr4_retention.c b/plat/imx/common/imx8m/lpddr4_retention.c -index 8cc44c8..dbec3d5 100644 ---- a/plat/imx/common/imx8m/lpddr4_retention.c -+++ b/plat/imx/common/imx8m/lpddr4_retention.c -@@ -184,7 +184,9 @@ void lpddr4_exit_retention(void) - - /* before write Dynamic reg, sw_done should be 0 */ - mmio_write_32(DDRC_SWCTL(0), 0x00000000); -+#if !defined(PLAT_imx8mn) - mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */ -+#endif - mmio_write_32(DDRC_DFIMISC(0), 0x00000000); - - /* dram phy re-init */ diff --git a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb index 4f697d4e6..b1c84b70c 100644 --- a/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb +++ b/meta-digi-arm/recipes-bsp/imx-atf/imx-atf_2.0.bb @@ -15,10 +15,7 @@ SRCBRANCH = "imx_4.14.98_2.3.0" SRC_URI = "${ATF_SRC};branch=${SRCBRANCH}" SRCREV = "09c5cc994634060ad7dfef4620866838d19694a4" -SRC_URI_append_ccimx8mn = " \ - file://0001-imx8mn-Disable-M7-debug-console.patch \ - file://0002-plat-imx8m-update-the-lpddr4-retention-flow-for-imx8.patch \ -" +SRC_URI_append_ccimx8mn = " file://0001-imx8mn-Disable-M7-debug-console.patch" S = "${WORKDIR}/git" From 23e758eb22a0c51391847b275bf511bf17aabb2e Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:05:00 +0100 Subject: [PATCH 082/120] imx-boot: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update SRCREV and SRCBRANCH, change the names of the m4 demos that are installed into imx-boot, change the name of the SECO firmware (ahab container) and update our patch so it applies over the newest revision of imx-mkimage. For the time being, use the B0 SECO firmware for all i.MX8QXP platforms and add the changes needed for C0 support in comments. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- ...C_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch | 14 +++++++------- .../imx-mkimage/imx-boot_0.2.bbappend | 18 +++++++++++++----- .../imx-mkimage/imx-mkimage_%.bbappend | 6 +++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot/0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot/0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch index d5467c928..6487ea4ca 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot/0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot/0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch @@ -17,15 +17,15 @@ Signed-off-by: Gabriel Valcazar 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iMX8QX/soc.mak b/iMX8QX/soc.mak -index 3c8e7b1..f06ece8 100755 +index e08cf3c..88f990a 100755 --- a/iMX8QX/soc.mak +++ b/iMX8QX/soc.mak -@@ -114,7 +114,7 @@ flash_linux_m4_xip: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf-co +@@ -120,7 +120,7 @@ flash_linux_m4_xip: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf-container.img m ./$(QSPI_PACKER) $(QSPI_HEADER) - flash_regression_linux_m4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_image.bin -- ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin -+ ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin + flash_regression_linux_m4: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf.bin m4_image.bin +- ./$(MKIMG) -soc QX -rev B0 -append $(AHAB_IMG) -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin ++ ./$(MKIMG) -soc QX -rev B0 -append $(AHAB_IMG) -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin - flash_regression_linux_m4_ddr: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_image.bin - ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x88000000 -out flash.bin + flash_regression_linux_m4_ddr: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf.bin m4_image.bin + ./$(MKIMG) -soc QX -rev B0 -append $(AHAB_IMG) -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x88000000 -out flash.bin diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend index 23f467b14..bee090679 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend @@ -1,4 +1,4 @@ -# Copyright 2019 Digi International, Inc. +# Copyright 2019,2020 Digi International, Inc. inherit boot-artifacts # Use the v4.14 latest BSP branch @@ -39,6 +39,12 @@ do_populate_lic[depends] += " \ ATF_MACHINE_NAME_mx8qxp = "bl31-imx8qx.bin" ATF_MACHINE_NAME_mx8mn = "bl31-imx8mn.bin" +SECO_FIRMWARE ?= "" +SECO_FIRMWARE_mx8qm = "mx8qmb0-ahab-container.img" +SECO_FIRMWARE_mx8qxp = "mx8qxb0-ahab-container.img" +# i.MX8QXP C0 support +#SECO_FIRMWARE_mx8qxp = "mx8qxc0-ahab-container.img" + # 8MQ/8MM/8MN share the same soc folder BOOT_STAGING_mx8mn = "${S}/iMX8M" @@ -51,9 +57,9 @@ IMXBOOT_TARGETS_ccimx8mn = "${@bb.utils.contains('UBOOT_CONFIG', 'fspi', 'flash_ compile_mx8x() { bbnote 8QX boot binary build - cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_srtm_demo.bin ${BOOT_STAGING}/m40_tcm.bin - cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_srtm_demo.bin ${BOOT_STAGING}/m4_image.bin - cp ${DEPLOY_DIR_IMAGE}/mx8qx-ahab-container.img ${BOOT_STAGING}/ + cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_power_mode_switch.bin ${BOOT_STAGING}/m40_tcm.bin + cp ${DEPLOY_DIR_IMAGE}/imx8qx_m4_TCM_power_mode_switch.bin ${BOOT_STAGING}/m4_image.bin + cp ${DEPLOY_DIR_IMAGE}/${SECO_FIRMWARE} ${BOOT_STAGING}/ cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/${ATF_MACHINE_NAME} ${BOOT_STAGING}/bl31.bin for type in ${UBOOT_CONFIG}; do cp ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/u-boot-${type}.bin ${BOOT_STAGING}/ @@ -94,6 +100,8 @@ do_compile () { for target in ${IMXBOOT_TARGETS}; do bbnote "building ${SOC_TARGET} - ${ramc} - ${target}" make SOC=${SOC_TARGET} ${target} + # i.MX8QXP C0 support + #make SOC=${SOC_TARGET} REV=C0 ${target} if [ -e "${BOOT_STAGING}/flash.bin" ]; then cp ${BOOT_STAGING}/flash.bin ${S}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin-${target} fi @@ -147,7 +155,7 @@ do_deploy () { # copy the tool mkimage to deploy path and sc fw, dcd and uboot if [ "${SOC_TARGET}" = "iMX8QX" ]; then - install -m 0644 ${BOOT_STAGING}/mx8qx-ahab-container.img ${DEPLOYDIR}/${BOOT_TOOLS} + install -m 0644 ${BOOT_STAGING}/${SECO_FIRMWARE} ${DEPLOYDIR}/${BOOT_TOOLS} install -m 0644 ${BOOT_STAGING}/m40_tcm.bin ${DEPLOYDIR}/${BOOT_TOOLS} install -m 0644 ${BOOT_STAGING}/m4_image.bin ${DEPLOYDIR}/${BOOT_TOOLS} fi diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend index 110a95c8e..079e27b22 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-mkimage_%.bbappend @@ -1,5 +1,5 @@ -# Copyright (C) 2018,2019 Digi International, Inc. +# Copyright (C) 2018-2020 Digi International, Inc. # Use the v4.14 ga BSP branch -SRCBRANCH = "imx_4.14.98_2.2.0" -SRCREV = "c00cd78d2e80178171d2d7f8d0d1ce6e2ea41ac5" +SRCBRANCH = "imx_4.14.98_2.3.0" +SRCREV = "2556000499f667123094af22326cfd8e4cbadaac" From a0b70c3ca94eca682208ee97fcbcaded67c87c16 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:14:55 +0100 Subject: [PATCH 083/120] imx-seco: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v2.5.4 and add new recipe imx-seco-libs. For the time being, use the B0 firmware for all i.MX8QXP platforms and leave C0 support in a comment. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../recipes-bsp/imx-seco/imx-seco-libs_git.bb | 24 +++++++++++++++++++ .../{imx-seco_2.3.1.bb => imx-seco_2.5.4.bb} | 14 ++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/imx-seco/imx-seco-libs_git.bb rename meta-digi-arm/recipes-bsp/imx-seco/{imx-seco_2.3.1.bb => imx-seco_2.5.4.bb} (51%) diff --git a/meta-digi-arm/recipes-bsp/imx-seco/imx-seco-libs_git.bb b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco-libs_git.bb new file mode 100644 index 000000000..1a9d4417e --- /dev/null +++ b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco-libs_git.bb @@ -0,0 +1,24 @@ +# Copyright 2019 NXP + +SUMMARY = "NXP i.MX SECO library" +DESCRIPTION = "NXP IMX SECO library" +SECTION = "base" +LICENSE = "Proprietary" +LIC_FILES_CHKSUM = "file://LA_OPT_NXP_Software_License.htm;md5=6a8fcab25f3d3f5c2898456114b91f44" + +DEPENDS = "zlib" + +SRCBRANCH = "master" +SECO_LIB_SRC ?= "git://github.com/NXP/imx-seco-libs.git;protocol=https" +SRC_URI = "${SECO_LIB_SRC};branch=${SRCBRANCH}" +SRCREV = "1afb4e66ba26cc723bd5bf96eb2e79a6c81daa70" + +S = "${WORKDIR}/git" + +TARGET_CC_ARCH += "${LDFLAGS}" + +do_install () { + oe_runmake DESTDIR=${D} install +} + +COMPATIBLE_MACHINE = "(mx8qm|mx8qxp)" diff --git a/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.5.4.bb similarity index 51% rename from meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb rename to meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.5.4.bb index bedaa7d2b..9b3b2684a 100644 --- a/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.3.1.bb +++ b/meta-digi-arm/recipes-bsp/imx-seco/imx-seco_2.5.4.bb @@ -4,22 +4,24 @@ SUMMARY = "NXP i.MX SECO firmware" DESCRIPTION = "NXP IMX SECO firmware" SECTION = "base" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=fb0303e4ee8b0e71c094171e2272bd44" +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" inherit fsl-eula-unpack deploy SRC_URI = "${FSL_MIRROR}/${PN}-${PV}.bin;fsl-eula=true " -SRC_URI[md5sum] = "cf8d6bbf93f0aa6e1049f1098a0f7e0f" -SRC_URI[sha256sum] = "b429ac58b2ea1771b3fdf7ae87bf1d37ccaf596bde01a5ecccae27b2145f6824" +SRC_URI[md5sum] = "52f71d8965e99cd162a91a326e2e5dd8" +SRC_URI[sha256sum] = "552076de1dfcf880bf1ccf208ad646dee0f32454bf4f620f71b8699c95ccb96e" do_compile[noexec] = "1" do_install[noexec] = "1" -SECO_FIRMWARE_NAME ?= "mx8qm-ahab-container.img" -SECO_FIRMWARE_NAME_mx8qm = "mx8qm-ahab-container.img" -SECO_FIRMWARE_NAME_mx8qxp = "mx8qx-ahab-container.img" +SECO_FIRMWARE_NAME ?= "mx8qmb0-ahab-container.img" +SECO_FIRMWARE_NAME_mx8qm = "mx8qmb0-ahab-container.img" +SECO_FIRMWARE_NAME_mx8qxp = "mx8qxb0-ahab-container.img" +# i.MX8QXP C0 support +#SECO_FIRMWARE_NAME_mx8qxp = "mx8qxc0-ahab-container.img" addtask deploy after do_install do_deploy () { From 2f3420ee435286009269c9b21a3c7791ded8c44d Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:19:40 +0100 Subject: [PATCH 084/120] imx-dpu-g2d: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v1.7.4. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../{imx-dpu-g2d_1.7.1.bb => imx-dpu-g2d_1.7.4.bb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename meta-digi-dey/recipes-graphics/imx-dpu-g2d/{imx-dpu-g2d_1.7.1.bb => imx-dpu-g2d_1.7.4.bb} (80%) diff --git a/meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.1.bb b/meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.4.bb similarity index 80% rename from meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.1.bb rename to meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.4.bb index b71eea828..f936a9a75 100644 --- a/meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.1.bb +++ b/meta-digi-dey/recipes-graphics/imx-dpu-g2d/imx-dpu-g2d_1.7.4.bb @@ -4,7 +4,7 @@ DESCRIPTION = "GPU G2D library and apps for i.MX with 2D GPU and DPU" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" RDEPENDS_${PN} = "libgal-imx libdrm" @@ -16,8 +16,8 @@ S="${WORKDIR}/${PN}-${PV}" inherit fsl-eula-unpack -SRC_URI[md5sum] = "cb59630320d91c4a11306e60a682781d" -SRC_URI[sha256sum] = "cee8b44509d15b9eb0dbf736d25c080d151602849a5e621be13e9b8f7b501f04" +SRC_URI[md5sum] = "111e89e33fe80be50ef526546c6b362b" +SRC_URI[sha256sum] = "4744a210af15c2d9ae9138c90e4ccc56138c9b03611286d781ac17d5a676c8ec" do_install () { From 2a9acc1031494f276168283aaca08e2ec1d2a684 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:24:50 +0100 Subject: [PATCH 085/120] imx-gpu: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v6.2.4.p4.6. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- ...gpu-g2d_6.2.4.p4.4.bb => imx-gpu-g2d_6.2.4.p4.6.bb} | 10 +++++----- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb | 8 -------- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb | 8 -------- .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch32.bb | 8 ++++++++ .../imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch64.bb | 8 ++++++++ 5 files changed, 21 insertions(+), 21 deletions(-) rename meta-digi-dey/recipes-graphics/imx-gpu-g2d/{imx-gpu-g2d_6.2.4.p4.4.bb => imx-gpu-g2d_6.2.4.p4.6.bb} (70%) delete mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb delete mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb create mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch32.bb create mode 100644 meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch64.bb diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb b/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.6.bb similarity index 70% rename from meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb rename to meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.6.bb index f00fe067b..c0d78dd82 100644 --- a/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.4.bb +++ b/meta-digi-dey/recipes-graphics/imx-gpu-g2d/imx-gpu-g2d_6.2.4.p4.6.bb @@ -5,7 +5,7 @@ DESCRIPTION = "GPU G2D library and apps for i.MX with 2D GPU and no DPU" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" DEPENDS += "libgal-imx" PROVIDES += "virtual/libg2d" @@ -13,10 +13,10 @@ PROVIDES += "virtual/libg2d" FSLBIN_NAME = "${PN}-${PV}-${TARGET_ARCH}" SRC_URI = "${FSL_MIRROR}/${FSLBIN_NAME}.bin;name=${TARGET_ARCH};fsl-eula=true" -SRC_URI[aarch64.md5sum] = "813675d610456050d23d13c383bfd272" -SRC_URI[aarch64.sha256sum] = "49443d34469a2464fc8d9ad412507a2da70154e79aa49803d64b23564ea61cb7" -SRC_URI[arm.md5sum] = "606909745143d7f7cb12f3f30af8946a" -SRC_URI[arm.sha256sum] = "a028fbbceb51e61662210bce7a4e50812d354bce54ba8e1d3a3af59338471ef1" +SRC_URI[aarch64.md5sum] = "a7c573ba8bea4850d60dfadead54fda8" +SRC_URI[aarch64.sha256sum] = "4964f799a4eb735689cdfd25f95ecc88140366986d8f48dfd0cf05264773d072" +SRC_URI[arm.md5sum] = "4789b83df4429ddfd649040c1c84efdc" +SRC_URI[arm.sha256sum] = "02756a63afb59f58445e9c9f08ec68cd0292b75ab7b99daad09eb06d020a7f54" S="${WORKDIR}/${FSLBIN_NAME}" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb deleted file mode 100644 index 1872bcb1d..000000000 --- a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch32.bb +++ /dev/null @@ -1,8 +0,0 @@ -require imx-gpu-viv-v6.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" - -SRC_URI[md5sum] = "6964c366e3998c60ca1dae5d3e2da33c" -SRC_URI[sha256sum] = "9cf5528a0ad8c53b2bcba236cb6861f5ef0c0c0735b3de5bab1ed0697be7b770" - -COMPATIBLE_MACHINE = "(mx6q|mx6dl|mx6sx|mx6sl|mx7ulp)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb deleted file mode 100644 index 8ea001d1f..000000000 --- a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.4-aarch64.bb +++ /dev/null @@ -1,8 +0,0 @@ -require imx-gpu-viv-v6.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" - -SRC_URI[md5sum] = "0868b86e5368d35fb4f3eac89b67c43b" -SRC_URI[sha256sum] = "527cdef23d5c9980fcecd5404c42950bfb7af947ae7bd84483fef073703e0686" - -COMPATIBLE_MACHINE = "(mx8)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch32.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch32.bb new file mode 100644 index 000000000..c19e182c6 --- /dev/null +++ b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch32.bb @@ -0,0 +1,8 @@ +require imx-gpu-viv-v6.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" + +SRC_URI[md5sum] = "24b5cd3a0bec8f91d82f404c61c6f7a7" +SRC_URI[sha256sum] = "59ab4f99cb8455cdfabd9228e2066190bbc229f758425846c60e853c2f70c26f" + +COMPATIBLE_MACHINE = "(mx6q|mx6dl|mx6sx|mx6sl|mx7ulp)" diff --git a/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch64.bb b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch64.bb new file mode 100644 index 000000000..40ecd825c --- /dev/null +++ b/meta-digi-dey/recipes-graphics/imx-gpu-viv/imx-gpu-viv_6.2.4.p4.6-aarch64.bb @@ -0,0 +1,8 @@ +require imx-gpu-viv-v6.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" + +SRC_URI[md5sum] = "c0e0431e8d67e57301b7fa91369cd6c5" +SRC_URI[sha256sum] = "0b7eda7d702c06a2b5274b93d870e8370bc85961f6e98b8d41afcfc86e384d80" + +COMPATIBLE_MACHINE = "(mx8)" From 03ee66d038e31e7a3325ac008d1560a07b4a1007 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:28:57 +0100 Subject: [PATCH 086/120] weston: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update SRCREV and add missing do_install() logic. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- meta-digi-dey/recipes-graphics/wayland/weston_5.0.0.imx.bb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-graphics/wayland/weston_5.0.0.imx.bb b/meta-digi-dey/recipes-graphics/wayland/weston_5.0.0.imx.bb index 6e3426145..7e4ea7824 100644 --- a/meta-digi-dey/recipes-graphics/wayland/weston_5.0.0.imx.bb +++ b/meta-digi-dey/recipes-graphics/wayland/weston_5.0.0.imx.bb @@ -17,7 +17,7 @@ SRC_URI = "${WESTON_SRC};branch=${SRCBRANCH} \ file://0001-weston-launch-Provide-a-default-version-that-doesn-t.patch \ file://0003-weston-touch-calibrator-Advertise-the-touchscreen-ca.patch \ " -SRCREV = "b85441fbc9e321931fb7ca833555d740beca054d" +SRCREV = "73a26456e43b6d4f72f0a995d437590065cafb15" S = "${WORKDIR}/git" UPSTREAM_CHECK_URI = "https://wayland.freedesktop.org/releases.html" @@ -155,6 +155,9 @@ do_install_append() { uncomment "use-g2d=1" weston.ini ;; esac + if "${@bb.utils.contains('PACKAGECONFIG', 'xwayland', 'true', 'false', d)}"; then + uncomment "xwayland=true" weston.ini + fi cd - fi } From 7fd927035b8828358ccf1035e454a0bccf9fe7cf Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:51:05 +0100 Subject: [PATCH 087/120] imx-alsa-plugins: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update SRCBRANCH. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- meta-digi-dey/recipes-multimedia/alsa/imx-alsa-plugins_git.bb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-multimedia/alsa/imx-alsa-plugins_git.bb b/meta-digi-dey/recipes-multimedia/alsa/imx-alsa-plugins_git.bb index a642c563b..b258d398b 100644 --- a/meta-digi-dey/recipes-multimedia/alsa/imx-alsa-plugins_git.bb +++ b/meta-digi-dey/recipes-multimedia/alsa/imx-alsa-plugins_git.bb @@ -18,7 +18,7 @@ LIC_FILES_CHKSUM = "file://COPYING.GPL;md5=94d55d512a9ba36caa9b7df079bae19f" inherit autotools pkgconfig use-imx-headers IMXALSA_SRC ?= "git://source.codeaurora.org/external/imx/imx-alsa-plugins.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = "${IMXALSA_SRC};branch=${SRCBRANCH}" SRCREV = "cde60d68ab2acee913dbfacb8aabb53d87dd3e38" From b4695d419ea45fe20de58aa2110455bc8871dc18 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 14:55:49 +0100 Subject: [PATCH 088/120] gstreamer: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update SRCBRANCH in most recipes and SRCREV for gstreamer1.0-plugins-good. update imx-gst1.0-plugin to v4.5.2. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb | 2 +- .../gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb | 2 +- .../gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb | 4 ++-- .../recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb | 2 +- ...{imx-gst1.0-plugin_4.5.0.bb => imx-gst1.0-plugin_4.5.2.bb} | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) rename meta-digi-dey/recipes-multimedia/gstreamer/{imx-gst1.0-plugin_4.5.0.bb => imx-gst1.0-plugin_4.5.2.bb} (97%) diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb index 3a02bb05b..07e2bc565 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.14.imx.bb @@ -41,7 +41,7 @@ SRC_URI_remove = "file://0001-Prepend-PKG_CONFIG_SYSROOT_DIR-to-pkg-config-outpu EXTRA_OECONF_remove = "WAYLAND_PROTOCOLS_SYSROOT_DIR=${RECIPE_SYSROOT}" GST1.0-PLUGINS-BAD_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-bad.git;protocol=https" -SRCBRANCH = "MM_04.05.00_1908_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-BAD_SRC};branch=${SRCBRANCH} \ diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb index b7deda83a..af8174263 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.14.imx.bb @@ -24,7 +24,7 @@ PACKAGECONFIG[gio-unix-2.0] = "" EXTRA_OECONF_append = " --disable-opengl --enable-wayland" GST1.0-PLUGINS-BASE_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-base.git;protocol=https" -SRCBRANCH = "MM_04.05.00_1908_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-BASE_SRC};branch=${SRCBRANCH} \ diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb index f3bbf7bf5..a58ff23f9 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.14.imx.bb @@ -8,12 +8,12 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343 \ DEPENDS += "libdrm" GST1.0-PLUGINS-GOOD_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-good.git;protocol=https" -SRCBRANCH = "MM_04.05.00_1908_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-GOOD_SRC};branch=${SRCBRANCH} \ " -SRCREV = "6aa0b5632a610ea09278624826fb312db9f7b1b9" +SRCREV = "604bc57870878c76a6735db74ff7f15c1802ba4c" EXTRA_AUTORECONF = "" PACKAGECONFIG_append = " vpx" diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb index b8b17d054..c07608513 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/gstreamer1.0_1.14.imx.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6762ed442b3822387a51c92d928ead0d \ # Use i.MX fork of GST for customizations GST1.0_SRC ?= "gitsm://source.codeaurora.org/external/imx/gstreamer.git;protocol=https" -SRCBRANCH = "MM_04.05.00_1908_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = " ${GST1.0_SRC};branch=${SRCBRANCH}" SRCREV = "d42548da09724ad8cc1aa4f1944607920be2f4c0" diff --git a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.2.bb similarity index 97% rename from meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb rename to meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.2.bb index efec52a32..d994dc068 100644 --- a/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.0.bb +++ b/meta-digi-dey/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.5.2.bb @@ -21,12 +21,12 @@ LIC_FILES_CHKSUM = "file://COPYING-LGPL-2;md5=5f30f0716dfdd0d91eb439ebec522ec2 \ file://COPYING-LGPL-2.1;md5=fbc093901857fcd118f065f900982c24" IMXGST_SRC ?= "git://source.codeaurora.org/external/imx/imx-gst1.0-plugin.git;protocol=https" -SRCBRANCH = "MM_04.05.00_1908_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = "${IMXGST_SRC};branch=${SRCBRANCH} \ file://0001-imx-gst1.0-plugin-Update-KERNEL_VERSION-check.patch \ " -SRCREV = "516d7ac1d7b129adc37645403887079e6cdfc7a3" +SRCREV = "a975ecbe1ad86d4951198ddd97d66309e526f7b2" S = "${WORKDIR}/git" From 45035fa29f9539a5948f0c7de7888ab7efac2123 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 15:00:18 +0100 Subject: [PATCH 089/120] imx-codec: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v4.5.2 https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../recipes-multimedia/imx-codec/imx-codec_4.4.7.bb | 12 ------------ .../recipes-multimedia/imx-codec/imx-codec_4.5.2.bb | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.4.7.bb create mode 100644 meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.5.2.bb diff --git a/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.4.7.bb b/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.4.7.bb deleted file mode 100644 index 546f0e0ba..000000000 --- a/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.4.7.bb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2013-2016 Freescale Semiconductor -# Copyright 2017-2018 NXP -# Released under the MIT license (see COPYING.MIT for the terms) - -require imx-codec.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" - -SRC_URI[md5sum] = "d8935dbc7b10e3f09c93bc0100c5eb03" -SRC_URI[sha256sum] = "baacda3525fa402dbdfc3bf1ee8cfb6fa3ac493c89511548ca8e095267366253" - -COMPATIBLE_MACHINE = "(mx6|mx7|mx8)" diff --git a/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.5.2.bb b/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.5.2.bb new file mode 100644 index 000000000..b1023d998 --- /dev/null +++ b/meta-digi-dey/recipes-multimedia/imx-codec/imx-codec_4.5.2.bb @@ -0,0 +1,12 @@ +# Copyright (C) 2013-2016 Freescale Semiconductor +# Copyright 2017-2018 NXP +# Released under the MIT license (see COPYING.MIT for the terms) + +require imx-codec.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" + +SRC_URI[md5sum] = "c6458ce98a0a6d5bd94df7917335d959" +SRC_URI[sha256sum] = "edcccf2cf29a7ae70d3d55c48a5985e583bf508baf29177b0474d68c7af2858e" + +COMPATIBLE_MACHINE = "(mx6|mx7|mx8)" From 58ad96c6570261bf52c98438276667e386ddfbac Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 15:01:42 +0100 Subject: [PATCH 090/120] imx-parser: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v4.5.2 https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../imx-parser/imx-parser_4.4.7.bb | 12 ------------ .../imx-parser/imx-parser_4.5.2.bb | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.4.7.bb create mode 100644 meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.5.2.bb diff --git a/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.4.7.bb b/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.4.7.bb deleted file mode 100644 index 89156896d..000000000 --- a/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.4.7.bb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2013-2016 Freescale Semiconductor -# Copyright 2017-2018 NXP -# Released under the MIT license (see COPYING.MIT for the terms) - -include imx-parser.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" - -SRC_URI[md5sum] = "1a6ae5be5389c23aaf2571e8fd7731ac" -SRC_URI[sha256sum] = "2cfab5311994669ad3bf6e84f4ffe6a89f6796149d6f88e316ecb34d46e44ab0" - -COMPATIBLE_MACHINE = "(mx6|mx7|mx8)" diff --git a/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.5.2.bb b/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.5.2.bb new file mode 100644 index 000000000..cea189af1 --- /dev/null +++ b/meta-digi-dey/recipes-multimedia/imx-parser/imx-parser_4.5.2.bb @@ -0,0 +1,12 @@ +# Copyright (C) 2013-2016 Freescale Semiconductor +# Copyright 2017-2018 NXP +# Released under the MIT license (see COPYING.MIT for the terms) + +include imx-parser.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" + +SRC_URI[md5sum] = "9e0911bca999ad17a2c1d04379e8075a" +SRC_URI[sha256sum] = "e6d00ef760a7779846809b44dfbfabaee90678b229bc9a300c175088b7b2b537" + +COMPATIBLE_MACHINE = "(mx6|mx7|mx8)" From 9a1a80311be572ce757ac21c30ed47fda02aa4ee Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 15:13:53 +0100 Subject: [PATCH 091/120] gstreamer1.0-plugins-good-qt: sync with meta-fsl-bsp-release sumo-4.14.98-2.3.0 Update SRCBRANCH and SRCREV. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../recipes-qt/qt5/gstreamer1.0-plugins-good-qt_1.14.imx.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-dey/recipes-qt/qt5/gstreamer1.0-plugins-good-qt_1.14.imx.bb b/meta-digi-dey/recipes-qt/qt5/gstreamer1.0-plugins-good-qt_1.14.imx.bb index 1993b194a..e2b11704d 100644 --- a/meta-digi-dey/recipes-qt/qt5/gstreamer1.0-plugins-good-qt_1.14.imx.bb +++ b/meta-digi-dey/recipes-qt/qt5/gstreamer1.0-plugins-good-qt_1.14.imx.bb @@ -6,13 +6,13 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343 \ file://gst/replaygain/rganalysis.c;beginline=1;endline=23;md5=b60ebefd5b2f5a8e0cab6bfee391a5fe" GST1.0-PLUGINS-GOOD_SRC ?= "gitsm://source.codeaurora.org/external/imx/gst-plugins-good.git;protocol=https" -SRCBRANCH = "MM_04.04.07_1906_L4.14.98" +SRCBRANCH = "MM_04.05.02_1911_L4.14.98" SRC_URI = " \ ${GST1.0-PLUGINS-GOOD_SRC};branch=${SRCBRANCH} \ file://0001-configure.ac-Add-prefix-to-correct-the-QT_PATH.patch \ " -SRCREV = "36d46a8a9a7dcf173f9a0a0145b6cfa44f879670" +SRCREV = "604bc57870878c76a6735db74ff7f15c1802ba4c" DEPENDS += "gstreamer1.0-plugins-base virtual/kernel \ ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'qtwayland', '', d)} \ From 03d7d4db4655846f456c08978fec87a8a17d4c07 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 15:19:27 +0100 Subject: [PATCH 092/120] imx-m4-demos: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Update to v2.7.0 https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- .../recipes-cpu/m4-demos/imx-m4-demos_2.5.2.bb | 14 -------------- .../recipes-cpu/m4-demos/imx-m4-demos_2.7.0.bb | 11 +++++++++++ 2 files changed, 11 insertions(+), 14 deletions(-) delete mode 100644 meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.5.2.bb create mode 100644 meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.7.0.bb diff --git a/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.5.2.bb b/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.5.2.bb deleted file mode 100644 index 910b7618e..000000000 --- a/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.5.2.bb +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2017-2019 NXP -# Released under the MIT license (see COPYING.MIT for the terms) - -require imx-m4-demos-2.inc - -LIC_FILES_CHKSUM = "file://COPYING;md5=80c0478f4339af024519b3723023fe28" - -SRC_URI[imx8qm.md5sum] = "6423c4c60412b509b6d7537ce1a3fd44" -SRC_URI[imx8qm.sha256sum] = "cf430d4a111370c021435e864666d34fae4c4242907c195aad0c46c48073f78f" - -SRC_URI[imx8qx.md5sum] = "fe2e5c9513faac946d29e5904bf792d9" -SRC_URI[imx8qx.sha256sum] = "151c6a578f6ae5a09b378015116061875047e4f3b6264e4becc80276621893b1" - -COMPATIBLE_MACHINE = "(mx8qm|mx8qxp)" diff --git a/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.7.0.bb b/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.7.0.bb new file mode 100644 index 000000000..e8ab3697b --- /dev/null +++ b/meta-digi-arm/recipes-cpu/m4-demos/imx-m4-demos_2.7.0.bb @@ -0,0 +1,11 @@ +# Copyright 2017-2019 NXP +# Released under the MIT license (see COPYING.MIT for the terms) + +require imx-m4-demos-2.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=fd4b227530cd88a82af6a5982cfb724d" + +SRC_URI[imx8qx.md5sum] = "659c0ccf3a215fae7345d30e85774143" +SRC_URI[imx8qx.sha256sum] = "74e97eea086b3cabe6d4430570e46586625fba822af97c0c2b5d025e69b3b3cb" + +COMPATIBLE_MACHINE = "(mx8qxp)" From 3a674e352606743eae6b9695857db23e4e9c68f9 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 13 Jan 2020 11:26:56 +0100 Subject: [PATCH 093/120] vulkan-demos: use poky sumo sources Otherwise, examples such as skeletalanimation are broken. Reported-by: Alfonso Martin Rey Signed-off-by: Gabriel Valcazar --- ...emos-with-questionably-licensed-data.patch | 91 +++++++++++++++++++ .../vulkan-demos/0001-Fix-build-on-x86.patch | 41 +++++++++ ...ing-demos-support-out-of-tree-builds.patch | 85 +++++++++++++++++ .../vulkan/vulkan-demos_%.bbappend | 14 +++ 4 files changed, 231 insertions(+) create mode 100644 meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Don-t-build-demos-with-questionably-licensed-data.patch create mode 100644 meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Fix-build-on-x86.patch create mode 100644 meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Support-installing-demos-support-out-of-tree-builds.patch diff --git a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Don-t-build-demos-with-questionably-licensed-data.patch b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Don-t-build-demos-with-questionably-licensed-data.patch new file mode 100644 index 000000000..d32c8f280 --- /dev/null +++ b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Don-t-build-demos-with-questionably-licensed-data.patch @@ -0,0 +1,91 @@ +From 55770fb07c42fe410cf8d09f8f5976babc89b9ef Mon Sep 17 00:00:00 2001 +From: Jussi Kukkonen +Date: Tue, 4 Jul 2017 17:13:45 +0300 +Subject: [PATCH] Don't build demos with questionably licensed data + +Some of the models don't have open source compatible licenses: +don't build demos using those. Also don't build demos that need +resources that are not included. + +ssao: +scenerendering: + Sibenik model, no license found + +deferred: +deferredmultisampling: +deferredshadows: + armor model, CC-BY-3.0 + +vulkanscene: +imgui: +shadowmapping: + vulkanscene model, no license found + +indirectdraw: + plant model, no license found + +hdr: +pbribl: +pbrtexture: + Require external Vulkan Asset Pack + +Upstream-Status: Inappropriate [configuration] +Signed-off-by: Jussi Kukkonen +--- + CMakeLists.txt | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4958fff..0f9d3e4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -150,17 +150,11 @@ set(EXAMPLES + computeparticles + computeshader + debugmarker +- deferred +- deferredmultisampling +- deferredshadows + displacement + distancefieldfonts + dynamicuniformbuffer + gears + geometryshader +- hdr +- imgui +- indirectdraw + instancing + mesh + multisampling +@@ -170,20 +164,14 @@ set(EXAMPLES + parallaxmapping + particlefire + pbrbasic +- pbribl +- pbrtexture + pipelines + pushconstants + radialblur + raytracing +- scenerendering + screenshot +- shadowmapping +- shadowmappingomni + skeletalanimation + specializationconstants + sphericalenvmapping +- ssao + subpasses + terraintessellation + tessellation +@@ -196,7 +184,6 @@ set(EXAMPLES + texturesparseresidency + triangle + viewportarray +- vulkanscene + ) + + buildExamples() +-- +2.13.2 + diff --git a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Fix-build-on-x86.patch b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Fix-build-on-x86.patch new file mode 100644 index 000000000..681b3422d --- /dev/null +++ b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Fix-build-on-x86.patch @@ -0,0 +1,41 @@ +From b0495efb6c3ea3a530fcbaddac86da57ecce5a66 Mon Sep 17 00:00:00 2001 +From: Jussi Kukkonen +Date: Mon, 10 Jul 2017 13:11:12 +0300 +Subject: [PATCH] Fix build on x86 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +| func_common.inl:193:51: error: wrong number of template arguments +| (5, should be 6) struct compute_sign + +The fix is backported from the upstream glm project. + +Upstream-Status: Pending [https://github.com/SaschaWillems/Vulkan/issues/356] +Signed-off-by: Jussi Kukkonen +--- + external/glm/glm/detail/func_common.inl | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/external/glm/glm/detail/func_common.inl b/external/glm/glm/detail/func_common.inl +index cafaed5..2dd94e1 100644 +--- a/external/glm/glm/detail/func_common.inl ++++ b/external/glm/glm/detail/func_common.inl +@@ -190,12 +190,12 @@ namespace detail + + # if GLM_ARCH == GLM_ARCH_X86 + template class vecType, bool Aligned> +- struct compute_sign ++ struct compute_sign + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + T const Shift(static_cast(sizeof(T) * 8 - 1)); +- vecType const y(vecType::type, P>(-x) >> typename make_unsigned::type(Shift)); ++ vecType const y(vecType::type, P>(-x) >> typename make_unsigned::type(Shift)); + + return (x >> Shift) | y; + } +-- +2.1.4 + diff --git a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Support-installing-demos-support-out-of-tree-builds.patch b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Support-installing-demos-support-out-of-tree-builds.patch new file mode 100644 index 000000000..4addea3bf --- /dev/null +++ b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos/0001-Support-installing-demos-support-out-of-tree-builds.patch @@ -0,0 +1,85 @@ +From edca667684764cfcc0460e448e834fadf623a887 Mon Sep 17 00:00:00 2001 +From: Jussi Kukkonen +Date: Mon, 3 Jul 2017 14:49:18 +0300 +Subject: [PATCH] Support installing demos, support out-of-tree builds + +This is especially useful for cross-compile situation where testing +happens on target. + +-DRESOURCE_INSTALL_DIR= decides where data is installed (and +where the binaries will load the data from): if it's left empty, +then nothing will be installed and binaries will load the data from +CMAKE_SOURCE_DIR. + +Binaries are now correctly built in CMAKE_BINARY_DIR. + +Upstream-Status: Submitted [https://github.com/SaschaWillems/Vulkan/pull/352] +Signed-off-by: Jussi Kukkonen +--- + CMakeLists.txt | 15 ++++++++++++++- + base/vulkanexamplebase.cpp | 2 +- + 2 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b9886bc..4958fff 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -16,6 +16,8 @@ include_directories(base) + OPTION(USE_D2D_WSI "Build the project using Direct to Display swapchain" OFF) + OPTION(USE_WAYLAND_WSI "Build the project using Wayland swapchain" OFF) + ++set(RESOURCE_INSTALL_DIR "" CACHE PATH "Path to install resources to (leave empty for running uninstalled)") ++ + # Use FindVulkan module added with CMAKE 3.7 + if (NOT CMAKE_VERSION VERSION_LESS 3.7.0) + message(STATUS "Using module to find Vulkan") +@@ -108,6 +110,10 @@ function(buildExample EXAMPLE_NAME) + add_executable(${EXAMPLE_NAME} ${MAIN_CPP} ${SOURCE} ${SHADERS}) + target_link_libraries(${EXAMPLE_NAME} ${Vulkan_LIBRARY} ${ASSIMP_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + endif(WIN32) ++ ++ if(RESOURCE_INSTALL_DIR) ++ install(TARGETS ${EXAMPLE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) ++ endif() + endfunction(buildExample) + + # Build all examples +@@ -117,6 +123,13 @@ function(buildExamples) + endforeach(EXAMPLE) + endfunction(buildExamples) + ++if(RESOURCE_INSTALL_DIR) ++ add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${RESOURCE_INSTALL_DIR}/\") ++ install(DIRECTORY data/ DESTINATION ${RESOURCE_INSTALL_DIR}/) ++else() ++ add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${CMAKE_SOURCE_DIR}/data/\") ++endif() ++ + # Compiler specific stuff + IF(MSVC) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") +@@ -128,7 +141,7 @@ ELSE(WIN32) + link_libraries(${XCB_LIBRARIES} ${Vulkan_LIBRARY}) + ENDIF(WIN32) + +-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/") ++set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") + + set(EXAMPLES + bloom +diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp +index 647368a..a0f28a5 100644 +--- a/base/vulkanexamplebase.cpp ++++ b/base/vulkanexamplebase.cpp +@@ -84,7 +84,7 @@ const std::string VulkanExampleBase::getAssetPath() + #if defined(__ANDROID__) + return ""; + #else +- return "./../data/"; ++ return VK_EXAMPLE_DATA_DIR; + #endif + } + #endif +-- +2.13.2 + diff --git a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend index a86a22fef..11cd87903 100644 --- a/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend +++ b/meta-digi-dey/recipes-graphics/vulkan/vulkan-demos_%.bbappend @@ -1,6 +1,20 @@ +# Copyright (C) 2020 Digi International + +# Use the sources in poky's sumo recipe +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +LIC_FILES_CHKSUM = "file://LICENSE.md;md5=dcf473723faabf17baa9b5f2207599d0 \ + file://triangle/triangle.cpp;endline=12;md5=bccd1bf9cadd9e10086cf7872157e4fa" + +SRC_URI = "git://github.com/SaschaWillems/Vulkan.git \ + file://0001-Support-installing-demos-support-out-of-tree-builds.patch \ + file://0001-Don-t-build-demos-with-questionably-licensed-data.patch \ + file://0001-Fix-build-on-x86.patch \ +" +SRCREV = "18df00c7b4677b0889486e16977857aa987947e2" DEPENDS_remove = "vulkan" DEPENDS_append = " vulkan-headers vulkan-loader" # The vulkan-validationlayers package is necessary for the demos to work RDEPENDS_${PN} = "vulkan-validationlayers" + From 0765189c934deae3c0b9932b12e16d56877eb8fa Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Wed, 15 Jan 2020 12:36:03 +0100 Subject: [PATCH 094/120] systemd: add firmware loading support Userspace firmware loading support is required for the Linux imx-sdma driver. The patches that accomplish this were originally in poky, but were removed in the thud upgrade. Re-work the patches so they apply over systemd v239. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- ...ve-userspace-firmware-loading-suppor.patch | 374 ++++++++++++++++++ ...-rules-remove-firmware-loading-rules.patch | 28 ++ .../recipes-core/systemd/systemd_%.bbappend | 4 +- 3 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 meta-digi-dey/recipes-core/systemd/systemd/0001-Revert-udev-remove-userspace-firmware-loading-suppor.patch create mode 100644 meta-digi-dey/recipes-core/systemd/systemd/0007-Revert-rules-remove-firmware-loading-rules.patch diff --git a/meta-digi-dey/recipes-core/systemd/systemd/0001-Revert-udev-remove-userspace-firmware-loading-suppor.patch b/meta-digi-dey/recipes-core/systemd/systemd/0001-Revert-udev-remove-userspace-firmware-loading-suppor.patch new file mode 100644 index 000000000..d37134abb --- /dev/null +++ b/meta-digi-dey/recipes-core/systemd/systemd/0001-Revert-udev-remove-userspace-firmware-loading-suppor.patch @@ -0,0 +1,374 @@ +From 6c0e15dd6c65b64ca773ce756a8f0356ea5229e9 Mon Sep 17 00:00:00 2001 +From: Chen Qi +Date: Wed, 28 Feb 2018 21:05:39 -0800 +Subject: [PATCH] Revert "udev: remove userspace firmware loading support" + +This reverts commit be2ea723b1d023b3d385d3b791ee4607cbfb20ca. +Userspace firmware loading support is needed for Linux < 3.7. + +Upstream-Status: Inappropriate [OE specific] + +Signed-off-by: Jonathan Liu +Signed-off-by: Khem Raj +Signed-off-by: Chen Qi +--- + README | 4 +- + TODO | 1 + + meson.build | 7 ++ + meson_options.txt | 2 + + rules/meson.build | 4 + + src/udev/meson.build | 4 + + src/udev/udev-builtin-firmware.c | 154 +++++++++++++++++++++++++++++++++++++++ + src/udev/udev-builtin.c | 3 + + src/udev/udev.h | 6 ++ + src/udev/udevd.c | 12 +++ + 10 files changed, 195 insertions(+), 2 deletions(-) + create mode 100644 src/udev/udev-builtin-firmware.c + +diff --git a/README b/README +index 2cde08c..c8cc573 100644 +--- a/README ++++ b/README +@@ -58,8 +58,8 @@ REQUIREMENTS: + Legacy hotplug slows down the system and confuses udev: + CONFIG_UEVENT_HELPER_PATH="" + +- Userspace firmware loading is not supported and should +- be disabled in the kernel: ++ Userspace firmware loading is deprecated, will go away, and ++ sometimes causes problems: + CONFIG_FW_LOADER_USER_HELPER=n + + Some udev rules and virtualization detection relies on it: +diff --git a/TODO b/TODO +index ff1008a..7949333 100644 +--- a/TODO ++++ b/TODO +@@ -844,6 +844,7 @@ Features: + * initialize the hostname from the fs label of /, if /etc/hostname does not exist? + + * udev: ++ - remove src/udev/udev-builtin-firmware.c (CONFIG_FW_LOADER_USER_HELPER=n) + - move to LGPL + - kill scsi_id + - add trigger --subsystem-match=usb/usb_device device +diff --git a/meson.build b/meson.build +index b283d1e..39dee74 100644 +--- a/meson.build ++++ b/meson.build +@@ -66,6 +66,10 @@ sysvrcnd_path = get_option('sysvrcnd-path') + conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '', + description : 'SysV init scripts and rcN.d links are supported') + ++firmware_path = get_option('firmware-path') ++conf.set10('HAVE_FIRMWARE', firmware_path != '', ++ description : 'Userspace firmware loading is supported') ++ + # join_paths ignore the preceding arguments if an absolute component is + # encountered, so this should canonicalize various paths when they are + # absolute or relative. +@@ -180,6 +184,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_PATH', join_paths(pkgsysc + conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) + conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) + conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) ++conf.set_quoted('FIRMWARE_PATH', firmware_path) + conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) + conf.set_quoted('RC_LOCAL_SCRIPT_PATH_STOP', get_option('halt-local')) + +@@ -267,6 +272,7 @@ substs.set('SYSTEMCTL', join_paths(rootbin + substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) + substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path) + substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) ++substs.set('FIRMWARE_PATH', firmware_path) + substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) + substs.set('RC_LOCAL_SCRIPT_PATH_STOP', get_option('halt-local')) + substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no') +@@ -2820,6 +2826,7 @@ status = [ + 'rootlib directory: @0@'.format(rootlibdir), + 'SysV init scripts: @0@'.format(sysvinit_path), + 'SysV rc?.d directories: @0@'.format(sysvrcnd_path), ++ 'firmware path: @0@'.format(firmware_path), + 'PAM modules directory: @0@'.format(pamlibdir), + 'PAM configuration directory: @0@'.format(pamconfdir), + 'RPM macros directory: @0@'.format(rpmmacrosdir), +diff --git a/meson_options.txt b/meson_options.txt +index a396ce3..9f7f1b1 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -109,6 +109,8 @@ option('tmpfiles', type : 'boolean', + description : 'support for tmpfiles.d') + option('importd', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'install the systemd-importd daemon') ++option('firmware-path', type : 'string', value : '', ++ description : 'Firmware search path') + option('hwdb', type : 'boolean', + description : 'support for the hardware database') + option('rfkill', type : 'boolean', +diff --git a/rules/meson.build b/rules/meson.build +index b6a32ba..d3f3214 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -26,6 +26,10 @@ rules = files(''' + install_data(rules, + install_dir : udevrulesdir) + ++if conf.get('HAVE_FIRMWARE') == 1 ++ install_data('50-firmware.rules', install_dir : udevrulesdir) ++endif ++ + all_rules = rules + + rules_in = ''' +diff --git a/src/udev/meson.build b/src/udev/meson.build +index 3bcd2bd..0dd4022 100644 +--- a/src/udev/meson.build ++++ b/src/udev/meson.build +@@ -52,6 +52,10 @@ if conf.get('HAVE_ACL') == 1 + sd_login_c] + endif + ++if conf.get('HAVE_FIRMWARE') == 1 ++ libudev_core_sources += ['udev-builtin-firmware.c'] ++endif ++ + ############################################################ + + generate_keyboard_keys_list = find_program('generate-keyboard-keys-list.sh') +diff --git a/src/udev/udev-builtin-firmware.c b/src/udev/udev-builtin-firmware.c +new file mode 100644 +index 0000000..bd8c2fb +--- /dev/null ++++ b/src/udev/udev-builtin-firmware.c +@@ -0,0 +1,154 @@ ++/* ++ * firmware - Kernel firmware loader ++ * ++ * Copyright (C) 2009 Piter Punk ++ * Copyright (C) 2009-2011 Kay Sievers ++ * ++ * 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 2 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:* ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "udev.h" ++ ++static bool set_loading(struct udev *udev, char *loadpath, const char *state) { ++ FILE *ldfile; ++ ++ ldfile = fopen(loadpath, "we"); ++ if (ldfile == NULL) { ++ log_error("error: can not open '%s'", loadpath); ++ return false; ++ }; ++ fprintf(ldfile, "%s\n", state); ++ fclose(ldfile); ++ return true; ++} ++ ++static bool copy_firmware(struct udev *udev, const char *source, const char *target, size_t size) { ++ char *buf; ++ FILE *fsource = NULL, *ftarget = NULL; ++ bool ret = false; ++ ++ buf = malloc(size); ++ if (buf == NULL) { ++ log_error("No memory available to load firmware file"); ++ return false; ++ } ++ ++ log_debug("writing '%s' (%zi) to '%s'", source, size, target); ++ ++ fsource = fopen(source, "re"); ++ if (fsource == NULL) ++ goto exit; ++ ftarget = fopen(target, "we"); ++ if (ftarget == NULL) ++ goto exit; ++ if (fread(buf, size, 1, fsource) != 1) ++ goto exit; ++ if (fwrite(buf, size, 1, ftarget) == 1) ++ ret = true; ++exit: ++ if (ftarget != NULL) ++ fclose(ftarget); ++ if (fsource != NULL) ++ fclose(fsource); ++ free(buf); ++ return ret; ++} ++ ++static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) { ++ struct udev *udev = udev_device_get_udev(dev); ++ static const char *searchpath[] = { FIRMWARE_PATH }; ++ char loadpath[UTIL_PATH_SIZE]; ++ char datapath[UTIL_PATH_SIZE]; ++ char fwpath[UTIL_PATH_SIZE]; ++ const char *firmware; ++ FILE *fwfile = NULL; ++ struct utsname kernel; ++ struct stat statbuf; ++ unsigned int i; ++ int rc = EXIT_SUCCESS; ++ ++ firmware = udev_device_get_property_value(dev, "FIRMWARE"); ++ if (firmware == NULL) { ++ log_error("firmware parameter missing"); ++ rc = EXIT_FAILURE; ++ goto exit; ++ } ++ ++ /* lookup firmware file */ ++ uname(&kernel); ++ for (i = 0; i < ELEMENTSOF(searchpath); i++) { ++ strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); ++ fwfile = fopen(fwpath, "re"); ++ if (fwfile != NULL) ++ break; ++ ++ strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); ++ fwfile = fopen(fwpath, "re"); ++ if (fwfile != NULL) ++ break; ++ } ++ ++ strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); ++ ++ if (fwfile == NULL) { ++ log_debug("did not find firmware file '%s'", firmware); ++ rc = EXIT_FAILURE; ++ /* ++ * Do not cancel the request in the initrd, the real root might have ++ * the firmware file and the 'coldplug' run in the real root will find ++ * this pending request and fulfill or cancel it. ++ * */ ++ if (!in_initrd()) ++ set_loading(udev, loadpath, "-1"); ++ goto exit; ++ } ++ ++ if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { ++ if (!in_initrd()) ++ set_loading(udev, loadpath, "-1"); ++ rc = EXIT_FAILURE; ++ goto exit; ++ } ++ ++ if (!set_loading(udev, loadpath, "1")) ++ goto exit; ++ ++ strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); ++ if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { ++ log_error("error sending firmware '%s' to device", firmware); ++ set_loading(udev, loadpath, "-1"); ++ rc = EXIT_FAILURE; ++ goto exit; ++ }; ++ ++ set_loading(udev, loadpath, "0"); ++exit: ++ if (fwfile) ++ fclose(fwfile); ++ return rc; ++} ++ ++const struct udev_builtin udev_builtin_firmware = { ++ .name = "firmware", ++ .cmd = builtin_firmware, ++ .help = "kernel firmware loader", ++ .run_once = true, ++}; +diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c +index 576d83d..e58f772 100644 +--- a/src/udev/udev-builtin.c ++++ b/src/udev/udev-builtin.c +@@ -14,6 +14,9 @@ static const struct udev_builtin *builtins[] = { + [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid, + #endif + [UDEV_BUILTIN_BTRFS] = &udev_builtin_btrfs, ++#if HAVE_FIRMWARE ++ [UDEV_BUILTIN_FIRMWARE] = &udev_builtin_firmware, ++#endif + [UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb, + [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id, + [UDEV_BUILTIN_KEYBOARD] = &udev_builtin_keyboard, +diff --git a/src/udev/udev.h b/src/udev/udev.h +index 4596d0e..c800ef5 100644 +--- a/src/udev/udev.h ++++ b/src/udev/udev.h +@@ -138,6 +138,9 @@ enum udev_builtin_cmd { + UDEV_BUILTIN_BLKID, + #endif + UDEV_BUILTIN_BTRFS, ++#if HAVE_FIRMWARE ++ UDEV_BUILTIN_FIRMWARE, ++#endif + UDEV_BUILTIN_HWDB, + UDEV_BUILTIN_INPUT_ID, + UDEV_BUILTIN_KEYBOARD, +@@ -166,6 +169,9 @@ struct udev_builtin { + extern const struct udev_builtin udev_builtin_blkid; + #endif + extern const struct udev_builtin udev_builtin_btrfs; ++#if HAVE_FIRMWARE ++extern const struct udev_builtin udev_builtin_firmware; ++#endif + extern const struct udev_builtin udev_builtin_hwdb; + extern const struct udev_builtin udev_builtin_input_id; + extern const struct udev_builtin udev_builtin_keyboard; +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index 34f6a95..b132db7 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -114,6 +114,9 @@ struct event { + bool is_block; + sd_event_source *timeout_warning; + sd_event_source *timeout; ++#if HAVE_FIRMWARE ++ bool nodelay; ++#endif + }; + + static void event_queue_cleanup(Manager *manager, enum event_state type); +@@ -604,6 +607,10 @@ static int event_queue_insert(Manager *manager, struct udev_device *dev) { + event->devnum = udev_device_get_devnum(dev); + event->is_block = streq("block", udev_device_get_subsystem(dev)); + event->ifindex = udev_device_get_ifindex(dev); ++#if HAVE_FIRMWARE ++ if (streq(udev_device_get_subsystem(dev), "firmware")) ++ event->nodelay = true; ++#endif + + log_debug("seq %llu queued, '%s' '%s'", udev_device_get_seqnum(dev), + udev_device_get_action(dev), udev_device_get_subsystem(dev)); +@@ -687,6 +694,11 @@ static bool is_devpath_busy(Manager *manager, struct event *event) { + return true; + } + ++#if HAVE_FIRMWARE ++ /* allow to bypass the dependency tracking */ ++ if (event->nodelay) ++ continue; ++#endif + /* parent device event found */ + if (event->devpath[common] == '/') { + event->delaying_seqnum = loop_event->seqnum; +-- +2.7.4 + diff --git a/meta-digi-dey/recipes-core/systemd/systemd/0007-Revert-rules-remove-firmware-loading-rules.patch b/meta-digi-dey/recipes-core/systemd/systemd/0007-Revert-rules-remove-firmware-loading-rules.patch new file mode 100644 index 000000000..bb12d30a4 --- /dev/null +++ b/meta-digi-dey/recipes-core/systemd/systemd/0007-Revert-rules-remove-firmware-loading-rules.patch @@ -0,0 +1,28 @@ +From 35d6d384e83ac38077603611bb791969ef95fe68 Mon Sep 17 00:00:00 2001 +From: Jonathan Liu +Date: Thu, 19 Mar 2015 15:01:29 +1100 +Subject: [PATCH 07/31] Revert "rules: remove firmware loading rules" + +This reverts commit 70e7d754ddb356fb1a2942b262f8cee9650e2a19. +Userspace firmware loading support is needed for Linux < 3.7. + +Upstream-Status: Inappropriate [OE specific] + +Signed-off-by: Jonathan Liu +--- + rules/50-firmware.rules | 3 +++ + 1 file changed, 3 insertions(+) + create mode 100644 rules/50-firmware.rules + +diff --git a/rules/50-firmware.rules b/rules/50-firmware.rules +new file mode 100644 +index 000000000..f0ae68451 +--- /dev/null ++++ b/rules/50-firmware.rules +@@ -0,0 +1,3 @@ ++# do not edit this file, it will be overwritten on update ++ ++SUBSYSTEM=="firmware", ACTION=="add", RUN{builtin}="firmware" +-- +2.13.0 + diff --git a/meta-digi-dey/recipes-core/systemd/systemd_%.bbappend b/meta-digi-dey/recipes-core/systemd/systemd_%.bbappend index 8c2d079c4..a8a9ca6ce 100644 --- a/meta-digi-dey/recipes-core/systemd/systemd_%.bbappend +++ b/meta-digi-dey/recipes-core/systemd/systemd_%.bbappend @@ -1,12 +1,12 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI += " \ + file://0001-Revert-udev-remove-userspace-firmware-loading-suppor.patch \ file://0001-udev-use-the-usual-set-of-load-paths-for-udev-rules.patch \ file://0002-sd-resolve-forcefully-cancel-worker-threads-during-r.patch \ + file://0007-Revert-rules-remove-firmware-loading-rules.patch \ " -#FIX-it: Workaround as missing ending slash in FIRMWARE_PATH [YOCIMX-2831] -EXTRA_OEMESON_remove = "-Dfirmware-path=${nonarch_base_libdir}/firmware " EXTRA_OEMESON += "-Dfirmware-path=${nonarch_base_libdir}/firmware/ " # Remove systemd-networkd from our images, since we already use NetworkManager From 2f1ee3f68fb94678d6201204a7e2627917f0cda3 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 16 Jan 2020 11:56:30 +0100 Subject: [PATCH 095/120] digi-sc-firmware: update to v1.3.0 Update to NXP's v1.3.0 porting kit and add power optimizations for suspend mode. https://jira.digi.com/browse/DEL-6932 Signed-off-by: Gabriel Valcazar --- ...igi-sc-firmware_1.2.5.1.bb => digi-sc-firmware_1.3.0.bb} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename meta-digi-arm/recipes-bsp/digi-sc-firmware/{digi-sc-firmware_1.2.5.1.bb => digi-sc-firmware_1.3.0.bb} (84%) diff --git a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb similarity index 84% rename from meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb rename to meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb index 26aefaa7c..52a25ba94 100644 --- a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.2.5.1.bb +++ b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb @@ -4,15 +4,15 @@ DESCRIPTION = "i.MX System Controller Firmware, customized for Digi platforms" LICENSE = "Proprietary" -LIC_FILES_CHKSUM = "file://COPYING;md5=72c0f70181bb6e83eee6aab8de12a9f3" +LIC_FILES_CHKSUM = "file://COPYING;md5=6c12031a11b81db21cdfe0be88cac4b3" SECTION = "BSP" inherit pkgconfig deploy SRC_URI = "${DIGI_PKG_SRC}/${PN}-${PV}.tar.gz" -SRC_URI[md5sum] = "6b6ee8074b7145a2f0c1fae74f4a7941" -SRC_URI[sha256sum] = "e6b9ef3e6db879d55072c177685ef24cbb9075c78f3537d8bcdbdede1ad8cc51" +SRC_URI[md5sum] = "b6d848b2395281cd581b628f3f5b922f" +SRC_URI[sha256sum] = "f3a379c540d57a3b221c91cb9a4dc7ee1556eeec3a2a5e00ba1d1ed34c5d1b8b" S = "${WORKDIR}/${PN}-${PV}" From dd1ab58d84c26212a62ea2ab540f6a345b196282 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Fri, 17 Jan 2020 09:45:06 +0100 Subject: [PATCH 096/120] imx-boot: update SRCREV and SRCBRANCH to sync with sumo-4.14.98-2.3.0 Although the recipe was updated with the modifications in meta-fsl-bsp-release, the revision was still pointing to the sumo-4.14.98-2.2.0 version of imx-mkimage, which is incompatible with our recently updated patch. Signed-off-by: Gabriel Valcazar --- meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend index bee090679..99ab339a1 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend @@ -2,8 +2,8 @@ inherit boot-artifacts # Use the v4.14 latest BSP branch -SRCBRANCH = "imx_4.14.98_2.2.0" -SRCREV = "c00cd78d2e80178171d2d7f8d0d1ce6e2ea41ac5" +SRCBRANCH = "imx_4.14.98_2.3.0" +SRCREV = "2556000499f667123094af22326cfd8e4cbadaac" FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" SRC_URI_append_ccimx8x = " file://0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag-in-flash_r.patch" From 5b8c6b283b27b6e19310989df03888551c8082a4 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 16 Jan 2020 13:38:25 +0100 Subject: [PATCH 097/120] recipes-graphics: remove recipes that are available in community layers Some .bbappend files for clutter, cogl and mesa recipes are already available in meta-freescale, so we can remove them from meta-digi. Also remove the libinput recipe, since a much newer version of it exists in poky. Signed-off-by: Gabriel Valcazar --- .../clutter/clutter-1.0_%.bbappend | 5 - .../recipes-graphics/cogl/cogl-1.0_%.bbappend | 5 - .../Add-OpenVG-demos-to-support-wayland.patch | 84 ----- ...apBuffer-calling-makes-wrong-throttl.patch | 28 -- ...dowPos2iARB-calls-with-glWindowPos2i.patch | 355 ------------------ .../mesa-demos/fix-clear-build-break.patch | 17 - .../mesa/mesa-demos_%.bbappend | 24 -- .../recipes-graphics/mesa/mesa_%.bbappend | 29 -- ...eed-to-fake-new-touches-on-TRIPLETAP.patch | 72 ---- .../wayland/libinput_1.6.1.bb | 25 -- 10 files changed, 644 deletions(-) delete mode 100644 meta-digi-dey/recipes-graphics/clutter/clutter-1.0_%.bbappend delete mode 100644 meta-digi-dey/recipes-graphics/cogl/cogl-1.0_%.bbappend delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa-demos/Add-OpenVG-demos-to-support-wayland.patch delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa-demos/Additional-eglSwapBuffer-calling-makes-wrong-throttl.patch delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa-demos/Replace-glWindowPos2iARB-calls-with-glWindowPos2i.patch delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa-demos/fix-clear-build-break.patch delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa-demos_%.bbappend delete mode 100644 meta-digi-dey/recipes-graphics/mesa/mesa_%.bbappend delete mode 100644 meta-digi-dey/recipes-graphics/wayland/libinput/touchpad-serial-synaptics-need-to-fake-new-touches-on-TRIPLETAP.patch delete mode 100644 meta-digi-dey/recipes-graphics/wayland/libinput_1.6.1.bb diff --git a/meta-digi-dey/recipes-graphics/clutter/clutter-1.0_%.bbappend b/meta-digi-dey/recipes-graphics/clutter/clutter-1.0_%.bbappend deleted file mode 100644 index bf03d1297..000000000 --- a/meta-digi-dey/recipes-graphics/clutter/clutter-1.0_%.bbappend +++ /dev/null @@ -1,5 +0,0 @@ -PACKAGECONFIG_imxgpu3d ??= " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland egl', \ - bb.utils.contains('DISTRO_FEATURES', 'x11', 'glx x11', \ - '', d), d)} \ -" diff --git a/meta-digi-dey/recipes-graphics/cogl/cogl-1.0_%.bbappend b/meta-digi-dey/recipes-graphics/cogl/cogl-1.0_%.bbappend deleted file mode 100644 index afbaee432..000000000 --- a/meta-digi-dey/recipes-graphics/cogl/cogl-1.0_%.bbappend +++ /dev/null @@ -1,5 +0,0 @@ -PACKAGECONFIG_imxgpu3d ??= " \ - cogl-pango gles2 \ - ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'egl-wayland', \ - bb.utils.contains('DISTRO_FEATURES', 'x11', 'egl-x11', \ - '', d), d)}" diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Add-OpenVG-demos-to-support-wayland.patch b/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Add-OpenVG-demos-to-support-wayland.patch deleted file mode 100644 index 19bcca98c..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Add-OpenVG-demos-to-support-wayland.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 8aba54422d9a77383c150f9f70240b18b6e1918e Mon Sep 17 00:00:00 2001 -From: Prabhu Sundararaj -Date: Thu, 9 Apr 2015 15:47:21 -0500 -Subject: [PATCH] Add OpenVG demos to support wayland. - -Upstream-Status: Pending - -Signed-off-by: Prabhu Sundararaj ---- - src/egl/Makefile.am | 6 +++--- - src/egl/openvg/Makefile.am | 33 +++++++++++++++++++++++++++++---- - 2 files changed, 32 insertions(+), 7 deletions(-) - -Index: mesa-demos-8.2.0/src/egl/Makefile.am -=================================================================== ---- mesa-demos-8.2.0.orig/src/egl/Makefile.am 2016-05-09 11:45:51.479100180 -0500 -+++ mesa-demos-8.2.0/src/egl/Makefile.am 2016-05-09 11:45:51.475100160 -0500 -@@ -26,10 +26,10 @@ - eglut \ - opengles1 \ - opengles2 \ -- oes_vg -+ oes_vg \ -+ openvg - - if HAVE_GLU - SUBDIRS += \ -- opengl \ -- openvg -+ opengl - endif -Index: mesa-demos-8.2.0/src/egl/openvg/Makefile.am -=================================================================== ---- mesa-demos-8.2.0.orig/src/egl/openvg/Makefile.am 2016-05-09 11:45:51.479100180 -0500 -+++ mesa-demos-8.2.0/src/egl/openvg/Makefile.am 2016-05-09 12:39:30.000000000 -0500 -@@ -47,13 +47,26 @@ - endif - endif - -+if HAVE_WAYLAND -+EGL_WL_DEMOS = \ -+ lion_wayland \ -+ sp_wayland -+ -+if HAVE_FREETYPE2 -+EGL_WL_DEMOS += \ -+ vgtext_wayland -+endif -+endif -+ - if HAVE_EGL - if HAVE_VG - bin_PROGRAMS = \ -- $(EGL_X11_DEMOS) -+ $(EGL_X11_DEMOS) \ -+ $(EGL_WL_DEMOS) - endif - endif - -+if HAVE_X11 - lion_x11_SOURCES = lion.c lion-render.c lion-render.h - sp_x11_SOURCES = sp.c - -@@ -63,6 +76,20 @@ - text_SOURCES = text.c - text_CFLAGS = $(AM_CFLAGS) @FREETYPE2_CFLAGS@ - text_LDADD = @FREETYPE2_LIBS@ ../eglut/libeglut_x11.la -+endif -+ -+if HAVE_WAYLAND -+lion_wayland_SOURCES = lion.c lion-render.c lion-render.h -+lion_wayland_LDADD = ../eglut/libeglut_wayland.la -+ -+sp_wayland_SOURCES = sp.c -+sp_wayland_LDADD = ../eglut/libeglut_wayland.la -+ -+vgtext_wayland_SOURCES = text.c -+vgtext_wayland_CFLAGS = $(AM_CFLAGS) @FREETYPE2_CFLAGS@ -+vgtext_wayland_LDADD = @FREETYPE2_LIBS@ ../eglut/libeglut_wayland.la -+ -+endif - - SUBDIRS = \ - trivial diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Additional-eglSwapBuffer-calling-makes-wrong-throttl.patch b/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Additional-eglSwapBuffer-calling-makes-wrong-throttl.patch deleted file mode 100644 index 180a9d84e..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Additional-eglSwapBuffer-calling-makes-wrong-throttl.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 010af1952d935352764389636b7165283e6c9e3f Mon Sep 17 00:00:00 2001 -From: Prabhu Sundararaj -Date: Tue, 7 Apr 2015 17:58:45 -0500 -Subject: [PATCH] Additional eglSwapBuffer calling makes wrong throttling - -Upstream Status: Pending - -Signed-off-by: Prabhu Sundararaj ---- - src/egl/eglut/eglut_wayland.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/egl/eglut/eglut_wayland.c b/src/egl/eglut/eglut_wayland.c -index 968b33f..5664d35 100644 ---- a/src/egl/eglut/eglut_wayland.c -+++ b/src/egl/eglut/eglut_wayland.c -@@ -155,7 +155,7 @@ draw(void *data, struct wl_callback *callback, uint32_t time) - - if (win->display_cb) - win->display_cb(); -- eglSwapBuffers(_eglut->dpy, win->surface); -+ /*eglSwapBuffers(_eglut->dpy, win->surface);*/ - - if (callback) - wl_callback_destroy(callback); --- -2.3.5 - diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Replace-glWindowPos2iARB-calls-with-glWindowPos2i.patch b/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Replace-glWindowPos2iARB-calls-with-glWindowPos2i.patch deleted file mode 100644 index d899540fb..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/Replace-glWindowPos2iARB-calls-with-glWindowPos2i.patch +++ /dev/null @@ -1,355 +0,0 @@ -From 757649a766f90e745f24df1d191caeef15c71399 Mon Sep 17 00:00:00 2001 -From: Otavio Salvador -Date: Tue, 4 Jun 2013 09:28:51 -0300 -Subject: [PATCH] Replace glWindowPos2iARB calls with glWindowPos2i - -Vivante libGL does not provide the glWindowPos2iARB symbol, but -glWindowPos2i. Use this instead. - -Upstream-Status: Inapropriate [embedded specific] - -Reported-by: Jeremy Stashluk -Signed-off-by: Otavio Salvador ---- - src/demos/copypix.c | 4 ++-- - src/demos/engine.c | 2 +- - src/demos/fogcoord.c | 4 ++-- - src/glsl/shadow_sampler.c | 2 +- - src/tests/auxbuffer.c | 2 +- - src/tests/copypixrate.c | 2 +- - src/tests/drawbuffers.c | 2 +- - src/tests/drawbuffers2.c | 2 +- - src/tests/fbotest1.c | 2 +- - src/tests/fbotest2.c | 4 ++-- - src/tests/fbotest3.c | 2 +- - src/tests/readrate.c | 10 +++++----- - src/tests/viewmemory.c | 2 +- - src/trivial/clear-fbo-scissor.c | 2 +- - src/trivial/clear-fbo-tex.c | 2 +- - src/trivial/clear-fbo.c | 2 +- - src/trivial/readpixels.c | 2 +- - src/trivial/tri-fbo.c | 2 +- - src/xdemos/glxsnoop.c | 2 +- - src/xdemos/wincopy.c | 4 ++-- - 20 files changed, 28 insertions(+), 28 deletions(-) - -diff --git a/src/demos/copypix.c b/src/demos/copypix.c -index 286c5a9..041b567 100644 ---- a/src/demos/copypix.c -+++ b/src/demos/copypix.c -@@ -54,7 +54,7 @@ static void Display( void ) - glClear( GL_COLOR_BUFFER_BIT ); - - /* draw original image */ -- glWindowPos2iARB(dx, dy); -+ glWindowPos2i(dx, dy); - glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); - - if (Scissor) -@@ -71,7 +71,7 @@ static void Display( void ) - - /* draw copy */ - glPixelZoom(Xzoom, Yzoom); -- glWindowPos2iARB(Xpos, Ypos); -+ glWindowPos2i(Xpos, Ypos); - glCopyPixels(dx, dy, ImgWidth, ImgHeight, GL_COLOR); - glPixelZoom(1, 1); - -diff --git a/src/demos/engine.c b/src/demos/engine.c -index 928fcbb..beace4c 100644 ---- a/src/demos/engine.c -+++ b/src/demos/engine.c -@@ -971,7 +971,7 @@ Draw(void) - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glColor3f(1, 1 , 1); -- glWindowPos2iARB(10, 10); -+ glWindowPos2i(10, 10); - PrintString(s); - if (lit) - glEnable(GL_LIGHTING); -diff --git a/src/demos/fogcoord.c b/src/demos/fogcoord.c -index 567eec0..e833009 100644 ---- a/src/demos/fogcoord.c -+++ b/src/demos/fogcoord.c -@@ -68,14 +68,14 @@ PrintInfo(void) - - sprintf(s, "Mode(m): %s Start(s/S): %g End(e/E): %g Density(d/D): %g", - ModeStr, fogStart, fogEnd, fogDensity); -- glWindowPos2iARB(5, 20); -+ glWindowPos2i(5, 20); - PrintString(s); - - sprintf(s, "Arrays(a): %s glFogCoord(c): %s EyeZ(z/z): %g", - (Arrays ? "Yes" : "No"), - (fogCoord ? "Yes" : "No"), - camz); -- glWindowPos2iARB(5, 5); -+ glWindowPos2i(5, 5); - PrintString(s); - } - -diff --git a/src/glsl/shadow_sampler.c b/src/glsl/shadow_sampler.c -index b830030..eb82d8b 100644 ---- a/src/glsl/shadow_sampler.c -+++ b/src/glsl/shadow_sampler.c -@@ -85,7 +85,7 @@ Redisplay(void) - glPopMatrix(); - - glUseProgram(0); -- glWindowPos2iARB(80, 20); -+ glWindowPos2i(80, 20); - PrintString("white black white black"); - - { -diff --git a/src/tests/auxbuffer.c b/src/tests/auxbuffer.c -index 5fa399a..0cd5f47 100644 ---- a/src/tests/auxbuffer.c -+++ b/src/tests/auxbuffer.c -@@ -419,7 +419,7 @@ event_loop(Display *dpy, Window win) - /* Copy aux buffer image to back color buffer */ - glReadBuffer(GL_AUX0); - glDrawBuffer(GL_BACK); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDisable(GL_DEPTH_TEST); - glCopyPixels(0, 0, WinWidth, WinHeight, GL_COLOR); - glEnable(GL_DEPTH_TEST); -diff --git a/src/tests/copypixrate.c b/src/tests/copypixrate.c -index 2f64e0a..df1f9b0 100644 ---- a/src/tests/copypixrate.c -+++ b/src/tests/copypixrate.c -@@ -91,7 +91,7 @@ BlitOne(void) - else - #endif - { -- glWindowPos2iARB(x, y); -+ glWindowPos2i(x, y); - glCopyPixels(0, 0, ImgWidth, ImgHeight, GL_COLOR); - } - } -diff --git a/src/tests/drawbuffers.c b/src/tests/drawbuffers.c -index fa2f8a7..cd5033f 100644 ---- a/src/tests/drawbuffers.c -+++ b/src/tests/drawbuffers.c -@@ -88,7 +88,7 @@ Display(void) - glUseProgram(0); - glDisable(GL_DEPTH_TEST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/tests/drawbuffers2.c b/src/tests/drawbuffers2.c -index 5bcf0b2..84d444b 100644 ---- a/src/tests/drawbuffers2.c -+++ b/src/tests/drawbuffers2.c -@@ -112,7 +112,7 @@ Display(void) - glUseProgram(0); - glDisable(GL_DEPTH_TEST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/tests/fbotest1.c b/src/tests/fbotest1.c -index 161903c..5930a6d 100644 ---- a/src/tests/fbotest1.c -+++ b/src/tests/fbotest1.c -@@ -61,7 +61,7 @@ Display( void ) - - /* draw to window */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/tests/fbotest2.c b/src/tests/fbotest2.c -index 6ef7f12..11c867e 100644 ---- a/src/tests/fbotest2.c -+++ b/src/tests/fbotest2.c -@@ -72,7 +72,7 @@ Display( void ) - - glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ - -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glCopyPixels(0, 0, Width, Height, GL_COLOR); - } - else if (blitPix) { -@@ -95,7 +95,7 @@ Display( void ) - /* draw to window */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/tests/fbotest3.c b/src/tests/fbotest3.c -index 19f684d..e6d7710 100644 ---- a/src/tests/fbotest3.c -+++ b/src/tests/fbotest3.c -@@ -79,7 +79,7 @@ Display( void ) - /* draw to window */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/tests/readrate.c b/src/tests/readrate.c -index 3859cf4..81eb8a3 100644 ---- a/src/tests/readrate.c -+++ b/src/tests/readrate.c -@@ -85,7 +85,7 @@ MeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo) - glEnd(); - - #if DRAW -- glWindowPos2iARB(0,0); -+ glWindowPos2i(0,0); - glDrawPixels(width, height, - fmt->Format, fmt->Type, Buffer); - glFinish(); -@@ -137,21 +137,21 @@ Draw(void) - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - -- glWindowPos2iARB(10, y); -+ glWindowPos2i(10, y); - sprintf(str, "ReadPixels size: %d x %d", width, height); - PrintString(str); - y -= 14; - -- glWindowPos2iARB(10, y); -+ glWindowPos2i(10, y); - PrintString("Press up/down/left/right to change image size."); - y -= 14; - -- glWindowPos2iARB(10, y); -+ glWindowPos2i(10, y); - PrintString("Press 'b' to run benchmark test."); - y -= 14; - - if (Benchmark) { -- glWindowPos2iARB(10, y); -+ glWindowPos2i(10, y); - PrintString("Testing..."); - } - -diff --git a/src/tests/viewmemory.c b/src/tests/viewmemory.c -index 16044b9..3584c33 100644 ---- a/src/tests/viewmemory.c -+++ b/src/tests/viewmemory.c -@@ -95,7 +95,7 @@ Draw(void) - - glDisable(GL_TEXTURE_2D); - glColor3f(0, 1, 0); -- glWindowPos2iARB(10, 10); -+ glWindowPos2i(10, 10); - PrintString(s); - - glutSwapBuffers(); -diff --git a/src/trivial/clear-fbo-scissor.c b/src/trivial/clear-fbo-scissor.c -index a30935c..5c15200 100644 ---- a/src/trivial/clear-fbo-scissor.c -+++ b/src/trivial/clear-fbo-scissor.c -@@ -182,7 +182,7 @@ Draw(void) - - /* draw to window */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/trivial/clear-fbo-tex.c b/src/trivial/clear-fbo-tex.c -index de84f98..f0fbdf6 100644 ---- a/src/trivial/clear-fbo-tex.c -+++ b/src/trivial/clear-fbo-tex.c -@@ -140,7 +140,7 @@ static void Draw( void ) - glClearColor(0.8, 0.8, 0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - -- glWindowPos2iARB(30, 30); -+ glWindowPos2i(30, 30); - glDrawPixels(Width-60, Height-60, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/trivial/clear-fbo.c b/src/trivial/clear-fbo.c -index 10d830b..3fee3e3 100644 ---- a/src/trivial/clear-fbo.c -+++ b/src/trivial/clear-fbo.c -@@ -116,7 +116,7 @@ Draw(void) - glClearColor(0.8, 0.8, 0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - -- glWindowPos2iARB(30, 30); -+ glWindowPos2i(30, 30); - glDrawPixels(Width-60, Height-60, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - free(buffer); -diff --git a/src/trivial/readpixels.c b/src/trivial/readpixels.c -index ccce4ed..74e0546 100644 ---- a/src/trivial/readpixels.c -+++ b/src/trivial/readpixels.c -@@ -71,7 +71,7 @@ static void Draw(void) - printf("Pixel(0,0) = %f, %f, %f, %f\n", - image[0], image[1], image[2], image[3]); - /* draw to right half of window */ -- glWindowPos2iARB(Width, 0); -+ glWindowPos2i(Width, 0); - glPixelZoom(Zoom, Zoom); - glDrawPixels(Width, Height, GL_RGBA, GL_FLOAT, image); - free(image); -diff --git a/src/trivial/tri-fbo.c b/src/trivial/tri-fbo.c -index d5800b2..dd1f21a 100644 ---- a/src/trivial/tri-fbo.c -+++ b/src/trivial/tri-fbo.c -@@ -119,7 +119,7 @@ static void Draw( void ) - glClearColor(0.8, 0.8, 0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - -- glWindowPos2iARB(30, 30); -+ glWindowPos2i(30, 30); - glDrawPixels(Width-60, Height-60, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - - -diff --git a/src/xdemos/glxsnoop.c b/src/xdemos/glxsnoop.c -index 2215cfd..13d2b2d 100644 ---- a/src/xdemos/glxsnoop.c -+++ b/src/xdemos/glxsnoop.c -@@ -91,7 +91,7 @@ redraw(Display *dpy, Window srcWin, Window dstWin ) - } - - glXMakeCurrent(dpy, dstWin, Context); -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glDrawBuffer(GL_FRONT); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); - glFlush(); -diff --git a/src/xdemos/wincopy.c b/src/xdemos/wincopy.c -index f670983..d010085 100644 ---- a/src/xdemos/wincopy.c -+++ b/src/xdemos/wincopy.c -@@ -156,11 +156,11 @@ Redraw(void) - glClear(GL_COLOR_BUFFER_BIT); - - if (TestClipping) { -- glWindowPos2iARB(-2, -2); -+ glWindowPos2i(-2, -2); - glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR); - } - else { -- glWindowPos2iARB(0, 0); -+ glWindowPos2i(0, 0); - glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR); - } - --- -1.8.1 - diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/fix-clear-build-break.patch b/meta-digi-dey/recipes-graphics/mesa/mesa-demos/fix-clear-build-break.patch deleted file mode 100644 index eb541d658..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa-demos/fix-clear-build-break.patch +++ /dev/null @@ -1,17 +0,0 @@ -mesa-demos: Add extension header to fix build break now that gl1 is removed - -Upstream Status: Pending - -diff --git a/src/egl/opengles1/clear.c b/src/egl/opengles1/clear.c -index 9fe1b5291e1905fd6fe572063ed707d59ce45a81..ca9954a21b5f475709dbdef07f90b900962fcbc7 100644 ---- a/src/egl/opengles1/clear.c -+++ b/src/egl/opengles1/clear.c -@@ -34,7 +34,7 @@ - #include - #include - #include -- -+#include - #include "eglut.h" - - typedef void (GL_APIENTRY *type_ClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa-demos_%.bbappend b/meta-digi-dey/recipes-graphics/mesa/mesa-demos_%.bbappend deleted file mode 100644 index 3aebea0de..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa-demos_%.bbappend +++ /dev/null @@ -1,24 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -DEPENDS = "mesa" - -SRC_URI_append_imxgpu = " file://Replace-glWindowPos2iARB-calls-with-glWindowPos2i.patch \ - file://fix-clear-build-break.patch \ - file://Additional-eglSwapBuffer-calling-makes-wrong-throttl.patch \ - file://Add-OpenVG-demos-to-support-wayland.patch" - -PACKAGECONFIG_IMX_REMOVE_IF_2D_ONLY = "" -PACKAGECONFIG_IMX_REMOVE_IF_2D_ONLY_imxgpu2d = "gles1 gles2" -PACKAGECONFIG_IMX_REMOVE_IF_2D_ONLY_imxgpu3d = "" - -PACKAGECONFIG_remove_imxgpu = " \ - ${PACKAGECONFIG_IMX_REMOVE_IF_2D_ONLY} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'glu x11', '', d)} \ -" - -PACKAGECONFIG_append_imxgpu = " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland vg', '', d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'glut', '', d)} \ -" - -PACKAGECONFIG[glut] = "--with-glut=${STAGING_EXECPREFIXDIR},--without-glut,freeglut" diff --git a/meta-digi-dey/recipes-graphics/mesa/mesa_%.bbappend b/meta-digi-dey/recipes-graphics/mesa/mesa_%.bbappend deleted file mode 100644 index 916f3a300..000000000 --- a/meta-digi-dey/recipes-graphics/mesa/mesa_%.bbappend +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2018 Digi International -PROVIDES_remove_imxgpu = "virtual/egl" -PROVIDES_remove_imxgpu3d = "virtual/libgl virtual/libgles1 virtual/libgles2" - -PACKAGECONFIG_remove_imxgpu = "egl gbm" -PACKAGECONFIG_remove_imxgpu3d = "gles" - -BACKEND = \ - "${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland', \ - bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', \ - 'fb', d), d)}" -do_install_append_imxgpu3d () { - rm -f ${D}${includedir}/GL/glx.h \ - ${D}${includedir}/GL/glxext.h - if [ "${BACKEND}" = "x11" ]; then - rm -f ${D}${libdir}/pkgconfig/gl.pc - fi -} - -do_install_append_imxgpu () { - rm -f ${D}${includedir}/KHR -} - -do_install_append () { - if [ "${BACKEND}" = "wayland" ]; then - rm -f ${D}${libdir}/pkgconfig/wayland-egl.pc - rm -f ${D}${libdir}/libwayland-egl* - fi -} diff --git a/meta-digi-dey/recipes-graphics/wayland/libinput/touchpad-serial-synaptics-need-to-fake-new-touches-on-TRIPLETAP.patch b/meta-digi-dey/recipes-graphics/wayland/libinput/touchpad-serial-synaptics-need-to-fake-new-touches-on-TRIPLETAP.patch deleted file mode 100644 index b52b4962b..000000000 --- a/meta-digi-dey/recipes-graphics/wayland/libinput/touchpad-serial-synaptics-need-to-fake-new-touches-on-TRIPLETAP.patch +++ /dev/null @@ -1,72 +0,0 @@ -This is a workaround upstream suggests for use with kernel 4.1. - -Upstream-Status: Inappropriate [temporary work-around] -Signed-off-by: Jussi Kukkonen - - - -From: Peter Hutterer -Date: Mon Aug 3 18:23:12 PDT 2015 -Subject: [PATCH v3 libinput] touchpad: serial synaptics need to fake new touches on TRIPLETAP - -On the 4.1 kernels synaptics pretends to have 3 slots (the serial fw only does -2). This was added to avoid cursor jumps but has since been reverted for 4.2 -(kernel commit dbf3c37086, 4.1.3 is still buggy). In some cases a TRIPLETAP -may be triggered without slot 2 ever activating. - -While there are still those kernels out there, work around this bug by opening -a new touch point where none exists if the fake finger count exceeds the slot -count. - -Reported-by: Jan Alexander Steffens -Signed-off-by: Peter Hutterer -Tested-by: Jan Alexander Steffens -Reviewed-by: Hans de Goede ---- -Changes to v2: -- split out the handling instead of having a tmp state variable, see Hans' - comments from v2 - -Mainly sending this to the list again so I have a link to point people to. -If you're on 4.1.x add this patch to your distribution package. - - src/evdev-mt-touchpad.c | 22 ++++++++++++++++------ - 1 file changed, 16 insertions(+), 6 deletions(-) - -diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c -index a683d9a..5ef03d5 100644 ---- a/src/evdev-mt-touchpad.c -+++ b/src/evdev-mt-touchpad.c -@@ -369,13 +369,23 @@ tp_restore_synaptics_touches(struct tp_dispatch *tp, - for (i = 0; i < tp->num_slots; i++) { - struct tp_touch *t = tp_get_touch(tp, i); - -- if (t->state != TOUCH_END) -+ switch(t->state) { -+ case TOUCH_HOVERING: -+ case TOUCH_BEGIN: -+ case TOUCH_UPDATE: - continue; -- -- /* new touch, move it through begin to update immediately */ -- tp_new_touch(tp, t, time); -- tp_begin_touch(tp, t, time); -- t->state = TOUCH_UPDATE; -+ case TOUCH_NONE: -+ /* new touch, move it through to begin immediately */ -+ tp_new_touch(tp, t, time); -+ tp_begin_touch(tp, t, time); -+ break; -+ case TOUCH_END: -+ /* touch just ended ,we need need to restore it to update */ -+ tp_new_touch(tp, t, time); -+ tp_begin_touch(tp, t, time); -+ t->state = TOUCH_UPDATE; -+ break; -+ } - } - } - --- -2.4.3 - diff --git a/meta-digi-dey/recipes-graphics/wayland/libinput_1.6.1.bb b/meta-digi-dey/recipes-graphics/wayland/libinput_1.6.1.bb deleted file mode 100644 index c8714f23e..000000000 --- a/meta-digi-dey/recipes-graphics/wayland/libinput_1.6.1.bb +++ /dev/null @@ -1,25 +0,0 @@ -SUMMARY = "Library to handle input devices in Wayland compositors" -HOMEPAGE = "http://www.freedesktop.org/wiki/Software/libinput/" -SECTION = "libs" - -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://COPYING;md5=2184aef38ff137ed33ce9a63b9d1eb8f" - -DEPENDS = "libevdev udev mtdev" - -SRC_URI = "http://www.freedesktop.org/software/${BPN}/${BP}.tar.xz \ - file://touchpad-serial-synaptics-need-to-fake-new-touches-on-TRIPLETAP.patch \ -" -SRC_URI[md5sum] = "7e282344f8ed7ec5cf87ca9fc22674fb" -SRC_URI[sha256sum] = "9d816f13eee63bcca0e9c3bb652c52ab55f39be4d1b90b54e4bfd1dc92ef55a8" - -inherit autotools pkgconfig - -PACKAGECONFIG ??= "" -PACKAGECONFIG[libunwind] = "--with-libunwind,--without-libunwind,libunwind" -PACKAGECONFIG[libwacom] = "--enable-libwacom,--disable-libwacom,libwacom" -PACKAGECONFIG[gui] = "--enable-event-gui,--disable-event-gui,cairo gtk+3" - -UDEVDIR = "`pkg-config --variable=udevdir udev`" - -EXTRA_OECONF += "--with-udev-dir=${UDEVDIR}" From d9e523578d54e0d5d16b7cde9849a9ed0710c7c1 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 16 Jan 2020 14:06:35 +0100 Subject: [PATCH 098/120] glm: update to v0.9.8.5 Signed-off-by: Gabriel Valcazar --- .../glm/glm/Fixed-GCC-7.3-compile.patch | 22 +++++++++++++++++++ .../glm/{glm_0.9.8.4.bb => glm_0.9.8.5.bb} | 9 ++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 meta-digi-dey/recipes-graphics/glm/glm/Fixed-GCC-7.3-compile.patch rename meta-digi-dey/recipes-graphics/glm/{glm_0.9.8.4.bb => glm_0.9.8.5.bb} (74%) diff --git a/meta-digi-dey/recipes-graphics/glm/glm/Fixed-GCC-7.3-compile.patch b/meta-digi-dey/recipes-graphics/glm/glm/Fixed-GCC-7.3-compile.patch new file mode 100644 index 000000000..1332cbfda --- /dev/null +++ b/meta-digi-dey/recipes-graphics/glm/glm/Fixed-GCC-7.3-compile.patch @@ -0,0 +1,22 @@ +diff --git a/glm/simd/platform.h b/glm/simd/platform.h +index a5510beb..b54d8a34 100644 +--- a/glm/simd/platform.h ++++ b/glm/simd/platform.h +@@ -111,6 +111,7 @@ + #define GLM_COMPILER_GCC70 0x02000A00 + #define GLM_COMPILER_GCC71 0x02000B00 + #define GLM_COMPILER_GCC72 0x02000C00 ++#define GLM_COMPILER_GCC7X 0x02000C01 + #define GLM_COMPILER_GCC80 0x02000D00 + + // CUDA +@@ -283,6 +284,8 @@ + # define GLM_COMPILER (GLM_COMPILER_GCC71) + # elif (__GNUC__ == 7) && (__GNUC_MINOR__ == 2) + # define GLM_COMPILER (GLM_COMPILER_GCC72) ++# elif (__GNUC__ == 7) ++# define GLM_COMPILER (GLM_COMPILER_GCC7X) + # elif (__GNUC__ >= 8) + # define GLM_COMPILER (GLM_COMPILER_GCC80) + # else + \ No newline at end of file diff --git a/meta-digi-dey/recipes-graphics/glm/glm_0.9.8.4.bb b/meta-digi-dey/recipes-graphics/glm/glm_0.9.8.5.bb similarity index 74% rename from meta-digi-dey/recipes-graphics/glm/glm_0.9.8.4.bb rename to meta-digi-dey/recipes-graphics/glm/glm_0.9.8.5.bb index 2d2e9ade4..c5fed924c 100644 --- a/meta-digi-dey/recipes-graphics/glm/glm_0.9.8.4.bb +++ b/meta-digi-dey/recipes-graphics/glm/glm_0.9.8.5.bb @@ -10,13 +10,14 @@ SECTION = "libs" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://copying.txt;md5=4431606d144252143c9c3df384a74cad" -SRC_URI = "git://github.com/g-truc/glm;protocol=https" - -SRCREV = "5dcc56489e1b66dfd5bca751fa9b8dc68059e008" - +SRC_URI = "git://github.com/g-truc/glm;branch=0.9.8 \ + file://Fixed-GCC-7.3-compile.patch" +SRCREV = "6fa203eeb7fbcbb6f620501fad40359c8a456049" S = "${WORKDIR}/git" inherit cmake FILES_${PN}-dev += "${libdir}/cmake" RDEPENDS_${PN}-dev = "" + +BBCLASSEXTEND = "native" From 759fc05e09251493c1a45390672df44ba9efacd2 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 16 Jan 2020 14:08:26 +0100 Subject: [PATCH 099/120] weston-init: sync with meta-fsl-bsp-release branch sumo-4.14.98-2.3.0 Rework the weston-init recipe and add a BBMASK to ignore meta-freescale's weston-init.bbappend file. Signed-off-by: Gabriel Valcazar --- meta-digi-dey/conf/layer.conf | 1 + .../wayland/weston-init.bbappend | 24 ++++++++++++------- .../wayland/weston-init/imxdrm/weston.config | 2 -- .../wayland/weston-init/mx6sl/weston.config | 2 ++ .../wayland/weston-init/weston.config | 2 -- 5 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 meta-digi-dey/recipes-graphics/wayland/weston-init/imxdrm/weston.config create mode 100755 meta-digi-dey/recipes-graphics/wayland/weston-init/mx6sl/weston.config delete mode 100644 meta-digi-dey/recipes-graphics/wayland/weston-init/weston.config diff --git a/meta-digi-dey/conf/layer.conf b/meta-digi-dey/conf/layer.conf index 3fd8b6d7a..3da920142 100644 --- a/meta-digi-dey/conf/layer.conf +++ b/meta-digi-dey/conf/layer.conf @@ -15,6 +15,7 @@ BBFILE_PATTERN_digi-dey := "^${LAYERDIR}/" BBFILE_PRIORITY_digi-dey = "6" BBMASK += "meta-freescale/recipes-graphics/drm/libdrm_%.bbappend" +BBMASK += "meta-freescale/recipes-graphics/wayland/weston-init.bbappend" LAYERDEPENDS_digi-dey = "core digi-arm" LAYERDEPENDS_digi-dey += "openembedded-layer networking-layer webserver qt5-layer swupdate" diff --git a/meta-digi-dey/recipes-graphics/wayland/weston-init.bbappend b/meta-digi-dey/recipes-graphics/wayland/weston-init.bbappend index abaa1ef2f..87c974938 100644 --- a/meta-digi-dey/recipes-graphics/wayland/weston-init.bbappend +++ b/meta-digi-dey/recipes-graphics/wayland/weston-init.bbappend @@ -1,23 +1,31 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" -REQUIRED_DISTRO_FEATURES_remove_mx6sl = "opengl" +# OpenGL is not required for parts with GPU support for 2D but not 3D +IMX_REQUIRED_DISTRO_FEATURES_REMOVE = "" +IMX_REQUIRED_DISTRO_FEATURES_REMOVE_imxgpu2d = "opengl" +IMX_REQUIRED_DISTRO_FEATURES_REMOVE_imxgpu3d = "" +REQUIRED_DISTRO_FEATURES_remove = "${IMX_REQUIRED_DISTRO_FEATURES_REMOVE}" -SRC_URI_append = " file://profile" -SRC_URI_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd wayland x11', 'file://weston.config', '', d)}" +SRC_URI_append_mx6sl = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd wayland x11', 'file://weston.config', '', d)}" HAS_SYSTEMD = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}" -HAS_XWAYLAND = "${@bb.utils.contains('DISTRO_FEATURES', 'wayland x11', 'true', 'false', d)}" do_install_append() { - install -Dm0755 ${WORKDIR}/profile ${D}${sysconfdir}/profile.d/weston.sh if ${HAS_SYSTEMD}; then sed -i \ -e 's,/usr/bin,${bindir},g' \ -e 's,/etc,${sysconfdir},g' \ -e 's,/var,${localstatedir},g' \ ${D}${systemd_system_unitdir}/weston.service - if ${HAS_XWAYLAND}; then - install -Dm0755 ${WORKDIR}/weston.config ${D}${sysconfdir}/default/weston - fi + fi + if [ -f ${WORKDIR}/weston.config ]; then + install -Dm0755 ${WORKDIR}/weston.config ${D}${sysconfdir}/default/weston fi } + +# Add profile support not accepted by upstream +SRC_URI += "file://profile" + +do_install_append() { + install -Dm0755 ${WORKDIR}/profile ${D}${sysconfdir}/profile.d/weston.sh +} diff --git a/meta-digi-dey/recipes-graphics/wayland/weston-init/imxdrm/weston.config b/meta-digi-dey/recipes-graphics/wayland/weston-init/imxdrm/weston.config deleted file mode 100644 index 7c92cf110..000000000 --- a/meta-digi-dey/recipes-graphics/wayland/weston-init/imxdrm/weston.config +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -OPTARGS="--xwayland" diff --git a/meta-digi-dey/recipes-graphics/wayland/weston-init/mx6sl/weston.config b/meta-digi-dey/recipes-graphics/wayland/weston-init/mx6sl/weston.config new file mode 100755 index 000000000..58749b289 --- /dev/null +++ b/meta-digi-dey/recipes-graphics/wayland/weston-init/mx6sl/weston.config @@ -0,0 +1,2 @@ +#!/bin/sh +FB_MULTI_BUFFER=1 diff --git a/meta-digi-dey/recipes-graphics/wayland/weston-init/weston.config b/meta-digi-dey/recipes-graphics/wayland/weston-init/weston.config deleted file mode 100644 index 7c92cf110..000000000 --- a/meta-digi-dey/recipes-graphics/wayland/weston-init/weston.config +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -OPTARGS="--xwayland" From c18a39ab55be7e45d2b087826d2053fed6aef3ec Mon Sep 17 00:00:00 2001 From: Hector Bujanda Date: Thu, 16 Jan 2020 17:36:37 +0100 Subject: [PATCH 100/120] dey-examples: adc_cmp_sample: Add support for CC8M https://jira.digi.com/browse/DEL-6931 Signed-off-by: Hector Bujanda --- .../files/adc_cmp_sample/adc_cmp_sample.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/meta-digi-dey/recipes-digi/dey-examples/files/adc_cmp_sample/adc_cmp_sample.c b/meta-digi-dey/recipes-digi/dey-examples/files/adc_cmp_sample/adc_cmp_sample.c index 578bc249e..25d721904 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/files/adc_cmp_sample/adc_cmp_sample.c +++ b/meta-digi-dey/recipes-digi/dey-examples/files/adc_cmp_sample/adc_cmp_sample.c @@ -1,7 +1,7 @@ /* - * ConnectCore 6UL Analog Comparator sample application. + * ConnectCore Analog Comparator sample application. * - * Copyright (c) 2017 Digi International Inc. + * Copyright (c) 2017-2020 Digi International Inc. * All rights reserved. * * Based on iio_event_monitor.c from the tools/iio directory, of the linux @@ -32,7 +32,7 @@ "Usage:\n" \ "adc_cmp_sample -c channel [options]\n\n" \ "Options:\n" \ - " -t : ADC_type ('MCA-CC6UL', 'MCA-CC8X')\n" \ + " -t : ADC_type ('MCA-CC6UL', 'MCA-CC8X', 'MCA-CC8M')\n" \ " -c : channel number to read from\n" \ " -h : Threshold_high higher limit of the comparator window\n" \ " -l : Threshold_low lower limit of the comparator window\n" \ @@ -44,6 +44,7 @@ enum adc_type { ADC_TYPE_UNKNOWN, ADC_TYPE_MCA_CC6UL, ADC_TYPE_MCA_CC8X, + ADC_TYPE_MCA_CC8M, }; struct adc_data { @@ -66,6 +67,12 @@ struct adc_data adc_list[] = { .dev_name = "mca-cc8x-adc", .nbits = 12, }, + { + .type = ADC_TYPE_MCA_CC8M, + .name = "MCA-CC8M", + .dev_name = "mca-cc8m-adc", + .nbits = 12, + }, }; typedef struct cmp { From f1d994bdc223e9760e9493a0ac07460bcf7ad9dd Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Mon, 13 Jan 2020 17:07:38 +0100 Subject: [PATCH 101/120] qca: update wireless driver Update the wireless driver to a newer version that supports both chips (qca6574 and qca6564). We keep the same bdwlan30_US.bin files as the previous version of the driver (or fakeboard_US for the qca6474). Rename directories to qca65X4_driver_interface. We have used the files from the following repo: qca6574au-le-2-2-2_qca_oem -> 4d29c6886f2Commit label r00005.1 - CS2.2 0.0.005.1 md5sum ---------------------------------------------------------- qca65X4_pcie: otp30.bin -> 9d1cf03473904bd8b97fa30bc92b4a16 qwlan30.bin -> 794f7a6f12ef3e6f8db6257b3a6f896f utf30.bin -> 41cfb4e50613cd0eeb0fa99a005131bd qca65X4_sdio: otp30.bin -> e018e7b629b055dc4616c7e88c615b41 qwlan30.bin -> fe37bc043132ecf21e504eb33f46b846 utf30.bin -> 4743dee015047752e433e69f4db89974 https://jira.digi.com/browse/DEL-6766 Signed-off-by: Francisco Gil --- .../firmware-qualcomm/firmware-qualcomm.bb | 33 +++++++++--------- .../bdwlan30_US.bin} | Bin .../otp30.bin} | Bin .../qwlan30.bin | Bin 655557 -> 655829 bytes .../utf30.bin} | Bin 407888 -> 407984 bytes .../otp30.bin | Bin .../qwlan30.bin | Bin 644568 -> 644616 bytes .../utf30.bin | Bin 397768 -> 397808 bytes .../kernel-module-qualcomm.bb | 6 ++-- .../kernel-module-qualcomm/qualcomm.sh | 9 ----- 10 files changed, 19 insertions(+), 29 deletions(-) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_proprietary/fakeboar_US.bin => ccimx8x/bdwlan30_US.bin} (100%) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_proprietary/otp.bin => qca65X4_pcie_proprietary/otp30.bin} (100%) mode change 100644 => 100755 rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_proprietary => qca65X4_pcie_proprietary}/qwlan30.bin (68%) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_proprietary/utf.bin => qca65X4_pcie_proprietary/utf30.bin} (77%) mode change 100644 => 100755 rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6564_proprietary => qca65X4_sdio_proprietary}/otp30.bin (100%) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6564_proprietary => qca65X4_sdio_proprietary}/qwlan30.bin (56%) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6564_proprietary => qca65X4_sdio_proprietary}/utf30.bin (61%) mode change 100644 => 100755 diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 81a850754..33ffcfcdc 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -15,27 +15,28 @@ FW_QUALCOMM_BT = " \ " # Firmware files for QCA6564 (Qualcomm proprietary driver) -FW_QCA6564_WIFI_PROPRIETARY = " \ +FW_QCA65X4_SDIO_PROPRIETARY = " \ file://bdwlan30_US.bin \ file://LICENCE.atheros_firmware \ - file://qca6564_proprietary/otp30.bin \ - file://qca6564_proprietary/qwlan30.bin \ - file://qca6564_proprietary/utf30.bin \ + file://qca65X4_sdio_proprietary/otp30.bin \ + file://qca65X4_sdio_proprietary/qwlan30.bin \ + file://qca65X4_sdio_proprietary/utf30.bin \ " # Firmware files for QCA6574 (Qualcomm proprietary driver) -FW_QCA6574_WIFI_PROPRIETARY = " \ +FW_QCA65X4_PCIE_PROPRIETARY = " \ + file://bdwlan30_US.bin \ file://LICENCE.atheros_firmware \ - file://qca6574_proprietary/qwlan30.bin \ - file://qca6574_proprietary/fakeboar_US.bin \ - file://qca6574_proprietary/otp.bin \ - file://qca6574_proprietary/utf.bin \ + file://qca65X4_pcie_proprietary/otp30.bin \ + file://qca65X4_pcie_proprietary/qwlan30.bin \ + file://qca65X4_pcie_proprietary/utf30.bin \ " # Firmware files for QCA6574 (Qualcomm community driver) # NOTE: the community file 'board.bin' must be substituted by proprietary -# 'fakeboar_US.bin' +# 'bdwlan30_US.bin' FW_QCA6574_WIFI_COMMUNITY = " \ + file://bdwlan30_US.bin \ file://qca6574_community/board-2.bin \ file://qca6574_community/firmware-4.bin \ file://qca6574_community/firmware-6.bin \ @@ -44,8 +45,8 @@ FW_QCA6574_WIFI_COMMUNITY = " \ file://qca6574_proprietary/fakeboar_US.bin \ " -FW_QUALCOMM_WIFI ?= "${FW_QCA6564_WIFI_PROPRIETARY}" -FW_QUALCOMM_WIFI_ccimx8x = "${@oe.utils.conditional('QUALCOMM_WIFI_DRIVER', 'community', '${FW_QCA6574_WIFI_COMMUNITY}', '${FW_QCA6574_WIFI_PROPRIETARY}', d)}" +FW_QUALCOMM_WIFI ?= "${FW_QCA65X4_SDIO_PROPRIETARY}" +FW_QUALCOMM_WIFI_ccimx8x = "${@oe.utils.conditional('QUALCOMM_WIFI_DRIVER', 'community', '${FW_QCA6574_WIFI_COMMUNITY}', '${FW_QCA65X4_PCIE_PROPRIETARY}', d)}" SRC_URI = " \ ${FW_QUALCOMM_BT} \ @@ -72,12 +73,12 @@ do_install() { install -m 0644 ${FW_WIFI_FILES} ${D}${WIFI_FW_PATH} if [ "${QUALCOMM_WIFI_DRIVER}" = "community" ]; then # If using community driver, create symlink 'board.bin' to - # proprietary 'fakeboar_US.bin' - ln -s fakeboar_US.bin ${D}${WIFI_FW_PATH}/board.bin + # proprietary 'bdwlan30_US.bin' + ln -s bdwlan30_US.bin ${D}${WIFI_FW_PATH}/board.bin else - if [ "${FW_QUALCOMM_WIFI}" = "${FW_QCA6574_WIFI_PROPRIETARY}" ]; then + if [ "${FW_QUALCOMM_WIFI}" = "${FW_QCA65X4_PCIE_PROPRIETARY}" ]; then ln -s qwlan30.bin ${D}${WIFI_FW_PATH}/athwlan.bin - ln -s otp.bin ${D}${WIFI_FW_PATH}/athsetup.bin + ln -s otp30.bin ${D}${WIFI_FW_PATH}/athsetup.bin fi fi } diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8x/bdwlan30_US.bin similarity index 100% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/fakeboar_US.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8x/bdwlan30_US.bin diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/otp.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/otp30.bin old mode 100644 new mode 100755 similarity index 100% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/otp.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/otp30.bin diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/qwlan30.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/qwlan30.bin similarity index 68% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/qwlan30.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/qwlan30.bin index 10c20eac444c7015bf4da269262238fee72980c5..7431c00012d42185a6f7133e7fd4f2c5ddeda9b2 100644 GIT binary patch delta 75558 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 diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/utf.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/utf30.bin old mode 100644 new mode 100755 similarity index 77% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_proprietary/utf.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_pcie_proprietary/utf30.bin index 768150396f96ba5bc7042d77c770d11b9edcb9c6..115fee910eb96489cd2abacf9cdff0ba7bb778a5 GIT binary patch delta 32400 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 I&a7qr2c!)I1^@s6 delta 32512 zcmZs?3tUvi`#(PC%;B~yy4){&cG+E6L_r0-;hn`xYF6N#(gJl&O$*J^Nxyd1Ia{K=1oWw;@7@4kV2$ufRxt_ zq#5C=Zw#bniGh59{FK={Ni$H3bUV_g5ne&qiE;|ib5Tzr!c5>Q=obLRoSh^{0s40a zvhh2E`F9%ZkpNoeVL#z7&aV(rO1ep3Lij>+u&2|rCKHWhnp-^~a;ABx*G5ibuJan} zpOOV8Ac3TkgXat+*X-vV#n)t+lf379v?D`d-tPS^xB+SM>`qdEP=hc9XrG@- zuBD+BsU@e5`=$2>A`{XfD!1)ddM)Y&|DYt8rNhV9y*e*Sz>-U)Z|f72m>(R4;{(Xn1_ccxs&FZVSPr= z*_ukG0^@;6Knl=(qPx3(2?i7#_*>K6-MuNLNQ!@O;n)ReMXVNfw)J;rsovQNws~2e}zn zO4gb)B61+~HxZI_!OBPY&aLLBl`5{?yjB_QN8U*#U!c;OcxcO9tqg_mA1eojcY>Y* z%#4X4?Ph^YLzoU|%zk1YkCbhxpbi%!VcZ$w*zh2f%-(Gv-UvG|fC_|~KZ?om!*(&0 zQ(r*x2zs2!FpiKiWj2feVIk1G)cm7L%`G!~sGkYWM**m$lbASiVLeBVAidT6in@;cS&k{&>h&>{WaOd5drW93PEoN-`w>nWaYRs23WBdM& z^hqG?n1Q7A#xNq@1Q1wPGtwyv!d>m$f#IC2jq=cd8f{*o?ZZ`=w`+%?ju!1$uGZ|Y z8)#Syt~DtsWEG%!4r&DIQGPAbod|OgZU9JGDv7sHLORYLNGCkWL^(2RZ~*$F3-zo) zs`)wdE}fcNW3JOFeey9nBn03X7g|d0{bv3&Y7C_Fi#`-`1=H&q(2N2a%<}H;x5>2`=GN$mnC0PmB^PfV zqF>;XhT*vq3P)kK>c@p=BX#25xw|!}y&j54tA>w*M+=mZ3V>O0AT;8&bAo z_JE@xrierhE+u;r&x}kVW#;r4C3o7qJZ7Xm1w3g$Hc$w3g1;VNJ3y9WmH;W{^D!?Z zcA~~Bqe{uD(WT@9TDXaH8gifb2<{T0Vh$E9g!Mo>K+Mbg4D|Q5q!Kxt!6>gHLdL_B zn5+9lp@%Jf#_1D~mjbjGl#9Y)G{3l$WL!t@12DN(V^IKVQAdpw0`g|s7{G7L^|4d_679yDTtM+Gv0l%WQ)_f2RPAjCU`v=Xx6ODq-ZptaYrX6B>s z;46G{=Pc3*W(}B@oi>wp2znLh1nvN}sGuH|r3``pH%kh_Dl(&#OqyOw>LFZr4(dOF zq0Ydf3*=X&kk24wvpKk52VY-e_KbU3z;xejUK_Wtf8krDBz`qG!J#R~s)3RUgfl%8 zNH)TQFw;A5A{|AgWT4qE{?T~^)CVZVA(W>LA_JQ>0|x;0NEdF$&=i)EJ6lWPdP+$O zxN3ou#ic|6+SQU$a*&mhtw7MWQldfF1irbYrI0s;d|`es{)N74_Mr9!DdgUK%qoN% zo-vbT(ArS)-pgjP0r7mG!2DSM(46szbz-GHg76NY(^Y@}>D}t@72BbBaK!r%vKI8( zV`vwsIE;2{A>$D&NA(5$b$p0Epz0QH?_QopB&G~0?u4TMktX`p8V z7Jw%@Qjf45Q0xW|pa~${z3b)=2gWR~@G2w31JKDxkWU#|C@Uj{2ot2Z9HCzsnFMIK zGE#tWD-a)4hNTR$!2{mGQdWa_JJ6lu3rvPvli*7_k)IGmxSI$S7Bp>6Pl%j+IvBMA zoxmM{gp`ry&@yryVUYJsvcZ%>3d71s319&#fEr*f_M-`eBlobx6~ciQnBPx0!R}S?7o47mk7yUO~_#L{UoK&g>}zP|Hg16J_!Ll1NBnDd6kVV$fV)+Z#4>?A8fFdKpi85KlGcO)V8lgz&io9}aQ z@=nq=X(yOwCdc_Tr@<%y&10~d!&{P-p*g3auE7y#6{rBF0vCW$$}*x5p#WeZ&<@;G zmyr||(!f^WByb!wMI;6qSO_cw@`1g;5#axCcus?U4Y(IsmP6t-7+)Y>3r1j)u8cHA z!;19iIxskaH19C861IkD}5IYbJ0|kRn$>1^~3_*_o4H}*U6apua7KWk$;3S|JRz|KO z9EC6q$OVo7Wy#Pca0ej6!4KpD^&>IHKs(S044yIyg@NNhCqPD{m%u1s4zK~(3hV`r z0C#|tF=b>1kO|ZS&CuGifo0~FQNzs@>CHJok3zMe-%CNh0m7!D*TBJXXm~v6K-dHb zGzo13*CwMAQy>gzWxx@j6NsM(KHxZT4TygPvY~uC!Xs$o3NROGZ}27qUjRW<%c98m zsYoD0j*7H3;-bgWd>lr!9mUdjtI~V zXmc72qzvf`X6<{SIkksi0#CsPflzGz%`&Y3lnC3 z8CkOcL)u4%lPBm4F?2{@Mf}bpw7eMI0ZszPQKsSvObkH21jD!#WtL)gDxQODScaLo z9EE_|S1{h2(GV~S7!P>A0Rez3z%^j}o3K0JG|&l5DgYgrvjxHet4a~>1>ZjK0bxLV zCG>g#LZQRUfUQn+t`4)a2@*v|W5GdB+qYsCZi8)=K$qL0Xdr9{3IjqK$^m81L+OD0 z1UhlIHZj{w(zwP?r!G()Y~C!rmvbPd8>K!e_u0Y`wVNJqbeGC(_qFnbpGfwbAs z=5xqL9r4+q12r#~k>De%(ZiLn3`n>b1-<~h&6AyxIa@zLUp|HtIECgBC#NAZPy$o{ z*=I0WfvLb3z!f0=9MVAYm+<9Zqp$zQKmcf}+{8cw^*}Q)^$*x6&;%sk zLi!dgqy9D;2V?XPP#mzh1tZ&v8Gr(JfW4pzE(ii7oQE|4L7$>RAmK+;1Z)M4{|r6- zioOG#K*BW$0h|P14e-TR7%T|e_9raqF4XZC>i9DUei{+QeN=$VGBkD^JsFJ3>bubx zPy*Bf7N7#C0R#v*2bJfe+*Jr12L5{=gN}-$p|!vNu#N8C&`(B0VJDe^)%7^tN%juH zT@Av6pdHV_zjz;9(g3S?Y?piy0u?}^9NVw{J4uri_TEY6s&JZ!#u^;BlPny7{DC{k zJs>_2`!x}Jogkzop!`BVlv4n`kROc3fw>T1VFJn~Vf99P^@tmqQ1Mh0ECl0`2uSCT zMu735C;%pJG$x>d>;RkL=UtO3>9UXZSOzDtu=EWD1*zsE+s`c;P$HL2zE{+ z7DzBBeh}zC_4`sXUCOa=ggjk>GyTjDKI38z>yI6j`~T~4`GNBBYn8@osvJMhQ@{G~ z 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�x!&OX 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 I!eCPO|K1^9A^-pY delta 53017 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 diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index db2f73598..73d8df971 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -6,11 +6,9 @@ LICENSE = "ISC" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d" # Reference Qualcomm tag/version -PV = "v4.2.89.63" -PV_ccimx8x = "v4.0.11.208Q" +PV = "v4.0.11.213X" -SRCBRANCH = "qca6564/master" -SRCBRANCH_ccimx8x = "qca6574/master" +SRCBRANCH = "qca65X4/master" SRCREV = "${AUTOREV}" QCOM_GIT_URI = "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_MTK_GIT}linux/qcacld-2.0.git;protocol=ssh', '${DIGI_GITHUB_GIT}/qcacld-2.0.git;protocol=https', d)}" diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh index 1e3b9ced5..bcc6e8a14 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh @@ -109,15 +109,6 @@ esac BDATA_WW="bdwlan30_World.bin" BDATA_LINK="bdwlan30.bin" UTFBDATA_LINK="utfbd30.bin" - elif [ -f "fakeboar_US.bin" ] || [ -f "fakeboar_World.bin" ]; then - BDATA_US="fakeboar_US.bin" - BDATA_WW="fakeboar_World.bin" - # Use different links for propietary and community drivers - if [ -f "board.bin" ]; then - BDATA_LINK="board.bin" - else - BDATA_LINK="fakeboar.bin" - fi else log "5" "[ERROR] Could not locate board data files" exit 1 From b6e2a0b7102f18697572efa436619e9d0df7fb66 Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Mon, 13 Jan 2020 17:07:55 +0100 Subject: [PATCH 102/120] bluetooth: update binary files for the new driver The new driver uses the same files for both platforms (6564, 6574). The specific platform binaries have been removed. Now the modifications of the nvm_tlv_3.2 to disable the IBS is done by the recipe. The disable of the deep sleep and the enable of the internal clock is done in the recipe only for the CC6UL. We have used the files from the following repo: qca6574au-le-2-2-2_qca_oem -> 4d29c6886f2Commit label r00005.1 - CS2.2 0.0.005.1 md5sum ------------------------------------------------------------ nvm_tlv_3.2.bin -> a97cdfe80e8109cf3574f74cd3c73fc7 rampatch_tlv_3.2.tlv -> 72d28614afd0abe5846c1758099282e3 https://jira.digi.com/browse/DEL-6766 Signed-off-by: Francisco Gil --- .../firmware-qualcomm/firmware-qualcomm.bb | 14 ++++++++++++-- .../qca6564_bt/nvm_tlv_3.2.bin | Bin 1968 -> 0 bytes .../qca6564_bt/rampatch_tlv_3.2.tlv | Bin 54228 -> 0 bytes .../nvm_tlv_3.2.bin | Bin 2010 -> 2010 bytes .../rampatch_tlv_3.2.tlv | Bin 5 files changed, 12 insertions(+), 2 deletions(-) delete mode 100644 meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/nvm_tlv_3.2.bin delete mode 100644 meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/rampatch_tlv_3.2.tlv rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_bt => qca65X4_bt}/nvm_tlv_3.2.bin (96%) rename meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/{qca6574_bt => qca65X4_bt}/rampatch_tlv_3.2.tlv (100%) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 33ffcfcdc..69ab65a49 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -10,8 +10,8 @@ QUALCOMM_WIFI_DRIVER ?= "proprietary" # Bluetooth firmware files FW_QUALCOMM_BT = " \ - file://${QCA_MODEL}_bt/nvm_tlv_3.2.bin \ - file://${QCA_MODEL}_bt/rampatch_tlv_3.2.tlv \ + file://qca65X4_bt/nvm_tlv_3.2.bin \ + file://qca65X4_bt/rampatch_tlv_3.2.tlv \ " # Firmware files for QCA6564 (Qualcomm proprietary driver) @@ -81,6 +81,16 @@ do_install() { ln -s otp30.bin ${D}${WIFI_FW_PATH}/athsetup.bin fi fi + + # Disable IBS over H4 for all the platforms in the bluetooth firmware + printf \"\\x02\" | dd of="${D}${base_libdir}/firmware/qca/nvm_tlv_3.2.bin" bs=1 seek=54 count=1 conv=notrunc,fsync +} + +do_install_append_ccimx6ul() { + # Disable DEEP SLEEP in the bluetooth firmware + printf \"\\x00\" | dd of="${D}${base_libdir}/firmware/qca/nvm_tlv_3.2.bin" bs=1 seek=74 count=1 conv=notrunc,fsync + # Enable Internal Clock in the bluetooth firmware + printf \"\\x01\\x00\" | dd of="${D}${base_libdir}/firmware/qca/nvm_tlv_3.2.bin" bs=1 seek=93 count=2 conv=notrunc,fsync } QCA_MODEL ?= "qca6564" diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/nvm_tlv_3.2.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/nvm_tlv_3.2.bin deleted file mode 100644 index 2715082decbf74920ab8efa2a2f98a062ed81acc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1968 zcmZuyYiv|S6#mZ4y}P%!+ugg}?OM9Eg_f2rMM}B|yUS~7cWEgCHMSK>uvKV%1eJ$U zB7!9-)E|nEKx|D+)j;Bck0=s@i6Qb*Fbc*5Vj@9Ne;5*@sYW2Sp1YU5U01(z&&-)K zb7s!WJ!eK7azem?4BqZEB?q*O0%N0lMlUW{wa1&K6XezuJ%k|09*0u+#~TJPjR^h` zAk1uHA}^GIv%V6uGY!NSHZ&%Zi<(xfbh`tAKv{LytnK4cevz*t7VlWRdd;{LEFtx~ z$#B_Ij7cpoFAvCb5~>ie^?)FfQo>{?m>Co*P>lk6go7T)TMv|*3Uvw($-u{F5JF+5 ziF(yp@PoI}cgz(xE*Czh%+qS{p50r^(x1G+&2Xbel;K|J*oIcT$cOn7Bo0t3QdEJ1 z(66VYFaB zdNBt=5L7Bb6B0-Y4|XDoXAnb^$U_HnSSXmzJGe|5HXtf(QopS6BwdtsIljHR8NbcF+=E5 z=PxvTpIl31sWCj}wbXKYRw%4vr>EIdNOmhLjG*gcIca1_m7|G>-j@zcl#+CZ@zGo) zZM**KqTb|VZ(_pv(rfs5?+xs@5yKxHb=by#yq81V&7(gr`4w09kKpUaS0T1$2|i=r z!WGd-svAOf(iABvVcPwk|?CyPJ{l>>OZ+YTp z;GS`-jHG}TvZE24bDnb!_!jc%XF!Tj6irbCM3c2{x<^r5N&>28wBeh~PzayDva)(g zB!b#BYSOqZjZhkOX%rXVQXD`q7%VLfPVjPlYmvW@>!JYHhTrcm@_7x9q9{_TPPeM6 zQula$s;U>bJ>Ei(;o(-H517Ao>!uB@t*wZ6chAr`q;BT776@qOl`y-jxhB$3!7)OL z#4e7Icj*lML_!3_?V>~M5c|bh@w=#!ck-eBKict^-7z*c2Z{PUbcBAPN#ZW?vbZAZ z*zyherE*=ZcIwnFMqGpu_M@xcfvIJe(zY&_i#MZKCFg;e31(%wTVC!r3`1HaJpTgQ zIUEjHWv*R`TjNby<$vu=!<**jdc2fX@_K0#tIV;3!>=}d)pzJgi%#^je`Sh-4wz|X zL00Kbt$zEi=l8vK;GH9%*g|L4g`2*ec=#$D&X{pF@TCT+Ksq6HNEaL~=x*c}!0o~D zNG^REG0D=Ni00Dqs7aRgWHgtu^{1ES(y686ba8nuU080CrCp6-+y6us+LDPji<5~& zk{ijk_FVL|xA*jPSX!=obJ3TD`}_L%+r7o+-Fo;kw!p94mCQ#fosn^bv0UZrpOatZrJ`Qey_N!-hi26XbT z)v=LkYZEO^$z-xIvEuIbw$7DR@lYr_FB*%*BGE*mu_2k9JZnPp3z;-C&t_lFlXKFj P_Vv5EjorQ(Zn*yerAcWx diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/rampatch_tlv_3.2.tlv b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6564_bt/rampatch_tlv_3.2.tlv deleted file mode 100644 index def7cc30a2af7eba36e4c5856856ba71d1a7de19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54228 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 diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_bt/nvm_tlv_3.2.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_bt/nvm_tlv_3.2.bin similarity index 96% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_bt/nvm_tlv_3.2.bin rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_bt/nvm_tlv_3.2.bin index 6d531b2f07c361223cec94e4b732fb1fd004feff..5228c71967e1f73935fb9bb5a245122c1f26c774 100644 GIT binary patch delta 12 Tcmcb`e~W*D8DrB%^Tq4{Av6T8 delta 12 Tcmcb`e~W*D86(q1^Tq4{9<&55 diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_bt/rampatch_tlv_3.2.tlv b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_bt/rampatch_tlv_3.2.tlv similarity index 100% rename from meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca6574_bt/rampatch_tlv_3.2.tlv rename to meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_bt/rampatch_tlv_3.2.tlv From f554820ce6dc8957052c4da9582d7db37b68b9c0 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Mon, 20 Jan 2020 11:18:05 +0100 Subject: [PATCH 103/120] firmware_qualcomm: ccimx8mn: update US Board Data File calibration data Update file: - bdwlan30_US.bin (d5221377de1dde9ff442740e56fea647) This file was generated by calibrating several CC8MN DVKs and merging their resulting BDF files into a Golden file. Reference calibration file is: - bdwlan30_US.bin (a5635e39aaaa220094e0d07f7a4f4567) Signed-off-by: Arturo Buzarra --- .../ccimx8mn/bdwlan30_US.bin | Bin 8124 -> 8124 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8mn/bdwlan30_US.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx8mn/bdwlan30_US.bin index e923f41b675424bf1472a4f4e58d5f73d48d8108..b5b763136af0f1482312730a83bf09c8d6c6c04d 100644 GIT binary patch literal 8124 zcmeHMeM}T*8lMGIEusQ0D+>(n;+!%Fqbn8N5#>XKeU}AxaK!~*5fE^f^0DinunP#Z zwg(UqXon}+n7yXK~Mx#oH~n`@J5{Nw)MlG2cCJF$1hcu8yd>%3=Xb^xip z=3-*J)R#Q_yz~Bk@ALHz%kzdmtVQ)vIwE?&N$6}Z5=6eAAPAF5PY`Q~D46PW@zFV; zzi*_brt5UX&fMJGZ@>A*)RguNK}1DeySDvTQ8C(doE$lGE_CtA8$v^kYKmd&TR^ZAzYuWTnqPX=sfHw;j$o)uo7-$hn!#s02{)ufl(hAjrbT2jShDL zur_oRidl|~_77(7LJ@y#gDj(}7|b@I=W!R`C!7>VrE#)^s$i+6Z*xMrPHK`@-aQ^5E{W}`3d2Q_?Gk= zvWP-V6&KO-BdR^})hL_>Il9}`02&!soW0?Nj4Yz=C}t^83TD83+_ zBKJ`TnHIJa_25B%SP;Ys>59U00kB-Vs7u!Xk@MWS8W3pI5{;*)DSB#ubu9@p=OZ_+n1Nyrie zkq4!X^t4neA_l{qNgMH&=jwMSdhKtB!SKnc5@OhM^1Bngez5#%dcCHpCP+LY>5b{>@?6#_2U3jY1~VxO?48q(>x7%kt69umAQT$VWHt-jwA@&f#&y=5V^)xW38LGdeaN3SYkZ=Hxr?zW4s0 zKK%GPbc8T|D29>VKwC|fCDF1b&{xw`SW2%pFPoj6c#Rkd08nYsTd6>ALo)#J8W04) zY0+EsL%qt5RYpSH(HrRC?3Ok3s-b=bh}VF=Kqu$0Bw14Yy*16&0`p1@2m(-{0R8BY zwb;1axLh^W6Yz1I#Yo5b`?*E{VvI3bRDQ0~k}3nJ&br&UOf%IV@FN$!hEDXJKrPl% z<0|7SWk(?B?LaQ`YC6^1&n*OodI8vL)+<1>b&qj{aYbZ@za3T4NpvzeZ?G24IS+IL z;G~nxao!W$5v$Ei#;chJdc8hWZ8p$p{u5l2wFFG5c>v%qgF%H{w+m1MMJZIo_yKfgS*= z%n5Yz&=3Gw=D0ai{ti@08!VKvV;&gk3;3bBCOU3tkn1t8wlMKuYok0%p&c&v|mRlb;YTM6RZgl=oMRsCH2{J3L!>Th8M zNF!xpXy^r5T*TXjy&{&HNdrYP>sbcn;$3`+P$}+*zHgqV_KX;MMm?3P^oLuaKis4A zhjq|fnxVJMf!?y1cL@8$I^eCI>m&1&K60NV^VTuh>{hf3m+%$Bez9Ki0xy|a$8JP9 zcn7~*aELAmld05C7>3P7`Pjxgg&MIzY9-@=m(FIQEtuttgt7>aQh2hxO2G|0FPX52 zw-@ZCfZr_en}_#+-)ixYbOh`f7ud6lGA}LScNZ=NziuVII4X%Tu^GsMt>D)#Rw?mO zkVmePN2QX7htznRfma|Pk%N9X{ej*bLvP*ze&_8K0Ow&t&p{q?{nR|-s5MF-z6tv9e8C2Nc+DJdXQa-DBoDcQGB9h|4QMmo4)LkHbyOyk z!|p)4v4h_y928q1zLgQ4Z0|u{9xBG=z^hYu^ZkD=^#3JdrR1JFH@SZDdDO$Xt)TP_ z3HO9-tnw;=M?P@A^0~D}-j_^x57hUiT52HIQ`yW`b{8tamHd98Ui3(Qu$KsV$mb!y z2lBZc0v^L`V+)WCJNX)+QEZj?NS!kuI5+cLzGb{iQ0u(-J#a|}7Mxod+^N)aTdCZ4 zHXyam@_olmZlrRUJhm7)@IL;a&@6UH$I0bX0+Y@ccp#4k(JLK=JPdHYs$cay+++r|nPJ%?REAwVhPz=K+zsXU zNR|S7Tfy%huy>H$L~UmZS)|-G8wIa;R0@&=MKAkc>ejE=qYuBI!hVZ-@f zzAf|R`^@5XZNH{}$bNNgh09f4m8@x}yTT14$!4=DdhvR#IygM$%`SD!0Z zYFec`VimgG9Kk_T#Pqyvv@^Q20Yl-=6vV%+x5xqI0-@Ihj zeKvEKxc%8(qTrH6XG(f`g(>MC$oe^15{lOmGXwp4&@ms(=(fY&I9+W1)2jaeRN%TA Ms`7u_|A(mm1N!aS_y7O^ literal 8124 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 EZxr%@b^rhX From a239ac860064b493a4ba83051ab43bdecb4cc1c2 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 20 Jan 2020 11:14:34 +0100 Subject: [PATCH 104/120] modemmanager: blacklist SPI-to-CAN interface on the ccimx8mn Signed-off-by: Gabriel Valcazar --- .../modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules index 113069765..4edd0c008 100644 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/ccimx8mn/80-mm-net-device-blacklist.rules @@ -6,6 +6,9 @@ ACTION!="add|change|move|bind", GOTO="mm_net_device_blacklist_end" # Remove Ethernet interfaces from ModemManager probing SUBSYSTEM=="net", DEVPATH=="/devices/platform/30be0000.ethernet*", ENV{ID_MM_CANDIDATE}="0", ENV{ID_MM_DEVICE_IGNORE}="1" +# Remove SPI-to-CAN interface from ModemManager probing +SUBSYSTEM=="net", DEVPATH=="/devices/platform/30840000.ecspi*", ENV{ID_MM_CANDIDATE}="0", ENV{ID_MM_DEVICE_IGNORE}="1" + # Remove MMC interfaces from ModemManager probing SUBSYSTEM=="net", DEVPATH=="/devices/platform/30b40000.mmc*", ENV{ID_MM_CANDIDATE}="0", ENV{ID_MM_DEVICE_IGNORE}="1" From 2fefbb044714d9d928769feb349317a4fdb12a24 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Mon, 20 Jan 2020 14:44:40 +0100 Subject: [PATCH 105/120] digi-sc-firmware: update to v1.3.0.1 Update the SCFW's DCDs with NXP's latest changes. Signed-off-by: Gabriel Valcazar --- ...{digi-sc-firmware_1.3.0.bb => digi-sc-firmware_1.3.0.1.bb} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename meta-digi-arm/recipes-bsp/digi-sc-firmware/{digi-sc-firmware_1.3.0.bb => digi-sc-firmware_1.3.0.1.bb} (89%) diff --git a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.1.bb similarity index 89% rename from meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb rename to meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.1.bb index 52a25ba94..721d0c8cf 100644 --- a/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.bb +++ b/meta-digi-arm/recipes-bsp/digi-sc-firmware/digi-sc-firmware_1.3.0.1.bb @@ -11,8 +11,8 @@ inherit pkgconfig deploy SRC_URI = "${DIGI_PKG_SRC}/${PN}-${PV}.tar.gz" -SRC_URI[md5sum] = "b6d848b2395281cd581b628f3f5b922f" -SRC_URI[sha256sum] = "f3a379c540d57a3b221c91cb9a4dc7ee1556eeec3a2a5e00ba1d1ed34c5d1b8b" +SRC_URI[md5sum] = "29c2ab80f539dd285a8d99a23d616d3e" +SRC_URI[sha256sum] = "cb3f90c07e7ba547a8c467012bef23083a8e8c414c4a90e1b88c5a70dd7ece19" S = "${WORKDIR}/${PN}-${PV}" From e9108338f3ee799b68f5e7988cd8ec3fc47a3ad7 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 21 Jan 2020 17:41:54 +0100 Subject: [PATCH 106/120] firmware_qualcomm: ccimx6ul: fix CH7 calibration Update US Board Data File to fix a wrong calibration of channel 7 (2442 MHz). The rest of the file remains the same. The new BDF is: - bdwlan30_US.bin (f6ec3328309aaa3e187295446966ab27) https://jira.digi.com/browse/DEL-6922 Signed-off-by: Gonzalo Ruiz --- .../ccimx6ul/bdwlan30_US.bin | Bin 8124 -> 8124 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx6ul/bdwlan30_US.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/ccimx6ul/bdwlan30_US.bin index e923f41b675424bf1472a4f4e58d5f73d48d8108..d3ad01bb6767e848453b53c02922baceb6c54bca 100644 GIT binary patch delta 67 zcmV-J0KEUaKfFH#ydPQ_u>>yz7L=HlfOb$vQ7xRFkehgPNKHX0`1qT%Ndu7r6b2Xw ZAPOi9FAg{oKNv?GPb60?UbF56&KWFy7CHa` delta 67 zcmV-J0KEUaKfFH#ydQ}Yu>>yz7K@mUh;LXyQ6HR}n4ExaSW8hS`1qc)Ndu7r6a*3m Z8VVu_DGV_WITAq^NgPonTC?s2&KWT177PFY From eb4ef7261004f866d46925737e728a78aa2354dc Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 21 Jan 2020 15:54:33 +0100 Subject: [PATCH 107/120] xbee: add support for multiple XBee interfaces XBEE_RESET_N_GPIO and XBEE_SLEEP_RQ_GPIO can now be comma-separated lists of GPIO indexes instead of just a single index. Modify the xbee-init script to support this change and modify the sed script in xbee.bb to allow commas in the aforementioned variables. https://jira.digi.com/browse/DEL-6887 Signed-off-by: Gabriel Valcazar --- .../recipes-connectivity/xbee/xbee.bb | 4 +-- .../recipes-connectivity/xbee/xbee/xbee-init | 36 ++++++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb index 26e796859..35f768c2a 100644 --- a/meta-digi-dey/recipes-connectivity/xbee/xbee.bb +++ b/meta-digi-dey/recipes-connectivity/xbee/xbee.bb @@ -18,8 +18,8 @@ do_install() { install -d ${D}${sysconfdir}/init.d/ install -m 0755 ${WORKDIR}/xbee-init ${D}${sysconfdir}/ ln -sf /etc/xbee-init ${D}${sysconfdir}/init.d/xbee-init - sed -i -e "s,##XBEE_RESET_N_GPIO##,${XBEE_RESET_N_GPIO},g" \ - -e "s,##XBEE_SLEEP_RQ_GPIO##,${XBEE_SLEEP_RQ_GPIO},g" \ + sed -i -e "s/##XBEE_RESET_N_GPIO##/${XBEE_RESET_N_GPIO}/g" \ + -e "s/##XBEE_SLEEP_RQ_GPIO##/${XBEE_SLEEP_RQ_GPIO}/g" \ ${D}${sysconfdir}/xbee-init install -d ${D}${systemd_unitdir}/system/ diff --git a/meta-digi-dey/recipes-connectivity/xbee/xbee/xbee-init b/meta-digi-dey/recipes-connectivity/xbee/xbee/xbee-init index 9236a2dc6..19909cf5a 100644 --- a/meta-digi-dey/recipes-connectivity/xbee/xbee/xbee-init +++ b/meta-digi-dey/recipes-connectivity/xbee/xbee/xbee-init @@ -33,29 +33,47 @@ set_gpio_value() { xbee_init() { # Power cycle XBEE_RESET_N - request_gpio_out ${XBEE_RESET_N_GPIO} - set_gpio_value ${XBEE_RESET_N_GPIO} 0 - set_gpio_value ${XBEE_RESET_N_GPIO} 1 + request_gpio_out ${1} + set_gpio_value ${1} 0 + set_gpio_value ${1} 1 # Set low XBEE_SLEEP_RQ - request_gpio_out ${XBEE_SLEEP_RQ_GPIO} - set_gpio_value ${XBEE_SLEEP_RQ_GPIO} 0 + request_gpio_out ${2} + set_gpio_value ${2} 0 } xbee_stop() { - free_gpio ${XBEE_RESET_N_GPIO} - free_gpio ${XBEE_SLEEP_RQ_GPIO} + free_gpio ${1} + free_gpio ${2} +} + +xbee_iterate_list() { + i=0 + for RESET in $(echo ${XBEE_RESET_N_GPIO} | sed "s/,/ /g"); do + j=0 + for SLEEP in $(echo ${XBEE_SLEEP_RQ_GPIO} | sed "s/,/ /g"); do + if [ "${i}" = "${j}" ]; then + if [ "${1}" = "start" ]; then + xbee_init ${RESET} ${SLEEP} + elif [ "${1}" = "stop" ]; then + xbee_stop ${RESET} ${SLEEP} + fi + fi + j="$((j + 1))" + done + i="$((i + 1))" + done } case "$1" in start) echo -n "Starting XBee hardware: " - xbee_init + xbee_iterate_list start echo "done." ;; stop) echo -n "Stopping XBee hardware: " - xbee_stop + xbee_iterate_list stop echo "done." ;; restart) From 30b0db051acf3b8b192b4fae278dd55246df9c1a Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Tue, 21 Jan 2020 15:57:24 +0100 Subject: [PATCH 108/120] ccimx8mn-dvk: add both XBee interfaces to the xbee-init script Now that xbee-init supports multiple interfaces, add the XBee Cellular GPIOs to the already existing XBee User ones to it so it can handle both of them on the ccimx8mn DVK. https://jira.digi.com/browse/DEL-6887 Signed-off-by: Gabriel Valcazar --- meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf index 2b2706544..4c24b550a 100644 --- a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -24,9 +24,9 @@ SERIAL_CONSOLES ?= "115200;ttymxc2" # Bluetooth tty BT_TTY ?= "ttymxc1" -# XBee2 -XBEE_RESET_N_GPIO ?= "8" -XBEE_SLEEP_RQ_GPIO ?= "7" +# XBees +XBEE_RESET_N_GPIO ?= "508,8" +XBEE_SLEEP_RQ_GPIO ?= "504,7" XBEE_TTY ?= "ttymxc3" # U-Boot script to be copied to the boot image From d9cb58097688e2fa58b9bf93adbba37b01cbd804 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Wed, 22 Jan 2020 11:25:50 +0100 Subject: [PATCH 109/120] firmware-qualcomm: remove reference to fakeboar_US.bin This file does not longer exist. It has been replaced by bdwlan30_US.bin, which is already included to the community driver option. Signed-off-by: Gonzalo Ruiz --- meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb | 1 - 1 file changed, 1 deletion(-) diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 69ab65a49..1e5c5c4d0 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -42,7 +42,6 @@ FW_QCA6574_WIFI_COMMUNITY = " \ file://qca6574_community/firmware-6.bin \ file://qca6574_community/notice_ath10k_firmware-4.txt \ file://qca6574_community/notice_ath10k_firmware-6.txt \ - file://qca6574_proprietary/fakeboar_US.bin \ " FW_QUALCOMM_WIFI ?= "${FW_QCA65X4_SDIO_PROPRIETARY}" From beff8e4adbd8935ae24765f597daaf2439a95b89 Mon Sep 17 00:00:00 2001 From: Hector Bujanda Date: Wed, 22 Jan 2020 10:38:22 +0100 Subject: [PATCH 110/120] mca-tool: update to v1.20 Includes: - add support for ccimx8mn. - add support to configure pwrio line https://jira.digi.com/browse/DEL-6866 https://jira.digi.com/browse/CC6UL-1107 Signed-off-by: Hector Bujanda --- .../mca/{mca-tool_1.19.bb => mca-tool_1.20.bb} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename meta-digi-arm/recipes-digi/mca/{mca-tool_1.19.bb => mca-tool_1.20.bb} (62%) diff --git a/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb b/meta-digi-arm/recipes-digi/mca/mca-tool_1.20.bb similarity index 62% rename from meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb rename to meta-digi-arm/recipes-digi/mca/mca-tool_1.20.bb index 0feeeb68d..0e5e7bf00 100644 --- a/meta-digi-arm/recipes-digi/mca/mca-tool_1.19.bb +++ b/meta-digi-arm/recipes-digi/mca/mca-tool_1.20.bb @@ -8,13 +8,13 @@ PKGNAME = "mca_tool" # ARM tarball SRC_URI_arm = "${DIGI_PKG_SRC}/${PKGNAME}-${PV}-${TUNE_ARCH}.tar.gz;name=arm" -SRC_URI[arm.md5sum] = "f677ccb2b6b627838c028f2281aa5b8c" -SRC_URI[arm.sha256sum] = "180ad5cdb9ddce7980db8019e9e710fcabde39ed896614f3ec8a05fedeb479f1" +SRC_URI[arm.md5sum] = "2007a858cd8f82ae2ddbff43f437335a" +SRC_URI[arm.sha256sum] = "d9a0c1ca1c9f20041602edd585c31bd79b75bc8d8a74648d1809350e731af3d5" # AARCH64 tarball SRC_URI_aarch64 = "${DIGI_PKG_SRC}/${PKGNAME}-${PV}-${TUNE_ARCH}.tar.gz;name=aarch64" -SRC_URI[aarch64.md5sum] = "183966e276383585048b85bfdf38fb49" -SRC_URI[aarch64.sha256sum] = "e7d0f375bd50b2f1936ba4770e64e8dc8f14af39cee4a85e26e4a22843a5638a" +SRC_URI[aarch64.md5sum] = "600451f7312a130c63f3b3b5c7abdbb6" +SRC_URI[aarch64.sha256sum] = "1acc7498943662e7e5bd26a67d2733a4814823170ba0756313459cb0e68e6e5f" S = "${WORKDIR}/${PKGNAME}-${PV}" From c005b004aed8e9542899f3b8dfe8a0522b4115e9 Mon Sep 17 00:00:00 2001 From: Hector Bujanda Date: Wed, 22 Jan 2020 10:54:05 +0100 Subject: [PATCH 111/120] ccimx8mn-dvk: fix SERIAL_CONSOLES to ttymxc0 The ccimx8mn console is on ttymxc0 (uart1 thanks to aliases). https://jira.digi.com/browse/DEL-6876 Signed-off-by: Hector Bujanda --- meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf index 4c24b550a..36b6b1197 100644 --- a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -19,7 +19,7 @@ KERNEL_DEVICETREE ?= " \ digi/ccimx8mn-dvk.dtb \ " -SERIAL_CONSOLES ?= "115200;ttymxc2" +SERIAL_CONSOLES ?= "115200;ttymxc0" # Bluetooth tty BT_TTY ?= "ttymxc1" From 571e4a521b1ffb6c022fc3fa151e4b6b66559699 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Fri, 24 Jan 2020 13:19:36 +0100 Subject: [PATCH 112/120] ccimx8x-sbc-express: add XBee TTY device Signed-off-by: Javier Viguera --- meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf index 3884f0242..674bf02c7 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf @@ -25,6 +25,7 @@ BT_TTY ?= "ttyLP1" # XBee XBEE_RESET_N_GPIO ?= "397" XBEE_SLEEP_RQ_GPIO ?= "400" +XBEE_TTY ?= "ttyLP0" # U-Boot script to be copied to the boot image BOOT_SCRIPTS = "boot.scr:boot.scr" From a8b3a130b70ace416776e4e5715c7cb54b47b1d9 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Fri, 24 Jan 2020 14:20:59 +0100 Subject: [PATCH 113/120] qualcomm.sh: remove regulatory domain support Regulatory domain support will be added completely with the 'regulatory-addon'. Also simplify symlink management now that BDF file has the same name for every platform. https://jira.digi.com/browse/DEL-6841 Signed-off-by: Gonzalo Ruiz --- .../kernel-module-qualcomm/qualcomm.sh | 58 ++----------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh index bcc6e8a14..d196ff416 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/qualcomm.sh @@ -81,69 +81,21 @@ if ! cmp -s ${TMP_MACFILE} ${MACFILE}; then fi rm -f "${TMP_MACFILE}" -OTP_REGION_CODE="$(cat /proc/device-tree/digi,hwid,cert 2>/dev/null | tr -d '\0')" -DTB_REGION_CODE="$(cat /proc/device-tree/wireless/regulatory-domain 2>/dev/null | tr -d '\0')" -US_CODE="0x0" -WW_CODE="0x1" -JP_CODE="0x2" -# Check if the DTB_REGION_CODE is in the list of valid codes, -# if not use the OTP programmed value. -case "${DTB_REGION_CODE}" in - ${US_CODE} | ${WW_CODE} | ${JP_CODE}) - REGULATORY_DOMAIN="${DTB_REGION_CODE}";; - *) - if [ -n "${DTB_REGION_CODE}" ]; then - log "5" "[WARN] Invalid region code in device tree, using OTP value" - fi - REGULATORY_DOMAIN="${OTP_REGION_CODE}";; -esac - - # Create symbolic links to the proper FW files depending on the country region # Use a sub-shell here to change to firmware directory ( cd "${FIRMWARE_DIR}" - if [ -f "bdwlan30_US.bin" ] || [ -f "bdwlan30_World.bin" ]; then - BDATA_US="bdwlan30_US.bin" - BDATA_WW="bdwlan30_World.bin" - BDATA_LINK="bdwlan30.bin" - UTFBDATA_LINK="utfbd30.bin" - else - log "5" "[ERROR] Could not locate board data files" - exit 1 - fi - - BDATA_SOURCE="${BDATA_US}" - case "${REGULATORY_DOMAIN}" in - ${US_CODE}) - log "5" "Setting US wireless region";; - ${WW_CODE}|${JP_CODE}) - if [ -f "${BDATA_WW}" ]; then - log "5" "Setting WW (world wide) wireless region" - BDATA_SOURCE="${BDATA_WW}" - else - log "5" "[WARN] No WW (worldwide) board data file, using US" - fi - ;; - "") - log "5" "[WARN] region code not found, using US";; - *) - log "5" "[WARN] Invalid region code, using US";; - esac + BDATA_SOURCE="bdwlan30_US.bin" + log "5" "Setting US wireless region" # When defined, update the links only if they are wrong so we don't # rewrite the internal memory every time we boot - if [ -n "${BDATA_LINK}" ] && - ([ ! -f "${BDATA_LINK}" ] || - ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"); then + BDATA_LINK="bdwlan30.bin" + UTFBDATA_LINK="utfbd30.bin" + if ([ ! -f "${BDATA_LINK}" ] || ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"); then set_filesystem_rw_access ${FIRMWARE_DIR} ln -sf "${BDATA_SOURCE}" "${BDATA_LINK}" - fi - if [ -n "${UTFBDATA_LINK}" ] && - ([ ! -f "${UTFBDATA_LINK}" ] || - ! cmp -s "${UTFBDATA_LINK}" "${BDATA_SOURCE}"); then - set_filesystem_rw_access ${FIRMWARE_DIR} ln -sf "${BDATA_SOURCE}" "${UTFBDATA_LINK}" fi ) From 8ebc7588d5512e6b92202cefa9b347ed33c7894b Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Mon, 3 Feb 2020 17:59:35 +0100 Subject: [PATCH 114/120] cc8mn: libdigiapix: change default values for examples https://jira.digi.com/browse/DEL-6955 Signed-off-by: Francisco Gil --- .../libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf index 632987f1c..e2c401ab4 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix-git/ccimx8mn-dvk/libdigiapix.conf @@ -27,10 +27,10 @@ DEFAULT_I2C_BUS = 4 [PWM] -# PWM0 channel 2 on XBEE1 connector (MCA_IO15) -DEFAULT_PWM = 0,2 +# PWM0 channel 1 USER_LED1. +DEFAULT_PWM = 0,1 [ADC] -# ADC_IN0 on Expansion connector -DEFAULT_ADC = 0,0 +# MCA_IO1 (channel 1) at XBEE1_UART_TX. Not enabled by default. +DEFAULT_ADC = 0,1 From 31d8ff94fe36b071688d5ae6cca26661fd8c31ba Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Mon, 16 Dec 2019 16:14:13 +0100 Subject: [PATCH 115/120] meta-digi-arm: u-boot: Update recipes with new u-boot version This commit updates the recipes to use the new u-boot version. Signed-off-by: Mike Engel --- meta-digi-arm/conf/machine/include/digi-defaults.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc | 3 +-- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb | 9 +++++++++ .../recipes-digi/trustfence/trustfence-sign-tools_git.bb | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb diff --git a/meta-digi-arm/conf/machine/include/digi-defaults.inc b/meta-digi-arm/conf/machine/include/digi-defaults.inc index 91bbe0bfc..8e86a5d57 100644 --- a/meta-digi-arm/conf/machine/include/digi-defaults.inc +++ b/meta-digi-arm/conf/machine/include/digi-defaults.inc @@ -12,7 +12,7 @@ PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg" # Platform Linux U-Boot # ------------------------------------------------- # ccimx6ul 4.14, 4.20 2017.03 -# ccimx8x 4.14 2018.03, 2017.03 (both packaged in imx-boot) +# ccimx8x 4.14 2019.04, 2018.03, 2017.03 (all packaged in imx-boot) # ccimx8mn 4.14 2018.03 (packaged in imx-boot) # diff --git a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc index 83a50c979..ab99d671a 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc @@ -4,7 +4,7 @@ require recipes-bsp/u-boot/u-boot.inc DESCRIPTION = "Bootloader for Digi platforms" LICENSE = "GPLv2+" -LIC_FILES_CHKSUM = "file://Licenses/README;md5=a2c678cfd4a4d97135585cad908541c6" +LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e" SECTION = "bootloaders" DEPENDS += "bc-native dtc-native u-boot-mkimage-native" @@ -63,7 +63,6 @@ do_compile () { if [ $j -eq $i ] then oe_runmake -C ${S} O=${B}/${config} ${config} - # Reconfigure U-Boot with Digi UBOOT_EXTRA_CONF for var in ${UBOOT_EXTRA_CONF}; do echo "${var}" >> ${B}/${config}/.config diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb new file mode 100644 index 000000000..7bcfbd8d2 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb @@ -0,0 +1,9 @@ +# Copyright (C) 2019 Digi International + +require digi-u-boot.inc +DEPENDS += "flex-native bison-native" + +SRCBRANCH = "v2019.04/master" +SRCREV = "${AUTOREV}" + +COMPATIBLE_MACHINE = "(ccimx8x)" \ No newline at end of file diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb index a4e47863e..705f660b4 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb @@ -6,6 +6,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425 DEPENDS = "trustfence-cst coreutils util-linux" SRCBRANCH = "v2017.03/master" +SRCBRANCH_ccimx8x = "v2019.04/master" SRCREV = "${AUTOREV}" S = "${WORKDIR}" From 5beec04b6adfaadaa2bac059662083c0ef607a40 Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Thu, 2 Jan 2020 17:32:42 +0100 Subject: [PATCH 116/120] trustfence: Add Trustfence support for CCMX8X This commit adds Trustfence support for the CCMX8X platform. Signed-off-by: Mike Engel https://jira.digi.com/browse/DEL-6917 --- .../classes/image_types_digi.bbclass | 8 +- meta-digi-arm/conf/machine/include/ccimx6.inc | 2 + .../conf/machine/include/ccimx6ul.inc | 2 + .../conf/machine/include/ccimx8x.inc | 10 + .../imx-mkimage/imx-boot_0.2.bbappend | 19 + .../trustfence-cst/trustfence-cst.inc | 11 +- ...005-ahab_pki_tree.sh-automate-script.patch | 206 ++++++++++ ...-use-a-random-password-for-the-defau.patch | 28 ++ .../recipes-bsp/u-boot/digi-u-boot.inc | 18 +- .../{encrypt_uimage => encrypt_hab} | 0 .../trustfence-sign-tools/sign_ahab | 23 ++ .../{sign_uimage => sign_hab} | 0 .../trustfence-sign-kernel.sh | 352 +++++++++++------- .../trustfence/trustfence-sign-tools_git.bb | 22 +- .../recipes-kernel/linux/linux-dey.inc | 58 ++- meta-digi-dey/classes/trustfence.bbclass | 13 +- .../recovery/recovery-initramfs.bb | 9 +- 17 files changed, 602 insertions(+), 179 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0005-ahab_pki_tree.sh-automate-script.patch create mode 100644 meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0006-ahab_pki_tree.sh-use-a-random-password-for-the-defau.patch rename meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/{encrypt_uimage => encrypt_hab} (100%) create mode 100644 meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_ahab rename meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/{sign_uimage => sign_hab} (100%) diff --git a/meta-digi-arm/classes/image_types_digi.bbclass b/meta-digi-arm/classes/image_types_digi.bbclass index bbfe2668d..5ebdbf869 100644 --- a/meta-digi-arm/classes/image_types_digi.bbclass +++ b/meta-digi-arm/classes/image_types_digi.bbclass @@ -206,16 +206,18 @@ trustence_sign_cpio() { [ -n "${TRUSTFENCE_KEY_INDEX}" ] && export CONFIG_KEY_INDEX="${TRUSTFENCE_KEY_INDEX}" [ -n "${TRUSTFENCE_DEK_PATH}" ] && [ "${TRUSTFENCE_DEK_PATH}" != "0" ] && export CONFIG_DEK_PATH="${TRUSTFENCE_DEK_PATH}" + if [ "${SIGN_MODE}" = "AHAB" ]; then + ${DEPLOY_DIR_IMAGE}/imx-boot-tools/mkimage_imx8 -soc ${MX8_SOC_VAR} -rev ${MX8_CHIP_REV} -c -ap ${1} a35 ${RAM_CONTAINER_LOC_TF} -out ${1}-mkimg + mv "${1}-mkimg" "${1}" + fi # Sign/encrypt the ramdisk trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -i "${1}" "${1}.tf" - else - # Copy the image with no changes - cp "${1}" "${1}.tf" fi } CONVERSIONTYPES += "tf" CONVERSION_CMD_tf = "trustence_sign_cpio ${IMAGE_NAME}.rootfs.${type}" CONVERSION_DEPENDS_tf = "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'trustfence-sign-tools-native', '', d)}" +CONVERSION_DEPENDS_tf += "${@oe.utils.conditional('SIGN_MODE', 'AHAB', 'imx-mkimage', '', d)}" IMAGE_TYPES += "cpio.gz.u-boot.tf" ################################################################################ diff --git a/meta-digi-arm/conf/machine/include/ccimx6.inc b/meta-digi-arm/conf/machine/include/ccimx6.inc index a426af847..0a4d41c03 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6.inc @@ -43,3 +43,5 @@ MACHINE_EXTRA_RRECOMMENDS += " \ " MACHINE_FEATURES += "accel-graphics accel-video wifi bluetooth pci" + +SIGN_MODE = "HAB" diff --git a/meta-digi-arm/conf/machine/include/ccimx6ul.inc b/meta-digi-arm/conf/machine/include/ccimx6ul.inc index 96349cf22..be96b3aba 100644 --- a/meta-digi-arm/conf/machine/include/ccimx6ul.inc +++ b/meta-digi-arm/conf/machine/include/ccimx6ul.inc @@ -57,3 +57,5 @@ MKUBIFS_BOOT_ARGS ?= "-m 2048 -e 126976 -c 255" # mkfs.ubifs parameters for rootfs partition # Max LEB count (-c 8191) calculated for a partition of up to 1 GiB considering 128 KiB erase-block size. MKUBIFS_ARGS ?= "-m 2048 -e 126976 -c 8191" + +SIGN_MODE = "HAB" diff --git a/meta-digi-arm/conf/machine/include/ccimx8x.inc b/meta-digi-arm/conf/machine/include/ccimx8x.inc index 20a37aacc..81a3cddb3 100644 --- a/meta-digi-arm/conf/machine/include/ccimx8x.inc +++ b/meta-digi-arm/conf/machine/include/ccimx8x.inc @@ -72,6 +72,16 @@ KERNEL_IMAGETYPE = "Image.gz" VIRTUAL-RUNTIME_init_manager ?= "systemd" VIRTUAL-RUNTIME_initscripts ?= "initscripts" +# For i.MX 8 silicon chip revision +MX8_CHIP_REV ?= "B0" +MX8_SOC_VAR ?= "QX" +SIGN_MODE = "AHAB" + +# For Trustfence container header RAM locations +RAM_CONTAINER_LOC_BOOT = "0x80280000" +RAM_CONTAINER_LOC_DTB = "0x82000000" +RAM_CONTAINER_LOC_TF = "0x82100000" + # Adding 'wayland' along with 'x11' enables the xwayland backend # Vulkan is necessary for wayland to build DISTRO_FEATURES_append = " wayland vulkan systemd pam" diff --git a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend index 99ab339a1..ab0299104 100644 --- a/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend +++ b/meta-digi-arm/recipes-bsp/imx-mkimage/imx-boot_0.2.bbappend @@ -11,6 +11,7 @@ SRC_URI_append_ccimx8x = " file://0001-iMX8QX-remove-SC_BD_FLAGS_ALT_CONFIG-flag IMX_EXTRA_FIRMWARE_ccimx8x = "digi-sc-firmware imx-seco" DEPENDS_append_ccimx8x = " coreutils-native" +DEPENDS_append_ccimx8x += "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'trustfence-sign-tools-native', '', d)}" # For i.MX 8, this package aggregates the imx-m4-demos # output. Note that this aggregation replaces the aggregation @@ -203,4 +204,22 @@ do_deploy () { } +do_deploy_append () { + if [ "${TRUSTFENCE_SIGN}" = "1" ] && [ "${SIGN_MODE}" = "AHAB" ]; then + export CONFIG_SIGN_KEYS_PATH="${TRUSTFENCE_SIGN_KEYS_PATH}" + [ -n "${TRUSTFENCE_KEY_INDEX}" ] && export CONFIG_KEY_INDEX="${TRUSTFENCE_KEY_INDEX}" + [ -n "${TRUSTFENCE_DEK_PATH}" ] && [ "${TRUSTFENCE_DEK_PATH}" != "0" ] && export CONFIG_DEK_PATH="${TRUSTFENCE_DEK_PATH}" + + # Sign U-boot image + for ramc in ${RAM_CONFIGS}; do + trustfence-sign-ahab-uboot.sh ${DEPLOYDIR}/${UBOOT_PREFIX}-${MACHINE}-${ramc}.bin ${DEPLOYDIR}/${UBOOT_PREFIX}-${MACHINE}-${ramc}-signed.bin + done + + cd ${DEPLOYDIR} + cp ${B}/${config}SRK_efuses.bin ${DEPLOYDIR} + install ${B}/${config}SRK_efuses.bin SRK_efuses-${PV}-${PR}.bin + ln -sf SRK_efuses-${PV}-${PR}.bin SRK_efuses.bin + fi +} + COMPATIBLE_MACHINE = "(ccimx8x|ccimx8mn)" diff --git a/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst.inc b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst.inc index 54ac3ec29..9639c584a 100644 --- a/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst.inc +++ b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst.inc @@ -13,6 +13,8 @@ SRC_URI = " \ file://0002-hab4_pki_tree.sh-automate-script.patch \ file://0003-openssl_helper-use-dev-urandom-as-seed-source.patch \ file://0004-hab4_pki_tree.sh-usa-a-random-password-for-the-defau.patch \ + file://0005-ahab_pki_tree.sh-automate-script.patch \ + file://0006-ahab_pki_tree.sh-use-a-random-password-for-the-defau.patch \ file://Makefile \ " @@ -41,7 +43,14 @@ do_install() { install -d ${D}${bindir} install -m 0755 linux64/cst ${D}${bindir}/cst install -m 0755 $(find linux64 -type f -name srktool) ${D}${bindir}/srktool - install -m 0755 keys/hab4_pki_tree.sh ${D}${bindir}/trustfence-gen-pki.sh + if [ "${SIGN_MODE}" = "AHAB" ]; then + install -m 0755 keys/ahab_pki_tree.sh ${D}${bindir}/trustfence-gen-pki.sh + elif [ "${SIGN_MODE}" = "HAB" ]; then + install -m 0755 keys/hab4_pki_tree.sh ${D}${bindir}/trustfence-gen-pki.sh + else + bberror "Unkown SIGN_MODE value" + exit 1 + fi install -m 0755 ca/openssl.cnf ${D}${bindir}/openssl.cnf install -m 0755 ca/v3_ca.cnf ${D}${bindir}/v3_ca.cnf install -m 0755 ca/v3_usr.cnf ${D}${bindir}/v3_usr.cnf diff --git a/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0005-ahab_pki_tree.sh-automate-script.patch b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0005-ahab_pki_tree.sh-automate-script.patch new file mode 100644 index 000000000..d238c945c --- /dev/null +++ b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0005-ahab_pki_tree.sh-automate-script.patch @@ -0,0 +1,206 @@ +From: Mike Engel +Date: Fri, 24 Jan 2020 17:31:50 +0100 +Subject: [PATCH] ahab_pki_tree.sh: automate script + +Signed-off-by: Mike Engel +--- + keys/ahab_pki_tree.sh | 116 ++++++++++++++++++------------------------------------- + 1 file changed, 38 insertions(+), 78 deletions(-) + +diff --git a/keys/ahab_pki_tree.sh b/keys/ahab_pki_tree.sh +index 988c27e..00dd143 100755 +--- a/keys/ahab_pki_tree.sh ++++ b/keys/ahab_pki_tree.sh +@@ -47,74 +47,36 @@ + # + #----------------------------------------------------------------------------- + +-printf "\n" +-printf " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" +-printf " This script is a part of the Code signing tools for NXP's\n" +-printf " Advanced High Assurance Boot. It generates a basic PKI tree. The\n" +-printf " PKI tree consists of one or more Super Root Keys (SRK), with each\n" +-printf " SRK having one subordinate keys: \n" +-printf " + a Signing key (SGK) \n" +-printf " Additional keys can be added to the PKI tree but a separate \n" +-printf " script is available for this. This this script assumes openssl\n" +-printf " is installed on your system and is included in your search \n" +-printf " path. Finally, the private keys generated are password \n" +-printf " protectedwith the password provided by the file key_pass.txt.\n" +-printf " The format of the file is the password repeated twice:\n" +-printf " my_password\n" +-printf " my_password\n" +-printf " All private keys in the PKI tree are in PKCS #8 format will be\n" +-printf " protected by the same password.\n\n" +-printf " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" +- +-stty erase  +- +-printf "Do you want to use an existing CA key (y/n)?: \b" +-read existing_ca +-if [ $existing_ca = "y" ] +-then +- printf "Enter CA key name: \b" +- read ca_key +- printf "Enter CA certificate name: \b" +- read ca_cert ++SCRIPT_BASEDIR="$(cd $(dirname ${0}) && pwd)" ++CSF_PATH="${1}" ++if [ ! -d "${CSF_PATH}" ]; then ++ echo "Invalid CSF_PATH: ${CSF_PATH}" ++ exit 1 + fi + +-printf "Do you want to use Elliptic Curve Cryptography (y/n)?: \b" +-read use_ecc +-if [ $use_ecc = "y" ] +-then +- printf "Enter length for elliptic curve to be used for PKI tree:\n" +- printf "Possible values p256, p384, p521: \b" +- read kl +- +- # Confirm that a valid key length has been entered +- case $kl in +- p256) +- cn="prime256v1" ;; +- p384) +- cn="secp384r1" ;; +- p521) +- cn="secp521r1" ;; +- *) +- echo Invalid key length. Supported key lengths: 256, 384, 521 +- exit 1 ;; +- esac +-else +- printf "Enter key length in bits for PKI tree: \b" +- read kl +- +- # Confirm that a valid key length has been entered +- case $kl in +- 2048) ;; +- 3072) ;; +- 4096) ;; +- *) +- echo Invalid key length. Supported key lengths: 2048, 3072, 4096 +- exit 1 ;; +- esac +-fi ++cd "${CSF_PATH}" ++ ++[ -d crts ] || mkdir crts ++[ -d keys ] || mkdir keys ++ ++cd keys ++ ++use_ecc="y" ++existing_ca="n" ++kl="p521" ++cn="secp521r1" ++ ++# Confirm that a valid key length has been entered ++case $kl in ++ p256);; ++ p384);; ++ p521);; ++ *) ++ echo Invalid key length. Supported key lengths: 256, 384, 521 ++ exit 1 ;; ++esac + +-printf "Enter the digest algorithm to use: \b" +-read da ++da="sha512" + + # Confirm that a valid digest algorithm has been entered + case $da in +@@ -126,8 +88,7 @@ case $da in + exit 1 ;; + esac + +-printf "Enter PKI tree duration (years): \b" +-read duration ++duration="10" + + # Compute validity period + val_period=$((duration*365)) +@@ -144,8 +105,7 @@ then + fi + + # Check if SRKs should be generated as CA certs or user certs +-printf "Do you want the SRK certificates to have the CA flag set? (y/n)?: \b" +-read srk_ca ++srk_ca="y" + + # Check that the file "serial" is present, if not create it: + if [ ! -f serial ] +@@ -201,7 +161,7 @@ then + -x509 -extensions v3_ca \ + -keyout temp_ca.pem \ + -out ${ca_cert}.pem \ +- -days ${val_period} -config ../ca/openssl.cnf ++ -days ${val_period} -config "${SCRIPT_BASEDIR}/openssl.cnf" + + # Generate CA key in PKCS #8 format - both PEM and DER + openssl pkcs8 -passin file:./key_pass.txt -passout file:./key_pass.txt \ +@@ -218,7 +178,7 @@ then + openssl x509 -inform PEM -outform DER -in ${ca_cert}.pem -out ${ca_cert}.der + + # Cleanup +- \rm temp_ca.pem ++ rm temp_ca.pem + fi + + +@@ -292,7 +252,7 @@ then + -out ${srk_key}.pem + + # Cleanup +- \rm ./temp_srk.pem ./temp_srk_req.pem ++ rm ./temp_srk.pem ./temp_srk_req.pem + i=$((i+1)) + done + else +@@ -341,10 +301,10 @@ do + -in ./temp_srk_req.pem \ + -cert ${ca_cert}.pem \ + -keyfile ${ca_key}.pem \ +- -extfile ../ca/v3_ca.cnf \ ++ -extfile "${SCRIPT_BASEDIR}/v3_ca.cnf" \ + -out ${srk_crt}.pem \ + -days ${val_period} \ +- -config ../ca/openssl.cnf ++ -config "${SCRIPT_BASEDIR}/openssl.cnf" + + # Convert SRK Certificate to DER format + openssl x509 -inform PEM -outform DER \ +@@ -365,7 +325,7 @@ do + -out ${srk_key}.pem + + # Cleanup +- \rm ./temp_srk.pem ./temp_srk_req.pem ++ rm ./temp_srk.pem ./temp_srk_req.pem + + echo + echo ++++++++++++++++++++++++++++++++++++++++ +@@ -410,10 +370,10 @@ do + -in ./temp_sgk_req.pem \ + -cert ${srk_crt_i} \ + -keyfile ${srk_key_i} \ +- -extfile ../ca/v3_usr.cnf \ ++ -extfile "${SCRIPT_BASEDIR}/v3_usr.cnf" \ + -out ${sgk_crt}.pem \ + -days ${val_period} \ +- -config ../ca/openssl.cnf ++ -config "${SCRIPT_BASEDIR}/openssl.cnf" + + # Convert SGK Certificate to DER format + openssl x509 -inform PEM -outform DER \ +@@ -432,7 +392,7 @@ do + -out ${sgk_key}.pem + + # Cleanup +- \rm ./temp_sgk.pem ./temp_sgk_req.pem ++ rm ./temp_sgk.pem ./temp_sgk_req.pem + + i=$((i+1)) + done diff --git a/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0006-ahab_pki_tree.sh-use-a-random-password-for-the-defau.patch b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0006-ahab_pki_tree.sh-use-a-random-password-for-the-defau.patch new file mode 100644 index 000000000..ab49ef09a --- /dev/null +++ b/meta-digi-arm/recipes-bsp/trustfence-cst/trustfence-cst/0006-ahab_pki_tree.sh-use-a-random-password-for-the-defau.patch @@ -0,0 +1,28 @@ +From: Mike Engel +Date: Fri, 24 Jan 2020 17:47:56 +0100 +Subject: [PATCH] ahab_pki_tree.sh: use a random password for the default PKI + generation + +Signed-off-by: Mike Engel +--- + keys/ahab_pki_tree.sh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/keys/ahab_pki_tree.sh b/keys/ahab_pki_tree.sh +index 00dd143..8b81143 100755 +--- a/keys/ahab_pki_tree.sh ++++ b/keys/ahab_pki_tree.sh +@@ -117,9 +117,10 @@ fi + # Check that the file "key_pass.txt" is present, if not create it with default user/pwd: + if [ ! -f key_pass.txt ] + then +- echo "test" > key_pass.txt +- echo "test" >> key_pass.txt +- echo "A default file 'key_pass.txt' was created with password = test!" ++ password="$(openssl rand -base64 32)" ++ echo "${password}" > key_pass.txt ++ echo "${password}" >> key_pass.txt ++ echo "A file 'key_pass.txt' was created with a random password!" + fi + + # The following is required otherwise OpenSSL complains diff --git a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc index ab99d671a..9b40be959 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc @@ -79,7 +79,7 @@ do_compile () { unset k # Secure boot artifacts - if [ "${TRUSTFENCE_SIGN}" = "1" ] + if [ "${TRUSTFENCE_SIGN}" = "1" ] && [ "${SIGN_MODE}" = "HAB" ] then cp ${B}/${config}/u-boot-dtb-signed.imx ${B}/${config}/u-boot-dtb-signed-${type}.${UBOOT_SUFFIX} cp ${B}/${config}/u-boot-dtb-usb-signed.imx ${B}/${config}/u-boot-dtb-usb-signed-${type}.${UBOOT_SUFFIX} @@ -122,8 +122,7 @@ do_deploy_append() { cd ${DEPLOYDIR} rm -r ${UBOOT_BINARY}-${type} ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} u-boot-${type}.${UBOOT_SUFFIX} - if [ "${TRUSTFENCE_SIGN}" = "1" ] - then + if [ "${TRUSTFENCE_SIGN}" = "1" ] && [ "${SIGN_MODE}" = "HAB" ]; then install ${B}/${config}/SRK_efuses.bin SRK_efuses-${PV}-${PR}.bin ln -sf SRK_efuses-${PV}-${PR}.bin SRK_efuses.bin @@ -162,9 +161,11 @@ do_deploy_append() { [ -n "${TRUSTFENCE_DEK_PATH}" ] && [ "${TRUSTFENCE_DEK_PATH}" != "0" ] && export CONFIG_DEK_PATH="${TRUSTFENCE_DEK_PATH}" # Sign boot script - TMP_SIGNED_BOOTSCR="$(mktemp ${WORKDIR}/bootscr-signed.XXXXXX)" - trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -b "${DEPLOYDIR}/boot.scr" "${TMP_SIGNED_BOOTSCR}" - mv "${TMP_SIGNED_BOOTSCR}" "${DEPLOYDIR}/boot.scr" + if [ "${SIGN_MODE}" = "HAB" ]; then + TMP_SIGNED_BOOTSCR="$(mktemp ${WORKDIR}/bootscr-signed.XXXXXX)" + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -b "${DEPLOYDIR}/boot.scr" "${TMP_SIGNED_BOOTSCR}" + mv "${TMP_SIGNED_BOOTSCR}" "${DEPLOYDIR}/boot.scr" + fi fi rm -f ${TMP_BOOTSCR} } @@ -177,6 +178,11 @@ do_deploy_append_ccimx8x() { install -d ${DEPLOYDIR}/${BOOT_TOOLS} mv ${DEPLOYDIR}/u-boot* ${DEPLOYDIR}/${BOOT_TOOLS}/ mv ${DEPLOYDIR}/${UBOOT_SYMLINK}-* ${DEPLOYDIR}/${BOOT_TOOLS}/ + if [ "${TRUSTFENCE_SIGN}" = "1" ]; then + ${DEPLOY_DIR_IMAGE}/${BOOT_TOOLS}/mkimage_imx8 -soc ${MX8_SOC_VAR} -rev ${MX8_CHIP_REV} -c -ap ${DEPLOYDIR}/boot.scr a35 ${RAM_CONTAINER_LOC_BOOT} -out ${DEPLOYDIR}/boot-mkimg.scr + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -b "${DEPLOYDIR}/boot-mkimg.scr" "${DEPLOYDIR}/boot.scr" + rm -f ${DEPLOYDIR}/boot-mkimg.scr + fi } do_deploy_append_ccimx8mn() { diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/encrypt_uimage b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/encrypt_hab similarity index 100% rename from meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/encrypt_uimage rename to meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/encrypt_hab diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_ahab b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_ahab new file mode 100644 index 000000000..839649e77 --- /dev/null +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_ahab @@ -0,0 +1,23 @@ +# The syntax for this file is documented in the HAB Code Signing Tool +# User's Guid which is included in the CST package distributed by NXP +[Header] + Target = AHAB + Version = 1.0 + +[Install SRK] + # SRK table generated by srktool + File = "%srk_table%" + # Public key certificate in PEM format + Source = "%cert_img%" + # Index of the public key certificate within the SRK table (0 .. 3) + Source index = %key_index% + # Type of SRK set (NXP or OEM) + Source set = OEM + # bitmask of the revoked SRKs + Revocations = 0x%key_index% + +[Authenticate Data] + # Binary to be signed generated by mkimage + File = "%kernel-img%" + # Offsets = Container header Signature block (printed out by mkimage) + Offsets = %container_offset% %block_offset% \ No newline at end of file diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_uimage b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_hab similarity index 100% rename from meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_uimage rename to meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/sign_hab diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/trustfence-sign-kernel.sh b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/trustfence-sign-kernel.sh index 93e0629fd..9b25083c7 100755 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/trustfence-sign-kernel.sh +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools/trustfence-sign-kernel.sh @@ -1,9 +1,9 @@ #!/bin/sh #=============================================================================== # -# trustfence_sign_uimage.sh +# trustfence-sign-kernel.sh # -# Copyright (C) 2016 by Digi International Inc. +# Copyright (C) 2016-2020 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ Usage: ${SCRIPT_NAME} [OPTIONS] input-unsigned-image output-signed-image -i sign/encrypt initramfs -l sign/encrypt Linux image -Supported platforms: ccimx6, ccimx6ul +Supported platforms: ccimx6, ccimx6ul, ccimx8x EOF } @@ -64,14 +64,16 @@ if [ "${#}" != "2" ]; then exit 1 fi -# Negative offset with respect to CONFIG_RAM_START in which U-Boot -# copies the DEK blob. -DEK_BLOB_OFFSET="0x100" -CONFIG_CSF_SIZE="0x4000" - UIMAGE_PATH="$(readlink -e ${1})" TARGET="$(readlink -m ${2})" +# Negative offset with respect to CONFIG_RAM_START in which U-Boot +# copies the DEK blob. +if [ "${SIGN_MODE}" = "HAB" ]; then + DEK_BLOB_OFFSET="0x100" + CONFIG_CSF_SIZE="0x4000" +fi + # Read user configuration file (if used) [ -f .config ] && . ./.config @@ -81,43 +83,45 @@ if [ -z "${CONFIG_SIGN_KEYS_PATH}" ]; then fi [ -d "${CONFIG_SIGN_KEYS_PATH}" ] || mkdir "${CONFIG_SIGN_KEYS_PATH}" -if [ -n "${CONFIG_DEK_PATH}" ]; then - if [ ! -f "${CONFIG_DEK_PATH}" ]; then - echo "DEK not found. Generating random 256 bit DEK." - [ -d $(dirname ${CONFIG_DEK_PATH}) ] || mkdir -p $(dirname ${CONFIG_DEK_PATH}) - dd if=/dev/urandom of="${CONFIG_DEK_PATH}" bs=32 count=1 >/dev/null 2>&1 +if [ "${SIGN_MODE}" = "HAB" ]; then + if [ -n "${CONFIG_DEK_PATH}" ]; then + if [ ! -f "${CONFIG_DEK_PATH}" ]; then + echo "DEK not found. Generating random 256 bit DEK." + [ -d $(dirname ${CONFIG_DEK_PATH}) ] || mkdir -p $(dirname ${CONFIG_DEK_PATH}) + dd if=/dev/urandom of="${CONFIG_DEK_PATH}" bs=32 count=1 >/dev/null 2>&1 + fi + dek_size="$((8 * $(stat -L -c %s ${CONFIG_DEK_PATH})))" + if [ "${dek_size}" != "128" ] && [ "${dek_size}" != "192" ] && [ "${dek_size}" != "256" ]; then + echo "Invalid DEK size: ${dek_size} bits. Valid sizes are 128, 192 and 256 bits" + exit 1 + fi + ENCRYPT="true" fi - dek_size="$((8 * $(stat -L -c %s ${CONFIG_DEK_PATH})))" - if [ "${dek_size}" != "128" ] && [ "${dek_size}" != "192" ] && [ "${dek_size}" != "256" ]; then - echo "Invalid DEK size: ${dek_size} bits. Valid sizes are 128, 192 and 256 bits" + + if [ "${PLATFORM}" = "ccimx6" ]; then + CONFIG_FDT_LOADADDR="0x18000000" + CONFIG_RAMDISK_LOADADDR="0x19000000" + CONFIG_KERNEL_LOADADDR="0x12000000" + elif [ "${PLATFORM}" = "ccimx6ul" ]; then + CONFIG_FDT_LOADADDR="0x83000000" + CONFIG_RAMDISK_LOADADDR="0x83800000" + CONFIG_KERNEL_LOADADDR="0x80800000" + else + echo "Invalid platform: ${PLATFORM}" + echo "Supported platforms: ccimx6, ccimx6ul" exit 1 fi - ENCRYPT="true" -fi -if [ "${PLATFORM}" = "ccimx6" ]; then - CONFIG_FDT_LOADADDR="0x18000000" - CONFIG_RAMDISK_LOADADDR="0x19000000" - CONFIG_KERNEL_LOADADDR="0x12000000" -elif [ "${PLATFORM}" = "ccimx6ul" ]; then - CONFIG_FDT_LOADADDR="0x83000000" - CONFIG_RAMDISK_LOADADDR="0x83800000" - CONFIG_KERNEL_LOADADDR="0x80800000" -else - echo "Invalid platform: ${PLATFORM}" - echo "Supported platforms: ccimx6, ccimx6ul" - exit 1 -fi + [ "${ARTIFACT_DTB}" = "y" ] && CONFIG_RAM_START="${CONFIG_FDT_LOADADDR}" + [ "${ARTIFACT_INITRAMFS}" = "y" ] && CONFIG_RAM_START="${CONFIG_RAMDISK_LOADADDR}" + [ "${ARTIFACT_KERNEL}" = "y" ] && CONFIG_RAM_START="${CONFIG_KERNEL_LOADADDR}" + # bootscripts are loaded to $loadaddr, just like the kernel + [ "${ARTIFACT_BOOTSCRIPT}" = "y" ] && CONFIG_RAM_START="${CONFIG_KERNEL_LOADADDR}" -[ "${ARTIFACT_DTB}" = "y" ] && CONFIG_RAM_START="${CONFIG_FDT_LOADADDR}" -[ "${ARTIFACT_INITRAMFS}" = "y" ] && CONFIG_RAM_START="${CONFIG_RAMDISK_LOADADDR}" -[ "${ARTIFACT_KERNEL}" = "y" ] && CONFIG_RAM_START="${CONFIG_KERNEL_LOADADDR}" -# bootscripts are loaded to $loadaddr, just like the kernel -[ "${ARTIFACT_BOOTSCRIPT}" = "y" ] && CONFIG_RAM_START="${CONFIG_KERNEL_LOADADDR}" - -if [ -z "${CONFIG_RAM_START}" ]; then - echo "Specify the type of image to process (-b, -i, -d, or -l)" - exit 1 + if [ -z "${CONFIG_RAM_START}" ]; then + echo "Specify the type of image to process (-b, -i, -d, or -l)" + exit 1 + fi fi # Default values @@ -125,135 +129,197 @@ fi CONFIG_KEY_INDEX_1="$((CONFIG_KEY_INDEX + 1))" SRK_KEYS="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/SRK*crt.pem | sed s/\ /\,/g)" -CERT_CSF="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/CSF${CONFIG_KEY_INDEX_1}*crt.pem)" -CERT_IMG="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/IMG${CONFIG_KEY_INDEX_1}*crt.pem)" +if [ "${SIGN_MODE}" = "HAB" ]; then + CERT_CSF="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/CSF${CONFIG_KEY_INDEX_1}*crt.pem)" + CERT_IMG="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/IMG${CONFIG_KEY_INDEX_1}*crt.pem)" +fi n_commas="$(echo ${SRK_KEYS} | grep -o "," | wc -l)" -if [ "${n_commas}" -eq 3 ] && [ -f "${CERT_CSF}" ] && [ -f "${CERT_IMG}" ]; then - # PKI tree already exists. - echo "Using existing PKI tree" -elif [ "${n_commas}" -eq 0 ] || [ ! -f "${CERT_CSF}" ] || [ ! -f "${CERT_IMG}" ]; then - # Generate PKI - trustfence-gen-pki.sh "${CONFIG_SIGN_KEYS_PATH}" +if [ "${SIGN_MODE}" = "HAB" ]; then + if [ "${n_commas}" -eq 3 ] && [ -f "${CERT_CSF}" ] && [ -f "${CERT_IMG}" ]; then + # PKI tree already exists. + echo "Using existing PKI tree" + elif [ "${n_commas}" -eq 0 ] || [ ! -f "${CERT_CSF}" ] || [ ! -f "${CERT_IMG}" ]; then + # Generate PKI + trustfence-gen-pki.sh "${CONFIG_SIGN_KEYS_PATH}" - SRK_KEYS="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/SRK*crt.pem | sed s/\ /\,/g)" - CERT_CSF="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/CSF${CONFIG_KEY_INDEX_1}*crt.pem)" - CERT_IMG="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/IMG${CONFIG_KEY_INDEX_1}*crt.pem)" -else - echo "Inconsistent CST folder." - exit 1 + SRK_KEYS="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/SRK*crt.pem | sed s/\ /\,/g)" + CERT_CSF="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/CSF${CONFIG_KEY_INDEX_1}*crt.pem)" + CERT_IMG="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/IMG${CONFIG_KEY_INDEX_1}*crt.pem)" + else + echo "Inconsistent CST folder." + exit 1 + fi +elif [ "${SIGN_MODE}" = "AHAB" ]; then + if [ "${n_commas}" -eq 3 ] && [ "${SIGN_MODE}" = "AHAB" ]; then + # PKI tree already exists. Do nothing + echo "Using existing PKI tree" + elif [ "${n_commas}" -eq 0 ] && [ "${SIGN_MODE}" = "AHAB" ]; then + # Generate PKI + trustfence-gen-pki.sh "${CONFIG_SIGN_KEYS_PATH}" + + SRK_KEYS="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/SRK*crt.pem | sed s/\ /\,/g)" + else + echo "Inconsistent CST folder." + exit 1 + fi fi SRK_TABLE="$(pwd)/SRK_table.bin" +if [ "${SIGN_MODE}" = "HAB" ]; then + HAB_VER="hab_ver 4" + DIGEST="digest" + DIGEST_ALGO="sha256" + SRK_EFUSES="/dev/null" -# Other constants -GAP_FILLER="0x00" + # Other constants + GAP_FILLER="0x00" -# The DEK blob is placed by U-Boot just before the kernel image -dek_blob_offset="$((CONFIG_KERNEL_LOADADDR - DEK_BLOB_OFFSET))" + # The DEK blob is placed by U-Boot just before the kernel image + dek_blob_offset="$((CONFIG_KERNEL_LOADADDR - DEK_BLOB_OFFSET))" -# Compute the layout: sizes and offsets. -uimage_size="$(stat -L -c %s ${UIMAGE_PATH})" -uimage_offset="0x0" -pad_len="$(((uimage_size + 0x1000 - 1) & ~(0x1000 - 1)))" -auth_len="$((pad_len + 0x20))" -sig_len="$((auth_len + CONFIG_CSF_SIZE))" + # Compute the layout: sizes and offsets. + uimage_size="$(stat -L -c %s ${UIMAGE_PATH})" + uimage_offset="0x0" + pad_len="$(((uimage_size + 0x1000 - 1) & ~(0x1000 - 1)))" + auth_len="$((pad_len + 0x20))" + sig_len="$((auth_len + CONFIG_CSF_SIZE))" -ivt_uimage_start="$((auth_len - 0x20))" -ivt_ram_start="$((CONFIG_RAM_START + ivt_uimage_start))" -ivt_size="0x20" -csf_ram_start="$((ivt_ram_start + ivt_size))" -entrypoint_uimage_offset="0x100" -entrypoint_ram_start="$((CONFIG_RAM_START + entrypoint_uimage_offset))" -entrypoint_size="0x20" -header_uimage_offset="0x0" -header_ram_start="${CONFIG_RAM_START}" -header_size="0x40" + ivt_uimage_start="$((auth_len - 0x20))" + ivt_ram_start="$((CONFIG_RAM_START + ivt_uimage_start))" + ivt_size="0x20" + csf_ram_start="$((ivt_ram_start + ivt_size))" + entrypoint_uimage_offset="0x100" + entrypoint_ram_start="$((CONFIG_RAM_START + entrypoint_uimage_offset))" + entrypoint_size="0x20" + header_uimage_offset="0x0" + header_ram_start="${CONFIG_RAM_START}" + header_size="0x40" -r1_uimage_offset="${header_size}" -r1_ram_start="$((CONFIG_RAM_START + r1_uimage_offset))" -r1_size="$((entrypoint_uimage_offset - header_size ))" -r2_uimage_offset="$((entrypoint_uimage_offset + entrypoint_size))" -r2_ram_start="$((CONFIG_RAM_START + r2_uimage_offset))" -r2_size="$((ivt_uimage_start - (entrypoint_uimage_offset + entrypoint_size)))" + r1_uimage_offset="${header_size}" + r1_ram_start="$((CONFIG_RAM_START + r1_uimage_offset))" + r1_size="$((entrypoint_uimage_offset - header_size ))" + r2_uimage_offset="$((entrypoint_uimage_offset + entrypoint_size))" + r2_ram_start="$((CONFIG_RAM_START + r2_uimage_offset))" + r2_size="$((ivt_uimage_start - (entrypoint_uimage_offset + entrypoint_size)))" -# Generate actual CSF descriptor file from template -if [ "${ENCRYPT}" = "true" ]; then - sed -e "s,%ram_start%,${CONFIG_RAM_START},g" \ - -e "s,%srk_table%,${SRK_TABLE},g " \ - -e "s,%cert_csf%,${CERT_CSF},g" \ - -e "s,%cert_img%,${CERT_IMG},g" \ - -e "s,%uimage_path%,${TARGET},g" \ - -e "s,%key_index%,${CONFIG_KEY_INDEX},g" \ - -e "s,%dek_len%,${dek_size},g" \ - -e "s,%dek_path%,${CONFIG_DEK_PATH},g" \ - -e "s,%dek_offset%,${dek_blob_offset},g" \ - -e "s,%ivt_uimage_start%,${ivt_uimage_start},g" \ - -e "s,%ivt_ram_start%,${ivt_ram_start},g" \ - -e "s,%ivt_size%,${ivt_size},g" \ - -e "s,%entrypoint_uimage_offset%,${entrypoint_uimage_offset},g" \ - -e "s,%entrypoint_ram_start%,${entrypoint_ram_start},g" \ - -e "s,%entrypoint_size%,${entrypoint_size},g" \ - -e "s,%header_uimage_offset%,${header_uimage_offset},g" \ - -e "s,%header_ram_start%,${header_ram_start},g" \ - -e "s,%header_size%,${header_size},g" \ - -e "s,%r1_uimage_offset%,${r1_uimage_offset},g" \ - -e "s,%r1_ram_start%,${r1_ram_start},g" \ - -e "s,%r1_size%,${r1_size},g" \ - -e "s,%r2_uimage_offset%,${r2_uimage_offset},g" \ - -e "s,%r2_ram_start%,${r2_ram_start},g" \ - -e "s,%r2_size%,${r2_size},g" \ - "${SCRIPT_PATH}/csf_templates/encrypt_uimage" > csf_descriptor + # Generate actual CSF descriptor file from template + if [ "${ENCRYPT}" = "true" ]; then + sed -e "s,%ram_start%,${CONFIG_RAM_START},g" \ + -e "s,%srk_table%,${SRK_TABLE},g " \ + -e "s,%cert_csf%,${CERT_CSF},g" \ + -e "s,%cert_img%,${CERT_IMG},g" \ + -e "s,%uimage_path%,${TARGET},g" \ + -e "s,%key_index%,${CONFIG_KEY_INDEX},g" \ + -e "s,%dek_len%,${dek_size},g" \ + -e "s,%dek_path%,${CONFIG_DEK_PATH},g" \ + -e "s,%dek_offset%,${dek_blob_offset},g" \ + -e "s,%ivt_uimage_start%,${ivt_uimage_start},g" \ + -e "s,%ivt_ram_start%,${ivt_ram_start},g" \ + -e "s,%ivt_size%,${ivt_size},g" \ + -e "s,%entrypoint_uimage_offset%,${entrypoint_uimage_offset},g" \ + -e "s,%entrypoint_ram_start%,${entrypoint_ram_start},g" \ + -e "s,%entrypoint_size%,${entrypoint_size},g" \ + -e "s,%header_uimage_offset%,${header_uimage_offset},g" \ + -e "s,%header_ram_start%,${header_ram_start},g" \ + -e "s,%header_size%,${header_size},g" \ + -e "s,%r1_uimage_offset%,${r1_uimage_offset},g" \ + -e "s,%r1_ram_start%,${r1_ram_start},g" \ + -e "s,%r1_size%,${r1_size},g" \ + -e "s,%r2_uimage_offset%,${r2_uimage_offset},g" \ + -e "s,%r2_ram_start%,${r2_ram_start},g" \ + -e "s,%r2_size%,${r2_size},g" \ + "${SCRIPT_PATH}/csf_templates/encrypt_hab" > csf_descriptor + else + sed -e "s,%ram_start%,${CONFIG_RAM_START},g" \ + -e "s,%srk_table%,${SRK_TABLE},g" \ + -e "s,%image_offset%,${uimage_offset},g" \ + -e "s,%auth_len%,${auth_len},g" \ + -e "s,%cert_csf%,${CERT_CSF},g" \ + -e "s,%cert_img%,${CERT_IMG},g" \ + -e "s,%uimage_path%,${TARGET},g" \ + -e "s,%key_index%,${CONFIG_KEY_INDEX},g" \ + "${SCRIPT_PATH}/csf_templates/sign_hab" > csf_descriptor + fi else - sed -e "s,%ram_start%,${CONFIG_RAM_START},g" \ - -e "s,%srk_table%,${SRK_TABLE},g" \ - -e "s,%image_offset%,${uimage_offset},g" \ - -e "s,%auth_len%,${auth_len},g" \ - -e "s,%cert_csf%,${CERT_CSF},g" \ - -e "s,%cert_img%,${CERT_IMG},g" \ - -e "s,%uimage_path%,${TARGET},g" \ - -e "s,%key_index%,${CONFIG_KEY_INDEX},g" \ - "${SCRIPT_PATH}/csf_templates/sign_uimage" > csf_descriptor + SRK_EFUSES="$(pwd)/SRK_efuses.bin" + + # Other constants + KERNEL_START_OFFSET="0x0" + KERNEL_SIG_BLOCK_OFFSET="0x90" + KERNEL_NAME="${1}" + + HAB_VER="ahab" + DIGEST="sign_digest" + DIGEST_ALGO="sha512" + + # Compute the layout: sizes and offsets. + container_header_offset="${KERNEL_START_OFFSET}" + signature_block_offset="${KERNEL_SIG_BLOCK_OFFSET}" + + SRK_CERT_KEY_IMG="$(echo ${CONFIG_SIGN_KEYS_PATH}/crts/SRK${CONFIG_KEY_INDEX_1}*crt.pem | sed s/\ /\,/g)" + + sed -e "s,%srk_table%,${SRK_TABLE},g" \ + -e "s,%cert_img%,${SRK_CERT_KEY_IMG},g" \ + -e "s,%kernel-img%,${KERNEL_NAME},g" \ + -e "s,%key_index%,${CONFIG_KEY_INDEX},g" \ + -e "s,%container_offset%,${container_header_offset},g" \ + -e "s,%block_offset%,${signature_block_offset},g" \ + "${SCRIPT_PATH}/csf_templates/sign_ahab" > csf_descriptor + + if [ "${ENCRYPT}" = "true" ]; then + echo "[ERROR] Environment encryption is not supported." + exit 1 + fi fi # Generate SRK tables -srktool --hab_ver 4 --certs "${SRK_KEYS}" --table "${SRK_TABLE}" --efuses /dev/null --digest sha256 +srktool --${HAB_VER} --certs "${SRK_KEYS}" --table "${SRK_TABLE}" --efuses "${SRK_EFUSES}" --${DIGEST} "${DIGEST_ALGO}" if [ $? -ne 0 ]; then echo "[ERROR] Could not generate SRK tables" exit 1 fi -# Pad to IVT -objcopy -I binary -O binary --pad-to "${pad_len}" --gap-fill="${GAP_FILLER}" "${UIMAGE_PATH}" "${TARGET}" +if [ "${SIGN_MODE}" = "HAB" ]; then + # Pad to IVT + objcopy -I binary -O binary --pad-to "${pad_len}" --gap-fill="${GAP_FILLER}" "${UIMAGE_PATH}" "${TARGET}" -# Generate and attach IVT -# Fields: header, jump location, reserved (0), DCD pointer (null) -# boot data (null), self pointer, CSF pointer, reserved (0) -PRINTF="$(which printf)" -IVT_HEADER="0x402000D1" -{ - ${PRINTF} $(${PRINTF} "%08x" ${IVT_HEADER} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" ${entrypoint_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" ${ivt_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" ${csf_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') - ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') -} >> "${TARGET}" + # Generate and attach IVT + # Fields: header, jump location, reserved (0), DCD pointer (null) + # boot data (null), self pointer, CSF pointer, reserved (0) + PRINTF="$(which printf)" + IVT_HEADER="0x402000D1" + { + ${PRINTF} $(${PRINTF} "%08x" ${IVT_HEADER} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" ${entrypoint_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" ${ivt_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" ${csf_ram_start} | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + ${PRINTF} $(${PRINTF} "%08x" 0 | sed 's/.\{2\}/&\n/g' | tac | sed 's,^,\\x,g' | tr -d '\n') + } >> "${TARGET}" -CURRENT_PATH="$(pwd)" -cst -o "${CURRENT_PATH}/csf.bin" -i "${CURRENT_PATH}/csf_descriptor" >/dev/null -if [ $? -ne 0 ]; then - echo "[ERROR] Could not generate CSF" - exit 1 + CURRENT_PATH="$(pwd)" + cst -o "${CURRENT_PATH}/csf.bin" -i "${CURRENT_PATH}/csf_descriptor" >/dev/null + if [ $? -ne 0 ]; then + echo "[ERROR] Could not generate CSF" + exit 1 + fi + + cat csf.bin >> "${TARGET}" + + objcopy -I binary -O binary --pad-to "${sig_len}" --gap-fill="${GAP_FILLER}" "${TARGET}" +else + CURRENT_PATH="$(pwd)" + cst -o "${TARGET}" -i "${CURRENT_PATH}/csf_descriptor" >/dev/null + if [ $? -ne 0 ]; then + echo "[ERROR] Could not generate CSF $?" + exit 1 + fi fi -cat csf.bin >> "${TARGET}" - -objcopy -I binary -O binary --pad-to "${sig_len}" --gap-fill="${GAP_FILLER}" "${TARGET}" - [ "${ENCRYPT}" = "true" ] && ENCRYPTED_MSG="and encrypted " echo "Signed ${ENCRYPTED_MSG}image ready: ${TARGET}" rm -f "${SRK_TABLE}" csf_descriptor csf.bin 2> /dev/null diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb index 705f660b4..5bdb19960 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools_git.bb @@ -17,8 +17,9 @@ UBOOT_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_GIT SRC_URI = " \ ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ file://trustfence-sign-kernel.sh;name=kernel-script \ - file://sign_uimage;name=kernel-sign \ - file://encrypt_uimage;name=kernel-encrypt \ + file://sign_hab;name=kernel-sign \ + file://encrypt_hab;name=kernel-encrypt \ + file://sign_ahab;name=kernel-sign \ " do_configure[noexec] = "1" @@ -26,12 +27,19 @@ do_compile[noexec] = "1" do_install() { install -d ${D}${bindir}/csf_templates + if [ "${SIGN_MODE}" = "AHAB" ]; then + install -m 0755 sign_ahab ${D}${bindir}/csf_templates/ + install -m 0755 git/scripts/sign.sh ${D}${bindir}/trustfence-sign-ahab-uboot.sh + elif [ "${SIGN_MODE}" = "HAB" ]; then + install -m 0755 sign_hab ${D}${bindir}/csf_templates/ + install -m 0755 encrypt_hab ${D}${bindir}/csf_templates/ + install -m 0755 git/scripts/sign.sh ${D}${bindir}/trustfence-sign-uboot.sh + else + bberror "Unkown SIGN_MODE value" + exit 1 + fi install -m 0755 trustfence-sign-kernel.sh ${D}${bindir}/ - install -m 0755 sign_uimage ${D}${bindir}/csf_templates/ - install -m 0755 encrypt_uimage ${D}${bindir}/csf_templates/ - install -m 0755 git/scripts/sign.sh ${D}${bindir}/trustfence-sign-uboot.sh - install -m 0755 git/scripts/csf_templates/sign_uboot ${D}${bindir}/csf_templates - install -m 0755 git/scripts/csf_templates/encrypt_uboot ${D}${bindir}/csf_templates + install -m 0755 git/scripts/csf_templates/* ${D}${bindir}/csf_templates } FILES_${PN} = "${bindir}" diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index 0575fb967..66db01319 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -24,23 +24,49 @@ trustfence_sign() { [ -n "${TRUSTFENCE_DEK_PATH}" ] && [ "${TRUSTFENCE_DEK_PATH}" != "0" ] && export CONFIG_DEK_PATH="${TRUSTFENCE_DEK_PATH}" # Sign/encrypt the kernel images - for type in ${KERNEL_IMAGETYPES}; do - KERNEL_IMAGE="${type}-${KERNEL_IMAGE_NAME}.bin" - TMP_KERNEL_IMAGE_SIGNED="$(mktemp ${KERNEL_IMAGE}-signed.XXXXXX)" - trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -l "${KERNEL_IMAGE}" "${TMP_KERNEL_IMAGE_SIGNED}" - mv "${TMP_KERNEL_IMAGE_SIGNED}" "${KERNEL_IMAGE}" - done + if [ "${SIGN_MODE}" = "HAB" ]; then + for type in ${KERNEL_IMAGETYPES}; do + KERNEL_IMAGE="${type}-${KERNEL_IMAGE_NAME}.bin" + TMP_KERNEL_IMAGE_SIGNED="$(mktemp ${KERNEL_IMAGE}-signed.XXXXXX)" + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -l "${KERNEL_IMAGE}" "${TMP_KERNEL_IMAGE_SIGNED}" + mv "${TMP_KERNEL_IMAGE_SIGNED}" "${KERNEL_IMAGE}" + done - # Sign/encrypt the device tree blobs - for DTB in ${KERNEL_DEVICETREE}; do - DTB=`normalize_dtb "${DTB}"` - DTB_EXT=${DTB##*.} - DTB_BASE_NAME=`basename ${DTB} ."${DTB_EXT}"` - DTB_IMAGE="${DTB_BASE_NAME}-${KERNEL_IMAGE_NAME}.${DTB_EXT}" - TMP_DTB_IMAGE_SIGNED="$(mktemp ${DTB_IMAGE}-signed.XXXXXX)" - trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -d "${DTB_IMAGE}" "${TMP_DTB_IMAGE_SIGNED}" - mv "${TMP_DTB_IMAGE_SIGNED}" "${DTB_IMAGE}" - done + # Sign/encrypt the device tree blobs + for DTB in ${KERNEL_DEVICETREE}; do + DTB=`normalize_dtb "${DTB}"` + DTB_EXT=${DTB##*.} + DTB_BASE_NAME=`basename ${DTB} ."${DTB_EXT}"` + DTB_IMAGE="${DTB_BASE_NAME}-${KERNEL_IMAGE_NAME}.${DTB_EXT}" + TMP_DTB_IMAGE_SIGNED="$(mktemp ${DTB_IMAGE}-signed.XXXXXX)" + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -d "${DTB_IMAGE}" "${TMP_DTB_IMAGE_SIGNED}" + mv "${TMP_DTB_IMAGE_SIGNED}" "${DTB_IMAGE}" + done + elif [ "${SIGN_MODE}" = "AHAB" ]; then + # Sign the kernel images + for type in ${KERNEL_IMAGETYPES}; do + KERNEL_IMAGE="${type}-${KERNEL_IMAGE_NAME}.bin" + ${DEPLOY_DIR_IMAGE}/imx-boot-tools/mkimage_imx8 -soc ${MX8_SOC_VAR} -rev ${MX8_CHIP_REV} -c -ap ${WORKDIR}/build/arch/arm64/boot/Image a35 ${RAM_CONTAINER_LOC_BOOT} -out flash_os.bin + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -l "flash_os.bin" "${type}-${MACHINE}-signed.bin" + gzip ${type}-${MACHINE}-signed.bin + mv ${type}-${MACHINE}-signed.bin.gz "${KERNEL_IMAGE}" + done + + # Sign/encrypt the device tree blobs + for DTB in ${KERNEL_DEVICETREE}; do + DTB=`normalize_dtb "${DTB}"` + DTB_EXT=${DTB##*.} + DTB_BASE_NAME=`basename ${DTB} ."${DTB_EXT}"` + DTB_IMAGE="${DTB_BASE_NAME}-${KERNEL_IMAGE_NAME}.${DTB_EXT}" + ${DEPLOY_DIR_IMAGE}/imx-boot-tools/mkimage_imx8 -soc ${MX8_SOC_VAR} -rev ${MX8_CHIP_REV} -c -ap ${DTB_IMAGE} a35 ${RAM_CONTAINER_LOC_DTB} -out ${DTB_IMAGE}-mkimg-signed + trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -d "${DTB_IMAGE}-mkimg-signed" "${DTB_IMAGE}-signed" + mv "${DTB_IMAGE}-signed" "${DTB_IMAGE}" + rm -f ${DTB_IMAGE}-mkimg-signed + done + else + bberror "Unkown SIGN_MODE value" + exit 1 + fi } trustfence_sign[dirs] = "${DEPLOYDIR}" diff --git a/meta-digi-dey/classes/trustfence.bbclass b/meta-digi-dey/classes/trustfence.bbclass index c9e391132..a443606a7 100644 --- a/meta-digi-dey/classes/trustfence.bbclass +++ b/meta-digi-dey/classes/trustfence.bbclass @@ -67,7 +67,11 @@ python () { if (d.getVar("TRUSTFENCE_DEK_PATH", True) not in [None, "0"]): d.appendVar("UBOOT_EXTRA_CONF", 'CONFIG_DEK_PATH=\\"%s\\" ' % d.getVar("TRUSTFENCE_DEK_PATH", True)) if (d.getVar("TRUSTFENCE_ENCRYPT_ENVIRONMENT", True) == "1"): - d.appendVar("UBOOT_EXTRA_CONF", 'CONFIG_ENV_AES=y CONFIG_ENV_AES_CAAM_KEY=y') + if ("ccimx8x" in d.getVar("MACHINE", True)): + bb.fatal("Environment encryption is not currently supported on the ccimx8x SOM") + return + else: + d.appendVar("UBOOT_EXTRA_CONF", 'CONFIG_ENV_AES=y CONFIG_ENV_AES_CAAM_KEY=y') # Provide sane default values for SWUPDATE class in case Trustfence is enabled if (d.getVar("TRUSTFENCE_SIGN", True) == "1"): @@ -84,7 +88,12 @@ python () { key_index_1 = key_index + 1 # Set the private key template, it will be expanded later in 'swu' recipes once keys are generated. - d.setVar("SWUPDATE_PRIVATE_KEY_TEMPLATE", keys_path + "/keys/IMG" + str(key_index_1) + "*key.pem") + if (d.getVar("SIGN_MODE", "") == "AHAB"): + d.setVar("SWUPDATE_PRIVATE_KEY_TEMPLATE", keys_path + "/keys/SRK" + str(key_index_1) + "*key.pem") + d.setVar("CONFIG_SIGN_MODE", "AHAB") + else: + d.setVar("SWUPDATE_PRIVATE_KEY_TEMPLATE", keys_path + "/keys/IMG" + str(key_index_1) + "*key.pem") + d.setVar("CONFIG_SIGN_MODE", "HAB") # Set the key password. d.setVar("SWUPDATE_PASSWORD_FILE", keys_path + "/keys/key_pass.txt") diff --git a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb index 25e3e9e3a..2df871b24 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb +++ b/meta-digi-dey/recipes-core/recovery/recovery-initramfs.bb @@ -40,7 +40,14 @@ do_install() { KEY_INDEX_1=$(expr ${KEY_INDEX} + 1) # Find the certificate to use. - CERT_IMG="$(echo ${TRUSTFENCE_SIGN_KEYS_PATH}/crts/IMG${KEY_INDEX_1}*crt.pem)" + if [ "${SIGN_MODE}" = "HAB" ]; then + CERT_IMG="$(echo ${TRUSTFENCE_SIGN_KEYS_PATH}/crts/IMG${KEY_INDEX_1}*crt.pem)" + elif [ "${SIGN_MODE}" = "AHAB" ]; then + CERT_IMG="$(echo ${TRUSTFENCE_SIGN_KEYS_PATH}/crts/SRK${KEY_INDEX_1}*_ca_crt.pem)" + else + bberror "Unkown SIGN_MODE value" + exit 1 + fi # Extract the public key from the certificate. install -d ${D}${sysconfdir}/ssl/certs From 909a8c9e8383e851d0534d4206c2bb044849c782 Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Thu, 2 Jan 2020 17:58:37 +0100 Subject: [PATCH 117/120] Revert "ccimx8x: prohibit dey-image-qt from building when trustfence is enabled" Added Trusfence support for the CC8X. This reverts commit 8b5c7100365b7e6136413fa30d87b501a3fa9de9. https://jira.digi.com/browse/DEL-6917 --- meta-digi-dey/classes/trustfence.bbclass | 4 ---- 1 file changed, 4 deletions(-) diff --git a/meta-digi-dey/classes/trustfence.bbclass b/meta-digi-dey/classes/trustfence.bbclass index a443606a7..c54b3b933 100644 --- a/meta-digi-dey/classes/trustfence.bbclass +++ b/meta-digi-dey/classes/trustfence.bbclass @@ -36,10 +36,6 @@ python () { import hashlib import os - if ("ccimx8x" in d.getVar("MACHINE", True)): - bb.fatal("Trustfence is not currently supported on the ccimx8x SOM") - return - # Secure console configuration if (d.getVar("TRUSTFENCE_CONSOLE_DISABLE", True) == "1"): d.appendVar("UBOOT_EXTRA_CONF", "CONFIG_CONSOLE_DISABLE=y ") From 25c6daf9b14828cf2939cd85efeea3633bb2899a Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Wed, 5 Feb 2020 09:34:19 +0100 Subject: [PATCH 118/120] meta-digi-arm: u-boot: Fix license checksum for different u-boot versions Commit 31d8ff94 ("meta-digi-arm: u-boot: Update recipes with new u-boot version") updates the license checksum for the new u-boot_2019.04 recipe, however this license file is different for the other u-boot versions. This commit reverts this change and includes the updated checksum only for the new u-boot_2019.04 recipe. Signed-off-by: Arturo Buzarra --- meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc index 9b40be959..68f14fc16 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/digi-u-boot.inc @@ -4,7 +4,7 @@ require recipes-bsp/u-boot/u-boot.inc DESCRIPTION = "Bootloader for Digi platforms" LICENSE = "GPLv2+" -LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e" +LIC_FILES_CHKSUM = "file://Licenses/README;md5=a2c678cfd4a4d97135585cad908541c6" SECTION = "bootloaders" DEPENDS += "bc-native dtc-native u-boot-mkimage-native" diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb index 7bcfbd8d2..604ebbc43 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2019.04.bb @@ -1,6 +1,8 @@ # Copyright (C) 2019 Digi International require digi-u-boot.inc +LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e" + DEPENDS += "flex-native bison-native" SRCBRANCH = "v2019.04/master" From 7477196c9b7890a2df35ae17d762a26c7831c13d Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Wed, 5 Feb 2020 15:58:34 +0100 Subject: [PATCH 119/120] image-types_digi.bbclass: fix imx-mkimage dependency with sign mode is AHAB Commit 5beec04b ("trustfence: Add Trustfence support for CCMX8X") introduces a dependency when the imx-mkimage recipe and the SIGN_MODE is equal to AHAB. However this dependency should be added only when the TRUSTFENCE_SIGN is equal to 1 and when the SIGN_MODE is equal to AHAB, not only when the SIGN_MODE is equal to AHAB. This commit introduces this double check. Signed-off-by: Arturo Buzarra --- meta-digi-arm/classes/image_types_digi.bbclass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta-digi-arm/classes/image_types_digi.bbclass b/meta-digi-arm/classes/image_types_digi.bbclass index 5ebdbf869..de4a07564 100644 --- a/meta-digi-arm/classes/image_types_digi.bbclass +++ b/meta-digi-arm/classes/image_types_digi.bbclass @@ -216,8 +216,8 @@ trustence_sign_cpio() { } CONVERSIONTYPES += "tf" CONVERSION_CMD_tf = "trustence_sign_cpio ${IMAGE_NAME}.rootfs.${type}" -CONVERSION_DEPENDS_tf = "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'trustfence-sign-tools-native', '', d)}" -CONVERSION_DEPENDS_tf += "${@oe.utils.conditional('SIGN_MODE', 'AHAB', 'imx-mkimage', '', d)}" +CONVERSION_DEPENDS_tf = "${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', \ + oe.utils.conditional('SIGN_MODE', 'AHAB', 'trustfence-sign-tools-native imx-mkimage', 'trustfence-sign-tools-native', d), '', d)}" IMAGE_TYPES += "cpio.gz.u-boot.tf" ################################################################################ From 1516bd03d02df2b4d0b739cf446763dc8ba05fa4 Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Wed, 5 Feb 2020 16:45:34 +0100 Subject: [PATCH 120/120] image-type_digi.bbclass: Fix copy of initramfs when Trustfence is disabled. This commit fixes the copy of the initramfs final image with the extension *.tf when Trustfence is disabled. This was introduced by commit 5beec04b ("trustfence: Add Trustfence support for CCMX8X") Signed-off-by: Mike Engel --- meta-digi-arm/classes/image_types_digi.bbclass | 3 +++ 1 file changed, 3 insertions(+) diff --git a/meta-digi-arm/classes/image_types_digi.bbclass b/meta-digi-arm/classes/image_types_digi.bbclass index de4a07564..dcb85f51d 100644 --- a/meta-digi-arm/classes/image_types_digi.bbclass +++ b/meta-digi-arm/classes/image_types_digi.bbclass @@ -212,6 +212,9 @@ trustence_sign_cpio() { fi # Sign/encrypt the ramdisk trustfence-sign-kernel.sh -p "${DIGI_FAMILY}" -i "${1}" "${1}.tf" + else + # Copy the image with no changes + cp "${1}" "${1}.tf" fi } CONVERSIONTYPES += "tf"