EMPTY=""
*/
+ public static final String EMPTY = "";
+ /** Constant DEFAULT_PAD_CHAR=' '
*/
+ public static final char DEFAULT_PAD_CHAR = ' ';
+
+ /**
+ * isNullOrEmpty.
+ * + * @param data a {@link String} object. + * @param trim a boolean. + * @return a boolean. + */ + public static boolean isNullOrEmpty(String data, boolean trim){ + if(data == null) + return true; + + // trim if requested + String test = data; + if(trim) + test = data.trim(); + + return (test.length() <= 0); + } + + /** + *isNullOrEmpty.
+ * + * @param data a {@link String} object. + * @return a boolean. + */ + public static boolean isNullOrEmpty(String data){ + return isNullOrEmpty(data, false); + } + + /** + *isNotNullOrEmpty.
+ * + * @param data a {@link String} object. + * @return a boolean. + */ + public static boolean isNotNullOrEmpty(String data){ + return isNotNullOrEmpty(data, false); + } + + /** + *isNotNullOrEmpty.
+ * + * @param data a {@link String} object. + * @param trim a boolean. + * @return a boolean. + */ + public static boolean isNotNullOrEmpty(String data, boolean trim){ + return !(isNullOrEmpty(data, trim)); + } + + /** + *setIfNullOrEmpty.
+ * + * @param data a {@link String} object. + * @param replacement a {@link String} object. + * @param trim a boolean. + * @return a {@link String} object. + */ + public static String setIfNullOrEmpty(String data, String replacement, boolean trim){ + if(isNullOrEmpty(data, trim)) { + return replacement; + } + return data; + } + + /** + *setIfNullOrEmpty.
+ * + * @param data a {@link String} object. + * @param replacement a {@link String} object. + * @return a {@link String} object. + */ + public static String setIfNullOrEmpty(String data, String replacement){ + return setIfNullOrEmpty(data, replacement, false); + } + + /** + *contains.
+ * + * @param source a {@link String} object. + * @param target a {@link String} object. + * @return a boolean. + */ + public static boolean contains(String source, String target) { + return (null != source && null != target && source.contains(target)); + } + + /** + *contains.
+ * + * @param source a {@link String} object. + * @param targets an array of {@link String} objects. + * @return a boolean. + */ + public static boolean contains(String source, String[] targets) { + if (null != source && null != targets) { + for(var target : targets) { + if (source.contains(target)) { + return true; + } + } + } + return false; + } + + /** + *contains.
+ * + * @param sources an array of {@link String} objects. + * @param target a {@link String} object. + * @return a boolean. + */ + public static boolean contains(String[] sources, String target) { + if (null != sources && null != target) { + for (var source : sources) { + if(contains(source, target)) + return true; + } + } + return false; + } + + /** + *contains.
+ * + * @param sources an array of {@link String} objects. + * @param targets an array of {@link String} objects. + * @return a boolean. + */ + public static boolean contains(String[] sources, String[] targets) { + if (null != sources && null != targets) { + for (var source : sources) { + if(contains(source, targets)) + return true; + } + } + return false; + } + + /** + *create.
+ * + * @param length a int. + * @return a {@link String} object. + */ + public static String create(int length) { + return create(DEFAULT_PAD_CHAR, length); + } + + /** + *create.
+ * + * @param c a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String create(char c, int length) { + StringBuilder sb = new StringBuilder(length); + for(var index = 0; index < length; index++) + sb.append(c); + return sb.toString(); + } + + /** + *create.
+ * + * @param s a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String create(String s, int length) { + StringBuilder sb = new StringBuilder(length * s.length()); + for(var index = 0; index < length; index++) + sb.append(s); + return sb.toString(); + } + + /** + *repeat.
+ * + * @param c a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String repeat(char c, int length) { + return create(c, length); + } + + /** + *repeat.
+ * + * @param s a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String repeat(String s, int length) { + return create(s, length); + } + + /** + *padLeft.
+ * + * @param data a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String padLeft(String data, int length) { + return padLeft(data, DEFAULT_PAD_CHAR, length); + } + + /** + *padLeft.
+ * + * @param data a {@link String} object. + * @param pad a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String padLeft(String data, char pad, int length) { + var sb = new StringBuilder(data.length() + length); + for(var index = 0; index < length; index++) + sb.append(pad); + sb.append(data); + return sb.toString(); + } + + /** + *padLeft.
+ * + * @param data a {@link String} object. + * @param pad a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String padLeft(String data, String pad, int length) { + var sb = new StringBuilder(data.length() + (length * pad.length())); + for(var index = 0; index < length; index++) + sb.append(pad); + sb.append(data); + return sb.toString(); + } + + /** + *padRight.
+ * + * @param data a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String padRight(String data, int length) { + return padRight(data, DEFAULT_PAD_CHAR, length); + } + + /** + *padRight.
+ * + * @param data a {@link String} object. + * @param pad a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String padRight(String data, char pad, int length) { + var sb = new StringBuilder(data.length() + length); + sb.append(data); + for(var index = 0; index < length; index++) + sb.append(pad); + return sb.toString(); + } + + /** + *padRight.
+ * + * @param data a {@link String} object. + * @param pad a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String padRight(String data, String pad, int length) { + var sb = new StringBuilder(data.length() + (length * pad.length())); + sb.append(data); + for(var index = 0; index < length; index++) + sb.append(pad); + return sb.toString(); + } + + /** + *pad.
+ * + * @param data a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String pad(String data, int length) { + return pad(data, DEFAULT_PAD_CHAR, length); + } + + /** + *pad.
+ * + * @param data a {@link String} object. + * @param pad a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String pad(String data, char pad, int length) { + return create(pad, length) + data + create(pad, length); + } + + /** + *pad.
+ * + * @param data a {@link String} object. + * @param pad a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String pad(String data, String pad, int length) { + return create(pad, length) + data + create(pad, length); + } + + /** + *padCenter.
+ * + * @param data a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String padCenter(String data, int length) { + return padCenter(data, DEFAULT_PAD_CHAR, length); + } + + /** + *padCenter.
+ * + * @param data a {@link String} object. + * @param pad a char. + * @param length a int. + * @return a {@link String} object. + */ + public static String padCenter(String data, char pad, int length) { + if(data.length() < length) { + int needed = length - data.length(); + int padNeeded = needed / 2; + StringBuilder result = new StringBuilder(); + result.append(create(pad, padNeeded)); + result.append(data); + result.append(create(pad, padNeeded)); + int remaining = length - result.length(); + result.append(create(pad, remaining)); + return result.toString(); + } + return data; + } + + /** + *trimLeft.
+ * + * @param data a {@link String} object. + * @return a {@link String} object. + */ + public static String trimLeft(String data) { + return trimLeft(data, DEFAULT_PAD_CHAR); + } + + /** + *trimLeft.
+ * + * @param data a {@link String} object. + * @param trim a char. + * @return a {@link String} object. + */ + public static String trimLeft(String data, char trim) { + for(var index = 0; index < data.length(); index++) + if(!(data.charAt(index) == trim)) + return data.substring(index); + return EMPTY; + } + + /** + *trimRight.
+ * + * @param data a {@link String} object. + * @return a {@link String} object. + */ + public static String trimRight(String data) { + return trimRight(data, DEFAULT_PAD_CHAR); + } + + /** + *trimRight.
+ * + * @param data a {@link String} object. + * @param trim a char. + * @return a {@link String} object. + */ + public static String trimRight(String data, char trim) { + int count = 0; + for(var index = data.length(); index > 0; index--) + if(data.charAt(index-1) == trim) + count++; + else + return data.substring(0, data.length() - count); + return EMPTY; + } + + /** + *trim.
+ * + * @param data a {@link String} object. + * @return a {@link String} object. + */ + public static String trim(String data) { + return trim(data, DEFAULT_PAD_CHAR); + } + + /** + *trim.
+ * + * @param data a {@link String} object. + * @param trim a char. + * @return a {@link String} object. + */ + public static String trim(String data, char trim) { + var result = trimLeft(data, trim); + return trimRight(result, trim); + } + + /** + *center.
+ * + * @param text a {@link String} object. + * @param length a int. + * @return a {@link String} object. + */ + public static String center(String text, int length){ + var out = String.format("%"+length+"s%s%"+length+"s", "",text,""); + var mid = (out.length()/2); + var start = mid - (length/2); + var end = start + length; + return out.substring((int) start, (int) end); + } + + /** + *concat.
+ * + * @param data a {@link String} object. + * @return a {@link String} object. + */ + public static String concat(String ... data) { + var sb = new StringBuilder(); + for(var d : data){ + sb.append(d); + } + return sb.toString(); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param byt a byte. + */ + public static void appendHexString(StringBuilder builder, byte byt){ + builder.append(String.format("%02X", byt)); + } + /** + *toHexString.
+ * + * @param byt a byte. + * @return a {@link String} object. + */ + public static String toHexString(byte byt){ + return String.format("%02X", byt); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param byt a int. + */ + public static void appendHexString(StringBuilder builder, int byt){ + builder.append(String.format("%02X", (byte)byt)); + } + /** + *toHexString.
+ * + * @param byt a int. + * @return a {@link String} object. + */ + public static String toHexString(int byt){ + return String.format("%02X", (byte)byt); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param bytes an array of {@link byte} objects. + */ + public static void appendHexString(StringBuilder builder, byte[] bytes){ + for (byte b : bytes) { + builder.append(String.format("%02X ", b)); + } + } + /** + *toHexString.
+ * + * @param bytes an array of {@link byte} objects. + * @return a {@link String} object. + */ + public static String toHexString(byte[] bytes){ + StringBuilder sb = new StringBuilder(); + appendHexString(sb, bytes); + return sb.toString().trim(); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param buffer a {@link ByteBuffer} object. + */ + public static void appendHexString(StringBuilder builder, ByteBuffer buffer){ + appendHexString(builder, buffer.array()); + } + /** + *toHexString.
+ * + * @param buffer a {@link ByteBuffer} object. + * @return a {@link String} object. + */ + public static String toHexString(ByteBuffer buffer){ + StringBuilder sb = new StringBuilder(); + appendHexString(sb, buffer); + return sb.toString().trim(); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param bytes an array of {@link byte} objects. + * @param offset a int. + * @param length a int. + */ + public static void appendHexString(StringBuilder builder, byte[] bytes, int offset, int length){ + appendHexString(builder, Arrays.copyOfRange(bytes, offset, length)); + } + /** + *toHexString.
+ * + * @param bytes an array of {@link byte} objects. + * @param offset a int. + * @param length a int. + * @return a {@link String} object. + */ + public static String toHexString(byte[] bytes, int offset, int length){ + StringBuilder sb = new StringBuilder(); + appendHexString(sb, bytes, offset, length); + return sb.toString().trim(); + } + + /** + *appendHexString.
+ * + * @param builder a {@link StringBuilder} object. + * @param buffer a {@link ByteBuffer} object. + * @param offset a int. + * @param length a int. + */ + public static void appendHexString(StringBuilder builder, ByteBuffer buffer, int offset, int length){ + appendHexString(builder, buffer.array(), offset, length); + } + /** + *toHexString.
+ * + * @param buffer a {@link ByteBuffer} object. + * @param offset a int. + * @param length a int. + * @return a {@link String} object. + */ + public static String toHexString(ByteBuffer buffer, int offset, int length){ + StringBuilder sb = new StringBuilder(); + appendHexString(sb, buffer, offset, offset+length); + return sb.toString().trim(); + } + + +} diff --git a/libraries/pi4j-library-kernel/src/main/java/module-info.java b/libraries/pi4j-library-kernel/src/main/java/module-info.java new file mode 100644 index 00000000..0c492d5d --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/java/module-info.java @@ -0,0 +1,17 @@ + +module com.pi4j.library.kernel { + + // SLF4J + requires org.slf4j; + + // PI4J + requires com.pi4j; + + + // JNA + requires jdk.unsupported; + requires com.sun.jna; + + // EXPORTS + exports com.pi4j.library.kernel; + } diff --git a/libraries/pi4j-library-kernel/src/main/native/Makefile b/libraries/pi4j-library-kernel/src/main/native/Makefile new file mode 100644 index 00000000..32ac2ada --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/native/Makefile @@ -0,0 +1,69 @@ +# +# Makefile: +# pi4j-gpiod - Pi4J Java (JNA) library wrapper for kernel +# + +#DEBUG = -g -O0 +ARCH := armhf +DEBUG = -O3 +CC = $(CROSS_PREFIX)gcc +AR = $(CROSS_PREFIX)ar +RANLIB = $(CROSS_PREFIX)ranlib +SIZE = $(CROSS_PREFIX)size +STRIP = $(CROSS_PREFIX)strip +SHLIB = $(CC) -shared +STRIPLIB = $(STRIP) --strip-unneeded +INCLUDE = -I. \ + -I/$(JAVA_HOME)/include \ + -I/$(JAVA_HOME)/include/linux \ + -I/usr/lib/jvm/jdk-11-oracle/include \ + -I/usr/lib/jvm/jdk-11-oracle/include/linux \ + -I/usr/lib/jvm/jdk-11-oracle-arm32-vfp-hflt/include \ + -I/usr/lib/jvm/jdk-11-oracle-arm32-vfp-hflt/include/linux \ + -I/usr/lib/jvm/java-11-openjdk-amd64/include \ + -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux \ + -I/usr/lib/jvm/java-11-openjdk-armhf/include \ + -I/usr/lib/jvm/java-11-openjdk-armhf/include/linux \ + +CFLAGS := $(DEBUG) -Wall $(INCLUDE) -Winline -pipe $(CARGS) -fPIC +LIBS = -L lib/$(ARCH)/pi4j-kernel + +TARGET=libpi4j-kernel.so + +# Should not alter anything below this line +############################################################################### + +SRC = com_pi4j_library_kernel_internal.c + +OBJ = $(SRC:.c=.o) + +all: $(OBJ) + @echo [LINK with DYNAMICALLY linked libraries] + @$(CC) $(OBJ) -shared -o $(TARGET) $(INCLUDE) $(LIBS) + +.c.o: + @echo [COMPILE] $< + @$(CC) -c $(CFLAGS) $< -o $@ + +clean: + rm -f $(OBJ) $(TARGET) *~ core tags Makefile.bak + +tags: $(SRC) + @echo [ctags] + @ctags $(SRC) + +depend: + makedepend -Y $(SRC) + +install: $(TARGET) + @echo [install] + install -m 0755 -d /usr/local/lib + install -m 0755 -d /usr/local/include + install -m 0644 $(TARGET) /usr/local/lib + +uninstall: + @echo [uninstall] + rm -f /usr/local/lib/$(TARGET) + +# DO NOT DELETE +com_pi4j_library_kernel_internal.o: com_pi4j_library_kernel_internal.h diff --git a/libraries/pi4j-library-kernel/src/main/native/build-docker.sh b/libraries/pi4j-library-kernel/src/main/native/build-docker.sh new file mode 100755 index 00000000..7a840635 --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/native/build-docker.sh @@ -0,0 +1,59 @@ +#!/bin/bash -e +### +# #%L +# ********************************************************************** +# ORGANIZATION : Pi4J +# PROJECT : Pi4J :: JNA Native Binding Library for Kernal +# FILENAME : build-docker.sh +# +# This file is part of the Pi4J project. More information about +# this project can be found here: https://pi4j.com/ +# ********************************************************************** +# %% +# Copyright (C) 2012 - 2019 Pi4J +# %% +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# #L% +### + +echo +echo "**********************************************************************" +echo "**********************************************************************" +echo "* *" +echo "* COMPILE Pi4J NATIVE LIBRARIES USING Pi4J DOCKER BUILDER IMAGE *" +echo "* *" +echo "**********************************************************************" +echo "**********************************************************************" +echo + +# validate compatible that "docker" exists +DOCKER=$(which docker) +if [[ ("$DOCKER" == "") ]]; then + echo "This native build is requires that 'docker' (https://www.docker.com/) is " + echo "installed and running on an Intel/AMD or ARM 64-bit platform." + echo "BUILD ABORTED; REASON: Missing 'docker' executable." + exit +fi + +# set executable permissions on build scripts +chmod +x build.sh + +# ------------------------------------------------------------- +# BUILD NATIVE LIBRARIES USING THE Pi4J DOCKER BUILDER IMAGE +# FOR ARMv6,ARMv7, ARMv8 32-BIT (ARMHF) +# FOR ARMv8 64-BIT (ARM64) +# ------------------------------------------------------------- +docker pull pi4j/pi4j-builder-native:2.0 +docker run --user "$(id -u):$(id -g)" --rm --volume $(pwd):/build pi4j/pi4j-builder-native:2.0 $@ diff --git a/libraries/pi4j-library-kernel/src/main/native/build-libpi4j.sh b/libraries/pi4j-library-kernel/src/main/native/build-libpi4j.sh new file mode 100755 index 00000000..9653d9c9 --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/native/build-libpi4j.sh @@ -0,0 +1,72 @@ +#!/bin/bash -e +### +# #%L +# ********************************************************************** +# ORGANIZATION : Pi4J +# PROJECT : Pi4J :: JNA Native Binding Library for kernel +# FILENAME : build-libpi4j.sh +# +# This file is part of the Pi4J project. More information about +# this project can be found here: https://pi4j.com/ +# ********************************************************************** +# %% +# Copyright (C) 2012 - 2021 Pi4J +# %% +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# #L% +### + +# ---------------------------------------------- +# build latest Pi4J kernel JNA Wrapper Library +# ---------------------------------------------- + +echo +echo "=============================================================================" +echo " STARTED BUILDING Pi4J-Kernel JNA NATIVE LIBRARY: ('${ARCH}/pi4j-kernel/libpi4j-kernel')" +echo "=============================================================================" +echo " - FOR ARCHITECTURE : ${ARCH}" +echo " - USING COMPILER : ${CC}" +echo " - USING CROSS PREFIX : ${CROSS_PREFIX}" +echo "-----------------------------------------------------------------------------" +echo + + +# set default kernel directory if not already defined +if [ -z $KERNEL_DIRECTORY ]; then + KERNEL_DIRECTORY=kernel +fi + +# ------------------------------------------------------ +# BUILD LIBPI4J-KERNEL +# ------------------------------------------------------ +echo +echo "=====================================" +echo "BUILDING: ${ARCH}/pi4j-kernel/libpi4j-kernel" +echo "=====================================" + +# perform compile +mkdir -p lib/${ARCH}/pi4j-kernel +make clean all \ + --always-make \ + CROSS_PREFIX=${CROSS_PREFIX} \ + CC=${CC} \ + ARCH=${ARCH} \ + TARGET=lib/${ARCH}/pi4j-kernel/libpi4j-kernel.so $@ + +echo +echo "-----------------------------------------------------------------------------" +echo " FINISHED BUILDING Pi4J-kernel JNA NATIVE LIBRARY: ('${ARCH}/libpi4j-kernel')" +echo "-----------------------------------------------------------------------------" +echo \ No newline at end of file diff --git a/libraries/pi4j-library-kernel/src/main/native/build-prerequisites.sh b/libraries/pi4j-library-kernel/src/main/native/build-prerequisites.sh new file mode 100755 index 00000000..6e15e612 --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/native/build-prerequisites.sh @@ -0,0 +1,130 @@ +#!/bin/bash +### +# #%L +# ********************************************************************** +# ORGANIZATION : Pi4J +# PROJECT : Pi4J :: JNA Native Binding Library for kernel +# FILENAME : build-prerequisites.sh +# +# This file is part of the Pi4J project. More information about +# this project can be found here: https://pi4j.com/ +# ********************************************************************** +# %% +# Copyright (C) 2012 - 2021 Pi4J +# %% +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# #L% +### +# ---------------------------------- +# install prerequisites +# ---------------------------------- +if [ ! -z "`type apt-get 2>/dev/null;`" ]; then + + # build-essential + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' build-essential|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + sudo apt-get --force-yes --yes install build-essential + else + echo " [PREREQUISITE] 'build-essential' already installed."; + fi + + # GCC + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + sudo apt-get --force-yes --yes install gcc + else + echo " [PREREQUISITE] 'gcc' already installed."; + fi + + # GIT + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' git|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + sudo apt-get --force-yes --yes install git + else + echo " [PREREQUISITE] 'git' already installed."; + fi + + # TREE + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' tree|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + sudo apt-get --force-yes --yes install tree + else + echo " [PREREQUISITE] 'tree' already installed."; + fi + + # gcc-arm-linux-gnueabihf + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc-arm-linux-gnueabihf|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'gcc-arm-linux-gnueabihf'..."; + sudo apt-get --force-yes --yes install gcc-arm-linux-gnueabihf + else + echo " [PREREQUISITE] 'gcc-arm-linux-gnueabihf' already installed."; + fi + + # gcc-aarch64-linux-gnu + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc-aarch64-linux-gnu|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'gcc-aarch64-linux-gnu'..."; + sudo apt-get --force-yes --yes install gcc-aarch64-linux-gnu + else + echo " [PREREQUISITE] 'gcc-aarch64-linux-gnu' already installed."; + fi + + + # autoconf + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' autoconf|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'autoconf'..."; + sudo apt-get --force-yes --yes install autoconf + else + echo " [PREREQUISITE] 'autoconf' already installed."; + fi + + # autoconf-archive + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' autoconf-archive|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'autoconf-archive'..."; + sudo apt-get --force-yes --yes install autoconf-archive + else + echo " [PREREQUISITE] 'autoconf-archive' already installed."; + fi + + # pkg-config + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' pkg-config|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'pkg-config'..."; + sudo apt-get --force-yes --yes install pkg-config + else + echo " [PREREQUISITE] 'pkg-config' already installed."; + fi + + # libtool + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' libtool|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'libtool'..."; + sudo apt-get --force-yes --yes install libtool + else + echo " [PREREQUISITE] 'libtool' already installed."; + fi + + # pkg-config + INSTALLED=$(dpkg-query -W --showformat='${Status}\n' pkg-config|grep "install ok installed") + if [[ "$?" == "1" ]] ; then + echo " [PREREQUISITE] installing 'pkg-config'..."; + sudo apt-get --force-yes --yes install pkg-config + else + echo " [PREREQUISITE] 'pkg-config' already installed."; + fi +fi diff --git a/libraries/pi4j-library-kernel/src/main/native/build.sh b/libraries/pi4j-library-kernel/src/main/native/build.sh new file mode 100755 index 00000000..c2db47a7 --- /dev/null +++ b/libraries/pi4j-library-kernel/src/main/native/build.sh @@ -0,0 +1,132 @@ +#!/bin/bash -e +### +# #%L +# ********************************************************************** +# ORGANIZATION : Pi4J +# PROJECT : Pi4J :: JNA Native Binding Library for Kernel +# FILENAME : build.sh +# +# This file is part of the Pi4J project. More information about +# this project can be found here: https://pi4j.com/ +# ********************************************************************** +# %% +# Copyright (C) 2012 - 2021 Pi4J +# %% +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# #L% +### + +echo +echo "**********************************************************************" +echo "* *" +echo "* Pi4J Kernel LIBRARY NATIVE BUILDNAME=KernelSpi"
+ */
+ public static final String NAME = "KernelSpi";
+ /**
+ * Constant ID="KernelSpi"
+ */
+ public static final String ID = "rp1";
+
+ /**
+ * Constant SPI_PROVIDER_NAME="NAME + SPI Provider"
+ */
+ public static final String SPI_PROVIDER_NAME = NAME + " Spi Provider";
+ /**
+ * Constant SPI_OUTPUT_PROVIDER_ID="ID + -spi"
+ */
+ public static final String SPI_PROVIDER_ID = ID + "-spi";
+
+
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(PluginService service) {
+
+
+ // create & define supported Linux file system I/O providers that will be exposed to Pi4J via this plugin
+ Provider[] providers = {
+ Rp1SpiProvider.newInstance()
+ };
+
+ // register the SPI Provider with the plugin service
+ service.register(providers);
+ }
+}
diff --git a/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1Spi.java b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1Spi.java
new file mode 100644
index 00000000..806b17dd
--- /dev/null
+++ b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1Spi.java
@@ -0,0 +1,232 @@
+package com.pi4j.plugin.rp1spi.provider;
+
+
+import com.pi4j.context.Context;
+import com.pi4j.exception.InitializeException;
+import com.pi4j.io.spi.*;
+import com.pi4j.library.kernel.SPIapi;
+import com.pi4j.library.kernel.SPIapiImpl;
+import com.pi4j.library.kernel.SPIapiIntrf;
+
+
+public class Rp1Spi extends SpiBase implements Spi {
+
+ protected SPIapiImpl functionsSpi = null;
+
+ protected SPIapi.spiApi_t spiApi = null;
+ protected static int SPI_BUS_MASK = 0x0100;
+ protected static int SPI_MODE_MASK = 0x0003;
+
+ /**
+ * Constructor for Rp1Spi
+ * + * @param provider a {@link SpiProvider} object. + * @param config a {@link SpiConfig} object. + *+ * ------------------------------------------------------------------ + * spiFlags consists of the least significant 22 bits. + * ------------------------------------------------------------------ + * 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m + *
+ * [mm] defines the SPI mode. + *
+ * Mode POL PHA + * 0 0 0 + * 1 0 1 + * 2 1 0 + * 3 1 1 + *
+ * [px] is 0 if CEx is active low (default) and 1 for active high.
+ * [ux] is 0 if the CEx GPIO is reserved for SPI (default) and 1 otherwise.
+ * [A] is 0 for the main SPI, 1 for the auxiliary SPI.
+ * [W] is 0 if the device is not 3-wire, 1 if the device is 3-wire. Main SPI only.
+ * [nnnn] defines the number of bytes (0-15) to write before switching the MOSI line to MISO to read data.
+ * This field is ignored if W is not set. Main SPI only.
+ * [T] is 1 if the least significant bit is transmitted on MOSI first, the default (0) shifts the
+ * most significant bit out first. Auxiliary SPI only.
+ * [R] is 1 if the least significant bit is received on MISO first, the default (0) receives the most
+ * significant bit first. Auxiliary SPI only.
+ * [bbbbbb] defines the word size in bits (0-32). The default (0) sets 8 bits per word. Auxiliary SPI only.
+ */
+ public Rp1Spi(SpiProvider provider, SpiConfig config) {
+ super(provider, config);
+
+ // set local reference instance
+ try {
+ this.functionsSpi = SPIapiIntrf.createSPIapiImpl();
+ } catch (java.io.IOException e) {
+ throw new RuntimeException(e);
+ // todo log something...
+ }
+
+ this.spiApi = new SPIapi.spiApi_t();
+
+
+ this.spiApi.dev = new SPIapi.spiApi_device_p.ByReference();
+
+
+ // get configured SPI bus
+ SpiBus bus = SpiBus.BUS_0;
+
+ // get configured SPI mode
+ SpiMode mode = SpiMode.MODE_0;
+
+ int baud = config.baud();
+
+ int channel = config.getChannel();
+
+ SpiChipSelect cs = config.getChipSelect();
+
+
+
+ // the default value for 'flags' is zero
+ int flags = 0;
+
+ // to_do Decode all possible flags to value used
+ // in ioctl.
+ //TO_do if bits no longet applicable to we warn or error+out ?
+ // if 'flags' were provided in the SPI config, then accept them
+ if (config().flags() != null) {
+ flags = config().flags().intValue();
+ }
+
+ // Mode
+ if(config.modeUserProvided()){
+ mode = config.mode();
+ flags = (flags & (0xFFFFFFFF ^ SPI_MODE_MASK)); // clear Mode bits
+ flags |= mode.getMode();
+ }else {
+ int mode_bits = flags & SPI_MODE_MASK;
+ if(mode_bits == 0b01) {
+ mode = SpiMode.MODE_1;
+ }
+ else if(mode_bits == 0b10) {
+ mode = SpiMode.MODE_2;
+ }
+ else if(mode_bits == 0b11) {
+ mode = SpiMode.MODE_3;
+ }
+ }
+
+ // Bus
+ if (config.busUserProvided()) { // user provided, overwrite flags
+ bus = config.bus();
+ }
+ else if ((config.flags() != null)) { // use bus number from flags
+ if((flags & SPI_BUS_MASK) == 0){
+ bus = SpiBus.BUS_0;
+ }
+ else{
+ bus = SpiBus.BUS_1;
+ }
+ }
+ // update flags value with BUS bit ('A' 0x0000=BUS0; 0x0100=BUS1)
+ if (bus == SpiBus.BUS_0) {
+ flags = (flags & (0xFFFFFFFF ^ SPI_BUS_MASK)); // clear AUX bit
+ } else if (bus == SpiBus.BUS_1) {
+ flags = (flags & (0xFFFFFFFF ^ SPI_BUS_MASK)) | SPI_BUS_MASK; // set AUX bit
+ }
+
+ this.spiApi.max_freq = 64000000;
+
+ this.spiApi.bus = bus.getBus();
+
+ this.spiApi.dev.driver_mode = mode.ordinal();
+
+ // To_do
+ // cs needs valid init value
+ this.spiApi.cs = cs.ordinal();
+
+
+
+ // channel
+
+ // cs
+
+ this.functionsSpi.spiApi_init(this.spiApi);
+
+
+ // set open state flag
+ this.isOpen = true;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Spi initialize(Context context) throws InitializeException {
+ super.initialize(context);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void close() {
+ // todo ???? call fini ???
+ // this.functionsSpi.spiClose();
+ super.close();
+ }
+
+ // -------------------------------------------------------------------
+ // DEVICE TRANSFER FUNCTIONS
+ // -------------------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int transfer(byte[] write, int writeOffset, byte[] read, int readOffset, int numberOfBytes) {
+ return this.functionsSpi.transfer(this.spiApi, write, writeOffset, read, readOffset, numberOfBytes, this.spiApi.max_freq);
+ }
+
+ // -------------------------------------------------------------------
+ // DEVICE WRITE FUNCTIONS
+ // -------------------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int write(byte b) {
+ return this.functionsSpi.spiApi_write_b(this.spiApi, b, this.spiApi.max_freq);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int write(byte[] data, int offset, int length) {
+ return this.functionsSpi.spiApi_write(this.spiApi, data, offset, length, this.spiApi.max_freq);
+ }
+
+
+ // -------------------------------------------------------------------
+ // RAW DEVICE READ FUNCTIONS
+ // -------------------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read() {
+ byte b = 0;
+ this.functionsSpi.spiApi_read_b(this.spiApi, b, this.spiApi.max_freq);
+ return b;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] buffer, int offset, int length) {
+ return this.functionsSpi.spiApi_read(this.spiApi, buffer, offset, length, this.spiApi.max_freq);
+ }
+
+
+}
+
+
diff --git a/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProvider.java b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProvider.java
new file mode 100644
index 00000000..97c30e72
--- /dev/null
+++ b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProvider.java
@@ -0,0 +1,24 @@
+package com.pi4j.plugin.rp1spi.provider;
+
+import com.pi4j.io.spi.SpiProvider;
+
+
+
+import com.pi4j.library.kernel.SPIapi;
+import com.pi4j.plugin.rp1spi.Rp1SpiPlugin;
+
+
+
+public interface Rp1SpiProvider extends SpiProvider {
+ /** Constant NAME="Rp1SpiPlugin.SPI_PROVIDER_NAME"
*/
+ String NAME = Rp1SpiPlugin.SPI_PROVIDER_NAME;
+ /** Constant ID="Rp1SpiPlugin.SPI_PROVIDER_ID"
*/
+ String ID = Rp1SpiPlugin.SPI_PROVIDER_ID;
+
+
+
+
+ static Rp1SpiProvider newInstance() {
+ return new Rp1SpiProviderImpl();
+ }
+}
diff --git a/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProviderImpl.java b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProviderImpl.java
new file mode 100644
index 00000000..9a9a8758
--- /dev/null
+++ b/plugins/pi4j-plugin-rp1spi/src/main/java/com/pi4j/plugin/rp1spi/provider/Rp1SpiProviderImpl.java
@@ -0,0 +1,34 @@
+package com.pi4j.plugin.rp1spi.provider;
+
+import com.pi4j.boardinfo.util.BoardInfoHelper;
+import com.pi4j.io.spi.Spi;
+import com.pi4j.io.spi.SpiConfig;
+import com.pi4j.io.spi.SpiProviderBase;
+
+public class Rp1SpiProviderImpl extends SpiProviderBase implements Rp1SpiProvider {
+
+
+ public Rp1SpiProviderImpl() {
+ this.id = ID;
+ this.name = NAME;
+ }
+
+ @Override
+ public int getPriority() {
+ return BoardInfoHelper.usesRP1() ? 150 : 25;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Spi create(SpiConfig config) {
+ //synchronized (this.piGpio) {
+
+ // create new I/O instance based on I/O config
+ Rp1Spi spi = new Rp1Spi( this, config);
+ this.context.registry().add(spi);
+ return spi;
+ //}
+ }
+}
diff --git a/plugins/pi4j-plugin-rp1spi/src/main/java/module-info.java b/plugins/pi4j-plugin-rp1spi/src/main/java/module-info.java
new file mode 100644
index 00000000..71181516
--- /dev/null
+++ b/plugins/pi4j-plugin-rp1spi/src/main/java/module-info.java
@@ -0,0 +1,20 @@
+
+import com.pi4j.plugin.rp1spi.Rp1SpiPlugin;
+
+
+module com.pi4j.plugin.rp1spi {
+ requires com.pi4j;
+ requires com.pi4j.library.kernel;
+ requires org.slf4j;
+ requires jdk.unsupported;
+
+ // uses com.pi4j.extension.Plugin;
+
+ exports com.pi4j.plugin.rp1spi;
+
+ exports com.pi4j.plugin.rp1spi.provider;
+
+ provides com.pi4j.extension.Plugin
+ with com.pi4j.plugin.rp1spi.Rp1SpiPlugin;
+
+}
diff --git a/plugins/pi4j-plugin-rp1spi/src/main/resources/META-INF.services/com.pi4j.extension.Plugin b/plugins/pi4j-plugin-rp1spi/src/main/resources/META-INF.services/com.pi4j.extension.Plugin
new file mode 100644
index 00000000..65f522cb
--- /dev/null
+++ b/plugins/pi4j-plugin-rp1spi/src/main/resources/META-INF.services/com.pi4j.extension.Plugin
@@ -0,0 +1 @@
+com.pi4j.plugin.rp1spi.Rp1SpiPlugin
\ No newline at end of file
diff --git a/plugins/pi4j-plugin/pom.xml b/plugins/pi4j-plugin/pom.xml
index 79dcc567..9387527a 100644
--- a/plugins/pi4j-plugin/pom.xml
+++ b/plugins/pi4j-plugin/pom.xml
@@ -32,6 +32,7 @@